/* trace.c -- Copyright 1994, 1995, 1996 Liam R. E. Quin. * All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. * * $Id: trace.c,v 1.9 2001/05/31 03:50:13 liam Exp $ * * Tracing for lq-text */ #include "globals.h" /* defines and declarations for database filenames */ #include "error.h" #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 "fileinfo.h" #include "wordinfo.h" #include "wordrules.h" #include "emalloc.h" #include "lqutil.h" #include "liblqtext.h" #include "lqtrace.h" t_TraceFlag LQTp_AsciiTraceLevel = 0; /** 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: **/ /** **/ static t_FlagNamePair LQTpTraceFlagArray[] = { { LQTRACE_VERBOSE, "Verbose" }, { LQTRACE_DEBUG, "Debug" }, { LQTRACE_READBLOCK, "ReadBlock" }, { LQTRACE_WRITEBLOCK, "WriteBlock" }, { LQTRACE_PUTPLACES, "PutPlaces" }, { LQTRACE_GETPLACES, "GetPlaces" }, { LQTRACE_WORDROOT, "WordRoot" }, { LQTRACE_READWORD, "ReadWord" }, { LQTRACE_ADDWORD, "AddWord" }, { LQTRACE_ABORT_ON_ERROR, "AbortOnError" }, { LQTRACE_CLOSE_ON_ERROR, "CloseOnError" }, { LQTRACE_BLOCKDUMP, "BlockDump" }, { LQTRACE_FINDFILE, "FindFile" }, { LQTRACE_WORDINFO, "WordInfo" }, { LQTRACE_READAFTERWRITE, "ReadAfterWrite" }, { LQTRACE_BLOCKCACHE, "BlockCache" }, { LQTRACE_WIDCACHE, "WidCache" }, { LQTRACE_FREEBLOCKS, "FreeBlocks" }, { LQTRACE_FID_ALLOC, "FIDAlloc" }, { LQTRACE_FINDMATCH, "FindMatch" }, { LQTRACE_MAKE_PHRASE, "MakePhrase" }, { LQTRACE_MATCH_PHRASE, "MatchPhrase" }, { LQTRACE_LASTBLOCK, "LastBlock" }, { LQTRACE_TERM_EXPANSION, "TermExpansion" }, { LQTRACE_FILTER_DATA, "FilterData" }, { 0L, "none" }, { 0L, (char *) 0 } }; /* * LQT_TraceFlagsSet * Tracing * * Determines whether any of a particular group of trace flags * are set; if so, a non-zero value is returned, otherwise zero. * The flags may have been or'd together, and are defined in * the lqtrace.h header file. For each such flag, all of * the bits set in the flag have been be set in the argument to * LQT_TraceFlags in order for it to be considered as being set. * * non-zero if one or more flags satisfies the constraints * * This may be implemented as a macro; the prototype shown may in * that case have a different name. * * LQT_Trace * LQT_SetTraceFlag * LQT_UnSetTraceFlag * LQT_GetTraceFlags * */ LIBRARY int LQTp_TraceFlagsSet(QueryFlags) t_TraceFlag QueryFlags; { t_FlagNamePair *wp; int i; for (i = 0; (wp = &LQTpTraceFlagArray[i])->Name; i++) { if ((QueryFlags & wp->Value) == wp->Value) { if (wp->Value) { return i + 1; } } } return 0; } /* * LQT_ForEachTraceFlag * Tracing * *

Calls the given function for each available trace flag. * The integer argument IsSet passed to the function is non-zero for * those flags that are set in the current trace flags, and zero * for the others.

*

The flags are defined in the lqtrace.h header file.

* * zero. * * LQT_Trace * LQT_SetTraceFlag *
*/ API int LQT_ForEachTraceFlag(CallMe) void (* CallMe)( #ifdef HAVE_PROTO char *Name, unsigned int Value, int isSet #endif ); { int i; for (i = 0; LQTpTraceFlagArray[i].Name; i++) { int amSet = ( LQTpTraceFlagArray[i].Value && ( LQT_TraceFlagsSet(LQTpTraceFlagArray[i].Value) != 0 ) ); (* CallMe) ( LQTpTraceFlagArray[i].Name, LQTpTraceFlagArray[i].Value, amSet ); } return 0; } /* * LQT_GetTraceFlagsAsString * Tracing * *

Returns a static pointer to a string representation of the * current lq-text trace flags. * This is suitable for printing in error messages, and can also be * used with LQT_SetTraceFlagsFromString to save and restore flags in * a machine-independent way.

*

The caller should not attempt to write into, or free, * the result string.

*

The flags are defined in the lqtrace.h header file.

* * a pointer to a private string. * * LQT_Trace * LQT_SetTraceFlag * LQT_UnSetTraceFlag * LQT_GetGivenTraceFlagsAsString * LQT_SetTraceFlagsFromString *
*/ API char * LQT_GetTraceFlagsAsString() { return LQT_FlagsToString(LQTp_AsciiTraceLevel, LQTpTraceFlagArray, "|"); } /* * LQT_GetGivenTraceFlagsAsString * Tracing * *

This function works like LQT_GetTraceFlagsAsString, except that it * uses the given flags instead of the current value of the lq-text * trace flags.

*

The caller should not attempt to write into, or free, * the result string.

*

The flags are defined in the lqtrace.h header file.

* * non-zero if one or more flags satisfies the constraints * * You can get a rather long line giving all possible flags using * the C expression (t_TraceFlag) ~(unsigned long) 0, which provides a * number with all bits set, as an argument to * LQT_GetGivenTraceFlagsAsString. * * LQT_Trace * LQT_SetTraceFlag * LQT_GetTraceFlags * LQT_GetTraceFlagsAsString *
*/ API char * LQT_GetGivenTraceFlagsAsString(Flags) t_TraceFlag Flags; { return LQT_FlagsToString((unsigned long) Flags, LQTpTraceFlagArray, "|"); } /* * LQT_GetTraceFlags * Tracing * *

Returns the current value of the lq-text trace flags. * The various flag values are defined in the lqtrace.h header * file, and may be combined (using bitwise or) in any combination.

*

The value returned by LQT_GetTraceFlags should not normally be used * by itself in diagnostic or error messages. * Instead, use LQT_GetTraceFlagsAsString, which provides a more * readable value for humans.

* * the current lq-text trace flags, or'd together * * LQT_Trace * LQT_SetTraceFlag * LQT_UnSetTraceFlag * LQT_SetTraceFlagsFromString *
*/ API t_TraceFlag LQT_GetTraceFlags() { return LQTp_AsciiTraceLevel; } /* * LQT_SetTraceFlag * Tracing * *

Adds the given argument to the current lq-text trace flags. * You can add several flags at a time by combining them with * bitwise or. * If you do, the return value may be hard to decipher, although * since the return value is primarily of interest to internal * liblqtext routines, this probably doesn't matter. * * non-zero if any of the the given flags were set. * * LQT_Trace * LQT_UnSetTraceFlag * LQT_GetTraceFlags * */ API t_TraceFlag LQT_SetTraceFlag(theFlag) t_TraceFlag theFlag; { t_TraceFlag FlagWasSet = LQT_TraceFlagsSet(theFlag); LQTp_AsciiTraceLevel |= theFlag; return FlagWasSet; } /* * LQT_UnSetTraceFlag * Tracing * *

The given flag is removed from the current lq-text trace flags. * You can combine multiple flag values using bitwise or.

*

This routine can be used in conjunction with LQT_GetTraceFlags to * unset all of the current flags.

* * 1 if any of the given flags were set, and 0 otherwise. * * An attempt to unset flags that were not set produces an error * of type E_WARN|E_INTERNAL. * * LQT_Trace * LQT_GetTraceFlags * LQT_SetTraceFlagsFromString *
*/ API int LQT_UnSetTraceFlag(theFlag) t_TraceFlag theFlag; { int FirstFlagSet; if (!theFlag) { Error(E_WARN|E_INTERNAL, "LQT_UnSetTraceFlag(0) makes no sense"); return 0; } FirstFlagSet = LQT_TraceFlagsSet(theFlag); if (!FirstFlagSet) { Error(E_WARN|E_INTERNAL, "LQT_UnSetTraceFlag(%u: %s), flags not set", theFlag, LQT_GetTraceFlagsAsString() ); LQTp_AsciiTraceLevel &= ~theFlag; /* just in case... */ return 0; } else { LQTp_AsciiTraceLevel &= ~theFlag; return 1; } } /* * LQT_SetTraceFlagsFromString * Tracing * *

Attempts to set the lq-text trace flags by reading a string * representation of them. * The string must be in the format produced by LQT_GetTraceFlagsAsString; * in other words, a sequence of words separated by the vertical bar. * The various flag values are defined in the lqtrace.h header * file, and may be combined (using bitwise or) in any combination

*

If the return value points to a NUL byte, the end of the string * was reached without error; otherwise, it is up to the caller to * determine whether the extra unconverted text was expected. * * a pointer to the first unconverted character in the given string * * LQT_Trace * LQT_SetTraceFlag * LQT_GetTraceFlagsAsString * LQT_StringToFlags * */ API char * LQT_SetTraceFlagsFromString(theString) char *theString; { return LQT_StringToFlags( theString, &LQTp_AsciiTraceLevel, LQTpTraceFlagArray, "|" ); } static FILE *TraceFile; /* * LQT_SetTraceFile * Tracing * *

After this call, all lq-text tracing output produced with LQT_Trace * will be sent to the given file. * It is the caller's responsibility to ensure that the given FILE * is * valid and points to a file that is open for writing.

*

The default file used before LQT_SetTraceFile has been called is * stderr. * An argument of (FILE *) NULL will reset the file to the default value, * but will not close the given stream. * The file is also not when a database is closed; * see LQT_AddActionOnClose for a way of changing this behaviour.

* * the previous file pointer * * LQT_Trace * LQT_SetTraceFlag * LQT_AddActionOnClose *
*/ API FILE * LQT_SetTraceFile(newFile) FILE *newFile; { FILE *oldFile = TraceFile; if (newFile) { TraceFile = newFile; } else { TraceFile = stderr; } return oldFile; } /* * LQT_Trace * Tracing * *

Prints diagnostic messages. * The Flags argument must be one or more flags * taken from lqtrace.h and combined with bitwise or. * If one of more of the given Flags is set in the current lq-text * trace flags, the remainder of the arguments are passed to fprintf

*

For efficiency, it may be best to use LQT_TraceFlagsSet first * to determine whether to call LQT_Trace, as the former is likely * to be implemented as a short macro in lqtrace.h, but * currently LQT_Trace cannot be so implemented.

*

Each line of trace output is preceded by the current program name, * the word `trace', and a string representation of * one or more of those flags in the Flags argument to LQT_Trace which * are set in the current lqtext trace flags.

* * LQT_SetTraceFlag * LQT_UnSetTraceFlag * LQT_SetTraceFlagsFromString *
*/ API void LQT_Trace(Flags, Format, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) t_TraceFlag Flags; char *Format; { int FirstFlagSet = LQT_TraceFlagsSet(Flags); if (FirstFlagSet > 0) { register char *p; for (p = Format; *p; p++) { if (*p == '\n') { break; } } /* Show only first trace flag that matched: */ if (LQTpTraceFlagArray[FirstFlagSet - 1].Value == LQTRACE_VERBOSE) { (void) fprintf(stderr, "%s: ", progname ); } else { (void) fprintf(stderr, "%s: <%s>: ", progname, LQTpTraceFlagArray[FirstFlagSet - 1].Name ); } fprintf(stderr, Format, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); if (*p != '\n') { fputc('\n', stderr); } (void) fflush(stderr); } }