debug.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /* GNU m4 -- A simple macro processor
  2. Copyright (C) 1991-1994, 2004, 2006-2007, 2009-2014, 2016 Free
  3. Software Foundation, Inc.
  4. This file is part of GNU M4.
  5. GNU M4 is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. GNU M4 is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "m4.h"
  17. #include <stdarg.h>
  18. #include <sys/stat.h>
  19. /* File for debugging output. */
  20. FILE *debug = NULL;
  21. /* Obstack for trace messages. */
  22. static struct obstack trace;
  23. static void debug_set_file (FILE *);
  24. /*----------------------------------.
  25. | Initialise the debugging module. |
  26. `----------------------------------*/
  27. void
  28. debug_init (void)
  29. {
  30. debug_set_file (stderr);
  31. obstack_init (&trace);
  32. }
  33. /*-----------------------------------------------------------------.
  34. | Function to decode the debugging flags OPTS. Used by main while |
  35. | processing option -d, and by the builtin debugmode (). |
  36. `-----------------------------------------------------------------*/
  37. int
  38. debug_decode (const char *opts)
  39. {
  40. int level;
  41. if (opts == NULL || *opts == '\0')
  42. level = DEBUG_TRACE_DEFAULT;
  43. else
  44. {
  45. for (level = 0; *opts; opts++)
  46. {
  47. switch (*opts)
  48. {
  49. case 'a':
  50. level |= DEBUG_TRACE_ARGS;
  51. break;
  52. case 'e':
  53. level |= DEBUG_TRACE_EXPANSION;
  54. break;
  55. case 'q':
  56. level |= DEBUG_TRACE_QUOTE;
  57. break;
  58. case 't':
  59. level |= DEBUG_TRACE_ALL;
  60. break;
  61. case 'l':
  62. level |= DEBUG_TRACE_LINE;
  63. break;
  64. case 'f':
  65. level |= DEBUG_TRACE_FILE;
  66. break;
  67. case 'p':
  68. level |= DEBUG_TRACE_PATH;
  69. break;
  70. case 'c':
  71. level |= DEBUG_TRACE_CALL;
  72. break;
  73. case 'i':
  74. level |= DEBUG_TRACE_INPUT;
  75. break;
  76. case 'x':
  77. level |= DEBUG_TRACE_CALLID;
  78. break;
  79. case 'V':
  80. level |= DEBUG_TRACE_VERBOSE;
  81. break;
  82. default:
  83. return -1;
  84. }
  85. }
  86. }
  87. /* This is to avoid screwing up the trace output due to changes in the
  88. debug_level. */
  89. obstack_free (&trace, obstack_finish (&trace));
  90. return level;
  91. }
  92. /*-----------------------------------------------------------------.
  93. | Change the debug output stream to FP. If the underlying file is |
  94. | the same as stdout, use stdout instead so that debug messages |
  95. | appear in the correct relative position. |
  96. `-----------------------------------------------------------------*/
  97. static void
  98. debug_set_file (FILE *fp)
  99. {
  100. struct stat stdout_stat, debug_stat;
  101. if (debug != NULL && debug != stderr && debug != stdout
  102. && close_stream (debug) != 0)
  103. {
  104. M4ERROR ((warning_status, errno, "error writing to debug stream"));
  105. retcode = EXIT_FAILURE;
  106. }
  107. debug = fp;
  108. if (debug != NULL && debug != stdout)
  109. {
  110. if (fstat (STDOUT_FILENO, &stdout_stat) < 0)
  111. return;
  112. if (fstat (fileno (debug), &debug_stat) < 0)
  113. return;
  114. /* mingw has a bug where fstat on a regular file reports st_ino
  115. of 0. On normal system, st_ino should never be 0. */
  116. if (stdout_stat.st_ino == debug_stat.st_ino
  117. && stdout_stat.st_dev == debug_stat.st_dev
  118. && stdout_stat.st_ino != 0)
  119. {
  120. if (debug != stderr && close_stream (debug) != 0)
  121. {
  122. M4ERROR ((warning_status, errno,
  123. "error writing to debug stream"));
  124. retcode = EXIT_FAILURE;
  125. }
  126. debug = stdout;
  127. }
  128. }
  129. }
  130. /*-----------------------------------------------------------.
  131. | Serialize files. Used before executing a system command. |
  132. `-----------------------------------------------------------*/
  133. void
  134. debug_flush_files (void)
  135. {
  136. fflush (stdout);
  137. fflush (stderr);
  138. if (debug != NULL && debug != stdout && debug != stderr)
  139. fflush (debug);
  140. /* POSIX requires that if m4 doesn't consume all input, but stdin is
  141. opened on a seekable file, that the file pointer be left at the
  142. next character on exit (but places no restrictions on the file
  143. pointer location on a non-seekable file). It also requires that
  144. fflush() followed by fseeko() on an input file set the underlying
  145. file pointer, and gnulib guarantees these semantics. However,
  146. fflush() on a non-seekable file can lose buffered data, which we
  147. might otherwise want to process after syscmd. Hence, we must
  148. check whether stdin is seekable. We must also be tolerant of
  149. operating with stdin closed, so we don't report any failures in
  150. this attempt. The stdio-safer module and friends are essential,
  151. so that if stdin was closed, this lseek is not on some other file
  152. that we have since opened. */
  153. if (lseek (STDIN_FILENO, 0, SEEK_CUR) >= 0
  154. && fflush (stdin) == 0)
  155. {
  156. fseeko (stdin, 0, SEEK_CUR);
  157. }
  158. }
  159. /*--------------------------------------------------------------.
  160. | Change the debug output to file NAME. If NAME is NULL, debug |
  161. | output is reverted to stderr, and if empty, debug output is |
  162. | discarded. Return true iff the output stream was changed. |
  163. `--------------------------------------------------------------*/
  164. bool
  165. debug_set_output (const char *name)
  166. {
  167. FILE *fp;
  168. if (name == NULL)
  169. debug_set_file (stderr);
  170. else if (*name == '\0')
  171. debug_set_file (NULL);
  172. else
  173. {
  174. fp = fopen (name, "a");
  175. if (fp == NULL)
  176. return false;
  177. if (set_cloexec_flag (fileno (fp), true) != 0)
  178. M4ERROR ((warning_status, errno,
  179. "Warning: cannot protect debug file across forks"));
  180. debug_set_file (fp);
  181. }
  182. return true;
  183. }
  184. /*--------------------------------------------------------------.
  185. | Print the header of a one-line debug message, starting by "m4 |
  186. | debug". |
  187. `--------------------------------------------------------------*/
  188. void
  189. debug_message_prefix (void)
  190. {
  191. xfprintf (debug, "m4debug:");
  192. if (current_line)
  193. {
  194. if (debug_level & DEBUG_TRACE_FILE)
  195. xfprintf (debug, "%s:", current_file);
  196. if (debug_level & DEBUG_TRACE_LINE)
  197. xfprintf (debug, "%d:", current_line);
  198. }
  199. putc (' ', debug);
  200. }
  201. /* The rest of this file contains the functions for macro tracing output.
  202. All tracing output for a macro call is collected on an obstack TRACE,
  203. and printed whenever the line is complete. This prevents tracing
  204. output from interfering with other debug messages generated by the
  205. various builtins. */
  206. /*------------------------------------------------------------------.
  207. | Tracing output is formatted here, by a simplified |
  208. | printf-to-obstack function trace_format (). Understands only %S, |
  209. | %s, %d, %l (optional left quote) and %r (optional right quote). |
  210. `------------------------------------------------------------------*/
  211. static void
  212. trace_format (const char *fmt, ...)
  213. {
  214. va_list args;
  215. char ch;
  216. int d;
  217. const char *s;
  218. int slen;
  219. int maxlen;
  220. va_start (args, fmt);
  221. while (true)
  222. {
  223. while ((ch = *fmt++) != '\0' && ch != '%')
  224. obstack_1grow (&trace, ch);
  225. if (ch == '\0')
  226. break;
  227. maxlen = 0;
  228. switch (*fmt++)
  229. {
  230. case 'S':
  231. maxlen = max_debug_argument_length;
  232. /* fall through */
  233. case 's':
  234. s = va_arg (args, const char *);
  235. break;
  236. case 'l':
  237. s = (debug_level & DEBUG_TRACE_QUOTE) ? lquote.string : "";
  238. break;
  239. case 'r':
  240. s = (debug_level & DEBUG_TRACE_QUOTE) ? rquote.string : "";
  241. break;
  242. case 'd':
  243. d = va_arg (args, int);
  244. s = ntoa (d, 10);
  245. break;
  246. default:
  247. s = "";
  248. break;
  249. }
  250. slen = strlen (s);
  251. if (maxlen == 0 || maxlen > slen)
  252. obstack_grow (&trace, s, slen);
  253. else
  254. {
  255. obstack_grow (&trace, s, maxlen);
  256. obstack_grow (&trace, "...", 3);
  257. }
  258. }
  259. va_end (args);
  260. }
  261. /*------------------------------------------------------------------.
  262. | Format the standard header attached to all tracing output lines. |
  263. `------------------------------------------------------------------*/
  264. static void
  265. trace_header (int id)
  266. {
  267. trace_format ("m4trace:");
  268. if (current_line)
  269. {
  270. if (debug_level & DEBUG_TRACE_FILE)
  271. trace_format ("%s:", current_file);
  272. if (debug_level & DEBUG_TRACE_LINE)
  273. trace_format ("%d:", current_line);
  274. }
  275. trace_format (" -%d- ", expansion_level);
  276. if (debug_level & DEBUG_TRACE_CALLID)
  277. trace_format ("id %d: ", id);
  278. }
  279. /*----------------------------------------------------.
  280. | Print current tracing line, and clear the obstack. |
  281. `----------------------------------------------------*/
  282. static void
  283. trace_flush (void)
  284. {
  285. char *line;
  286. obstack_1grow (&trace, '\0');
  287. line = (char *) obstack_finish (&trace);
  288. DEBUG_PRINT1 ("%s\n", line);
  289. obstack_free (&trace, line);
  290. }
  291. /*-------------------------------------------------------------.
  292. | Do pre-argument-collction tracing for macro NAME. Used from |
  293. | expand_macro (). |
  294. `-------------------------------------------------------------*/
  295. void
  296. trace_prepre (const char *name, int id)
  297. {
  298. trace_header (id);
  299. trace_format ("%s ...", name);
  300. trace_flush ();
  301. }
  302. /*--------------------------------------------------------------.
  303. | Format the parts of a trace line, that can be made before the |
  304. | macro is actually expanded. Used from expand_macro (). |
  305. `--------------------------------------------------------------*/
  306. void
  307. trace_pre (const char *name, int id, int argc, token_data **argv)
  308. {
  309. int i;
  310. const builtin *bp;
  311. trace_header (id);
  312. trace_format ("%s", name);
  313. if (argc > 1 && (debug_level & DEBUG_TRACE_ARGS))
  314. {
  315. trace_format ("(");
  316. for (i = 1; i < argc; i++)
  317. {
  318. if (i != 1)
  319. trace_format (", ");
  320. switch (TOKEN_DATA_TYPE (argv[i]))
  321. {
  322. case TOKEN_TEXT:
  323. trace_format ("%l%S%r", TOKEN_DATA_TEXT (argv[i]));
  324. break;
  325. case TOKEN_FUNC:
  326. bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[i]));
  327. if (bp == NULL)
  328. {
  329. M4ERROR ((warning_status, 0, "\
  330. INTERNAL ERROR: builtin not found in builtin table! (trace_pre ())"));
  331. abort ();
  332. }
  333. trace_format ("<%s>", bp->name);
  334. break;
  335. case TOKEN_VOID:
  336. default:
  337. M4ERROR ((warning_status, 0,
  338. "INTERNAL ERROR: bad token data type (trace_pre ())"));
  339. abort ();
  340. }
  341. }
  342. trace_format (")");
  343. }
  344. if (debug_level & DEBUG_TRACE_CALL)
  345. {
  346. trace_format (" -> ???");
  347. trace_flush ();
  348. }
  349. }
  350. /*-------------------------------------------------------------------.
  351. | Format the final part of a trace line and print it all. Used from |
  352. | expand_macro (). |
  353. `-------------------------------------------------------------------*/
  354. void
  355. trace_post (const char *name, int id, int argc, const char *expanded)
  356. {
  357. if (debug_level & DEBUG_TRACE_CALL)
  358. {
  359. trace_header (id);
  360. trace_format ("%s%s", name, (argc > 1) ? "(...)" : "");
  361. }
  362. if (expanded && (debug_level & DEBUG_TRACE_EXPANSION))
  363. trace_format (" -> %l%S%r", expanded);
  364. trace_flush ();
  365. }