home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 329_01 / egrep.c < prev    next >
C/C++ Source or Header  |  1988-12-09  |  6KB  |  273 lines

  1. /*
  2. **    name:        egrep
  3. **    purpose:    Regular expresion matcher
  4. */
  5. #define LINT_ARGS
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "regexp.h"
  9. char *fgets();
  10. /*
  11.  * egrep.
  12.  */
  13.  
  14.  
  15. char    *documentation[] = 
  16. {
  17. "egrep searches a file for a given pattern.  Execute by",
  18. "   egrep [flags] regular_expression file_list",
  19. "",
  20. "Flags are single characters preceeded by '-':",
  21. "   -c      Only a count of matching lines is printed",
  22. "   -f      Print file name for matching lines switch, see below",
  23. "   -n      Each line is preceeded by its line number",
  24. "   -v      Only print non-matching lines",
  25. NULL
  26. };
  27.  
  28.  
  29. char    *patdoc[] = 
  30. {
  31. "The regular_expression defines the pattern to search for.",
  32. "The expression should be quoted to prevent file-name translation.",
  33. "x      An ordinary character (not mentioned below) matches that character.",
  34. "'\\'    The backslash quotes any character.  \"\\$\" matches a dollar-sign.",
  35. "'^'    A circumflex at the beginning of an expression matches the",
  36. "       beginning of a line.",
  37. "'$'    A dollar-sign at the end of an expression matches the end of a line.",
  38. "'.'    A period matches any character except \"new-line\".",
  39. "'*'    An expression followed by an asterisk matches zero or more",
  40. "       occurrances of that expression.",
  41. "'+'    An expression followed by a plus sign matches one or more",
  42. "       occurrances of that expression.",
  43. "'?'    An expression followed by a question mark matches zero or one",
  44. "       occurrences of that expression.",
  45. "'[]'   A string enclosed in square brackets matches any character in",
  46. "       that string, but no others.  If the first character in the",
  47. "       string is a circumflex, the expression matches any character",
  48. "       except \"new-line\" and the characters in the string.",
  49. "       If two characters in the string are seperated by \"-\"",
  50. "       this matches all characters between and including those two",
  51. "       characters.  To include a \"]\" in the sequence, make it the first",
  52. "       character.  To include \"-\" in the sequence, make it the first or",
  53. "       last character.",
  54. "'()'   A regular expression in parentheses matches that regular expression.",
  55. "'|'    Two regular expressions joined by \"|\" match either the first, or",
  56. "       the second regular expression.",
  57. "       The concatenation of regular expressions is a regular expression.",
  58. NULL
  59. };
  60.  
  61. int    cflag;
  62. int    fflag;
  63. int    nflag;
  64. int    vflag;
  65. int    nfile;
  66.  
  67. int    debug    =    0;       /* Set for debug code      */
  68.  
  69. char    *pp;
  70. #define LMAX 512
  71. char    lbuf[LMAX];
  72. regexp    *pbuf;
  73. /*******************************************************/
  74.  
  75. int main(argc, argv)
  76. char *argv[];
  77. {
  78.     register char   *p;
  79.     register int    i,c;
  80.     int           gotpattern;
  81.  
  82.    FILE        *f;
  83.  
  84.        if (argc <= 1)
  85.       usage("No arguments");
  86.        if (argc == 2 && (0 == strncmp(argv[1],"-h",2) || 
  87.                         0 == strncmp(argv[1],"-H",2))
  88.         )
  89.     {
  90.       help(documentation);
  91.       help(patdoc);
  92.       return(1);
  93.     }
  94.    nfile = argc-1;
  95.    gotpattern = 0;
  96.    for (i=1; i < argc; ++i) 
  97.    {
  98.       p = argv[i];
  99.       if (*p == '-') 
  100.       {
  101.          ++p;
  102.          while (0 != (c = *p++)) 
  103.          {
  104.             switch(tolower(c)) 
  105.             {
  106.             case 'h':
  107.                help(documentation);
  108.                break;
  109.             case 'c':
  110.                ++cflag;
  111.                break;
  112.             case 'd':
  113.                ++debug;
  114.                break;
  115.             case 'f':
  116.                ++fflag;
  117.                break;
  118.             case 'n':
  119.                ++nflag;
  120.                break;
  121.             case 'v':
  122.                ++vflag;
  123.                break;
  124.             default:
  125.                usage("Unknown flag");
  126.             }
  127.          }
  128.          argv[i] = 0;
  129.          --nfile;
  130.       } else if (!gotpattern) 
  131.       {
  132.          pbuf = regcomp(p);
  133.          argv[i] = 0;
  134.          ++gotpattern;
  135.          --nfile;
  136.       }
  137.    }
  138.    if (!gotpattern)
  139.       usage("No pattern");
  140.    if (nfile == 0)
  141.       grep(stdin, 0);
  142.    else 
  143.    {
  144.          fflag = ((nfile > 0) ? (fflag ^ 1) : fflag);
  145.       for (i=1; i < argc; ++i) 
  146.       {
  147.          if (0 != (p = argv[i])) 
  148.          {
  149.             if ((f=fopen(p, "r")) == NULL)
  150.                cant(p);
  151.             else 
  152.             {
  153.                grep(f, p);
  154.                fclose(f);
  155.             }
  156.          }
  157.       }
  158.    }
  159. return(0);
  160. }
  161.  
  162. /*******************************************************/
  163.  
  164. void file(s)
  165. char *s;
  166. {
  167.    printf("File %s:\n", s);
  168. }
  169.  
  170. /*******************************************************/
  171.  
  172. void cant(s)
  173. char *s;
  174. {
  175.    fprintf(stderr, "%s: cannot open\n", s);
  176. }
  177.  
  178.  
  179. /*******************************************************/
  180.  
  181. void help(hp)
  182. char **hp;  /* dns added extra '*'  */
  183. /*
  184.  * Give good help
  185.  */
  186. {
  187.    register char   **dp;
  188.  
  189.    for (dp = hp; *dp; dp++)
  190.       printf("%s\n", *dp);
  191. }
  192.  
  193.  
  194. /*******************************************************/
  195.  
  196. void usage(s)
  197. char    *s;
  198. {
  199.    fprintf(stderr,
  200.       "%s\nUsage: grep [-cfhnv] pattern [file ...].  grep -h for help\n",s);
  201.    exit(1);
  202. }
  203.  
  204.  
  205.  
  206. /*******************************************************/
  207.  
  208. void grep(fp, fn)
  209. FILE       *fp;       /* File to process        */
  210. char       *fn;       /* File name (for -f option)  */
  211. /*
  212.  * Scan the file for the pattern in pbuf[]
  213.  */
  214. {
  215.    register int lno, count, m;
  216.  
  217.    lno = 0;
  218.    count = 0;
  219.    while (fgets(lbuf, LMAX, fp)) 
  220.    {
  221.         ++lno;
  222.         m = match();
  223.         if ((m && !vflag) || (!m && vflag)) 
  224.         {
  225.             ++count;
  226.             if (!cflag) 
  227.             {
  228.                 if (fflag && fn) 
  229.                 {
  230.                     file(fn);
  231.                     fn = 0;
  232.                 }
  233.                 if (nflag)
  234.                     printf("%d\t", lno);
  235.                     printf("%s", lbuf);
  236.             }
  237.         }
  238.     }
  239.     if (cflag) 
  240.     {
  241.         if (fflag && fn)
  242.             file(fn);
  243.         printf("%d\n", count);
  244.     }
  245. }
  246.  
  247.  
  248. /*******************************************************/
  249.  
  250. int match()
  251. /*
  252.  * Match the current line (in lbuf[]), return 1 if it does.
  253.  */
  254. {
  255.    register char   *l;          /* Line pointer        */
  256.  
  257.    for (l = lbuf; *l; l++) 
  258.    {
  259.       if (regexec(pbuf,l))
  260.          return(1);
  261.    }
  262.    return(0);
  263. }
  264.  
  265.  
  266. /*******************************************************/
  267. void error(s)
  268. char *s;
  269. {
  270.    fprintf(stderr, "%s", s);
  271.    exit(1);
  272. }
  273.