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