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