Mercurial > ~dholland > hg > tradcpp > index.cgi
annotate output.c @ 142:26ee741196d1
Allow complain(NULL, format, ...)
author | David A. Holland |
---|---|
date | Sat, 13 Jul 2013 12:38:54 -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 } |