1986-04-21 17:27:06 +00:00
|
|
|
/* P A R S E T R E E W A L K E R */
|
|
|
|
|
1986-05-01 19:06:53 +00:00
|
|
|
#ifndef NORCSID
|
1986-04-21 17:27:06 +00:00
|
|
|
static char *RcsId = "$Header$";
|
1986-05-01 19:06:53 +00:00
|
|
|
#endif
|
1986-04-21 17:27:06 +00:00
|
|
|
|
|
|
|
/* Routines to walk through parts of the parse tree, and generate
|
|
|
|
code for these parts.
|
|
|
|
*/
|
|
|
|
|
1986-05-01 19:06:53 +00:00
|
|
|
#include "debug.h"
|
|
|
|
|
1986-04-21 17:27:06 +00:00
|
|
|
#include <em_arith.h>
|
|
|
|
#include <em_label.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "def.h"
|
|
|
|
#include "type.h"
|
|
|
|
#include "scope.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "LLlex.h"
|
|
|
|
#include "node.h"
|
1986-04-22 22:36:16 +00:00
|
|
|
#include "Lpars.h"
|
1986-05-16 17:15:36 +00:00
|
|
|
#include "desig.h"
|
1986-05-23 09:46:31 +00:00
|
|
|
#include "f_info.h"
|
1986-04-21 17:27:06 +00:00
|
|
|
|
|
|
|
extern arith align();
|
1986-05-23 09:46:31 +00:00
|
|
|
extern arith NewPtr();
|
1986-05-16 17:15:36 +00:00
|
|
|
extern int proclevel;
|
1986-05-01 19:06:53 +00:00
|
|
|
static label instructionlabel;
|
1986-04-23 22:12:22 +00:00
|
|
|
static char return_expr_occurred;
|
|
|
|
static struct type *func_type;
|
1986-05-16 17:15:36 +00:00
|
|
|
struct withdesig *WithDesigs;
|
1986-04-21 17:27:06 +00:00
|
|
|
|
1986-05-01 19:06:53 +00:00
|
|
|
label
|
|
|
|
text_label()
|
|
|
|
{
|
|
|
|
return instructionlabel++;
|
|
|
|
}
|
|
|
|
|
|
|
|
label
|
|
|
|
data_label()
|
|
|
|
{
|
1986-05-14 09:03:51 +00:00
|
|
|
static label datalabel = 0;
|
|
|
|
|
|
|
|
return ++datalabel;
|
1986-05-01 19:06:53 +00:00
|
|
|
}
|
|
|
|
|
1986-05-23 09:46:31 +00:00
|
|
|
static
|
|
|
|
DoProfil()
|
|
|
|
{
|
|
|
|
static label filename_label = 0;
|
|
|
|
|
|
|
|
if (options['p']) {
|
|
|
|
if (!filename_label) {
|
|
|
|
filename_label = data_label();
|
|
|
|
C_df_dlb(filename_label);
|
|
|
|
C_rom_scon(FileName, (arith) strlen(FileName));
|
|
|
|
}
|
|
|
|
|
|
|
|
C_fil_dlb(filename_label, (arith) 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1986-04-21 17:27:06 +00:00
|
|
|
WalkModule(module)
|
|
|
|
register struct def *module;
|
|
|
|
{
|
|
|
|
/* Walk through a module, and all its local definitions.
|
|
|
|
Also generate code for its body.
|
|
|
|
*/
|
1986-04-28 18:06:58 +00:00
|
|
|
register struct def *df = module->mod_vis->sc_scope->sc_def;
|
1986-05-23 19:25:21 +00:00
|
|
|
register struct scope *sc;
|
1986-04-28 18:06:58 +00:00
|
|
|
struct scopelist *vis;
|
1986-04-21 17:27:06 +00:00
|
|
|
|
1986-04-28 18:06:58 +00:00
|
|
|
vis = CurrVis;
|
|
|
|
CurrVis = module->mod_vis;
|
1986-05-23 19:25:21 +00:00
|
|
|
sc = CurrentScope;
|
1986-04-22 22:36:16 +00:00
|
|
|
|
1986-05-16 17:15:36 +00:00
|
|
|
if (!proclevel && module != Defined) {
|
1986-04-21 17:27:06 +00:00
|
|
|
/* This module is a local module, but not within a
|
|
|
|
procedure. Generate code to allocate storage for its
|
1986-04-22 22:36:16 +00:00
|
|
|
variables. This is done by generating a "bss",
|
|
|
|
with label "_<modulenumber><modulename>".
|
1986-04-21 17:27:06 +00:00
|
|
|
*/
|
1986-05-23 19:25:21 +00:00
|
|
|
arith size = align(sc->sc_off, word_align);
|
1986-04-21 17:27:06 +00:00
|
|
|
|
|
|
|
if (size == 0) size = word_size;
|
1986-05-16 17:15:36 +00:00
|
|
|
/* WHY ??? because we generated an INA for it ??? */
|
|
|
|
|
1986-05-23 19:25:21 +00:00
|
|
|
C_df_dnam(&(sc->sc_name[1]));
|
1986-04-21 17:27:06 +00:00
|
|
|
C_bss_cst(size, (arith) 0, 0);
|
|
|
|
}
|
1986-04-28 18:06:58 +00:00
|
|
|
else if (CurrVis == Defined->mod_vis) {
|
1986-04-21 17:27:06 +00:00
|
|
|
/* This module is the module currently being compiled.
|
|
|
|
Again, generate code to allocate storage for its
|
|
|
|
variables, which all have an explicit name.
|
|
|
|
*/
|
|
|
|
while (df) {
|
|
|
|
if (df->df_kind == D_VARIABLE) {
|
|
|
|
C_df_dnam(df->var_name);
|
|
|
|
C_bss_cst(df->df_type->tp_size, (arith) 0, 0);
|
|
|
|
}
|
|
|
|
df = df->df_nextinscope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now, walk through it's local definitions
|
|
|
|
*/
|
1986-05-23 19:25:21 +00:00
|
|
|
WalkDef(sc->sc_def);
|
1986-04-21 17:27:06 +00:00
|
|
|
|
|
|
|
/* Now, generate initialization code for this module.
|
|
|
|
First call initialization routines for modules defined within
|
|
|
|
this module.
|
|
|
|
*/
|
1986-05-23 19:25:21 +00:00
|
|
|
sc->sc_off = 0;
|
1986-05-14 09:03:51 +00:00
|
|
|
instructionlabel = 2;
|
1986-04-23 22:12:22 +00:00
|
|
|
func_type = 0;
|
1986-05-23 19:25:21 +00:00
|
|
|
C_pro_narg(sc->sc_name);
|
1986-05-23 09:46:31 +00:00
|
|
|
DoProfil();
|
1986-05-23 19:25:21 +00:00
|
|
|
MkCalls(sc->sc_def);
|
1986-04-22 22:36:16 +00:00
|
|
|
WalkNode(module->mod_body, (label) 0);
|
1986-05-14 09:03:51 +00:00
|
|
|
C_df_ilb((label) 1);
|
|
|
|
C_ret(0);
|
1986-05-23 19:25:21 +00:00
|
|
|
C_end(-sc->sc_off);
|
1986-05-23 09:46:31 +00:00
|
|
|
TmpClose();
|
1986-04-21 17:27:06 +00:00
|
|
|
|
1986-04-28 18:06:58 +00:00
|
|
|
CurrVis = vis;
|
1986-04-21 17:27:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WalkProcedure(procedure)
|
|
|
|
struct def *procedure;
|
|
|
|
{
|
|
|
|
/* Walk through the definition of a procedure and all its
|
|
|
|
local definitions
|
|
|
|
*/
|
1986-04-28 18:06:58 +00:00
|
|
|
struct scopelist *vis = CurrVis;
|
1986-05-23 19:25:21 +00:00
|
|
|
register struct scope *sc;
|
1986-04-21 17:27:06 +00:00
|
|
|
|
1986-05-16 17:15:36 +00:00
|
|
|
proclevel++;
|
1986-04-28 18:06:58 +00:00
|
|
|
CurrVis = procedure->prc_vis;
|
1986-05-23 19:25:21 +00:00
|
|
|
sc = CurrentScope;
|
1986-04-21 17:27:06 +00:00
|
|
|
|
1986-05-23 19:25:21 +00:00
|
|
|
WalkDef(sc->sc_def);
|
1986-04-21 17:27:06 +00:00
|
|
|
|
|
|
|
/* Generate code for this procedure
|
|
|
|
*/
|
1986-05-23 19:25:21 +00:00
|
|
|
C_pro_narg(sc->sc_name);
|
1986-05-23 09:46:31 +00:00
|
|
|
DoProfil();
|
1986-04-21 17:27:06 +00:00
|
|
|
/* generate calls to initialization routines of modules defined within
|
|
|
|
this procedure
|
|
|
|
*/
|
1986-05-23 19:25:21 +00:00
|
|
|
MkCalls(sc->sc_def);
|
1986-05-14 09:03:51 +00:00
|
|
|
return_expr_occurred = 0;
|
1986-04-23 22:12:22 +00:00
|
|
|
instructionlabel = 2;
|
|
|
|
func_type = procedure->df_type->next;
|
1986-04-22 22:36:16 +00:00
|
|
|
WalkNode(procedure->prc_body, (label) 0);
|
1986-05-14 09:03:51 +00:00
|
|
|
C_df_ilb((label) 1);
|
|
|
|
if (func_type) {
|
|
|
|
if (! return_expr_occurred) {
|
|
|
|
node_error(procedure->prc_body,"function procedure does not return a value");
|
|
|
|
}
|
|
|
|
C_ret((int) align(func_type->tp_size, word_align));
|
|
|
|
}
|
|
|
|
else C_ret(0);
|
1986-05-23 19:25:21 +00:00
|
|
|
C_end(-sc->sc_off);
|
1986-05-23 09:46:31 +00:00
|
|
|
TmpClose();
|
1986-04-28 18:06:58 +00:00
|
|
|
CurrVis = vis;
|
1986-05-16 17:15:36 +00:00
|
|
|
proclevel--;
|
1986-04-21 17:27:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WalkDef(df)
|
|
|
|
register struct def *df;
|
|
|
|
{
|
|
|
|
/* Walk through a list of definitions
|
|
|
|
*/
|
1986-04-28 18:06:58 +00:00
|
|
|
|
1986-04-21 17:27:06 +00:00
|
|
|
while (df) {
|
|
|
|
if (df->df_kind == D_MODULE) {
|
|
|
|
WalkModule(df);
|
|
|
|
}
|
|
|
|
else if (df->df_kind == D_PROCEDURE) {
|
|
|
|
WalkProcedure(df);
|
|
|
|
}
|
|
|
|
df = df->df_nextinscope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MkCalls(df)
|
|
|
|
register struct def *df;
|
|
|
|
{
|
|
|
|
/* Generate calls to initialization routines of modules
|
|
|
|
*/
|
1986-04-28 18:06:58 +00:00
|
|
|
|
1986-04-21 17:27:06 +00:00
|
|
|
while (df) {
|
|
|
|
if (df->df_kind == D_MODULE) {
|
|
|
|
C_lxl((arith) 0);
|
1986-04-28 18:06:58 +00:00
|
|
|
C_cal(df->mod_vis->sc_scope->sc_name);
|
1986-04-21 17:27:06 +00:00
|
|
|
}
|
|
|
|
df = df->df_nextinscope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1986-04-22 22:36:16 +00:00
|
|
|
WalkNode(nd, lab)
|
|
|
|
register struct node *nd;
|
|
|
|
label lab;
|
1986-04-21 17:27:06 +00:00
|
|
|
{
|
|
|
|
/* Node "nd" represents either a statement or a statement list.
|
1986-04-22 22:36:16 +00:00
|
|
|
Walk through it.
|
|
|
|
"lab" represents the label that must be jumped to on
|
|
|
|
encountering an EXIT statement.
|
|
|
|
*/
|
1986-04-28 18:06:58 +00:00
|
|
|
|
1986-04-22 22:36:16 +00:00
|
|
|
while (nd->nd_class == Link) { /* statement list */
|
|
|
|
WalkStat(nd->nd_left, lab);
|
|
|
|
nd = nd->nd_right;
|
|
|
|
}
|
|
|
|
|
|
|
|
WalkStat(nd, lab);
|
|
|
|
}
|
|
|
|
|
|
|
|
WalkStat(nd, lab)
|
1986-05-23 19:25:21 +00:00
|
|
|
struct node *nd;
|
1986-04-22 22:36:16 +00:00
|
|
|
label lab;
|
|
|
|
{
|
|
|
|
/* Walk through a statement, generating code for it.
|
|
|
|
"lab" represents the label that must be jumped to on
|
|
|
|
encountering an EXIT statement.
|
|
|
|
*/
|
|
|
|
register struct node *left = nd->nd_left;
|
|
|
|
register struct node *right = nd->nd_right;
|
1986-05-23 19:25:21 +00:00
|
|
|
register struct desig *pds = &Desig;
|
1986-05-23 09:46:31 +00:00
|
|
|
|
1986-05-14 09:03:51 +00:00
|
|
|
if (!nd) {
|
|
|
|
/* Empty statement
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1986-05-23 19:25:21 +00:00
|
|
|
if (options['p']) C_lin((arith) nd->nd_lineno);
|
|
|
|
|
1986-04-22 22:36:16 +00:00
|
|
|
if (nd->nd_class == Call) {
|
1986-05-01 19:06:53 +00:00
|
|
|
if (chk_call(nd)) CodeCall(nd);
|
1986-04-22 22:36:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(nd->nd_class == Stat);
|
|
|
|
|
|
|
|
switch(nd->nd_symb) {
|
1986-05-21 18:32:20 +00:00
|
|
|
case BECOMES: {
|
|
|
|
struct desig ds;
|
|
|
|
|
|
|
|
WalkExpr(right, NO_LABEL, NO_LABEL);
|
|
|
|
ds = Desig;
|
1986-05-14 09:03:51 +00:00
|
|
|
WalkDesignator(left); /* May we do it in this order??? */
|
1986-04-28 18:06:58 +00:00
|
|
|
|
|
|
|
if (! TstAssCompat(left->nd_type, right->nd_type)) {
|
|
|
|
node_error(nd, "type incompatibility in assignment");
|
|
|
|
break;
|
|
|
|
}
|
1986-05-01 19:06:53 +00:00
|
|
|
|
1986-05-23 19:25:21 +00:00
|
|
|
CodeAssign(nd, &ds, pds);
|
1986-05-21 18:32:20 +00:00
|
|
|
}
|
1986-04-22 22:36:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IF:
|
1986-05-21 18:32:20 +00:00
|
|
|
{ label l1, l2, l3;
|
1986-04-22 22:36:16 +00:00
|
|
|
|
|
|
|
l1 = instructionlabel++;
|
|
|
|
l2 = instructionlabel++;
|
1986-05-21 18:32:20 +00:00
|
|
|
l3 = instructionlabel++;
|
|
|
|
ExpectBool(left, l3, l1);
|
1986-04-22 22:36:16 +00:00
|
|
|
assert(right->nd_symb == THEN);
|
1986-05-21 18:32:20 +00:00
|
|
|
C_df_ilb(l3);
|
1986-04-22 22:36:16 +00:00
|
|
|
WalkNode(right->nd_left, lab);
|
|
|
|
|
|
|
|
if (right->nd_right) { /* ELSE part */
|
|
|
|
C_bra(l2);
|
|
|
|
C_df_ilb(l1);
|
|
|
|
WalkNode(right->nd_right, lab);
|
|
|
|
C_df_ilb(l2);
|
|
|
|
}
|
|
|
|
else C_df_ilb(l1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case CASE:
|
1986-05-01 19:06:53 +00:00
|
|
|
CaseCode(nd, lab);
|
|
|
|
break;
|
1986-04-22 22:36:16 +00:00
|
|
|
|
|
|
|
case WHILE:
|
1986-05-21 18:32:20 +00:00
|
|
|
{ label l1, l2, l3;
|
1986-04-22 22:36:16 +00:00
|
|
|
|
|
|
|
l1 = instructionlabel++;
|
|
|
|
l2 = instructionlabel++;
|
1986-05-21 18:32:20 +00:00
|
|
|
l3 = instructionlabel++;
|
1986-04-22 22:36:16 +00:00
|
|
|
C_df_ilb(l1);
|
1986-05-21 18:32:20 +00:00
|
|
|
ExpectBool(left, l3, l2);
|
|
|
|
C_df_ilb(l3);
|
1986-04-22 22:36:16 +00:00
|
|
|
WalkNode(right, lab);
|
|
|
|
C_bra(l1);
|
|
|
|
C_df_ilb(l2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case REPEAT:
|
1986-05-21 18:32:20 +00:00
|
|
|
{ label l1, l2;
|
1986-04-22 22:36:16 +00:00
|
|
|
|
|
|
|
l1 = instructionlabel++;
|
1986-05-21 18:32:20 +00:00
|
|
|
l2 = instructionlabel++;
|
1986-04-22 22:36:16 +00:00
|
|
|
C_df_ilb(l1);
|
|
|
|
WalkNode(left, lab);
|
1986-05-21 18:32:20 +00:00
|
|
|
ExpectBool(right, l2, l1);
|
|
|
|
C_df_ilb(l2);
|
1986-04-22 22:36:16 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LOOP:
|
|
|
|
{ label l1, l2;
|
|
|
|
|
|
|
|
l1 = instructionlabel++;
|
|
|
|
l2 = instructionlabel++;
|
|
|
|
C_df_ilb(l1);
|
|
|
|
WalkNode(left, l2);
|
|
|
|
C_bra(l1);
|
|
|
|
C_df_ilb(l2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case FOR:
|
|
|
|
/* ??? */
|
1986-04-28 18:06:58 +00:00
|
|
|
WalkNode(right, lab);
|
1986-04-22 22:36:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WITH:
|
1986-04-28 18:06:58 +00:00
|
|
|
{
|
|
|
|
struct scopelist link;
|
1986-05-16 17:15:36 +00:00
|
|
|
struct withdesig wds;
|
1986-05-23 09:46:31 +00:00
|
|
|
arith tmp = 0;
|
1986-04-28 18:06:58 +00:00
|
|
|
|
|
|
|
WalkDesignator(left);
|
|
|
|
if (left->nd_type->tp_fund != T_RECORD) {
|
|
|
|
node_error(left, "record variable expected");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1986-05-16 17:15:36 +00:00
|
|
|
wds.w_next = WithDesigs;
|
|
|
|
WithDesigs = &wds;
|
|
|
|
wds.w_scope = left->nd_type->rec_scope;
|
1986-05-23 19:25:21 +00:00
|
|
|
if (pds->dsg_kind != DSG_PFIXED) {
|
1986-05-23 09:46:31 +00:00
|
|
|
/* In this case, we use a temporary variable
|
|
|
|
*/
|
1986-05-23 19:25:21 +00:00
|
|
|
CodeAddress(pds);
|
|
|
|
pds->dsg_kind = DSG_FIXED;
|
1986-05-23 09:46:31 +00:00
|
|
|
/* Only for the store ... */
|
1986-05-23 19:25:21 +00:00
|
|
|
pds->dsg_offset = tmp = NewPtr();
|
|
|
|
pds->dsg_name = 0;
|
|
|
|
CodeStore(pds, pointer_size);
|
|
|
|
pds->dsg_kind = DSG_PFIXED;
|
1986-05-23 09:46:31 +00:00
|
|
|
/* the record is indirectly available */
|
|
|
|
}
|
1986-05-21 18:32:20 +00:00
|
|
|
wds.w_desig = Desig;
|
1986-05-16 17:15:36 +00:00
|
|
|
link.sc_scope = wds.w_scope;
|
1986-04-28 18:06:58 +00:00
|
|
|
link.next = CurrVis;
|
|
|
|
CurrVis = &link;
|
|
|
|
WalkNode(right, lab);
|
|
|
|
CurrVis = link.next;
|
1986-05-16 17:15:36 +00:00
|
|
|
WithDesigs = wds.w_next;
|
1986-05-23 09:46:31 +00:00
|
|
|
if (tmp) FreePtr(tmp);
|
1986-04-28 18:06:58 +00:00
|
|
|
break;
|
|
|
|
}
|
1986-04-22 22:36:16 +00:00
|
|
|
|
|
|
|
case EXIT:
|
|
|
|
assert(lab != 0);
|
|
|
|
|
|
|
|
C_bra(lab);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RETURN:
|
1986-04-23 22:12:22 +00:00
|
|
|
if (right) {
|
1986-05-21 18:32:20 +00:00
|
|
|
WalkExpr(right, NO_LABEL, NO_LABEL);
|
1986-04-28 18:06:58 +00:00
|
|
|
/* What kind of compatibility do we need here ???
|
|
|
|
assignment compatibility?
|
|
|
|
*/
|
|
|
|
if (!TstAssCompat(func_type, right->nd_type)) {
|
1986-04-23 22:12:22 +00:00
|
|
|
node_error(right, "type incompatibility in RETURN statement");
|
|
|
|
}
|
1986-05-01 19:06:53 +00:00
|
|
|
return_expr_occurred = 1;
|
1986-04-23 22:12:22 +00:00
|
|
|
}
|
1986-05-14 09:03:51 +00:00
|
|
|
C_bra((label) 1);
|
1986-04-22 22:36:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1986-05-21 18:32:20 +00:00
|
|
|
ExpectBool(nd, true_label, false_label)
|
1986-05-23 19:25:21 +00:00
|
|
|
register struct node *nd;
|
1986-05-21 18:32:20 +00:00
|
|
|
label true_label, false_label;
|
1986-04-22 22:36:16 +00:00
|
|
|
{
|
|
|
|
/* "nd" must indicate a boolean expression. Check this and
|
|
|
|
generate code to evaluate the expression.
|
|
|
|
*/
|
|
|
|
|
1986-05-21 18:32:20 +00:00
|
|
|
WalkExpr(nd, true_label, false_label);
|
1986-04-22 22:36:16 +00:00
|
|
|
|
1986-04-22 23:22:19 +00:00
|
|
|
if (nd->nd_type != bool_type && nd->nd_type != error_type) {
|
1986-04-22 22:36:16 +00:00
|
|
|
node_error(nd, "boolean expression expected");
|
|
|
|
}
|
1986-04-23 22:12:22 +00:00
|
|
|
}
|
1986-04-22 22:36:16 +00:00
|
|
|
|
1986-05-21 18:32:20 +00:00
|
|
|
WalkExpr(nd, true_label, false_label)
|
1986-04-23 22:12:22 +00:00
|
|
|
struct node *nd;
|
1986-05-21 18:32:20 +00:00
|
|
|
label true_label, false_label;
|
1986-04-23 22:12:22 +00:00
|
|
|
{
|
|
|
|
/* Check an expression and generate code for it
|
1986-04-21 17:27:06 +00:00
|
|
|
*/
|
1986-04-23 22:12:22 +00:00
|
|
|
|
|
|
|
DO_DEBUG(1, (DumpTree(nd), print("\n")));
|
|
|
|
|
1986-05-01 19:06:53 +00:00
|
|
|
if (! chk_expr(nd)) return;
|
|
|
|
|
1986-05-21 18:32:20 +00:00
|
|
|
Desig = InitDesig;
|
|
|
|
CodeExpr(nd, &Desig, true_label, false_label);
|
1986-04-23 22:12:22 +00:00
|
|
|
}
|
|
|
|
|
1986-04-25 10:14:08 +00:00
|
|
|
WalkDesignator(nd)
|
|
|
|
struct node *nd;
|
|
|
|
{
|
|
|
|
/* Check designator and generate code for it
|
|
|
|
*/
|
|
|
|
|
|
|
|
DO_DEBUG(1, (DumpTree(nd), print("\n")));
|
|
|
|
|
1986-05-01 19:06:53 +00:00
|
|
|
if (! chk_designator(nd, DESIGNATOR|VARIABLE)) return;
|
|
|
|
|
1986-05-21 18:32:20 +00:00
|
|
|
Desig = InitDesig;
|
|
|
|
CodeDesig(nd, &Desig);
|
1986-04-25 10:14:08 +00:00
|
|
|
}
|
|
|
|
|
1986-04-23 22:12:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
DumpTree(nd)
|
|
|
|
struct node *nd;
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
extern char *symbol2str();
|
|
|
|
|
|
|
|
if (!nd) {
|
|
|
|
print("()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
print("(");
|
|
|
|
DumpTree(nd->nd_left);
|
|
|
|
switch(nd->nd_class) {
|
|
|
|
case Def: s = "Def"; break;
|
|
|
|
case Oper: s = "Oper"; break;
|
|
|
|
case Uoper: s = "Uoper"; break;
|
|
|
|
case Name: s = "Name"; break;
|
|
|
|
case Set: s = "Set"; break;
|
|
|
|
case Value: s = "Value"; break;
|
|
|
|
case Call: s = "Call"; break;
|
|
|
|
case Xset: s = "Xset"; break;
|
|
|
|
case Stat: s = "Stat"; break;
|
|
|
|
case Link: s = "Link"; break;
|
|
|
|
default: s = "ERROR"; break;
|
|
|
|
}
|
|
|
|
print("%s %s", s, symbol2str(nd->nd_symb));
|
|
|
|
DumpTree(nd->nd_right);
|
|
|
|
print(")");
|
1986-04-21 17:27:06 +00:00
|
|
|
}
|
1986-04-23 22:12:22 +00:00
|
|
|
#endif
|