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