Annotation of src/usr.bin/m4/trace.c, Revision 1.6
1.6 ! espie 1: /* $OpenBSD: trace.c,v 1.5 2002/04/26 13:12:33 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.1 espie 32: #include "mdef.h"
33: #include "stdd.h"
34: #include "extern.h"
35:
36: FILE *traceout = stderr;
37:
38: int traced_macros = 0;
39:
40: #define TRACE_ARGS 1
41: #define TRACE_EXPANSION 2
42: #define TRACE_QUOTE 4
43: #define TRACE_FILENAME 8
44: #define TRACE_LINENO 16
45: #define TRACE_CONT 32
46: #define TRACE_ID 64
47: #define TRACE_NEWFILE 128 /* not implemented yet */
48: #define TRACE_INPUT 256 /* not implemented yet */
49: #define TRACE_ALL 512
50:
1.2 espie 51: static struct t {
52: struct t *next;
53: char *name;
54: int on;
55: } *l;
1.1 espie 56:
1.4 millert 57: static unsigned int letter_to_flag(int);
58: static void print_header(struct input_file *);
59: static struct t *find_trace_entry(const char *);
60: static int frame_level(void);
1.1 espie 61:
62: static unsigned int flags = TRACE_QUOTE | TRACE_EXPANSION;
63:
1.2 espie 64: static struct t *
1.6 ! espie 65: find_trace_entry(const char *name)
1.2 espie 66: {
67: struct t *n;
68:
69: for (n = l; n != NULL; n = n->next)
70: if (STREQ(n->name, name))
71: return n;
72: return NULL;
73: }
74:
1.1 espie 75:
76: void
1.6 ! espie 77: mark_traced(const char *name, int on)
1.1 espie 78: {
1.2 espie 79: struct t *n, *n2;
1.1 espie 80:
81: traced_macros = 1;
1.2 espie 82:
83: if (name == NULL) {
84: if (on)
85: flags |= TRACE_ALL;
86: else {
87: flags &= ~TRACE_ALL;
88: traced_macros = 0;
89: }
90: for (n = l; n != NULL; n = n2) {
91: n2 = n->next;
92: free(n->name);
93: free(n);
94: }
95: l = NULL;
96: } else {
97: n = find_trace_entry(name);
98: if (n == NULL) {
1.5 espie 99: n = xalloc(sizeof(struct t));
100: n->name = xstrdup(name);
101: n->next = l;
102: l = n;
1.2 espie 103: }
104: n->on = on;
105: }
1.1 espie 106: }
107:
108: int
1.6 ! espie 109: is_traced(const char *name)
1.1 espie 110: {
111: struct t *n;
112:
113: for (n = l; n != NULL; n = n->next)
114: if (STREQ(n->name, name))
1.2 espie 115: return n->on;
116: return (flags & TRACE_ALL) ? 1 : 0;
1.1 espie 117: }
118:
119: void
1.6 ! espie 120: trace_file(const char *name)
1.1 espie 121: {
122:
123: if (traceout != stderr)
124: fclose(traceout);
125: traceout = fopen(name, "w");
126: if (!traceout)
127: err(1, "can't open %s", name);
128: }
129:
130: static unsigned int
1.6 ! espie 131: letter_to_flag(int c)
1.1 espie 132: {
133: switch(c) {
134: case 'a':
135: return TRACE_ARGS;
136: case 'e':
137: return TRACE_EXPANSION;
138: case 'q':
139: return TRACE_QUOTE;
140: case 'c':
141: return TRACE_CONT;
142: case 'x':
143: return TRACE_ID;
144: case 'f':
145: return TRACE_FILENAME;
146: case 'l':
147: return TRACE_LINENO;
148: case 'p':
149: return TRACE_NEWFILE;
150: case 'i':
151: return TRACE_INPUT;
152: case 't':
153: return TRACE_ALL;
154: case 'V':
155: return ~0;
156: default:
157: return 0;
158: }
159: }
160:
161: void
1.6 ! espie 162: set_trace_flags(const char *s)
1.1 espie 163: {
164: char mode = 0;
165: unsigned int f = 0;
166:
167: traced_macros = 1;
168:
169: if (*s == '+' || *s == '-')
170: mode = *s++;
171: while (*s)
172: f |= letter_to_flag(*s++);
173: switch(mode) {
174: case 0:
175: flags = f;
176: break;
177: case '+':
178: flags |= f;
179: break;
180: case '-':
181: flags &= ~f;
182: break;
183: }
184: }
185:
1.3 espie 186: static int
187: frame_level()
188: {
189: int level;
190: int framep;
191:
192: for (framep = fp, level = 0; framep != 0;
193: level++,framep = mstack[framep-2].sfra)
194: ;
195: return level;
196: }
197:
1.1 espie 198: static void
1.6 ! espie 199: print_header(struct input_file *inp)
1.1 espie 200: {
201: fprintf(traceout, "m4trace:");
202: if (flags & TRACE_FILENAME)
203: fprintf(traceout, "%s:", inp->name);
204: if (flags & TRACE_LINENO)
205: fprintf(traceout, "%lu:", inp->lineno);
1.3 espie 206: fprintf(traceout, " -%d- ", frame_level());
1.1 espie 207: if (flags & TRACE_ID)
208: fprintf(traceout, "id %lu: ", expansion_id);
209: }
210:
211: ssize_t
1.6 ! espie 212: trace(const char *argv[], int argc, struct input_file *inp)
1.1 espie 213: {
214: print_header(inp);
215: if (flags & TRACE_CONT) {
216: fprintf(traceout, "%s ...\n", argv[1]);
217: print_header(inp);
218: }
219: fprintf(traceout, "%s", argv[1]);
220: if ((flags & TRACE_ARGS) && argc > 2) {
1.3 espie 221: char delim[3];
1.1 espie 222: int i;
223:
1.3 espie 224: delim[0] = LPAREN;
225: delim[1] = EOS;
1.1 espie 226: for (i = 2; i < argc; i++) {
1.3 espie 227: fprintf(traceout, "%s%s%s%s", delim,
1.1 espie 228: (flags & TRACE_QUOTE) ? lquote : "",
229: argv[i],
230: (flags & TRACE_QUOTE) ? rquote : "");
1.3 espie 231: delim[0] = COMMA;
232: delim[1] = ' ';
233: delim[2] = EOS;
1.1 espie 234: }
235: fprintf(traceout, "%c", RPAREN);
236: }
237: if (flags & TRACE_CONT) {
238: fprintf(traceout, " -> ???\n");
239: print_header(inp);
240: fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]);
241: }
242: if (flags & TRACE_EXPANSION)
243: return buffer_mark();
244: else {
245: fprintf(traceout, "\n");
246: return -1;
247: }
248: }
249:
250: void
1.6 ! espie 251: finish_trace(size_t mark)
1.1 espie 252: {
253: fprintf(traceout, " -> ");
254: if (flags & TRACE_QUOTE)
255: fprintf(traceout, "%s", lquote);
256: dump_buffer(traceout, mark);
257: if (flags & TRACE_QUOTE)
258: fprintf(traceout, "%s", rquote);
259: fprintf(traceout, "\n");
260: }