xref: /openbsd-src/usr.bin/m4/trace.c (revision 8445c53715e7030056b779e8ab40efb7820981f2)
1 /* $OpenBSD: trace.c,v 1.1 2001/09/18 14:55:52 espie Exp $ */
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>
31 #include "mdef.h"
32 #include "stdd.h"
33 #include "extern.h"
34 
35 FILE *traceout = stderr;
36 
37 int traced_macros = 0;
38 
39 #define TRACE_ARGS 	1
40 #define TRACE_EXPANSION 2
41 #define TRACE_QUOTE	4
42 #define TRACE_FILENAME	8
43 #define TRACE_LINENO	16
44 #define TRACE_CONT	32
45 #define TRACE_ID	64
46 #define TRACE_NEWFILE	128	/* not implemented yet */
47 #define TRACE_INPUT	256	/* not implemented yet */
48 #define TRACE_ALL	512
49 
50 
51 static unsigned int letter_to_flag __P((int));
52 static void print_header __P((struct input_file *));
53 
54 static unsigned int flags = TRACE_QUOTE | TRACE_EXPANSION;
55 
56 static struct t {
57 	struct t *next;
58 	char 	 *name;
59 } *l;
60 
61 void
62 mark_traced(name)
63 	const char *name;
64 {
65 	struct t *n;
66 
67 	traced_macros = 1;
68 	n = xalloc(sizeof(struct t));
69 	n->name = xstrdup(name);
70 	n->next = l;
71 	l = n;
72 }
73 
74 
75 int
76 is_traced(name)
77 	const char *name;
78 {
79 	struct t *n;
80 
81 	if (flags & TRACE_ALL)
82 		return 1;
83 	for (n = l; n != NULL; n = n->next)
84 		if (STREQ(n->name, name))
85 			return 1;
86 	return 0;
87 }
88 
89 void
90 trace_file(name)
91 	const char *name;
92 {
93 
94 	if (traceout != stderr)
95 		fclose(traceout);
96 	traceout = fopen(name, "w");
97 	if (!traceout)
98 		err(1, "can't open %s", name);
99 }
100 
101 static unsigned int
102 letter_to_flag(c)
103 	int c;
104 {
105 	switch(c) {
106 	case 'a':
107 		return TRACE_ARGS;
108 	case 'e':
109 		return TRACE_EXPANSION;
110 	case 'q':
111 		return TRACE_QUOTE;
112 	case 'c':
113 		return TRACE_CONT;
114 	case 'x':
115 		return TRACE_ID;
116 	case 'f':
117 		return TRACE_FILENAME;
118 	case 'l':
119 		return TRACE_LINENO;
120 	case 'p':
121 		return TRACE_NEWFILE;
122 	case 'i':
123 		return TRACE_INPUT;
124 	case 't':
125 		return TRACE_ALL;
126 	case 'V':
127 		return ~0;
128 	default:
129 		return 0;
130 	}
131 }
132 
133 void
134 set_trace_flags(s)
135 	const char *s;
136 {
137 	char mode = 0;
138 	unsigned int f = 0;
139 
140 	traced_macros = 1;
141 
142 	if (*s == '+' || *s == '-')
143 		mode = *s++;
144 	while (*s)
145 		f |= letter_to_flag(*s++);
146 	switch(mode) {
147 	case 0:
148 		flags = f;
149 		break;
150 	case '+':
151 		flags |= f;
152 		break;
153 	case '-':
154 		flags &= ~f;
155 		break;
156 	}
157 }
158 
159 static void
160 print_header(inp)
161 	struct input_file *inp;
162 {
163 	fprintf(traceout, "m4trace:");
164 	if (flags & TRACE_FILENAME)
165 		fprintf(traceout, "%s:", inp->name);
166 	if (flags & TRACE_LINENO)
167 		fprintf(traceout, "%lu:", inp->lineno);
168 	fprintf(traceout, " -1- ");
169 	if (flags & TRACE_ID)
170 		fprintf(traceout, "id %lu: ", expansion_id);
171 }
172 
173 ssize_t
174 trace(argv, argc, inp)
175 	const char **argv;
176 	int argc;
177 	struct input_file *inp;
178 {
179 	print_header(inp);
180 	if (flags & TRACE_CONT) {
181 		fprintf(traceout, "%s ...\n", argv[1]);
182 		print_header(inp);
183 	}
184 	fprintf(traceout, "%s", argv[1]);
185 	if ((flags & TRACE_ARGS) && argc > 2) {
186 		char delim = LPAREN;
187 		int i;
188 
189 		for (i = 2; i < argc; i++) {
190 			fprintf(traceout, "%c%s%s%s", delim,
191 			    (flags & TRACE_QUOTE) ? lquote : "",
192 			    argv[i],
193 			    (flags & TRACE_QUOTE) ? rquote : "");
194 			delim = COMMA;
195 		}
196 		fprintf(traceout, "%c", RPAREN);
197 	}
198 	if (flags & TRACE_CONT) {
199 		fprintf(traceout, " -> ???\n");
200 		print_header(inp);
201 		fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]);
202 	}
203 	if (flags & TRACE_EXPANSION)
204 		return buffer_mark();
205 	else {
206 		fprintf(traceout, "\n");
207 		return -1;
208 	}
209 }
210 
211 void
212 finish_trace(mark)
213 size_t mark;
214 {
215 	fprintf(traceout, " -> ");
216 	if (flags & TRACE_QUOTE)
217 		fprintf(traceout, "%s", lquote);
218 	dump_buffer(traceout, mark);
219 	if (flags & TRACE_QUOTE)
220 		fprintf(traceout, "%s", rquote);
221 	fprintf(traceout, "\n");
222 }
223