xref: /netbsd-src/usr.bin/m4/trace.c (revision 7c332fd36c3502ff81db1b291deeda7c97cb57f7)
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