1*7c332fd3Suwe /* $NetBSD: trace.c,v 1.9 2020/06/25 02:25:53 uwe Exp $ */
2f3efdb75Schristos /* $OpenBSD: trace.c,v 1.15 2006/03/24 08:03:44 espie Exp $ */
34b087712Stv /*
44b087712Stv * Copyright (c) 2001 Marc Espie.
54b087712Stv *
64b087712Stv * Redistribution and use in source and binary forms, with or without
74b087712Stv * modification, are permitted provided that the following conditions
84b087712Stv * are met:
94b087712Stv * 1. Redistributions of source code must retain the above copyright
104b087712Stv * notice, this list of conditions and the following disclaimer.
114b087712Stv * 2. Redistributions in binary form must reproduce the above copyright
124b087712Stv * notice, this list of conditions and the following disclaimer in the
134b087712Stv * documentation and/or other materials provided with the distribution.
144b087712Stv *
154b087712Stv * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
164b087712Stv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
174b087712Stv * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
184b087712Stv * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
194b087712Stv * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
204b087712Stv * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
214b087712Stv * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
224b087712Stv * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
234b087712Stv * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
244b087712Stv * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
254b087712Stv * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
264b087712Stv */
27b2f78261Sjmc #if HAVE_NBTOOL_CONFIG_H
28b2f78261Sjmc #include "nbtool_config.h"
29b2f78261Sjmc #endif
30f3efdb75Schristos #include <sys/cdefs.h>
31*7c332fd3Suwe __RCSID("$NetBSD: trace.c,v 1.9 2020/06/25 02:25:53 uwe Exp $");
32b2f78261Sjmc
334b087712Stv #include <sys/types.h>
34f3efdb75Schristos #include <err.h>
354b087712Stv #include <stddef.h>
36f3efdb75Schristos #include <stdint.h>
374b087712Stv #include <stdio.h>
384b087712Stv #include <stdlib.h>
394b087712Stv #include "mdef.h"
404b087712Stv #include "stdd.h"
414b087712Stv #include "extern.h"
424b087712Stv
43279abfc5Stv FILE *traceout;
444b087712Stv
454b087712Stv #define TRACE_ARGS 1
464b087712Stv #define TRACE_EXPANSION 2
474b087712Stv #define TRACE_QUOTE 4
484b087712Stv #define TRACE_FILENAME 8
494b087712Stv #define TRACE_LINENO 16
504b087712Stv #define TRACE_CONT 32
514b087712Stv #define TRACE_ID 64
524b087712Stv #define TRACE_NEWFILE 128 /* not implemented yet */
534b087712Stv #define TRACE_INPUT 256 /* not implemented yet */
544b087712Stv
55f3efdb75Schristos static unsigned int letter_to_flag(int);
56f3efdb75Schristos static void print_header(struct input_file *);
57f3efdb75Schristos static int frame_level(void);
584b087712Stv
594b087712Stv
60f3efdb75Schristos unsigned int trace_flags = TRACE_QUOTE | TRACE_EXPANSION;
614b087712Stv
62*7c332fd3Suwe int
trace_file(const char * name)63f3efdb75Schristos trace_file(const char *name)
644b087712Stv {
65*7c332fd3Suwe FILE *newfp;
66*7c332fd3Suwe
67*7c332fd3Suwe if (name == NULL)
68*7c332fd3Suwe newfp = stderr;
69*7c332fd3Suwe #if 0 /* not yet */
70*7c332fd3Suwe else if (*name == '\0')
71*7c332fd3Suwe newfp = NULL;
72*7c332fd3Suwe #endif
73*7c332fd3Suwe else {
74*7c332fd3Suwe newfp = fopen(name, "a");
75*7c332fd3Suwe if (newfp == NULL)
76*7c332fd3Suwe return -1;
77*7c332fd3Suwe }
784b087712Stv
79f3efdb75Schristos if (traceout && traceout != stderr)
804b087712Stv fclose(traceout);
81*7c332fd3Suwe traceout = newfp;
82*7c332fd3Suwe return 0;
834b087712Stv }
844b087712Stv
854b087712Stv static unsigned int
letter_to_flag(int c)86f3efdb75Schristos letter_to_flag(int c)
874b087712Stv {
884b087712Stv switch(c) {
894b087712Stv case 'a':
904b087712Stv return TRACE_ARGS;
914b087712Stv case 'e':
924b087712Stv return TRACE_EXPANSION;
934b087712Stv case 'q':
944b087712Stv return TRACE_QUOTE;
954b087712Stv case 'c':
964b087712Stv return TRACE_CONT;
974b087712Stv case 'x':
984b087712Stv return TRACE_ID;
994b087712Stv case 'f':
1004b087712Stv return TRACE_FILENAME;
1014b087712Stv case 'l':
1024b087712Stv return TRACE_LINENO;
1034b087712Stv case 'p':
1044b087712Stv return TRACE_NEWFILE;
1054b087712Stv case 'i':
1064b087712Stv return TRACE_INPUT;
1074b087712Stv case 't':
1084b087712Stv return TRACE_ALL;
1094b087712Stv case 'V':
1104b087712Stv return ~0;
1114b087712Stv default:
1124b087712Stv return 0;
1134b087712Stv }
1144b087712Stv }
1154b087712Stv
1164b087712Stv void
set_trace_flags(const char * s)117f3efdb75Schristos set_trace_flags(const char *s)
1184b087712Stv {
1194b087712Stv char mode = 0;
1204b087712Stv unsigned int f = 0;
1214b087712Stv
1224b087712Stv if (*s == '+' || *s == '-')
1234b087712Stv mode = *s++;
1244b087712Stv while (*s)
1254b087712Stv f |= letter_to_flag(*s++);
1264b087712Stv switch(mode) {
1274b087712Stv case 0:
128f3efdb75Schristos trace_flags = f;
1294b087712Stv break;
1304b087712Stv case '+':
131f3efdb75Schristos trace_flags |= f;
1324b087712Stv break;
1334b087712Stv case '-':
134f3efdb75Schristos trace_flags &= ~f;
1354b087712Stv break;
1364b087712Stv }
1374b087712Stv }
1384b087712Stv
1394b087712Stv static int
frame_level(void)140d34c2845Smatt frame_level(void)
1414b087712Stv {
1424b087712Stv int level;
1434b087712Stv int framep;
1444b087712Stv
1454b087712Stv for (framep = fp, level = 0; framep != 0;
146f3efdb75Schristos level++,framep = mstack[framep-3].sfra)
1474b087712Stv ;
1484b087712Stv return level;
1494b087712Stv }
1504b087712Stv
1514b087712Stv static void
print_header(struct input_file * inp)152f3efdb75Schristos print_header(struct input_file *inp)
1534b087712Stv {
154f3efdb75Schristos fprintf(traceout, "m4trace:");
155f3efdb75Schristos if (trace_flags & TRACE_FILENAME)
156f3efdb75Schristos fprintf(traceout, "%s:", inp->name);
157f3efdb75Schristos if (trace_flags & TRACE_LINENO)
1580b915be3Schristos fprintf(traceout, "%lu:", TOKEN_LINE(inp));
159f3efdb75Schristos fprintf(traceout, " -%d- ", frame_level());
160f3efdb75Schristos if (trace_flags & TRACE_ID)
161f3efdb75Schristos fprintf(traceout, "id %lu: ", expansion_id);
1624b087712Stv }
1634b087712Stv
164f3efdb75Schristos size_t
trace(const char * argv[],int argc,struct input_file * inp)165f3efdb75Schristos trace(const char *argv[], int argc, struct input_file *inp)
1664b087712Stv {
167f3efdb75Schristos if (!traceout)
168f3efdb75Schristos traceout = stderr;
1694b087712Stv print_header(inp);
170f3efdb75Schristos if (trace_flags & TRACE_CONT) {
171f3efdb75Schristos fprintf(traceout, "%s ...\n", argv[1]);
1724b087712Stv print_header(inp);
1734b087712Stv }
174f3efdb75Schristos fprintf(traceout, "%s", argv[1]);
175f3efdb75Schristos if ((trace_flags & TRACE_ARGS) && argc > 2) {
1764b087712Stv char delim[3];
1774b087712Stv int i;
1784b087712Stv
1794b087712Stv delim[0] = LPAREN;
1804b087712Stv delim[1] = EOS;
1814b087712Stv for (i = 2; i < argc; i++) {
182f3efdb75Schristos fprintf(traceout, "%s%s%s%s", delim,
183f3efdb75Schristos (trace_flags & TRACE_QUOTE) ? lquote : "",
1844b087712Stv argv[i],
185f3efdb75Schristos (trace_flags & TRACE_QUOTE) ? rquote : "");
1864b087712Stv delim[0] = COMMA;
1874b087712Stv delim[1] = ' ';
1884b087712Stv delim[2] = EOS;
1894b087712Stv }
190f3efdb75Schristos fprintf(traceout, "%c", RPAREN);
1914b087712Stv }
192f3efdb75Schristos if (trace_flags & TRACE_CONT) {
193f3efdb75Schristos fprintf(traceout, " -> ???\n");
1944b087712Stv print_header(inp);
195f3efdb75Schristos fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]);
1964b087712Stv }
197f3efdb75Schristos if (trace_flags & TRACE_EXPANSION)
1984b087712Stv return buffer_mark();
1994b087712Stv else {
200f3efdb75Schristos fprintf(traceout, "\n");
201f3efdb75Schristos return SIZE_MAX;
2024b087712Stv }
2034b087712Stv }
2044b087712Stv
2054b087712Stv void
finish_trace(size_t mark)206f3efdb75Schristos finish_trace(size_t mark)
2074b087712Stv {
208f3efdb75Schristos fprintf(traceout, " -> ");
209f3efdb75Schristos if (trace_flags & TRACE_QUOTE)
210f3efdb75Schristos fprintf(traceout, "%s", lquote);
211f3efdb75Schristos dump_buffer(traceout, mark);
212f3efdb75Schristos if (trace_flags & TRACE_QUOTE)
213f3efdb75Schristos fprintf(traceout, "%s", rquote);
214f3efdb75Schristos fprintf(traceout, "\n");
2154b087712Stv }
216