home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / SNPD9404.ZIP / JGREP.C < prev    next >
C/C++ Source or Header  |  1994-04-03  |  5KB  |  179 lines

  1. /*
  2. **  JGREP.C - A utility to search files for text.
  3. **
  4. **  public domain by Jerry Coffin
  5. **
  6. **  Link with wildargs.obj (Borland), setargv.obj (Microsoft), _mainX.obj 
  7. **  (Symantech/Zortech), or wildargX.obj (Watcom) which allows you to pass 
  8. **  wildcards on the command line.
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <limits.h>
  15. #include <ctype.h>
  16.  
  17. #define LINELEN 1024
  18. #define BUFSIZE 32767
  19.  
  20. #if defined(_QC) || defined(_MSC_VER)
  21.     void _cdecl _setenvp(void) {}
  22.     void _cdecl _nullcheck(void) {}
  23. #endif
  24.  
  25. enum { FALSE, TRUE };
  26.  
  27. typedef unsigned char uchar;
  28.  
  29. static size_t table[UCHAR_MAX+1];
  30. static size_t len;
  31. static char *string=NULL;
  32.  
  33. void init_find(char *new_string)
  34. {
  35.       size_t i;
  36.  
  37.       if (NULL != string)
  38.             free(string);
  39.       string = strdup(new_string);
  40.       len = strlen(string);
  41.  
  42.       for (i=0;i<=UCHAR_MAX;i++)
  43.             table[i]=len;
  44.       for (i=0;i<len;i++)
  45.             table[string[i]]=len-i-1;
  46. }
  47.  
  48. char *find_case(char *string2)
  49. {
  50.       size_t limit = strlen(string2);
  51.       size_t shift;
  52.       size_t pos=len-1;
  53.       char *here;
  54.  
  55.       while (pos < limit)
  56.       {
  57.             while( pos < limit && (shift=table[(uchar)string2[pos]])>0)
  58.                   pos+=shift;
  59.             if (0==shift)
  60.             {
  61.                   if (!memcmp(string,here=string2+pos-len+1,len))
  62.                         return(here);
  63.                   else  pos++;
  64.             }
  65.       }
  66.       return NULL;
  67. }
  68.  
  69. char *find_no_case(char *string2)
  70. {
  71.       size_t limit = strlen(string2);
  72.       size_t shift;
  73.       size_t pos=len-1;
  74.       char *here;
  75.  
  76.       while (pos < limit)
  77.       {
  78.             while( pos < limit &&
  79.                   (shift=table[(uchar)toupper(string2[pos])])>0)
  80.             {
  81.                   pos+=shift;
  82.             }
  83.             if (0==shift)
  84.             {
  85.                   if (!memicmp(string,here=string2+pos-len+1,len))
  86.                         return(here);
  87.                   else  pos++;
  88.             }
  89.       }
  90.       return NULL;
  91. }
  92.  
  93. char *( *find)    (char *)=find_case;
  94.  
  95. int _cdecl main(int argc, char **argv)
  96. {
  97.       int         k, first;
  98.       unsigned    line;
  99.       int line_numbers=FALSE, reverse=FALSE, print_file_name=FALSE;
  100.       int no_case = TRUE;
  101.       char line_buffer[LINELEN],*string,c;
  102.       FILE *infile=NULL;
  103.       static char buffer[BUFSIZE];
  104.  
  105.       while ((c=argv[1][0])=='/' || c=='-')
  106.       {
  107.             switch(tolower(argv[1][1]))
  108.             {
  109.             case 'c':
  110.             case 'y':
  111.                   no_case=FALSE;
  112.                   break;
  113.  
  114.             case 'f':
  115.                   print_file_name=TRUE;
  116.  
  117.             case 'n':
  118.                   line_numbers=TRUE;
  119.                   break;
  120.  
  121.             case 'v':
  122.                   reverse = TRUE;
  123.                   break;
  124.  
  125.             default:
  126.                   fprintf(stderr,"unknown switch -%c",argv[1][1]);
  127.             }
  128.             argv++;
  129.             argc--;
  130.       }
  131.       if (argc < 3)
  132.       {
  133.             fprintf(stderr ,"\nsyntax: find [-c|y][-n][-v][-f] "
  134.                   "string filename ..."
  135.                   "\n\t-c | -y : make case significant ('c' != 'C')"
  136.                   "\n\t-n      : number lines"
  137.                   "\n\t-f      : place file name before lines ( forces -n)"
  138.                   "\n\t-v      : print lines that don't match"
  139.                   "\n - by itself to read from standard input");
  140.             return(1);
  141.       }
  142.  
  143.       string=argv[1];
  144.       if (no_case)
  145.       {
  146.             strupr(string);
  147.             find=find_no_case;
  148.       }
  149.       init_find(string);
  150.       for (k=2;k<argc;k++)
  151.       {
  152.             if (infile != NULL)
  153.                   fclose(infile);
  154.             if ((infile=fopen(argv[k],"r"))==NULL)
  155.                   continue;
  156.             first=TRUE;
  157.             setvbuf(infile,buffer,_IOFBF,BUFSIZE);
  158.             line=0;
  159.             while (fgets(line_buffer,LINELEN,infile)!=NULL)
  160.             {
  161.                   line ++;
  162.                   if ((NULL!=find(line_buffer)) ^ reverse)
  163.                   {
  164.                         if (first && !print_file_name )
  165.                         {
  166.                               printf("\n\t%s:\n",argv[k]);
  167.                               first = FALSE;
  168.                         }
  169.                         if (print_file_name)
  170.                               printf(" %s ",argv[k]);
  171.                         if (line_numbers)
  172.                               printf("%d:",line);
  173.                         printf("%s",line_buffer);
  174.                   }
  175.             }
  176.       }
  177.       return 0;
  178. }
  179.