1 /* GNU m4 -- A simple macro processor
3 Copyright (C) 1991-1994, 2004, 2006-2007, 2009-2011 Free Software
6 This file is part of GNU M4.
8 GNU M4 is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU M4 is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 /* File for debugging output. */
30 /* Obstack for trace messages. */
31 static struct obstack trace;
33 extern int expansion_level;
35 static void debug_set_file (FILE *);
37 /*----------------------------------.
38 | Initialise the debugging module. |
39 `----------------------------------*/
44 debug_set_file (stderr);
45 obstack_init (&trace);
48 /*-----------------------------------------------------------------.
49 | Function to decode the debugging flags OPTS. Used by main while |
50 | processing option -d, and by the builtin debugmode (). |
51 `-----------------------------------------------------------------*/
54 debug_decode (const char *opts)
58 if (opts == NULL || *opts == '\0')
59 level = DEBUG_TRACE_DEFAULT;
62 for (level = 0; *opts; opts++)
67 level |= DEBUG_TRACE_ARGS;
71 level |= DEBUG_TRACE_EXPANSION;
75 level |= DEBUG_TRACE_QUOTE;
79 level |= DEBUG_TRACE_ALL;
83 level |= DEBUG_TRACE_LINE;
87 level |= DEBUG_TRACE_FILE;
91 level |= DEBUG_TRACE_PATH;
95 level |= DEBUG_TRACE_CALL;
99 level |= DEBUG_TRACE_INPUT;
103 level |= DEBUG_TRACE_CALLID;
107 level |= DEBUG_TRACE_VERBOSE;
116 /* This is to avoid screwing up the trace output due to changes in the
119 obstack_free (&trace, obstack_finish (&trace));
124 /*-----------------------------------------------------------------.
125 | Change the debug output stream to FP. If the underlying file is |
126 | the same as stdout, use stdout instead so that debug messages |
127 | appear in the correct relative position. |
128 `-----------------------------------------------------------------*/
131 debug_set_file (FILE *fp)
133 struct stat stdout_stat, debug_stat;
135 if (debug != NULL && debug != stderr && debug != stdout
136 && close_stream (debug) != 0)
138 M4ERROR ((warning_status, errno, "error writing to debug stream"));
139 retcode = EXIT_FAILURE;
143 if (debug != NULL && debug != stdout)
145 if (fstat (STDOUT_FILENO, &stdout_stat) < 0)
147 if (fstat (fileno (debug), &debug_stat) < 0)
150 /* mingw has a bug where fstat on a regular file reports st_ino
151 of 0. On normal system, st_ino should never be 0. */
152 if (stdout_stat.st_ino == debug_stat.st_ino
153 && stdout_stat.st_dev == debug_stat.st_dev
154 && stdout_stat.st_ino != 0)
156 if (debug != stderr && close_stream (debug) != 0)
158 M4ERROR ((warning_status, errno,
159 "error writing to debug stream"));
160 retcode = EXIT_FAILURE;
167 /*-----------------------------------------------------------.
168 | Serialize files. Used before executing a system command. |
169 `-----------------------------------------------------------*/
172 debug_flush_files (void)
176 if (debug != NULL && debug != stdout && debug != stderr)
178 /* POSIX requires that if m4 doesn't consume all input, but stdin is
179 opened on a seekable file, that the file pointer be left at the
180 next character on exit (but places no restrictions on the file
181 pointer location on a non-seekable file). It also requires that
182 fflush() followed by fseeko() on an input file set the underlying
183 file pointer, and gnulib guarantees these semantics. However,
184 fflush() on a non-seekable file can lose buffered data, which we
185 might otherwise want to process after syscmd. Hence, we must
186 check whether stdin is seekable. We must also be tolerant of
187 operating with stdin closed, so we don't report any failures in
188 this attempt. The stdio-safer module and friends are essential,
189 so that if stdin was closed, this lseek is not on some other file
190 that we have since opened. */
191 if (lseek (STDIN_FILENO, 0, SEEK_CUR) >= 0
192 && fflush (stdin) == 0)
194 fseeko (stdin, 0, SEEK_CUR);
198 /*--------------------------------------------------------------.
199 | Change the debug output to file NAME. If NAME is NULL, debug |
200 | output is reverted to stderr, and if empty, debug output is |
201 | discarded. Return true iff the output stream was changed. |
202 `--------------------------------------------------------------*/
205 debug_set_output (const char *name)
210 debug_set_file (stderr);
211 else if (*name == '\0')
212 debug_set_file (NULL);
215 fp = fopen (name, "a");
219 if (set_cloexec_flag (fileno (fp), true) != 0)
220 M4ERROR ((warning_status, errno,
221 "Warning: cannot protect debug file across forks"));
227 /*--------------------------------------------------------------.
228 | Print the header of a one-line debug message, starting by "m4 |
230 `--------------------------------------------------------------*/
233 debug_message_prefix (void)
235 xfprintf (debug, "m4debug:");
238 if (debug_level & DEBUG_TRACE_FILE)
239 xfprintf (debug, "%s:", current_file);
240 if (debug_level & DEBUG_TRACE_LINE)
241 xfprintf (debug, "%d:", current_line);
246 /* The rest of this file contains the functions for macro tracing output.
247 All tracing output for a macro call is collected on an obstack TRACE,
248 and printed whenever the line is complete. This prevents tracing
249 output from interfering with other debug messages generated by the
252 /*------------------------------------------------------------------.
253 | Tracing output is formatted here, by a simplified |
254 | printf-to-obstack function trace_format (). Understands only %S, |
255 | %s, %d, %l (optional left quote) and %r (optional right quote). |
256 `------------------------------------------------------------------*/
259 trace_format (const char *fmt, ...)
269 va_start (args, fmt);
273 while ((ch = *fmt++) != '\0' && ch != '%')
274 obstack_1grow (&trace, ch);
283 maxlen = max_debug_argument_length;
287 s = va_arg (args, const char *);
291 s = (debug_level & DEBUG_TRACE_QUOTE) ? lquote.string : "";
295 s = (debug_level & DEBUG_TRACE_QUOTE) ? rquote.string : "";
299 d = va_arg (args, int);
309 if (maxlen == 0 || maxlen > slen)
310 obstack_grow (&trace, s, slen);
313 obstack_grow (&trace, s, maxlen);
314 obstack_grow (&trace, "...", 3);
321 /*------------------------------------------------------------------.
322 | Format the standard header attached to all tracing output lines. |
323 `------------------------------------------------------------------*/
326 trace_header (int id)
328 trace_format ("m4trace:");
331 if (debug_level & DEBUG_TRACE_FILE)
332 trace_format ("%s:", current_file);
333 if (debug_level & DEBUG_TRACE_LINE)
334 trace_format ("%d:", current_line);
336 trace_format (" -%d- ", expansion_level);
337 if (debug_level & DEBUG_TRACE_CALLID)
338 trace_format ("id %d: ", id);
341 /*----------------------------------------------------.
342 | Print current tracing line, and clear the obstack. |
343 `----------------------------------------------------*/
350 obstack_1grow (&trace, '\0');
351 line = (char *) obstack_finish (&trace);
352 DEBUG_PRINT1 ("%s\n", line);
353 obstack_free (&trace, line);
356 /*-------------------------------------------------------------.
357 | Do pre-argument-collction tracing for macro NAME. Used from |
359 `-------------------------------------------------------------*/
362 trace_prepre (const char *name, int id)
365 trace_format ("%s ...", name);
369 /*--------------------------------------------------------------.
370 | Format the parts of a trace line, that can be made before the |
371 | macro is actually expanded. Used from expand_macro (). |
372 `--------------------------------------------------------------*/
375 trace_pre (const char *name, int id, int argc, token_data **argv)
381 trace_format ("%s", name);
383 if (argc > 1 && (debug_level & DEBUG_TRACE_ARGS))
387 for (i = 1; i < argc; i++)
392 switch (TOKEN_DATA_TYPE (argv[i]))
395 trace_format ("%l%S%r", TOKEN_DATA_TEXT (argv[i]));
399 bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[i]));
402 M4ERROR ((warning_status, 0, "\
403 INTERNAL ERROR: builtin not found in builtin table! (trace_pre ())"));
406 trace_format ("<%s>", bp->name);
411 M4ERROR ((warning_status, 0,
412 "INTERNAL ERROR: bad token data type (trace_pre ())"));
420 if (debug_level & DEBUG_TRACE_CALL)
422 trace_format (" -> ???");
427 /*-------------------------------------------------------------------.
428 | Format the final part of a trace line and print it all. Used from |
430 `-------------------------------------------------------------------*/
433 trace_post (const char *name, int id, int argc, const char *expanded)
435 if (debug_level & DEBUG_TRACE_CALL)
438 trace_format ("%s%s", name, (argc > 1) ? "(...)" : "");
441 if (expanded && (debug_level & DEBUG_TRACE_EXPANSION))
442 trace_format (" -> %l%S%r", expanded);