Mercurial > ~dholland > hg > tradcpp > index.cgi
annotate output.c @ 136:59680a727e9d
Improve previous.
Just in case we ever crash and reach cleanup() while processing an
-include foo option, take the array entry for it out of the array to
make sure it doesn't get freed twice. This case shouldn't be
reachable, but it's better to be safe.
author | David A. Holland |
---|---|
date | Tue, 09 Jul 2013 13:38:43 -0400 |
parents | 1cda505ddc78 |
children | ed45f2d8d3bc |
rev | line source |
---|---|
30 | 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 | |
27 | 30 #include <string.h> |
20 | 31 #include <unistd.h> |
32 #include <fcntl.h> | |
33 #include <err.h> | |
34 | |
35 #include "utils.h" | |
36 #include "mode.h" | |
21 | 37 #include "place.h" |
20 | 38 #include "output.h" |
39 | |
40 static int outputfd = -1; | |
21 | 41 static bool incomment = false; |
27 | 42 static char *linebuf; |
43 static size_t linebufpos, linebufmax; | |
44 static struct place linebufplace; | |
20 | 45 |
46 static | |
47 void | |
48 output_open(void) | |
49 { | |
24 | 50 if (mode.output_file == NULL) { |
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 warn("%s", mode.output_file); | |
57 die(); | |
58 } | |
20 | 59 } |
60 } | |
61 | |
21 | 62 static |
20 | 63 void |
21 | 64 dowrite(const char *buf, size_t len) |
20 | 65 { |
66 size_t done; | |
67 ssize_t result; | |
68 static unsigned write_errors = 0; | |
69 | |
22 | 70 if (!mode.do_output) { |
71 return; | |
72 } | |
73 | |
20 | 74 if (outputfd < 0) { |
75 output_open(); | |
76 } | |
77 | |
78 done = 0; | |
79 while (done < len) { | |
80 result = write(outputfd, buf+done, len-done); | |
81 if (result == -1) { | |
82 warn("%s: write", mode.output_file); | |
83 complain_failed(); | |
84 write_errors++; | |
85 if (write_errors > 5) { | |
86 warnx("%s: giving up", mode.output_file); | |
87 die(); | |
88 } | |
89 /* XXX is this really a good idea? */ | |
90 sleep(1); | |
91 } | |
92 done += (size_t)result; | |
93 } | |
94 } | |
95 | |
27 | 96 |
97 static | |
20 | 98 void |
103 | 99 filter_output(const char *buf, size_t len) |
21 | 100 { |
101 size_t pos, start; | |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
102 bool inesc = false; |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
103 bool inquote = false; |
128
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
103
diff
changeset
|
104 char quote = '\0'; |
21 | 105 |
106 start = 0; | |
107 for (pos = 0; pos < len - 1; pos++) { | |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
108 if (!inquote && buf[pos] == '/' && buf[pos+1] == '*') { |
78
4cc1c575951f
No need to warn about nested comments twice.
David A. Holland
parents:
39
diff
changeset
|
109 if (!incomment) { |
21 | 110 if (pos > start) { |
111 dowrite(buf + start, pos - start); | |
112 } | |
113 start = pos; | |
114 pos += 2; | |
115 incomment = true; | |
116 /* cancel out the loop's pos++ */ | |
117 pos--; | |
118 continue; | |
119 } | |
120 } else if (buf[pos] == '*' && buf[pos+1] == '/') { | |
121 if (incomment) { | |
122 pos += 2; | |
123 if (mode.output_retain_comments) { | |
124 dowrite(buf + start, pos - start); | |
125 } | |
126 start = pos; | |
127 incomment = false; | |
128 /* cancel out the loop's pos++ */ | |
129 pos--; | |
130 continue; | |
131 } | |
132 } | |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
133 |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
134 if (incomment) { |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
135 /* nothing */ |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
136 } else if (inesc) { |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
137 inesc = false; |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
138 } else if (buf[pos] == '\\') { |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
139 inesc = true; |
128
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
103
diff
changeset
|
140 } else if (!inquote && (buf[pos] == '"' || buf[pos] == '\'')) { |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
103
diff
changeset
|
141 inquote = true; |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
103
diff
changeset
|
142 quote = buf[pos]; |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
103
diff
changeset
|
143 } else if (inquote && buf[pos] == quote) { |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
103
diff
changeset
|
144 inquote = false; |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
78
diff
changeset
|
145 } |
21 | 146 } |
24 | 147 pos++; |
148 | |
149 if (pos > start) { | |
150 if (!incomment || mode.output_retain_comments) { | |
151 dowrite(buf + start, pos - start); | |
152 } | |
153 } | |
21 | 154 } |
155 | |
156 void | |
27 | 157 output(const struct place *p, const char *buf, size_t len) |
158 { | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
159 size_t oldmax; |
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
160 |
27 | 161 if (linebufpos + len > linebufmax) { |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
162 oldmax = linebufmax; |
27 | 163 if (linebufmax == 0) { |
164 linebufmax = 64; | |
165 } | |
166 while (linebufpos + len > linebufmax) { | |
167 linebufmax *= 2; | |
168 } | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
169 linebuf = dorealloc(linebuf, oldmax, linebufmax); |
27 | 170 } |
171 if (linebufpos == 0) { | |
172 linebufplace = *p; | |
173 } | |
174 memcpy(linebuf + linebufpos, buf, len); | |
175 linebufpos += len; | |
176 | |
177 if (len == 1 && buf[0] == '\n') { | |
103 | 178 filter_output(linebuf, linebufpos); |
27 | 179 linebufpos = 0; |
180 } | |
181 } | |
182 | |
183 void | |
20 | 184 output_eof(void) |
185 { | |
24 | 186 if (mode.output_file != NULL && outputfd >= 0) { |
20 | 187 close(outputfd); |
188 } | |
189 outputfd = -1; | |
190 } |