GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/m4/trace.c Lines: 0 74 0.0 %
Date: 2017-11-07 Branches: 0 50 0.0 %

Line Branch Exec Source
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
}