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