/**************************************************************************** * * C R U N T I M E G R E P R O U T I N E * ------------------------------------------- * Copyright 1983 by Digital Research Inc. All rights reserved. * * The routine "grep" searches for an ascii character pattern in * a series of files. "Grep" allows the following options: * * OPTION FUNCTION * ------ -------- * -v Print only lines not matching the pattern * -c Print only a count of the lines * -n Print with line numbers * -s Write out the sector number in which the pattern was found * -l Write out a list of the files in which the pattern was found * -y Do not distinguish between upper & lower case * * Calling Sequence: * * grep(options,expression,files); * * Where: * * options Is a pointer to a string of options * expression Is a pointer to the search pattern * files Is an array of pointers to filenames * *****************************************************************************/ /****************************/ /* INCLUDE FILES */ /****************************/ #include /* standard I/O library */ #include /* CP/M portability defines */ #include /* char type definitions */ /****************************/ /* GLOBAL VARIABLES */ /****************************/ GLOBAL BYTE __match = TRUE; /* Print Matching lines only*/ GLOBAL BYTE __count = FALSE; /* Just count the lines */ GLOBAL BYTE __num = FALSE; /* Print line #'s */ GLOBAL BYTE __sector = FALSE; /* Display the sector */ GLOBAL BYTE __list = FALSE; /* Display only a file list */ GLOBAL BYTE __nocase = FALSE; /* Distinguish between cases*/ GLOBAL FILE *fstream; /* file stream ptr */ GLOBAL BYTE line[129]; /* line buffer */ GLOBAL BYTE line1[129]; /* Temp line buffer */ GLOBAL BYTE first = TRUE; /* used on the list option */ GLOBAL UWORD numfound = 0; /* number of lines found */ /****************************/ /* FUNCTIONS */ /****************************/ FILE *fopenb(); /* returns a ptr to a file */ /****************************/ /* MAIN */ main(argc,argv) /* Entry point */ WORD argc; /* = # args */ BYTE **argv; /* -> args */ { /****************************/ BYTE *options; /* Option pointer */ BYTE *expression; /* -> expression */ BYTE **files; /* -> files */ /* */ if(argc < 2) /* Must have at least 2 */ { /* */ usage: printf("Usage: find [-options] pattern files\n"); exit(); /* */ } /****************************/ /* */ options = "-ny"; /* Set up option */ if(*argv[1] == '-') /* Options specified? */ { /* */ options = argv[1]; /* Yes, use them */ if(argc < 3) goto usage; /* check for valid args */ expression = argv[2]; /* -> Pattern */ files = &argv[3]; /* -> file list */ } /****************************/ else { /* No options */ expression = argv[1]; /* Expression */ files = &argv[2]; /* file list */ } /****************************/ return(grep(options,expression,files)); /* Call the real function */ } /* */ /****************************/ grep(options,expression,files) /* */ REG BYTE *options; /* option list */ REG BYTE *expression; /* pattern to search for */ BYTE *files[]; /* array of files */ { /* */ REG BYTE *p; /* temp pointer */ REG UWORD patt_cnt; /* pattern counter */ REG UWORD char_cnt; /* character count */ REG UWORD line_cnt; /* line count */ REG UWORD i; /* counter */ UWORD length; /* length of pattern */ BYTE found; /* set if pattern is found */ /* */ /* */ if(*options != '-') /* Legal option list? */ { /* */ fprintf(stderr,"FIND--Illegal option list: %s\n",options); /* */ exit(-1); /* Just quit */ } /****************************/ while(*options) /* if found ........ */ { /* */ switch(*++options) /* */ { /* */ case 'v' : __match = FALSE; /* print non-matching lines */ break; /* */ case 'c' : __count = TRUE; /* print a count of lines */ break; /* */ case 'n' : __num = TRUE; /* number the lines */ break; /* */ case 's' : __sector= TRUE; /* print sector number */ break; /* */ case 'l' : __list = TRUE; /* list the files */ break; /* */ case 'y' : __nocase= TRUE; /* no case distinction */ /*break;*/ /* */ } /* */ } /* */ /****************************/ if(__list) /* list option has priority */ { /* over these..... */ __count = FALSE; /* */ __num = FALSE; /* */ __sector = FALSE; /* */ } /* */ else /* */ if(__count) /* count option has priority*/ { /* over these..... */ __num = FALSE; /* */ __sector = FALSE; /* */ } /* */ else /* */ if(__num) /* num option has priority */ __sector = FALSE; /* over the sector option */ if(__nocase) /* if no case destinction */ { /* */ p = expression; /* */ while(*p) /* change expression to */ { /* */ *p = toupper(*p); /* upper case letters */ p++; /* */ } /* */ } /* */ length = strlen(expression); /* count the characters in */ /* the pattern to match */ while(*files) /* search all the files */ { /* */ if((fstream = fopenb(*files,"r")) != NULL)/*try to open the file */ { /* */ char_cnt = 0; /* initialize char count */ line_cnt = 0; /* initialize line # count */ numfound = 0; /* initialize # found */ first = TRUE; /* initialize for list */ if(!__list && !__count) /* if these options are not */ { /* ON then print the file- */ printf("\nFILE: %s\n",*files); /* name before each search */ printf("----\n"); /* */ } /* */ while(!feof(fstream)) /* go until end of file */ { /* */ found = FALSE; patt_cnt = 0; /* */ p = expression; /* */ for(i=0;i<129;i++) /* Zap out the buffers */ line[i]=line1[i]=0; /* */ fgets(line1,129,fstream); /* read a line */ /****************************/ for(i = 0;line1[i];i++) /* */ if(__nocase) /* Translate? */ line[i] = toupper(line1[i]);/* */ else /* Don't translate */ line[i] = line1[i]; /* Just copy */ /****************************/ i = 0; /* */ while(line[i]) /* scan until a NULL */ { /* */ char_cnt++; /* bump the char count */ if(line[i] == *p) /* check pattern */ { /* */ p++; /* look for next char */ patt_cnt++; /* we found a character */ if(patt_cnt == length) /* Have we found the end ? */ { /* */ found = TRUE; /* set a flag */ p = expression; /* */ patt_cnt = 0; /* */ } /* */ } /* */ else /* */ { /* */ p = expression; /* reset the pattern ptr */ patt_cnt = 0; /* start the count over */ } /* */ i++; /* check next character */ } /* */ line[i-1] = NULL; /* mask out extra LF */ line_cnt++; /* bump the line count */ prtline(found,char_cnt,line_cnt,files);/*then print routine */ } /* */ if(__count) /* is count option ON ? */ printf("\n%s: %d",*files,numfound);/*print a count of # fnd */ } /* */ fclose(fstream); /* Close the file */ files++; /* go to next file */ } /* */ } /****************************/ /* PRINT ROUTINE */ prtline(found,char_cnt,line_cnt,files) /****************************/ BYTE found; /* does line contain pattern*/ UWORD char_cnt; /* number of chars searched */ UWORD line_cnt; /* number of lines searched */ BYTE *files[]; /* current file */ { /****************************/ if((__match && found) || /* have we a line ? */ (!__match && !found)) /* */ { /* */ numfound++; /* count the # lines found */ if(__count) return; /* nothing to do */ if(__list) /* if the list option */ { /* */ if(first) /* FIRST pattern found ? */ printf("\n%s",*files); /* print the filename */ first = FALSE; /* turn off flag */ return; /* and return.. */ } /* */ if(__sector) /* do we print the sector# ?*/ { /* */ printf("\n%d",char_cnt/128);/* divide count by 128 */ return; /* */ } /* */ if(__num) /* do we print a line # ? */ { /* */ printf("%5d: ",line_cnt); /* */ } /* otherwise..... */ fputs(line1,stdout); /* just print the line */ } /* */ } /****************************/  */ } /****************************/  */ } /****************************/  */ } /****************************/