27
|
1 #include <string.h>
|
20
|
2 #include <unistd.h>
|
|
3 #include <fcntl.h>
|
|
4 #include <err.h>
|
|
5
|
|
6 #include "utils.h"
|
|
7 #include "mode.h"
|
21
|
8 #include "place.h"
|
20
|
9 #include "output.h"
|
|
10
|
|
11 static int outputfd = -1;
|
21
|
12 static bool incomment = false;
|
27
|
13 static char *linebuf;
|
|
14 static size_t linebufpos, linebufmax;
|
|
15 static struct place linebufplace;
|
20
|
16
|
|
17 static
|
|
18 void
|
|
19 output_open(void)
|
|
20 {
|
24
|
21 if (mode.output_file == NULL) {
|
|
22 outputfd = STDOUT_FILENO;
|
|
23 } else {
|
|
24 outputfd = open(mode.output_file, O_WRONLY|O_CREAT|O_TRUNC,
|
|
25 0664);
|
|
26 if (outputfd < 0) {
|
|
27 warn("%s", mode.output_file);
|
|
28 die();
|
|
29 }
|
20
|
30 }
|
|
31 }
|
|
32
|
21
|
33 static
|
20
|
34 void
|
21
|
35 dowrite(const char *buf, size_t len)
|
20
|
36 {
|
|
37 size_t done;
|
|
38 ssize_t result;
|
|
39 static unsigned write_errors = 0;
|
|
40
|
22
|
41 if (!mode.do_output) {
|
|
42 return;
|
|
43 }
|
|
44
|
20
|
45 if (outputfd < 0) {
|
|
46 output_open();
|
|
47 }
|
|
48
|
|
49 done = 0;
|
|
50 while (done < len) {
|
|
51 result = write(outputfd, buf+done, len-done);
|
|
52 if (result == -1) {
|
|
53 warn("%s: write", mode.output_file);
|
|
54 complain_failed();
|
|
55 write_errors++;
|
|
56 if (write_errors > 5) {
|
|
57 warnx("%s: giving up", mode.output_file);
|
|
58 die();
|
|
59 }
|
|
60 /* XXX is this really a good idea? */
|
|
61 sleep(1);
|
|
62 }
|
|
63 done += (size_t)result;
|
|
64 }
|
|
65 }
|
|
66
|
27
|
67
|
|
68 static
|
20
|
69 void
|
27
|
70 filter_output(const struct place *p, const char *buf, size_t len)
|
21
|
71 {
|
|
72 size_t pos, start;
|
|
73 struct place p2;
|
|
74
|
|
75 start = 0;
|
|
76 for (pos = 0; pos < len - 1; pos++) {
|
|
77 if (buf[pos] == '/' && buf[pos+1] == '*') {
|
|
78 if (incomment && warns.nestcomment) {
|
|
79 p2 = *p;
|
|
80 p2.column += pos;
|
|
81 complain(p, "Warning: %c%c within comment",
|
|
82 '/', '*');
|
|
83 if (mode.werror) {
|
|
84 complain_failed();
|
|
85 }
|
|
86 } else if (!incomment) {
|
|
87 if (pos > start) {
|
|
88 dowrite(buf + start, pos - start);
|
|
89 }
|
|
90 start = pos;
|
|
91 pos += 2;
|
|
92 incomment = true;
|
|
93 /* cancel out the loop's pos++ */
|
|
94 pos--;
|
|
95 continue;
|
|
96 }
|
|
97 } else if (buf[pos] == '*' && buf[pos+1] == '/') {
|
|
98 if (incomment) {
|
|
99 pos += 2;
|
|
100 if (mode.output_retain_comments) {
|
|
101 dowrite(buf + start, pos - start);
|
|
102 }
|
|
103 start = pos;
|
|
104 incomment = false;
|
|
105 /* cancel out the loop's pos++ */
|
|
106 pos--;
|
|
107 continue;
|
|
108 }
|
|
109 }
|
|
110 }
|
24
|
111 pos++;
|
|
112
|
|
113 if (pos > start) {
|
|
114 if (!incomment || mode.output_retain_comments) {
|
|
115 dowrite(buf + start, pos - start);
|
|
116 }
|
|
117 }
|
21
|
118 }
|
|
119
|
|
120 void
|
27
|
121 output(const struct place *p, const char *buf, size_t len)
|
|
122 {
|
|
123 if (linebufpos + len > linebufmax) {
|
|
124 if (linebufmax == 0) {
|
|
125 linebufmax = 64;
|
|
126 }
|
|
127 while (linebufpos + len > linebufmax) {
|
|
128 linebufmax *= 2;
|
|
129 }
|
|
130 linebuf = dorealloc(linebuf, linebufmax);
|
|
131 }
|
|
132 if (linebufpos == 0) {
|
|
133 linebufplace = *p;
|
|
134 }
|
|
135 memcpy(linebuf + linebufpos, buf, len);
|
|
136 linebufpos += len;
|
|
137
|
|
138 if (len == 1 && buf[0] == '\n') {
|
|
139 filter_output(&linebufplace, linebuf, linebufpos);
|
|
140 linebufpos = 0;
|
|
141 }
|
|
142 }
|
|
143
|
|
144 void
|
20
|
145 output_eof(void)
|
|
146 {
|
24
|
147 if (mode.output_file != NULL && outputfd >= 0) {
|
20
|
148 close(outputfd);
|
|
149 }
|
|
150 outputfd = -1;
|
|
151 }
|