Make intra-release version numbers more intelligent.
[m4/ericb.git] / src / debug.c
blob46e1306f76269dc4204eb7f7adf599cdad697e4a
1 /* GNU m4 -- A simple macro processor
3 Copyright (C) 1991, 1992, 1993, 1994, 2004, 2006, 2007, 2008 Free
4 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 <http://www.gnu.org/licenses/>.
22 #include "m4.h"
24 #include <stdarg.h>
25 #include <sys/stat.h>
27 /* File for debugging output. */
28 FILE *debug = NULL;
30 /* Obstack for trace messages. */
31 static struct obstack trace;
33 static void debug_set_file (const char *, FILE *);
35 /*----------------------------------.
36 | Initialise the debugging module. |
37 `----------------------------------*/
39 void
40 debug_init (void)
42 debug_set_file (NULL, 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 `-----------------------------------------------------------------*/
51 int
52 debug_decode (const char *opts)
54 int level;
56 if (opts == NULL || *opts == '\0')
57 level = DEBUG_TRACE_DEFAULT;
58 else
60 for (level = 0; *opts; opts++)
62 switch (*opts)
64 case 'a':
65 level |= DEBUG_TRACE_ARGS;
66 break;
68 case 'e':
69 level |= DEBUG_TRACE_EXPANSION;
70 break;
72 case 'q':
73 level |= DEBUG_TRACE_QUOTE;
74 break;
76 case 't':
77 level |= DEBUG_TRACE_ALL;
78 break;
80 case 'l':
81 level |= DEBUG_TRACE_LINE;
82 break;
84 case 'f':
85 level |= DEBUG_TRACE_FILE;
86 break;
88 case 'p':
89 level |= DEBUG_TRACE_PATH;
90 break;
92 case 'c':
93 level |= DEBUG_TRACE_CALL;
94 break;
96 case 'i':
97 level |= DEBUG_TRACE_INPUT;
98 break;
100 case 'x':
101 level |= DEBUG_TRACE_CALLID;
102 break;
104 case 'V':
105 level |= DEBUG_TRACE_VERBOSE;
106 break;
108 default:
109 return -1;
113 return level;
116 /*------------------------------------------------------------------------.
117 | Change the debug output stream to FP. If the underlying file is the |
118 | same as stdout, use stdout instead so that debug messages appear in the |
119 | correct relative position. |
120 `------------------------------------------------------------------------*/
122 static void
123 debug_set_file (const char *caller, FILE *fp)
125 struct stat stdout_stat, debug_stat;
127 if (debug != NULL && debug != stderr && debug != stdout
128 && close_stream (debug) != 0)
129 m4_error (0, errno, caller, _("error writing to debug stream"));
130 debug = fp;
132 if (debug != NULL && debug != stdout)
134 if (fstat (STDOUT_FILENO, &stdout_stat) < 0)
135 return;
136 if (fstat (fileno (debug), &debug_stat) < 0)
137 return;
139 /* mingw has a bug where fstat on a regular file reports st_ino
140 of 0. On normal system, st_ino should never be 0. */
141 if (stdout_stat.st_ino == debug_stat.st_ino
142 && stdout_stat.st_dev == debug_stat.st_dev
143 && stdout_stat.st_ino != 0)
145 if (debug != stderr && close_stream (debug) != 0)
146 m4_error (0, errno, caller, _("error writing to debug stream"));
147 debug = stdout;
152 /*-----------------------------------------------------------.
153 | Serialize files. Used before executing a system command. |
154 `-----------------------------------------------------------*/
156 void
157 debug_flush_files (void)
159 fflush (stdout);
160 fflush (stderr);
161 if (debug != NULL && debug != stdout && debug != stderr)
162 fflush (debug);
163 /* POSIX requires that if m4 doesn't consume all input, but stdin is
164 opened on a seekable file, that the file pointer be left at the
165 next character on exit (but places no restrictions on the file
166 pointer location on a non-seekable file). It also requires that
167 fflush() followed by fseeko() on an input file set the underlying
168 file pointer, and gnulib guarantees these semantics. However,
169 fflush() on a non-seekable file can lose buffered data, which we
170 might otherwise want to process after syscmd. Hence, we must
171 check whether stdin is seekable. We must also be tolerant of
172 operating with stdin closed, so we don't report any failures in
173 this attempt. The stdio-safer module and friends are essential,
174 so that if stdin was closed, this lseek is not on some other file
175 that we have since opened. */
176 if (lseek (STDIN_FILENO, 0, SEEK_CUR) >= 0
177 && fflush (stdin) == 0)
179 fseeko (stdin, 0, SEEK_CUR);
183 /*-------------------------------------------------------------------.
184 | Change the debug output to file NAME. If NAME is NULL, debug |
185 | output is reverted to stderr, and if empty, debug output is |
186 | discarded. Return true iff the output stream was changed. Report |
187 | errors on behalf of CALLER. |
188 `-------------------------------------------------------------------*/
190 bool
191 debug_set_output (const char *caller, const char *name)
193 FILE *fp;
195 if (name == NULL)
196 debug_set_file (caller, stderr);
197 else if (*name == '\0')
198 debug_set_file (caller, NULL);
199 else
201 fp = fopen (name, "a");
202 if (fp == NULL)
203 return false;
205 if (set_cloexec_flag (fileno (fp), true) != 0)
206 m4_warn (errno, caller, _("cannot protect debug file across forks"));
207 debug_set_file (caller, fp);
209 return true;
212 /*-----------------------------------------------------------------------.
213 | Print the header of a one-line debug message, starting by "m4 debug". |
214 `-----------------------------------------------------------------------*/
216 void
217 debug_message_prefix (void)
219 xfprintf (debug, "m4debug:");
220 if (current_line)
222 if (debug_level & DEBUG_TRACE_FILE)
223 xfprintf (debug, "%s:", current_file);
224 if (debug_level & DEBUG_TRACE_LINE)
225 xfprintf (debug, "%d:", current_line);
227 putc (' ', debug);
230 /* The rest of this file contains the functions for macro tracing output.
231 All tracing output for a macro call is collected on an obstack TRACE,
232 and printed whenever the line is complete. This prevents tracing
233 output from interfering with other debug messages generated by the
234 various builtins. */
236 /*-------------------------------------------------------------------.
237 | Tracing output to the obstack is formatted here, by a simplified |
238 | printf-like function trace_format (). Understands only %B (1 arg: |
239 | input block), %S (1 arg: length-limited text), %s (1 arg: text), |
240 | %d (1 arg: integer), %l (0 args: optional left quote) and %r (0 |
241 | args: optional right quote). |
242 `-------------------------------------------------------------------*/
244 static void
245 trace_format (const char *fmt, ...)
247 va_list args;
248 char ch;
249 int d;
250 const char *s;
251 size_t maxlen;
253 va_start (args, fmt);
255 while (true)
257 while ((ch = *fmt++) != '\0' && ch != '%')
258 obstack_1grow (&trace, ch);
260 if (ch == '\0')
261 break;
263 maxlen = SIZE_MAX;
264 switch (*fmt++)
266 case 'B':
267 s = "";
268 input_print (&trace, va_arg (args, input_block *));
269 break;
271 case 'S':
272 maxlen = max_debug_argument_length;
273 /* fall through */
275 case 's':
276 s = va_arg (args, const char *);
277 break;
279 case 'l':
280 s = (debug_level & DEBUG_TRACE_QUOTE) ? curr_quote.str1 : "";
281 break;
283 case 'r':
284 s = (debug_level & DEBUG_TRACE_QUOTE) ? curr_quote.str2 : "";
285 break;
287 case 'd':
288 d = va_arg (args, int);
289 s = ntoa (d, 10);
290 break;
292 default:
293 s = "";
294 break;
297 if (shipout_string_trunc (&trace, s, SIZE_MAX, &maxlen))
298 break;
301 va_end (args);
304 /*------------------------------------------------------------------.
305 | Format the standard header attached to all tracing output lines. |
306 | ID is the current macro id. |
307 `------------------------------------------------------------------*/
309 static void
310 trace_header (int id)
312 trace_format ("m4trace:");
313 if (current_line)
315 if (debug_level & DEBUG_TRACE_FILE)
316 trace_format ("%s:", current_file);
317 if (debug_level & DEBUG_TRACE_LINE)
318 trace_format ("%d:", current_line);
320 trace_format (" -%d- ", expansion_level);
321 if (debug_level & DEBUG_TRACE_CALLID)
322 trace_format ("id %d: ", id);
325 /*----------------------------------------------------.
326 | Print current tracing line, and clear the obstack. |
327 `----------------------------------------------------*/
329 static void
330 trace_flush (void)
332 char *line;
334 obstack_1grow (&trace, '\0');
335 line = (char *) obstack_finish (&trace);
336 DEBUG_PRINT1 ("%s\n", line);
337 obstack_free (&trace, line);
340 /*----------------------------------------------------------------.
341 | Do pre-argument-collection tracing for macro NAME, with a given |
342 | ID. Used from expand_macro (). |
343 `----------------------------------------------------------------*/
345 void
346 trace_prepre (const char *name, int id)
348 trace_header (id);
349 trace_format ("%s ...", name);
350 trace_flush ();
353 /*-----------------------------------------------------------------.
354 | Format the parts of a trace line that are known before the macro |
355 | is actually expanded. Called for the macro NAME with ID, and |
356 | arguments ARGV. Used from expand_macro (). |
357 `-----------------------------------------------------------------*/
359 void
360 trace_pre (const char *name, int id, macro_arguments *argv)
362 trace_header (id);
363 trace_format ("%s", name);
365 if (arg_argc (argv) > 1 && (debug_level & DEBUG_TRACE_ARGS))
367 size_t len = max_debug_argument_length;
368 trace_format ("(");
369 arg_print (&trace, argv, 1,
370 (debug_level & DEBUG_TRACE_QUOTE) ? &curr_quote : NULL,
371 false, ", ", &len, true);
372 trace_format (")");
375 if (debug_level & DEBUG_TRACE_CALL)
377 trace_format (" -> ???");
378 trace_flush ();
382 /*-------------------------------------------------------------------.
383 | Format the final part of a trace line and print it all. Print |
384 | details for macro NAME with ID, given arguemnts ARGV and expansion |
385 | EXPANDED. Used from expand_macro (). |
386 `-------------------------------------------------------------------*/
388 void
389 trace_post (const char *name, int id, macro_arguments *argv,
390 const input_block *expanded)
392 int argc = arg_argc (argv);
394 if (debug_level & DEBUG_TRACE_CALL)
396 trace_header (id);
397 trace_format ("%s%s", name, (argc > 1) ? "(...)" : "");
400 if (expanded && (debug_level & DEBUG_TRACE_EXPANSION))
401 trace_format (" -> %l%B%r", expanded);
402 trace_flush ();