X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/dd3c57bc8cac59e0d657ee665ce462988d27d714..18c831dcd0ae4d660c70ccac69d27ed2a97851be:/trace/trace.c diff --git a/trace/trace.c b/trace/trace.c new file mode 100644 index 0000000..2681cd3 --- /dev/null +++ b/trace/trace.c @@ -0,0 +1,212 @@ +/* -*-c-*- + * + * Tracing functions for debugging + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +/* --- ANSI headers --- */ + +#include +#include +#include +#include +#include + +/* --- Local headers --- */ + +#include "dstr.h" +#include "quis.h" +#include "trace.h" + +/*----- Private state information -----------------------------------------*/ + +static void (*tracefunc)(const char *buf, size_t sz, void *v) = 0; +static void *tracearg; +static unsigned tracelvl = 0; /* How much tracing gets done? */ + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @t_file@ --- * + * + * Arguments: @const char *buf@ = buffer to print + * @size_t sz@ = buffer size + * @void *v@ = file handle + * + * Returns: --- + * + * Use: Dumps tracing information to a file. + */ + +static void t_file(const char *buf, size_t sz, void *v) +{ + FILE *fp = v; + fprintf(fp, "+ %s: ", QUIS); + fwrite(buf, 1, sz, fp); + fputc('\n', fp); +} + +/* --- @trace@ --- * + * + * Arguments: @unsigned l@ = trace level for output + * @const char *f@ = a @printf@-style format string + * @...@ = other arguments + * + * Returns: --- + * + * Use: Reports a message to the trace output. + */ + +void trace(unsigned l, const char *f, ...) +{ + va_list ap; + dstr d = DSTR_INIT; + if ((l & tracing()) == 0) + return; + va_start(ap, f); + dstr_vputf(&d, f, &ap); + va_end(ap); + tracefunc(d.buf, d.len, tracearg); + dstr_destroy(&d); +} + +/* --- @trace_block@ --- * + * + * Arguments: @unsigned l@ = trace level for output + * @const char *s@ = some header string to write + * @const void *b@ = pointer to a block of memory to dump + * @size_t sz@ = size of the block of memory + * + * Returns: --- + * + * Use: Dumps the contents of a block to the trace output. + */ + +void trace_block(unsigned l, const char *s, const void *b, size_t sz) +{ + const unsigned char *p = b; + size_t i; + unsigned long o = 0; + dstr d = DSTR_INIT; + size_t c; + + /* --- Skip if the trace level is too high --- */ + + if ((l & tracing()) == 0) + return; + + /* --- Now start work --- */ + + tracefunc(s, strlen(s), tracearg); + while (sz) { + dstr_reset(&d); + dstr_putf(&d, " %08lx : ", o); + for (i = 0; i < 8; i++) { + if (i < sz) + dstr_putf(&d, "%02x ", p[i]); + else + dstr_puts(&d, "** "); + } + dstr_puts(&d, ": "); + for (i = 0; i < 8; i++) { + if (i < sz) + dstr_putc(&d, isprint(p[i]) ? p[i] : '.'); + else + dstr_putc(&d, '*'); + } + dstr_putz(&d); + tracefunc(d.buf, d.len, tracearg); + c = (sz >= 8) ? 8 : sz; + sz -= c, p += c, o += c; + } + dstr_destroy(&d); +} + +/* --- @trace_on@ --- * + * + * Arguments: @FILE *fp@ = a file to trace on + * @unsigned l@ = trace level to set + * + * Returns: --- + * + * Use: Enables tracing to a file. + */ + +void trace_on(FILE *fp, unsigned l) +{ + tracefunc = t_file; + tracearg = fp; + if (!tracelvl) + tracelvl = l; +} + +/* --- @trace_custom@ --- * + * + * Arguments: @void (*func)(const char *buf, size_t sz, void *v)@ = + * output function + * @void *v@ = magic handle to give to function + * + * Returns: --- + * + * Use: Sets up a custom trace handler. + */ + +void trace_custom(void (*func)(const char */*buf*/, + size_t /*sz*/, void */*v*/), + void *v) +{ + tracefunc = func; + tracearg = v; +} + +/* --- @trace_level@ --- * + * + * Arguments: @unsigned l@ = trace level to set + * + * Returns: --- + * + * Use: Sets the tracing level. + */ + +void trace_level(unsigned l) +{ + tracelvl = l; +} + +/* --- @tracing@ --- * + * + * Arguments: --- + * + * Returns: Zero if not tracing, tracing level if tracing. + * + * Use: Informs the caller whether tracing is enabled. + */ + +unsigned tracing(void) +{ + return (tracefunc ? tracelvl : 0u); +} + +/*----- That's all, folks -------------------------------------------------*/