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