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