home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / txtutl / pgrep.arc / PGREP.C next >
Encoding:
C/C++ Source or Header  |  1986-10-08  |  13.6 KB  |  428 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #define  MAXLINE 1024
  5. #define  MAXNAME 100
  6. #define  BIGBUF  8192 /* Read buffer size */
  7.  
  8. #define  andc '+'     /* and character */
  9. #define  orch '|'     /* or character  */
  10. #define  arbc '@'     /* arbitrary ch  */
  11. #define  swch '?'     /* single wild   */
  12. #define  lbch '^'     /* Line begin ch */
  13. #define  lech '$'     /* Line End char */
  14. #define  lwch '{'     /* Left word ch  */
  15. #define  rwch '}'     /* right word ch */
  16.  
  17. /* Public domain program written by Hern Chen 10/86 304-776-8336    */
  18. /* To get a brief description, type "pgrep" at DOS prompt.          */
  19. /* This is a variation of fgrep/egrep program                       */
  20. /* .  Multiple filespecs are allowed.                               */
  21. /* .  Multiple patterns allowed. (and, or, pat followed by pat)     */
  22. /* .  Line begin/end, word boundaries, and single wild char.        */
  23. /* .  Search binary files as well as text files.                    */
  24. /* .  Patterns can be placed in a file.                             */
  25. /* .  Generate simple batch file exec.bat for matching files.       */
  26. /*                                                                  */
  27. /* This program contains some Lattice specific codes:               */
  28. /* .  Open file in binary mode.                                     */
  29. /* .  dfind/dnext for finding files match a filespec.               */
  30. /*                                                                  */
  31.  
  32. int _fmode;           /* Lattice C; 0x0000=text, 0x8000=binary      */
  33.  
  34. main (argc,argv)
  35. int  argc;
  36. char *argv[];
  37. {
  38. register int   ch;
  39. register char  *se;
  40.          int   msize;
  41.          int   invert;
  42.          int   linef;
  43.          int   countf;
  44.          int   mixedc;
  45.          int   talkf;
  46.          int   batch, batchx, batchy;
  47.          int   number;
  48.          int   nlines;
  49.          int   nmatch;
  50.          int   nfiles;
  51.          char  *pat, *patfile;
  52.          char  *p;
  53.          char  *bigbuf;
  54.          char  *src;
  55.          char  *src2;
  56.          char  fname[MAXNAME];
  57.          int   i;
  58.          char  *sb;
  59.          int   karg;
  60.          FILE  *fp;
  61.          FILE  *fptr;
  62.          char  *patmatch();
  63.          char  *malloc();
  64.          char  *strcpy();
  65.          int   atoi();
  66.          int   printf();
  67.          int   fprintf();
  68.          int   invalid, more;
  69.  
  70.    countf = linef = number = 1;
  71.    mixedc = invert = talkf = batch = msize = invalid = 0;
  72.    batchx = batchy = 2;
  73.    patfile = pat = NULL;
  74.    for (karg=0; ++karg<argc; )
  75.    if ((p=argv[karg])!=NULL)
  76.    {
  77.       if (*p=='-' || *p=='/' || *p=='+')
  78.          while (ch = *++p)
  79.             switch (ch)
  80.             {
  81.                case 'M': if (*(p+1))
  82.                          {
  83.                             msize = atoi(p+1);
  84.                             while (*++p);
  85.                             p--;
  86.                          }
  87.                          else if (++karg<argc)
  88.                          {
  89.                             msize = atoi(argv[karg]);
  90.                             argv[karg] = NULL;
  91.                          };
  92.                          break;
  93.                case 'b': batch = 1;
  94.                          if (isdigit(*(p+1)))
  95.                             batchx = *(++p) - '0';
  96.                          if (isdigit(*(p+1)))
  97.                             batchy = *(++p) - '0';
  98.                          break;
  99.                case 'f': if (*(p+1))
  100.                          {
  101.                             patfile = p++;
  102.                             while (*++p);
  103.                             p--;
  104.                          }
  105.                          else if (++karg<argc)
  106.                          {
  107.                             patfile = argv[karg];
  108.                             argv[karg] = NULL;
  109.                          };
  110.                          break;
  111.                case 'c': countf = 1-countf;
  112.                          break;
  113.                case 'l': linef = 1-linef;
  114.                          break;
  115.                case 'm': mixedc = 1-mixedc;
  116.                          break;
  117.                case 'n': number = 1-number;
  118.                          break;
  119.                case 'v': invert = 1-invert;
  120.                          break;
  121.                case 't': talkf = 1-talkf;
  122.                          break;
  123.                default:  invalid = 1;
  124.             }
  125.       else if (patfile==NULL && pat==NULL)
  126.       {
  127.          pat = argv[karg];
  128.          argv[karg] = NULL;
  129.       };
  130.    };
  131.  
  132.    if ((pat==NULL && patfile==NULL) || (pat!=NULL && patfile!=NULL) || invalid)
  133.    {
  134.       fprintf(stderr,"\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",
  135.       "pgrep 1.10 (1986) by Hern Chen for text and binary files",
  136.       "Usage: pgrep [-mvnlct] [-bxy] {-f pat_file | pattern} file1 file2 ...",
  137.       "       -m,  Mixed,  force match to be case sensitive",
  138.       "       -v,  inVert, print lines that does not match pattern",
  139.       "       -bxy,Btach,  create exec.bat with %1 .. %x file %x+1 .. %x+y",
  140.       "       -n,  Number, don't print line number",
  141.       "       -l,  Line,   don't print the line",
  142.       "       -c,  Count,  don't print match count",
  143.       "       -t,  Trace,  print name before search\n",
  144.       "pattern ::= token [{+, @, |, CR} pattern]",
  145.       "token   ::= [^, {] string [$, }]",
  146.       "            ^ = line begin,    $ = line end,",
  147.       "            { = word boundary, } = word boundary",
  148.       "            + = and, @ = zero or more chars (followed by)",
  149.       "            | = or, CR in pat_file = or, ? = any single char\n",
  150.       "Example:  pgrep \"pgrep|quote+blank|dos}@command\" pgrep.*",
  151.       "          pgrep subroutine *.f \abc\*.f",
  152.       "          pgrep \"objfcn@=\" *.f\n",
  153.       "Note: Enclose blank, |, <, and > in double quotes",
  154.       "      Quote \" by preceeding it with a backslash",
  155.       "      MSDOS removes & from the command line");
  156.       exit (1);
  157.    };
  158.  
  159.    if (patfile!=NULL)
  160.    {
  161.       if ((fp = fopen(patfile,"r"))==NULL)
  162.       {
  163.          fprintf(stderr,"%s: invalid -f spec\n",argv[0]);
  164.          exit (2);
  165.       };
  166.       if (msize==0) msize = 4000;
  167.       pat = malloc(msize);
  168.       for (p=pat; (ch = getc(fp))!=EOF; *p++ = ch);
  169.       *p = '\0';
  170.       fclose(fp);
  171.    };
  172.  
  173.    /* if ignore case then upcase the pattern */
  174.    if (mixedc!=1)
  175.       for (p=pat-1; *++p; *p = toupper(*p));
  176.  
  177.    if (batch && (fp = fopen("exec.bat","w"))==NULL)
  178.    {
  179.       fprintf(stderr,"%s: cannot open 'exec.bat' for output\n",argv[0]);
  180.       exit (3);
  181.    };
  182.  
  183.    nfiles = 0;
  184.    _fmode = 0x8000; /* Binary mode for LATTICE */
  185.    if ((bigbuf = malloc(BIGBUF))==NULL ||
  186.        (src = malloc(MAXLINE+2))==NULL || (src2 = malloc(MAXLINE+2))==NULL)
  187.    {
  188.       fprintf(stderr,"%s: cannot allocate working buffers\n",argv[0]);
  189.       exit (4);
  190.    };
  191.  
  192.    fptr = stdin;
  193.    while (((more=morefile(argc,argv,00,fname))==0 && nfiles==0) ||
  194.           (more==1 && (fptr=fopen(fname,"r"))!=NULL))
  195.    {
  196.        if (talkf) printf("==> Searching file %s\n",fname);
  197.        setvbuf(fptr,bigbuf,_IOFBF,BIGBUF);
  198.        nfiles++;
  199.        nmatch = 0;
  200.        nlines = 0;
  201.        do
  202.        {
  203.           while ((ch=getc(fptr))=='\0');
  204.           for (se=src,p=se+MAXLINE; se<p && ch && ch!=EOF && ch!='\n';
  205.                *se++ = ch, ch=getc(fptr));
  206.           if (ch=='\n' && *(se-1)=='\015') se--;
  207.           *se = '\0';
  208.           nlines++;
  209.  
  210.           if (mixedc==1)
  211.              sb = src;
  212.           else
  213.           {
  214.              sb = src2;
  215.              for (p=src-1, se=src2; *(++p); *se++ = toupper(*p));
  216.              *se = '\0';
  217.           };
  218.  
  219.           if ((((p = patmatch(pat, sb, se))==NULL && invert==1) ||
  220.                 (p!=NULL && invert==0)) && ch!=EOF)
  221.           {
  222.               nmatch++;
  223.               if (linef)
  224.               {
  225.                  for (se=src; *se; se++)
  226.                     if (*se!='\t' && *se!='\014' && iscntrl(*se)) *se='~';
  227.                  if (number==1)
  228.                     printf("%4d: %s\n", nlines, src);
  229.                  else
  230.                     printf("%s\n",src);
  231.               };
  232.           };
  233.        }
  234.        while (ch!=EOF);
  235.        fclose(fptr);
  236.        if (nmatch>0)
  237.        {
  238.           if (countf) printf("----- %d lines from file < %s > -----\n",
  239.                       nmatch, fname);
  240.           if (batch)
  241.           {
  242.              for (i=1; i<=batchx; i++) fprintf(fp," %%%d",i);
  243.              fprintf(fp," %s",fname);
  244.              while (i<=(batchx+batchy)) fprintf(fp," %%%d",i++);
  245.              fprintf(fp,"\n");
  246.           }
  247.        };
  248.    };
  249.    if (batch) fclose(fp);
  250. }
  251.  
  252. #include <dos.h>
  253. int   morefile (argc, argv, mode, fname) /* 1=yes, 0=no, -1=bad spec */
  254. int   argc;
  255. char  *argv[];
  256. int   mode;      /* file attributes to look for e.g. read_only, ...  */
  257. char  *fname;    /* filename may include drive/path                  */
  258. {
  259.    static int karg = 0;
  260.    static struct FILEINFO fileinfo;
  261.    static int wild = 0;
  262.           int more;
  263.           char ch, *f, *p, *t;
  264.  
  265.    more = 1;
  266.    if (wild!=1 || dnext(&fileinfo)!=0)
  267.    {
  268.       while (++karg<argc && (argv[karg]==NULL || (ch=*argv[karg])=='-'
  269.                               || ch=='+' || ch=='/'));
  270.       if (karg>=argc)
  271.       {  
  272.          more = 0;
  273.          strcpy(fname,"stdin");
  274.       }
  275.       else if (dfind(&fileinfo,argv[karg],mode)!=0)
  276.       {
  277.          fprintf(stderr,"%s: no file match <%s>\n", argv[0], argv[karg]);
  278.          more = -1;
  279.       };
  280.    };
  281.  
  282.    if (more==1)
  283.    {
  284.       wild = 0;
  285.       for (f=fname,p=fname,t=argv[karg]; (*f++ = *t);  ++t)
  286.       {
  287.          if (*t==':' || *t=='\\') p = f;
  288.          if (*t=='*' || *t=='?') wild = 1;
  289.       };
  290.       for (t=fileinfo.name; (*p++ = *t++); );
  291.    };
  292.    return (more);
  293. }
  294.  
  295. char      *patmatch(pat, src, se)
  296. char      *pat;
  297. char      *src;
  298. char      *se;
  299.  
  300. /*                                                                      */
  301. /*  patmatch tries to decide whether there is a match of pat in src     */
  302. /*  The pattern is defined as                                           */
  303. /*    pat := pat op pat                                                 */
  304. /*  Allowed op's are                                                    */
  305. /*  + = and, @ = zero or more characters, | or \n = or                  */
  306. /*                                                                      */
  307. /*  pat11+pat12+pat13|pat21|pat31+pat32\0 will match lines contains     */
  308. /*     a. pat11 and pat12 followed by pat13  or                         */
  309. /*     b. pat21                              or                         */
  310. /*     c. pat31 followed by pat32            or                         */
  311. /*  other special characters:                                           */
  312. /*     ^: begin of a line                                               */
  313. /*     $: end of a line                                                 */
  314. /*     {: word boundary                                                 */
  315. /*     }: word boundary                                                 */
  316. /*                                                                      */
  317.  
  318. {
  319.    register char   ch;
  320.             char   *pb;
  321.    register char   *pe;
  322.             char   *pt;
  323.             char   *sb;
  324.             char   *sn;
  325.             int    lpat;
  326.             int    match;
  327.             int    matchi;
  328.             char   lch;
  329.             char   rch;
  330.             char   *strmatch();
  331.  
  332.    match = 0;
  333.    pe = pat-1;
  334.    sb = src;
  335.  
  336.    do
  337.    {
  338.       for (pb = ++pe; (ch = *pe) && ch!=orch && ch!='\n' && ch!=andc
  339.                                  && ch!=arbc; pe++);
  340.       /* check for begining special symbols '^' and '{' */
  341.       if ((lch = *pb)==lbch || lch==lwch) pb++;
  342.  
  343.       /* check for endng special symbols '$' and '}' */
  344.       if ((rch = *(pt=pe-1))!=lech && rch!=rwch) pt++;
  345.  
  346.       
  347.       matchi = 0;
  348.       if ((lpat=pt-pb)<=(se-sb))
  349.       {
  350.          if (lpat>0)
  351.          {
  352.             do
  353.             {
  354.                if ((sn=strmatch(pb, lpat, sb, se))!=NULL)
  355.                {
  356.                   matchi = 1;
  357.                   if ((pt = sn-lpat-1)>=src && (lch==lbch || (lch==lwch
  358.                       && isalnum(*pt)))) matchi = 0;
  359.                   if (sn<se && (rch==lech || (rch==rwch && isalnum(*sn))))
  360.                       matchi = 0;
  361.                   sb = sn;
  362.                }
  363.             }
  364.             while (sn!=NULL && matchi==0);
  365.          }
  366.          else
  367.          {
  368.             matchi = (sb==se);
  369.             sn = se;
  370.          };
  371.       };
  372.  
  373.       if (matchi==1)
  374.       {
  375.          if ((ch = *pe)=='\0' || ch=='\n' || ch==orch)
  376.             match = 1;
  377.          else if (ch==andc)
  378.             sb = src;
  379.          else if (ch==arbc)
  380.             sb = sn;
  381.       }
  382.       else
  383.       {
  384.          while ((ch = *pe) && ch!='\n' && ch!=orch)
  385.             pe++;
  386.          sb = src;
  387.       }
  388.    }
  389.    while (match==0 && *pe);
  390.  
  391.    if (match==0) sn = NULL;
  392.    return (sn);
  393. }
  394.  
  395. char      *strmatch(pat, lpat, src, slast)
  396. char      *pat;
  397. int       lpat;
  398. char      *src;
  399. char      *slast;
  400.  
  401. /*                                                                      */
  402. /*  strmatch tries to find the first exact match of 'pat' in 'src'.     */
  403. /*                                                                      */
  404.  
  405. {
  406.    register char   *sb;
  407.    register char   *pb;
  408.             char   *plast;
  409.             char   *sl;
  410.    register char   *s;
  411.  
  412.  
  413.    sl = slast-lpat;
  414.    plast = pat+lpat;
  415.    sb = src;
  416.    do
  417.    {
  418.       if (*(pb=pat)!=swch)
  419.          while(sb<sl && *sb!=*pb) sb++;
  420.  
  421.       if (*sb++==*pb || *pb==swch)
  422.          for (s=sb; ++pb<plast && (*pb==*s++ || *pb==swch); );
  423.    }
  424.    while (sb<=sl && pb<plast);
  425.  
  426.    return ((pb<plast) ? NULL : s);
  427. }
  428.