1 /* Output or logging functions for GNU Make.
2
3 Copyright (C) 2005, 2007, 2008, 2020 R. Bernstein <rocky@gnu.org>
4 This file is part of GNU Make (remake variant).
5 Copyright (C) 2004, 2005, 2007, 2008, Free Software Foundation, Inc.
6
7 GNU Make is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Make is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Make; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "makeint.h"
23 #include "make.h"
24 #include "main.h"
25 #include "commands.h"
26 #include "debugger/cmd.h"
27 #include "debug.h"
28 #include "dep.h"
29 #include "read.h"
30 #include "print.h"
31
32 #include <stdarg.h>
33
34 /* Think of the below not as an enumeration but as #defines done in a
35 way that we'll be able to use the value in a gdb. */
36 enum debug_print_enums_e debug_print_enums1;
37
38
39 /* Write a message indicating what directory we are in
40 and the make level number. */
41
42 static void
err_log_working_directory(void)43 err_log_working_directory (void)
44 {
45 static char *buf = NULL;
46 static unsigned int len = 0;
47 unsigned int need;
48 const char *fmt;
49 char *p;
50
51 /* Get enough space for the longest possible output. */
52 need = strlen (program) + INTSTR_LENGTH + 2 + 1;
53 if (starting_directory)
54 need += strlen (starting_directory);
55
56 /* Use entire sentences to give the translators a fighting chance. */
57 if (makelevel == 0)
58 if (starting_directory == 0)
59 fmt = _("%s\n");
60 else
61 fmt = _("%s: directory '%s'\n");
62 else
63 if (starting_directory == 0)
64 fmt = _("%s[%u]: unknown directory\n");
65 else
66 fmt = _("%s[%u]: directory '%s'\n");
67
68 need += strlen (fmt);
69
70 if (need > len)
71 {
72 buf = xrealloc (buf, need);
73 len = need;
74 }
75
76 p = buf;
77 if (print_data_base_flag)
78 {
79 *(p++) = '#';
80 *(p++) = ' ';
81 }
82
83 if (makelevel == 0)
84 if (starting_directory == 0)
85 sprintf (p, fmt , program);
86 else
87 sprintf (p, fmt, program, starting_directory);
88 else if (starting_directory == 0)
89 sprintf (p, fmt, program, makelevel);
90 else
91 sprintf (p, fmt, program, makelevel, starting_directory);
92
93 outputs (0, buf);
94 }
95
96
97 void
err_with_stack(target_stack_node_t * p_call,const char * fmt,...)98 err_with_stack (target_stack_node_t *p_call, const char *fmt, ...)
99 {
100 va_list args;
101 gmk_floc *p_floc = NULL;
102 file_t *p_target = NULL;
103
104 if (p_call && p_call->p_target) {
105 p_target = p_call->p_target;
106 p_floc = &(p_target->floc);
107 }
108
109 if (p_floc) {
110 if (!p_floc->filenm)
111 fprintf (stderr, "<builtin>");
112 else
113 fprintf (stderr, "%s:%lu: ", p_floc->filenm, p_floc->lineno + p_floc->offset);
114 } else {
115 err_log_working_directory ();
116 if (makelevel == 0)
117 fprintf (stderr, "%s: ", program);
118 else
119 fprintf (stderr, "%s[%u]: ", program, makelevel);
120 }
121
122 va_start (args, fmt);
123 vfprintf (stderr, fmt, args);
124 va_end (args);
125
126 putc ('\n', stderr);
127 if (!no_extended_errors) {
128 if (p_call) {
129 putc ('\n', stdout);
130 print_target_stack(p_call, -1, MAX_STACK_SHOW);
131 } else if (p_stack_floc_top) {
132 putc ('\n', stdout);
133 print_floc_stack(-1, MAX_STACK_SHOW);
134 }
135 }
136 fflush (stdout);
137 fflush (stderr);
138 if (debugger_on_error & DEBUGGER_ON_ERROR)
139 enter_debugger(p_call, p_target, -1, DEBUG_ERROR_HIT);
140 }
141
142 /* Print an error message and exit. */
143 void
fatal_err(target_stack_node_t * p_call,const char * fmt,...)144 fatal_err (target_stack_node_t *p_call, const char *fmt, ...)
145 {
146 va_list args;
147 gmk_floc *p_floc = NULL;
148 file_t *p_target = NULL;
149
150 err_log_working_directory ();
151
152 if (p_call && p_call->p_target) {
153 p_target = p_call->p_target;
154 p_floc = &(p_target->floc);
155 }
156
157 if (p_floc && p_floc->filenm)
158 fprintf (stderr, "%s:%lu: *** ", p_floc->filenm, p_floc->lineno);
159 else if (makelevel == 0)
160 fprintf (stderr, "%s: *** ", program);
161 else
162 fprintf (stderr, "%s[%u]: *** ", program, makelevel);
163
164 va_start (args, fmt);
165 vfprintf (stderr, fmt, args);
166 va_end (args);
167
168 fputs (_(". Stop.\n"), stderr);
169 if (!no_extended_errors) {
170 if (p_call)
171 print_target_stack(p_call, -1, MAX_STACK_SHOW);
172 else if (p_stack_floc_top)
173 print_floc_stack(-1, MAX_STACK_SHOW);
174 }
175 if ( (debugger_on_error & DEBUGGER_ON_FATAL) || debugger_enabled )
176 enter_debugger(p_call, p_target, 2, DEBUG_ERROR_HIT);
177 die (MAKE_FAILURE);
178 }
179
180 /*! Under -d, write a message describing the current IDs. */
181
182 void
log_access(char * flavor)183 log_access (char *flavor)
184 {
185 if (! ISDB (DB_JOBS))
186 return;
187
188 /* All the other debugging messages go to stdout,
189 but we write this one to stderr because it might be
190 run in a child fork whose stdout is piped. */
191
192 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
193 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
194 (unsigned long) getegid (), (unsigned long) getgid ());
195 fflush (stderr);
196 }
197
198 /*! Display a variable and its value. */
199 void
print_variable(variable_t * p_v)200 print_variable (variable_t *p_v)
201 {
202 if (p_v) {
203 const char *psz_origin = origin2str(p_v->origin);
204 if (NULL != p_v->fileinfo.filenm) {
205 printf(_("%s:%lu (origin: %s) %s = %s\n"),
206 p_v->fileinfo.filenm, p_v->fileinfo.lineno,
207 psz_origin,
208 p_v->name, p_v->value);
209 } else {
210 printf("(origin %s) %s = %s\n", psz_origin, p_v->name, p_v->value);
211 }
212 }
213 }
214
215 /*! Display a variable and its value with all substitutions included. */
216 void
print_variable_expand(variable_t * p_v)217 print_variable_expand (variable_t *p_v)
218 {
219 if (p_v) {
220 const char *psz_origin = origin2str(p_v->origin);
221 if (NULL != p_v->fileinfo.filenm) {
222 printf(_("%s:%lu (origin: %s) %s := %s\n"),
223 p_v->fileinfo.filenm, p_v->fileinfo.lineno,
224 psz_origin,
225 p_v->name, variable_expand(p_v->value));
226 } else {
227 printf("(origin %s) %s := %s\n", psz_origin,
228 p_v->name, variable_expand(p_v->value));
229 }
230 }
231 }
232
233 /*! Show a command before executing it. */
234 extern void
print_target_prefix(const char * p_name)235 print_target_prefix (const char *p_name)
236 {
237 printf(" %s", p_name);
238 if (makelevel != 0) {
239 printf ("[%u]", makelevel);
240 }
241 }
242
243 /*! Show target information: location and name. */
244 extern void
print_file_target_prefix(const file_t * p_target)245 print_file_target_prefix (const file_t *p_target)
246 {
247 print_floc_prefix(&(p_target->floc));
248 print_target_prefix(p_target->name);
249 }
250
251 /*! Show a command before executing it. */
252 extern void
print_floc_prefix(const gmk_floc * p_floc)253 print_floc_prefix (const gmk_floc *p_floc)
254 {
255 if (!p_floc) return;
256 if (p_floc->filenm) {
257 if (!basename_filenames && strlen(p_floc->filenm)
258 && p_floc->filenm[0] != '/')
259 printf("%s/", starting_directory);
260 printf("%s:%lu", p_floc->filenm, p_floc->lineno);
261 } else {
262 if (!basename_filenames)
263 printf("%s/", starting_directory);
264 printf("??:%lu", p_floc->lineno);
265 }
266 }
267
268 /*! Show a command before executing it. */
269 extern debug_return_t
print_child_cmd(child_t * p_child,target_stack_node_t * p)270 print_child_cmd (child_t *p_child, target_stack_node_t *p)
271 {
272 debug_return_t rc = continue_execution;
273
274
275 if (!p_child) return continue_execution;
276
277 if (i_debugger_stepping || p_child->file->tracing) {
278 debug_enter_reason_t reason = DEBUG_STEP_HIT;
279 if (i_debugger_stepping)
280 reason = DEBUG_STEP_HIT;
281 else if (p_child->file->tracing & BRK_BEFORE_PREREQ)
282 reason = DEBUG_BRKPT_BEFORE_PREREQ;
283 else if (p_child->file->tracing & BRK_BEFORE_PREREQ)
284 reason = DEBUG_BRKPT_AFTER_PREREQ;
285
286 rc=enter_debugger(p, p_child->file, 0, reason);
287 }
288
289 return rc;
290 }
291
292 void
print_target_stack_entry(const file_t * p_target,int i,int i_pos)293 print_target_stack_entry (const file_t *p_target, int i, int i_pos)
294 {
295 gmk_floc floc;
296 const char *psz_target_name =
297 (p_target && p_target->name) ? p_target->name : "(null)";
298
299 /* If we don't have a line recorded for the target,
300 but we do have one for the commands it runs,
301 use that.
302 */
303 if (p_target->floc.filenm) {
304 memcpy(&floc, &(p_target->floc), sizeof(gmk_floc));
305 } else if (p_target->cmds) {
306 memcpy(&floc, &(p_target->cmds->fileinfo.filenm), sizeof(gmk_floc));
307 /* HACK: is it okay to assume that the target is on the line
308 before the first command? Or should we list the line
309 that the command starts on - so we know we've faked the location?
310 */
311 floc.lineno--;
312 } else {
313 floc.filenm = NULL;
314 }
315
316 if (floc.filenm) {
317 if (i_pos != -1) {
318 printf("%s", (i == i_pos) ? "=>" : " ");
319 }
320 printf ("#%d %s at ", i, psz_target_name);
321 print_floc_prefix(&floc);
322 } else {
323 if (i_pos != -1) {
324 printf("%s", (i == i_pos) ? "=>" : " ");
325 }
326 if (p_target->phony)
327 printf ("#%d %s (.PHONY target)", i, psz_target_name);
328 else
329 printf ("#%d %s at ??", i, psz_target_name);
330
331 }
332 printf ("\n");
333 }
334
335
336 /*! Display the target stack. i_pos is the position we are currently.
337 i_max is the maximum number of entries to show.
338 */
339 extern void
print_target_stack(target_stack_node_t * p,int i_pos,int i_max)340 print_target_stack (target_stack_node_t *p, int i_pos, int i_max)
341 {
342 int i=0;
343 for ( ; p && i < i_max ;
344 i++, p = p->p_parent ) {
345 print_target_stack_entry (p->p_target, i, i_pos);
346 }
347 }
348
349 /*! Display the Makefile read stack. i_pos is the position we are currently.
350 i_max is the maximum number of entries to show. */
351 extern void
print_floc_stack(int i_pos,int i_max)352 print_floc_stack (int i_pos, int i_max)
353 {
354 int i=0;
355 floc_stack_node_t *p;
356 printf("\n");
357 for ( p=p_stack_floc_top; p && i < i_max ;
358 i++, p = p->p_parent ) {
359 if (i_pos != -1) {
360 printf("%s", (i == i_pos) ? "=>" : " ");
361 }
362 printf ("#%d ", i);
363 if (p->p_floc->filenm) {
364 print_floc_prefix(p->p_floc);
365 }
366 printf ("\n");
367 }
368 }
369
370 /*! Print the file information. */
print_file(file_t * p_file)371 void print_file (file_t *p_file)
372 {
373 char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
374 printf("File %s:\n", p_file->name);
375 file_timestamp_sprintf (buf, p_file->last_mtime);
376 printf("\tLast modified: %s\n", buf);
377 if (p_file->mtime_before_update != p_file->last_mtime) {
378 file_timestamp_sprintf (buf, p_file->mtime_before_update);
379 printf("\tBefore update: %s\n", buf);
380 }
381 printf("\tNumber of lines: %u\n", p_file->nlines);
382 }
383
384 /*! Print the list makefiles read by read_makefiles(). */
print_read_makefiles(const char * psz_filename)385 bool print_read_makefiles(const char *psz_filename)
386 {
387 goaldep_t *p_dep;
388 if (!read_makefiles) return false;
389 if (NULL == psz_filename) {
390 for (p_dep = read_makefiles; p_dep; p_dep = p_dep->next) {
391 if (p_dep->file) {
392 print_file(p_dep->file);
393 }
394 }
395 return true;
396 } else {
397 for (p_dep = read_makefiles; p_dep; p_dep = p_dep->next) {
398 if (p_dep->file && 0 == strcmp(p_dep->file->name, psz_filename)) {
399 print_file(p_dep->file);
400 return true;
401 }
402 }
403 }
404 return false;
405 }
406
407 /*! Print the command line used to invoke Make. */
print_cmdline(void)408 void print_cmdline (void)
409 {
410 unsigned int i;
411 printf(_("Command-line invocation:"));
412 printf("\n\t\"");
413 if (global_argv[1]) {
414 printf("%s", argv0);
415 for (i = 1; global_argv[i]; i++) {
416 printf(" %s", global_argv[i]);
417 }
418 printf("\"");
419 } else {
420 printf(_(" none"));
421 }
422 printf("\n");
423 }
424
425
426 /*
427 * Local variables:
428 * eval: (c-set-style "gnu")
429 * indent-tabs-mode: nil
430 * End:
431 */
432