|
|
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.