GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: libexec/tradcpp/output.c Lines: 0 67 0.0 %
Date: 2017-11-07 Branches: 0 72 0.0 %

Line Branch Exec Source
1
/*-
2
 * Copyright (c) 2010 The NetBSD Foundation, Inc.
3
 * All rights reserved.
4
 *
5
 * This code is derived from software contributed to The NetBSD Foundation
6
 * by David A. Holland.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
#include <string.h>
31
#include <unistd.h>
32
#include <fcntl.h>
33
#include <errno.h>
34
35
#include "utils.h"
36
#include "mode.h"
37
#include "place.h"
38
#include "output.h"
39
40
static int outputfd = -1;
41
static bool incomment = false;
42
static char *linebuf;
43
static size_t linebufpos, linebufmax;
44
static struct place linebufplace;
45
46
static
47
void
48
output_open(void)
49
{
50
	if ((mode.output_file == NULL) || !strcmp(mode.output_file, "-")) {
51
		outputfd = STDOUT_FILENO;
52
	} else {
53
		outputfd = open(mode.output_file, O_WRONLY|O_CREAT|O_TRUNC,
54
				0664);
55
		if (outputfd < 0) {
56
			complain(NULL, "%s: %s",
57
				 mode.output_file, strerror(errno));
58
			die();
59
		}
60
	}
61
}
62
63
static
64
void
65
dowrite(const char *buf, size_t len)
66
{
67
	size_t done;
68
	ssize_t result;
69
	static unsigned write_errors = 0;
70
71
	if (!mode.do_output) {
72
		return;
73
	}
74
75
	if (outputfd < 0) {
76
		output_open();
77
	}
78
79
	done = 0;
80
	while (done < len) {
81
		result = write(outputfd, buf+done, len-done);
82
		if (result == -1) {
83
			complain(NULL, "%s: write: %s",
84
				 mode.output_file, strerror(errno));
85
			complain_failed();
86
			write_errors++;
87
			if (write_errors > 5) {
88
				complain(NULL, "%s: giving up",
89
					 mode.output_file);
90
				die();
91
			}
92
			/* XXX is this really a good idea? */
93
			sleep(1);
94
		}
95
		done += (size_t)result;
96
	}
97
}
98
99
100
static
101
void
102
filter_output(const char *buf, size_t len)
103
{
104
	size_t pos, start;
105
	bool inesc = false;
106
	bool inquote = false;
107
	char quote = '\0';
108
109
	start = 0;
110
	for (pos = 0; pos < len - 1; pos++) {
111
		if (!inquote && buf[pos] == '/' && buf[pos+1] == '*') {
112
			if (!incomment) {
113
				if (pos > start) {
114
					dowrite(buf + start, pos - start);
115
				}
116
				start = pos;
117
				pos += 2;
118
				incomment = true;
119
				/* cancel out the loop's pos++ */
120
				pos--;
121
				continue;
122
			}
123
		} else if (buf[pos] == '*' && buf[pos+1] == '/') {
124
			if (incomment) {
125
				pos += 2;
126
				if (mode.output_retain_comments) {
127
					dowrite(buf + start, pos - start);
128
				}
129
				start = pos;
130
				incomment = false;
131
				/* cancel out the loop's pos++ */
132
				pos--;
133
				continue;
134
			}
135
		}
136
137
		if (incomment) {
138
			/* nothing */
139
		} else if (inesc) {
140
			inesc = false;
141
		} else if (buf[pos] == '\\') {
142
			inesc = true;
143
		} else if (!inquote && (buf[pos] == '"' || buf[pos] == '\'')) {
144
			inquote = true;
145
			quote = buf[pos];
146
		} else if (inquote && buf[pos] == quote) {
147
			inquote = false;
148
		}
149
	}
150
	pos++;
151
152
	if (pos > start) {
153
		if (!incomment || mode.output_retain_comments) {
154
			dowrite(buf + start, pos - start);
155
		}
156
	}
157
}
158
159
void
160
output(const struct place *p, const char *buf, size_t len)
161
{
162
	size_t oldmax;
163
164
	if (linebufpos + len > linebufmax) {
165
		oldmax = linebufmax;
166
		if (linebufmax == 0) {
167
			linebufmax = 64;
168
		}
169
		while (linebufpos + len > linebufmax) {
170
			linebufmax *= 2;
171
		}
172
		linebuf = dorealloc(linebuf, oldmax, linebufmax);
173
	}
174
	if (linebufpos == 0) {
175
		linebufplace = *p;
176
	}
177
	memcpy(linebuf + linebufpos, buf, len);
178
	linebufpos += len;
179
180
	if (len == 1 && buf[0] == '\n') {
181
		filter_output(linebuf, linebufpos);
182
		linebufpos = 0;
183
	}
184
}
185
186
void
187
output_eof(void)
188
{
189
	if (mode.output_file != NULL && outputfd >= 0) {
190
		close(outputfd);
191
	}
192
	outputfd = -1;
193
}