diff -ruN ls.orig/Makefile ls/Makefile --- ls.orig/Makefile Sun Aug 29 14:12:45 1999 +++ ls/Makefile Mon Mar 20 22:24:02 2000 @@ -2,6 +2,6 @@ # $FreeBSD: src/bin/ls/Makefile,v 1.4.2.1 1999/08/29 14:12:45 peter Exp $ PROG= ls -SRCS= cmp.c stat_flags.c ls.c print.c util.c +SRCS= cmp.c stat_flags.c ls.c print.c util.c whs_cmp.c .include diff -ruN ls.orig/cmp.c ls/cmp.c --- ls.orig/cmp.c Sun Aug 29 14:12:46 1999 +++ ls/cmp.c Mon Mar 20 22:26:09 2000 @@ -52,6 +52,22 @@ #include "ls.h" #include "extern.h" +//#include "whs_cmp.c" + +int +alpha_numcmp(a, b) + const FTSENT *a, *b; +{ + return (whs_alpha_num_cmp(a->fts_name, b->fts_name)); +} + +int +revalpha_numcmp(a, b) + const FTSENT *a, *b; +{ + return (whs_alpha_num_cmp(b->fts_name, a->fts_name)); +} + int namecmp(a, b) const FTSENT *a, *b; diff -ruN ls.orig/extern.h ls/extern.h --- ls.orig/extern.h Sun Aug 29 14:12:47 1999 +++ ls/extern.h Mon Mar 20 22:58:23 2000 @@ -34,6 +34,9 @@ * $FreeBSD: src/bin/ls/extern.h,v 1.6.2.1 1999/08/29 14:12:47 peter Exp $ */ +int alpha_numcmp __P((const FTSENT *, const FTSENT *)); +int revalpha_numcmp __P((const FTSENT *, const FTSENT *)); + int acccmp __P((const FTSENT *, const FTSENT *)); int revacccmp __P((const FTSENT *, const FTSENT *)); int modcmp __P((const FTSENT *, const FTSENT *)); @@ -42,6 +45,7 @@ int revnamecmp __P((const FTSENT *, const FTSENT *)); int statcmp __P((const FTSENT *, const FTSENT *)); int revstatcmp __P((const FTSENT *, const FTSENT *)); +int whs_alpha_num_cmp __P((const char *a, const char *b)); char *flags_to_string __P((u_long, char *)); void prcopy __P((char *, char *, int)); diff -ruN ls.orig/ls.c ls/ls.c --- ls.orig/ls.c Sun Aug 29 14:12:48 1999 +++ ls/ls.c Mon Mar 20 22:22:27 2000 @@ -101,6 +101,8 @@ int f_type; /* add type character for non-regular files */ int f_whiteout; /* show whiteout entries */ +int f_sort_alpha_num; /* sort alpha & numeric separately */ + int rval; int @@ -137,7 +139,7 @@ f_listdot = 1; fts_options = FTS_PHYSICAL; - while ((ch = getopt(argc, argv, "1ABCFHLPRTWabcdfgikloqrstu")) != -1) { + while ((ch = getopt(argc, argv, "1ABCFHLNPRTWabcdfgikloqrstu")) != -1) { switch (ch) { /* * The -1, -C and -l options all override each other so shell @@ -220,6 +222,9 @@ case 'r': f_reversesort = 1; break; + case 'N': + f_sort_alpha_num = 1; + break; case 's': f_size = 1; break; @@ -279,7 +284,9 @@ /* Select a sort function. */ if (f_reversesort) { - if (!f_timesort) + if (f_sort_alpha_num) + sortfcn = revalpha_numcmp; + else if (!f_timesort) sortfcn = revnamecmp; else if (f_accesstime) sortfcn = revacccmp; @@ -288,7 +295,9 @@ else /* Use modification time. */ sortfcn = revmodcmp; } else { - if (!f_timesort) + if (f_sort_alpha_num) + sortfcn = alpha_numcmp; + else if (!f_timesort) sortfcn = namecmp; else if (f_accesstime) sortfcn = acccmp; diff -ruN ls.orig/whs_cmp.c ls/whs_cmp.c --- ls.orig/whs_cmp.c Thu Jan 1 00:00:00 1970 +++ ls/whs_cmp.c Mon Mar 20 22:54:50 2000 @@ -0,0 +1,117 @@ +/* Copyright (C) 2000 W.H.Scholten + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the following + conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS + IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +/* alpha - numeric sorting: + It works as follows: get the longest alpha part (=anything not containing + 0 .. 9) from both strings, compare these. If equal, compare the numerical + parts that follow e.g. 2 < 10, 0002<10, 02 < 0002, by stripping leading + zeros, checking string lengths, and finally do a lexicographical comparison + (strcmp) if these lengths are equal. + + Version 1.1 + */ + +int +whs_alpha_num_cmp(a, b) + const char *a, *b; +{ + int la, lb; + int ca, cb; + int na, nb; + + int new_ca, new_cb, new_na, new_nb; + + for (;;) { + int cmp; + + la = strlen(a); + lb = strlen(b); + + ca = strcspn(a, "0123456789"); + cb = strcspn(b, "0123456789"); + + if (ca >= la || cb >= lb) { + /* At most one of the strings has digits: */ + // V 1.1: + return strcmp(a, b); + } + + /* Both strings have digits: */ + if (ca != cb) { + cmp = strncmp(a, b, min(ca, cb)); + if (cmp) { /* alpha parts of the strings are different */ + return cmp; + } + + /* So, the alpha parts are the same up to min(ca, cb). + * + * If cb > ca the rest of b starts with alpha whereas the rest of + * a starts with a digit. + */ + // V 1.1: + return a [ min(ca, cb) ] - b [ min(ca, cb) ]; + } + + + cmp = strncmp(a, b, ca); + if (cmp) { + return cmp; + } + + /* ca=cb & alpha parts are the same; + * Now we have a look at the numbers and compare them. */ + na = strspn(a+ca, "0123456789"); + nb = strspn(b+cb, "0123456789"); + + /* Remove leading 0's */ + new_na = na; + new_ca = ca; + while (a [ new_ca ] == '0') { new_na --; new_ca ++; } + + new_nb = nb; + new_cb = cb; + while (b [ new_cb ] == '0') { new_nb --; new_cb ++; } + + if (new_na != new_nb) { + return new_na - new_nb; + } + + cmp = strncmp( (a+new_ca), (b+new_cb), new_na); + if (cmp) { + return cmp; + } + if (na != nb) { + return na - nb; + } + + a = (a+ca+na); + b = (b+cb+nb); + } +}