/* rmatch.c -- Copyright 1994 Liam R. E. Quin. * All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. * * $Id: rmatch.c,v 1.3 2001/05/31 03:50:13 liam Exp $ * * Read matches from a file stream into memory. */ #include "globals.h" /* defines and declarations for database filenames */ #include "error.h" /* curses files are for terminfo variables */ #ifdef CURSESX # include # include #endif #include #include /* for fileinfo.h */ #ifndef FILE # include #endif #ifdef HAVE_STRING_H # include #else # include #endif #ifdef HAVE_STDLIB_H # include #else # include #endif #include "range.h" #include "fileinfo.h" #include "wordinfo.h" #include "wordrules.h" #include "emalloc.h" #include "lqutil.h" #include "liblqtext.h" /** Unix system calls that need declaring: **/ /** Unix/C Library Functions that need declaring: **/ /** lqtext library functions that need declaring: **/ /** Functions within this file that are used before being defined: **/ /** **/ #define TryNumber(ErrorMessage, Variable, p) \ { \ *(Variable) = 0; \ \ if (!isdigit(*(p))) { \ return (ErrorMessage); \ } \ \ while (isdigit(*(p))) { \ *(Variable) *= 10; \ *(Variable) += *(p)++ - '0'; \ } \ \ /* skip trailing space */ \ while (isspace(*(p))) { \ (p)++; \ } \ } \ /* end */ /* * LQT_StringToMatch * Input * *

Converts a string representation of a match to a t_Match object. * Leading and trailing white space on the line is ignored.

*

The match is considered to consist of a number of ASCII decimal * numbers followed by a file name. * The numbers are, in this order, the number of words matched, the * block within the file, the word within the block, and the File * Identifier (t_FID). * There may be an optional filename after the FID.

*

If the FID is given as zero, there must be a filename, and this * is given as an argument to LQT_NameToFID to complete the FID entry * in the match.

* *

The returned Match is contained in a static buffer and should * not be freed or overwritten. You must make a copy if you need to * retain the information over successive calls to LQT_StringToMatch. * The FileName field of the Match will point either into the * middle of the given string, or to an internal static buffer, or, * in the case that the given FID was invalid, will be NULL

*

A static internal buffer is retained containing the previous * result of LQT_NameToFID, for efficiency in the common case that * there are several matches in a row from the same document.

* * *
  • NULL if there was no error; * in that case, *theMatchpp is set to either * a pointer to a Match, or NULL if the line didn't * contain a match.
  • *
  • On error, a string describing the problem is returned. * * */ API char * LQT_StringToMatch(db, Severity, theString, theMatchpp) t_LQTEXT_Database *db; int Severity; char *theString; t_MatchStart **theMatchpp; { register char *p; static t_MatchStart Result; *theMatchpp = (t_MatchStart *) 0; /** eat leading whitespace **/ for (p = theString; *p; p++) { if (isascii(*p) && isspace(*p)) { continue; } else if (*p == '#') { return (char *) 0; } } /** number of words in phrase **/ TryNumber( "Must start with number of words matched", &Result.NumberOfWordsMatched, p ); /** block in file **/ TryNumber( "Second number (block within file) not found", &Result.BlockInFile, p ); /* Word In Block */ TryNumber( "Third number (word within block) not found", &Result.WordInBlock, p ); /** file identifier (FID) **/ TryNumber( "Fourth number (FID = File IDentifier) not found", &Result.FID, p ); /** filename **/ if (!Result.FID && !*p) { return "Must give at least one of FID and filename"; } if (*p) { Result.FileName = p; /* file name, already null-terminated */ while (*p) { p++; } if (*p == '\r') { *p = '\0'; p--; } if (*p == '\n') { *p = '\0'; p--; } } else { Result.FileName = (char *) 0; } if (!Result.FileName || !Result.FID) { static t_FID theFID = 0L; static char *PreviousFileName = 0; t_FileInfo *FileInfo; if (!Result.FID) { /* filename and no FID */ if (PreviousFileName && STREQ(Result.FileName, PreviousFileName)) { Result.FID = theFID; } else { Result.FID = LQT_NameToFID(db, Result.FileName); } } else { /* p is null, FID and no filename */ if (Result.FID == theFID) { Result.FileName = PreviousFileName; } else { FileInfo = LQT_FIDToFileInfo(db, Result.FID); if (!FileInfo) { return "the given FID does not correspond to any indexed file"; } theFID = Result.FID; if (PreviousFileName) { efree(PreviousFileName); } PreviousFileName = Result.FileName = FileInfo->Name; (void) efree((char *) FileInfo); /* don't use LQT_DestroyFileInfo as this woiuld * also free the filename... */ } } } *theMatchpp = &Result; return (char *) NULL; }