/* query.c -- Copyright 1996 Liam R. Quin. * All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. */ /* * Match a query including wildcard support * * $Id: lqquery.c,v 1.5 2001/05/31 03:50:13 liam Exp $ * */ #include "error.h" #include "globals.h" /* defines and declarations for database filenames */ #ifndef FILE # include /* stderr, also for fileinfo.h */ #endif #include #ifdef HAVE_SYSV_FCNTL_H # include #endif #ifdef HAVE_FCNTL_H #include #endif #include #ifdef HAVE_STRING_H # include #else # include #endif #ifdef HAVE_STDLIB_H # include #else # include #endif #include "emalloc.h" /* for efree() */ #include "fileinfo.h" /* for wordinfo.h */ #include "wordinfo.h" #include "pblock.h" #include "phrase.h" #include "lqutil.h" #include "liblqtext.h" #include "lqtrace.h" /** **/ API t_Phrase *LQT_QueryToPhraseKludge( #ifdef HAVE_PROTO t_LQTEXT_Database *db, t_LQT_Query *Query #endif ); int OneMatch( #ifdef HAVE_PROTO t_LQTEXT_Database *db, t_Phrase *Phrase, t_Match *Match #endif ); PRIVATE t_Range *RangeOfMatchesToPrint = 0; PRIVATE t_Range *RangeOfFilesToPrint = 0; int main(argc, argv) int argc; char *argv[]; { extern int optind, getopt(); extern char *optarg; int ch; int ErrorFlag = 0; t_lqdbOptions *Options; t_LQTEXT_Database *db = 0; progname = argv[0]; Options = LQT_InitFromArgv(argc, argv); while ((ch = getopt(argc, argv, "o:O:Zz:xv")) != EOF) { switch (ch) { case 'o': RangeOfMatchesToPrint = LQU_StringToRange(optarg); break; case 'O': RangeOfFilesToPrint = LQU_StringToRange(optarg); break; case 'z': case 'Z': break; /* done by LQT_InitFromArgv(); */ case 'x': ErrorFlag = (-1); break; case '?': ErrorFlag = 1; } } if (ErrorFlag) { fprintf(stderr, "Usage: %s [options] \"query\" [...]\n", progname); fprintf(stderr, "\ -o range - print only matches falling within the given range\n\ -O range - print only matches in documents within the given range\n" ); LQT_PrintDefaultUsage(Options); exit( ErrorFlag > 0 ? 1 : 0); /* 0 means -x was used */ } db = LQT_OpenDatabase(Options, O_RDONLY, 0); if (!db || LQT_ObtainReadOnlyAccess(db) < 0) { Error(E_FATAL, "couldn't open lq-text database"); } while (optind < argc) { t_Phrase *thePhrase; register char *p; t_LQT_Query *oneQuery; thePhrase = (t_Phrase *) 0; oneQuery = (t_LQT_Query *) 0; for (p = argv[optind]; *p; p++) { if (*p == '*' || *p == '?') { oneQuery = LQT_ParseQuery(db, argv[optind]); if (oneQuery) { thePhrase = LQT_QueryToPhraseKludge(db, oneQuery); } break; } } if (!thePhrase) { thePhrase = LQT_StringToPhrase(db, argv[optind]); } if (thePhrase) { (void) LQT_MakeMatchesWhere( db, thePhrase, OneMatch ); if (!oneQuery) { /* don't do this if it's a query, because * LQT_QueryToPhraseKludge probably doesn't make * a valid phrase structure yet. Sigh. */ LQT_DestroyPhrase(db, thePhrase); } } optind++; } return 0; } static long FileNumber = 0, MatchNumber = 0; static t_FID lastFID = (t_FID) -1; int OneMatch(db, Phrase, Match) t_LQTEXT_Database *db; t_Phrase *Phrase; t_Match *Match; { if (RangeOfFilesToPrint) { if (Match->Where->FID != lastFID) { lastFID = Match->Where->FID; ++FileNumber; if (!LQU_NumberWithinRange(FileNumber, RangeOfFilesToPrint)) { if (LQU_LargerThanRangeTop(FileNumber, RangeOfFilesToPrint)) { exit(0); } return LQMATCH_REJECT; /* don't save in memory */ } } } if (RangeOfMatchesToPrint) { ++MatchNumber; if (!LQU_NumberWithinRange(MatchNumber, RangeOfMatchesToPrint)) { if (LQU_LargerThanRangeTop(MatchNumber, RangeOfMatchesToPrint)) { exit(0); } return LQMATCH_REJECT; } } return LQT_PrintAndRejectOneMatch(db, Phrase, Match); }