/* This program, SEARCH, is used to search a "database" for * matches to a user supplied set of strings. The match function implemented * is the OR case. Others may be added later if it does not too severly * detract from the usefulness of the program. * * SEARCH functions similart to the excellent public domain utility FIND. The * major difference is that SEARCH will display multiple lines (a record) when * a pattern match is made. SEARCH is valuable for accessing information * entered in a random database. * * The term "database" is used very loosely. Database, here, refers to a * loose collection of information. The program expects to see * a "database" bound together in the form of records. Records, here is * also defined very loosely. For our purposes a record is a collection * of ASCII text separated from other ASCII text by a record delimiter. The * record delimiter, itself, is a predefined sequence of ASCII text or a blank * line. * The main reason we keep everything in ASCII is so that the database can be * created, modified, and searched using very primitive tools. The tools we * will need are a simple editor to create and modify the database, and the * program SEARCH for searching and extracting information from the database. * * ENVIRONMENT: * The program was written and compiled using Aztec C on a CP/M 80 system. * * Copyright notice: * This program is Copyrighted by Don Finley (May 1985) * It is released into the public domain for all to freely use. * It may be freely given away, but must not be sold for commercial gain * without the author's permission. * I ask only that should you find bugs in the program or add enhancements * please let me know. In the case of enhancements, I would appreciate getting * a copy. RBBS 615-229-4488 300/1200 bps, 24 hrs. * * Don L. Finley * 310 Willow St. * MT. Carmel, TN 37642 (615) 357-3355 * */ #include "fcntl.h" #include "stdio.h" #include "ctype.h" #include "sgtty.h" #define MAXCHR 2048 /* maximum size of record */ #define MAXLINE 50 /* maximum number of lines in a record */ #define RECMARK "--" /* delimiter between records */ #define MAXWIDE 256 /* maximum width of a line */ #define TRUE 1 #define FALSE 0 #define PHANTOM '_' /* phantom space */ char *string[MAXLINE]; /* pointers to strings */ char *tl; /* pointer to cat'ed string shifted to lower case */ int chrcnt; char *frag[MAXLINE]; /* fragments to search for */ int no_frags; /* number of fragments */ int incname; /* flag to include file names */ int recno; struct sgttyb stty; FILE *fopen(),*fd; main(argc,argv) int argc; char **argv; { int rec_len; int i,hit,j,k,kf; int forhit; char *p,*strlow(); no_frags=0; recno=1; forhit=FALSE; incname=FALSE; chrcnt=MAXCHR; if(argc < 2) error(1); /* not enough arguments */ for(j=1;j MAXLINE)error(2); } if(lcount)return lcount; if(feof(fd))return -1; return 0; } /*************************** strlow(() **********************/ /* copy string p to string s while shifting s to lower case */ /* remove excess spaces */ /* replace phantom character with space */ /* replace punctuation with space */ /* strip starting spaces */ /* add trailing space */ char *strlow(s,p) char *s,*p; { char c,flag; flag=FALSE; if(!*p)return (s); while(*p == ' ' || isspace(*p) || isperiod(*p) )p++; while(*p && chrcnt){ c=tolower(*p); if( isperiod(c) || isspace(c)) c=' '; if(!((c==' ') && (flag == ' '))){ *s++=c; chrcnt--; } flag=c; p++; } if(!chrcnt) return (0); /* about to overflow buffer */ if(c != ' ')*s++=' '; *s=0; return s; } isperiod(c) char c; { if(c == '.' || c == ',' || c == ';' || c == '?' || c == PHANTOM || c == ':' ) return TRUE; return FALSE; } force_con() { if(!isatty(stdout))freopen("con:","w",stdout); } /*************************** usage () ***************************/ usage() { force_con(); /* force output to console */ puts(""); puts("--- Program to look for string matches in files ---"); puts(" Copyright Don L. Finley May, 1985 Mt. Carmel, TN"); puts(" Released into the public domain for non commerial distribution."); puts(""); puts("The files should contain freeform ASCII text grouped as records."); printf("A record is defined as up to %d lines separated by a\n",MAXLINE); printf("record delimiter. The record delimiter is a line beginning\n"); printf("with the special sequence %s or a blank line.\n\n",RECMARK); puts("USAGE: SEARCH file.ext FOR word1 word2 word3 etc "); puts(" file.ext can be one or more valid file name(s). NO wildcards."); puts(" FOR separates the file names from the word fragments to match."); puts(" word(s) can be any valid ASCII strings. Spaces separate words."); puts(" The underline character '_' can be used as a phantom space."); puts(" i.e. to search for 4 mhz, enter the string as: 4_mhz"); puts("OPTIONS:"); puts(" -N include file name in output."); puts(" to send output to a file, specify output file name as >file."); exit(); } /*************************** left() *************************/ /* determine if two strings start the same */ left(s,p) char *s,*p; { for( ; *p; p++, s++){ if(*s != *p)break; } if(*p)return FALSE; return TRUE; } /*************************** error() *************************/ /* Error function */ error(n) int n; { fprintf(stderr,"Error. "); switch(n){ case 1 : usage(); abort(); case 2 : fprintf(stderr,"\nToo many lines in record."); fprintf(stderr," Maximum of %d allowed\n",MAXLINE); abort(); case 3 : fprintf(stderr,"Unable to allocate required memory.\n"); abort(); case 4 : fprintf(stderr,"No FOR directive encountered.\n"); abort(); case 5 : fprintf(stderr,"No string fragments to search for.\n"); abort(); case 6 : fprintf(stderr,"Unknown OPTION.\n"); abort(); case 8 : fprintf(stderr,"Too many characters in record #%d.\n",recno); fprintf(stderr,"Maximum of ( %d) permitted.\n",MAXCHR); abort(); default : puts("Unrecognized error number "); abort(); } } abort() { exit(1); } /************************** pri_rec() *****************************/ /* Print record. Most always 'cause we got a match */ pri_rec(s,n,fname,flg) char **s,*fname; int n; { int i; if(flg){ printf("---- File --> %s ---------\n",fname); } else{ puts(""); } for(i=0;i