275 lines
4.7 KiB
C++
275 lines
4.7 KiB
C++
/* $Header$ */
|
|
|
|
#include <alloc.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#include "position.h"
|
|
#include "tree.h"
|
|
#include "operator.h"
|
|
|
|
extern FILE *db_out;
|
|
extern int db_ss;
|
|
|
|
typedef struct item {
|
|
struct item *i_next;
|
|
struct tree *i_node;
|
|
int i_disabled;
|
|
int i_itemno;
|
|
} t_item, *p_item;
|
|
|
|
/* STATICALLOCDEF "item" 10 */
|
|
|
|
struct itemlist {
|
|
p_item il_first, il_last;
|
|
};
|
|
|
|
static struct itemlist item_list;
|
|
static int stop_reason;
|
|
int item_count;
|
|
|
|
static int
|
|
in_item_list(p)
|
|
p_tree p;
|
|
{
|
|
register p_item i = item_list.il_first;
|
|
|
|
while (i) {
|
|
if (i->i_node == p) return 1;
|
|
i = i->i_next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
pr_item(i)
|
|
p_item i;
|
|
{
|
|
fprintf(db_out, "(%d)\t", i->i_itemno);
|
|
print_node(db_out, i->i_node, 0);
|
|
fputs(i->i_disabled ? " (disabled)\n": "\n", db_out);
|
|
}
|
|
|
|
int
|
|
item_addr_actions(a, mess_type, may_stop)
|
|
t_addr a;
|
|
int mess_type;
|
|
int may_stop;
|
|
{
|
|
/* Perform actions associated with position 'a', and return stop_reason
|
|
if we must stop there, and 0 if not.
|
|
*/
|
|
register p_item i = item_list.il_first;
|
|
|
|
stop_reason = 0;
|
|
for (i = item_list.il_first; i != 0; i = i->i_next) {
|
|
register p_tree p = i->i_node;
|
|
|
|
if (! i->i_disabled
|
|
&& (p->t_address == a || p->t_address == NO_ADDR)) {
|
|
switch(p->t_oper) {
|
|
case OP_STOP:
|
|
if (mess_type != 1) break;
|
|
if (! p->t_args[1] || eval_cond(p->t_args[1])) {
|
|
if (! stop_reason) stop_reason = i->i_itemno;
|
|
}
|
|
break;
|
|
case OP_TRACE:
|
|
case OP_WHEN:
|
|
case OP_DUMP:
|
|
case OP_DISPLAY:
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
for (i = item_list.il_first; i != 0; i = i->i_next) {
|
|
register p_tree p = i->i_node;
|
|
|
|
if (! i->i_disabled
|
|
&& (p->t_address == a || p->t_address == NO_ADDR)) {
|
|
switch(p->t_oper) {
|
|
case OP_TRACE:
|
|
if ((! stop_reason && mess_type != 0)
|
|
|| p->t_args[2] || ! may_stop) {
|
|
perform(p, a);
|
|
}
|
|
break;
|
|
case OP_WHEN:
|
|
perform(p, a);
|
|
break;
|
|
case OP_STOP:
|
|
case OP_DUMP:
|
|
case OP_DISPLAY:
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
return stop_reason;
|
|
}
|
|
|
|
handle_displays()
|
|
{
|
|
register p_item i = item_list.il_first;
|
|
|
|
while (i) {
|
|
register p_tree p = i->i_node;
|
|
|
|
if (! i->i_disabled && p->t_oper == OP_DISPLAY) do_print(p);
|
|
i = i->i_next;
|
|
}
|
|
}
|
|
|
|
add_to_item_list(p)
|
|
p_tree p;
|
|
{
|
|
p_item i;
|
|
|
|
if (in_item_list(p)) return;
|
|
|
|
i = new_item();
|
|
i->i_node = p;
|
|
if (p->t_address == NO_ADDR
|
|
&& (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss++;
|
|
if (item_list.il_first == 0) {
|
|
item_list.il_first = i;
|
|
}
|
|
else {
|
|
item_list.il_last->i_next = i;
|
|
}
|
|
i->i_itemno = ++item_count;
|
|
item_list.il_last = i;
|
|
pr_item(i);
|
|
}
|
|
|
|
remove_from_item_list(n)
|
|
int n;
|
|
{
|
|
register p_item i = item_list.il_first, prev = 0;
|
|
p_tree p;
|
|
|
|
if (n == 0) {
|
|
n = stop_reason;
|
|
if (n == 0) {
|
|
error("no current stopping point");
|
|
return;
|
|
}
|
|
stop_reason = 0;
|
|
}
|
|
if (n < 0) n = item_count + n + 1;
|
|
while (i) {
|
|
if (i->i_itemno == n) break;
|
|
prev = i;
|
|
i = i->i_next;
|
|
}
|
|
if (! i) {
|
|
error("no item %d in current status", n);
|
|
return;
|
|
}
|
|
if (i->i_itemno == stop_reason) stop_reason = 0;
|
|
if (prev) {
|
|
prev->i_next = i->i_next;
|
|
}
|
|
else item_list.il_first = i->i_next;
|
|
if (i == item_list.il_last) item_list.il_last = prev;
|
|
p = i->i_node;
|
|
if (p->t_address == NO_ADDR
|
|
&& (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss--;
|
|
free_item(i);
|
|
switch(p->t_oper) {
|
|
case OP_STOP:
|
|
case OP_WHEN:
|
|
(void) setstop(p, 0);
|
|
break;
|
|
case OP_TRACE:
|
|
(void) settrace(p, 0);
|
|
break;
|
|
case OP_DUMP:
|
|
free_dump(p);
|
|
break;
|
|
}
|
|
freenode(p);
|
|
}
|
|
|
|
p_tree
|
|
get_from_item_list(n)
|
|
int n;
|
|
{
|
|
register p_item i = item_list.il_first;
|
|
|
|
if (n == 0) {
|
|
n = stop_reason;
|
|
if (n == 0) return 0;
|
|
}
|
|
if (n < 0) n = item_count + n + 1;
|
|
while (i) {
|
|
if (i->i_itemno == n) return i->i_node;
|
|
i = i->i_next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
able_item(n, kind)
|
|
int n;
|
|
{
|
|
register p_item i = item_list.il_first;
|
|
register p_tree p;
|
|
|
|
if (n == 0) {
|
|
n = stop_reason;
|
|
if (n == 0) {
|
|
error("no current stopping point");
|
|
return;
|
|
}
|
|
}
|
|
if (n < 0) n = item_count + n + 1;
|
|
while (i) {
|
|
if (i->i_itemno == n) break;
|
|
i = i->i_next;
|
|
}
|
|
if (! i) {
|
|
error("no item %d in current status", n);
|
|
return;
|
|
}
|
|
p = i->i_node;
|
|
if (i->i_disabled == kind) {
|
|
warning("item %d already %sabled", n, kind ? "dis" : "en");
|
|
return;
|
|
}
|
|
if (p->t_address == NO_ADDR
|
|
&& (p->t_oper != OP_TRACE || ! p->t_args[0])) {
|
|
db_ss += kind == 1 ? (-1) : 1;
|
|
}
|
|
i->i_disabled = kind;
|
|
switch(p->t_oper) {
|
|
case OP_STOP:
|
|
case OP_WHEN:
|
|
(void) setstop(p, ! kind);
|
|
break;
|
|
case OP_TRACE:
|
|
(void) settrace(p, ! kind);
|
|
break;
|
|
}
|
|
}
|
|
|
|
print_items()
|
|
{
|
|
register p_item i = item_list.il_first;
|
|
|
|
for (; i; i = i->i_next) {
|
|
pr_item(i);
|
|
}
|
|
}
|
|
|
|
perform_items()
|
|
{
|
|
register p_item i = item_list.il_first;
|
|
|
|
for (; i; i = i->i_next) {
|
|
if (! i->i_disabled && i->i_node->t_oper != OP_DUMP) eval(i->i_node);
|
|
}
|
|
}
|