1 /*
2 Copyright (C) 2005, 2007-2008, 2015, 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 /** debugger command stack routines. */
21
22 #include <assert.h>
23 #include "break.h"
24 #include "msg.h"
25 #include "filedef.h"
26 #include "print.h"
27
28 /*! Node for an item in the target call stack */
29 struct breakpoint_node
30 {
31 file_t *p_target;
32 unsigned int i_num;
33 brkpt_mask_t brkpt_mask;
34 breakpoint_node_t *p_next;
35 };
36
37 /** Pointers to top/bottom of current breakpoint target stack */
38 breakpoint_node_t *p_breakpoint_top = NULL;
39 breakpoint_node_t *p_breakpoint_bottom = NULL;
40
41 unsigned int i_breakpoints = 0;
42
43 /*! Add "p_target" to the list of breakpoints. Return true if
44 there were no errors
45 */
46 bool
add_breakpoint(file_t * p_target,const brkpt_mask_t brkpt_mask)47 add_breakpoint (file_t *p_target, const brkpt_mask_t brkpt_mask)
48 {
49 breakpoint_node_t *p_new = CALLOC (breakpoint_node_t, 1);
50
51 if (!p_new) return false;
52
53 /* Add breakpoint to list of breakpoints. */
54 if (!p_breakpoint_top) {
55 assert(!p_breakpoint_bottom);
56 p_breakpoint_top = p_breakpoint_bottom = p_new;
57 } else {
58 p_breakpoint_bottom->p_next = p_new;
59 }
60 p_breakpoint_bottom = p_new;
61 p_new->p_target = p_target;
62 p_new->i_num = ++i_breakpoints;
63 p_new->brkpt_mask = brkpt_mask;
64
65
66 /* Finally, note that we are tracing this target. */
67 if (p_target->tracing & (BRK_BEFORE_PREREQ & brkpt_mask)) {
68 dbg_msg(_("Note: prerequisite breakpoint already set at target %s."),
69 p_target->name);
70 }
71 if (p_target->tracing & (BRK_AFTER_PREREQ & brkpt_mask)) {
72 dbg_msg(_("Note: command breakpoint already set at target %s."),
73 p_target->name);
74 }
75 if (p_target->tracing & (BRK_AFTER_CMD & brkpt_mask)) {
76 dbg_msg(_("Note: target end breakpont set at target %s."),
77 p_target->name);
78 }
79 p_target->tracing = brkpt_mask;
80 printf(_("Breakpoint %u on target `%s', mask 0x%02x"), i_breakpoints,
81 p_target->name, brkpt_mask);
82 if (p_target->floc.filenm)
83 dbg_msg(": file %s, line %lu.", p_target->floc.filenm,
84 p_target->floc.lineno);
85 else
86 printf(".\n");
87 if (p_target->updated)
88 dbg_msg("Warning: target is already updated; so it might not get stopped at again.");
89 else if (p_target->updating && (brkpt_mask & (BRK_BEFORE_PREREQ | BRK_AFTER_PREREQ))) {
90 dbg_msg("Warning: target is in the process of being updated;");
91 dbg_msg("so it might not get stopped at again.");
92 }
93 return true;
94
95 }
96
97 /*! Remove breakpoint i from the list of breakpoints. Return true if
98 there were no errors
99 */
100 bool
remove_breakpoint(unsigned int i,bool silent)101 remove_breakpoint (unsigned int i, bool silent)
102 {
103 if (!i) {
104 dbg_errmsg(_("Invalid Breakpoint number 0."));
105 return false;
106 }
107 if (i > i_breakpoints) {
108 dbg_errmsg(_("Breakpoint number %u is too high. "
109 "%u is the highest breakpoint number."), i, i_breakpoints);
110 return false;
111 } else {
112 /* Find breakpoint i */
113 breakpoint_node_t *p_prev = NULL;
114 breakpoint_node_t *p;
115 for (p = p_breakpoint_top; p && p->i_num != i; p = p->p_next) {
116 p_prev = p;
117 }
118
119 if (p && p->i_num == i) {
120 /* Delete breakpoint */
121 if (!p->p_next) p_breakpoint_bottom = p_prev;
122 if (p == p_breakpoint_top) p_breakpoint_top = p->p_next;
123
124 if (p_prev) p_prev->p_next = p->p_next;
125
126 if (p->p_target->tracing) {
127 p->p_target->tracing = BRK_NONE;
128 dbg_msg(_("Breakpoint %u on target `%s' cleared."),
129 i, p->p_target->name);
130 free(p);
131 return true;
132 } else {
133 dbg_msg(_("No breakpoint at target `%s'; nothing cleared."),
134 p->p_target->name);
135 free(p);
136 return false;
137 }
138 } else {
139 if (!silent)
140 dbg_errmsg(_("No Breakpoint number %u set."), i);
141 return false;
142 }
143 }
144 }
145
146 /*! List breakpoints.*/
147 void
list_breakpoints(void)148 list_breakpoints (void)
149 {
150 breakpoint_node_t *p;
151
152 if (!p_breakpoint_top) {
153 dbg_msg(_("No breakpoints."));
154 return;
155 }
156
157 dbg_msg( "Num Type Disp Enb Mask Target Location");
158 for (p = p_breakpoint_top; p; p = p->p_next) {
159 printf("%3u breakpoint keep y 0x%02x %s",
160 p->i_num,
161 p->brkpt_mask,
162 p->p_target->name);
163 if (p->p_target->floc.filenm) {
164 printf(" at ");
165 print_floc_prefix(&(p->p_target->floc));
166 }
167 printf("\n");
168 }
169 }
170 /*
171 * Local variables:
172 * eval: (c-set-style "gnu")
173 * indent-tabs-mode: nil
174 * End:
175 */
176