Mercurial > ~dholland > hg > tradcpp > index.cgi
annotate output.c @ 80:7e64b1dd0a26
improve the nested comment test
author | David A. Holland |
---|---|
date | Mon, 10 Jun 2013 20:19:49 -0400 |
parents | 4cc1c575951f |
children | 27c9aafcaca1 |
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 |
27 | 99 filter_output(const struct place *p, const char *buf, size_t len) |
21 | 100 { |
101 size_t pos, start; | |
102 | |
103 start = 0; | |
104 for (pos = 0; pos < len - 1; pos++) { | |
105 if (buf[pos] == '/' && buf[pos+1] == '*') { | |
78
4cc1c575951f
No need to warn about nested comments twice.
David A. Holland
parents:
39
diff
changeset
|
106 if (!incomment) { |
21 | 107 if (pos > start) { |
108 dowrite(buf + start, pos - start); | |
109 } | |
110 start = pos; | |
111 pos += 2; | |
112 incomment = true; | |
113 /* cancel out the loop's pos++ */ | |
114 pos--; | |
115 continue; | |
116 } | |
117 } else if (buf[pos] == '*' && buf[pos+1] == '/') { | |
118 if (incomment) { | |
119 pos += 2; | |
120 if (mode.output_retain_comments) { | |
121 dowrite(buf + start, pos - start); | |
122 } | |
123 start = pos; | |
124 incomment = false; | |
125 /* cancel out the loop's pos++ */ | |
126 pos--; | |
127 continue; | |
128 } | |
129 } | |
130 } | |
24 | 131 pos++; |
132 | |
133 if (pos > start) { | |
134 if (!incomment || mode.output_retain_comments) { | |
135 dowrite(buf + start, pos - start); | |
136 } | |
137 } | |
21 | 138 } |
139 | |
140 void | |
27 | 141 output(const struct place *p, const char *buf, size_t len) |
142 { | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
143 size_t oldmax; |
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
144 |
27 | 145 if (linebufpos + len > linebufmax) { |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
146 oldmax = linebufmax; |
27 | 147 if (linebufmax == 0) { |
148 linebufmax = 64; | |
149 } | |
150 while (linebufpos + len > linebufmax) { | |
151 linebufmax *= 2; | |
152 } | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
30
diff
changeset
|
153 linebuf = dorealloc(linebuf, oldmax, linebufmax); |
27 | 154 } |
155 if (linebufpos == 0) { | |
156 linebufplace = *p; | |
157 } | |
158 memcpy(linebuf + linebufpos, buf, len); | |
159 linebufpos += len; | |
160 | |
161 if (len == 1 && buf[0] == '\n') { | |
162 filter_output(&linebufplace, linebuf, linebufpos); | |
163 linebufpos = 0; | |
164 } | |
165 } | |
166 | |
167 void | |
20 | 168 output_eof(void) |
169 { | |
24 | 170 if (mode.output_file != NULL && outputfd >= 0) { |
20 | 171 close(outputfd); |
172 } | |
173 outputfd = -1; | |
174 } |