remake  4.3+dbg-1.5
command/info.h
Go to the documentation of this file.
1 /*
2 Copyright (C) 2008, 2011, 2020 R. Bernstein rocky@gnu.org
3 This file is part of GNU Make (remake variant).
4 
5 GNU Make is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9 
10 GNU Make is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with GNU Make; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19 
20 #include "../../file.h"
21 #include "../../implicit.h"
22 #include "../../print.h"
23 #include "../../main.h"
24 #include "../../rule.h"
25 #include "../../debug.h"
26 #include "../../vpath.h"
27 #include "../info.h"
28 #include "../msg.h"
29 #include "../stack.h"
30 #include "../file2line.h"
31 
32 const char *WARRANTY =
33 " NO WARRANTY\n"
34 "\n"
35 " 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
36 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
37 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
38 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
39 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
40 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
41 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
42 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
43 "REPAIR OR CORRECTION.\n"
44 "\n"
45 " 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
46 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
47 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
48 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
49 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
50 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
51 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
52 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
53 "POSSIBILITY OF SUCH DAMAGES.\n";
54 
55 #include "../subcmd.h"
56 
58  { "break",
59  "Show list of target breakpoints",
60  "\n\nShow list of target breakpoints.",
61  NULL, false,
62  1},
63  { "line",
64  "Show where we are currently stopped",
65  "\n\nShow line and Makefile name of where we are currently stopped.",
66  NULL, false,
67  2},
68  { "lines",
69  "Show possible breakpoint lines for all targets",
70  "\n\nShow possible breakpoint lines for all targets.",
71  NULL, false,
72  2},
73  { "locals",
74  "Show target local variables and their values",
75  "\n\nShow target local variables and their values.",
76  NULL, false,
77  2},
78  { "files",
79  "Show read-in Makefiles",
80  "\n\nShow read-in Makefiles. The last is the one initially named.",
81  NULL, false,
82  2},
83  { "frame",
84  "Show target-stack frame",
85  "\n\nShow target-stack frame.",
86  NULL, false,
87  2},
88  { "rules",
89  "Show implicit or pattern rules",
90  " [VERBOSE]\n\n"
91 "Show implicit or pattern rules. Add VERBOSE if you want more info."
92  ,
93  NULL, false,
94  1},
95  { "program",
96  "Show program information and why we are stopped",
97  "\n\nShow program information and why we are stopped.",
98  NULL, false,
99  1},
100  { "target",
101  "Same as 'target'",
102  "\n\nShow specific target information. See 'help target'.",
103  NULL, false,
104  1},
105  { "targets",
106  "Show a list of target names and file locations",
107  " [NAMES|POSITIONS|TASKS|ALL]\n\n"
108 "Show the explicitly-named targets found in read Makefiles.\n"
109 "Suboptions are as follows:\n"
110 " NAMES -- shows target names,\n"
111 " POSITIONS -- shows the location in the Makefile\n"
112 " ALL -- shows names and location\n"
113 " TASKS -- shows target name if it has commands associated with it\n"
114 "\n"
115 "The default is ALL.",
116  NULL, false,
117  7},
118  { "tasks",
119  "Show a list of tasks and their descriptions",
120  "\n",
121  NULL, false,
122  3},
123  { "variables",
124  "Show all GNU Make variables",
125  "\n\nShow all GNU Make variables.",
126  NULL, false,
127  2},
128  { "warranty",
129  "Various kinds of warranty you do not have",
130  "\n\nVarious kinds of warranty you do not have.",
131  NULL, false,
132  1},
133  { NULL, NULL, NULL, NULL, false, 0}
134 };
135 
137 static void
138 dbg_cmd_info_target_entry (const file_t *p_target,
139  info_target_output_mask_t output_mask)
140 {
141  const gmk_floc *p_floc = &p_target->floc;
142  if (p_floc) {
143  if ((p_floc->filenm) && (output_mask & INFO_TARGET_POSITION)) {
144  printf("%s:%lu", p_floc->filenm, p_floc->lineno);
145  if (output_mask & INFO_TARGET_NAME)
146  printf(":\n");
147  else
148  printf("\n");
149  }
150  }
151  if (output_mask & INFO_TARGET_NAME) {
152  printf("\t%s", p_target->name);
153  if (p_target->description)
154  printf("\t# %s", p_target->description);
155  printf("\n");
156  } else if
157  ( (output_mask & INFO_TARGET_TASKS
158  && (p_target->cmds || p_target->phony)
159  && p_floc->filenm)
160  || (output_mask & INFO_TARGET_NAME) ) {
161  if (p_target->description) {
162  printf("%s", p_target->name);
163  printf("\t# %s\n", p_target->description);
164  } else if (!(output_mask & INFO_TARGET_TASK_COMMENT)) {
165  printf("%s\n", p_target->name);
166  }
167  }
168 }
169 
170 int
171 dbg_target_compare(const void *p1, const void *p2)
172 {
173  const struct file *p_target1 = *(const file_t **) p1;
174  const struct file *p_target2 = *(const file_t **) p2;
175  return strcmp(p_target1->name, p_target2->name);
176 }
177 
178 void
180 {
181  struct file **file_slot_0 = (struct file **) hash_dump (&files, 0,
183  struct file **file_end = file_slot_0 + files.ht_fill;
184  struct file **pp_file_slot;
185  struct file *p_target;
186 
187  for (pp_file_slot = file_slot_0; pp_file_slot < file_end; pp_file_slot++) {
188  if ((p_target = *pp_file_slot) != NULL)
189  dbg_cmd_info_target_entry(p_target, output_mask);
190  }
191 }
192 
193 void
195 {
196  struct file **file_slot_0 = (struct file **) hash_dump (&files, 0,
198  struct file **file_end = file_slot_0 + files.ht_fill;
199  struct file **pp_file_slot;
200  struct file *p_target;
201 
202  for (pp_file_slot = file_slot_0; pp_file_slot < file_end; pp_file_slot++) {
203  if ((p_target = *pp_file_slot) != NULL && p_target->description) {
204  printf("%-20s %s\n", p_target->name, p_target->description);
205  }
206  }
207 }
208 
209 /* Show line information. We want output to be compatible with gdb output.*/
210 void
212 {
213  if (p_stack_top && p_stack_top->p_target &&
215  const gmk_floc *p_floc = &p_stack_top->p_target->floc;
216  if (!basename_filenames && strlen(p_floc->filenm)
217  && p_floc->filenm[0] != '/')
218  dbg_msg("Line %lu of \"%s/%s\"",
219  p_floc->lineno, starting_directory,
220  p_floc->filenm);
221  else
222  dbg_msg("Line %lu of \"%s\"", p_floc->lineno, p_floc->filenm);
223  } else {
224  dbg_msg("No line number info recorded.\n");
225  }
226 }
227 
228 void
230 {
231  printf(_("Starting directory `%s'\n"), starting_directory);
232  printf(_("Program invocation:\n"));
233  printf("\t");
235  printf(_("Recursion level: %u\n"), makelevel);
237  switch (last_stop_reason)
238  {
240  printf(_("Program is stopped after running rule command(s).\n"));
241  break;
243  printf(_("Program stopped before rule-prequisite checking.\n"));
244  break;
246  printf(_("Program is stopped after rule-prequisite checking.\n"));
247  break;
249  printf(_("Program stopped for updating a goal.\n"));
250  printf("\n");
251  break;
252  case DEBUG_READ_HIT:
253  printf(_("Program stopped for reading a file.\n"));
254  printf("\n");
255  break;
256  case DEBUG_ERROR_HIT:
257  printf(_("Program stopped after an error encountered.\n"));
258  printf("\n");
259  break;
260  case DEBUG_STEP_HIT:
261  printf(_("Program stopped in stepping.\n"));
262  printf("\n");
263  break;
264  case DEBUG_STEP_COMMAND:
265  printf(_("Program stopped in stepping before running rule command(s).\n"));
266  printf("\n");
267  break;
268  case DEBUG_EXPLICIT_CALL:
269  printf(_("Program stopped from explicit debugger function call.\n"));
270  printf("\n");
271  break;
272  case DEBUG_NOT_GIVEN:
273  printf(_("Reason not given.\n"));
274  break;
276  /* Should not happen? */
277  break;
278  }
279 }
280 
281 
282 /* Give some info regarding the running program. */
284 dbg_cmd_info(char *psz_args)
285 {
286  if (!psz_args || 0==strlen(psz_args)) {
287  unsigned int i;
288  for (i = 0; info_subcommands[i].name; i++) {
289  dbg_help_subcmd_entry("info", "%-10s -- %s",
290  &(info_subcommands[i]), false);
291  }
292  return debug_readloop;
293  } else {
294  char *psz_subcmd = get_word(&psz_args);
295  if (0 == strcmp(psz_subcmd, "lines")) {
296  file2lines_dump();
297  } else if (is_abbrev_of (psz_subcmd, "line", 2)) {
299  } else if (is_abbrev_of (psz_subcmd, "locals", 2)) {
300  const char *psz_target = NULL;
301  char *psz_subcmds = NULL;
302  file_t *p_target = get_target(&psz_subcmds, &psz_target);
303 
304  if (p_target) {
305  if (!p_target->variables) {
306  initialize_file_variables (p_target, 0);
307  set_file_variables (p_target);
308  if (!p_target->variables) {
309  printf("Can't get variable information for target %s\n",
310  psz_target);
311  return debug_readloop;
312  }
313  }
314  } else {
315  dbg_errmsg("No target information for %s.", psz_target);
316  return debug_cmd_error;
317  }
318  hash_map_arg (&p_target->variables->set->table,
319  print_variable_info, NULL);
320  } else if (is_abbrev_of (psz_subcmd, "breakpoints", 1)) {
322  } else if (is_abbrev_of (psz_subcmd, "makefiles", 1) ||
323  is_abbrev_of (psz_subcmd, "files", 2)) {
324  if (0 == strlen(psz_args))
325  print_read_makefiles(NULL);
326  else {
327  if (!print_read_makefiles(psz_args))
328  dbg_errmsg("File %s not in list of read-in files.", psz_args);
329  }
330  } else if (is_abbrev_of (psz_subcmd, "frame", 2)) {
331  dbg_cmd_where(psz_args);
332  } else if (is_abbrev_of (psz_subcmd, "program", 1)) {
334  } else if (is_abbrev_of (psz_subcmd, "rules", 1)) {
335  if (0 == strlen(psz_args))
336  print_rule_data_base (false);
337  else if (0 == strcmp(psz_args, "verbose"))
338  print_rule_data_base (true);
339  else
340  {
341  rule_t *r = find_rule(psz_args);
342  if (r)
343  print_rule(r, true);
344  else
345  dbg_errmsg(_("Rule %s not found."), psz_args);
346  }
347  } else if (is_abbrev_of (psz_subcmd, "stack", 1)) {
349  } else if (0 == strcmp(psz_subcmd, "targets")) {
350  /* Note: "targets" has to come before "target" */
351  info_target_output_mask_t output_type;
352  if (0 == strlen(psz_args))
353  output_type = INFO_TARGET_POSITION_AND_NAME;
354  else if (is_abbrev_of (psz_args, "all", 1))
355  output_type = INFO_TARGET_POSITION_AND_NAME;
356  else if (is_abbrev_of (psz_args, "positions", 1))
357  output_type = INFO_TARGET_POSITION;
358  else if (is_abbrev_of (psz_args, "names", 1))
359  output_type = INFO_TARGET_NAME;
360  else if (is_abbrev_of (psz_args, "tasks", 1))
361  output_type = INFO_TARGET_TASKS;
362  else {
363  printf("Expecting 'all', 'positions', 'names', 'tasks', or nothing; got %s.\n",
364  psz_args);
365  return debug_cmd_error;
366  }
367  dbg_cmd_info_targets(output_type);
368 
369  } else if (0 == strcmp(psz_subcmd, "tasks")) {
371 
372  } else if (is_abbrev_of (psz_subcmd, "target", 1)) {
373  if (0 == strlen(psz_args)) {
374  if (p_stack_top && p_stack_top->p_target &&
376  printf("target: %s\n", p_stack_top->p_target->name);
377  else
378  {
379  printf("target unknown\n");
380  }
381  }
382  else
383  dbg_cmd_target(psz_args);
384 
385  } else if (is_abbrev_of (psz_subcmd, "variables", 1)) {
387  } else if (is_abbrev_of (psz_subcmd, "vpath", 1)) {
389  } else if (is_abbrev_of (psz_subcmd, "warranty", 1)) {
390  printf("%s", WARRANTY);
391  } else {
392  dbg_errmsg(_("Undefined command \"%s\". Try \"help info\"."),
393  psz_subcmd);
394  }
395  }
396 
397  return debug_readloop;
398 }
399 
400 static void
401 dbg_cmd_info_init(unsigned int c)
402 {
403  short_command[c].func = &dbg_cmd_info;
404  short_command[c].use = _("info [SUBCOMMAND]");
405  short_command[c].doc =
406  _("Show program information regarding SUBCOMMAND.\n"
407  "If SUBCOMMAND is not specified, give list of \"info\" subcommands.");
408 }
409 
410 /*
411  * Local variables:
412  * c-file-style: "gnu"
413  * indent-tabs-mode: nil
414  * End:
415  */
file_t * p_target
Definition: trace.h:81
unsigned int phony
Definition: filedef.h:109
info_target_output_mask_t
Definition: trace.h:61
const char * name
Definition: filedef.h:36
char * starting_directory
const char * name
Definition: subcmd.h:5
Definition: trace.h:49
debug_enter_reason_t last_stop_reason
const char * WARRANTY
Definition: command/info.h:32
gmk_floc floc
Definition: filedef.h:39
void print_variable_info(const void *item, void *arg)
Definition: trace.h:63
rule_t * find_rule(const char *psz_name)
void dbg_cmd_info_tasks()
Definition: command/info.h:194
void print_variable_data_base(void)
void dbg_errmsg()
Definition: rule.h:25
struct hash_table table
Definition: variable.h:93
Definition: trace.h:53
struct commands * cmds
Definition: filedef.h:46
debug_return_t dbg_cmd_info(char *psz_args)
Definition: command/info.h:284
void print_rule(rule_t *r, bool b_verbose)
unsigned int makelevel
Definition: trace.h:48
void dbg_print_invocation(void)
bool is_abbrev_of(const char *psz_substr, const char *psz_word, unsigned int i_min)
struct hash_table files
void dbg_cmd_info_program()
Definition: command/info.h:229
debug_return_t
Definition: trace.h:32
void list_breakpoints(void)
Definition: trace.h:64
unsigned long ht_fill
Definition: hash.h:49
Definition: subcmd.h:4
int i_stack_pos
void dbg_cmd_info_line()
Definition: command/info.h:211
#define _(msgid)
Definition: make.h:293
Definition: trace.h:62
Definition: trace.h:40
unsigned long lineno
Definition: gnuremake.h:26
file_t * get_target(char **ppsz_args, const char **ppsz_target)
void initialize_file_variables(struct file *file, int reading)
void print_vpath_data_base(void)
Definition: trace.h:50
Definition: trace.h:57
int basename_filenames
void file2lines_dump(void)
Definition: trace.h:66
struct variable_set_list * variables
Definition: filedef.h:60
void dbg_msg()
char * get_word(char **ppsz_str)
Definition: gnuremake.h:23
void print_rule_data_base(bool b_verbose)
const char * filenm
Definition: gnuremake.h:25
Definition: trace.h:42
Definition: trace.h:54
struct variable_set * set
Definition: variable.h:101
void set_file_variables(struct file *file)
Definition: trace.h:55
debug_return_t dbg_cmd_where(char *psz_args)
Definition: where.h:23
void dbg_help_subcmd_entry(const char *psz_subcmd_name, const char *psz_fmt, subcommand_var_info_t *p_subcmd, bool full_info)
Definition: help.h:25
void dbg_cmd_info_targets(info_target_output_mask_t output_mask)
Definition: command/info.h:179
int dbg_target_compare(const void *p1, const void *p2)
Definition: command/info.h:171
Definition: trace.h:56
target_stack_node_t * p_stack_top
Definition: trace.h:52
Definition: trace.h:51
Definition: trace.h:65
const char * description
Definition: filedef.h:43
subcommand_var_info_t info_subcommands[]
Definition: command/info.h:57
debug_return_t dbg_cmd_target(char *psz_args)
Definition: target.h:21
Definition: trace.h:58
Definition: filedef.h:34