|
|
1.1 root 1: /* cpgrep
2: *
3: * HISTORY:
4: * 23-Mar-87 danl exit(x) -> DOSEXIT(1, x)
5: *
6: */
7:
8: #include <stdio.h>
9: #include <fcntl.h>
10: #include <ctype.h>
11:
12: int far pascal DOSCREATETHREAD(void (far *)(),int far *,int far *);
13: int far pascal DOSGETMACHINEMODE(char far *);
14: int far pascal DOSQHANDTYPE(int,int far *,int far *);
15: int far pascal DOSREAD(int,char far *,int,int far *);
16: int far pascal DOSSEMCLEAR(long far *);
17: int far pascal DOSSEMREQUEST(long far *,long);
18: int far pascal DOSSEMSET(long far *);
19: int far pascal DOSSEMWAIT(long far *,long);
20: int far pascal DOSSLEEP(long);
21: int far pascal DOSWRITE(int,char far *,int,int far *);
22: int far pascal DOSEXIT(int, int);
23:
24: #define BEGLINE 0x40
25: #define DEBUG 0x08
26: #define ENDLINE 0x80
27: #define FILBUFLEN (SECTORLEN*30)
28: #define FILNAMLEN 80
29: #define INVERT 0x10
30: #define ISCOT 0x0002
31: #define LG2SECLEN 9
32: #define LINELEN 128
33: #define LINENOS 0x04
34: #define LNOLEN 8
35: #define MAXSTRLEN 128
36: #define NAMEONLY 0x02
37: #define OUTBUFLEN (SECTORLEN*4)
38: #define SECTORLEN (1 << LG2SECLEN)
39: #define SHOWNAME 0x01
40: #define STKLEN 256
41: #define TIMER 0x20
42: #define TRTABLEN 256
43: #define s_text(x) (((char *)(x)) - ((x)->s_must))
44:
45: typedef struct stringnode
46: {
47: struct stringnode *s_alt; /* List of alternates */
48: struct stringnode *s_suf; /* List of suffixes */
49: int s_must; /* Length of portion that must match */
50: }
51: STRINGNODE;
52:
53: char filbuf[(FILBUFLEN + 2)*2];
54: char *bufptr[] = { filbuf, filbuf + FILBUFLEN + 2 };
55: char outbuf[OUTBUFLEN*2];
56: char *obuf[] = { outbuf, outbuf + OUTBUFLEN };
57: char *optr[] = { outbuf, outbuf + OUTBUFLEN };
58: int ocnt[] = { OUTBUFLEN, OUTBUFLEN };
59: int oi = 0;
60: char transtab[TRTABLEN] = { 0 };
61: STRINGNODE *stringlist[TRTABLEN/2];
62: int arrc; /* I/O return code for DOSREAD */
63: int awrc; /* I/O return code for DOSWRITE */
64: int casesen = 1; /* Assume case-sensitivity */
65: int cbread; /* Bytes read by DOSREAD */
66: int cbwrite; /* Bytes written by DOSWRITE */
67: int clists = 1; /* One is first available index */
68: int flags; /* Flags */
69: int lineno; /* Current line number */
70: char pmode; /* Protected mode flag */
71: long readdone; /* Async read done semaphore */
72: long readpending; /* Async read pending semaphore */
73: int status = 1; /* Assume failure */
74: char *t2buf; /* Async read buffer */
75: int t2buflen; /* Async read buffer length */
76: int t2fd; /* Async read file */
77: char *t3buf; /* Async write buffer */
78: int t3buflen; /* Async write buffer length */
79: int t3fd; /* Async write file */
80: long writedone; /* Async write done semaphore */
81: long writepending; /* Async write pending semaphore */
82: char target[MAXSTRLEN];
83: /* Last string added */
84: int targetlen; /* Length of last string added */
85:
86: int countlines(); /* See CPGREPSB.ASM */
87: int countmatched(); /* See CPGREPSB.ASM */
88: char *findlist(); /* See CPGREPSB.ASM */
89: char *findone(); /* See CPGREPSB.ASM */
90: void flush1buf(); /* See below */
91: int grepbuffer(); /* See below */
92: int revfind(); /* See CPGREPSB.ASM */
93: void write1buf(); /* See below */
94: char *(*find)() = findlist;
95: void (*flush1)() = flush1buf;
96: int (*grep)() = grepbuffer;
97: void (*write1)() = write1buf;
98:
99: void freenode(x)
100: register STRINGNODE *x; /* Pointer to node to free */
101: {
102: register STRINGNODE *y; /* Pointer to next node in list */
103:
104: while(x != NULL) /* While not at end of list */
105: {
106: if(x->s_suf != NULL) freenode(x->s_suf);
107: /* Free suffix list */
108: y = x; /* Save pointer */
109: x = x->s_alt; /* Move down the list */
110: free(y); /* Free the node */
111: }
112: }
113:
114:
115: STRINGNODE *newnode(s,n)
116: char *s; /* String */
117: int n; /* Length of string */
118: {
119: register STRINGNODE *new; /* Pointer to new node */
120: char *t; /* String pointer */
121: char *malloc(); /* Storage allocator */
122:
123: if((t = malloc(sizeof(STRINGNODE) + n + (n & 1))) == NULL)
124: { /* If allocation fails */
125: fprintf(stderr,"Out of memory\n");
126: DOSEXIT(1, 2); /* Print error message and die */
127: }
128: if(n & 1) ++t; /* END of string word-aligned */
129: strncpy(t,s,n); /* Copy string text */
130: new = (STRINGNODE *)(t + n); /* Set pointer to node */
131: new->s_alt = NULL; /* No alternates yet */
132: new->s_suf = NULL; /* No suffixes yet */
133: new->s_must = n; /* Set string length */
134: return(new); /* Return pointer to new node */
135: }
136:
137:
138: void reallocnode(node,s,n)
139: register STRINGNODE *node; /* Pointer to node */
140: char *s; /* String */
141: register int n; /* Length of string */
142: {
143: if(n > node->s_must) /* If node must grow */
144: {
145: fprintf(stderr,"Internal error\n");
146: /* Error message */
147: DOSEXIT(1, 2); /* Error exit */
148: }
149: node->s_must = n; /* Set new length */
150: memcpy(s_text(node),s,n); /* Copy new text */
151: }
152:
153:
154: void addstring(s,n)
155: char *s; /* String to add */
156: int n; /* Length of string */
157: {
158: register STRINGNODE *cur; /* Current string */
159: register STRINGNODE **pprev; /* Pointer to previous link */
160: STRINGNODE *new; /* New string */
161: int i; /* Index */
162: int j; /* Count */
163: int k; /* Count */
164:
165: if(n <= 0 || n > 127) return; /* Should never happen */
166: i = transtab[*s]; /* Get current index */
167: if(i == 0) /* If no existing list */
168: {
169: /*
170: * We have to start a new list
171: */
172: if((i = clists++) >= TRTABLEN/2)
173: { /* If too many string lists */
174: fprintf(stderr,"Too many string lists\n");
175: /* Error message */
176: DOSEXIT(1, 2); /* Die */
177: }
178: stringlist[i] = NULL; /* Initialize */
179: transtab[*s] = i; /* Set pointer to new list */
180: if(!casesen && isalpha(*s)) transtab[*s ^ '\x20'] = i;
181: /* Set pointer for other case */
182: }
183: else if(stringlist[i] == NULL) return;
184: /* Check for existing 1-byte string */
185: if(--n == 0) /* If 1-byte string */
186: {
187: freenode(stringlist[i]); /* Free any existing stuff */
188: stringlist[i] = NULL; /* No record here */
189: return; /* Done */
190: }
191: ++s; /* Skip first char */
192: pprev = stringlist + i; /* Get pointer to link */
193: cur = *pprev; /* Get pointer to node */
194: while(cur != NULL) /* Loop to traverse match tree */
195: {
196: i = (n > cur->s_must)? cur->s_must: n;
197: /* Find minimum of string lengths */
198: matchstrings(s,s_text(cur),i,&j,&k);
199: /* Compare the strings */
200: if(j == 0) /* If complete mismatch */
201: {
202: if(k < 0) break; /* Break if insertion point found */
203: pprev = &(cur->s_alt); /* Get pointer to alternate link */
204: cur = *pprev; /* Follow the link */
205: }
206: else if(i == j) /* Else if strings matched */
207: {
208: if(i == n) /* If new is prefix of current */
209: {
210: reallocnode(cur,s_text(cur),n);
211: /* Shorten text of node */
212: if(cur->s_suf != NULL) /* If there are suffixes */
213: {
214: freenode(cur->s_suf);
215: /* Suffixes no longer needed */
216: cur->s_suf = NULL;
217: }
218: return; /* All done */
219: }
220: pprev = &(cur->s_suf); /* Get pointer to suffix link */
221: if((cur = *pprev) == NULL) return;
222: /* Done if current is prefix of new */
223: s += i; /* Skip matched portion */
224: n -= i;
225: }
226: else /* Else partial match */
227: {
228: /*
229: * We must split an existing node.
230: * This is the trickiest case.
231: */
232: new = newnode(s_text(cur) + j,cur->s_must - j);
233: /* Unmatched part of current string */
234: reallocnode(cur,s_text(cur),j);
235: /* Set length to matched portion */
236: new->s_suf = cur->s_suf; /* Current string's suffixes */
237: if(k < 0) /* If new preceded current */
238: {
239: cur->s_suf = newnode(s + j,n - j);
240: /* FIrst suffix is new string */
241: cur->s_suf->s_alt = new;/* Alternate is part of current */
242: }
243: else /* Else new followed current */
244: {
245: new->s_alt = newnode(s + j,n - j);
246: /* Unmatched new string is alternate */
247: cur->s_suf = new; /* New suffix list */
248: }
249: return;
250: }
251: }
252: *pprev = newnode(s,n); /* Set pointer to new node */
253: (*pprev)->s_alt = cur; /* Attach alternates */
254: }
255:
256:
257: int addfancy(buffer,buflen,seplist)
258: register char *buffer; /* Buffer */
259: int buflen; /* Length of buffer */
260: char *seplist; /* List of separators */
261: {
262: register char *bufend; /* Pointer to end of buffer */
263: int strcnt = 0; /* String count */
264: int len; /* String length */
265: char c; /* One char buffer */
266:
267: bufend = buffer + buflen; /* Set end pointer */
268: while(buffer < bufend) /* Loop through all strings */
269: {
270: len = strncspn(buffer,seplist,bufend - buffer);
271: /* Length of string */
272: if(flags & ENDLINE) /* If match must be at end of line */
273: {
274: c = buffer[len]; /* Save 1st character past string */
275: buffer[len++] = '\r'; /* Carriage return marks end of line */
276: }
277: if(findlist(buffer,buffer + len) == NULL)
278: { /* If no match within string */
279: addstring(buffer,len); /* Add string to list */
280: if(strcnt++ == 0) /* If first string */
281: {
282: memcpy(target,buffer,len);
283: /* Save first string in buffer */
284: targetlen = len; /* Remember length */
285: }
286: }
287: buffer += len; /* Skip over string */
288: if(flags & ENDLINE) (--buffer)[0] = c;
289: /* Restore saved character */
290: buffer += strnspn(buffer,seplist,bufend - buffer);
291: /* Skip over trailing separators */
292: }
293: return(strcnt); /* Return string count */
294: }
295:
296:
297: int addplain(buffer,buflen,seplist)
298: register char *buffer; /* String list buffer */
299: int buflen; /* Buffer length */
300: char *seplist; /* List of separators */
301: {
302: int strcnt; /* String count */
303: register int len; /* String length */
304: char c; /* One char buffer */
305:
306: strcnt = 0;
307: while((len = strncspn(buffer,seplist,buflen)) > 0)
308: { /* While not at end of input list */
309: if(flags & ENDLINE) /* If match must be at end of line */
310: {
311: c = buffer[len]; /* Save 1st character past string */
312: buffer[len++] = '\r'; /* Carriage return marks end of line */
313: }
314: if(strcnt == 0) /* Save first string */
315: {
316: strncpy(target,buffer,len); /* Save string in buffer */
317: targetlen = len; /* Save string length */
318: }
319: addstring(buffer,len); /* Add the string to the table */
320: if(flags & ENDLINE) buffer[--len] = c;
321: /* Restore saved character */
322: buffer += len; /* Skip the string */
323: buflen -= len;
324: len = strnspn(buffer,seplist,buflen);
325: /* Skip separators */
326: buffer += len;
327: buflen -= len;
328: ++strcnt; /* Increment string count */
329: }
330: return(strcnt); /* Return string count */
331: }
332:
333:
334: void dumplist(node,indent)
335: register STRINGNODE *node; /* Pointer to list to dump */
336: int indent; /* Current length of buffer */
337: {
338: int i; /* Counter */
339:
340: while(node != NULL) /* While not at end of list */
341: {
342: for(i = 0; i < indent; ++i) fputc(' ',stderr);
343: fwrite(s_text(node),sizeof(char),node->s_must,stderr);
344: fprintf(stderr,"\n");
345: if(node->s_suf != NULL)
346: dumplist(node->s_suf,indent + node->s_must);
347: /* Recurse to do suffixes */
348: node = node->s_alt; /* Do next alternate in list */
349: }
350: }
351:
352:
353: void dumpstrings()
354: {
355: int i; /* Index */
356:
357: for(i = 0; i < TRTABLEN; ++i) /* Loop through translation table */
358: {
359: if(transtab[i] == 0) continue; /* Skip null entries */
360: fprintf(stderr,"%c\n",i); /* Print the first byte */
361: dumplist(stringlist[transtab[i]],1);
362: /* Dump the list */
363: }
364: }
365:
366:
367: int openfile(name)
368: char *name; /* File name */
369: {
370: int fd; /* File descriptor */
371:
372: if((fd = open(name,0)) == -1) /* If error opening file */
373: {
374: fprintf(stderr,"Cannot open %s\r\n",name);
375: /* Print error message */
376: }
377: return(fd); /* Return file descriptor */
378: }
379:
380:
381: void far thread2() /* Read thread */
382: {
383: while(DOSSEMREQUEST((long far *) &readpending,-1L) == 0)
384: { /* While there is work to do */
385: arrc = DOSREAD(t2fd,(char far *) t2buf,t2buflen,(int far *) &cbread);
386: /* Do the read */
387: DOSSEMCLEAR((long far *) &readdone);
388: /* Signal read completed */
389: }
390: fprintf(stderr,"Thread 2: DOSSEMREQUEST failed\n");
391: /* Print error message */
392: DOSEXIT(1, 2); /* Die */
393: }
394:
395:
396: void far thread3() /* Write thread */
397: {
398: while(DOSSEMREQUEST((long far *) &writepending,-1L) == 0)
399: { /* While there is work to do */
400: awrc = DOSWRITE(t3fd,(char far *) t3buf,t3buflen,(int far *) &cbwrite);
401: /* Do the write */
402: DOSSEMCLEAR((long far *) &writedone);
403: /* Signal write completed */
404: }
405: fprintf(stderr,"Thread 3: DOSSEMREQUEST failed\n");
406: /* Print error message */
407: DOSEXIT(1, 2); /* Die */
408: }
409:
410:
411: void startread(fd,buffer,buflen)
412: int fd; /* File handle */
413: char *buffer; /* Buffer */
414: int buflen; /* Buffer length */
415: {
416: if(pmode) /* If protected mode */
417: {
418: if(DOSSEMREQUEST((long far *) &readdone,-1L) != 0)
419: { /* If we fail to get the semaphore */
420: fprintf(stderr,"DOSSEMREQUEST failed\n");
421: /* Error message */
422: DOSEXIT(1, 2); /* Die */
423: }
424: t2fd = fd; /* Set parameters for read */
425: t2buf = buffer;
426: t2buflen = buflen;
427: DOSSEMCLEAR((long far *) &readpending);
428: /* Wake thread 2 for read */
429: DOSSLEEP(0L); /* Yield the CPU */
430: }
431: else arrc = DOSREAD(fd,(char far *) buffer,buflen,(int far *) &cbread);
432: }
433:
434:
435: int finishread()
436: {
437: if(pmode && DOSSEMWAIT((long far *) &readdone,-1L) != 0)
438: { /* If protected mode and wait fails */
439: fprintf(stderr,"DOSSEMWAIT failed\n");
440: /* Print error message */
441: DOSEXIT(1, 2); /* Die */
442: }
443: return((arrc == 0)? cbread: -1); /* Return number of bytes read */
444: }
445:
446:
447: void startwrite(fd,buffer,buflen)
448: int fd; /* File handle */
449: char *buffer; /* Buffer */
450: int buflen; /* Buffer length */
451: {
452: if(pmode) /* If protected mode */
453: {
454: if(DOSSEMREQUEST((long far *) &writedone,-1L) != 0)
455: { /* If we fail to get the semaphore */
456: fprintf(stderr,"DOSSEMREQUEST failed\n");
457: /* Error message */
458: DOSEXIT(1, 2); /* Die */
459: }
460: t3fd = fd; /* Set parameters for write */
461: t3buf = buffer;
462: t3buflen = buflen;
463: DOSSEMCLEAR((long far *) &writepending);
464: /* Wake thread 3 for read */
465: DOSSLEEP(0L); /* Yield the CPU */
466: }
467: else awrc = DOSWRITE(fd,(char far *) buffer,buflen,(int far *) &cbwrite);
468: }
469:
470:
471: int finishwrite()
472: {
473: if(pmode && DOSSEMWAIT((long far *) &writedone,-1L) != 0)
474: { /* If protected mode and wait fails */
475: fprintf(stderr,"DOSSEMWAIT failed\n");
476: /* Print error message */
477: DOSEXIT(1, 2); /* Die */
478: }
479: return((awrc == 0)? cbwrite: -1); /* Return number of bytes written */
480: }
481:
482:
483: void write1nobuf(buffer,buflen)
484: char *buffer; /* Buffer */
485: register int buflen; /* Buffer length */
486: {
487: int cb; /* Count of bytes written */
488:
489: if(DOSWRITE(1,(char far *) buffer,buflen,(int far *) &cb) != 0 ||
490: cb != buflen) /* If write fails */
491: {
492: fprintf(stderr,"write error %d\n",awrc);
493: /* Print error message */
494: DOSEXIT(1, 2); /* Die */
495: }
496: }
497:
498:
499: void write1buf(buffer,buflen)
500: char *buffer; /* Buffer */
501: register int buflen; /* Buffer length */
502: {
503: register int cb; /* Byte count */
504:
505: while(buflen > 0) /* While bytes remain */
506: {
507: if(awrc != 0) /* If previous write failed */
508: {
509: fprintf(stderr,"write error %d\n",awrc);
510: /* Print error message */
511: DOSEXIT(1, 2); /* Die */
512: }
513: if((cb = ocnt[oi]) == 0) /* If buffer full */
514: {
515: startwrite(1,obuf[oi],OUTBUFLEN);
516: /* Write the buffer */
517: ocnt[oi] = OUTBUFLEN; /* Reset count and pointer */
518: optr[oi] = obuf[oi];
519: oi ^= 1; /* Switch buffers */
520: cb = ocnt[oi]; /* Get space remaining */
521: }
522: if(cb > buflen) cb = buflen; /* Get minimum */
523: memcpy(optr[oi],buffer,cb); /* Copy bytes to buffer */
524: ocnt[oi] -= cb; /* Update buffer length and pointers */
525: optr[oi] += cb;
526: buflen -= cb;
527: buffer += cb;
528: }
529: }
530:
531:
532: void flush1nobuf()
533: {
534: }
535:
536:
537: void flush1buf()
538: {
539: int cb; /* Byte count */
540:
541: if((cb = OUTBUFLEN - ocnt[oi]) > 0) /* If buffer not empty */
542: {
543: startwrite(1,obuf[oi],cb); /* Start write */
544: if(finishwrite() != cb) /* If write failed */
545: {
546: fprintf(stderr,"write error %d\n",awrc);
547: /* Print error message */
548: DOSEXIT(1, 2); /* Die */
549: }
550: }
551: }
552:
553:
554: int grepnull(cp,endbuf,name)
555: register char *cp; /* Buffer pointer */
556: char *endbuf; /* End of buffer */
557: char *name; /* File name */
558: {
559: return(0); /* Do nothing */
560: }
561:
562:
563: int grepbuffer(startbuf,endbuf,name)
564: char *startbuf; /* Start of buffer */
565: char *endbuf; /* End of buffer */
566: char *name; /* File name */
567: {
568: register char *cp; /* Buffer pointer */
569: char *lastmatch; /* Last matching line */
570: int linelen; /* Line length */
571: int namlen = 0; /* Length of name */
572: char lnobuf[LNOLEN]; /* Line number buffer */
573: char nambuf[LINELEN];/* Name buffer */
574:
575: cp = startbuf; /* Initialize to start of buffer */
576: lastmatch = cp; /* No previous match yet */
577: while((cp = (*find)(cp,endbuf)) != NULL)
578: { /* While matches are found */
579: if((flags & BEGLINE) && cp[-1] != '\n' && cp > startbuf)
580: { /* If begin line conditions not met */
581: ++cp; /* Skip first char of match */
582: continue; /* Keep looking */
583: }
584: status = 0; /* Match found */
585: if(flags & NAMEONLY) /* If filename only wanted */
586: {
587: (*write1)(nambuf,sprintf(nambuf,"%s\r\n",name));
588: /* Print the name */
589: return(1); /* Punt remainder of buffer */
590: }
591: cp -= revfind(cp,'\n',cp - startbuf);
592: /* Point at last linefeed */
593: if(*cp == '\n') ++cp; /* Point at start of line */
594: if(flags & SHOWNAME) /* If name wanted */
595: {
596: if(namlen == 0) namlen = sprintf(nambuf,"%s:",name);
597: /* Format name if not done already */
598: (*write1)(nambuf,namlen); /* Show name */
599: }
600: if(flags & LINENOS) /* If line number wanted */
601: {
602: lineno += countlines(lastmatch,cp);
603: /* Count lines since last match */
604: (*write1)(lnobuf,sprintf(lnobuf,"%d:",lineno));
605: /* Print line number */
606: lastmatch = cp; /* New last match */
607: }
608: linelen = strncspn(cp,"\n",endbuf - cp) + 1;
609: /* Calculate line length */
610: (*write1)(cp,linelen); /* Print the line */
611: cp += linelen; /* Skip the line */
612: }
613: if(flags & LINENOS) lineno += countlines(lastmatch,endbuf);
614: /* Count remaining lines in buffer */
615: return(0); /* Keep searching */
616: }
617:
618:
619: void showv(name,lastmatch,thismatch)
620: char *name;
621: register char *lastmatch;
622: char *thismatch;
623: {
624: register int linelen;
625: int namlen = 0; /* Length of name */
626: char lnobuf[LNOLEN]; /* Line number buffer */
627: char nambuf[LINELEN];/* Name buffer */
628:
629: if(flags & (SHOWNAME | LINENOS))
630: {
631: while(lastmatch < thismatch)
632: {
633: if(flags & SHOWNAME) /* If name wanted */
634: {
635: if(namlen == 0) namlen = sprintf(nambuf,"%s:",name);
636: /* Format name if not done already */
637: (*write1)(nambuf,namlen);
638: /* Write the name */
639: }
640: if(flags & LINENOS)
641: {
642: (*write1)(lnobuf,sprintf(lnobuf,"%d:",lineno++));
643: }
644: linelen = strncspn(lastmatch,"\n",thismatch - lastmatch) + 1;
645: (*write1)(lastmatch,linelen);
646: lastmatch += linelen;
647: }
648: }
649: else (*write1)(lastmatch,thismatch - lastmatch);
650: }
651:
652:
653: int grepvbuffer(startbuf,endbuf,name)
654: char *startbuf; /* Start of buffer */
655: char *endbuf; /* End of buffer */
656: char *name; /* File name */
657: {
658: register char *cp; /* Buffer pointer */
659: register char *lastmatch; /* Pointer to line after last match */
660:
661: cp = startbuf; /* Initialize to start of buffer */
662: lastmatch = cp;
663: while((cp = (*find)(cp,endbuf)) != NULL)
664: {
665: if((flags & BEGLINE) && cp[-1] != '\n' && cp > startbuf)
666: { /* If begin line conditions not met */
667: ++cp; /* Skip first char of match */
668: continue; /* Keep looking */
669: }
670: status = 1; /* Match found */
671: if(flags & NAMEONLY) return(1); /* Skip rest of file if NAMEONLY */
672: cp -= revfind(cp,'\n',cp - startbuf);
673: /* Point at last linefeed */
674: if(*cp == '\n') ++cp; /* Point at start of line */
675: showv(name,lastmatch,cp); /* Show from last match to this */
676: cp += strncspn(cp,"\n",endbuf - cp) + 1;
677: /* Skip over line with match */
678: lastmatch = cp; /* New "last" match */
679: ++lineno; /* Increment line count */
680: }
681: if(!(flags & NAMEONLY)) showv(name,lastmatch,endbuf);
682: /* Show buffer tail if not NAMEONLY */
683: return(0); /* Keep searching file */
684: }
685:
686:
687: void qgrep(name,fd)
688: char *name; /* File name */
689: int fd; /* File descriptor */
690: {
691: register int cb; /* Byte count */
692: register char *cp; /* Buffer pointer */
693: char *endbuf; /* End of buffer */
694: int taillen; /* Length of buffer tail */
695: int bufi; /* Buffer index */
696: char line[LINELEN]; /* Line buffer */
697:
698: lineno = 1; /* File starts on line 1 */
699: taillen = 0; /* No buffer tail yet */
700: bufi = 0; /* Initialize buffer index */
701: cp = bufptr[0]; /* Initialize to start of buffer */
702: finishread(); /* Make sure no I/O activity */
703: arrc = DOSREAD(fd,(char far *) cp,FILBUFLEN,(int far *) &cbread);
704: /* Do first read synchronously */
705: while((cb = finishread()) + taillen > 0)
706: { /* While search incomplete */
707: if(cb == 0) /* If buffer tail is all that's left */
708: {
709: taillen = 0; /* Set tail length to zero */
710: *cp++ = '\r'; /* Add end of line sequence */
711: *cp++ = '\n';
712: endbuf = cp; /* Note end of buffer */
713: }
714: else /* Else start next read */
715: {
716: taillen = revfind(cp + cb - 1,'\n',cb);
717: /* Find length of partial line */
718: endbuf = cp + cb - taillen; /* Get pointer to end of buffer */
719: cp = bufptr[bufi ^ 1]; /* Pointer to other buffer */
720: memcpy(cp,endbuf,taillen); /* Copy tail to head of other buffer */
721: cp += taillen; /* Skip over tail */
722: startread(fd,cp,(FILBUFLEN - taillen) & (~0 << LG2SECLEN));
723: /* Start next read */
724: }
725: if((*grep)(bufptr[bufi],endbuf,name)) return;
726: /* Done if NAMEONLY and match found */
727: bufi ^= 1; /* Switch buffers */
728: }
729: if((flags & (NAMEONLY | INVERT)) == (NAMEONLY | INVERT))
730: (*write1)(line,sprintf(line,"%s\r\n",name));
731: /* Write name if -lv */
732: }
733:
734:
735: void usage(verbose)
736: int verbose; /* Verbose message flag */
737: {
738: static char *opts[] =
739: {
740: "-? - print this message",
741: "-B - match pattern if at beginning of line",
742: "-E - match pattern if at end of line",
743: "-l - print only file name if file contains match",
744: "-n - print line number before each matching line",
745: "-v - print only lines not containing a match",
746: "-x - print lines that match exactly (-BE)",
747: "-y - treat upper and lower case as equivalent",
748: "-e - treat next argument as the search string",
749: "-f - read search strings from file named by next argument",
750: "-i - read file list from file named by next argument",
751: 0
752: };
753: register char **opt = opts; /* Option list */
754:
755: fprintf(stderr,"usage: CPGREP [-?BElnvxy][-e][-f <file>][-i <file>][<strings>][<files>]\n");
756: if(verbose) /* If verbose message wanted */
757: {
758: while(*opt != 0) fprintf(stderr,"%s\n",*opt++);
759: /* Print option list */
760: }
761: DOSEXIT(1, 2); /* Error exit */
762: }
763:
764:
765: void main(argc,argv)
766: int argc;
767: char **argv;
768: {
769: register char *cp;
770: int fd;
771: FILE *fi;
772: char filnam[FILNAMLEN];
773: int i;
774: char *inpfile = NULL;
775: int j;
776: char *seplist = " \t";
777: int strcnt;
778: char *strfile = NULL;
779: long start; /* Start time */
780: int (*add)();
781: int t2stk[STKLEN]; /* Read thread stack */
782: int t3stk[STKLEN]; /* Write thread stack */
783: long time(); /* Time and date in seconds */
784:
785: DOSGETMACHINEMODE((char far *) &pmode);
786: flags = 0;
787: for(i = 1; i < argc && argv[i][0] == '-'; ++i)
788: {
789: switch(argv[i][1])
790: {
791: case 'f':
792: case 'i':
793: if(i == argc - 1)
794: {
795: fprintf(stderr,"File name missing after -%c\n",argv[i][1]);
796: DOSEXIT(1, 2);
797: }
798: if(argv[i++][1] == 'i') inpfile = argv[i];
799: else strfile = argv[i];
800: break;
801:
802: case '?':
803: case 'B':
804: case 'E':
805: case 'N':
806: case 'S':
807: case 'd':
808: case 'l':
809: case 'n':
810: case 't':
811: case 'v':
812: case 'x':
813: case 'y':
814: for(cp = &argv[i][1]; *cp != '\0'; ++cp)
815: {
816: switch(*cp)
817: {
818: case '?':
819: usage(1); /* Verbose usage message */
820:
821: case 'B':
822: flags |= BEGLINE;
823: break;
824:
825: case 'E':
826: flags |= ENDLINE;
827: break;
828:
829: case 'N':
830: grep = grepnull;
831: break;
832:
833: case 'S':
834: pmode = 0; /* Force synchronous I/O */
835: break;
836:
837: case 'd':
838: flags |= DEBUG;
839: break;
840:
841: case 'l':
842: flags |= NAMEONLY;
843: break;
844:
845: case 'n':
846: flags |= LINENOS;
847: break;
848:
849: case 't':
850: flags |= TIMER;
851: break;
852:
853: case 'v':
854: status = 0; /* Assume success */
855: flags |= INVERT;
856: grep = grepvbuffer;
857: break;
858:
859: case 'x':
860: flags |= BEGLINE | ENDLINE;
861: break;
862:
863: case 'y':
864: casesen = 0;
865: break;
866:
867: default:
868: fprintf(stderr,"-%c ignored\n",*cp);
869: break;
870: }
871: }
872: break;
873:
874: case 'e':
875: if(strfile == NULL)
876: {
877: ++i;
878: seplist = ""; /* Allow anything in string */
879: goto endfor0;
880: }
881: /* Drop through to "default" */
882:
883: default:
884: fprintf(stderr,"%s ignored\n",argv[i]);
885: break;
886: }
887: }
888: endfor0:
889:
890: if(i == argc && strfile == NULL) usage(0);
891: /* Simple usage message if arg error */
892: if(flags & TIMER) start = time(NULL);
893: /* Get start time if timer on */
894: if(pmode) /* Initialize semaphores and threads */
895: {
896: DOSSEMCLEAR((long far *) &readdone);
897: DOSSEMCLEAR((long far *) &writedone);
898: DOSSEMSET((long far *) &readpending);
899: DOSSEMSET((long far *) &writepending);
900: if(DOSCREATETHREAD(thread2,(int far *) &fd,
901: (int far *) t2stk + STKLEN) != 0 ||
902: DOSCREATETHREAD(thread3,(int far *) &fd,
903: (int far *) t3stk + STKLEN) != 0)
904: { /* If thread creation fails */
905: fprintf(stderr,"Failed to create child threads\n");
906: /* Print error message */
907: DOSEXIT(1, 2); /* Die */
908: }
909: }
910: setmode(fileno(stdout),O_BINARY);
911: add = addplain; /* Assume plain string adds */
912: if(strfile != NULL) /* If strings from file */
913: {
914: if(!(flags & BEGLINE)) add = addfancy;
915: /* Try to add intelligently */
916: if((fd = open(strfile,0)) == -1)
917: { /* If open fails */
918: fprintf(stderr,"Cannot read strings from %s\n",strfile);
919: DOSEXIT(1, 2); /* Print message and die */
920: }
921: for(cp = filbuf, j = 0; (j = read(fd,cp,FILBUFLEN*2 - j)) > 0; cp += j);
922: /* Read strings file into buffer */
923: j = cp - filbuf; /* Get total length of buffer */
924: close(fd); /* Close strings file */
925: filbuf[j] = '\0'; /* Null-terminate the buffer */
926: cp = filbuf; /* Set pointer to string list */
927: seplist = "\r\n"; /* Only '\r' and '\n' are separators */
928: }
929: else /* Else strings on command line */
930: {
931: cp = argv[i++]; /* Set pointer to strings */
932: j = strlen(cp); /* Get length of strings */
933: }
934: if((strcnt = (*add)(cp,j,seplist)) == 0)
935: { /* If no strings */
936: fprintf(stderr,"No search strings\n");
937: DOSEXIT(1, 2); /* Print error message and die */
938: }
939:
940: /*
941: * Check type of handle for std. out.
942: */
943: if(DOSQHANDTYPE(fileno(stdout),(int far *) &j,(int far *) &fd) != 0)
944: { /* If error */
945: fprintf(stderr,"Standard output bad handle\n");
946: /* Print error message */
947: DOSEXIT(1, 2); /* Die */
948: }
949: if(j != 0 && (fd & ISCOT)) /* If handle is console output */
950: {
951: write1 = write1nobuf; /* Use unbuffered output */
952: flush1 = flush1nobuf;
953: }
954:
955: if(strcnt > 1) /* If more than one string */
956: {
957: if(flags & DEBUG) /* Print debug info maybe */
958: {
959: fprintf(stderr,"Here are the strings:\n");
960: dumpstrings();
961: }
962: }
963: else if(casesen) find = findone; /* Else use findone() */
964: if(inpfile != NULL) /* If file list from file */
965: {
966: flags |= SHOWNAME; /* Always show name of file */
967: if((fi = fopen(inpfile,"r")) == NULL)
968: { /* If open fails */
969: fprintf(stderr,"Cannot read file list from %s\r\n",inpfile);
970: /* Error message */
971: DOSEXIT(1, 2); /* Error exit */
972: }
973: while(fgets(filnam,FILNAMLEN,fi) != NULL)
974: { /* While there are names */
975: filnam[strcspn(filnam,"\r\n")] = '\0';
976: /* Null-terminate the name */
977: if((fd = openfile(filnam)) == -1) continue;
978: /* Skip file if it cannot be opened */
979: qgrep(filnam,fd); /* Do the work */
980: close(fd); /* Close the file */
981: }
982: fclose(fi); /* Close the list file */
983: }
984: else if(i == argc)
985: {
986: flags &= ~(NAMEONLY | SHOWNAME);
987: setmode(fileno(stdin),O_BINARY);
988: qgrep(NULL,fileno(stdin));
989: }
990: if(argc > i + 1) flags |= SHOWNAME;
991: for(; i < argc; ++i)
992: {
993: if((fd = openfile(argv[i])) == -1) continue;
994: qgrep(argv[i],fd);
995: close(fd);
996: }
997: (*flush1)();
998: if(flags & TIMER) fprintf(stderr,"%ld seconds\n",time(NULL) - start);
999: /* Print elapsed time if timer on */
1000: DOSEXIT(1, status);
1001: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.