output.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. #include <stdio.h>
  30. #include <string.h>
  31. #include <unistd.h>
  32. #include <fcntl.h>
  33. #include <errno.h>
  34. #include "utils.h"
  35. #include "mode.h"
  36. #include "place.h"
  37. #include "output.h"
  38. static int outputfd = -1;
  39. static bool incomment = false;
  40. static char *linebuf;
  41. static size_t linebufpos, linebufmax;
  42. static struct place linebufplace;
  43. static
  44. void
  45. output_open(void)
  46. {
  47. if (mode.output_file == NULL) {
  48. outputfd = STDOUT_FILENO;
  49. } else {
  50. outputfd = open(mode.output_file, O_WRONLY|O_CREAT|O_TRUNC,
  51. 0664);
  52. if (outputfd < 0) {
  53. complain(NULL, "%s: %s",
  54. mode.output_file, strerror(errno));
  55. die();
  56. }
  57. }
  58. }
  59. static
  60. void
  61. dowrite(const char *buf, size_t len)
  62. {
  63. size_t done;
  64. ssize_t result;
  65. static unsigned write_errors = 0;
  66. if (!mode.do_output) {
  67. return;
  68. }
  69. if (outputfd < 0) {
  70. output_open();
  71. }
  72. done = 0;
  73. while (done < len) {
  74. result = write(outputfd, buf+done, len-done);
  75. if (result == -1) {
  76. complain(NULL, "%s: write: %s",
  77. mode.output_file, strerror(errno));
  78. complain_failed();
  79. write_errors++;
  80. if (write_errors > 5) {
  81. complain(NULL, "%s: giving up",
  82. mode.output_file);
  83. die();
  84. }
  85. /* XXX is this really a good idea? */
  86. sleep(1);
  87. }
  88. done += (size_t)result;
  89. }
  90. }
  91. static
  92. void
  93. filter_output(const char *buf, size_t len)
  94. {
  95. size_t pos, start;
  96. bool inesc = false;
  97. bool inquote = false;
  98. char quote = '\0';
  99. start = 0;
  100. for (pos = 0; pos < len - 1; pos++) {
  101. if (!inquote && buf[pos] == '/' && buf[pos+1] == '*') {
  102. if (!incomment) {
  103. if (pos > start) {
  104. dowrite(buf + start, pos - start);
  105. }
  106. start = pos;
  107. pos += 2;
  108. incomment = true;
  109. /* cancel out the loop's pos++ */
  110. pos--;
  111. continue;
  112. }
  113. } else if (buf[pos] == '*' && buf[pos+1] == '/') {
  114. if (incomment) {
  115. pos += 2;
  116. if (mode.output_retain_comments) {
  117. dowrite(buf + start, pos - start);
  118. }
  119. start = pos;
  120. incomment = false;
  121. /* cancel out the loop's pos++ */
  122. pos--;
  123. continue;
  124. }
  125. }
  126. if (incomment) {
  127. /* nothing */
  128. } else if (inesc) {
  129. inesc = false;
  130. } else if (buf[pos] == '\\') {
  131. inesc = true;
  132. } else if (!inquote && (buf[pos] == '"' || buf[pos] == '\'')) {
  133. inquote = true;
  134. quote = buf[pos];
  135. } else if (inquote && buf[pos] == quote) {
  136. inquote = false;
  137. }
  138. }
  139. pos++;
  140. if (pos > start) {
  141. if (!incomment || mode.output_retain_comments) {
  142. dowrite(buf + start, pos - start);
  143. }
  144. }
  145. }
  146. void
  147. output(const struct place *p, const char *buf, size_t len)
  148. {
  149. size_t oldmax;
  150. if (linebufpos + len > linebufmax) {
  151. oldmax = linebufmax;
  152. if (linebufmax == 0) {
  153. linebufmax = 64;
  154. }
  155. while (linebufpos + len > linebufmax) {
  156. linebufmax *= 2;
  157. }
  158. linebuf = dorealloc(linebuf, oldmax, linebufmax);
  159. }
  160. if (linebufpos == 0) {
  161. if (!place_samefile(&linebufplace, p)) {
  162. if (mode.output_cheaplinenumbers) {
  163. char str[256];
  164. snprintf(str, sizeof(str), "# %u \"%s\"\n",
  165. p->line, place_getname(p));
  166. dowrite(str, strlen(str));
  167. }
  168. }
  169. linebufplace = *p;
  170. }
  171. memcpy(linebuf + linebufpos, buf, len);
  172. linebufpos += len;
  173. if (len == 1 && buf[0] == '\n') {
  174. filter_output(linebuf, linebufpos);
  175. linebufpos = 0;
  176. }
  177. }
  178. void
  179. output_eof(void)
  180. {
  181. if (mode.output_file != NULL && outputfd >= 0) {
  182. close(outputfd);
  183. }
  184. outputfd = -1;
  185. }