1 |
|
|
/* $OpenBSD: trace.c,v 1.16 2010/09/07 19:58:09 marco 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 <err.h> |
28 |
|
|
#include <stddef.h> |
29 |
|
|
#include <stdint.h> |
30 |
|
|
#include <stdio.h> |
31 |
|
|
#include <stdlib.h> |
32 |
|
|
#include "mdef.h" |
33 |
|
|
#include "stdd.h" |
34 |
|
|
#include "extern.h" |
35 |
|
|
|
36 |
|
|
FILE *traceout; |
37 |
|
|
|
38 |
|
|
#define TRACE_ARGS 1 |
39 |
|
|
#define TRACE_EXPANSION 2 |
40 |
|
|
#define TRACE_QUOTE 4 |
41 |
|
|
#define TRACE_FILENAME 8 |
42 |
|
|
#define TRACE_LINENO 16 |
43 |
|
|
#define TRACE_CONT 32 |
44 |
|
|
#define TRACE_ID 64 |
45 |
|
|
#define TRACE_NEWFILE 128 /* not implemented yet */ |
46 |
|
|
#define TRACE_INPUT 256 /* not implemented yet */ |
47 |
|
|
|
48 |
|
|
static unsigned int letter_to_flag(int); |
49 |
|
|
static void print_header(struct input_file *); |
50 |
|
|
static int frame_level(void); |
51 |
|
|
|
52 |
|
|
|
53 |
|
|
unsigned int trace_flags = TRACE_QUOTE | TRACE_EXPANSION; |
54 |
|
|
|
55 |
|
|
void |
56 |
|
|
trace_file(const char *name) |
57 |
|
|
{ |
58 |
|
|
|
59 |
|
|
if (traceout && traceout != stderr) |
60 |
|
|
fclose(traceout); |
61 |
|
|
traceout = fopen(name, "w"); |
62 |
|
|
if (!traceout) |
63 |
|
|
err(1, "can't open %s", name); |
64 |
|
|
} |
65 |
|
|
|
66 |
|
|
static unsigned int |
67 |
|
|
letter_to_flag(int c) |
68 |
|
|
{ |
69 |
|
|
switch(c) { |
70 |
|
|
case 'a': |
71 |
|
|
return TRACE_ARGS; |
72 |
|
|
case 'e': |
73 |
|
|
return TRACE_EXPANSION; |
74 |
|
|
case 'q': |
75 |
|
|
return TRACE_QUOTE; |
76 |
|
|
case 'c': |
77 |
|
|
return TRACE_CONT; |
78 |
|
|
case 'x': |
79 |
|
|
return TRACE_ID; |
80 |
|
|
case 'f': |
81 |
|
|
return TRACE_FILENAME; |
82 |
|
|
case 'l': |
83 |
|
|
return TRACE_LINENO; |
84 |
|
|
case 'p': |
85 |
|
|
return TRACE_NEWFILE; |
86 |
|
|
case 'i': |
87 |
|
|
return TRACE_INPUT; |
88 |
|
|
case 't': |
89 |
|
|
return TRACE_ALL; |
90 |
|
|
case 'V': |
91 |
|
|
return ~0; |
92 |
|
|
default: |
93 |
|
|
return 0; |
94 |
|
|
} |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
void |
98 |
|
|
set_trace_flags(const char *s) |
99 |
|
|
{ |
100 |
|
|
char mode = 0; |
101 |
|
|
unsigned int f = 0; |
102 |
|
|
|
103 |
|
|
if (*s == '+' || *s == '-') |
104 |
|
|
mode = *s++; |
105 |
|
|
while (*s) |
106 |
|
|
f |= letter_to_flag(*s++); |
107 |
|
|
switch(mode) { |
108 |
|
|
case 0: |
109 |
|
|
trace_flags = f; |
110 |
|
|
break; |
111 |
|
|
case '+': |
112 |
|
|
trace_flags |= f; |
113 |
|
|
break; |
114 |
|
|
case '-': |
115 |
|
|
trace_flags &= ~f; |
116 |
|
|
break; |
117 |
|
|
} |
118 |
|
|
} |
119 |
|
|
|
120 |
|
|
static int |
121 |
|
|
frame_level() |
122 |
|
|
{ |
123 |
|
|
int level; |
124 |
|
|
int framep; |
125 |
|
|
|
126 |
|
|
for (framep = fp, level = 0; framep != 0; |
127 |
|
|
level++,framep = mstack[framep-3].sfra) |
128 |
|
|
; |
129 |
|
|
return level; |
130 |
|
|
} |
131 |
|
|
|
132 |
|
|
static void |
133 |
|
|
print_header(struct input_file *inp) |
134 |
|
|
{ |
135 |
|
|
fprintf(traceout, "m4trace:"); |
136 |
|
|
if (trace_flags & TRACE_FILENAME) |
137 |
|
|
fprintf(traceout, "%s:", inp->name); |
138 |
|
|
if (trace_flags & TRACE_LINENO) |
139 |
|
|
fprintf(traceout, "%lu:", inp->lineno); |
140 |
|
|
fprintf(traceout, " -%d- ", frame_level()); |
141 |
|
|
if (trace_flags & TRACE_ID) |
142 |
|
|
fprintf(traceout, "id %lu: ", expansion_id); |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
size_t |
146 |
|
|
trace(const char *argv[], int argc, struct input_file *inp) |
147 |
|
|
{ |
148 |
|
|
if (!traceout) |
149 |
|
|
traceout = stderr; |
150 |
|
|
print_header(inp); |
151 |
|
|
if (trace_flags & TRACE_CONT) { |
152 |
|
|
fprintf(traceout, "%s ...\n", argv[1]); |
153 |
|
|
print_header(inp); |
154 |
|
|
} |
155 |
|
|
fprintf(traceout, "%s", argv[1]); |
156 |
|
|
if ((trace_flags & TRACE_ARGS) && argc > 2) { |
157 |
|
|
char delim[3]; |
158 |
|
|
int i; |
159 |
|
|
|
160 |
|
|
delim[0] = LPAREN; |
161 |
|
|
delim[1] = EOS; |
162 |
|
|
for (i = 2; i < argc; i++) { |
163 |
|
|
fprintf(traceout, "%s%s%s%s", delim, |
164 |
|
|
(trace_flags & TRACE_QUOTE) ? lquote : "", |
165 |
|
|
argv[i], |
166 |
|
|
(trace_flags & TRACE_QUOTE) ? rquote : ""); |
167 |
|
|
delim[0] = COMMA; |
168 |
|
|
delim[1] = ' '; |
169 |
|
|
delim[2] = EOS; |
170 |
|
|
} |
171 |
|
|
fprintf(traceout, "%c", RPAREN); |
172 |
|
|
} |
173 |
|
|
if (trace_flags & TRACE_CONT) { |
174 |
|
|
fprintf(traceout, " -> ???\n"); |
175 |
|
|
print_header(inp); |
176 |
|
|
fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]); |
177 |
|
|
} |
178 |
|
|
if (trace_flags & TRACE_EXPANSION) |
179 |
|
|
return buffer_mark(); |
180 |
|
|
else { |
181 |
|
|
fprintf(traceout, "\n"); |
182 |
|
|
return SIZE_MAX; |
183 |
|
|
} |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
void |
187 |
|
|
finish_trace(size_t mark) |
188 |
|
|
{ |
189 |
|
|
fprintf(traceout, " -> "); |
190 |
|
|
if (trace_flags & TRACE_QUOTE) |
191 |
|
|
fprintf(traceout, "%s", lquote); |
192 |
|
|
dump_buffer(traceout, mark); |
193 |
|
|
if (trace_flags & TRACE_QUOTE) |
194 |
|
|
fprintf(traceout, "%s", rquote); |
195 |
|
|
fprintf(traceout, "\n"); |
196 |
|
|
} |