1 /* GNU m4 -- A simple macro processor
3 Copyright (C) 1991-1994, 2004, 2006-2007, 2009-2014, 2016-2017,
4 2020-2021 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>.
27 /* File for debugging output. */
30 /* Obstack for trace messages. */
31 static struct obstack trace;
33 static void debug_set_file (FILE *);
35 /*----------------------------------.
36 | Initialise the debugging module. |
37 `----------------------------------*/
42 debug_set_file (stderr);
43 obstack_init (&trace);
46 /*-----------------------------------------------------------------.
47 | Function to decode the debugging flags OPTS. Used by main while |
48 | processing option -d, and by the builtin debugmode (). |
49 `-----------------------------------------------------------------*/
52 debug_decode (const char *opts)
56 if (opts == NULL || *opts == '\0')
57 level = DEBUG_TRACE_DEFAULT;
60 for (level = 0; *opts; opts++)
65 level |= DEBUG_TRACE_ARGS;
69 level |= DEBUG_TRACE_EXPANSION;
73 level |= DEBUG_TRACE_QUOTE;
77 level |= DEBUG_TRACE_ALL;
81 level |= DEBUG_TRACE_LINE;
85 level |= DEBUG_TRACE_FILE;
89 level |= DEBUG_TRACE_PATH;
93 level |= DEBUG_TRACE_CALL;
97 level |= DEBUG_TRACE_INPUT;
101 level |= DEBUG_TRACE_CALLID;
105 level |= DEBUG_TRACE_VERBOSE;
114 /* This is to avoid screwing up the trace output due to changes in the
117 obstack_free (&trace, obstack_finish (&trace));
122 /*-----------------------------------------------------------------.
123 | Change the debug output stream to FP. If the underlying file is |
124 | the same as stdout, use stdout instead so that debug messages |
125 | appear in the correct relative position. |
126 `-----------------------------------------------------------------*/
129 debug_set_file (FILE *fp)
131 struct stat stdout_stat, debug_stat;
133 if (debug != NULL && debug != stderr && debug != stdout
134 && close_stream (debug) != 0)
136 M4ERROR ((warning_status, errno, _("error writing to debug stream")));
137 retcode = EXIT_FAILURE;
141 if (debug != NULL && debug != stdout)
143 if (fstat (STDOUT_FILENO, &stdout_stat) < 0)
145 if (fstat (fileno (debug), &debug_stat) < 0)
148 /* mingw has a bug where fstat on a regular file reports st_ino
149 of 0. On normal system, st_ino should never be 0. */
150 if (stdout_stat.st_ino == debug_stat.st_ino
151 && stdout_stat.st_dev == debug_stat.st_dev
152 && stdout_stat.st_ino != 0)
154 if (debug != stderr && close_stream (debug) != 0)
156 M4ERROR ((warning_status, errno,
157 _("error writing to debug stream")));
158 retcode = EXIT_FAILURE;
165 /*-----------------------------------------------------------.
166 | Serialize files. Used before executing a system command. |
167 `-----------------------------------------------------------*/
170 debug_flush_files (void)
174 if (debug != NULL && debug != stdout && debug != stderr)
176 /* POSIX requires that if m4 doesn't consume all input, but stdin is
177 opened on a seekable file, that the file pointer be left at the
178 next character on exit (but places no restrictions on the file
179 pointer location on a non-seekable file). It also requires that
180 fflush() followed by fseeko() on an input file set the underlying
181 file pointer, and gnulib guarantees these semantics. However,
182 fflush() on a non-seekable file can lose buffered data, which we
183 might otherwise want to process after syscmd. Hence, we must
184 check whether stdin is seekable. We must also be tolerant of
185 operating with stdin closed, so we don't report any failures in
186 this attempt. The stdio-safer module and friends are essential,
187 so that if stdin was closed, this lseek is not on some other file
188 that we have since opened. */
189 if (lseek (STDIN_FILENO, 0, SEEK_CUR) >= 0
190 && fflush (stdin) == 0)
192 fseeko (stdin, 0, SEEK_CUR);
196 /*--------------------------------------------------------------.
197 | Change the debug output to file NAME. If NAME is NULL, debug |
198 | output is reverted to stderr, and if empty, debug output is |
199 | discarded. Return true iff the output stream was changed. |
200 `--------------------------------------------------------------*/
203 debug_set_output (const char *name)
208 debug_set_file (stderr);
209 else if (*name == '\0')
210 debug_set_file (NULL);
213 fp = fopen (name, "ae");
221 /*--------------------------------------------------------------.
222 | Print the header of a one-line debug message, starting by "m4 |
224 `--------------------------------------------------------------*/
227 debug_message_prefix (void)
229 xfprintf (debug, "m4debug:");
232 if (debug_level & DEBUG_TRACE_FILE)
233 xfprintf (debug, "%s:", current_file);
234 if (debug_level & DEBUG_TRACE_LINE)
235 xfprintf (debug, "%d:", current_line);
240 /* The rest of this file contains the functions for macro tracing output.
241 All tracing output for a macro call is collected on an obstack TRACE,
242 and printed whenever the line is complete. This prevents tracing
243 output from interfering with other debug messages generated by the
246 /*------------------------------------------------------------------.
247 | Tracing output is formatted here, by a simplified |
248 | printf-to-obstack function trace_format (). Understands only %S, |
249 | %s, %d, %l (optional left quote) and %r (optional right quote). |
250 `------------------------------------------------------------------*/
253 trace_format (const char *fmt, ...)
263 va_start (args, fmt);
267 while ((ch = *fmt++) != '\0' && ch != '%')
268 obstack_1grow (&trace, ch);
277 maxlen = max_debug_argument_length;
280 s = va_arg (args, const char *);
284 s = (debug_level & DEBUG_TRACE_QUOTE) ? lquote.string : "";
288 s = (debug_level & DEBUG_TRACE_QUOTE) ? rquote.string : "";
292 d = va_arg (args, int);
302 if (maxlen == 0 || maxlen > slen)
303 obstack_grow (&trace, s, slen);
306 obstack_grow (&trace, s, maxlen);
307 obstack_grow (&trace, "...", 3);
314 /*------------------------------------------------------------------.
315 | Format the standard header attached to all tracing output lines. |
316 `------------------------------------------------------------------*/
319 trace_header (int id)
321 trace_format ("m4trace:");
324 if (debug_level & DEBUG_TRACE_FILE)
325 trace_format ("%s:", current_file);
326 if (debug_level & DEBUG_TRACE_LINE)
327 trace_format ("%d:", current_line);
329 trace_format (" -%d- ", expansion_level);
330 if (debug_level & DEBUG_TRACE_CALLID)
331 trace_format ("id %d: ", id);
334 /*----------------------------------------------------.
335 | Print current tracing line, and clear the obstack. |
336 `----------------------------------------------------*/
343 obstack_1grow (&trace, '\0');
344 line = (char *) obstack_finish (&trace);
345 DEBUG_PRINT1 ("%s\n", line);
346 obstack_free (&trace, line);
349 /*-------------------------------------------------------------.
350 | Do pre-argument-collction tracing for macro NAME. Used from |
352 `-------------------------------------------------------------*/
355 trace_prepre (const char *name, int id)
358 trace_format ("%s ...", name);
362 /*--------------------------------------------------------------.
363 | Format the parts of a trace line, that can be made before the |
364 | macro is actually expanded. Used from expand_macro (). |
365 `--------------------------------------------------------------*/
368 trace_pre (const char *name, int id, int argc, token_data **argv)
374 trace_format ("%s", name);
376 if (argc > 1 && (debug_level & DEBUG_TRACE_ARGS))
380 for (i = 1; i < argc; i++)
385 switch (TOKEN_DATA_TYPE (argv[i]))
388 trace_format ("%l%S%r", TOKEN_DATA_TEXT (argv[i]));
392 bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[i]));
395 M4ERROR ((warning_status, 0, "\
396 INTERNAL ERROR: builtin not found in builtin table! (trace_pre ())"));
399 trace_format ("<%s>", bp->name);
404 M4ERROR ((warning_status, 0,
405 "INTERNAL ERROR: bad token data type (trace_pre ())"));
413 if (debug_level & DEBUG_TRACE_CALL)
415 trace_format (" -> ???");
420 /*-------------------------------------------------------------------.
421 | Format the final part of a trace line and print it all. Used from |
423 `-------------------------------------------------------------------*/
426 trace_post (const char *name, int id, int argc, const char *expanded)
428 if (debug_level & DEBUG_TRACE_CALL)
431 trace_format ("%s%s", name, (argc > 1) ? "(...)" : "");
434 if (expanded && (debug_level & DEBUG_TRACE_EXPANSION))
435 trace_format (" -> %l%S%r", expanded);