chiark / gitweb /
2681cd32e456c6f621f96862ea1fac993f21d324
[mLib] / trace.c
1 /* -*-c-*-
2  *
3  * Tracing functions for debugging
4  *
5  * (c) 1998 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 /* --- ANSI headers --- */
31
32 #include <ctype.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 /* --- Local headers --- */
39
40 #include "dstr.h"
41 #include "quis.h"
42 #include "trace.h"
43
44 /*----- Private state information -----------------------------------------*/
45
46 static void (*tracefunc)(const char *buf, size_t sz, void *v) = 0;
47 static void *tracearg;
48 static unsigned tracelvl = 0;           /* How much tracing gets done? */
49
50 /*----- Functions provided ------------------------------------------------*/
51
52 /* --- @t_file@ --- *
53  *
54  * Arguments:   @const char *buf@ = buffer to print
55  *              @size_t sz@ = buffer size
56  *              @void *v@ = file handle
57  *
58  * Returns:     ---
59  *
60  * Use:         Dumps tracing information to a file.
61  */
62
63 static void t_file(const char *buf, size_t sz, void *v)
64 {
65   FILE *fp = v;
66   fprintf(fp, "+ %s: ", QUIS);
67   fwrite(buf, 1, sz, fp);
68   fputc('\n', fp);
69 }
70
71 /* --- @trace@ --- *
72  *
73  * Arguments:   @unsigned l@ = trace level for output
74  *              @const char *f@ = a @printf@-style format string
75  *              @...@ = other arguments
76  *
77  * Returns:     ---
78  *
79  * Use:         Reports a message to the trace output.
80  */
81
82 void trace(unsigned l, const char *f, ...)
83 {
84   va_list ap;
85   dstr d = DSTR_INIT;
86   if ((l & tracing()) == 0)
87     return;
88   va_start(ap, f);
89   dstr_vputf(&d, f, &ap);
90   va_end(ap);
91   tracefunc(d.buf, d.len, tracearg);
92   dstr_destroy(&d);
93 }
94
95 /* --- @trace_block@ --- *
96  *
97  * Arguments:   @unsigned l@ = trace level for output
98  *              @const char *s@ = some header string to write
99  *              @const void *b@ = pointer to a block of memory to dump
100  *              @size_t sz@ = size of the block of memory
101  *
102  * Returns:     ---
103  *
104  * Use:         Dumps the contents of a block to the trace output.
105  */
106
107 void trace_block(unsigned l, const char *s, const void *b, size_t sz)
108 {
109   const unsigned char *p = b;
110   size_t i;
111   unsigned long o = 0;
112   dstr d = DSTR_INIT;
113   size_t c;
114
115   /* --- Skip if the trace level is too high --- */
116
117   if ((l & tracing()) == 0)
118     return;
119
120   /* --- Now start work --- */
121
122   tracefunc(s, strlen(s), tracearg);
123   while (sz) {
124     dstr_reset(&d);
125     dstr_putf(&d, "   %08lx : ", o);
126     for (i = 0; i < 8; i++) {
127       if (i < sz)
128         dstr_putf(&d, "%02x ", p[i]);
129       else
130         dstr_puts(&d, "** ");
131     }
132     dstr_puts(&d, ": ");
133     for (i = 0; i < 8; i++) {
134       if (i < sz)
135         dstr_putc(&d, isprint(p[i]) ? p[i] : '.');
136       else
137         dstr_putc(&d, '*');
138     }
139     dstr_putz(&d);
140     tracefunc(d.buf, d.len, tracearg);
141     c = (sz >= 8) ? 8 : sz;
142     sz -= c, p += c, o += c;
143   }
144   dstr_destroy(&d);
145 }
146
147 /* --- @trace_on@ --- *
148  *
149  * Arguments:   @FILE *fp@ = a file to trace on
150  *              @unsigned l@ = trace level to set
151  *
152  * Returns:     ---
153  *
154  * Use:         Enables tracing to a file.
155  */
156
157 void trace_on(FILE *fp, unsigned l)
158 {
159   tracefunc = t_file;
160   tracearg = fp;
161   if (!tracelvl)
162     tracelvl = l;
163 }
164
165 /* --- @trace_custom@ --- *
166  *
167  * Arguments:   @void (*func)(const char *buf, size_t sz, void *v)@ =
168  *                      output function
169  *              @void *v@ = magic handle to give to function
170  *
171  * Returns:     ---
172  *
173  * Use:         Sets up a custom trace handler.
174  */
175
176 void trace_custom(void (*func)(const char */*buf*/,
177                                size_t /*sz*/, void */*v*/),
178                   void *v)
179 {
180   tracefunc = func;
181   tracearg = v;
182 }
183
184 /* --- @trace_level@ --- *
185  *
186  * Arguments:   @unsigned l@ = trace level to set
187  *
188  * Returns:     ---
189  *
190  * Use:         Sets the tracing level.
191  */
192
193 void trace_level(unsigned l)
194 {
195   tracelvl = l;
196 }
197
198 /* --- @tracing@ --- *
199  *
200  * Arguments:   ---
201  *
202  * Returns:     Zero if not tracing, tracing level if tracing.
203  *
204  * Use:         Informs the caller whether tracing is enabled.
205  */
206
207 unsigned tracing(void)
208 {
209   return (tracefunc ? tracelvl : 0u);
210 }
211
212 /*----- That's all, folks -------------------------------------------------*/