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