xref: /freebsd/usr.bin/m4/trace.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
1a841e1ebSBaptiste Daroussin /* $OpenBSD: trace.c,v 1.16 2010/09/07 19:58:09 marco Exp $ */
2e3d86717SJuli Mallett /*
3*1de7b4b8SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause
4*1de7b4b8SPedro F. Giffuni  *
5e3d86717SJuli Mallett  * Copyright (c) 2001 Marc Espie.
6e3d86717SJuli Mallett  *
7e3d86717SJuli Mallett  * Redistribution and use in source and binary forms, with or without
8e3d86717SJuli Mallett  * modification, are permitted provided that the following conditions
9e3d86717SJuli Mallett  * are met:
10e3d86717SJuli Mallett  * 1. Redistributions of source code must retain the above copyright
11e3d86717SJuli Mallett  *    notice, this list of conditions and the following disclaimer.
12e3d86717SJuli Mallett  * 2. Redistributions in binary form must reproduce the above copyright
13e3d86717SJuli Mallett  *    notice, this list of conditions and the following disclaimer in the
14e3d86717SJuli Mallett  *    documentation and/or other materials provided with the distribution.
15e3d86717SJuli Mallett  *
16e3d86717SJuli Mallett  * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
17e3d86717SJuli Mallett  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18e3d86717SJuli Mallett  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19e3d86717SJuli Mallett  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
20e3d86717SJuli Mallett  * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21e3d86717SJuli Mallett  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22e3d86717SJuli Mallett  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23e3d86717SJuli Mallett  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24e3d86717SJuli Mallett  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25e3d86717SJuli Mallett  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26e3d86717SJuli Mallett  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27e3d86717SJuli Mallett  */
28acc9d408SJuli Mallett #include <sys/cdefs.h>
29e3d86717SJuli Mallett #include <err.h>
30a841e1ebSBaptiste Daroussin #include <stddef.h>
31a841e1ebSBaptiste Daroussin #include <stdint.h>
32a841e1ebSBaptiste Daroussin #include <stdio.h>
33e3d86717SJuli Mallett #include <stdlib.h>
34e3d86717SJuli Mallett #include "mdef.h"
35e3d86717SJuli Mallett #include "stdd.h"
36e3d86717SJuli Mallett #include "extern.h"
37e3d86717SJuli Mallett 
38acc9d408SJuli Mallett FILE *traceout;
39e3d86717SJuli Mallett 
40e3d86717SJuli Mallett #define TRACE_ARGS	1
41e3d86717SJuli Mallett #define TRACE_EXPANSION 2
42e3d86717SJuli Mallett #define TRACE_QUOTE	4
43e3d86717SJuli Mallett #define TRACE_FILENAME	8
44e3d86717SJuli Mallett #define TRACE_LINENO	16
45e3d86717SJuli Mallett #define TRACE_CONT	32
46e3d86717SJuli Mallett #define TRACE_ID	64
47e3d86717SJuli Mallett #define TRACE_NEWFILE	128	/* not implemented yet */
48e3d86717SJuli Mallett #define TRACE_INPUT	256	/* not implemented yet */
49e3d86717SJuli Mallett 
50e3d86717SJuli Mallett static unsigned int letter_to_flag(int);
51e3d86717SJuli Mallett static void print_header(struct input_file *);
52e3d86717SJuli Mallett static int frame_level(void);
53e3d86717SJuli Mallett 
54e3d86717SJuli Mallett 
55a841e1ebSBaptiste Daroussin unsigned int trace_flags = TRACE_QUOTE | TRACE_EXPANSION;
56e3d86717SJuli Mallett 
57e3d86717SJuli Mallett void
trace_file(const char * name)58bd2bfb58SJuli Mallett trace_file(const char *name)
59e3d86717SJuli Mallett {
60e3d86717SJuli Mallett 
61a841e1ebSBaptiste Daroussin 	if (traceout && traceout != stderr)
62e3d86717SJuli Mallett 		fclose(traceout);
63e3d86717SJuli Mallett 	traceout = fopen(name, "w");
64e3d86717SJuli Mallett 	if (!traceout)
65e3d86717SJuli Mallett 		err(1, "can't open %s", name);
66e3d86717SJuli Mallett }
67e3d86717SJuli Mallett 
68e3d86717SJuli Mallett static unsigned int
letter_to_flag(int c)69bd2bfb58SJuli Mallett letter_to_flag(int c)
70e3d86717SJuli Mallett {
71e3d86717SJuli Mallett 	switch(c) {
72e3d86717SJuli Mallett 	case 'a':
73e3d86717SJuli Mallett 		return TRACE_ARGS;
74e3d86717SJuli Mallett 	case 'e':
75e3d86717SJuli Mallett 		return TRACE_EXPANSION;
76e3d86717SJuli Mallett 	case 'q':
77e3d86717SJuli Mallett 		return TRACE_QUOTE;
78e3d86717SJuli Mallett 	case 'c':
79e3d86717SJuli Mallett 		return TRACE_CONT;
80e3d86717SJuli Mallett 	case 'x':
81e3d86717SJuli Mallett 		return TRACE_ID;
82e3d86717SJuli Mallett 	case 'f':
83e3d86717SJuli Mallett 		return TRACE_FILENAME;
84e3d86717SJuli Mallett 	case 'l':
85e3d86717SJuli Mallett 		return TRACE_LINENO;
86e3d86717SJuli Mallett 	case 'p':
87e3d86717SJuli Mallett 		return TRACE_NEWFILE;
88e3d86717SJuli Mallett 	case 'i':
89e3d86717SJuli Mallett 		return TRACE_INPUT;
90e3d86717SJuli Mallett 	case 't':
91e3d86717SJuli Mallett 		return TRACE_ALL;
92e3d86717SJuli Mallett 	case 'V':
93e3d86717SJuli Mallett 		return ~0;
94e3d86717SJuli Mallett 	default:
95e3d86717SJuli Mallett 		return 0;
96e3d86717SJuli Mallett 	}
97e3d86717SJuli Mallett }
98e3d86717SJuli Mallett 
99e3d86717SJuli Mallett void
set_trace_flags(const char * s)100bd2bfb58SJuli Mallett set_trace_flags(const char *s)
101e3d86717SJuli Mallett {
102e3d86717SJuli Mallett 	char mode = 0;
103e3d86717SJuli Mallett 	unsigned int f = 0;
104e3d86717SJuli Mallett 
105e3d86717SJuli Mallett 	if (*s == '+' || *s == '-')
106e3d86717SJuli Mallett 		mode = *s++;
107e3d86717SJuli Mallett 	while (*s)
108e3d86717SJuli Mallett 		f |= letter_to_flag(*s++);
109e3d86717SJuli Mallett 	switch(mode) {
110e3d86717SJuli Mallett 	case 0:
111a841e1ebSBaptiste Daroussin 		trace_flags = f;
112e3d86717SJuli Mallett 		break;
113e3d86717SJuli Mallett 	case '+':
114a841e1ebSBaptiste Daroussin 		trace_flags |= f;
115e3d86717SJuli Mallett 		break;
116e3d86717SJuli Mallett 	case '-':
117a841e1ebSBaptiste Daroussin 		trace_flags &= ~f;
118e3d86717SJuli Mallett 		break;
119e3d86717SJuli Mallett 	}
120e3d86717SJuli Mallett }
121e3d86717SJuli Mallett 
122e3d86717SJuli Mallett static int
frame_level(void)123d1fea89cSJuli Mallett frame_level(void)
124e3d86717SJuli Mallett {
125e3d86717SJuli Mallett 	int level;
126e3d86717SJuli Mallett 	int framep;
127e3d86717SJuli Mallett 
128e3d86717SJuli Mallett 	for (framep = fp, level = 0; framep != 0;
129a841e1ebSBaptiste Daroussin 		level++,framep = mstack[framep-3].sfra)
130e3d86717SJuli Mallett 		;
131e3d86717SJuli Mallett 	return level;
132e3d86717SJuli Mallett }
133e3d86717SJuli Mallett 
134e3d86717SJuli Mallett static void
print_header(struct input_file * inp)135bd2bfb58SJuli Mallett print_header(struct input_file *inp)
136e3d86717SJuli Mallett {
137e3d86717SJuli Mallett 	fprintf(traceout, "m4trace:");
138a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_FILENAME)
139e3d86717SJuli Mallett 		fprintf(traceout, "%s:", inp->name);
140a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_LINENO)
141e3d86717SJuli Mallett 		fprintf(traceout, "%lu:", inp->lineno);
142e3d86717SJuli Mallett 	fprintf(traceout, " -%d- ", frame_level());
143a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_ID)
144e3d86717SJuli Mallett 		fprintf(traceout, "id %lu: ", expansion_id);
145e3d86717SJuli Mallett }
146e3d86717SJuli Mallett 
147a841e1ebSBaptiste Daroussin size_t
trace(const char * argv[],int argc,struct input_file * inp)148bd2bfb58SJuli Mallett trace(const char *argv[], int argc, struct input_file *inp)
149e3d86717SJuli Mallett {
150a841e1ebSBaptiste Daroussin 	if (!traceout)
151a841e1ebSBaptiste Daroussin 		traceout = stderr;
152e3d86717SJuli Mallett 	print_header(inp);
153a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_CONT) {
154e3d86717SJuli Mallett 		fprintf(traceout, "%s ...\n", argv[1]);
155e3d86717SJuli Mallett 		print_header(inp);
156e3d86717SJuli Mallett 	}
157e3d86717SJuli Mallett 	fprintf(traceout, "%s", argv[1]);
158a841e1ebSBaptiste Daroussin 	if ((trace_flags & TRACE_ARGS) && argc > 2) {
159e3d86717SJuli Mallett 		char delim[3];
160e3d86717SJuli Mallett 		int i;
161e3d86717SJuli Mallett 
162e3d86717SJuli Mallett 		delim[0] = LPAREN;
163e3d86717SJuli Mallett 		delim[1] = EOS;
164e3d86717SJuli Mallett 		for (i = 2; i < argc; i++) {
165e3d86717SJuli Mallett 			fprintf(traceout, "%s%s%s%s", delim,
166a841e1ebSBaptiste Daroussin 			    (trace_flags & TRACE_QUOTE) ? lquote : "",
167e3d86717SJuli Mallett 			    argv[i],
168a841e1ebSBaptiste Daroussin 			    (trace_flags & TRACE_QUOTE) ? rquote : "");
169e3d86717SJuli Mallett 			delim[0] = COMMA;
170e3d86717SJuli Mallett 			delim[1] = ' ';
171e3d86717SJuli Mallett 			delim[2] = EOS;
172e3d86717SJuli Mallett 		}
173e3d86717SJuli Mallett 		fprintf(traceout, "%c", RPAREN);
174e3d86717SJuli Mallett 	}
175a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_CONT) {
176e3d86717SJuli Mallett 		fprintf(traceout, " -> ???\n");
177e3d86717SJuli Mallett 		print_header(inp);
178e3d86717SJuli Mallett 		fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]);
179e3d86717SJuli Mallett 	}
180a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_EXPANSION)
181e3d86717SJuli Mallett 		return buffer_mark();
182e3d86717SJuli Mallett 	else {
183e3d86717SJuli Mallett 		fprintf(traceout, "\n");
184a841e1ebSBaptiste Daroussin 		return SIZE_MAX;
185e3d86717SJuli Mallett 	}
186e3d86717SJuli Mallett }
187e3d86717SJuli Mallett 
188e3d86717SJuli Mallett void
finish_trace(size_t mark)189bd2bfb58SJuli Mallett finish_trace(size_t mark)
190e3d86717SJuli Mallett {
191e3d86717SJuli Mallett 	fprintf(traceout, " -> ");
192a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_QUOTE)
193e3d86717SJuli Mallett 		fprintf(traceout, "%s", lquote);
194e3d86717SJuli Mallett 	dump_buffer(traceout, mark);
195a841e1ebSBaptiste Daroussin 	if (trace_flags & TRACE_QUOTE)
196e3d86717SJuli Mallett 		fprintf(traceout, "%s", rquote);
197e3d86717SJuli Mallett 	fprintf(traceout, "\n");
198e3d86717SJuli Mallett }
199