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