home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 316.lha / LookFor_v1.0 / LookFor.c < prev    next >
C/C++ Source or Header  |  1989-12-04  |  10KB  |  453 lines

  1. /*
  2.  
  3.                             LookFor Version 1.0
  4.                       Copyright © 1989 by Ray Lambert
  5.                            Created by Ray Lambert
  6.  
  7.          Searches for the specified string (either ASCII or HEX) in
  8.            the specified file(s) and displays absolute offset in
  9.          file where string is located, and approximate line number.
  10.  
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <ctype.h>
  16. #include <libraries/dos.h>
  17. #include <exec/memory.h>
  18. #include <proto/exec.h>
  19.  
  20. #define FALSE 0
  21. #define TRUE 1
  22. #define iswhite(c) (((c)=='\t')||((c)==' '))
  23.  
  24. unsigned char   /* global switches */
  25.   hex_search=FALSE,
  26.   ignore_case=FALSE,
  27.   text_mode=FALSE;
  28.  
  29. int
  30.    count,
  31.    bytes; /* number of bytes in search string */
  32.  
  33. unsigned int
  34.    line,
  35.    j,
  36.    size;
  37.  
  38. char
  39.    path[255],
  40.    name[255],
  41.    orig_pattern[100],
  42.    pattern[100];
  43.  
  44. char *buf=NULL;
  45.  
  46. struct FileInfoBlock *info;
  47.  
  48. FILE *f;
  49.  
  50. extern int msflag;
  51.  
  52. /** ********* **/
  53.  
  54. void clean_exit(char *message, int xcode)
  55. {
  56.   if (buf) FreeMem(buf,size);
  57.   if (info) FreeMem(info,sizeof(struct FileInfoBlock));
  58.   if (message) printf("\n%s\n",message);
  59.   printf("\n");
  60.   exit(xcode);
  61. }
  62.  
  63. /** ********* **/
  64.  
  65. void make_hex(char *S)
  66. {
  67.   char lookup[] = "0123456789ABCDEF";
  68.   int cnt=1;  /* indexes characters in S */
  69.   int i;      /* \ Used in building */
  70.   int n;      /* / Hex bytes        */
  71.  
  72.   strupr(S);
  73.  
  74.   for(j=0; S[cnt]; j++)
  75.     {
  76.       if (!isxdigit(S[cnt]))
  77.         clean_exit("\23333mInvalid digit in Hex String\2330m",5);
  78.       i=0;    /* Get first digit */
  79.       while( (i<16) && (S[cnt]!=lookup[i]) ) i++;
  80.       n=(i<<4);
  81.       cnt++;
  82.       if (S[cnt])  /* Get second digit */
  83.         {
  84.           i=0;
  85.           while( (i<16) && (S[cnt]!=lookup[i]) ) i++;
  86.           n|=i;
  87.           orig_pattern[j]=(char)n;
  88.           cnt++;
  89.         }
  90.     }
  91.  
  92.   orig_pattern[j]='\0';
  93.   hex_search=TRUE;
  94. }
  95.  
  96. /** ********* **/
  97.  
  98. void get_buffer()
  99. {
  100.   size=0x20000;
  101.  
  102.   info=AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR);
  103.   if (!info)
  104.     {
  105.       clean_exit("\23333mInsufficient memory!\nLookFor halted.\2330m",21);
  106.     }
  107.  
  108.   do
  109.     {
  110.       buf=(char *)AllocMem(size,MEMF_CLEAR);
  111.       if (!buf)
  112.         {
  113.           size-=0x0400;
  114.           if (size<0x0400)
  115.             {
  116.               clean_exit("\23333mInsufficient memory!\nLookFor halted.\2330m",21);
  117.             }
  118.         }
  119.     }
  120.   while(!buf);
  121. }
  122.  
  123. /** ********* **/
  124.  
  125. void extract_path(char *n)
  126. {
  127.   register char *c=path;
  128.  
  129.   strcpy(path,n);
  130.   c+=(strlen(c)-1);
  131.   while( (c>path) && (*c!='/') && (*c!=':') ) c--;
  132.   if (c<=path)
  133.     {
  134.       *path='\0';
  135.     }
  136.   else
  137.     {
  138.       c++;
  139.       *c='\0';
  140.     }
  141. }
  142.  
  143. /** ********* **/
  144.  
  145. void set_msflag(char *n)
  146. {
  147.   while(*n)
  148.     {
  149.       if (*n=='*')
  150.         {
  151.           msflag=1;
  152.           return;
  153.         }
  154.       n++;
  155.     }
  156.   msflag=0;
  157. }
  158.  
  159. /** ********* **/
  160.  
  161. int match(char *wild)
  162. {
  163.   int status;
  164.  
  165.   if (name[0]=='\0')  /* find first */
  166.     {
  167.       extract_path(wild);
  168.       set_msflag(wild);
  169.       status=dfind(info,wild,1);
  170.       if (status) printf("\nNo match for: '%s'\n",wild);
  171.     }
  172.   else    /* find next */
  173.     {
  174. skipdir:
  175.       status=dnext(info);
  176.     }
  177.  
  178.   if (status==0)
  179.     {
  180.       if (info->fib_DirEntryType > 0) /* a directory */
  181.         {
  182.           goto skipdir;
  183.         }
  184.       strcpy(name,path);
  185.       strcat(name,info->fib_FileName);
  186.     }
  187.   return(!status);
  188. }
  189.  
  190. /** ********* **/
  191.  
  192. #define LINE_LEN 50 /* maximum length of line of text that can be printed */
  193.  
  194. void print_line(char *line, char *match)
  195. {
  196.   int lead=((LINE_LEN-bytes)>>1);
  197.   char *c=(match-lead);
  198.   char str[LINE_LEN+1];
  199.   int cnt=0;  /* count of characters that have been placed in string */
  200.  
  201.   if (c<line) c=line;
  202.   line=str;
  203.  
  204.   while(iswhite(*c)) c++; /* strip leading white space */
  205.  
  206.   while( (cnt<=LINE_LEN) && (*c) && (*c!='\n') )
  207.     {
  208.       if (isprint(*c))
  209.         {
  210.           *line=*c;
  211.           line++;
  212.           cnt++;
  213.         }
  214.       c++;
  215.     }
  216.   *line='\0';
  217.  
  218.   printf("\"%s\"\n",str);
  219. }
  220.  
  221. /** ********* **/
  222.  
  223. char search()
  224. {
  225.   unsigned long int pos;  /* actual file position at read-time */
  226.   unsigned long int temp; /* used to calculate offset for report */
  227.   unsigned int red;       /* holds number of bytes read by Read() */
  228.   char *top;              /* last byte to search at */
  229.   char *P;                /* used to scan the buffer */
  230.   char test;              /* the actual byte from the file to test */
  231.   char firsttime=TRUE;    /* flag for error conditions */
  232.   char *lastline;         /* tracks beginning of text line for printing */
  233.  
  234.   strcpy(pattern,orig_pattern);
  235.   if (ignore_case) strupr(pattern);
  236.  
  237.   line=1;
  238.   count=0;
  239.   pos=0;
  240.  
  241.   do
  242.     {
  243.       if (pos>0) fseek(f,pos,0);
  244.       red=fread(buf,1,size,f);
  245.       if (red<1)
  246.         {
  247.           if (firsttime)  /* couldn't read on first try - error */
  248.             {
  249.               return(FALSE);
  250.             }
  251.           else  /* reached EOF */
  252.             {
  253.               return(TRUE);
  254.             }
  255.         }
  256.  
  257.       firsttime=FALSE;
  258.       top=buf+(red-(bytes-1));
  259.       P=buf;
  260.  
  261.       do
  262.         {
  263.           test=(ignore_case)?toupper(*P):*P;
  264.  
  265.         /* scan for match of first character */
  266.           while( (test!=pattern[0]) && (P<=top) )
  267.             {
  268.               if (*P=='\n')
  269.                 {
  270.                   line++;
  271.                   lastline=(P+1);
  272.                 }
  273.               P++;
  274.               test=(ignore_case)?toupper(*P):*P;
  275.             }
  276.  
  277.         /* first character matches - now check rest of pattern */
  278.           if (P<=top)
  279.             {
  280.               j=0;
  281.               do
  282.                 {
  283.                   j++;
  284.                   test=(ignore_case)?toupper(*(P+j)):*(P+j);
  285.                 }
  286.               while( (test==pattern[j]) && (j<bytes) );
  287.  
  288.               if (j>=bytes) /* found a match! */
  289.                 {
  290.                   count++;
  291.                   temp=(pos+((unsigned long int)P-(unsigned long int)buf));
  292.                   printf("  Found match at offset %07lu ($%06lX)\n",temp,temp);
  293.                   if (text_mode)
  294.                     {
  295.                       printf("    Line #%u: ",line);
  296.                       print_line(lastline,P);
  297.                     }
  298.                 }
  299.  
  300.               P++;
  301.             }
  302.         }
  303.       while(P<=top);
  304.       pos+=(size-(bytes-1));
  305.     }
  306.   while(red==size);
  307.   return(TRUE);
  308. }
  309.  
  310. /** ********* **/
  311.  
  312. void usage()
  313. {
  314.   printf("\n\2333mUsage:\2330m  LookFor SEARCHSTRING [OPTIONS ] FILE [FILE...]\n");
  315.   printf("\n  All command-line arguments must be seperated by at least one\n");
  316.   printf("    space character.  Arguments which contain spaces must be\n");
  317.   printf("    enclosed in quotes.\n");
  318.   printf("\n  SEARCHSTRING: can be ASCII, eg. \"This is an ASCII string\"\n");
  319.   printf("                    or HEX, eg. $1A2B3C4D5E6F\n");
  320.   printf("\n  OPTIONS: May be mixed between filenames.\n");
  321.   printf("      Options are turned ON if they are prefixed with a '+' (plus)\n");
  322.   printf("      and are turned OFF if prefixed with a '-' (minus)\n");
  323.   printf("    Current valid options are:\n");
  324.   printf("        +I  Ignore case ON (HEX searches are always case sensitive)\n");
  325.   printf("        -I  Ignore case OFF (This is the default)\n");
  326.   printf("        +T  Text mode ON (Report matched line # and line)\n");
  327.   printf("        -T  Text mode OFF (This is the default)\n");
  328.   printf("\n  FILE: Multiple complete filenames are allowed and each may\n");
  329.   printf("      contain either AmigaDOS or MS-DOS wildcards.\n");
  330.   clean_exit(NULL,5);
  331. }
  332.  
  333. /** ********* **/
  334.  
  335. void process_switch(char *sw)
  336. {
  337.   switch(sw[0])
  338.     {
  339.       case '-':
  340.         {
  341.           switch(toupper(sw[1]))
  342.             {
  343.               case 'I':
  344.                 {
  345.                   ignore_case=FALSE;
  346.                   break;
  347.                 }
  348.               case 'T':
  349.                 {
  350.                   text_mode=FALSE;
  351.                   break;
  352.                 }
  353.             }
  354.           break;
  355.         }
  356.       case '+':
  357.         {
  358.           switch(toupper(sw[1]))
  359.             {
  360.               case 'I':
  361.                 {
  362.                   ignore_case=TRUE;
  363.                   break;
  364.                 }
  365.               case 'T':
  366.                 {
  367.                   text_mode=TRUE;
  368.                   break;
  369.                 }
  370.             }
  371.           break;
  372.         }
  373.     }
  374. }
  375.  
  376. /** ********* **/
  377.  
  378. void main(int argc,char *argv[])
  379. {
  380.   int cnt=2;
  381.   printf("\n\23333m\2333mLookFor\2330m\23332m  Copyright © 1989 by Ray Lambert\n");
  382.   printf("         Created by Ray Lambert\2330m\n");
  383.  
  384.   if (argc<3) usage();
  385.  
  386.   if (argv[1][0]=='$')
  387.     {
  388.       make_hex(argv[1]);
  389.     }
  390.   else
  391.     {
  392.       strcpy(orig_pattern,argv[1]);
  393.     }
  394.  
  395.   bytes=strlen(orig_pattern);
  396.  
  397.   get_buffer();  /* allocate work buffer */
  398.  
  399.   do      /* search loop */
  400.     {
  401.       if ( (argv[cnt][0]=='-') || (argv[cnt][0]=='+') )
  402.         {
  403.           process_switch(argv[cnt]);
  404.           continue;
  405.         }
  406.  
  407.       name[0]='\0'; /* initialize global search name (flag a findfirst) */
  408.  
  409.       while(match(argv[cnt]))
  410.         {
  411.           f=fopen(name,"rt");
  412.           if (f)
  413.             {
  414.               printf("\nSearching file: '%s'\n",name);
  415.               if (!search())
  416.                 {
  417.                   printf("    \23333mCan't read this file!\2330m\n");
  418.                 }
  419.               else
  420.                 {
  421.                   switch(count)
  422.                     {
  423.                       case 0:
  424.                         {
  425.                           printf("No matches found\n");
  426.                           break;
  427.                         }
  428.                       case 1:
  429.                         {
  430.                           printf("One match found\n");
  431.                           break;
  432.                         }
  433.                       default:
  434.                         {
  435.                           printf("%d matches found in file: '%s'\n",count,name);
  436.                           break;
  437.                         }
  438.                     }
  439.                 }
  440.               fclose(f);
  441.             }
  442.           else
  443.             {
  444.               printf("\n\23333mError opening file: '%s'\2330m\n",name);
  445.             }
  446.         }
  447.     }
  448.   while((++cnt)<argc);
  449.  
  450.   clean_exit("All files searched.",0);
  451. }
  452.  
  453.