Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - kcc-6/kcc/ccnode.c
There is 1 other file named ccnode.c in the archive. Click here to see a list.
/*	CCNODE.C - Parse-tree node routines
**
**	(c) Copyright Ken Harrenstien 1989
**		Plus all CCDUMP changes after v.142, 8-Apr-1988
**	(c) Copyright Ken Harrenstien, SRI International 1985, 1986
**		All CCDUMP changes after v.58, 8-Aug-1985
**
** Original CCDUMP (C) 1981  K. Chen
*/

#include "cc.h"
#include <string.h>	/* memcpy */
#include <stdlib.h>	/* malloc, free */

/* Exported functions */
NODE *ndef();		/* Basic NODE definition routine */
NODE *ndefop(),		/* Auxiliary variations */
	*ndeft(), *ndeftf(), *ndeftl(), *ndeftr(),
	*ndefl(), *ndefr(), *ndeflr();
NODE *ndefident();
NODE *ndeficonst();	/* For CCSTMT, CCTYPE */
void nodedump();	/* CC */
int nodeidx();		/* CCERR */

/* Internal functions */
static int dmpnsum();
static void dumpnode(), dmpntype(), dmpcast();

/* Internal data & defs */
#define NODEBLKSIZ 100		/* Dynamically alloc in increments of this */
struct xnode {
	NODE xn;
	int xn_idx;
};

struct nodeblk {		/* Dynamically allocated node blocks */
	struct nodeblk *nb_next;
	char nb_check[4];	/* To hold "NODE" for possible debug check */
	struct xnode nb_nodes[NODEBLKSIZ];
};

static int maxnode = 0;			/* Total # nodes in use */
static struct nodeblk *nodehd = NULL;	/* Start of any allocated blks */
static int nodebcnt = 0;		/* # of nodes used in current blk */
/* NODEINIT - Initialize the static node table and free any dynamic nodes.
*/
void
nodeinit()
{
    struct nodeblk *this;

    maxnode = 0;		/* Init static table */
    while (this = nodehd) {
	nodehd = this->nb_next;	/* Save ptr to next */
	free((char *)this);	/* Free up this one */
    }
    nodebcnt = 0;		/* Nothing in any blk */
}

/* NGET - Auxiliary to obtain a free node, without filling it in.
*/
static NODE *
nget()
{
    NODE *nd;

    if (++maxnode < MAXNODE)		/* Normal case, use static array */
	nd = &nodes[maxnode-1];
    else {
	/* Static table full, try to get dynamic allocation */
	struct nodeblk *nb;

	if (!nodehd || nodebcnt >= NODEBLKSIZ-1) {
	    if (!(nb = (struct nodeblk *)malloc(sizeof(struct nodeblk))))
		efatal("Out of memory, cannot allocate more nodes (%d used)", maxnode);
	    memcpy(nb->nb_check, "NODE", 4);	/* Install check value */
	    nb->nb_next = nodehd;		/* Link into block list */
	    nodehd = nb;
	    nodebcnt = 0;			/* Initialize count */
	}
	nd = (NODE *) &(nodehd->nb_nodes[nodebcnt++]);
	((struct xnode *)nd)->xn_idx = maxnode;		/* Put in index # */
    }
    return nd;
}

/* NODEIDX - Return index for a node pointer.
**	Returns -1 if pointer seems bad.
*/
int
nodeidx(n)
NODE *n;
{
    int i;
    i = n - &nodes[0];	/* First try to derive index into static array */
    if (i < 0 || i >= MAXNODE) {	/* If bad result, maybe dynamic */
	if (nodehd == NULL)		/* see if have any dynamic stuff */
	    return -1;			/* Nope, error */
	i = ((struct xnode *)n)->xn_idx;	/* Else assume dynamic */
    }
    return i;
}
/* NDEF - Node DEFinition routines
*/

#define NSET(op,t,f,l,r) NODE *n = nget(); \
	n->Nop = op, n->Ntype = t, n->Nflag = f, n->Nleft = l, n->Nright = r;\
	n->Nendlab = 0, n->Nxfint = 0; \
	return n;
NODE *
ndef(op, t, f, l, r)
int op;		/* Node token value (a N_ or Q_ token) */
TYPE *t;	/* Node's C type */
int f;		/* Flags */
NODE *l, *r;	/* Left and Right links */
{
    NSET(op,t,f,l,r)
}

/* Handy variations for defining a node.  The op is always required.
**	NDEFOP	- Op
**	NDEFT	- Op, Type.
**	NDEFTF	- Op, Type, Flags.
**	NDEFTL	- Op, Type, Left.
**	NDEFTR	- Op, Type, Right.
**	NDEFL	- Op, Left.
**	NDEFR	- Op, Right.
**	NDEFLR	- Op, Left, Right.
*/
NODE *ndefop(op)			{ NSET(op,0,0,0,0) }
NODE *ndeft(op,t)    TYPE *t;		{ NSET(op,t,0,0,0) }
NODE *ndeftf(op,t,f) TYPE *t;		{ NSET(op,t,f,0,0) }
NODE *ndeftl(op,t,l) TYPE *t; NODE *l;	{ NSET(op,t,0,l,0) }
NODE *ndeftr(op,t,r) TYPE *t; NODE *r;	{ NSET(op,t,0,0,r) }
NODE *ndefl(op,l)    NODE *l;		{ NSET(op,0,0,l,0) }
NODE *ndefr(op,r)    NODE *r;		{ NSET(op,0,0,0,r) }
NODE *ndeflr(op,l,r) NODE *l, *r;	{ NSET(op,0,0,l,r) }
/* Auxiliaries for common kinds of node definitions */

/* NDEFICONST - Makes a N_ICONST node of type (int) and sets its value.
*/
NODE *
ndeficonst(val)
int val;
{
    NODE *n = ndeft(N_ICONST, inttype);
    n->Niconst = val;
    return n;
}


/* NDEFIDENT - Makes a Q_IDENT node and sets its symbol.
*/
NODE *
ndefident(s)
SYMBOL *s;
{
    NODE *n = ndeft(Q_IDENT, s->Stype);
    n->Nid = s;
    return n;
}
/* ---------------------------- */
/*	dump code 		*/
/* ---------------------------- */

static char dmphlp[] = "\
Each line represents one parse-tree node, in the format:\n\
 # <L/R>: <Nname> (N#), nflag: <#>, ntype: <desc>, <extra stuff>\n\
where\n\
   #	- Node index.  This is sometimes shown in internal error messages.\n\
  <L/R> - Left or Right.  Left nodes are considered inferior (child) nodes\n\
	and are indented.  Right nodes are considered successors and keep\n\
	the existing indentation.  L/R == Lisp CAR/CDR.\n\
  <Nname> - Node op name, as used in KCC, followed by actual decimal index.\n\
  <#> - octal value of nflag member, if non-zero.\n\
  <desc> - description of ntype member, if non-zero: #n -> ttype\n\
	where n is its index in the types table and ttype the type's type.\n\
  <extra> - node specific information, if any.\n\
";

void
nodedump(n)
NODE *n;
{
    char *s;
    static int helpdone = 0;
    int ind = 0;

    if (n == NULL) return;
    if(!helpdone) {
	fputs(dmphlp,fdeb);
	helpdone++;
    }
    switch (n->Nop) {
    case N_DATA:
	s = "Data";
	break;
    case N_FUNCTION:
	s = "Function";
	break;
    default:
	s = "ILLEGAL toplevel node";
	ind++;		/* Don't process further */
	break;
    }
    fprintf(fdeb, "---- %s ----\nTop: ", s);
    dmpnsum(n);
    fprintf(fdeb, "\n");

    if(ind) return;		/* Hack to avoid unknown nodes */

    if (n->Nleft)
	dumpnode(n->Nleft, "L", 8);
    if (n->Nright)
	dumpnode(n->Nright, "R", 4);
}

static void
dumpnode(n, branch, ind)
NODE *n;
char *branch;
int ind;
{
    int size;

    /* First print node index as an identifier (helps relate to err msgs) */
    fprintf(fdeb,"%4d ", nodeidx(n));

    /* Do indentation.  Avoid using fancy printf features for now. */
    size = (ind - 1) - strlen(branch);
    while(--size >= 0)
	putc(' ', fdeb);

    /* Output same summary for all nodes */
    fprintf(fdeb, "%s: ", branch);	/* Do indentation */
    if(!dmpnsum(n)) return;

    /* Now do stuff specific to each node op.  In particular, every
     * op which does NOT have left+right pointers should be trapped.
     */
    switch (n->Nop) {

	/* Default is to assume that node has a link structure, since this
	 * is true for almost all node ops.  The exceptions should be
	 * handled as specific cases below.
	 */
    default: break;

    case Q_GOTO:
    case N_LABEL:
	fprintf(fdeb, " = label sym \"%s\"", n->Nxfsym->Sname);
	break;

    case Q_SWITCH:
	fprintf(fdeb, ", caselist %o", nodeidx(n->Nxswlist));
	break;		/* Now do normal linkages */

    case Q_DEFAULT:
	fprintf(fdeb, ", caseptr %o\n", nodeidx(n->Nright));
	if(n->Nleft)
	    dumpnode(n->Nleft, "L", ind+4);
	return;

    case Q_CASE:
	fprintf(fdeb, " = case value %d, caseptr %o\n",
		n->Nxfint, nodeidx(n->Nright));
	if(n->Nleft)
	    dumpnode(n->Nleft, "L", ind+4);
	return;

    case Q_DOT:
    case Q_MEMBER:
	fprintf(fdeb, ", offset %d\n", n->Nxoff);
	if(n->Nleft)
	    dumpnode(n->Nleft, "L", ind+4);
	return;

    case N_CAST:
	fprintf(fdeb, ", ");
	dmpcast(n->Ncast);
	putc('\n', fdeb);
	if(n->Nleft)
	    dumpnode(n->Nleft, "L", ind+4);
	return;

    /* Now handle special cases which never have links */
    case N_FCONST:
	fprintf(fdeb, ", val = %.20g\n", n->Nfconst);
	return;
    case N_ICONST:
	fprintf(fdeb, ", val = %d\n", n->Niconst);
	return;
    case N_SCONST:
	fprintf(fdeb, ", val = \"%s\" (%d)\n", n->Nsconst, n->Nsclen);
	return;
    case Q_IDENT:
	fprintf(fdeb, ", name \"%s\"\n", n->Nid->Sname);
	return;

    }

    if (tok[n->Nop].tktype == TKTY_ASOP && (n->Nascast != CAST_NONE)) {
	fprintf(fdeb, ", ascast=");
	dmpcast(n->Nascast);
    }

    /* Do default */
    putc('\n', fdeb);
    if (n->Nleft)
	dumpnode(n->Nleft, "L", ind+4);
    if (n->Nright)
	dumpnode(n->Nright, "R", ind);
}
/* dmpnsum - dump a standard summary of the node's generic contents.
 *	Returns 0 if node address is suspected to be bad.
 */
static int
dmpnsum(n)
NODE *n;
{
    int i;

    i = nodeidx(n);		/* Attempt to derive index of node */
    if(i < 0) {
	fprintf(fdeb, "ERROR: bad node address %o (= index %d)\n", n, i);
	return(0);
    }
    fprintf(fdeb, "%s (%d)", ((n->Nop >= NTOKDEFS) ? "??" : nopname[n->Nop]),
		n->Nop);
    if(n->Nflag) fprintf(fdeb, ", nflag: 0%o", n->Nflag);
    if(n->Ntype) {
	fprintf(fdeb, ", ntype: ");
	dmpntype(n->Ntype);
    }
    return(1);
}

/* dmpntype - dump node's ntype value in readable form */
static void
dmpntype(typ)
TYPE *typ;
{   char *s;

    if(!typ) {
	fprintf(fdeb, "0");
	return;
    }
    fprintf(fdeb,"#%d ->", typ - types);
    while(typ) {
	if (0 <= typ->Tspec && typ->Tspec < TS_MAX) {
	    s = tsnames[typ->Tspec];
	    if (typ->Tspec == TS_STRUCT || typ->Tspec == TS_UNION)
		typ = 0;
	} else {
	    fprintf(fdeb, "ILLEGAL! %d=", typ->Tspec);
	    s = "?";
	    typ = 0;
	}
	fprintf(fdeb, " %s", s);
	if(typ) typ = typ->Tsubt;	/* Get next subtype */
    }
}

static char *castnames[] = {
#define castspec(op,str) str,
	allcastmacro		/* Expand */
#undef castspec
};

static void
dmpcast(castop)
int castop;
{
    if (0 <= castop && castop < CAST_MAX)
	fprintf(fdeb, "%s", castnames[castop]);
    else fprintf(fdeb, "ERROR: unknown cast-type = %d", castop);
}