Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/coreutils/sort.c

    r821 r1765  
    66 *
    77 * MAINTAINER: Rob Landley <rob@landley.net>
    8  * 
     8 *
    99 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    1010 *
     
    1313 */
    1414
    15 #include <ctype.h>
    16 #include <math.h>
    17 #include <stdio.h>
    18 #include <stdlib.h>
    19 #include <string.h>
    20 #include <time.h>
    21 #include <unistd.h>
    22 #include "busybox.h"
    23 
    24 static int global_flags;
     15#include "libbb.h"
     16
     17/* This is a NOEXEC applet. Be very careful! */
     18
    2519
    2620/*
     
    3024
    3125/* These are sort types */
    32 #define FLAG_n          1       /* Numeric sort */
    33 #define FLAG_g          2       /* Sort using strtod() */
    34 #define FLAG_M          4       /* Sort date */
     26static const char OPT_STR[] ALIGN1 = "ngMucszbrdfimS:T:o:k:t:";
     27enum {
     28    FLAG_n  = 1,            /* Numeric sort */
     29    FLAG_g  = 2,            /* Sort using strtod() */
     30    FLAG_M  = 4,            /* Sort date */
    3531/* ucsz apply to root level only, not keys.  b at root level implies bb */
    36 #define FLAG_u          8       /* Unique */
    37 #define FLAG_c          16      /* Check: no output, exit(!ordered) */
    38 #define FLAG_s          32      /* Stable sort, no ascii fallback at end */
    39 #define FLAG_z          64      /* Input is null terminated, not \n */
     32    FLAG_u  = 8,            /* Unique */
     33    FLAG_c  = 0x10,         /* Check: no output, exit(!ordered) */
     34    FLAG_s  = 0x20,         /* Stable sort, no ascii fallback at end */
     35    FLAG_z  = 0x40,         /* Input is null terminated, not \n */
    4036/* These can be applied to search keys, the previous four can't */
    41 #define FLAG_b          128     /* Ignore leading blanks */
    42 #define FLAG_r          256     /* Reverse */
    43 #define FLAG_d          512     /* Ignore !(isalnum()|isspace()) */
    44 #define FLAG_f          1024    /* Force uppercase */
    45 #define FLAG_i          2048    /* Ignore !isprint() */
    46 #define FLAG_bb         32768   /* Ignore trailing blanks  */
    47 
    48 
    49 #ifdef CONFIG_FEATURE_SORT_BIG
     37    FLAG_b  = 0x80,         /* Ignore leading blanks */
     38    FLAG_r  = 0x100,        /* Reverse */
     39    FLAG_d  = 0x200,        /* Ignore !(isalnum()|isspace()) */
     40    FLAG_f  = 0x400,        /* Force uppercase */
     41    FLAG_i  = 0x800,        /* Ignore !isprint() */
     42    FLAG_m  = 0x1000,       /* ignored: merge already sorted files; do not sort */
     43    FLAG_S  = 0x2000,       /* ignored: -S, --buffer-size=SIZE */
     44    FLAG_T  = 0x4000,       /* ignored: -T, --temporary-directory=DIR */
     45    FLAG_o  = 0x8000,
     46    FLAG_k  = 0x10000,
     47    FLAG_t  = 0x20000,
     48    FLAG_bb = 0x80000000,   /* Ignore trailing blanks  */
     49};
     50
     51#if ENABLE_FEATURE_SORT_BIG
    5052static char key_separator;
    5153
    52 static struct sort_key
    53 {
     54static struct sort_key {
    5455    struct sort_key *next_key;  /* linked list */
    55     unsigned short range[4];    /* start word, start char, end word, end char */
    56     int flags;
     56    unsigned range[4];  /* start word, start char, end word, end char */
     57    unsigned flags;
    5758} *key_list;
    5859
    5960static char *get_key(char *str, struct sort_key *key, int flags)
    6061{
    61     int start=0,end,len,i,j;
     62    int start = 0, end = 0, len, i, j;
    6263
    6364    /* Special case whole string, so we don't have to make a copy */
    64     if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3]
    65         && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str;
    66     /* Find start of key on first pass, end on second pass*/
    67     len=strlen(str);
    68 
    69     for(j=0;j<2;j++) {
    70         if(!key->range[2*j]) end=len;
     65    if (key->range[0] == 1 && !key->range[1] && !key->range[2] && !key->range[3]
     66     && !(flags & (FLAG_b | FLAG_d | FLAG_f | FLAG_i | FLAG_bb))
     67    ) {
     68        return str;
     69    }
     70
     71    /* Find start of key on first pass, end on second pass */
     72    len = strlen(str);
     73    for (j = 0; j < 2; j++) {
     74        if (!key->range[2*j])
     75            end = len;
    7176        /* Loop through fields */
    7277        else {
    73             end=0;
    74             for(i=1;i<key->range[2*j]+j;i++) {
    75                 /* Skip leading blanks or first separator */
    76                 if(str[end]) {
    77                     if(!key_separator && isspace(str[end]))
    78                         while(isspace(str[end])) end++;
    79                 }
    80                 /* Skip body of key */
    81                 for(;str[end];end++) {
    82                     if(key_separator) {
    83                         if(str[end]==key_separator) break;
    84                     } else if(isspace(str[end])) break;
     78            end = 0;
     79            for (i = 1; i < key->range[2*j] + j; i++) {
     80                if (key_separator) {
     81                    /* Skip body of key and separator */
     82                    while (str[end]) {
     83                        if (str[end++] == key_separator)
     84                            break;
     85                    }
     86                } else {
     87                    /* Skip leading blanks */
     88                    while (isspace(str[end]))
     89                        end++;
     90                    /* Skip body of key */
     91                    while (str[end]) {
     92                        if (isspace(str[end]))
     93                            break;
     94                        end++;
     95                    }
    8596                }
    8697            }
    8798        }
    88         if(!j) start=end;
    89     }
    90     /* Key with explicit separator starts after separator */
    91     if(key_separator && str[start]==key_separator) start++;
     99        if (!j) start = end;
     100    }
    92101    /* Strip leading whitespace if necessary */
    93     if(flags&FLAG_b) while(isspace(str[start])) start++;
     102//XXX: skip_whitespace()
     103    if (flags & FLAG_b)
     104        while (isspace(str[start])) start++;
    94105    /* Strip trailing whitespace if necessary */
    95     if(flags&FLAG_bb) while(end>start && isspace(str[end-1])) end--;
     106    if (flags & FLAG_bb)
     107        while (end > start && isspace(str[end-1])) end--;
    96108    /* Handle offsets on start and end */
    97     if(key->range[3]) {
    98         end+=key->range[3]-1;
    99         if(end>len) end=len;
    100     }
    101     if(key->range[1]) {
    102         start+=key->range[1]-1;
    103         if(start>len) start=len;
     109    if (key->range[3]) {
     110        end += key->range[3] - 1;
     111        if (end > len) end = len;
     112    }
     113    if (key->range[1]) {
     114        start += key->range[1] - 1;
     115        if (start > len) start = len;
    104116    }
    105117    /* Make the copy */
    106     if(end<start) end=start;
    107     str=bb_xstrndup(str+start,end-start);
     118    if (end < start) end = start;
     119    str = xstrndup(str+start, end-start);
    108120    /* Handle -d */
    109     if(flags&FLAG_d) {
    110         for(start=end=0;str[end];end++)
    111             if(isspace(str[end]) || isalnum(str[end])) str[start++]=str[end];
    112         str[start]=0;
     121    if (flags & FLAG_d) {
     122        for (start = end = 0; str[end]; end++)
     123            if (isspace(str[end]) || isalnum(str[end]))
     124                str[start++] = str[end];
     125        str[start] = '\0';
    113126    }
    114127    /* Handle -i */
    115     if(flags&FLAG_i) {
    116         for(start=end=0;str[end];end++)
    117             if(isprint(str[end])) str[start++]=str[end];
    118         str[start]=0;
     128    if (flags & FLAG_i) {
     129        for (start = end = 0; str[end]; end++)
     130            if (isprint(str[end]))
     131                str[start++] = str[end];
     132        str[start] = '\0';
    119133    }
    120134    /* Handle -f */
    121     if(flags*FLAG_f) for(i=0;str[i];i++) str[i]=toupper(str[i]);
     135    if (flags & FLAG_f)
     136        for (i = 0; str[i]; i++)
     137            str[i] = toupper(str[i]);
    122138
    123139    return str;
     
    126142static struct sort_key *add_key(void)
    127143{
    128     struct sort_key **pkey=&key_list;
    129     while(*pkey) pkey=&((*pkey)->next_key);
    130     return *pkey=xcalloc(1,sizeof(struct sort_key));
     144    struct sort_key **pkey = &key_list;
     145    while (*pkey)
     146        pkey = &((*pkey)->next_key);
     147    return *pkey = xzalloc(sizeof(struct sort_key));
    131148}
    132149
    133 #define GET_LINE(fp) (global_flags&FLAG_z) ? bb_get_chunk_from_file(fp,NULL) \
    134                                            : bb_get_chomped_line_from_file(fp)
     150#define GET_LINE(fp) \
     151    ((option_mask32 & FLAG_z) \
     152    ? bb_get_chunk_from_file(fp, NULL) \
     153    : xmalloc_getline(fp))
    135154#else
    136 #define GET_LINE(fp)        bb_get_chomped_line_from_file(fp)
     155#define GET_LINE(fp) xmalloc_getline(fp)
    137156#endif
    138157
     
    140159static int compare_keys(const void *xarg, const void *yarg)
    141160{
    142     int flags=global_flags,retval=0;
    143     char *x,*y;
    144 
    145 #ifdef CONFIG_FEATURE_SORT_BIG
     161    int flags = option_mask32, retval = 0;
     162    char *x, *y;
     163
     164#if ENABLE_FEATURE_SORT_BIG
    146165    struct sort_key *key;
    147166
    148     for(key=key_list;!retval && key;key=key->next_key) {
    149         flags=(key->flags) ? key->flags : global_flags;
     167    for (key = key_list; !retval && key; key = key->next_key) {
     168        flags = key->flags ? key->flags : option_mask32;
    150169        /* Chop out and modify key chunks, handling -dfib */
    151         x=get_key(*(char **)xarg,key,flags);
    152         y=get_key(*(char **)yarg,key,flags);
     170        x = get_key(*(char **)xarg, key, flags);
     171        y = get_key(*(char **)yarg, key, flags);
    153172#else
    154173    /* This curly bracket serves no purpose but to match the nesting
    155        level of the for() loop we're not using */
     174       level of the for () loop we're not using */
    156175    {
    157         x=*(char **)xarg;
    158         y=*(char **)yarg;
     176        x = *(char **)xarg;
     177        y = *(char **)yarg;
    159178#endif
    160179        /* Perform actual comparison */
    161         switch(flags&7) {
    162             default:
    163                 bb_error_msg_and_die("Unknown sort type.");
    164                 break;
    165             /* Ascii sort */
    166             case 0:
    167                 retval=strcmp(x,y);
    168                 break;
    169 #ifdef CONFIG_FEATURE_SORT_BIG
    170             case FLAG_g:
    171             {
    172                 char *xx,*yy;
    173                 double dx=strtod(x,&xx), dy=strtod(y,&yy);
    174                 /* not numbers < NaN < -infinity < numbers < +infinity) */
    175                 if(x==xx) retval=(y==yy ? 0 : -1);
    176                 else if(y==yy) retval=1;
    177                 /* Check for isnan */
    178                 else if(dx != dx) retval = (dy != dy) ? 0 : -1;
    179                 else if(dy != dy) retval = 1;
    180                 /* Check for infinity.  Could underflow, but it avoids libm. */
    181                 else if(1.0/dx == 0.0) {
    182                     if(dx<0) retval=((1.0/dy == 0.0 && dy<0) ? 0 : -1);
    183                     else retval=((1.0/dy == 0.0 && dy>0) ? 0 : 1);
    184                 } else if(1.0/dy == 0.0) retval=dy<0 ? 1 : -1;
    185                 else retval=dx>dy ? 1 : (dx<dy ? -1 : 0);
    186                 break;
    187             }
    188             case FLAG_M:
    189             {
    190                 struct tm thyme;
    191                 int dx;
    192                 char *xx,*yy;
    193 
    194                 xx=strptime(x,"%b",&thyme);
    195                 dx=thyme.tm_mon;
    196                 yy=strptime(y,"%b",&thyme);
    197                 if(!xx) retval=(!yy ? 0 : -1);
    198                 else if(!yy) retval=1;
    199                 else retval=(dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon);
    200                 break;
    201             }
    202             /* Full floating point version of -n */
    203             case FLAG_n:
    204             {
    205                 double dx=atof(x),dy=atof(y);
    206                 retval=dx>dy ? 1 : (dx<dy ? -1 : 0);
    207                 break;
    208             }
    209         }
     180        switch (flags & 7) {
     181        default:
     182            bb_error_msg_and_die("unknown sort type");
     183            break;
     184        /* Ascii sort */
     185        case 0:
     186#if ENABLE_LOCALE_SUPPORT
     187            retval = strcoll(x, y);
     188#else
     189            retval = strcmp(x, y);
     190#endif
     191            break;
     192#if ENABLE_FEATURE_SORT_BIG
     193        case FLAG_g: {
     194            char *xx, *yy;
     195            double dx = strtod(x, &xx);
     196            double dy = strtod(y, &yy);
     197            /* not numbers < NaN < -infinity < numbers < +infinity) */
     198            if (x == xx)
     199                retval = (y == yy ? 0 : -1);
     200            else if (y == yy)
     201                retval = 1;
     202            /* Check for isnan */
     203            else if (dx != dx)
     204                retval = (dy != dy) ? 0 : -1;
     205            else if (dy != dy)
     206                retval = 1;
     207            /* Check for infinity.  Could underflow, but it avoids libm. */
     208            else if (1.0 / dx == 0.0) {
     209                if (dx < 0)
     210                    retval = (1.0 / dy == 0.0 && dy < 0) ? 0 : -1;
     211                else
     212                    retval = (1.0 / dy == 0.0 && dy > 0) ? 0 : 1;
     213            } else if (1.0 / dy == 0.0)
     214                retval = (dy < 0) ? 1 : -1;
     215            else
     216                retval = (dx > dy) ? 1 : ((dx < dy) ? -1 : 0);
     217            break;
     218        }
     219        case FLAG_M: {
     220            struct tm thyme;
     221            int dx;
     222            char *xx, *yy;
     223
     224            xx = strptime(x, "%b", &thyme);
     225            dx = thyme.tm_mon;
     226            yy = strptime(y, "%b", &thyme);
     227            if (!xx)
     228                retval = (!yy) ? 0 : -1;
     229            else if (!yy)
     230                retval = 1;
     231            else
     232                retval = (dx == thyme.tm_mon) ? 0 : dx - thyme.tm_mon;
     233            break;
     234        }
     235        /* Full floating point version of -n */
     236        case FLAG_n: {
     237            double dx = atof(x);
     238            double dy = atof(y);
     239            retval = (dx > dy) ? 1 : ((dx < dy) ? -1 : 0);
     240            break;
     241        }
     242        } /* switch */
    210243        /* Free key copies. */
    211         if(x!=*(char **)xarg) free(x);
    212         if(y!=*(char **)yarg) free(y);
    213         if(retval) break;
     244        if (x != *(char **)xarg) free(x);
     245        if (y != *(char **)yarg) free(y);
     246        /* if (retval) break; - done by for () anyway */
    214247#else
    215             /* Integer version of -n for tiny systems */
    216             case FLAG_n:
    217                 retval=atoi(x)-atoi(y);
    218                 break;
    219         }
    220 #endif
    221     }
     248        /* Integer version of -n for tiny systems */
     249        case FLAG_n:
     250            retval = atoi(x) - atoi(y);
     251            break;
     252        } /* switch */
     253#endif
     254    } /* for */
     255
    222256    /* Perform fallback sort if necessary */
    223     if(!retval && !(global_flags&FLAG_s))
    224             retval=strcmp(*(char **)xarg, *(char **)yarg);
    225 //dprintf(2,"reverse=%d\n",flags&FLAG_r);
    226     return ((flags&FLAG_r)?-1:1)*retval;
     257    if (!retval && !(option_mask32 & FLAG_s))
     258        retval = strcmp(*(char **)xarg, *(char **)yarg);
     259
     260    if (flags & FLAG_r) return -retval;
     261    return retval;
    227262}
    228263
     264#if ENABLE_FEATURE_SORT_BIG
     265static unsigned str2u(char **str)
     266{
     267    unsigned long lu;
     268    if (!isdigit((*str)[0]))
     269        bb_error_msg_and_die("bad field specification");
     270    lu = strtoul(*str, str, 10);
     271    if ((sizeof(long) > sizeof(int) && lu > INT_MAX) || !lu)
     272        bb_error_msg_and_die("bad field specification");
     273    return lu;
     274}
     275#endif
     276
     277int sort_main(int argc, char **argv);
    229278int sort_main(int argc, char **argv)
    230279{
    231     FILE *fp,*outfile=NULL;
    232     int linecount=0,i,flag;
    233     char *line,**lines=NULL,*optlist="ngMucszbrdfimS:T:o:k:t:";
    234     int c;
    235 
    236     bb_default_error_retval = 2;
     280    FILE *fp, *outfile = stdout;
     281    char *line, **lines = NULL;
     282    char *str_ignored, *str_o, *str_t;
     283    llist_t *lst_k = NULL;
     284    int i, flag;
     285    int linecount = 0;
     286
     287    xfunc_error_retval = 2;
     288
    237289    /* Parse command line options */
    238     while((c=getopt(argc,argv,optlist))>0) {
    239         line=strchr(optlist,c);
    240         if(!line) bb_show_usage();
    241         switch(*line) {
    242 #ifdef CONFIG_FEATURE_SORT_BIG
    243             case 'o':
    244                 if(outfile) bb_error_msg_and_die("Too many -o.");
    245                 outfile=bb_xfopen(optarg,"w");
    246                 break;
    247             case 't':
    248                 if(key_separator || optarg[1])
    249                     bb_error_msg_and_die("Too many -t.");
    250                 key_separator=*optarg;
    251                 break;
    252             /* parse sort key */
    253             case 'k':
    254             {
    255                 struct sort_key *key=add_key();
    256                 char *temp, *temp2;
    257 
    258                 temp=optarg;
    259                 for(i=0;*temp;) {
    260                     /* Start of range */
    261                     key->range[2*i]=(unsigned short)strtol(temp,&temp,10);
    262                     if(*temp=='.')
    263                         key->range[(2*i)+1]=(unsigned short)strtol(temp+1,&temp,10);
    264                     for(;*temp;temp++) {
    265                         if(*temp==',' && !i++) {
    266                             temp++;
    267                             break;
    268                         } /* no else needed: fall through to syntax error
    269                              because comma isn't in optlist */
    270                         temp2=strchr(optlist,*temp);
    271                         flag=(1<<(temp2-optlist));
    272                         if(!temp2 || (flag>FLAG_M && flag<FLAG_b))
    273                             bb_error_msg_and_die("Unknown key option.");
    274                         /* b after , means strip _trailing_ space */
    275                         if(i && flag==FLAG_b) flag=FLAG_bb;
    276                         key->flags|=flag;
    277                     }
    278                 }
    279                 break;
     290    /* -o and -t can be given at most once */
     291    opt_complementary = "o--o:t--t:" /* -t, -o: maximum one of each */
     292            "k::"; /* -k takes list */
     293    getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t);
     294#if ENABLE_FEATURE_SORT_BIG
     295    if (option_mask32 & FLAG_o) outfile = xfopen(str_o, "w");
     296    if (option_mask32 & FLAG_t) {
     297        if (!str_t[0] || str_t[1])
     298            bb_error_msg_and_die("bad -t parameter");
     299        key_separator = str_t[0];
     300    }
     301    /* parse sort key */
     302    while (lst_k) {
     303        enum {
     304            FLAG_allowed_for_k =
     305                FLAG_n | /* Numeric sort */
     306                FLAG_g | /* Sort using strtod() */
     307                FLAG_M | /* Sort date */
     308                FLAG_b | /* Ignore leading blanks */
     309                FLAG_r | /* Reverse */
     310                FLAG_d | /* Ignore !(isalnum()|isspace()) */
     311                FLAG_f | /* Force uppercase */
     312                FLAG_i | /* Ignore !isprint() */
     313            0
     314        };
     315        struct sort_key *key = add_key();
     316        char *str_k = lst_k->data;
     317        const char *temp2;
     318
     319        i = 0; /* i==0 before comma, 1 after (-k3,6) */
     320        while (*str_k) {
     321            /* Start of range */
     322            /* Cannot use bb_strtou - suffix can be a letter */
     323            key->range[2*i] = str2u(&str_k);
     324            if (*str_k == '.') {
     325                str_k++;
     326                key->range[2*i+1] = str2u(&str_k);
    280327            }
    281 #endif
    282             default:
    283                 global_flags|=(1<<(line-optlist));
    284                 /* global b strips leading and trailing spaces */
    285                 if(global_flags&FLAG_b) global_flags|=FLAG_bb;
    286                 break;
    287         }
    288     }
     328            while (*str_k) {
     329                if (*str_k == ',' && !i++) {
     330                    str_k++;
     331                    break;
     332                } /* no else needed: fall through to syntax error
     333                     because comma isn't in OPT_STR */
     334                temp2 = strchr(OPT_STR, *str_k);
     335                if (!temp2)
     336                    bb_error_msg_and_die("unknown key option");
     337                flag = 1 << (temp2 - OPT_STR);
     338                if (flag & ~FLAG_allowed_for_k)
     339                    bb_error_msg_and_die("unknown sort type");
     340                /* b after ',' means strip _trailing_ space */
     341                if (i && flag == FLAG_b) flag = FLAG_bb;
     342                key->flags |= flag;
     343                str_k++;
     344            }
     345        }
     346        /* leaking lst_k... */
     347        lst_k = lst_k->link;
     348    }
     349#endif
     350    /* global b strips leading and trailing spaces */
     351    if (option_mask32 & FLAG_b) option_mask32 |= FLAG_bb;
     352
    289353    /* Open input files and read data */
    290     for(i=argv[optind] ? optind : optind-1;argv[i];i++) {
    291         if(i<optind || (*argv[i]=='-' && !argv[i][1])) fp=stdin;
    292         else fp=bb_xfopen(argv[i],"r");
    293         for(;;) {
    294             line=GET_LINE(fp);
    295             if(!line) break;
    296             if(!(linecount&63))
    297                 lines=xrealloc(lines, sizeof(char *)*(linecount+64));
    298             lines[linecount++]=line;
     354    for (i = argv[optind] ? optind : optind-1; argv[i]; i++) {
     355        fp = stdin;
     356        if (i >= optind && NOT_LONE_DASH(argv[i]))
     357            fp = xfopen(argv[i], "r");
     358        for (;;) {
     359            line = GET_LINE(fp);
     360            if (!line) break;
     361            if (!(linecount & 63))
     362                lines = xrealloc(lines, sizeof(char *) * (linecount + 64));
     363            lines[linecount++] = line;
    299364        }
    300365        fclose(fp);
    301366    }
    302 #ifdef CONFIG_FEATURE_SORT_BIG
     367#if ENABLE_FEATURE_SORT_BIG
    303368    /* if no key, perform alphabetic sort */
    304     if(!key_list) add_key()->range[0]=1;
     369    if (!key_list)
     370        add_key()->range[0] = 1;
    305371    /* handle -c */
    306     if(global_flags&FLAG_c) {
    307         int j=(global_flags&FLAG_u) ? -1 : 0;
    308         for(i=1;i<linecount;i++)
    309             if(compare_keys(&lines[i-1],&lines[i])>j) {
    310                 fprintf(stderr,"Check line %d\n",i);
     372    if (option_mask32 & FLAG_c) {
     373        int j = (option_mask32 & FLAG_u) ? -1 : 0;
     374        for (i = 1; i < linecount; i++)
     375            if (compare_keys(&lines[i-1], &lines[i]) > j) {
     376                fprintf(stderr, "Check line %d\n", i);
    311377                return 1;
    312378            }
     
    315381#endif
    316382    /* Perform the actual sort */
    317     qsort(lines,linecount,sizeof(char *),compare_keys);
     383    qsort(lines, linecount, sizeof(char *), compare_keys);
    318384    /* handle -u */
    319     if(global_flags&FLAG_u) {
    320         for(flag=0,i=1;i<linecount;i++) {
    321             if(!compare_keys(&lines[flag],&lines[i])) free(lines[i]);
    322             else lines[++flag]=lines[i];
    323         }
    324         if(linecount) linecount=flag+1;
     385    if (option_mask32 & FLAG_u) {
     386        flag = 0;
     387        /* coreutils 6.3 drop lines for which only key is the same */
     388        /* -- disabling last-resort compare... */
     389        option_mask32 |= FLAG_s;
     390        for (i = 1; i < linecount; i++) {
     391            if (!compare_keys(&lines[flag], &lines[i]))
     392                free(lines[i]);
     393            else
     394                lines[++flag] = lines[i];
     395        }
     396        if (linecount) linecount = flag+1;
    325397    }
    326398    /* Print it */
    327     if(!outfile) outfile=stdout;
    328     for(i=0;i<linecount;i++) fprintf(outfile,"%s\n",lines[i]);
    329     bb_fflush_stdout_and_exit(EXIT_SUCCESS);
     399    for (i = 0; i < linecount; i++)
     400        fprintf(outfile, "%s\n", lines[i]);
     401
     402    fflush_stdout_and_exit(EXIT_SUCCESS);
    330403}
Note: See TracChangeset for help on using the changeset viewer.