home *** CD-ROM | disk | FTP | other *** search
- /* 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 <pattern> <file(s)>
- *
- * The <file(s)> specification can use normal file widcards, as
- * defined by wildexp in CP/M and the shell in Unix.
- * The <pattern> is a string of characters, some of which have special
- * meanings:
- *
- * <char> - 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 <char>-<char>. 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 <pattern> <files>". 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 <pattern> <file(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++;
- };
- }