|
|
1.1 root 1: /*
2: * split -- break up a file on specified boundaries
3: *
4: * status returns:
5: * 0 - ok, and some matches
6: * 1 - ok, but no matches
7: * 2 - some error
8: */
9:
10: #include <stdio.h>
11: #include <ctype.h>
12: #include <sys/param.h>
13:
14: #define CBRA 1
15: #define CCHR 2
16: #define CDOT 4
17: #define CCL 6
18: #define NCCL 8
19: #define CDOL 10
20: #define CEOF 11
21: #define CKET 12
22: #define CBACK 18
23:
24: #define STAR 01
25:
26: #define LBSIZE 512
27: #define ESIZE 256
28: #define NBRA 9
29:
30: char bracket[NBRA];
31: char numbra;
32: char nbra;
33: char linebuf[LBSIZE+1];
34: char filebuf[LBSIZE+1];
35: char ybuf[ESIZE];
36: char *fflag="x";
37: char *sflag="";
38: unsigned nfile;
39: unsigned nline;
40: int nflag=1000;
41: int xflag;
42: int yflag;
43: int retcode = 0;
44: int circf;
45: int nsucc;
46: char *braslist[NBRA];
47: char *braelist[NBRA];
48: char bittab[] = {
49: 1,
50: 2,
51: 4,
52: 8,
53: 16,
54: 32,
55: 64,
56: 128
57: };
58: struct exp{
59: char expbuf[ESIZE];
60: struct exp *next;
61: }*firstexp, *lastexp, *expp, *malloc();
62:
63: main(argc, argv)
64: char **argv;
65: {
66: while (--argc > 0 && (++argv)[0][0]=='-')
67: switch (argv[0][1]) {
68: case '1': case '2': case '3': case '4': case '5':
69: case '6': case '7': case '8': case '9':
70: nflag=atoi(&argv[0][1]);
71: if(nflag<=0)
72: errexit("split: invalid numeric interval %s\n", argv[0]);
73: continue;
74:
75: case 'f':
76: --argc; ++argv;
77: if(argc<=0)
78: errexit("split: too few args for -f\n", (char *)NULL);
79: fflag= *argv;
80: if(fflag[0]=='\0')
81: errexit("split: null file name specified for -f\n", (char *)NULL);
82: continue;
83:
84: case 's':
85: --argc; ++argv;
86: if(argc<=0)
87: errexit("split: too few args for -s\n", (char *)NULL);
88: sflag= *argv;
89: continue;
90:
91: case 'x':
92: xflag++;
93: continue;
94:
95: case 'y':
96: yflag++;
97: continue;
98:
99: case 'e':
100: --argc;
101: ++argv;
102: if(*argv==0 || **argv=='\0')
103: errexit("split: null expression for -e\n", (char *)NULL);
104: if (yflag) {
105: register char *p, *s;
106: for (s = ybuf, p = *argv; *p; ) {
107: if (*p == '\\') {
108: *s++ = *p++;
109: if (*p)
110: *s++ = *p++;
111: } else if (*p == '[') {
112: while (*p != '\0' && *p != ']')
113: *s++ = *p++;
114: } else if (islower(*p)) {
115: *s++ = '[';
116: *s++ = toupper(*p);
117: *s++ = *p++;
118: *s++ = ']';
119: } else
120: *s++ = *p++;
121: if (s >= ybuf+ESIZE-5)
122: errexit("split: argument too long\n", (char *)NULL);
123: }
124: *s = '\0';
125: *argv = ybuf;
126: }
127: compile(*argv);
128: nflag=0;
129: continue;
130:
131: default:
132: errexit("split: unknown flag\n", (char *)NULL);
133: continue;
134: }
135: if(nflag)
136: succeed(1); /* Create first file */
137: if (argc<=0)
138: execute((char *)NULL);
139: else
140: execute(*argv);
141: return (retcode != 0 ? retcode : nsucc == 0);
142: }
143:
144: compile(astr)
145: char *astr;
146: {
147: register c;
148: register char *ep, *sp;
149: char *cstart;
150: char *lastep;
151: char *bracketp;
152: int cclcnt;
153: int closed;
154: char neg;
155:
156: expp=malloc(sizeof *expp);
157: if(expp==NULL)
158: errexit("split: too many expressions; can't malloc\n", (char *)NULL);
159: if(firstexp==0) {
160: firstexp=expp;
161: lastexp=expp;
162: } else {
163: lastexp->next = expp;
164: lastexp = expp;
165: }
166: expp->next=0;
167: ep = expp->expbuf;
168: sp = astr;
169: lastep = 0;
170: bracketp = bracket;
171: closed = numbra = 0;
172: if (*sp == '^') {
173: circf++;
174: sp++;
175: }
176: for (;;) {
177: if (ep >= &expp->expbuf[ESIZE])
178: goto cerror;
179: if ((c = *sp++) != '*')
180: lastep = ep;
181: switch (c) {
182:
183: case '\0':
184: *ep++ = CEOF;
185: if(expp==firstexp)
186: nbra=numbra;
187: else if(nbra!=numbra)
188: errexit("split: inconsistent parentheses in expression %s\n", astr);
189: return;
190:
191: case '.':
192: *ep++ = CDOT;
193: continue;
194:
195: case '*':
196: if (lastep==0 || *lastep==CBRA || *lastep==CKET)
197: goto defchar;
198: *lastep |= STAR;
199: continue;
200:
201: case '$':
202: if (*sp != '\0')
203: goto defchar;
204: *ep++ = CDOL;
205: continue;
206:
207: case '[':
208: if(&ep[17] >= &expp->expbuf[ESIZE])
209: goto cerror;
210: *ep++ = CCL;
211: neg = 0;
212: if((c = *sp++) == '^') {
213: neg = 1;
214: c = *sp++;
215: }
216: cstart = sp;
217: do {
218: if (c=='\0')
219: goto cerror;
220: if (c=='-' && sp>cstart && *sp!=']') {
221: for (c = sp[-2]; c<*sp; c++)
222: ep[c>>3] |= bittab[c&07];
223: sp++;
224: }
225: ep[c>>3] |= bittab[c&07];
226: } while((c = *sp++) != ']');
227: if(neg) {
228: for(cclcnt = 0; cclcnt < 16; cclcnt++)
229: ep[cclcnt] ^= -1;
230: ep[0] &= 0376;
231: }
232:
233: ep += 16;
234:
235: continue;
236:
237: case '\\':
238: if((c = *sp++) == '(') {
239: if(numbra >= NBRA) {
240: goto cerror;
241: }
242: *bracketp++ = numbra;
243: *ep++ = CBRA;
244: *ep++ = numbra++;
245: continue;
246: }
247: if(c == ')') {
248: if(bracketp <= bracket) {
249: goto cerror;
250: }
251: *ep++ = CKET;
252: *ep++ = *--bracketp;
253: closed++;
254: continue;
255: }
256:
257: if(c >= '1' && c <= '9') {
258: if((c -= '1') >= closed)
259: goto cerror;
260: *ep++ = CBACK;
261: *ep++ = c;
262: continue;
263: }
264:
265: defchar:
266: default:
267: *ep++ = CCHR;
268: *ep++ = c;
269: }
270: }
271: cerror:
272: errexit("split: RE error\n", (char *)NULL);
273: }
274:
275: execute(file)
276: char *file;
277: {
278: register char *p1, *p2;
279: register c;
280:
281: if (file) {
282: if (freopen(file, "r", stdin) == NULL) {
283: fprintf(stderr, "split: can't open %s\n", file);
284: retcode = 2;
285: return;
286: }
287: }
288: expp=firstexp;
289: for (;;) {
290: p1 = linebuf;
291: if(expp==firstexp){
292: while ((c = getchar()) != '\n') {
293: if (c == EOF)
294: return;
295: *p1++ = c;
296: if (p1 >= &linebuf[LBSIZE-2])
297: break;
298: }
299: *p1++ = '\0';
300: p1 = linebuf;
301: if(nflag){
302: printf("%s\n", linebuf);
303: if(++nline>=nflag){
304: succeed(1);
305: nline=0;
306: }
307: continue;
308: }
309: }
310: p2 = expp->expbuf;
311: if (circf) {
312: if (advance(p1, p2))
313: goto found;
314: goto nfound;
315: }
316: /* fast check for first character */
317: if (*p2==CCHR) {
318: c = p2[1];
319: do {
320: if (*p1!=c)
321: continue;
322: if (advance(p1, p2))
323: goto found;
324: } while (*p1++);
325: goto nfound;
326: }
327: /* regular algorithm */
328: do {
329: if (advance(p1, p2))
330: goto found;
331: } while (*p1++);
332: nfound:
333: if((expp=expp->next)==0){
334: expp=firstexp;
335: printf("%s\n", linebuf);
336: }
337: continue;
338: found:
339: succeed(xflag);
340: expp=firstexp;
341: }
342: }
343:
344: advance(lp, ep)
345: register char *lp, *ep;
346: {
347: register char *curlp;
348: char c;
349: char *bbeg;
350: int ct;
351:
352: for (;;) switch (*ep++) {
353:
354: case CCHR:
355: if (*ep++ == *lp++)
356: continue;
357: return(0);
358:
359: case CDOT:
360: if (*lp++)
361: continue;
362: return(0);
363:
364: case CDOL:
365: if (*lp==0)
366: continue;
367: return(0);
368:
369: case CEOF:
370: return(1);
371:
372: case CCL:
373: c = *lp++ & 0177;
374: if(ep[c>>3] & bittab[c & 07]) {
375: ep += 16;
376: continue;
377: }
378: return(0);
379: case CBRA:
380: braslist[*ep++] = lp;
381: continue;
382:
383: case CKET:
384: braelist[*ep++] = lp;
385: continue;
386:
387: case CBACK:
388: bbeg = braslist[*ep];
389: if (braelist[*ep]==0)
390: return(0);
391: ct = braelist[*ep++] - bbeg;
392: if(ecmp(bbeg, lp, ct)) {
393: lp += ct;
394: continue;
395: }
396: return(0);
397:
398: case CBACK|STAR:
399: bbeg = braslist[*ep];
400: if (braelist[*ep]==0)
401: return(0);
402: ct = braelist[*ep++] - bbeg;
403: curlp = lp;
404: while(ecmp(bbeg, lp, ct))
405: lp += ct;
406: while(lp >= curlp) {
407: if(advance(lp, ep)) return(1);
408: lp -= ct;
409: }
410: return(0);
411:
412:
413: case CDOT|STAR:
414: curlp = lp;
415: while (*lp++);
416: goto star;
417:
418: case CCHR|STAR:
419: curlp = lp;
420: while (*lp++ == *ep);
421: ep++;
422: goto star;
423:
424: case CCL|STAR:
425: curlp = lp;
426: do {
427: c = *lp++ & 0177;
428: } while(ep[c>>3] & bittab[c & 07]);
429: ep += 16;
430: goto star;
431:
432: star:
433: if(--lp == curlp) {
434: continue;
435: }
436:
437: if(*ep == CCHR) {
438: c = ep[1];
439: do {
440: if(*lp != c)
441: continue;
442: if(advance(lp, ep))
443: return(1);
444: } while(lp-- > curlp);
445: return(0);
446: }
447:
448: do {
449: if (advance(lp, ep))
450: return(1);
451: } while (lp-- > curlp);
452: return(0);
453:
454: default:
455: errexit("split RE botch\n", (char *)NULL);
456: }
457: }
458:
459: char *
460: suffix()
461: {
462: static char s[3];
463: if(nfile>26*26)
464: errexit("split: too many files (max 26*26)\n", (char *)NULL);
465: s[0]='a'+nfile/26;
466: s[1]='a'+nfile%26;
467: s[2]='\0';
468: nfile++;
469: return(s);
470: }
471:
472: char *
473: filename()
474: {
475: extern char *strcat(), *strcpy();
476: if(numbra==0)
477: return(strcat(strcpy(filebuf, fflag), suffix()));
478: if(braslist[0]>=braelist[0])
479: errexit("split: null file name match; line:\n%s\n", linebuf);
480: (void) strncpy(filebuf, braslist[0], braelist[0]-braslist[0]);
481: if(yflag)
482: lowercase(filebuf);
483: (void) strcpy(&filebuf[braelist[0]-braslist[0]], sflag);
484: return(filebuf);
485: }
486:
487: lowercase(s)
488: register char *s;
489: {
490: do
491: if(isupper(*s))
492: *s=tolower(*s);
493: while(*s++);
494: }
495:
496: succeed(xflag)
497: {
498: long ftell();
499: nsucc = 1;
500: if(freopen(filename(), "w", stdout)==NULL)
501: errexit("split: can't open %s\n", filebuf);
502: if(!xflag)
503: printf("%s\n", linebuf);
504: }
505:
506: ecmp(a, b, count)
507: char *a, *b;
508: {
509: register cc = count;
510: while(cc--)
511: if(*a++ != *b++) return(0);
512: return(1);
513: }
514:
515: errexit(s, f)
516: char *s, *f;
517: {
518: fprintf(stderr, s, f);
519: exit(2);
520: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.