1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 4bd389b36SDavid du Colombier 5bd389b36SDavid du Colombier /* 6bd389b36SDavid du Colombier bugs: 7bd389b36SDavid du Colombier 00/ff for end of file can conflict with 00/ff characters 8bd389b36SDavid du Colombier */ 9bd389b36SDavid du Colombier 10bd389b36SDavid du Colombier enum 11bd389b36SDavid du Colombier { 12bd389b36SDavid du Colombier Nline = 100000, /* max number of lines saved in memory */ 13bd389b36SDavid du Colombier Nmerge = 10, /* max number of temporary files merged */ 14bd389b36SDavid du Colombier Nfield = 20, /* max number of argument fields */ 15bd389b36SDavid du Colombier 16bd389b36SDavid du Colombier Bflag = 1<<0, /* flags per field */ 17bd389b36SDavid du Colombier B1flag = 1<<1, 18bd389b36SDavid du Colombier 19bd389b36SDavid du Colombier Dflag = 1<<2, 20bd389b36SDavid du Colombier Fflag = 1<<3, 21bd389b36SDavid du Colombier Gflag = 1<<4, 22bd389b36SDavid du Colombier Iflag = 1<<5, 23bd389b36SDavid du Colombier Mflag = 1<<6, 24bd389b36SDavid du Colombier Nflag = 1<<7, 25bd389b36SDavid du Colombier Rflag = 1<<8, 26bd389b36SDavid du Colombier Wflag = 1<<9, 27bd389b36SDavid du Colombier 28bd389b36SDavid du Colombier NSstart = 0, /* states for number to key decoding */ 29bd389b36SDavid du Colombier NSsign, 30bd389b36SDavid du Colombier NSzero, 31bd389b36SDavid du Colombier NSdigit, 32bd389b36SDavid du Colombier NSpoint, 33bd389b36SDavid du Colombier NSfract, 34bd389b36SDavid du Colombier NSzerofract, 35bd389b36SDavid du Colombier NSexp, 36bd389b36SDavid du Colombier NSexpsign, 37bd389b36SDavid du Colombier NSexpdigit, 38bd389b36SDavid du Colombier }; 39bd389b36SDavid du Colombier 40bd389b36SDavid du Colombier typedef struct Line Line; 41bd389b36SDavid du Colombier typedef struct Key Key; 42bd389b36SDavid du Colombier typedef struct Merge Merge; 43bd389b36SDavid du Colombier typedef struct Field Field; 44bd389b36SDavid du Colombier 45bd389b36SDavid du Colombier struct Line 46bd389b36SDavid du Colombier { 47bd389b36SDavid du Colombier Key* key; 48bd389b36SDavid du Colombier int llen; /* always >= 1 */ 49bd389b36SDavid du Colombier uchar line[1]; /* always ends in '\n' */ 50bd389b36SDavid du Colombier }; 51bd389b36SDavid du Colombier 52bd389b36SDavid du Colombier struct Merge 53bd389b36SDavid du Colombier { 54bd389b36SDavid du Colombier Key* key; /* copy of line->key so (Line*) looks like (Merge*) */ 55bd389b36SDavid du Colombier Line* line; /* line at the head of a merged temp file */ 56bd389b36SDavid du Colombier int fd; /* file descriptor */ 57bd389b36SDavid du Colombier Biobuf b; /* iobuf for reading a temp file */ 58bd389b36SDavid du Colombier }; 59bd389b36SDavid du Colombier 60bd389b36SDavid du Colombier struct Key 61bd389b36SDavid du Colombier { 62bd389b36SDavid du Colombier int klen; 63bd389b36SDavid du Colombier uchar key[1]; 64bd389b36SDavid du Colombier }; 65bd389b36SDavid du Colombier 66bd389b36SDavid du Colombier struct Field 67bd389b36SDavid du Colombier { 68bd389b36SDavid du Colombier int beg1; 69bd389b36SDavid du Colombier int beg2; 70bd389b36SDavid du Colombier int end1; 71bd389b36SDavid du Colombier int end2; 72bd389b36SDavid du Colombier 73bd389b36SDavid du Colombier long flags; 74bd389b36SDavid du Colombier uchar mapto[256]; 75bd389b36SDavid du Colombier 76bd389b36SDavid du Colombier void (*dokey)(Key*, uchar*, uchar*, Field*); 77bd389b36SDavid du Colombier }; 78bd389b36SDavid du Colombier 79*219b2ee8SDavid du Colombier struct args 80bd389b36SDavid du Colombier { 81bd389b36SDavid du Colombier char* ofile; 82bd389b36SDavid du Colombier char* tname; 83bd389b36SDavid du Colombier Rune tabchar; 84bd389b36SDavid du Colombier char cflag; 85bd389b36SDavid du Colombier char uflag; 86bd389b36SDavid du Colombier char vflag; 87bd389b36SDavid du Colombier int nfield; 88bd389b36SDavid du Colombier int nfile; 89bd389b36SDavid du Colombier Field field[Nfield]; 90bd389b36SDavid du Colombier 91bd389b36SDavid du Colombier Line** linep; 92bd389b36SDavid du Colombier long nline; /* number of lines in this temp file */ 93bd389b36SDavid du Colombier long lineno; /* overall ordinal for -s option */ 94bd389b36SDavid du Colombier int ntemp; 95bd389b36SDavid du Colombier } args; 96bd389b36SDavid du Colombier 97bd389b36SDavid du Colombier extern int latinmap[]; 98bd389b36SDavid du Colombier extern Rune* month[12]; 99bd389b36SDavid du Colombier 100bd389b36SDavid du Colombier void buildkey(Line*); 101bd389b36SDavid du Colombier void doargs(int, char*[]); 102bd389b36SDavid du Colombier void dofield(char*, int*, int*, int, int); 103bd389b36SDavid du Colombier void dofile(Biobuf*); 104bd389b36SDavid du Colombier void dokey_(Key*, uchar*, uchar*, Field*); 105bd389b36SDavid du Colombier void dokey_dfi(Key*, uchar*, uchar*, Field*); 106bd389b36SDavid du Colombier void dokey_gn(Key*, uchar*, uchar*, Field*); 107bd389b36SDavid du Colombier void dokey_m(Key*, uchar*, uchar*, Field*); 108bd389b36SDavid du Colombier void dokey_r(Key*, uchar*, uchar*, Field*); 109bd389b36SDavid du Colombier void done(char*); 110bd389b36SDavid du Colombier int kcmp(Key*, Key*); 111bd389b36SDavid du Colombier void makemapd(Field*); 112bd389b36SDavid du Colombier void makemapm(Field*); 113bd389b36SDavid du Colombier void mergefiles(int, int, Biobuf*); 114bd389b36SDavid du Colombier void mergeout(Biobuf*); 115bd389b36SDavid du Colombier void newfield(void); 116bd389b36SDavid du Colombier Line* newline(Biobuf*); 117bd389b36SDavid du Colombier void nomem(void); 118bd389b36SDavid du Colombier void notifyf(void*, char*); 119bd389b36SDavid du Colombier void printargs(void); 120bd389b36SDavid du Colombier void printout(Biobuf*); 121bd389b36SDavid du Colombier void setfield(int, int); 122bd389b36SDavid du Colombier uchar* skip(uchar*, int, int, int, int); 123bd389b36SDavid du Colombier void sort4(void*, ulong); 124bd389b36SDavid du Colombier char* tempfile(int); 125bd389b36SDavid du Colombier void tempout(void); 126*219b2ee8SDavid du Colombier void lineout(Biobuf*, Line*); 127bd389b36SDavid du Colombier 128bd389b36SDavid du Colombier void 129bd389b36SDavid du Colombier main(int argc, char *argv[]) 130bd389b36SDavid du Colombier { 131bd389b36SDavid du Colombier int i, f; 132bd389b36SDavid du Colombier char *s; 133bd389b36SDavid du Colombier Biobuf bbuf; 134bd389b36SDavid du Colombier 135bd389b36SDavid du Colombier notify(notifyf); /**/ 136bd389b36SDavid du Colombier doargs(argc, argv); 137bd389b36SDavid du Colombier if(args.vflag) 138bd389b36SDavid du Colombier printargs(); 139bd389b36SDavid du Colombier 140bd389b36SDavid du Colombier for(i=1; i<argc; i++) { 141bd389b36SDavid du Colombier s = argv[i]; 142bd389b36SDavid du Colombier if(s == 0) 143bd389b36SDavid du Colombier continue; 144bd389b36SDavid du Colombier if(strcmp(s, "-") == 0) { 145bd389b36SDavid du Colombier Binit(&bbuf, 0, OREAD); 146bd389b36SDavid du Colombier dofile(&bbuf); 147*219b2ee8SDavid du Colombier Bterm(&bbuf); 148bd389b36SDavid du Colombier continue; 149bd389b36SDavid du Colombier } 150bd389b36SDavid du Colombier f = open(s, OREAD); 151bd389b36SDavid du Colombier if(f < 0) { 152bd389b36SDavid du Colombier fprint(2, "sort: open %s: %r\n", s); 153bd389b36SDavid du Colombier done("open"); 154bd389b36SDavid du Colombier } 155bd389b36SDavid du Colombier Binit(&bbuf, f, OREAD); 156bd389b36SDavid du Colombier dofile(&bbuf); 157*219b2ee8SDavid du Colombier Bterm(&bbuf); 158bd389b36SDavid du Colombier close(f); 159bd389b36SDavid du Colombier } 160bd389b36SDavid du Colombier if(args.nfile == 0) { 161bd389b36SDavid du Colombier Binit(&bbuf, 0, OREAD); 162bd389b36SDavid du Colombier dofile(&bbuf); 163*219b2ee8SDavid du Colombier Bterm(&bbuf); 164bd389b36SDavid du Colombier } 165bd389b36SDavid du Colombier if(args.cflag) 166bd389b36SDavid du Colombier done(0); 167bd389b36SDavid du Colombier if(args.vflag) 168bd389b36SDavid du Colombier fprint(2, "=========\n"); 169bd389b36SDavid du Colombier 170bd389b36SDavid du Colombier f = 1; 171bd389b36SDavid du Colombier if(args.ofile) { 172bd389b36SDavid du Colombier f = create(args.ofile, OWRITE, 0666); 173bd389b36SDavid du Colombier if(f < 0) { 174bd389b36SDavid du Colombier fprint(2, "sort: create %s: %r\n", args.ofile); 175bd389b36SDavid du Colombier done("create"); 176bd389b36SDavid du Colombier } 177bd389b36SDavid du Colombier } 178bd389b36SDavid du Colombier 179bd389b36SDavid du Colombier Binit(&bbuf, f, OWRITE); 180bd389b36SDavid du Colombier if(args.ntemp) { 181bd389b36SDavid du Colombier tempout(); 182bd389b36SDavid du Colombier mergeout(&bbuf); 183bd389b36SDavid du Colombier } else { 184bd389b36SDavid du Colombier printout(&bbuf); 185bd389b36SDavid du Colombier } 186*219b2ee8SDavid du Colombier Bterm(&bbuf); 187bd389b36SDavid du Colombier done(0); 188bd389b36SDavid du Colombier } 189bd389b36SDavid du Colombier 190bd389b36SDavid du Colombier void 191bd389b36SDavid du Colombier dofile(Biobuf *b) 192bd389b36SDavid du Colombier { 193bd389b36SDavid du Colombier Line *l, *ol; 194bd389b36SDavid du Colombier int n; 195bd389b36SDavid du Colombier 196bd389b36SDavid du Colombier if(args.cflag) { 197bd389b36SDavid du Colombier ol = newline(b); 198bd389b36SDavid du Colombier if(ol == 0) 199bd389b36SDavid du Colombier return; 200bd389b36SDavid du Colombier for(;;) { 201bd389b36SDavid du Colombier l = newline(b); 202bd389b36SDavid du Colombier if(l == 0) 203bd389b36SDavid du Colombier break; 204bd389b36SDavid du Colombier n = kcmp(ol->key, l->key); 205bd389b36SDavid du Colombier if(n > 0 || (n == 0 && args.uflag)) { 206bd389b36SDavid du Colombier /* no output shall be produced 207bd389b36SDavid du Colombier fprint(2, "sort: -c file not in sort\n"); /**/ 208bd389b36SDavid du Colombier done("order"); 209bd389b36SDavid du Colombier } 210bd389b36SDavid du Colombier free(ol->key); 211bd389b36SDavid du Colombier free(ol); 212bd389b36SDavid du Colombier ol = l; 213bd389b36SDavid du Colombier } 214bd389b36SDavid du Colombier return; 215bd389b36SDavid du Colombier } 216bd389b36SDavid du Colombier 217bd389b36SDavid du Colombier if(args.linep == 0) { 218bd389b36SDavid du Colombier args.linep = malloc(Nline * sizeof(args.linep)); 219bd389b36SDavid du Colombier if(args.linep == 0) 220bd389b36SDavid du Colombier nomem(); 221bd389b36SDavid du Colombier } 222bd389b36SDavid du Colombier for(;;) { 223bd389b36SDavid du Colombier l = newline(b); 224bd389b36SDavid du Colombier if(l == 0) 225bd389b36SDavid du Colombier break; 226bd389b36SDavid du Colombier if(args.nline >= Nline) 227bd389b36SDavid du Colombier tempout(); 228bd389b36SDavid du Colombier args.linep[args.nline] = l; 229bd389b36SDavid du Colombier args.nline++; 230bd389b36SDavid du Colombier args.lineno++; 231bd389b36SDavid du Colombier } 232bd389b36SDavid du Colombier } 233bd389b36SDavid du Colombier 234bd389b36SDavid du Colombier void 235bd389b36SDavid du Colombier notifyf(void *a, char *s) 236bd389b36SDavid du Colombier { 237bd389b36SDavid du Colombier 238bd389b36SDavid du Colombier USED(a); 239bd389b36SDavid du Colombier if(strcmp(s, "interrupt") == 0) 240bd389b36SDavid du Colombier done(0); 241bd389b36SDavid du Colombier if(strcmp(s, "hangup") == 0) 242bd389b36SDavid du Colombier done(0); 243*219b2ee8SDavid du Colombier if(strcmp(s, "kill") == 0) 244*219b2ee8SDavid du Colombier done(0); 245*219b2ee8SDavid du Colombier if(strcmp(s, "sys: write on closed pipe") == 0) 246*219b2ee8SDavid du Colombier done(0); 247bd389b36SDavid du Colombier fprint(2, "sort: note: %s\n", s); 248bd389b36SDavid du Colombier abort(); 249bd389b36SDavid du Colombier } 250bd389b36SDavid du Colombier 251bd389b36SDavid du Colombier Line* 252bd389b36SDavid du Colombier newline(Biobuf *b) 253bd389b36SDavid du Colombier { 254bd389b36SDavid du Colombier Line *l; 255bd389b36SDavid du Colombier char *p; 256bd389b36SDavid du Colombier int n, c; 257bd389b36SDavid du Colombier 258bd389b36SDavid du Colombier p = Brdline(b, '\n'); 259bd389b36SDavid du Colombier n = Blinelen(b); 260bd389b36SDavid du Colombier if(p == 0) { 261bd389b36SDavid du Colombier if(n == 0) 262bd389b36SDavid du Colombier return 0; 263bd389b36SDavid du Colombier l = 0; 264bd389b36SDavid du Colombier for(n=0;;) { 265bd389b36SDavid du Colombier if((n & 31) == 0) { 266bd389b36SDavid du Colombier l = realloc(l, sizeof(Line) + 267bd389b36SDavid du Colombier (n+31)*sizeof(l->line[0])); 268bd389b36SDavid du Colombier if(l == 0) 269bd389b36SDavid du Colombier nomem(); 270bd389b36SDavid du Colombier } 271bd389b36SDavid du Colombier c = Bgetc(b); 272bd389b36SDavid du Colombier if(c < 0) { 273bd389b36SDavid du Colombier fprint(2, "sort: newline added\n"); 274bd389b36SDavid du Colombier c = '\n'; 275bd389b36SDavid du Colombier } 276bd389b36SDavid du Colombier l->line[n++] = c; 277bd389b36SDavid du Colombier if(c == '\n') 278bd389b36SDavid du Colombier break; 279bd389b36SDavid du Colombier } 280bd389b36SDavid du Colombier l->llen = n; 281bd389b36SDavid du Colombier buildkey(l); 282bd389b36SDavid du Colombier return l; 283bd389b36SDavid du Colombier } 284bd389b36SDavid du Colombier l = malloc(sizeof(Line) + 285bd389b36SDavid du Colombier (n-1)*sizeof(l->line[0])); 286bd389b36SDavid du Colombier if(l == 0) 287bd389b36SDavid du Colombier nomem(); 288bd389b36SDavid du Colombier l->llen = n; 289bd389b36SDavid du Colombier memmove(l->line, p, n); 290bd389b36SDavid du Colombier buildkey(l); 291bd389b36SDavid du Colombier return l; 292bd389b36SDavid du Colombier } 293bd389b36SDavid du Colombier 294bd389b36SDavid du Colombier void 295*219b2ee8SDavid du Colombier lineout(Biobuf *b, Line *l) 296*219b2ee8SDavid du Colombier { 297*219b2ee8SDavid du Colombier int n, m; 298*219b2ee8SDavid du Colombier 299*219b2ee8SDavid du Colombier n = l->llen; 300*219b2ee8SDavid du Colombier m = Bwrite(b, l->line, n); 301*219b2ee8SDavid du Colombier if(n != m) 302*219b2ee8SDavid du Colombier exits("write"); 303*219b2ee8SDavid du Colombier } 304*219b2ee8SDavid du Colombier 305*219b2ee8SDavid du Colombier void 306bd389b36SDavid du Colombier tempout(void) 307bd389b36SDavid du Colombier { 308bd389b36SDavid du Colombier long n; 309bd389b36SDavid du Colombier Line **lp, *l; 310bd389b36SDavid du Colombier char *tf; 311*219b2ee8SDavid du Colombier int f; 312bd389b36SDavid du Colombier Biobuf tb; 313bd389b36SDavid du Colombier 314bd389b36SDavid du Colombier sort4(args.linep, args.nline); 315bd389b36SDavid du Colombier tf = tempfile(args.ntemp); 316bd389b36SDavid du Colombier args.ntemp++; 317bd389b36SDavid du Colombier f = create(tf, OWRITE, 0666); 318bd389b36SDavid du Colombier if(f < 0) { 319bd389b36SDavid du Colombier fprint(2, "sort: create %s: %r\n", tf); 320bd389b36SDavid du Colombier done("create"); 321bd389b36SDavid du Colombier } 322bd389b36SDavid du Colombier 323bd389b36SDavid du Colombier Binit(&tb, f, OWRITE); 324bd389b36SDavid du Colombier lp = args.linep; 325bd389b36SDavid du Colombier for(n=args.nline; n>0; n--) { 326bd389b36SDavid du Colombier l = *lp++; 327*219b2ee8SDavid du Colombier lineout(&tb, l); 328bd389b36SDavid du Colombier free(l->key); 329bd389b36SDavid du Colombier free(l); 330bd389b36SDavid du Colombier } 331bd389b36SDavid du Colombier args.nline = 0; 332*219b2ee8SDavid du Colombier Bterm(&tb); 333bd389b36SDavid du Colombier close(f); 334bd389b36SDavid du Colombier } 335bd389b36SDavid du Colombier 336bd389b36SDavid du Colombier void 337bd389b36SDavid du Colombier done(char *xs) 338bd389b36SDavid du Colombier { 339bd389b36SDavid du Colombier int i; 340bd389b36SDavid du Colombier 341bd389b36SDavid du Colombier for(i=0; i<args.ntemp; i++) 342bd389b36SDavid du Colombier remove(tempfile(i)); 343bd389b36SDavid du Colombier exits(xs); 344bd389b36SDavid du Colombier } 345bd389b36SDavid du Colombier 346bd389b36SDavid du Colombier void 347bd389b36SDavid du Colombier nomem(void) 348bd389b36SDavid du Colombier { 349bd389b36SDavid du Colombier fprint(2, "sort: out of memory\n"); 350bd389b36SDavid du Colombier done("mem"); 351bd389b36SDavid du Colombier } 352bd389b36SDavid du Colombier 353bd389b36SDavid du Colombier char* 354bd389b36SDavid du Colombier tempfile(int n) 355bd389b36SDavid du Colombier { 356bd389b36SDavid du Colombier static char file[20]; 357bd389b36SDavid du Colombier static int pid; 358bd389b36SDavid du Colombier char *dir; 359bd389b36SDavid du Colombier 360bd389b36SDavid du Colombier dir = "/tmp"; 361bd389b36SDavid du Colombier if(args.tname) 362bd389b36SDavid du Colombier dir = args.tname; 363bd389b36SDavid du Colombier if(pid == 0) 364bd389b36SDavid du Colombier pid = getpid() % 1000; 365bd389b36SDavid du Colombier if(pid == 0) 366bd389b36SDavid du Colombier pid = 1; 367bd389b36SDavid du Colombier sprint(file, "%s/sort.%.3d.%.3d", dir, pid, n); 368bd389b36SDavid du Colombier return file; 369bd389b36SDavid du Colombier } 370bd389b36SDavid du Colombier 371bd389b36SDavid du Colombier void 372bd389b36SDavid du Colombier mergeout(Biobuf *b) 373bd389b36SDavid du Colombier { 374bd389b36SDavid du Colombier int n, i, f; 375bd389b36SDavid du Colombier char *tf; 376bd389b36SDavid du Colombier Biobuf tb; 377bd389b36SDavid du Colombier 378bd389b36SDavid du Colombier for(i=0; i<args.ntemp; i+=n) { 379bd389b36SDavid du Colombier n = args.ntemp - i; 380bd389b36SDavid du Colombier if(n > Nmerge) { 381bd389b36SDavid du Colombier tf = tempfile(args.ntemp); 382bd389b36SDavid du Colombier args.ntemp++; 383bd389b36SDavid du Colombier f = create(tf, OWRITE, 0666); 384bd389b36SDavid du Colombier if(f < 0) { 385bd389b36SDavid du Colombier fprint(2, "sort: create %s: %r\n", tf); 386bd389b36SDavid du Colombier done("create"); 387bd389b36SDavid du Colombier } 388bd389b36SDavid du Colombier Binit(&tb, f, OWRITE); 389bd389b36SDavid du Colombier 390bd389b36SDavid du Colombier n = Nmerge; 391bd389b36SDavid du Colombier mergefiles(i, n, &tb); 392bd389b36SDavid du Colombier 393*219b2ee8SDavid du Colombier Bterm(&tb); 394bd389b36SDavid du Colombier close(f); 395bd389b36SDavid du Colombier } else 396bd389b36SDavid du Colombier mergefiles(i, n, b); 397bd389b36SDavid du Colombier } 398bd389b36SDavid du Colombier } 399bd389b36SDavid du Colombier 400bd389b36SDavid du Colombier void 401bd389b36SDavid du Colombier mergefiles(int t, int n, Biobuf *b) 402bd389b36SDavid du Colombier { 403bd389b36SDavid du Colombier Merge *m, *mp, **mmp; 404bd389b36SDavid du Colombier Key *ok; 405bd389b36SDavid du Colombier Line *l; 406bd389b36SDavid du Colombier char *tf; 407bd389b36SDavid du Colombier int i, f, nn; 408bd389b36SDavid du Colombier 409bd389b36SDavid du Colombier mmp = malloc(n*sizeof(*mmp)); 410bd389b36SDavid du Colombier mp = malloc(n*sizeof(*mp)); 411bd389b36SDavid du Colombier if(mmp == 0 || mp == 0) 412bd389b36SDavid du Colombier nomem(); 413bd389b36SDavid du Colombier 414bd389b36SDavid du Colombier nn = 0; 415bd389b36SDavid du Colombier m = mp; 416bd389b36SDavid du Colombier for(i=0; i<n; i++,m++) { 417bd389b36SDavid du Colombier tf = tempfile(t+i); 418bd389b36SDavid du Colombier f = open(tf, OREAD); 419bd389b36SDavid du Colombier if(f < 0) { 420bd389b36SDavid du Colombier fprint(2, "sort: reopen %s: %r\n", tf); 421bd389b36SDavid du Colombier done("open"); 422bd389b36SDavid du Colombier } 423bd389b36SDavid du Colombier m->fd = f; 424bd389b36SDavid du Colombier Binit(&m->b, f, OREAD); 425bd389b36SDavid du Colombier mmp[nn] = m; 426bd389b36SDavid du Colombier 427bd389b36SDavid du Colombier l = newline(&m->b); 428bd389b36SDavid du Colombier if(l == 0) 429bd389b36SDavid du Colombier continue; 430bd389b36SDavid du Colombier nn++; 431bd389b36SDavid du Colombier m->line = l; 432bd389b36SDavid du Colombier m->key = l->key; 433bd389b36SDavid du Colombier } 434bd389b36SDavid du Colombier 435bd389b36SDavid du Colombier ok = 0; 436bd389b36SDavid du Colombier for(;;) { 437bd389b36SDavid du Colombier sort4(mmp, nn); 438bd389b36SDavid du Colombier m = *mmp; 439bd389b36SDavid du Colombier if(nn == 0) 440bd389b36SDavid du Colombier break; 441bd389b36SDavid du Colombier for(;;) { 442bd389b36SDavid du Colombier l = m->line; 443bd389b36SDavid du Colombier if(args.uflag && ok && kcmp(ok, l->key) == 0) { 444bd389b36SDavid du Colombier free(l->key); 445bd389b36SDavid du Colombier } else { 446*219b2ee8SDavid du Colombier lineout(b, l); 447bd389b36SDavid du Colombier if(ok) 448bd389b36SDavid du Colombier free(ok); 449bd389b36SDavid du Colombier ok = l->key; 450bd389b36SDavid du Colombier free(l); 451bd389b36SDavid du Colombier } 452bd389b36SDavid du Colombier 453bd389b36SDavid du Colombier l = newline(&m->b); 454bd389b36SDavid du Colombier if(l == 0) { 455bd389b36SDavid du Colombier nn--; 456bd389b36SDavid du Colombier mmp[0] = mmp[nn]; 457bd389b36SDavid du Colombier break; 458bd389b36SDavid du Colombier } 459bd389b36SDavid du Colombier m->line = l; 460bd389b36SDavid du Colombier m->key = l->key; 461bd389b36SDavid du Colombier if(nn > 1 && kcmp(mmp[0]->key, mmp[1]->key) > 0) 462bd389b36SDavid du Colombier break; 463bd389b36SDavid du Colombier } 464bd389b36SDavid du Colombier } 465bd389b36SDavid du Colombier if(ok) 466bd389b36SDavid du Colombier free(ok); 467bd389b36SDavid du Colombier 468bd389b36SDavid du Colombier m = mp; 469bd389b36SDavid du Colombier for(i=0; i<n; i++,m++) { 470*219b2ee8SDavid du Colombier Bterm(&m->b); 471bd389b36SDavid du Colombier close(m->fd); 472bd389b36SDavid du Colombier } 473bd389b36SDavid du Colombier 474bd389b36SDavid du Colombier free(mp); 475bd389b36SDavid du Colombier free(mmp); 476bd389b36SDavid du Colombier } 477bd389b36SDavid du Colombier 478bd389b36SDavid du Colombier int 479bd389b36SDavid du Colombier kcmp(Key *ka, Key *kb) 480bd389b36SDavid du Colombier { 481bd389b36SDavid du Colombier int n, m; 482bd389b36SDavid du Colombier 483bd389b36SDavid du Colombier /* 484bd389b36SDavid du Colombier * set n to length of smaller key 485bd389b36SDavid du Colombier */ 486bd389b36SDavid du Colombier n = ka->klen; 487bd389b36SDavid du Colombier m = kb->klen; 488bd389b36SDavid du Colombier if(n > m) 489bd389b36SDavid du Colombier n = m; 490bd389b36SDavid du Colombier return memcmp(ka->key, kb->key, n); 491bd389b36SDavid du Colombier } 492bd389b36SDavid du Colombier 493bd389b36SDavid du Colombier void 494bd389b36SDavid du Colombier printout(Biobuf *b) 495bd389b36SDavid du Colombier { 496bd389b36SDavid du Colombier long n; 497bd389b36SDavid du Colombier Line **lp, *l; 498bd389b36SDavid du Colombier Key *ok; 499bd389b36SDavid du Colombier 500bd389b36SDavid du Colombier sort4(args.linep, args.nline); 501bd389b36SDavid du Colombier lp = args.linep; 502bd389b36SDavid du Colombier ok = 0; 503bd389b36SDavid du Colombier for(n=args.nline; n>0; n--) { 504bd389b36SDavid du Colombier l = *lp++; 505bd389b36SDavid du Colombier if(args.uflag && ok && kcmp(ok, l->key) == 0) 506bd389b36SDavid du Colombier continue; 507*219b2ee8SDavid du Colombier lineout(b, l); 508bd389b36SDavid du Colombier ok = l->key; 509bd389b36SDavid du Colombier } 510bd389b36SDavid du Colombier } 511bd389b36SDavid du Colombier 512bd389b36SDavid du Colombier void 513bd389b36SDavid du Colombier setfield(int n, int c) 514bd389b36SDavid du Colombier { 515bd389b36SDavid du Colombier Field *f; 516bd389b36SDavid du Colombier 517bd389b36SDavid du Colombier f = &args.field[n]; 518bd389b36SDavid du Colombier switch(c) { 519bd389b36SDavid du Colombier default: 520bd389b36SDavid du Colombier fprint(2, "sort: unknown option: field.%C\n", c); 521bd389b36SDavid du Colombier done("option"); 522bd389b36SDavid du Colombier case 'b': /* skip blanks */ 523bd389b36SDavid du Colombier f->flags |= Bflag; 524bd389b36SDavid du Colombier break; 525bd389b36SDavid du Colombier case 'd': /* directory order */ 526bd389b36SDavid du Colombier f->flags |= Dflag; 527bd389b36SDavid du Colombier break; 528bd389b36SDavid du Colombier case 'f': /* fold case */ 529bd389b36SDavid du Colombier f->flags |= Fflag; 530bd389b36SDavid du Colombier break; 531bd389b36SDavid du Colombier case 'g': /* floating point -n case */ 532bd389b36SDavid du Colombier f->flags |= Gflag; 533bd389b36SDavid du Colombier break; 534bd389b36SDavid du Colombier case 'i': /* ignore non-ascii */ 535bd389b36SDavid du Colombier f->flags |= Iflag; 536bd389b36SDavid du Colombier break; 537bd389b36SDavid du Colombier case 'M': /* month */ 538bd389b36SDavid du Colombier f->flags |= Mflag; 539bd389b36SDavid du Colombier break; 540bd389b36SDavid du Colombier case 'n': /* numbers */ 541bd389b36SDavid du Colombier f->flags |= Nflag; 542bd389b36SDavid du Colombier break; 543bd389b36SDavid du Colombier case 'r': /* reverse */ 544bd389b36SDavid du Colombier f->flags |= Rflag; 545bd389b36SDavid du Colombier break; 546bd389b36SDavid du Colombier case 'w': /* ignore white */ 547bd389b36SDavid du Colombier f->flags |= Wflag; 548bd389b36SDavid du Colombier break; 549bd389b36SDavid du Colombier } 550bd389b36SDavid du Colombier } 551bd389b36SDavid du Colombier 552bd389b36SDavid du Colombier void 553bd389b36SDavid du Colombier dofield(char *s, int *n1, int *n2, int off1, int off2) 554bd389b36SDavid du Colombier { 555bd389b36SDavid du Colombier int c, n; 556bd389b36SDavid du Colombier 557bd389b36SDavid du Colombier c = *s++; 558bd389b36SDavid du Colombier if(c >= '0' && c <= '9') { 559bd389b36SDavid du Colombier n = 0; 560bd389b36SDavid du Colombier while(c >= '0' && c <= '9') { 561bd389b36SDavid du Colombier n = n*10 + (c-'0'); 562bd389b36SDavid du Colombier c = *s++; 563bd389b36SDavid du Colombier } 564bd389b36SDavid du Colombier n -= off1; /* posix committee: rot in hell */ 565bd389b36SDavid du Colombier if(n < 0) { 566bd389b36SDavid du Colombier fprint(2, "sort: field offset must be positive\n"); 567bd389b36SDavid du Colombier done("option"); 568bd389b36SDavid du Colombier } 569bd389b36SDavid du Colombier *n1 = n; 570bd389b36SDavid du Colombier } 571bd389b36SDavid du Colombier if(c == '.') { 572bd389b36SDavid du Colombier c = *s++; 573bd389b36SDavid du Colombier if(c >= '0' && c <= '9') { 574bd389b36SDavid du Colombier n = 0; 575bd389b36SDavid du Colombier while(c >= '0' && c <= '9') { 576bd389b36SDavid du Colombier n = n*10 + (c-'0'); 577bd389b36SDavid du Colombier c = *s++; 578bd389b36SDavid du Colombier } 579bd389b36SDavid du Colombier n -= off2; 580bd389b36SDavid du Colombier if(n < 0) { 581bd389b36SDavid du Colombier fprint(2, "sort: character offset must be positive\n"); 582bd389b36SDavid du Colombier done("option"); 583bd389b36SDavid du Colombier } 584bd389b36SDavid du Colombier *n2 = n; 585bd389b36SDavid du Colombier } 586bd389b36SDavid du Colombier } 587bd389b36SDavid du Colombier while(c != 0) { 588bd389b36SDavid du Colombier setfield(args.nfield, c); 589bd389b36SDavid du Colombier c = *s++; 590bd389b36SDavid du Colombier } 591bd389b36SDavid du Colombier } 592bd389b36SDavid du Colombier 593bd389b36SDavid du Colombier void 594bd389b36SDavid du Colombier printargs(void) 595bd389b36SDavid du Colombier { 596bd389b36SDavid du Colombier int i, n; 597bd389b36SDavid du Colombier Field *f; 598bd389b36SDavid du Colombier char *prefix; 599bd389b36SDavid du Colombier 600bd389b36SDavid du Colombier fprint(2, "sort"); 601bd389b36SDavid du Colombier for(i=0; i<=args.nfield; i++) { 602bd389b36SDavid du Colombier f = &args.field[i]; 603bd389b36SDavid du Colombier prefix = " -"; 604bd389b36SDavid du Colombier if(i) { 605bd389b36SDavid du Colombier n = f->beg1; 606bd389b36SDavid du Colombier if(n >= 0) 607bd389b36SDavid du Colombier fprint(2, " +%d", n); 608bd389b36SDavid du Colombier else 609bd389b36SDavid du Colombier fprint(2, " +*"); 610bd389b36SDavid du Colombier n = f->beg2; 611bd389b36SDavid du Colombier if(n >= 0) 612bd389b36SDavid du Colombier fprint(2, ".%d", n); 613bd389b36SDavid du Colombier else 614bd389b36SDavid du Colombier fprint(2, ".*"); 615bd389b36SDavid du Colombier 616bd389b36SDavid du Colombier if(f->flags & B1flag) 617bd389b36SDavid du Colombier fprint(2, "b"); 618bd389b36SDavid du Colombier 619bd389b36SDavid du Colombier n = f->end1; 620bd389b36SDavid du Colombier if(n >= 0) 621bd389b36SDavid du Colombier fprint(2, " -%d", n); 622bd389b36SDavid du Colombier else 623bd389b36SDavid du Colombier fprint(2, " -*"); 624bd389b36SDavid du Colombier n = f->end2; 625bd389b36SDavid du Colombier if(n >= 0) 626bd389b36SDavid du Colombier fprint(2, ".%d", n); 627bd389b36SDavid du Colombier else 628bd389b36SDavid du Colombier fprint(2, ".*"); 629bd389b36SDavid du Colombier prefix = ""; 630bd389b36SDavid du Colombier } 631bd389b36SDavid du Colombier if(f->flags & Bflag) 632bd389b36SDavid du Colombier fprint(2, "%sb", prefix); 633bd389b36SDavid du Colombier if(f->flags & Dflag) 634bd389b36SDavid du Colombier fprint(2, "%sd", prefix); 635bd389b36SDavid du Colombier if(f->flags & Fflag) 636bd389b36SDavid du Colombier fprint(2, "%sf", prefix); 637bd389b36SDavid du Colombier if(f->flags & Gflag) 638bd389b36SDavid du Colombier fprint(2, "%sg", prefix); 639bd389b36SDavid du Colombier if(f->flags & Iflag) 640bd389b36SDavid du Colombier fprint(2, "%si", prefix); 641bd389b36SDavid du Colombier if(f->flags & Mflag) 642bd389b36SDavid du Colombier fprint(2, "%sM", prefix); 643bd389b36SDavid du Colombier if(f->flags & Nflag) 644bd389b36SDavid du Colombier fprint(2, "%sn", prefix); 645bd389b36SDavid du Colombier if(f->flags & Rflag) 646bd389b36SDavid du Colombier fprint(2, "%sr", prefix); 647bd389b36SDavid du Colombier if(f->flags & Wflag) 648bd389b36SDavid du Colombier fprint(2, "%sw", prefix); 649bd389b36SDavid du Colombier } 650bd389b36SDavid du Colombier if(args.cflag) 651bd389b36SDavid du Colombier fprint(2, " -c"); 652bd389b36SDavid du Colombier if(args.uflag) 653bd389b36SDavid du Colombier fprint(2, " -u"); 654bd389b36SDavid du Colombier if(args.ofile) 655bd389b36SDavid du Colombier fprint(2, " -o %s", args.ofile); 656bd389b36SDavid du Colombier fprint(2, "\n"); 657bd389b36SDavid du Colombier } 658bd389b36SDavid du Colombier 659bd389b36SDavid du Colombier void 660bd389b36SDavid du Colombier newfield(void) 661bd389b36SDavid du Colombier { 662bd389b36SDavid du Colombier int n; 663bd389b36SDavid du Colombier Field *f; 664bd389b36SDavid du Colombier 665bd389b36SDavid du Colombier n = args.nfield + 1; 666bd389b36SDavid du Colombier if(n >= Nfield) { 667bd389b36SDavid du Colombier fprint(2, "sort: too many fields specified\n"); 668bd389b36SDavid du Colombier done("option"); 669bd389b36SDavid du Colombier } 670bd389b36SDavid du Colombier args.nfield = n; 671bd389b36SDavid du Colombier f = &args.field[n]; 672bd389b36SDavid du Colombier f->beg1 = -1; 673bd389b36SDavid du Colombier f->beg2 = -1; 674bd389b36SDavid du Colombier f->end1 = -1; 675bd389b36SDavid du Colombier f->end2 = -1; 676bd389b36SDavid du Colombier } 677bd389b36SDavid du Colombier 678bd389b36SDavid du Colombier void 679bd389b36SDavid du Colombier doargs(int argc, char *argv[]) 680bd389b36SDavid du Colombier { 681bd389b36SDavid du Colombier int i, c, hadplus; 682bd389b36SDavid du Colombier char *s, *p, *q; 683bd389b36SDavid du Colombier Field *f; 684bd389b36SDavid du Colombier 685bd389b36SDavid du Colombier hadplus = 0; 686bd389b36SDavid du Colombier for(i=1; i<argc; i++) { 687bd389b36SDavid du Colombier s = argv[i]; 688bd389b36SDavid du Colombier c = *s++; 689bd389b36SDavid du Colombier if(c == '-') { 690bd389b36SDavid du Colombier c = *s; 691bd389b36SDavid du Colombier if(c == 0) /* forced end of arg marker */ 692bd389b36SDavid du Colombier break; 693bd389b36SDavid du Colombier argv[i] = 0; /* clobber args processed */ 694bd389b36SDavid du Colombier if(c == '.' || (c >= '0' && c <= '9')) { 695bd389b36SDavid du Colombier if(!hadplus) 696bd389b36SDavid du Colombier newfield(); 697bd389b36SDavid du Colombier f = &args.field[args.nfield]; 698bd389b36SDavid du Colombier dofield(s, &f->end1, &f->end2, 0, 0); 699bd389b36SDavid du Colombier hadplus = 0; 700bd389b36SDavid du Colombier continue; 701bd389b36SDavid du Colombier } 702bd389b36SDavid du Colombier 703bd389b36SDavid du Colombier while(c = *s++) 704bd389b36SDavid du Colombier switch(c) { 705bd389b36SDavid du Colombier case '-': /* end of options */ 706bd389b36SDavid du Colombier i = argc; 707bd389b36SDavid du Colombier continue; 708bd389b36SDavid du Colombier case 'T': /* temp directory */ 709bd389b36SDavid du Colombier if(*s == 0) { 710bd389b36SDavid du Colombier i++; 711bd389b36SDavid du Colombier if(i < argc) { 712bd389b36SDavid du Colombier args.tname = argv[i]; 713bd389b36SDavid du Colombier argv[i] = 0; 714bd389b36SDavid du Colombier } 715bd389b36SDavid du Colombier } else 716bd389b36SDavid du Colombier args.tname = s; 717bd389b36SDavid du Colombier s = strchr(s, 0); 718bd389b36SDavid du Colombier break; 719bd389b36SDavid du Colombier case 'o': /* output file */ 720bd389b36SDavid du Colombier if(*s == 0) { 721bd389b36SDavid du Colombier i++; 722bd389b36SDavid du Colombier if(i < argc) { 723bd389b36SDavid du Colombier args.ofile = argv[i]; 724bd389b36SDavid du Colombier argv[i] = 0; 725bd389b36SDavid du Colombier } 726bd389b36SDavid du Colombier } else 727bd389b36SDavid du Colombier args.ofile = s; 728bd389b36SDavid du Colombier s = strchr(s, 0); 729bd389b36SDavid du Colombier break; 730bd389b36SDavid du Colombier case 'k': /* posix key (what were they thinking?) */ 731bd389b36SDavid du Colombier p = 0; 732bd389b36SDavid du Colombier if(*s == 0) { 733bd389b36SDavid du Colombier i++; 734bd389b36SDavid du Colombier if(i < argc) { 735bd389b36SDavid du Colombier p = argv[i]; 736bd389b36SDavid du Colombier argv[i] = 0; 737bd389b36SDavid du Colombier } 738bd389b36SDavid du Colombier } else 739bd389b36SDavid du Colombier p = s; 740bd389b36SDavid du Colombier s = strchr(s, 0); 741bd389b36SDavid du Colombier if(p == 0) 742bd389b36SDavid du Colombier break; 743bd389b36SDavid du Colombier 744bd389b36SDavid du Colombier newfield(); 745bd389b36SDavid du Colombier q = strchr(p, ','); 746bd389b36SDavid du Colombier if(q) 747bd389b36SDavid du Colombier *q++ = 0; 748bd389b36SDavid du Colombier f = &args.field[args.nfield]; 749bd389b36SDavid du Colombier dofield(p, &f->beg1, &f->beg2, 1, 1); 750bd389b36SDavid du Colombier if(f->flags & Bflag) { 751bd389b36SDavid du Colombier f->flags |= B1flag; 752bd389b36SDavid du Colombier f->flags &= ~Bflag; 753bd389b36SDavid du Colombier } 754bd389b36SDavid du Colombier if(q) { 755bd389b36SDavid du Colombier dofield(q, &f->end1, &f->end2, 1, 0); 756bd389b36SDavid du Colombier if(f->end2 <= 0) 757bd389b36SDavid du Colombier f->end1++; 758bd389b36SDavid du Colombier } 759bd389b36SDavid du Colombier hadplus = 0; 760bd389b36SDavid du Colombier break; 761bd389b36SDavid du Colombier case 't': /* tab character */ 762bd389b36SDavid du Colombier if(*s == 0) { 763bd389b36SDavid du Colombier i++; 764bd389b36SDavid du Colombier if(i < argc) { 765bd389b36SDavid du Colombier chartorune(&args.tabchar, argv[i]); 766bd389b36SDavid du Colombier argv[i] = 0; 767bd389b36SDavid du Colombier } 768bd389b36SDavid du Colombier } else 769bd389b36SDavid du Colombier s += chartorune(&args.tabchar, s); 770bd389b36SDavid du Colombier if(args.tabchar == '\n') { 771bd389b36SDavid du Colombier fprint(2, "aw come on, rob\n"); 772bd389b36SDavid du Colombier done("rob"); 773bd389b36SDavid du Colombier } 774bd389b36SDavid du Colombier break; 775bd389b36SDavid du Colombier case 'c': /* check order */ 776bd389b36SDavid du Colombier args.cflag = 1; 777bd389b36SDavid du Colombier break; 778bd389b36SDavid du Colombier case 'u': /* unique */ 779bd389b36SDavid du Colombier args.uflag = 1; 780bd389b36SDavid du Colombier break; 781bd389b36SDavid du Colombier case 'v': /* debugging noise */ 782bd389b36SDavid du Colombier args.vflag = 1; 783bd389b36SDavid du Colombier break; 784bd389b36SDavid du Colombier 785bd389b36SDavid du Colombier case 'M': /* month */ 786bd389b36SDavid du Colombier case 'b': /* skip blanks */ 787bd389b36SDavid du Colombier case 'd': /* directory order */ 788bd389b36SDavid du Colombier case 'f': /* fold case */ 789bd389b36SDavid du Colombier case 'g': /* floating numbers */ 790bd389b36SDavid du Colombier case 'i': /* ignore non-ascii */ 791bd389b36SDavid du Colombier case 'n': /* numbers */ 792bd389b36SDavid du Colombier case 'r': /* reverse */ 793bd389b36SDavid du Colombier case 'w': /* ignore white */ 794bd389b36SDavid du Colombier if(args.nfield > 0) 795bd389b36SDavid du Colombier fprint(2, "sort: global field set after -k\n"); 796bd389b36SDavid du Colombier setfield(0, c); 797bd389b36SDavid du Colombier break; 798bd389b36SDavid du Colombier case 'm': 799*219b2ee8SDavid du Colombier /* option m silently ignored but required by posix */ 800bd389b36SDavid du Colombier break; 801bd389b36SDavid du Colombier default: 802bd389b36SDavid du Colombier fprint(2, "sort: unknown option: -%C\n", c); 803bd389b36SDavid du Colombier done("option"); 804bd389b36SDavid du Colombier } 805bd389b36SDavid du Colombier continue; 806bd389b36SDavid du Colombier } 807bd389b36SDavid du Colombier if(c == '+') { 808bd389b36SDavid du Colombier argv[i] = 0; /* clobber args processed */ 809bd389b36SDavid du Colombier c = *s; 810bd389b36SDavid du Colombier if(c == '.' || (c >= '0' && c <= '9')) { 811bd389b36SDavid du Colombier newfield(); 812bd389b36SDavid du Colombier f = &args.field[args.nfield]; 813bd389b36SDavid du Colombier dofield(s, &f->beg1, &f->beg2, 0, 0); 814bd389b36SDavid du Colombier if(f->flags & Bflag) { 815bd389b36SDavid du Colombier f->flags |= B1flag; 816bd389b36SDavid du Colombier f->flags &= ~Bflag; 817bd389b36SDavid du Colombier } 818bd389b36SDavid du Colombier hadplus = 1; 819bd389b36SDavid du Colombier continue; 820bd389b36SDavid du Colombier } 821bd389b36SDavid du Colombier fprint(2, "sort: unknown option: +%C\n", c); 822bd389b36SDavid du Colombier done("option"); 823bd389b36SDavid du Colombier } 824bd389b36SDavid du Colombier args.nfile++; 825bd389b36SDavid du Colombier } 826bd389b36SDavid du Colombier 827bd389b36SDavid du Colombier for(i=0; i<=args.nfield; i++) { 828bd389b36SDavid du Colombier f = &args.field[i]; 829bd389b36SDavid du Colombier 830bd389b36SDavid du Colombier /* 831bd389b36SDavid du Colombier * global options apply to fields that 832bd389b36SDavid du Colombier * specify no options 833bd389b36SDavid du Colombier */ 834bd389b36SDavid du Colombier if(f->flags == 0) { 835bd389b36SDavid du Colombier f->flags = args.field[0].flags; 836bd389b36SDavid du Colombier if(args.field[0].flags & Bflag) 837bd389b36SDavid du Colombier f->flags |= B1flag; 838bd389b36SDavid du Colombier } 839bd389b36SDavid du Colombier 840bd389b36SDavid du Colombier 841bd389b36SDavid du Colombier /* 842bd389b36SDavid du Colombier * build buildkey specification 843bd389b36SDavid du Colombier */ 844bd389b36SDavid du Colombier switch(f->flags & ~(Bflag|B1flag)) { 845bd389b36SDavid du Colombier default: 846bd389b36SDavid du Colombier fprint(2, "sort: illegal combination of flags: %lx\n", f->flags); 847bd389b36SDavid du Colombier done("option"); 848bd389b36SDavid du Colombier case 0: 849bd389b36SDavid du Colombier f->dokey = dokey_; 850bd389b36SDavid du Colombier break; 851bd389b36SDavid du Colombier case Rflag: 852bd389b36SDavid du Colombier f->dokey = dokey_r; 853bd389b36SDavid du Colombier break; 854bd389b36SDavid du Colombier case Gflag: 855bd389b36SDavid du Colombier case Nflag: 856bd389b36SDavid du Colombier case Gflag|Nflag: 857bd389b36SDavid du Colombier case Gflag|Rflag: 858bd389b36SDavid du Colombier case Nflag|Rflag: 859bd389b36SDavid du Colombier case Gflag|Nflag|Rflag: 860bd389b36SDavid du Colombier f->dokey = dokey_gn; 861bd389b36SDavid du Colombier break; 862bd389b36SDavid du Colombier case Mflag: 863bd389b36SDavid du Colombier case Mflag|Rflag: 864bd389b36SDavid du Colombier f->dokey = dokey_m; 865bd389b36SDavid du Colombier makemapm(f); 866bd389b36SDavid du Colombier break; 867bd389b36SDavid du Colombier case Dflag: 868bd389b36SDavid du Colombier case Dflag|Fflag: 869bd389b36SDavid du Colombier case Dflag|Fflag|Iflag: 870bd389b36SDavid du Colombier case Dflag|Fflag|Iflag|Rflag: 871bd389b36SDavid du Colombier case Dflag|Fflag|Iflag|Rflag|Wflag: 872bd389b36SDavid du Colombier case Dflag|Fflag|Iflag|Wflag: 873bd389b36SDavid du Colombier case Dflag|Fflag|Rflag: 874bd389b36SDavid du Colombier case Dflag|Fflag|Rflag|Wflag: 875bd389b36SDavid du Colombier case Dflag|Fflag|Wflag: 876bd389b36SDavid du Colombier case Dflag|Iflag: 877bd389b36SDavid du Colombier case Dflag|Iflag|Rflag: 878bd389b36SDavid du Colombier case Dflag|Iflag|Rflag|Wflag: 879bd389b36SDavid du Colombier case Dflag|Iflag|Wflag: 880bd389b36SDavid du Colombier case Dflag|Rflag: 881bd389b36SDavid du Colombier case Dflag|Rflag|Wflag: 882bd389b36SDavid du Colombier case Dflag|Wflag: 883bd389b36SDavid du Colombier case Fflag: 884bd389b36SDavid du Colombier case Fflag|Iflag: 885bd389b36SDavid du Colombier case Fflag|Iflag|Rflag: 886bd389b36SDavid du Colombier case Fflag|Iflag|Rflag|Wflag: 887bd389b36SDavid du Colombier case Fflag|Iflag|Wflag: 888bd389b36SDavid du Colombier case Fflag|Rflag: 889bd389b36SDavid du Colombier case Fflag|Rflag|Wflag: 890bd389b36SDavid du Colombier case Fflag|Wflag: 891bd389b36SDavid du Colombier case Iflag: 892bd389b36SDavid du Colombier case Iflag|Rflag: 893bd389b36SDavid du Colombier case Iflag|Rflag|Wflag: 894bd389b36SDavid du Colombier case Iflag|Wflag: 895bd389b36SDavid du Colombier case Wflag: 896bd389b36SDavid du Colombier f->dokey = dokey_dfi; 897bd389b36SDavid du Colombier makemapd(f); 898bd389b36SDavid du Colombier break; 899bd389b36SDavid du Colombier } 900bd389b36SDavid du Colombier } 901bd389b36SDavid du Colombier 902bd389b36SDavid du Colombier /* 903bd389b36SDavid du Colombier * random spot checks 904bd389b36SDavid du Colombier */ 905bd389b36SDavid du Colombier if(args.nfile > 1 && args.cflag) { 906bd389b36SDavid du Colombier fprint(2, "sort: -c can have at most one input file\n"); 907bd389b36SDavid du Colombier done("option"); 908bd389b36SDavid du Colombier } 909bd389b36SDavid du Colombier return; 910bd389b36SDavid du Colombier } 911bd389b36SDavid du Colombier 912bd389b36SDavid du Colombier uchar* 913bd389b36SDavid du Colombier skip(uchar *l, int n1, int n2, int bflag, int endfield) 914bd389b36SDavid du Colombier { 915bd389b36SDavid du Colombier int i, c, tc; 916bd389b36SDavid du Colombier Rune r; 917bd389b36SDavid du Colombier 918bd389b36SDavid du Colombier if(endfield && n1 < 0) 919bd389b36SDavid du Colombier return 0; 920bd389b36SDavid du Colombier 921bd389b36SDavid du Colombier c = *l++; 922bd389b36SDavid du Colombier tc = args.tabchar; 923bd389b36SDavid du Colombier if(tc) { 924bd389b36SDavid du Colombier if(tc < Runeself) { 925bd389b36SDavid du Colombier for(i=n1; i>0; i--) { 926bd389b36SDavid du Colombier while(c != tc) { 927bd389b36SDavid du Colombier if(c == '\n') 928bd389b36SDavid du Colombier return 0; 929bd389b36SDavid du Colombier c = *l++; 930bd389b36SDavid du Colombier } 931bd389b36SDavid du Colombier if(!(endfield && i == 1)) 932bd389b36SDavid du Colombier c = *l++; 933bd389b36SDavid du Colombier } 934bd389b36SDavid du Colombier } else { 935bd389b36SDavid du Colombier l--; 936bd389b36SDavid du Colombier l += chartorune(&r, (char*)l); 937bd389b36SDavid du Colombier for(i=n1; i>0; i--) { 938bd389b36SDavid du Colombier while(r != tc) { 939bd389b36SDavid du Colombier if(r == '\n') 940bd389b36SDavid du Colombier return 0; 941bd389b36SDavid du Colombier l += chartorune(&r, (char*)l); 942bd389b36SDavid du Colombier } 943bd389b36SDavid du Colombier if(!(endfield && i == 1)) 944bd389b36SDavid du Colombier l += chartorune(&r, (char*)l); 945bd389b36SDavid du Colombier } 946bd389b36SDavid du Colombier c = r; 947bd389b36SDavid du Colombier } 948bd389b36SDavid du Colombier } else { 949bd389b36SDavid du Colombier for(i=n1; i>0; i--) { 950bd389b36SDavid du Colombier while(c == ' ' || c == '\t') 951bd389b36SDavid du Colombier c = *l++; 952bd389b36SDavid du Colombier while(c != ' ' && c != '\t') { 953bd389b36SDavid du Colombier if(c == '\n') 954bd389b36SDavid du Colombier return 0; 955bd389b36SDavid du Colombier c = *l++; 956bd389b36SDavid du Colombier } 957bd389b36SDavid du Colombier } 958bd389b36SDavid du Colombier } 959bd389b36SDavid du Colombier 960bd389b36SDavid du Colombier if(bflag) 961bd389b36SDavid du Colombier while(c == ' ' || c == '\t') 962bd389b36SDavid du Colombier c = *l++; 963bd389b36SDavid du Colombier 964bd389b36SDavid du Colombier l--; 965bd389b36SDavid du Colombier for(i=n2; i>0; i--) { 966bd389b36SDavid du Colombier c = *l; 967bd389b36SDavid du Colombier if(c < Runeself) { 968bd389b36SDavid du Colombier if(c == '\n') 969bd389b36SDavid du Colombier return 0; 970bd389b36SDavid du Colombier l++; 971bd389b36SDavid du Colombier continue; 972bd389b36SDavid du Colombier } 973bd389b36SDavid du Colombier l += chartorune(&r, (char*)l); 974bd389b36SDavid du Colombier } 975bd389b36SDavid du Colombier return l; 976bd389b36SDavid du Colombier } 977bd389b36SDavid du Colombier 978bd389b36SDavid du Colombier void 979bd389b36SDavid du Colombier dokey_gn(Key *k, uchar *lp, uchar *lpe, Field *f) 980bd389b36SDavid du Colombier { 981bd389b36SDavid du Colombier uchar *kp; 982bd389b36SDavid du Colombier int c, cl, dp; 983bd389b36SDavid du Colombier int state, nzero, exp, expsign, rflag; 984bd389b36SDavid du Colombier 985bd389b36SDavid du Colombier cl = k->klen + 3; 986bd389b36SDavid du Colombier kp = k->key + cl; /* skip place for sign, exponent[2] */ 987bd389b36SDavid du Colombier 988bd389b36SDavid du Colombier nzero = 0; /* number of trailing zeros */ 989bd389b36SDavid du Colombier exp = 0; /* value of the exponent */ 990bd389b36SDavid du Colombier expsign = 0; /* sign of the exponent */ 991bd389b36SDavid du Colombier dp = 0x4040; /* location of decimal point */ 992bd389b36SDavid du Colombier rflag = f->flags&Rflag; /* xor of rflag and - sign */ 993bd389b36SDavid du Colombier state = NSstart; 994bd389b36SDavid du Colombier 995bd389b36SDavid du Colombier for(;; lp++) { 996bd389b36SDavid du Colombier if(lp >= lpe) 997bd389b36SDavid du Colombier break; 998bd389b36SDavid du Colombier c = *lp; 999bd389b36SDavid du Colombier 1000bd389b36SDavid du Colombier if(c == ' ' || c == '\t') { 1001bd389b36SDavid du Colombier switch(state) { 1002bd389b36SDavid du Colombier case NSstart: 1003bd389b36SDavid du Colombier case NSsign: 1004bd389b36SDavid du Colombier continue; 1005bd389b36SDavid du Colombier } 1006bd389b36SDavid du Colombier break; 1007bd389b36SDavid du Colombier } 1008bd389b36SDavid du Colombier if(c == '+' || c == '-') { 1009bd389b36SDavid du Colombier switch(state) { 1010bd389b36SDavid du Colombier case NSstart: 1011bd389b36SDavid du Colombier state = NSsign; 1012bd389b36SDavid du Colombier if(c == '-') 1013bd389b36SDavid du Colombier rflag = !rflag; 1014bd389b36SDavid du Colombier continue; 1015bd389b36SDavid du Colombier case NSexp: 1016bd389b36SDavid du Colombier state = NSexpsign; 1017bd389b36SDavid du Colombier if(c == '-') 1018bd389b36SDavid du Colombier expsign = 1; 1019bd389b36SDavid du Colombier continue; 1020bd389b36SDavid du Colombier } 1021bd389b36SDavid du Colombier break; 1022bd389b36SDavid du Colombier } 1023bd389b36SDavid du Colombier if(c == '0') { 1024bd389b36SDavid du Colombier switch(state) { 1025bd389b36SDavid du Colombier case NSdigit: 1026bd389b36SDavid du Colombier if(rflag) 1027bd389b36SDavid du Colombier c = ~c; 1028bd389b36SDavid du Colombier *kp++ = c; 1029bd389b36SDavid du Colombier cl++; 1030bd389b36SDavid du Colombier nzero++; 1031bd389b36SDavid du Colombier dp++; 1032bd389b36SDavid du Colombier state = NSdigit; 1033bd389b36SDavid du Colombier continue; 1034bd389b36SDavid du Colombier case NSfract: 1035bd389b36SDavid du Colombier if(rflag) 1036bd389b36SDavid du Colombier c = ~c; 1037bd389b36SDavid du Colombier *kp++ = c; 1038bd389b36SDavid du Colombier cl++; 1039bd389b36SDavid du Colombier nzero++; 1040bd389b36SDavid du Colombier state = NSfract; 1041bd389b36SDavid du Colombier continue; 1042bd389b36SDavid du Colombier case NSstart: 1043bd389b36SDavid du Colombier case NSsign: 1044bd389b36SDavid du Colombier case NSzero: 1045bd389b36SDavid du Colombier state = NSzero; 1046bd389b36SDavid du Colombier continue; 1047bd389b36SDavid du Colombier case NSzerofract: 1048bd389b36SDavid du Colombier case NSpoint: 1049bd389b36SDavid du Colombier dp--; 1050bd389b36SDavid du Colombier state = NSzerofract; 1051bd389b36SDavid du Colombier continue; 1052bd389b36SDavid du Colombier case NSexpsign: 1053bd389b36SDavid du Colombier case NSexp: 1054bd389b36SDavid du Colombier case NSexpdigit: 1055bd389b36SDavid du Colombier exp = exp*10 + (c - '0'); 1056bd389b36SDavid du Colombier state = NSexpdigit; 1057bd389b36SDavid du Colombier continue; 1058bd389b36SDavid du Colombier } 1059bd389b36SDavid du Colombier break; 1060bd389b36SDavid du Colombier } 1061bd389b36SDavid du Colombier if(c >= '1' && c <= '9') { 1062bd389b36SDavid du Colombier switch(state) { 1063bd389b36SDavid du Colombier case NSzero: 1064bd389b36SDavid du Colombier case NSstart: 1065bd389b36SDavid du Colombier case NSsign: 1066bd389b36SDavid du Colombier case NSdigit: 1067bd389b36SDavid du Colombier if(rflag) 1068bd389b36SDavid du Colombier c = ~c; 1069bd389b36SDavid du Colombier *kp++ = c; 1070bd389b36SDavid du Colombier cl++; 1071bd389b36SDavid du Colombier nzero = 0; 1072bd389b36SDavid du Colombier dp++; 1073bd389b36SDavid du Colombier state = NSdigit; 1074bd389b36SDavid du Colombier continue; 1075bd389b36SDavid du Colombier case NSzerofract: 1076bd389b36SDavid du Colombier case NSpoint: 1077bd389b36SDavid du Colombier case NSfract: 1078bd389b36SDavid du Colombier if(rflag) 1079bd389b36SDavid du Colombier c = ~c; 1080bd389b36SDavid du Colombier *kp++ = c; 1081bd389b36SDavid du Colombier cl++; 1082bd389b36SDavid du Colombier nzero = 0; 1083bd389b36SDavid du Colombier state = NSfract; 1084bd389b36SDavid du Colombier continue; 1085bd389b36SDavid du Colombier case NSexpsign: 1086bd389b36SDavid du Colombier case NSexp: 1087bd389b36SDavid du Colombier case NSexpdigit: 1088bd389b36SDavid du Colombier exp = exp*10 + (c - '0'); 1089bd389b36SDavid du Colombier state = NSexpdigit; 1090bd389b36SDavid du Colombier continue; 1091bd389b36SDavid du Colombier } 1092bd389b36SDavid du Colombier break; 1093bd389b36SDavid du Colombier } 1094bd389b36SDavid du Colombier if(c == '.') { 1095bd389b36SDavid du Colombier switch(state) { 1096bd389b36SDavid du Colombier case NSstart: 1097bd389b36SDavid du Colombier case NSsign: 1098bd389b36SDavid du Colombier state = NSpoint; 1099bd389b36SDavid du Colombier continue; 1100bd389b36SDavid du Colombier case NSzero: 1101bd389b36SDavid du Colombier state = NSzerofract; 1102bd389b36SDavid du Colombier continue; 1103bd389b36SDavid du Colombier case NSdigit: 1104bd389b36SDavid du Colombier state = NSfract; 1105bd389b36SDavid du Colombier continue; 1106bd389b36SDavid du Colombier } 1107bd389b36SDavid du Colombier break; 1108bd389b36SDavid du Colombier } 1109bd389b36SDavid du Colombier if((f->flags & Gflag) && (c == 'e' || c == 'E')) { 1110bd389b36SDavid du Colombier switch(state) { 1111bd389b36SDavid du Colombier case NSdigit: 1112bd389b36SDavid du Colombier case NSfract: 1113bd389b36SDavid du Colombier state = NSexp; 1114bd389b36SDavid du Colombier continue; 1115bd389b36SDavid du Colombier } 1116bd389b36SDavid du Colombier break; 1117bd389b36SDavid du Colombier } 1118bd389b36SDavid du Colombier break; 1119bd389b36SDavid du Colombier } 1120bd389b36SDavid du Colombier 1121bd389b36SDavid du Colombier switch(state) { 1122bd389b36SDavid du Colombier /* 1123bd389b36SDavid du Colombier * result is zero 1124bd389b36SDavid du Colombier */ 1125bd389b36SDavid du Colombier case NSstart: 1126bd389b36SDavid du Colombier case NSsign: 1127bd389b36SDavid du Colombier case NSzero: 1128bd389b36SDavid du Colombier case NSzerofract: 1129bd389b36SDavid du Colombier case NSpoint: 1130bd389b36SDavid du Colombier kp = k->key + k->klen; 1131bd389b36SDavid du Colombier k->klen += 2; 1132bd389b36SDavid du Colombier kp[0] = 0x20; /* between + and - */ 1133bd389b36SDavid du Colombier kp[1] = 0; 1134bd389b36SDavid du Colombier return; 1135bd389b36SDavid du Colombier /* 1136bd389b36SDavid du Colombier * result has exponent 1137bd389b36SDavid du Colombier */ 1138bd389b36SDavid du Colombier case NSexpsign: 1139bd389b36SDavid du Colombier case NSexp: 1140bd389b36SDavid du Colombier case NSexpdigit: 1141bd389b36SDavid du Colombier if(expsign) 1142bd389b36SDavid du Colombier exp = -exp; 1143bd389b36SDavid du Colombier dp += exp; 1144bd389b36SDavid du Colombier 1145bd389b36SDavid du Colombier /* 1146bd389b36SDavid du Colombier * result is fixed point number 1147bd389b36SDavid du Colombier */ 1148bd389b36SDavid du Colombier case NSdigit: 1149bd389b36SDavid du Colombier case NSfract: 1150bd389b36SDavid du Colombier kp -= nzero; 1151bd389b36SDavid du Colombier cl -= nzero; 1152bd389b36SDavid du Colombier break; 1153bd389b36SDavid du Colombier } 1154bd389b36SDavid du Colombier 1155bd389b36SDavid du Colombier /* 1156bd389b36SDavid du Colombier * end of number 1157bd389b36SDavid du Colombier */ 1158bd389b36SDavid du Colombier c = 0; 1159bd389b36SDavid du Colombier if(rflag) 1160bd389b36SDavid du Colombier c = ~c; 1161bd389b36SDavid du Colombier *kp = c; 1162bd389b36SDavid du Colombier 1163bd389b36SDavid du Colombier /* 1164bd389b36SDavid du Colombier * sign and exponent 1165bd389b36SDavid du Colombier */ 1166bd389b36SDavid du Colombier c = 0x30; 1167bd389b36SDavid du Colombier if(rflag) { 1168bd389b36SDavid du Colombier c = 0x10; 1169bd389b36SDavid du Colombier dp = ~dp; 1170bd389b36SDavid du Colombier } 1171bd389b36SDavid du Colombier kp = k->key + k->klen; 1172bd389b36SDavid du Colombier kp[0] = c; 1173bd389b36SDavid du Colombier kp[1] = (dp >> 8); 1174bd389b36SDavid du Colombier kp[2] = dp; 1175bd389b36SDavid du Colombier k->klen = cl+1; 1176bd389b36SDavid du Colombier } 1177bd389b36SDavid du Colombier 1178bd389b36SDavid du Colombier void 1179bd389b36SDavid du Colombier dokey_m(Key *k, uchar *lp, uchar *lpe, Field *f) 1180bd389b36SDavid du Colombier { 1181bd389b36SDavid du Colombier uchar *kp; 1182bd389b36SDavid du Colombier Rune r, place[3]; 1183bd389b36SDavid du Colombier int c, cl, pc; 1184bd389b36SDavid du Colombier int rflag; 1185bd389b36SDavid du Colombier 1186bd389b36SDavid du Colombier rflag = f->flags&Rflag; 1187bd389b36SDavid du Colombier pc = 0; 1188bd389b36SDavid du Colombier 1189bd389b36SDavid du Colombier cl = k->klen; 1190bd389b36SDavid du Colombier kp = k->key + cl; 1191bd389b36SDavid du Colombier 1192bd389b36SDavid du Colombier for(;;) { 1193bd389b36SDavid du Colombier /* 1194bd389b36SDavid du Colombier * get the character 1195bd389b36SDavid du Colombier */ 1196bd389b36SDavid du Colombier if(lp >= lpe) 1197bd389b36SDavid du Colombier break; 1198bd389b36SDavid du Colombier c = *lp; 1199bd389b36SDavid du Colombier if(c >= Runeself) { 1200bd389b36SDavid du Colombier lp += chartorune(&r, (char*)lp); 1201bd389b36SDavid du Colombier c = r; 1202bd389b36SDavid du Colombier } else 1203bd389b36SDavid du Colombier lp++; 1204bd389b36SDavid du Colombier 1205bd389b36SDavid du Colombier if(c < nelem(f->mapto)) { 1206bd389b36SDavid du Colombier c = f->mapto[c]; 1207bd389b36SDavid du Colombier if(c == 0) 1208bd389b36SDavid du Colombier continue; 1209bd389b36SDavid du Colombier } 1210bd389b36SDavid du Colombier place[pc++] = c; 1211bd389b36SDavid du Colombier if(pc < 3) 1212bd389b36SDavid du Colombier continue; 1213bd389b36SDavid du Colombier for(c=11; c>=0; c--) 1214bd389b36SDavid du Colombier if(memcmp(month[c], place, sizeof(place)) == 0) 1215bd389b36SDavid du Colombier break; 1216bd389b36SDavid du Colombier c += 10; 1217bd389b36SDavid du Colombier if(rflag) 1218bd389b36SDavid du Colombier c = ~c; 1219bd389b36SDavid du Colombier *kp++ = c; 1220bd389b36SDavid du Colombier cl++; 1221bd389b36SDavid du Colombier break; 1222bd389b36SDavid du Colombier } 1223bd389b36SDavid du Colombier 1224bd389b36SDavid du Colombier c = 0; 1225bd389b36SDavid du Colombier if(rflag) 1226bd389b36SDavid du Colombier c = ~c; 1227bd389b36SDavid du Colombier *kp = c; 1228bd389b36SDavid du Colombier k->klen = cl+1; 1229bd389b36SDavid du Colombier } 1230bd389b36SDavid du Colombier 1231bd389b36SDavid du Colombier void 1232bd389b36SDavid du Colombier dokey_dfi(Key *k, uchar *lp, uchar *lpe, Field *f) 1233bd389b36SDavid du Colombier { 1234bd389b36SDavid du Colombier uchar *kp; 1235bd389b36SDavid du Colombier Rune r; 1236bd389b36SDavid du Colombier int c, cl, n, rflag; 1237bd389b36SDavid du Colombier 1238bd389b36SDavid du Colombier cl = k->klen; 1239bd389b36SDavid du Colombier kp = k->key + cl; 1240bd389b36SDavid du Colombier rflag = f->flags & Rflag; 1241bd389b36SDavid du Colombier 1242bd389b36SDavid du Colombier for(;;) { 1243bd389b36SDavid du Colombier /* 1244bd389b36SDavid du Colombier * get the character 1245bd389b36SDavid du Colombier */ 1246bd389b36SDavid du Colombier if(lp >= lpe) 1247bd389b36SDavid du Colombier break; 1248bd389b36SDavid du Colombier c = *lp; 1249bd389b36SDavid du Colombier if(c >= Runeself) { 1250bd389b36SDavid du Colombier lp += chartorune(&r, (char*)lp); 1251bd389b36SDavid du Colombier c = r; 1252bd389b36SDavid du Colombier } else 1253bd389b36SDavid du Colombier lp++; 1254bd389b36SDavid du Colombier 1255bd389b36SDavid du Colombier /* 1256bd389b36SDavid du Colombier * do the various mappings. 1257bd389b36SDavid du Colombier * the common case is handled 1258bd389b36SDavid du Colombier * completely by the table. 1259bd389b36SDavid du Colombier */ 1260bd389b36SDavid du Colombier if(c != 0 && c < Runeself) { 1261bd389b36SDavid du Colombier c = f->mapto[c]; 1262bd389b36SDavid du Colombier if(c) { 1263bd389b36SDavid du Colombier *kp++ = c; 1264bd389b36SDavid du Colombier cl++; 1265bd389b36SDavid du Colombier } 1266bd389b36SDavid du Colombier continue; 1267bd389b36SDavid du Colombier } 1268bd389b36SDavid du Colombier 1269bd389b36SDavid du Colombier /* 1270bd389b36SDavid du Colombier * for characters out of range, 1271bd389b36SDavid du Colombier * the table does not do Rflag. 1272bd389b36SDavid du Colombier * ignore is based on mapto[255] 1273bd389b36SDavid du Colombier */ 1274bd389b36SDavid du Colombier if(c != 0 && c < nelem(f->mapto)) { 1275bd389b36SDavid du Colombier c = f->mapto[c]; 1276bd389b36SDavid du Colombier if(c == 0) 1277bd389b36SDavid du Colombier continue; 1278bd389b36SDavid du Colombier } else 1279bd389b36SDavid du Colombier if(f->mapto[nelem(f->mapto)-1] == 0) 1280bd389b36SDavid du Colombier continue; 1281bd389b36SDavid du Colombier 1282bd389b36SDavid du Colombier /* 1283bd389b36SDavid du Colombier * put it in the key 1284bd389b36SDavid du Colombier */ 1285bd389b36SDavid du Colombier r = c; 1286bd389b36SDavid du Colombier n = runetochar((char*)kp, &r); 1287bd389b36SDavid du Colombier kp += n; 1288bd389b36SDavid du Colombier cl += n; 1289bd389b36SDavid du Colombier if(rflag) 1290bd389b36SDavid du Colombier while(n > 0) { 1291bd389b36SDavid du Colombier kp[-n] = ~kp[-n]; 1292bd389b36SDavid du Colombier n--; 1293bd389b36SDavid du Colombier } 1294bd389b36SDavid du Colombier } 1295bd389b36SDavid du Colombier 1296bd389b36SDavid du Colombier /* 1297bd389b36SDavid du Colombier * end of key 1298bd389b36SDavid du Colombier */ 1299bd389b36SDavid du Colombier k->klen = cl+1; 1300bd389b36SDavid du Colombier if(rflag) { 1301bd389b36SDavid du Colombier *kp = ~0; 1302bd389b36SDavid du Colombier return; 1303bd389b36SDavid du Colombier } 1304bd389b36SDavid du Colombier *kp = 0; 1305bd389b36SDavid du Colombier } 1306bd389b36SDavid du Colombier 1307bd389b36SDavid du Colombier void 1308bd389b36SDavid du Colombier dokey_r(Key *k, uchar *lp, uchar *lpe, Field *f) 1309bd389b36SDavid du Colombier { 1310bd389b36SDavid du Colombier int cl, n; 1311bd389b36SDavid du Colombier uchar *kp; 1312bd389b36SDavid du Colombier 1313bd389b36SDavid du Colombier USED(f); 1314bd389b36SDavid du Colombier n = lpe - lp; 1315bd389b36SDavid du Colombier if(n < 0) 1316bd389b36SDavid du Colombier n = 0; 1317bd389b36SDavid du Colombier cl = k->klen; 1318bd389b36SDavid du Colombier kp = k->key + cl; 1319bd389b36SDavid du Colombier k->klen = cl+n+1; 1320bd389b36SDavid du Colombier 1321bd389b36SDavid du Colombier lpe -= 3; 1322bd389b36SDavid du Colombier while(lp < lpe) { 1323bd389b36SDavid du Colombier kp[0] = ~lp[0]; 1324bd389b36SDavid du Colombier kp[1] = ~lp[1]; 1325bd389b36SDavid du Colombier kp[2] = ~lp[2]; 1326bd389b36SDavid du Colombier kp[3] = ~lp[3]; 1327bd389b36SDavid du Colombier kp += 4; 1328bd389b36SDavid du Colombier lp += 4; 1329bd389b36SDavid du Colombier } 1330bd389b36SDavid du Colombier 1331bd389b36SDavid du Colombier lpe += 3; 1332bd389b36SDavid du Colombier while(lp < lpe) 1333bd389b36SDavid du Colombier *kp++ = ~*lp++; 1334bd389b36SDavid du Colombier *kp = ~0; 1335bd389b36SDavid du Colombier } 1336bd389b36SDavid du Colombier 1337bd389b36SDavid du Colombier void 1338bd389b36SDavid du Colombier dokey_(Key *k, uchar *lp, uchar *lpe, Field *f) 1339bd389b36SDavid du Colombier { 1340bd389b36SDavid du Colombier int n, cl; 1341bd389b36SDavid du Colombier uchar *kp; 1342bd389b36SDavid du Colombier 1343bd389b36SDavid du Colombier USED(f); 1344bd389b36SDavid du Colombier n = lpe - lp; 1345bd389b36SDavid du Colombier if(n < 0) 1346bd389b36SDavid du Colombier n = 0; 1347bd389b36SDavid du Colombier cl = k->klen; 1348bd389b36SDavid du Colombier kp = k->key + cl; 1349bd389b36SDavid du Colombier k->klen = cl+n+1; 1350bd389b36SDavid du Colombier memmove(kp, lp, n); 1351bd389b36SDavid du Colombier kp[n] = 0; 1352bd389b36SDavid du Colombier } 1353bd389b36SDavid du Colombier 1354bd389b36SDavid du Colombier void 1355bd389b36SDavid du Colombier buildkey(Line *l) 1356bd389b36SDavid du Colombier { 1357bd389b36SDavid du Colombier Key *k; 1358bd389b36SDavid du Colombier uchar *lp, *lpe; 1359bd389b36SDavid du Colombier int ll, kl, cl, i, n; 1360bd389b36SDavid du Colombier Field *f; 1361bd389b36SDavid du Colombier 1362bd389b36SDavid du Colombier ll = l->llen - 1; 1363bd389b36SDavid du Colombier kl = 0; /* allocated length */ 1364bd389b36SDavid du Colombier cl = 0; /* current length */ 1365bd389b36SDavid du Colombier k = 0; 1366bd389b36SDavid du Colombier 1367bd389b36SDavid du Colombier for(i=1; i<=args.nfield; i++) { 1368bd389b36SDavid du Colombier f = &args.field[i]; 1369bd389b36SDavid du Colombier lp = skip(l->line, f->beg1, f->beg2, f->flags&B1flag, 0); 1370bd389b36SDavid du Colombier if(lp == 0) 1371bd389b36SDavid du Colombier lp = l->line + ll; 1372bd389b36SDavid du Colombier lpe = skip(l->line, f->end1, f->end2, f->flags&Bflag, 1); 1373bd389b36SDavid du Colombier if(lpe == 0) 1374bd389b36SDavid du Colombier lpe = l->line + ll; 1375bd389b36SDavid du Colombier n = (lpe - lp) + 1; 1376bd389b36SDavid du Colombier if(n <= 0) 1377bd389b36SDavid du Colombier n = 1; 1378bd389b36SDavid du Colombier if(cl+(n+4) > kl) { 1379bd389b36SDavid du Colombier kl = cl+(n+4); 1380bd389b36SDavid du Colombier k = realloc(k, sizeof(Key) + 1381bd389b36SDavid du Colombier (kl-1)*sizeof(k->key[0])); 1382bd389b36SDavid du Colombier if(k == 0) 1383bd389b36SDavid du Colombier nomem(); 1384bd389b36SDavid du Colombier } 1385bd389b36SDavid du Colombier k->klen = cl; 1386bd389b36SDavid du Colombier (*f->dokey)(k, lp, lpe, f); 1387bd389b36SDavid du Colombier cl = k->klen; 1388bd389b36SDavid du Colombier } 1389bd389b36SDavid du Colombier 1390bd389b36SDavid du Colombier /* 1391bd389b36SDavid du Colombier * global comparisons 1392bd389b36SDavid du Colombier */ 1393bd389b36SDavid du Colombier if(!(args.uflag && cl > 0)) { 1394bd389b36SDavid du Colombier f = &args.field[0]; 1395bd389b36SDavid du Colombier if(cl+(ll+4) > kl) { 1396bd389b36SDavid du Colombier kl = cl+(ll+4); 1397bd389b36SDavid du Colombier k = realloc(k, sizeof(Key) + 1398bd389b36SDavid du Colombier (kl-1)*sizeof(k->key[0])); 1399bd389b36SDavid du Colombier if(k == 0) 1400bd389b36SDavid du Colombier nomem(); 1401bd389b36SDavid du Colombier } 1402bd389b36SDavid du Colombier k->klen = cl; 1403bd389b36SDavid du Colombier (*f->dokey)(k, l->line, l->line+ll, f); 1404bd389b36SDavid du Colombier cl = k->klen; 1405bd389b36SDavid du Colombier } 1406bd389b36SDavid du Colombier 1407bd389b36SDavid du Colombier l->key = k; 1408bd389b36SDavid du Colombier k->klen = cl; 1409bd389b36SDavid du Colombier 1410bd389b36SDavid du Colombier if(args.vflag) { 1411bd389b36SDavid du Colombier fprint(2, "%.*s", l->llen, l->line); 1412bd389b36SDavid du Colombier for(i=0; i<k->klen; i++) { 1413bd389b36SDavid du Colombier fprint(2, " %.2x", k->key[i]); 1414bd389b36SDavid du Colombier if(k->key[i] == 0x00 || k->key[i] == 0xff) 1415bd389b36SDavid du Colombier fprint(2, "\n"); 1416bd389b36SDavid du Colombier } 1417bd389b36SDavid du Colombier } 1418bd389b36SDavid du Colombier } 1419bd389b36SDavid du Colombier 1420bd389b36SDavid du Colombier void 1421bd389b36SDavid du Colombier makemapm(Field *f) 1422bd389b36SDavid du Colombier { 1423bd389b36SDavid du Colombier int i, c; 1424bd389b36SDavid du Colombier 1425bd389b36SDavid du Colombier for(i=0; i<nelem(f->mapto); i++) { 1426bd389b36SDavid du Colombier c = 1; 1427bd389b36SDavid du Colombier if(i == ' ' || i == '\t') 1428bd389b36SDavid du Colombier c = 0; 1429bd389b36SDavid du Colombier if(i >= 'a' && i <= 'z') 1430bd389b36SDavid du Colombier c = i + ('A' - 'a'); 1431bd389b36SDavid du Colombier if(i >= 'A' && i <= 'Z') 1432bd389b36SDavid du Colombier c = i; 1433bd389b36SDavid du Colombier f->mapto[i] = c; 1434bd389b36SDavid du Colombier if(args.vflag) { 1435bd389b36SDavid du Colombier if((i & 15) == 0) 1436bd389b36SDavid du Colombier fprint(2, " "); 1437bd389b36SDavid du Colombier fprint(2, " %.2x", c); 1438bd389b36SDavid du Colombier if((i & 15) == 15) 1439bd389b36SDavid du Colombier fprint(2, "\n"); 1440bd389b36SDavid du Colombier } 1441bd389b36SDavid du Colombier } 1442bd389b36SDavid du Colombier } 1443bd389b36SDavid du Colombier 1444bd389b36SDavid du Colombier void 1445bd389b36SDavid du Colombier makemapd(Field *f) 1446bd389b36SDavid du Colombier { 1447bd389b36SDavid du Colombier int i, j, c; 1448bd389b36SDavid du Colombier 1449bd389b36SDavid du Colombier for(i=0; i<nelem(f->mapto); i++) { 1450bd389b36SDavid du Colombier c = i; 1451bd389b36SDavid du Colombier if(f->flags & Iflag) 1452bd389b36SDavid du Colombier if(c < 040 || c > 0176) 1453bd389b36SDavid du Colombier c = -1; 1454bd389b36SDavid du Colombier if((f->flags & Wflag) && c >= 0) 1455bd389b36SDavid du Colombier if(c == ' ' || c == '\t') 1456bd389b36SDavid du Colombier c = -1; 1457bd389b36SDavid du Colombier if((f->flags & Dflag) && c >= 0) 1458bd389b36SDavid du Colombier if(!(c == ' ' || c == '\t' || 1459bd389b36SDavid du Colombier (c >= 'a' && c <= 'z') || 1460bd389b36SDavid du Colombier (c >= 'A' && c <= 'Z') || 1461bd389b36SDavid du Colombier (c >= '0' && c <= '9'))) { 1462bd389b36SDavid du Colombier for(j=0; latinmap[j]; j+=3) 1463bd389b36SDavid du Colombier if(c == latinmap[j+0] || 1464bd389b36SDavid du Colombier c == latinmap[j+1]) 1465bd389b36SDavid du Colombier break; 1466bd389b36SDavid du Colombier if(latinmap[j] == 0) 1467bd389b36SDavid du Colombier c = -1; 1468bd389b36SDavid du Colombier } 1469bd389b36SDavid du Colombier if((f->flags & Fflag) && c >= 0) { 1470bd389b36SDavid du Colombier if(c >= 'a' && c <= 'z') 1471bd389b36SDavid du Colombier c += 'A' - 'a'; 1472bd389b36SDavid du Colombier for(j=0; latinmap[j]; j+=3) 1473bd389b36SDavid du Colombier if(c == latinmap[j+0] || 1474bd389b36SDavid du Colombier c == latinmap[j+1]) { 1475bd389b36SDavid du Colombier c = latinmap[j+2]; 1476bd389b36SDavid du Colombier break; 1477bd389b36SDavid du Colombier } 1478bd389b36SDavid du Colombier } 1479bd389b36SDavid du Colombier if((f->flags & Rflag) && c >= 0 && i > 0 && i < Runeself) 1480bd389b36SDavid du Colombier c = ~c & 0xff; 1481bd389b36SDavid du Colombier if(c < 0) 1482bd389b36SDavid du Colombier c = 0; 1483bd389b36SDavid du Colombier f->mapto[i] = c; 1484bd389b36SDavid du Colombier if(args.vflag) { 1485bd389b36SDavid du Colombier if((i & 15) == 0) 1486bd389b36SDavid du Colombier fprint(2, " "); 1487bd389b36SDavid du Colombier fprint(2, " %.2x", c); 1488bd389b36SDavid du Colombier if((i & 15) == 15) 1489bd389b36SDavid du Colombier fprint(2, "\n"); 1490bd389b36SDavid du Colombier } 1491bd389b36SDavid du Colombier } 1492bd389b36SDavid du Colombier } 1493bd389b36SDavid du Colombier 1494bd389b36SDavid du Colombier int latinmap[] = 1495bd389b36SDavid du Colombier { 1496bd389b36SDavid du Colombier /* lcase ucase fold */ 1497bd389b36SDavid du Colombier L'à', L'À', L'A', 1498bd389b36SDavid du Colombier L'á', L'Á', L'A', 1499bd389b36SDavid du Colombier L'â', L'Â', L'A', 1500bd389b36SDavid du Colombier L'ä', L'Ä', L'A', 1501bd389b36SDavid du Colombier L'ã', L'Ã', L'A', 1502bd389b36SDavid du Colombier L'å', L'Å', L'A', 1503bd389b36SDavid du Colombier L'è', L'È', L'E', 1504bd389b36SDavid du Colombier L'é', L'É', L'E', 1505bd389b36SDavid du Colombier L'ê', L'Ê', L'E', 1506bd389b36SDavid du Colombier L'ë', L'Ë', L'E', 1507bd389b36SDavid du Colombier L'ì', L'Ì', L'I', 1508bd389b36SDavid du Colombier L'í', L'Í', L'I', 1509bd389b36SDavid du Colombier L'î', L'Î', L'I', 1510bd389b36SDavid du Colombier L'ï', L'Ï', L'I', 1511bd389b36SDavid du Colombier L'ò', L'Ò', L'O', 1512bd389b36SDavid du Colombier L'ó', L'Ó', L'O', 1513bd389b36SDavid du Colombier L'ô', L'Ô', L'O', 1514bd389b36SDavid du Colombier L'ö', L'Ö', L'O', 1515bd389b36SDavid du Colombier L'õ', L'Õ', L'O', 1516bd389b36SDavid du Colombier L'ø', L'Ø', L'O', 1517bd389b36SDavid du Colombier L'ù', L'Ù', L'U', 1518bd389b36SDavid du Colombier L'ú', L'Ú', L'U', 1519bd389b36SDavid du Colombier L'û', L'Û', L'U', 1520bd389b36SDavid du Colombier L'ü', L'Ü', L'U', 1521bd389b36SDavid du Colombier L'æ', L'Æ', L'A', 1522bd389b36SDavid du Colombier L'ð', L'Ð', L'D', 1523bd389b36SDavid du Colombier L'ñ', L'Ñ', L'N', 1524bd389b36SDavid du Colombier L'ý', L'Ý', L'Y', 1525bd389b36SDavid du Colombier L'ç', L'Ç', L'C', 1526bd389b36SDavid du Colombier 0, 1527bd389b36SDavid du Colombier }; 1528bd389b36SDavid du Colombier 1529bd389b36SDavid du Colombier Rune* month[12] = 1530bd389b36SDavid du Colombier { 1531bd389b36SDavid du Colombier L"JAN", 1532bd389b36SDavid du Colombier L"FEB", 1533bd389b36SDavid du Colombier L"MAR", 1534bd389b36SDavid du Colombier L"APR", 1535bd389b36SDavid du Colombier L"MAY", 1536bd389b36SDavid du Colombier L"JUN", 1537bd389b36SDavid du Colombier L"JUL", 1538bd389b36SDavid du Colombier L"AUG", 1539bd389b36SDavid du Colombier L"SEP", 1540bd389b36SDavid du Colombier L"OCT", 1541bd389b36SDavid du Colombier L"NOV", 1542bd389b36SDavid du Colombier L"DEC", 1543bd389b36SDavid du Colombier }; 1544bd389b36SDavid du Colombier 1545bd389b36SDavid du Colombier /************** radix sort ***********/ 1546bd389b36SDavid du Colombier 1547bd389b36SDavid du Colombier enum 1548bd389b36SDavid du Colombier { 1549bd389b36SDavid du Colombier Threshold = 14, 1550bd389b36SDavid du Colombier }; 1551bd389b36SDavid du Colombier 1552bd389b36SDavid du Colombier void rsort4(Key***, ulong, int); 1553bd389b36SDavid du Colombier void bsort4(Key***, ulong, int); 1554bd389b36SDavid du Colombier 1555bd389b36SDavid du Colombier void 1556bd389b36SDavid du Colombier sort4(void *a, ulong n) 1557bd389b36SDavid du Colombier { 1558bd389b36SDavid du Colombier if(n > Threshold) 1559bd389b36SDavid du Colombier rsort4((Key***)a, n, 0); 1560bd389b36SDavid du Colombier else 1561bd389b36SDavid du Colombier bsort4((Key***)a, n, 0); 1562bd389b36SDavid du Colombier } 1563bd389b36SDavid du Colombier 1564bd389b36SDavid du Colombier void 1565bd389b36SDavid du Colombier rsort4(Key ***a, ulong n, int b) 1566bd389b36SDavid du Colombier { 1567bd389b36SDavid du Colombier Key ***ea, ***t, ***u, **t1, **u1, *k; 1568bd389b36SDavid du Colombier Key ***part[257]; 1569bd389b36SDavid du Colombier static long count[257]; 1570bd389b36SDavid du Colombier long clist[257+257], *cp, *cp1; 1571bd389b36SDavid du Colombier int c, lowc, higc; 1572bd389b36SDavid du Colombier 1573bd389b36SDavid du Colombier /* 1574bd389b36SDavid du Colombier * pass 1 over all keys, 1575bd389b36SDavid du Colombier * count the number of each key[b]. 1576bd389b36SDavid du Colombier * find low count and high count. 1577bd389b36SDavid du Colombier */ 1578bd389b36SDavid du Colombier lowc = 256; 1579bd389b36SDavid du Colombier higc = 0; 1580bd389b36SDavid du Colombier ea = a+n; 1581bd389b36SDavid du Colombier for(t=a; t<ea; t++) { 1582bd389b36SDavid du Colombier k = **t; 1583bd389b36SDavid du Colombier n = k->klen; 1584bd389b36SDavid du Colombier if(b >= n) { 1585bd389b36SDavid du Colombier count[256]++; 1586bd389b36SDavid du Colombier continue; 1587bd389b36SDavid du Colombier } 1588bd389b36SDavid du Colombier c = k->key[b]; 1589bd389b36SDavid du Colombier n = count[c]++; 1590bd389b36SDavid du Colombier if(n == 0) { 1591bd389b36SDavid du Colombier if(c < lowc) 1592bd389b36SDavid du Colombier lowc = c; 1593bd389b36SDavid du Colombier if(c > higc) 1594bd389b36SDavid du Colombier higc = c; 1595bd389b36SDavid du Colombier } 1596bd389b36SDavid du Colombier } 1597bd389b36SDavid du Colombier 1598bd389b36SDavid du Colombier /* 1599bd389b36SDavid du Colombier * pass 2 over all counts, 1600bd389b36SDavid du Colombier * put partition pointers in part[c]. 1601bd389b36SDavid du Colombier * save compacted indexes and counts 1602bd389b36SDavid du Colombier * in clist[]. 1603bd389b36SDavid du Colombier */ 1604bd389b36SDavid du Colombier t = a; 1605bd389b36SDavid du Colombier n = count[256]; 1606bd389b36SDavid du Colombier clist[0] = n; 1607bd389b36SDavid du Colombier part[256] = t; 1608bd389b36SDavid du Colombier t += n; 1609bd389b36SDavid du Colombier 1610bd389b36SDavid du Colombier cp1 = clist+1; 1611bd389b36SDavid du Colombier cp = count+lowc; 1612bd389b36SDavid du Colombier for(c=lowc; c<=higc; c++,cp++) { 1613bd389b36SDavid du Colombier n = *cp; 1614bd389b36SDavid du Colombier if(n) { 1615bd389b36SDavid du Colombier cp1[0] = n; 1616bd389b36SDavid du Colombier cp1[1] = c; 1617bd389b36SDavid du Colombier cp1 += 2; 1618bd389b36SDavid du Colombier part[c] = t; 1619bd389b36SDavid du Colombier t += n; 1620bd389b36SDavid du Colombier } 1621bd389b36SDavid du Colombier } 1622bd389b36SDavid du Colombier *cp1 = 0; 1623bd389b36SDavid du Colombier 1624bd389b36SDavid du Colombier /* 1625bd389b36SDavid du Colombier * pass 3 over all counts. 1626bd389b36SDavid du Colombier * chase lowest pointer in each partition 1627bd389b36SDavid du Colombier * around a permutation until it comes 1628bd389b36SDavid du Colombier * back and is stored where it started. 1629bd389b36SDavid du Colombier * static array, count[], should be 1630bd389b36SDavid du Colombier * reduced to zero entries except maybe 1631bd389b36SDavid du Colombier * count[256]. 1632bd389b36SDavid du Colombier */ 1633bd389b36SDavid du Colombier for(cp1=clist+1; cp1[0]; cp1+=2) { 1634bd389b36SDavid du Colombier c = cp1[1]; 1635bd389b36SDavid du Colombier cp = count+c; 1636bd389b36SDavid du Colombier while(*cp) { 1637bd389b36SDavid du Colombier t1 = *part[c]; 1638bd389b36SDavid du Colombier for(;;) { 1639bd389b36SDavid du Colombier k = *t1; 1640bd389b36SDavid du Colombier n = 256; 1641bd389b36SDavid du Colombier if(b < k->klen) 1642bd389b36SDavid du Colombier n = k->key[b]; 1643bd389b36SDavid du Colombier u = part[n]++; 1644bd389b36SDavid du Colombier count[n]--; 1645bd389b36SDavid du Colombier u1 = *u; 1646bd389b36SDavid du Colombier *u = t1; 1647bd389b36SDavid du Colombier if(n == c) 1648bd389b36SDavid du Colombier break; 1649bd389b36SDavid du Colombier t1 = u1; 1650bd389b36SDavid du Colombier } 1651bd389b36SDavid du Colombier } 1652bd389b36SDavid du Colombier } 1653bd389b36SDavid du Colombier 1654bd389b36SDavid du Colombier /* 1655bd389b36SDavid du Colombier * pass 4 over all partitions. 1656bd389b36SDavid du Colombier * call recursively. 1657bd389b36SDavid du Colombier */ 1658bd389b36SDavid du Colombier b++; 1659bd389b36SDavid du Colombier t = a + clist[0]; 1660bd389b36SDavid du Colombier count[256] = 0; 1661bd389b36SDavid du Colombier for(cp1=clist+1; n=cp1[0]; cp1+=2) { 1662bd389b36SDavid du Colombier if(n > Threshold) 1663bd389b36SDavid du Colombier rsort4(t, n, b); 1664bd389b36SDavid du Colombier else 1665bd389b36SDavid du Colombier if(n > 1) 1666bd389b36SDavid du Colombier bsort4(t, n, b); 1667bd389b36SDavid du Colombier t += n; 1668bd389b36SDavid du Colombier } 1669bd389b36SDavid du Colombier } 1670bd389b36SDavid du Colombier 1671bd389b36SDavid du Colombier /* 1672bd389b36SDavid du Colombier * bubble sort to pick up 1673bd389b36SDavid du Colombier * the pieces. 1674bd389b36SDavid du Colombier */ 1675bd389b36SDavid du Colombier void 1676bd389b36SDavid du Colombier bsort4(Key ***a, ulong n, int b) 1677bd389b36SDavid du Colombier { 1678bd389b36SDavid du Colombier Key ***i, ***j, ***k, ***l, **t; 1679bd389b36SDavid du Colombier Key *ka, *kb; 1680bd389b36SDavid du Colombier int n1, n2; 1681bd389b36SDavid du Colombier 1682bd389b36SDavid du Colombier l = a+n; 1683bd389b36SDavid du Colombier j = a; 1684bd389b36SDavid du Colombier 1685bd389b36SDavid du Colombier loop: 1686bd389b36SDavid du Colombier i = j; 1687bd389b36SDavid du Colombier j++; 1688bd389b36SDavid du Colombier if(j >= l) 1689bd389b36SDavid du Colombier return; 1690bd389b36SDavid du Colombier 1691bd389b36SDavid du Colombier ka = **i; 1692bd389b36SDavid du Colombier kb = **j; 1693bd389b36SDavid du Colombier n1 = ka->klen - b; 1694bd389b36SDavid du Colombier n2 = kb->klen - b; 1695bd389b36SDavid du Colombier if(n1 > n2) 1696bd389b36SDavid du Colombier n1 = n2; 1697bd389b36SDavid du Colombier if(n1 <= 0) 1698bd389b36SDavid du Colombier goto loop; 1699bd389b36SDavid du Colombier n2 = ka->key[b] - kb->key[b]; 1700bd389b36SDavid du Colombier if(n2 == 0) 1701bd389b36SDavid du Colombier n2 = memcmp(ka->key+b, kb->key+b, n1); 1702bd389b36SDavid du Colombier if(n2 <= 0) 1703bd389b36SDavid du Colombier goto loop; 1704bd389b36SDavid du Colombier 1705bd389b36SDavid du Colombier for(;;) { 1706bd389b36SDavid du Colombier k = i+1; 1707bd389b36SDavid du Colombier 1708bd389b36SDavid du Colombier t = *k; 1709bd389b36SDavid du Colombier *k = *i; 1710bd389b36SDavid du Colombier *i = t; 1711bd389b36SDavid du Colombier 1712bd389b36SDavid du Colombier if(i <= a) 1713bd389b36SDavid du Colombier goto loop; 1714bd389b36SDavid du Colombier 1715bd389b36SDavid du Colombier i--; 1716bd389b36SDavid du Colombier ka = **i; 1717bd389b36SDavid du Colombier kb = *t; 1718bd389b36SDavid du Colombier n1 = ka->klen - b; 1719bd389b36SDavid du Colombier n2 = kb->klen - b; 1720bd389b36SDavid du Colombier if(n1 > n2) 1721bd389b36SDavid du Colombier n1 = n2; 1722bd389b36SDavid du Colombier if(n1 <= 0) 1723bd389b36SDavid du Colombier goto loop; 1724bd389b36SDavid du Colombier n2 = ka->key[b] - kb->key[b]; 1725bd389b36SDavid du Colombier if(n2 == 0) 1726bd389b36SDavid du Colombier n2 = memcmp(ka->key+b, kb->key+b, n1); 1727bd389b36SDavid du Colombier if(n2 <= 0) 1728bd389b36SDavid du Colombier goto loop; 1729bd389b36SDavid du Colombier } 1730bd389b36SDavid du Colombier } 1731