/* Copyright (c) 1982 Regents of the University of California */
static char sccsid
[] = "@(#)tree.c 1.2 %G%";
typedef struct Node
*Node
;
#define evalcmd(cmd) eval(cmd)
#define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl)
#define nextarg(type) ((type *) (ap += sizeof(type)))[-1]
public Node
build(op
, args
)
p
->value
.name
= nextarg(Name
);
p
->value
.sym
= nextarg(Symbol
);
p
->value
.lcon
= nextarg(long);
p
->value
.fcon
= nextarg(double);
p
->value
.scon
= nextarg(String
);
if (q
!= nil
and q
->op
== O_RVAL
) {
p
->value
.arg
[0] = q
->value
.arg
[0];
p
->value
.event
.cond
= nextarg(Node
);
p
->value
.event
.actions
= nextarg(Cmdlist
);
p
->value
.trace
.inst
= nextarg(Boolean
);
p
->value
.trace
.event
= nil
;
p
->value
.trace
.actions
= nextarg(Cmdlist
);
p
->value
.step
.source
= nextarg(Boolean
);
p
->value
.step
.skipcalls
= nextarg(Boolean
);
p
->value
.examine
.mode
= nextarg(String
);
p
->value
.examine
.beginaddr
= nextarg(Node
);
p
->value
.examine
.endaddr
= nextarg(Node
);
p
->value
.examine
.count
= nextarg(Integer
);
for (i
= 0; i
< nargs(op
); i
++) {
p
->value
.arg
[i
] = nextarg(Node
);
* Create a command list from a single command.
public Cmdlist
buildcmdlist(cmd
)
cmdlist_append(cmd
, cmdlist
);
* Return the tree for a unary ampersand operator.
r
= build(O_LCON
, codeloc(p
->value
.arg
[0]->value
.sym
));
if (isblock(p
->value
.sym
)) {
r
= build(O_LCON
, codeloc(p
->value
.sym
));
r
= build(O_LCON
, address(p
->value
.sym
, nil
));
fprintf(stderr
, "expected variable, found ");
* Create a "concrete" version of a node.
* This is necessary when the type of the node contains
* an unresolved type reference.
return build(O_INDIR
, p
);
if (cmd
->value
.step
.skipcalls
) {
if (not cmd
->value
.step
.source
) {
fprintf(f
, "%s", opinfo
[ord(cmd
->op
)].opstring
);
if (nargs(cmd
->op
) != 0) {
fprintf(f
, "%s", symname(cmd
->value
.sym
));
if (p
!= nil
and p
->op
!= O_QLINE
) {
fprintf(f
, "%s", cmd
->value
.scon
);
fprintf(f
, "%d", cmd
->value
.lcon
);
prtree(f
, cmd
->value
.event
.cond
);
foreach (Command
, c
, cmd
->value
.event
.actions
)
fprintf(f
, " }", opinfo
[ord(cmd
->op
)].opstring
);
prtree(f
, cmd
->value
.examine
.beginaddr
);
if (cmd
->value
.examine
.endaddr
!= nil
) {
prtree(f
, cmd
->value
.examine
.endaddr
);
if (cmd
->value
.examine
.count
> 1) {
fprintf(f
, "%d", cmd
->value
.examine
.count
);
fprintf("%s", cmd
->value
.examine
.mode
);
if (nargs(cmd
->op
) != 0) {
prtree(f
, cmd
->value
.arg
[i
]);
if (i
>= nargs(cmd
->op
)) break;
* Print out a trace/stop command name.
private print_tracestop(f
, cmd
)
register Command c
, ifcmd
, stopcmd
;
ifcmd
= list_element(Command
, list_head(cmd
->value
.trace
.actions
));
stopcmd
= list_element(Command
, list_head(ifcmd
->value
.event
.actions
));
if (stopcmd
->op
== O_STOPX
) {
fprintf(f
, "%s if ", cmd
->value
.trace
.inst
? "stopi" : "stop");
prtree(f
, ifcmd
->value
.event
.cond
);
fprintf(f
, "%s ", cmd
->value
.trace
.inst
? "tracei" : "trace");
foreach (Command
, c
, cmd
->value
.trace
.actions
)
* Print a tree back out in Pascal form.
if (ord(op
) > ord(O_LASTOP
)) {
panic("bad op %d in prtree", p
->op
);
fprintf(f
, "%s", ident(p
->value
.name
));
printname(f
, p
->value
.sym
);
prtree(f
, p
->value
.arg
[0]);
prtree(f
, p
->value
.arg
[1]);
if (compatible(p
->nodetype
, t_char
)) {
fprintf(f
, "'%c'", p
->value
.lcon
);
fprintf(f
, "%d", p
->value
.lcon
);
fprintf(f
, "%g", p
->value
.fcon
);
fprintf(f
, "\"%s\"", p
->value
.scon
);
prtree(f
, p
->value
.arg
[0]);
prtree(f
, p
->value
.arg
[1]);
prtree(f
, p
->value
.arg
[0]);
if (p
->value
.arg
[1] != nil
) {
prtree(f
, p
->value
.arg
[1]);
if (p
->value
.arg
[0]->op
== O_SYM
) {
printname(f
, p
->value
.arg
[0]->value
.sym
);
prtree(f
, p
->value
.arg
[0]);
prtree(f
, p
->value
.arg
[0]);
prtree(f
, p
->value
.arg
[0]);
if (p
->value
.arg
[1]!= nil
) {
prtree(f
, p
->value
.arg
[1]);
if (isvarparam(q
->nodetype
)) {
if (q
->op
== O_SYM
or q
->op
== O_LCON
or q
->op
== O_DOT
) {
prtree(f
, q
->value
.arg
[0]);
fprintf(f
, ".%s", symname(p
->value
.arg
[1]->value
.sym
));
prtree(f
, p
->value
.arg
[0]);
fprintf(f
, "%s", opinfo
[ord(op
)].opstring
);
prtree(f
, p
->value
.arg
[1]);
fprintf(f
, "%s", opinfo
[ord(op
)].opstring
);
prtree(f
, p
->value
.arg
[0]);
error("internal error: bad op %d in prtree", op
);
* Free storage associated with a tree.
dispose(p
->value
.arg
[0]->value
.scon
);
dispose(p
->value
.arg
[0]);
for (i
= 0; i
< nargs(p
->op
); i
++) {
* A recursive tree search routine to test if two trees * are equivalent.
public Boolean
tr_equal(t1
, t2
)
if (t1
== nil
and t2
== nil
) {
} else if (t1
== nil
or t2
== nil
) {
} else if (t1
->op
!= t2
->op
or degree(t1
->op
) != degree(t2
->op
)) {
switch (degree(t1
->op
)) {
b
= (Boolean
) (t1
->value
.name
== t2
->value
.name
);
b
= (Boolean
) (t1
->value
.sym
== t2
->value
.sym
);
b
= (Boolean
) (t1
->value
.lcon
== t2
->value
.lcon
);
b
= (Boolean
) (t1
->value
.fcon
== t2
->value
.fcon
);
b
= (Boolean
) (t1
->value
.scon
== t2
->value
.scon
);
panic("tr_equal: leaf %d\n", t1
->op
);
if (not tr_equal(t1
->value
.arg
[0], t2
->value
.arg
[0])) {
b
= tr_equal(t1
->value
.arg
[1], t2
->value
.arg
[1]);
b
= tr_equal(t1
->value
.arg
[0], t2
->value
.arg
[0]);
panic("tr_equal: bad degree for op %d\n", t1
->op
);