Annotation of src/usr.bin/m4/trace.c, Revision 1.7
1.7 ! espie 1: /* $OpenBSD: trace.c,v 1.6 2002/04/26 16:15:16 espie Exp $ */
1.1 espie 2: /*
3: * Copyright (c) 2001 Marc Espie.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
15: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
18: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: #include <sys/types.h>
28: #include <stddef.h>
29: #include <stdio.h>
30: #include <err.h>
1.2 espie 31: #include <stdlib.h>
1.7 ! espie 32: #include <ohash.h>
1.1 espie 33: #include "mdef.h"
34: #include "stdd.h"
35: #include "extern.h"
36:
37: FILE *traceout = stderr;
38:
39: int traced_macros = 0;
40:
41: #define TRACE_ARGS 1
42: #define TRACE_EXPANSION 2
43: #define TRACE_QUOTE 4
44: #define TRACE_FILENAME 8
45: #define TRACE_LINENO 16
46: #define TRACE_CONT 32
47: #define TRACE_ID 64
48: #define TRACE_NEWFILE 128 /* not implemented yet */
49: #define TRACE_INPUT 256 /* not implemented yet */
50: #define TRACE_ALL 512
51:
1.7 ! espie 52: struct t {
1.2 espie 53: int on;
1.7 ! espie 54: char name[1];
! 55: };
! 56:
1.1 espie 57:
1.4 millert 58: static unsigned int letter_to_flag(int);
59: static void print_header(struct input_file *);
60: static struct t *find_trace_entry(const char *);
61: static int frame_level(void);
1.7 ! espie 62: static void *hash_alloc(size_t, void *);
! 63: static void hash_free(void *, size_t, void *);
! 64: static void *element_alloc(size_t, void *);
1.1 espie 65:
66: static unsigned int flags = TRACE_QUOTE | TRACE_EXPANSION;
67:
1.7 ! espie 68: static struct ohash_info trace_info = {
! 69: offsetof(struct t, name),
! 70: NULL, hash_alloc, hash_free, element_alloc };
! 71:
! 72: static struct ohash trace_hash;
! 73:
! 74: /* Support routines for hash tables. */
! 75: void *
! 76: hash_alloc(s, u)
! 77: size_t s;
! 78: void *u UNUSED;
1.2 espie 79: {
1.7 ! espie 80: void *storage = xalloc(s);
! 81: if (storage)
! 82: memset(storage, 0, s);
! 83: return storage;
! 84: }
! 85:
! 86: void
! 87: hash_free(p, s, u)
! 88: void *p;
! 89: size_t s UNUSED;
! 90: void *u UNUSED;
! 91: {
! 92: free(p);
! 93: }
1.2 espie 94:
1.7 ! espie 95: void *
! 96: element_alloc(s, u)
! 97: size_t s;
! 98: void *u UNUSED;
! 99: {
! 100: return xalloc(s);
1.2 espie 101: }
102:
1.1 espie 103:
104: void
1.7 ! espie 105: init_trace()
! 106: {
! 107: ohash_init(&trace_hash, 5, &trace_info);
! 108: }
! 109:
! 110: void
1.6 espie 111: mark_traced(const char *name, int on)
1.1 espie 112: {
1.7 ! espie 113: struct t *n;
! 114: unsigned int i;
! 115: const char *end = NULL;
1.1 espie 116:
117: traced_macros = 1;
1.2 espie 118:
119: if (name == NULL) {
120: if (on)
121: flags |= TRACE_ALL;
122: else {
123: flags &= ~TRACE_ALL;
124: traced_macros = 0;
125: }
1.7 ! espie 126: for (n = ohash_first(&trace_hash, &i); n != NULL;
! 127: n = ohash_next(&trace_hash, &i))
1.2 espie 128: free(n);
129: } else {
1.7 ! espie 130: i = ohash_qlookupi(&trace_hash, name, &end);
! 131: n = ohash_find(&trace_hash, i);
1.2 espie 132: if (n == NULL) {
1.7 ! espie 133: n = ohash_create_entry(&trace_info, name, &end);
! 134: ohash_insert(&trace_hash, i, n);
1.2 espie 135: }
136: n->on = on;
137: }
1.1 espie 138: }
139:
140: int
1.6 espie 141: is_traced(const char *name)
1.1 espie 142: {
143: struct t *n;
144:
1.7 ! espie 145: n = ohash_find(&trace_hash, ohash_qlookup(&trace_hash, name));
! 146: if (n)
! 147: return n->on;
! 148: else
! 149: return (flags & TRACE_ALL) ? 1 : 0;
1.1 espie 150: }
151:
152: void
1.6 espie 153: trace_file(const char *name)
1.1 espie 154: {
155:
156: if (traceout != stderr)
157: fclose(traceout);
158: traceout = fopen(name, "w");
159: if (!traceout)
160: err(1, "can't open %s", name);
161: }
162:
163: static unsigned int
1.6 espie 164: letter_to_flag(int c)
1.1 espie 165: {
166: switch(c) {
167: case 'a':
168: return TRACE_ARGS;
169: case 'e':
170: return TRACE_EXPANSION;
171: case 'q':
172: return TRACE_QUOTE;
173: case 'c':
174: return TRACE_CONT;
175: case 'x':
176: return TRACE_ID;
177: case 'f':
178: return TRACE_FILENAME;
179: case 'l':
180: return TRACE_LINENO;
181: case 'p':
182: return TRACE_NEWFILE;
183: case 'i':
184: return TRACE_INPUT;
185: case 't':
186: return TRACE_ALL;
187: case 'V':
188: return ~0;
189: default:
190: return 0;
191: }
192: }
193:
194: void
1.6 espie 195: set_trace_flags(const char *s)
1.1 espie 196: {
197: char mode = 0;
198: unsigned int f = 0;
199:
200: traced_macros = 1;
201:
202: if (*s == '+' || *s == '-')
203: mode = *s++;
204: while (*s)
205: f |= letter_to_flag(*s++);
206: switch(mode) {
207: case 0:
208: flags = f;
209: break;
210: case '+':
211: flags |= f;
212: break;
213: case '-':
214: flags &= ~f;
215: break;
216: }
217: }
218:
1.3 espie 219: static int
220: frame_level()
221: {
222: int level;
223: int framep;
224:
225: for (framep = fp, level = 0; framep != 0;
226: level++,framep = mstack[framep-2].sfra)
227: ;
228: return level;
229: }
230:
1.1 espie 231: static void
1.6 espie 232: print_header(struct input_file *inp)
1.1 espie 233: {
234: fprintf(traceout, "m4trace:");
235: if (flags & TRACE_FILENAME)
236: fprintf(traceout, "%s:", inp->name);
237: if (flags & TRACE_LINENO)
238: fprintf(traceout, "%lu:", inp->lineno);
1.3 espie 239: fprintf(traceout, " -%d- ", frame_level());
1.1 espie 240: if (flags & TRACE_ID)
241: fprintf(traceout, "id %lu: ", expansion_id);
242: }
243:
244: ssize_t
1.6 espie 245: trace(const char *argv[], int argc, struct input_file *inp)
1.1 espie 246: {
247: print_header(inp);
248: if (flags & TRACE_CONT) {
249: fprintf(traceout, "%s ...\n", argv[1]);
250: print_header(inp);
251: }
252: fprintf(traceout, "%s", argv[1]);
253: if ((flags & TRACE_ARGS) && argc > 2) {
1.3 espie 254: char delim[3];
1.1 espie 255: int i;
256:
1.3 espie 257: delim[0] = LPAREN;
258: delim[1] = EOS;
1.1 espie 259: for (i = 2; i < argc; i++) {
1.3 espie 260: fprintf(traceout, "%s%s%s%s", delim,
1.1 espie 261: (flags & TRACE_QUOTE) ? lquote : "",
262: argv[i],
263: (flags & TRACE_QUOTE) ? rquote : "");
1.3 espie 264: delim[0] = COMMA;
265: delim[1] = ' ';
266: delim[2] = EOS;
1.1 espie 267: }
268: fprintf(traceout, "%c", RPAREN);
269: }
270: if (flags & TRACE_CONT) {
271: fprintf(traceout, " -> ???\n");
272: print_header(inp);
273: fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]);
274: }
275: if (flags & TRACE_EXPANSION)
276: return buffer_mark();
277: else {
278: fprintf(traceout, "\n");
279: return -1;
280: }
281: }
282:
283: void
1.6 espie 284: finish_trace(size_t mark)
1.1 espie 285: {
286: fprintf(traceout, " -> ");
287: if (flags & TRACE_QUOTE)
288: fprintf(traceout, "%s", lquote);
289: dump_buffer(traceout, mark);
290: if (flags & TRACE_QUOTE)
291: fprintf(traceout, "%s", rquote);
292: fprintf(traceout, "\n");
293: }