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