|
|
1.1 ! root 1: /* ! 2: * To compile use ! 3: * cc cgrep.c -lmisc ! 4: * This uses libmisc.a and the misc.h header from libmisc.a.Z ! 5: */ ! 6: ! 7: /* ! 8: * cgrep is egrep for c source programs. ! 9: * cgrep [-r new] [-clnsA] [pattern] [file ...] ! 10: * ! 11: * cgrep checks all c identifiers (cgrep considers if, etc to be ! 12: * identifiers) against an egrep type pattern for a full match. ! 13: * ! 14: * cgrep tmp *.c ! 15: * will find tmp as an identifier, but not tmpname, or tmp in a string or ! 16: * comment. ! 17: * cgrep "x|abc|d" *.c ! 18: * will find x, ab, or d. Note these are egrep style patterns with a ! 19: * surrounding ^( )$ Thus "reg*" will not match register but "reg.*" ! 20: * will. ! 21: * ! 22: * cgrep accumulates names with included . and -> for testing against the ! 23: * egrep pattern. Thus you can look for ptr->val with ! 24: * cgrep "ptr->val" x.c ! 25: * This will find ptr->val even if it contains spaces, comments or is ! 26: * spread across lines. If it is spread across lines it will be reported ! 27: * on the line containing the last token unless the -A option is used ! 28: * in which case it will be reported on the line containing the first ! 29: * token. ! 30: * ! 31: * For structure.member use ! 32: * cgrep "structure\.member" x.c ! 33: * because . has the egrep meaning any character. Do not include spaces ! 34: * in any pattern. Only identifiers and . or -> between identifiers are ! 35: * included in the tokens checked for pattern match. ! 36: * ! 37: * Where no files are given cgrep will read stdin. Options -lA require ! 38: * a file name. Where stdin is used with option -r a new file is written ! 39: * out stdout. ! 40: * ! 41: * Options. ! 42: * ! 43: * -l lists the files with hits not the lines. ! 44: * ! 45: * -n puts a line number on found lines. ! 46: * ! 47: * -s List all strings. This form takes no pattern. ! 48: * ! 49: * -c List all comments. This form takes no pattern. ! 50: * ! 51: * -A builds a tmp file and calls 'me' to process the file with the tmp file ! 52: * as an "error" list like the -A option of cc. Each line of this list ! 53: * shows the found pattern and where multiple patterns are found on a ! 54: * line there are multiple lines, just like cc -A showing multiple ! 55: * errors on a line. This is to allow emacs scripts to make systematic ! 56: * changes. Where a patttern is split across multiple lines -A causes ! 57: * it to be reported on the line with the first token, also to ! 58: * simplify emacs scripts. ! 59: * ! 60: * If cgrep -A is used to process a number of files it will search each ! 61: * file for patttern matches and call 'me' only if the file has a hit. To ! 62: * stop the process exit 'me' with <ctl-u><ctl-x><ctl-c>. See the new emacs ! 63: * initialization macro feature for a way to process these files ! 64: * automatically. ! 65: * ! 66: * -r Replaces all occurances of the pattern with "new". This form only matches ! 67: * simple tokens, not things like "ptr->val". -r is incompatible with all ! 68: * other options. ! 69: * ! 70: * -R Replaces all occurances of the pattern with a new after the following ! 71: * substitutions. & is the whole pattern found. \1 is the first ! 72: * parenthesized subexpression, \2 the second etc. ! 73: * ! 74: * -d token. Take following string and comment. For documentation extraction. ! 75: * use the first char of the token as an output delimeter. ! 76: * ! 77: * -C token. Use token as delimeter -c option. ! 78: */ ! 79: #include <ctype.h> ! 80: #include <stdio.h> ! 81: #include <misc.h> ! 82: ! 83: /* ! 84: * Cgrep never runs out of room on lines or buffers until malloc fails ! 85: * these are buffer expanders. ! 86: */ ! 87: #define TROOM(buf, has, needs) while ((needs) >= has) \ ! 88: if (NULL == (buf = realloc(buf, sizeof(*buf) * (has += 10)))) \ ! 89: fatal(outSpace) ! 90: ! 91: #define ROOM(buf, has, needs) while ((needs) >= has) \ ! 92: if (NULL == (buf = realloc(buf, has += 512))) \ ! 93: fatal(outSpace) ! 94: ! 95: extern char *realloc(); ! 96: static char outSpace[] = "cgrep: out of space"; ! 97: ! 98: struct token { /* collected token array */ ! 99: int start; /* token index on buff */ ! 100: int atline; /* line number where token spotted */ ! 101: }; ! 102: ! 103: enum fstate { /* lexical processing state */ ! 104: start, ! 105: slash, /* slash encountered in normal state */ ! 106: comment, /* in comment */ ! 107: cppcom, /* in cpp comment */ ! 108: star, /* * in comment */ ! 109: bsl, /* back slash */ ! 110: dquote, /* double quote */ ! 111: squote, /* single quote */ ! 112: token, /* c word */ ! 113: minus /* - maybe -> */ ! 114: }; ! 115: ! 116: enum wstate { /* word processing states */ ! 117: word, /* some c identifier */ ! 118: dot, /* . or -> */ ! 119: other /* anything else */ ! 120: }; ! 121: ! 122: /* cgrep has no fixed size arrays only growable buffers */ ! 123: static char *buff = NULL; /* accumulate stuff */ ! 124: static int buffLen; /* buffer length */ ! 125: ! 126: static struct token *tokens = NULL; /* token array */ ! 127: static int tokenLen; /* size of token array */ ! 128: ! 129: static char *line; /* expandable input line */ ! 130: static int lineLen; /* current length of input line */ ! 131: ! 132: static char lswitch; /* list files found */ ! 133: static char aswitch; /* call emacs with line list */ ! 134: static char dswitch; /* special for docs */ ! 135: static char dtoken[80]; /* token copy for dswitch */ ! 136: static char nswitch; /* print line number */ ! 137: static char sswitch; /* print all strings */ ! 138: static char cswitch; /* print all comments */ ! 139: static char rswitch; /* replace found pattern */ ! 140: static char Rswitch; /* do substition magic */ ! 141: ! 142: static regexp *pat; /* a compiled regular expression */ ! 143: ! 144: static char *newstr; /* The new string with rswitch */ ! 145: ! 146: static char *filen = NULL; /* the file currently being processed */ ! 147: static char *tname = NULL; /* temp file name */ ! 148: static FILE *tfp; /* tmp file pointer */ ! 149: ! 150: static int lineno; /* current line number */ ! 151: static int marked; /* 1 if pattern found on line. */ ! 152: ! 153: static int matched; /* 1 if any match found. */ ! 154: ! 155: /* ! 156: * Character types table ! 157: * for the ASCII character set modified to see _ as alpha. ! 158: * _ctype[0] is for EOF, the rest if indexed ! 159: * by the ascii values of the characters. ! 160: */ ! 161: static unsigned char _ctype[] = { ! 162: 0, /* EOF */ ! 163: _C, _C, _C, _C, _C, _C, _C, _C, ! 164: _C, _S|_C, _S|_C, _S|_C, _S|_C, _S|_C, _C, _C, ! 165: _C, _C, _C, _C, _C, _C, _C, _C, ! 166: _C, _C, _C, _C, _C, _C, _C, _C, ! 167: _S|_X, _P, _P, _P, _P, _P, _P, _P, ! 168: _P, _P, _P, _P, _P, _P, _P, _P, ! 169: _N, _N, _N, _N, _N, _N, _N, _N, ! 170: _N, _N, _P, _P, _P, _P, _P, _P, ! 171: _P, _U, _U, _U, _U, _U, _U, _U, ! 172: _U, _U, _U, _U, _U, _U, _U, _U, ! 173: _U, _U, _U, _U, _U, _U, _U, _U, ! 174: _U, _U, _U, _P, _P, _P, _P, _L, ! 175: _P, _L, _L, _L, _L, _L, _L, _L, ! 176: _L, _L, _L, _L, _L, _L, _L, _L, ! 177: _L, _L, _L, _L, _L, _L, _L, _L, ! 178: _L, _L, _L, _P, _P, _P, _P, _C, ! 179: _C, _C, _C, _C, _C, _C, _C, _C, ! 180: _C, _C, _C, _C, _C, _C, _C, _C, ! 181: _C, _C, _C, _C, _C, _C, _C, _C, ! 182: _C, _C, _C, _C, _C, _C, _C, _C, ! 183: _C, _C, _C, _C, _C, _C, _C, _C, ! 184: _C, _C, _C, _C, _C, _C, _C, _C, ! 185: _C, _C, _C, _C, _C, _C, _C, _C, ! 186: _C, _C, _C, _C, _C, _C, _C, _C, ! 187: _C, _C, _C, _C, _C, _C, _C, _C, ! 188: _C, _C, _C, _C, _C, _C, _C, _C, ! 189: _C, _C, _C, _C, _C, _C, _C, _C, ! 190: _C, _C, _C, _C, _C, _C, _C, _C, ! 191: _C, _C, _C, _C, _C, _C, _C, _C, ! 192: _C, _C, _C, _C, _C, _C, _C, _C, ! 193: _C, _C, _C, _C, _C, _C, _C, _C, ! 194: _C, _C, _C, _C, _C, _C, _C, _C ! 195: }; ! 196: ! 197: /* ! 198: * Report errors for public domain regexp package. ! 199: */ ! 200: void ! 201: regerror(s) ! 202: char *s; ! 203: { ! 204: fatal("cgrep: pattern error %s\n", s); ! 205: } ! 206: ! 207: /* ! 208: * Pattern found with -A mode. It is assumed that users of ! 209: * this mode will want to know about all hits on a line. ! 210: */ ! 211: static void ! 212: emacsLine(found, atline) ! 213: char *found; ! 214: { ! 215: extern char *tempnam(); ! 216: ! 217: /* if tmp file not opened open it. */ ! 218: if ((NULL == tname) && ! 219: ((NULL == (tname = tempnam(NULL, "cgr"))) || ! 220: (NULL == (tfp = fopen(tname, "w"))))) ! 221: fatal("cgrep: Cannot open tmp file"); ! 222: fprintf(tfp, "%d: %s: found '%s'\n", atline, filen, found); ! 223: } ! 224: ! 225: /* ! 226: * When we get a word, dot, arrow or other we come here. ! 227: * ! 228: * cgrep accumulates things like ptr->memb.x in buff. ! 229: * as these are accumulated it is nessisary to match buff ! 230: * against the regular expression one slice at a time ! 231: * that is when the x in ptr->memb.x was found cgrep would check ! 232: * ptr->memb.x then memb.x then x ! 233: * against the pattern. Thus memb.x matches ptr->memb.x ! 234: */ ! 235: static void ! 236: gota(got, what) ! 237: register enum wstate got; /* what we have */ ! 238: char *what; /* the string we have or NULL */ ! 239: { ! 240: static int tokenCt; /* number of tokens */ ! 241: static enum wstate state; /* current word processing state */ ! 242: static int wlen, blen; /* strlen(what) and strlen(buff) + 1 */ ! 243: int i; ! 244: ! 245: if (sswitch || cswitch) ! 246: return; ! 247: ! 248: if (rswitch) { /* replace mode works on tokens only */ ! 249: marked = (word == got) && regexec(pat, what); ! 250: matched |= marked; ! 251: return; ! 252: } ! 253: ! 254: switch (got) { ! 255: case word: ! 256: wlen = strlen(what); ! 257: switch (state) { ! 258: case other: ! 259: case word: ! 260: /* store start and line number of token */ ! 261: tokenCt = 1; ! 262: TROOM(tokens, tokenLen, tokenCt); ! 263: tokens[0].start = 0; ! 264: tokens[0].atline = lineno; ! 265: ! 266: /* store token */ ! 267: blen = wlen; ! 268: ROOM(buff, buffLen, blen); ! 269: strcpy(buff, what); ! 270: break; ! 271: case dot: ! 272: /* store start and line number of token */ ! 273: TROOM(tokens, tokenLen, tokenCt); ! 274: tokens[tokenCt].start = blen; ! 275: tokens[tokenCt++].atline = lineno; ! 276: ! 277: /* store token */ ! 278: blen += wlen; ! 279: ROOM(buff, buffLen, blen); ! 280: strcat(buff, what); ! 281: } ! 282: ! 283: /* Check the accumulated token for matches */ ! 284: for (i = 0; i < tokenCt; i++) { ! 285: char *p; ! 286: ! 287: if (regexec(pat, p = buff + tokens[i].start)) { ! 288: if (aswitch) ! 289: emacsLine(p, tokens[i].atline); ! 290: else { ! 291: marked = 1; ! 292: matched = 1; ! 293: if (dswitch) { ! 294: strcpy(dtoken, p); ! 295: cswitch = sswitch = 1; ! 296: } ! 297: break; ! 298: } ! 299: } ! 300: } ! 301: ! 302: state = got; ! 303: break; ! 304: ! 305: case dot: ! 306: if (word == state) { ! 307: blen += strlen(what); ! 308: ROOM(buff, buffLen, blen); ! 309: strcat(buff, what); ! 310: state = got; ! 311: break; ! 312: } ! 313: case other: ! 314: state = other; ! 315: } ! 316: } ! 317: ! 318: /* ! 319: * call emacs with file and tmpfile. ! 320: */ ! 321: static void ! 322: callEmacs() ! 323: { ! 324: #ifdef GEMDOS ! 325: #include <path.h> ! 326: extern char *path(), *getenv(); ! 327: extern char **environ; ! 328: static char* cmda[5] = { NULL, "-e", NULL, NULL, NULL }; ! 329: #endif ! 330: int quit; ! 331: ! 332: fclose(tfp); ! 333: #ifdef MSDOS ! 334: sprintf(line, "-e %s %s", tname, filen); ! 335: if (0x7f == (quit = execall("me", line))) ! 336: #endif ! 337: #ifdef COHERENT ! 338: sprintf(line, "me -e %s %s ", tname, filen); ! 339: if (0x7f == (quit = system(line))) ! 340: #endif ! 341: #ifdef GEMDOS ! 342: cmda[2] = tname; ! 343: cmda[3] = filen; ! 344: if ((NULL == cmda[0]) && ! 345: (NULL == (cmda[0] = path(getenv("PATH"), "me.tos", 1)))) ! 346: fatal("cgrep: Cannot locate me.tos\n"); ! 347: else if ((quit = execve(cmda[0], cmda, environ)) < 0) ! 348: #endif ! 349: fatal("cgrep: cannot execute 'me'"); ! 350: unlink(tname); ! 351: free(tname); ! 352: tname = NULL; ! 353: if (quit) ! 354: exit(0); ! 355: } ! 356: ! 357: /* ! 358: * find first word in a string excluding printf % constructs. ! 359: * make it lower case and return it. ! 360: */ ! 361: static char * ! 362: firstWord(p) ! 363: char *p; ! 364: { ! 365: static char buf[80]; ! 366: char *out, c; ! 367: enum state { start, pct, name } state; ! 368: ! 369: out = NULL; ! 370: for (state = start; c = *p++;) { ! 371: switch(state) { ! 372: case start: ! 373: if (isalpha(c)) { ! 374: state = name; ! 375: out = buf; ! 376: *out++ = tolower(c); ! 377: continue; ! 378: } ! 379: if ('%' == c) ! 380: state = pct; ! 381: continue; ! 382: ! 383: case pct: ! 384: if (isalpha(c) && 'l' != c) ! 385: state = start; ! 386: continue; ! 387: ! 388: case name: ! 389: if (isalnum(c)) { ! 390: *out++ = tolower(c); ! 391: continue; ! 392: } ! 393: *out = '\0'; ! 394: return (buf); ! 395: } ! 396: } ! 397: if (NULL == out) ! 398: return ("???"); ! 399: *out = '\0'; ! 400: return (buf); ! 401: } ! 402: ! 403: /* ! 404: * print a hit for options -s or -c. Option -d creates -s and -c. ! 405: */ ! 406: static void ! 407: printx(s, sw) ! 408: register char *s; ! 409: { ! 410: register char c, *p; ! 411: ! 412: if (aswitch) ! 413: emacsLine(s, lineno); ! 414: else if (cswitch > 1) { ! 415: for (p = s; (c = *p) && isspace(c); p++) ! 416: ; ! 417: if ('*' == c) ! 418: s = p + 1; ! 419: ! 420: printf("%s", s); ! 421: putchar(sw ? cswitch : '\n'); ! 422: } ! 423: else if (dswitch) { ! 424: for (p = s; (c = *p) && isspace(c); p++) ! 425: ; ! 426: if ('*' == c) ! 427: s = p + 1; ! 428: ! 429: if (dtoken[0]) { ! 430: printf("%s%c%s%c%s", ! 431: firstWord(s), dswitch, s, dswitch, dtoken); ! 432: dtoken[0] = '\0'; ! 433: } ! 434: else ! 435: printf("%s", s); ! 436: putchar(cswitch ? dswitch : '\n'); ! 437: } ! 438: else { ! 439: if (NULL != filen) ! 440: printf("%s: ", filen); ! 441: if (nswitch) ! 442: printf("%4d: ", lineno); ! 443: printf("%s\n", s); ! 444: } ! 445: } ! 446: ! 447: /* ! 448: * Lexically process a file. ! 449: */ ! 450: static void ! 451: lex() ! 452: { ! 453: int c, i; ! 454: enum fstate state, pstate; ! 455: char *w, changed; ! 456: FILE *ifp, *tfp; ! 457: ! 458: if (NULL == filen) ! 459: ifp = stdin; ! 460: else if (NULL == (ifp = fopen(filen, "r"))) { ! 461: fprintf(stderr, "cgrep: warning cannot open %s\n", filen); ! 462: return; ! 463: } ! 464: ! 465: if (rswitch) { ! 466: changed = 0; /* no changes so far */ ! 467: ! 468: if (NULL == filen) ! 469: tfp = stdout; ! 470: else if ((NULL == (tname = tempnam(NULL, "cse"))) || ! 471: (NULL == (tfp = fopen(tname, "w")))) ! 472: fatal("cgrep: Cannot open tmp file"); ! 473: } ! 474: ! 475: lineno = 1; ! 476: i = marked = 0; ! 477: gota(other, NULL); /* initialize word machine */ ! 478: ! 479: for (state = start; ; ) { ! 480: line[i] = '\0'; ! 481: c = fgetc(ifp); ! 482: ! 483: switch (state) { ! 484: case minus: ! 485: if ('>' == c) { ! 486: gota(dot, "->"); ! 487: state = start; ! 488: break; ! 489: } ! 490: goto isstart; ! 491: case token: ! 492: if (isalnum(c)) ! 493: break; ! 494: gota(word, w); ! 495: ! 496: /* we have a word to replace */ ! 497: if (rswitch && marked) { ! 498: if(Rswitch) { ! 499: char buf[80]; ! 500: ! 501: regsub(pat, newstr, buf); ! 502: i += strlen(buf) - strlen(w); ! 503: ROOM(line, lineLen, i); ! 504: strcpy(w, buf); ! 505: } else { ! 506: i += strlen(newstr) - strlen(w); ! 507: ROOM(line, lineLen, i); ! 508: strcpy(w, newstr); ! 509: } ! 510: changed = 1; ! 511: } ! 512: isstart: state = start; ! 513: case start: ! 514: switch (c) { ! 515: case '.': ! 516: gota(dot, "."); ! 517: break; ! 518: case '-': ! 519: state = minus; ! 520: break; ! 521: case '/': ! 522: state = slash; ! 523: break; ! 524: case '\\': ! 525: pstate = state; ! 526: state = bsl; ! 527: break; ! 528: case '"': ! 529: w = line + i; ! 530: state = dquote; ! 531: break; ! 532: case '\'': ! 533: state = squote; ! 534: break; ! 535: default: ! 536: if (isalpha(c)) { ! 537: w = line + i; ! 538: state = token; ! 539: } ! 540: else if (!isspace(c)) ! 541: gota(other, NULL); ! 542: } ! 543: break; ! 544: ! 545: case slash: ! 546: switch (c) { ! 547: case '*': ! 548: state = comment; ! 549: w = line + i + 1; ! 550: break; ! 551: case '/': ! 552: state = cppcom; ! 553: w = line + i + 1; ! 554: break; ! 555: default: ! 556: goto isstart; ! 557: } ! 558: break; ! 559: ! 560: case cppcom: ! 561: if ('\n' == c) { ! 562: if (cswitch) { /* report comment */ ! 563: if (dswitch) ! 564: cswitch = 0; ! 565: line[i] = '\0'; ! 566: printx(w, 0); ! 567: line[i] = '\n'; ! 568: } ! 569: state = start; ! 570: } ! 571: break; ! 572: ! 573: case star: ! 574: if ('/' == c) { ! 575: if (cswitch) { /* report comment */ ! 576: if (dswitch) ! 577: cswitch = 0; ! 578: line[i - 1] = '\0'; ! 579: printx(w, 0); ! 580: line[i - 1] = '*'; ! 581: } ! 582: state = start; ! 583: break; ! 584: } ! 585: state = comment; ! 586: case comment: ! 587: if ('*' == c) ! 588: state = star; ! 589: break; ! 590: case bsl: ! 591: state = pstate; ! 592: break; ! 593: case dquote: ! 594: switch (c) { ! 595: case '"': ! 596: case '\n': ! 597: state = start; ! 598: if (sswitch) { ! 599: if (dswitch) ! 600: sswitch = 0; ! 601: printx(w + 1, 0); ! 602: } ! 603: else ! 604: gota(other, NULL); ! 605: break; ! 606: case '\\': ! 607: pstate = state; ! 608: state = bsl; ! 609: break; ! 610: } ! 611: break; ! 612: case squote: ! 613: switch (c) { ! 614: case '\'': ! 615: case '\n': ! 616: gota(other, NULL); ! 617: state = start; ! 618: break; ! 619: case '\\': ! 620: pstate = state; ! 621: state = bsl; ! 622: break; ! 623: } ! 624: break; ! 625: } ! 626: if (('\n' != c) && (EOF != c)) { ! 627: line[i++] = c; ! 628: ROOM(line, lineLen, i); ! 629: } ! 630: else { /* end of line */ ! 631: if (rswitch) { ! 632: if (EOF == c) { ! 633: if (!i) /* null line */ ! 634: break; ! 635: } ! 636: else ! 637: line[i++] = c; ! 638: ROOM(line, lineLen, i); ! 639: line[i] = 0; ! 640: fputs(line, tfp); ! 641: marked = 0; ! 642: } ! 643: ! 644: if (cswitch && (comment == state)) { ! 645: printx(w, 1); ! 646: w = line; ! 647: } ! 648: ! 649: if (marked && !dswitch) { ! 650: if (lswitch) { ! 651: printf("%s\n", filen); ! 652: break; ! 653: } ! 654: printx(line, 0); ! 655: } ! 656: ! 657: lineno++; ! 658: marked = i = 0; ! 659: if (EOF == c) ! 660: break; ! 661: } ! 662: } ! 663: ! 664: fclose(ifp); ! 665: ! 666: if (rswitch) { ! 667: fclose(tfp); ! 668: ! 669: if (NULL != filen) { /* tmp file used */ ! 670: if (changed) { ! 671: unlink(filen); ! 672: sprintf(line, "mv %s %s", tname, filen); ! 673: system(line); ! 674: } ! 675: else ! 676: unlink(tname); ! 677: } ! 678: } ! 679: ! 680: if (aswitch && (NULL != tname)) /* tmp file opened for -A option */ ! 681: callEmacs(); ! 682: } ! 683: ! 684: main(argc, argv) ! 685: int argc; ! 686: register char **argv; ! 687: { ! 688: register char c; ! 689: int errsw = 0; ! 690: static char msg[] = ! 691: "cgrep [-[rR] newStr] [-clnsA] [pattern] filename ..."; ! 692: char *p, *q; ! 693: extern int optind; ! 694: extern char *optarg; ! 695: ! 696: if (1 == argc) ! 697: usage(msg); ! 698: ! 699: while (EOF != (c = getopt(argc, argv, "cC:d:slnA?r:R:V"))) { ! 700: switch (c) { ! 701: case 'V': ! 702: printf("cgrep version 1.2\n"); ! 703: exit(0); ! 704: case 'C': ! 705: cswitch = *optarg; /* get delimiter */ ! 706: break; ! 707: case 'c': ! 708: cswitch = 1; /* comments only */ ! 709: break; ! 710: case 'd': /* report following string & comment */ ! 711: dswitch = *optarg; ! 712: break; ! 713: case 's': ! 714: sswitch = 1; /* strings only */ ! 715: break; ! 716: case 'l': ! 717: lswitch = 1; /* print filenames only */ ! 718: break; ! 719: case 'n': ! 720: nswitch = 1; /* print line numbers */ ! 721: break; ! 722: case 'A': ! 723: aswitch = 1; /* interact with emacs */ ! 724: break; ! 725: case 'R': ! 726: Rswitch = 1; /* do substitution magic */ ! 727: for (p = optarg; *p; p++) ! 728: if('\\' == *p && (p[1] <= '8') && (p[1] > '0')) ! 729: p[1]++; ! 730: case 'r': ! 731: rswitch = 1; /* replace hits */ ! 732: newstr = optarg; ! 733: break; ! 734: default: ! 735: errsw = 1; ! 736: } ! 737: } ! 738: ! 739: /* check unknown switches and rswitch goes with no other switches */ ! 740: if (errsw || ! 741: (rswitch && (aswitch | nswitch | lswitch | cswitch | sswitch))) ! 742: usage(msg); ! 743: ! 744: if (!sswitch && !cswitch) { /* process pattern */ ! 745: if (optind == argc) /* no pattern */ ! 746: usage(msg); ! 747: ! 748: /* inclose pattern in ^( )$ to force full match */ ! 749: p = alloc(5 + strlen(q = argv[optind++])); ! 750: sprintf(p, "^(%s)$", q); ! 751: if (NULL == (pat = regcomp(p))) ! 752: fatal("cgrep: Illegal pattern\n"); ! 753: } ! 754: ! 755: ROOM(line, lineLen, 1); /* get input line started */ ! 756: ! 757: if (optind == argc) { ! 758: if (aswitch | lswitch) ! 759: fatal("cgrep: -A and -l require a filename"); ! 760: lex(); ! 761: } ! 762: else { ! 763: while (optind < argc) { ! 764: filen = argv[optind++]; ! 765: lex(); ! 766: } ! 767: } ! 768: exit(! matched); ! 769: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.