Pristine Ack-5.5
[Ack-5.5.git] / util / grind / itemlist.cc
1 /* $Id: itemlist.cc,v 1.9 1994/06/24 11:00:06 ceriel Exp $ */
2
3 #include <alloc.h>
4 #include <stdio.h>
5 #include <assert.h>
6
7 #include "position.h"
8 #include "tree.h"
9 #include "operator.h"
10 #include "misc.h"
11
12 extern FILE     *db_out;
13 extern int      db_ss;
14
15 typedef struct item {
16   struct item   *i_next;
17   struct tree   *i_node;
18   int           i_disabled;
19   int           i_itemno;
20 } t_item, *p_item;
21
22 /* STATICALLOCDEF "item" 10 */
23
24 struct itemlist {
25   p_item        il_first, il_last;
26 };
27
28 static struct itemlist  item_list;
29 static int      stop_reason;
30 int             item_count;
31
32 static int
33 in_item_list(p)
34   p_tree        p;
35 {
36   register p_item i = item_list.il_first;
37
38   while (i) {
39         if (i->i_node == p) return 1;
40         i = i->i_next;
41   }
42   return 0;
43 }
44
45 static
46 pr_item(i)
47   p_item        i;
48 {
49   fprintf(db_out, "(%d)\t", i->i_itemno);
50   print_node(db_out, i->i_node, 0);
51   fputs(i->i_disabled ? " (disabled)\n": "\n", db_out);
52 }
53
54 int
55 item_addr_actions(a, mess_type, may_stop)
56   t_addr        a;
57   int           mess_type;
58   int           may_stop;
59 {
60   /* Perform actions associated with position 'a', and return stop_reason
61      if we must stop there, and 0 if not.
62   */
63   register p_item i = item_list.il_first;
64
65   stop_reason = 0;
66   for (i = item_list.il_first; i != 0; i = i->i_next) {
67         register p_tree p = i->i_node;
68
69         if (! i->i_disabled
70             && (p->t_address == a || p->t_address == NO_ADDR)) {
71                 switch(p->t_oper) {
72                 case OP_STOP:
73                         if (mess_type != 1) break;
74                         if (! p->t_args[1] || eval_cond(p->t_args[1])) {
75                                 if (! stop_reason) stop_reason = i->i_itemno;
76                         }
77                         break;
78                 case OP_TRACE:
79                 case OP_WHEN:
80                 case OP_DUMP:
81                 case OP_DISPLAY:
82                         break;
83                 default:
84                         assert(0);
85                 }
86         }
87   }
88   for (i = item_list.il_first; i != 0; i = i->i_next) {
89         register p_tree p = i->i_node;
90
91         if (! i->i_disabled
92             && (p->t_address == a || p->t_address == NO_ADDR)) {
93                 switch(p->t_oper) {
94                 case OP_TRACE:
95                         if ((! stop_reason && mess_type != 0)
96                             || p->t_args[2] || ! may_stop) {
97                                 perform(p, a);
98                         }
99                         break;
100                 case OP_WHEN:
101                         perform(p, a);
102                         break;
103                 case OP_STOP:
104                 case OP_DUMP:
105                 case OP_DISPLAY:
106                         break;
107                 default:
108                         assert(0);
109                 }
110         }
111   }
112   return stop_reason;
113 }
114
115 handle_displays()
116 {
117   register p_item i = item_list.il_first;
118
119   while (i) {
120         register p_tree p = i->i_node;
121
122         if (! i->i_disabled && p->t_oper == OP_DISPLAY) do_print(p);
123         i = i->i_next;
124   }
125 }
126
127 add_to_item_list(p)
128   p_tree        p;
129 {
130   p_item i;
131   
132   if (in_item_list(p)) return;
133
134   i = new_item();
135   i->i_node = p;
136   if (p->t_address == NO_ADDR
137       && (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss++;
138   if (item_list.il_first == 0) {
139         item_list.il_first = i;
140   }
141   else {
142         item_list.il_last->i_next = i;
143   }
144   i->i_itemno = ++item_count;
145   item_list.il_last = i;
146   pr_item(i);
147 }
148
149 remove_from_item_list(n)
150   int   n;
151 {
152   register p_item i = item_list.il_first, prev = 0;
153   p_tree        p;
154
155   if (n == 0) {
156         n = stop_reason;
157         if (n == 0) {
158                 error("no current stopping point");
159                 return;
160         }
161         stop_reason = 0;
162   }
163   if (n < 0) n = item_count + n + 1;
164   while (i) {
165         if (i->i_itemno == n) break;
166         prev = i;
167         i = i->i_next;
168   }
169   if (! i) {
170         error("no item %d in current status", n);
171         return;
172   }
173   if (i->i_itemno == stop_reason) stop_reason = 0;
174   if (prev) {
175         prev->i_next = i->i_next;
176   }
177   else item_list.il_first = i->i_next;
178   if (i == item_list.il_last) item_list.il_last = prev;
179   p = i->i_node;
180   if (p->t_address == NO_ADDR
181       && (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss--;
182   free_item(i);
183   switch(p->t_oper) {
184   case OP_STOP:
185   case OP_WHEN:
186         (void) setstop(p, 0);
187         break;
188   case OP_TRACE:
189         (void) settrace(p, 0);
190         break;
191   case OP_DUMP:
192         free_dump(p);
193         break;
194   }
195   freenode(p);
196 }
197
198 p_tree
199 get_from_item_list(n)
200   int   n;
201 {
202   register p_item i = item_list.il_first;
203
204   if (n == 0) {
205         n = stop_reason;
206         if (n == 0) return 0;
207   }
208   if (n < 0) n = item_count + n + 1;
209   while (i) {
210         if (i->i_itemno == n) return i->i_node;
211         i = i->i_next;
212   }
213   return 0;
214 }
215
216 able_item(n, kind)
217   int   n;
218 {
219   register p_item i = item_list.il_first;
220   register p_tree p;
221
222   if (n == 0) {
223         n = stop_reason;
224         if (n == 0) {
225                 error("no current stopping point");
226                 return;
227         }
228   }
229   if (n < 0) n = item_count + n + 1;
230   while (i) {
231         if (i->i_itemno == n) break;
232         i = i->i_next;
233   }
234   if (! i) {
235         error("no item %d in current status", n);
236         return;
237   }
238   p = i->i_node;
239   if (i->i_disabled == kind) {
240         warning("item %d already %sabled", n, kind ? "dis" : "en");
241         return;
242   }
243   if (p->t_address == NO_ADDR
244       && (p->t_oper != OP_TRACE || ! p->t_args[0])) {
245         db_ss += kind == 1 ? (-1) : 1;
246   }
247   i->i_disabled = kind;
248   switch(p->t_oper) {
249   case OP_STOP:
250   case OP_WHEN:
251         (void) setstop(p, ! kind);
252         break;
253   case OP_TRACE:
254         (void) settrace(p, ! kind);
255         break;
256   }
257 }
258
259 print_items()
260 {
261   register p_item i = item_list.il_first;
262
263   for (; i; i = i->i_next) {
264         pr_item(i);
265   }
266 }
267
268 perform_items()
269 {
270   register p_item i = item_list.il_first;
271
272   for (; i; i = i->i_next) {
273         if (! i->i_disabled && i->i_node->t_oper != OP_DUMP) eval(i->i_node);
274   }
275 }