/* Find Pattern * * This is a program which prints out all lines in a file with a * given pattern. It can be conditionally compiled for either CP/M or * Unix. In either case, it is invoked by: * * fp * * The specification can use normal file widcards, as * defined by wildexp in CP/M and the shell in Unix. * The is a string of characters, some of which have special * meanings: * * - any character not listed below matches exactly that * character. * ? - matches any single character. * * - matches zero or more of any character. * [...] - matches one of any of the characters included between * the brackets; character ranges can also be indicated * by -. E.g., [a-z0-9] will match any * letter or digit. * [-...] - matches one of any of the characters not included * between the brackets. * * Also, backslash (\) can be used to quote characters (i.e., keep them * from being interpreted specially). * * To compile and load the program, make sure that one of UNIX or CPM * is defined (not both!) in fp.c, and that you have pat.h and pat.c (and * wildexp.crl). On CP/M, then do: * * cc1 pat.c * cc1 fp.c * clink fp pat wildexp * * On Unix, then do: * * cc -O -o fp fp.c pat.c * * Note: On Unix, fp runs about three times slower than grep, so it's * not clear why you'd want to use it. This is probably because I use * recursion. Maybe I'll do a non-recursive version later, but this way * is much simpler. * * * Initial coding 8/18/82 by Harry R. Chesley. * * * Copyright 1982 by Harry R. Chesley. * Unlimited permission granted for non-profit use only. */ #include "pat.h" /* UNIX - defined for use on Unix. * CPM - defined for use on CP/M (with BDS-C). * * MAXBSZ - max size of text buffer (big to minimize IO); should be a multiple * of 128 for CPM, but doesn't really have to be. One more char is * allocated so that a zero byte can be appended when printing * strings. * MAXPSZ - max size of pattern string. */ #define UNIX /*#define CPM*/ #define MAXBSZ 10240+1 #define MAXPSZ 100 /* main() * * Function: Invoked by "fp ". Prints every line in * each file containing the pattern. * * Algorithm: Use srchpat() to locate each subsequent line to be output. * * Comments: The only tricky things here are: (1) The search pattern is * surrounded with "*"s because srchpat() will only do exact matches; * inserting the "*"s makes it match the pattern anywhere on the line. And * (2) when we find outselves at the end of a buffer, we read in a new buffer * of text, but keep any partial lines to concatenate with the next buffer * load. * I use puts() in the CP/M version because BDS-C printf breaks on long * lines. I don't use it in the Unix version because Unix puts() appends * newlines to the string. */ main(argc,argv) int argc; char *argv[]; { int fd; /* File descriptor. */ char tbuf[MAXBSZ]; /* Input buffer. */ char pat[MAXPSZ]; /* Search pattern. */ char *pptr; /* Pattern string pointer. */ char *aptr; /* Argv pattern pointer. */ char *nptr; /* New pointer (in copying partials). */ char *tptr; /* Text pointer (while searching). */ char *retstr; /* Srchpat() return value. */ char *eosret; /* EOS pointer return from srchpat(). */ char ctmp; /* Temp storage. */ int sz, osz; /* Bytes remaining sizes. */ #ifdef CPM /* Fake command name. */ argv[0] = "FP"; #endif /* Verify proper calling procedure: */ if (argc < 3) { printf("Usage: %s \n",argv[0]); exit(1); }; /* Copy search pattern, prepend and postpend "*". */ pptr = pat; *pptr++ = '*'; for (aptr = argv[1]; *aptr != 0; *pptr++ = *aptr++); *pptr++ = '*'; *pptr = 0; /* Compile search pattern; normal EOL, ignore case. */ comppat(pat,'\n',TRUE); #ifdef CPM /* Remove search pattern from argv, and expand file names. */ argv[1] = "NOARG"; wildexp(&argc, &argv); #endif /* Go thru the files one by one. */ argc--; argv++; argc--; argv++; /* Skip command name and pattern. */ while (argc-- > 0) { if ((fd = open(argv[0],0)) == -1) { printf("Bad file name: %s!\n",argv[0]); argv++; continue; }; /* Read & write, read & write, ... */ osz = 0; #ifdef UNIX while ((sz = read(fd,tbuf+osz,(MAXBSZ-1)-osz)) > 0) { #endif #ifdef CPM while ((sz = 128*read(fd,tbuf+osz,((MAXBSZ-1)-osz)/128)) > 0){ #endif osz += sz; tptr = tbuf; /* While there's something worth printing. */ while ((retstr = srchpat(tptr,osz,&eosret)) != 0) { ctmp = *eosret; *eosret = 0; #ifdef UNIX printf("%s: %s",argv[0],retstr); #endif #ifdef CPM puts(argv[0]); puts(": "); puts(retstr); #endif *eosret = ctmp; osz -= eosret - tptr; tptr = eosret; }; /* Find partial line at end. */ tptr += osz-1; for (sz = 0; sz != osz; sz++) { if (*tptr == '\n') break; tptr--; }; /* Copy partial. */ tptr++; osz = sz; for (nptr = tbuf; sz != 0; sz--) *nptr++ = *tptr++; }; close(fd); argv++; }; }  .