view mc-parse.c @ 33:8500dbb69dd9

bad macro processing. give up this method.
author kono
date Sun, 09 Feb 2003 23:17:23 +0900
parents b35787d8a442
children 0756caa79167
line wrap: on
line source

/* Micro-C Parser Part */
/* $Id$ */

#define EXTERN /**/
#include "mc.h"

void ntable_consistency();
static void adecl(NMTBL *n);
static int decl_data(int t, NMTBL *n,int offset);
static int alpha(char c);
static int binop(int op, int e1, int e2, int t1, int t2);
static void compatible(int t1, int t2);
static void decl(void);
static void def(NMTBL *n);
static int digit(char c);
static void docase(void);
static void docomp(void);
static void dodefault(void);
static void dodo(void);
static void dofor(void);
static void dogoto(void);
static void doif(void);
static void dolabel(void);
static void doswitch(void);
static void doreturn(void);
static void dowhile(void);
static void errmsg(void);
static void macro_processing();
static void macro_define();
static void macro_define0();
static void copy(NMTBL *nptr, char *s);
void error(int n);
static int expr(void);
static int expr0(void);
static int expr1(void);
static int expr2(void);
static int expr3(void);
static int expr4(void);
static int expr5(void);
static int expr6(void);
static int expr7(void);
static int expr8(void);
static int expr9(void);
static int expr10(void);
static int expr11(void);
static int expr12(void);
static int expr13(void);
static int expr14(void);
static int expr15(int e1);
static int expr16(int e1);
static void fcheck(NMTBL *n);
static void fdecl(NMTBL *n);
static int getch(void);
static int getfree(int n);
static void getline(void);
static void getstring(void);
static int getsym(void);
static int indop(int e);
static void init(void);
static int integral(int t);
static void lcheck(int e);
extern int glist2(int e1,int e2);
extern int list2(int e1, int e2);
extern int list3(int e1, int e2, int e3);
extern int list4(int e1, int e2, int e3, int e4);
extern int rplacad(int e, int n);
extern int rplacadd(int e, int n);
static void reserve(char *s, int d);
static int macroeq(char *s);
static int ndecl0(void);
static int ndecl1(void);
static int neqname(char *p,char *name);
static void newfile(void);
static int postequ(int s1, int s2);
static void reverse(int t1);
int reverse0(int t1);
static int rvalue(int e);
int scalar(int t);
static int sdecl(int s);
static int skipspc(void);
static void statement(void);
static int strop(int e);
static int typeid(int s);
static int typename(void);
static int typespec(void);
static int cexpr(int e);
static void code_decl(NMTBL *n);
static int macro_args();
static void fmacro();
static void local_define();
static void local_undef();
static int recursive_macro(char *);

extern void display_ntable(NMTBL *n, char *s);
extern void closing(void);
extern void opening(char *filename);
extern void gen_gdecl(char *n, int gpc);
extern void emit_init(void);
extern void enter(char *name);
extern void enter1(int disp);
extern void leave(int control, char *name);
extern void ret(void);
extern void jmp(int l);
extern void gexpr(int e1);
extern void g_expr(int e1);
extern int get_register_var(void);
extern void bexpr(int e1, char cond, int l1);
extern int fwdlabel(void);
extern void fwddef(int l);
extern int backdef(void);
extern int def_label(int cslabel, int dlabel);
extern void jmp_label(int l);
extern void cmpdimm(int e, int csreg);
extern void jcond(int l, char cond);
extern void jmp_eq_label(int l);
extern void gen_comment(char *s);
extern void gen_source(char *s);
extern void code_init(void);
extern void code_enter(char *name) ;
extern void code_leave(char *name) ;
extern void code_enter1(int disp0,int args);

extern void emit_data_closing(NMTBL *n);
extern void emit_data(int e, int t, NMTBL *n);

extern void exit(int l);

int
main(int argc, char **argv)
{
    NMTBL *nptr;
    int i;
    char *ccout;

    if(argc==1) exit(1);
    lsrc = chk = asmf = 0;
    ccout = OUTPUT_FILE_NAME;
    ac=argc;
    av=argv;
    for (ac2=1; (ac2 < ac) && (*av[ac2] == '-'); ++ac2) {
	switch (*(av[ac2]+1)) {
	case 'S': case 's':
	    lsrc = 1;
	    break;
	case 'O': case 'o':
	    ccout = av[ac2]+2;
	    break;
	case 'C': case 'c':
	    chk = 1;
	    break;
	case 'D': case 'd':
	    debug = 1;
	    break;
	default:
	    error(OPTION);
	    exit(1);
	}
    }
    if (!chk)
	if ( (freopen(ccout,"w",stdout)) == NULL ) error(FILERR);
    init();
    while(1) {	
	for (nptr = &ntable[GSYMS],i=LSYMS; i--;) {
	    (nptr++)->sc = 0;
	}
	emit_init();
	mode=TOP;
	lfree= HEAPSIZE;
	while(getsym()==SM);
	mode=GDECL;
	stmode=0;
	args=0;
	decl();
    }
    /*NOTREACHED*/
}

void
error(int n)
{
    if(n == EOFERR) {
	if(filep!=filestack) {	
	    fclose(filep->fcb);
	    lineno=filep->ln;
	    --filep;
	    return;
	} else if(ac2!=ac) {	
	    fclose(filep->fcb);
	    newfile();
	    return;
	} else if(mode == TOP) {	
		/*
	    if (!chk) fprintf(stderr,
		    "Total internal labels	: %u.\n",labelno-1);
	    fprintf(stderr,
		    "Total global variables : %u bytes.\n\n",gpc);
		 */
	    closing();
	    exit(0);
	}
    }
    fprintf(stderr,"%s:%d:%s\n",filep->name0,lineno,
	(n==FILERR) ? "Can't open specified file" :
	(n==DCERR) ? "Declaration syntax" :
	(n==STERR) ? "Statement syntax" :
	(n==EXERR) ? "Expression syntax" :
	(n==CNERR) ? "Constant required" :
	(n==CHERR) ? "Illegal character" :
	(n==GSERR) ? "Too many global symbols" :
	(n==LSERR) ? "Too many local symbols" :
	(n==MSERR) ? "Too many macro symbols" :
	(n==STRERR) ? "Too many strings or macros" :
	(n==LNERR) ? "Line too long" :
	(n==EOFERR) ? "Unexpected end of file" :
	(n==MCERR) ? "Macro syntax" :
	(n==INCERR) ? "Include syntax" :
	(n==HPERR) ? "Too long expression" :
	(n==TYERR) ? "Type mismatch" :
	(n==LVERR) ? "Lvalue required" :
	(n==UDERR) ? "Undeclared identifier" :
	(n==OPTION) ? "Illegal option" :
	(n==REG_ERR) ? "illegal register var" :
	(n==CODE_ERR) ? "goto code is necessary" :
	"Bug of compiler");
    errmsg();
    exit(1);
}

void
errmsg(void)
{
    char *p,*lim;

    if(lineno==0) return;
    fprintf(stderr,"%s",linebuf);
    lim=chptr;
    while (chptrsave) {
	lim = (char *)car(chptrsave);
	chptrsave = cadr(chptrsave);
    }
    for (p=linebuf; p < lim;)
	    fprintf(stderr,(*p++ == '\t') ? "\t" : " ");
    fprintf (stderr,"^\n");
}

void
checksym(int s)
{
    char *p;

    if (sym != s) {	
	p=(s==RPAR) ? "')'": (s==RBRA) ? "']'": (s==SM) ? "';'":
	  (s==LPAR) ? "'('": (s==WHILE) ? "'while'":
	  (s==COLON) ? "':'": "Identifier";
	fprintf(stderr,"%d:%s expected.\n",lineno,p);
	errmsg();
    } else 
	getsym();
}

void
init(void)
{
    NMTBL *nptr;
    int i;

    cheapp=cheap;
    for(nptr = ntable,i = GSYMS; i--;) (nptr++)->sc = 0;
    for(nptr = mtable,i = MSYMS; i--;) (nptr++)->sc = 0;
    reserve("int",INT);
    reserve("void",VOID);
    reserve("char",CHAR);
    reserve("const",KONST);
    reserve("struct",STRUCT);
    reserve("union",UNION);
    reserve("unsigned",UNSIGNED);
    reserve("static",STATIC);
    reserve("goto",GOTO);
    reserve("return",RETURN);
    reserve("break",BREAK);
    reserve("continue",CONTINUE);
    reserve("if",IF);
    reserve("else",ELSE);
    reserve("for",FOR);
    reserve("do",DO);
    reserve("while",WHILE);
    reserve("switch",SWITCH);
    reserve("case",CASE);
    reserve("default",DEFAULT);
    reserve("typedef",TYPEDEF);
    reserve("sizeof",SIZEOF);
    reserve("long",LONG);
    reserve("short",SHORT);
    reserve("extern",EXTRN);
    reserve("defined",DEFINED);
    reserve("register",REGISTER);
    reserve("code",CODE);
    reserve("environment",ENVIRONMENT);

    gpc=glineno=mflag=0;
    gfree=ilabel=1;
    labelno=2;
    lfree=HEAPSIZE;
    filep=filestack;
    code_init();
    newfile();

    macro_define("__micro_c__ 1\n");

    getline();
    getch();
}

void
newfile(void)
{
    char *s;
    lineno=0;
    /* fprintf(stderr,"%s:\n",av[ac2]); */
    opening(av[ac2]);
    if ( (filep->fcb = fopen(av[ac2++],"r")) == NULL ) error(FILERR);
    s = av[ac2-1];
    filep->name0 = cheapp;
    while((*cheapp++ = *s++));
}

void
reserve(char *s, int d)
{
    NMTBL *nptr;
    int i;

    hash=0; name=namebuf; i=0;
    while((name[i++] = *s)) {
	hash=((7*hash) ^ *s++);
    }
    if (cheapp+i >= cheap+CHEAPSIZE) error(STRERR);
    name[i++] = 0;
    (nptr = gsearch())->sc = RESERVE;
    if (d==0) {
	nptr->sc = MACRO;
	nptr->dsp = (int)""; nptr->ty=0;
    } else {
	nptr->dsp = d;
    }
}

static
NMTBL null_nptr;

void
decl(void)
{
    NMTBL *n;
    int t;

    if(sym==STATIC) {
	if(mode==LDECL) {	
		getsym();
		mode=STADECL;
		stmode=LDECL;
	} else if(mode==GDECL) {	
		getsym();
		stmode=STATIC;
	} else 
	    error(DCERR);
    } else if(sym==REGISTER) {
	if(mode!=LDECL)  
	    error(DCERR);
	stmode=REGISTER;
	getsym();
    } else if(sym==EXTRN) {
	getsym();
	stmode=EXTRN;
    } else if(sym==TYPEDEF) {
	if(mode==GDECL) {	
		getsym();
		mode=GTDECL;
	} else if(mode==LDECL) {	
		getsym();
		mode=LTDECL;
	} else 
		error(DCERR);
    }
    if((t=typespec())==0) return;
    if(sym==SM) return;
    type=t;
    n=decl0();
    reverse(t);
    if (n == &null_nptr) {
	error(DCERR);
	return;
    }
    if(sym==LC || ( sym!=SM && sym!=COMMA && sym!=ASS )) {
	if (car(type)==CODE) {
	    code_decl(n); return;
	} else if (car(type)==FUNCTION) {
	    fdecl(n); return;
	}
    }
    def(n);
    while(sym==COMMA) {	
	getsym();
	type=t;
	n=decl0();
	reverse(t);
	if(n == &null_nptr) error(DCERR); 
	/* if(args) error(DCERR); */
	def(n);
    }
    if(sym!=SM) error(DCERR);
    if(mode==GTDECL) 
	mode=GDECL;
    if(mode==STADECL||mode==LTDECL) 
	mode=LDECL;
}

int
typespec(void)
{
    int t;

    while (sym==KONST) {
	getsym();
    }
    switch(sym) {
    case VOID:
    case INT:
    case CHAR:
    case CODE:
	t= sym;
	getsym();
	break;
    case STRUCT:
    case UNION:
	t=sdecl(sym);
	break;
    case UNSIGNED:
	t = UNSIGNED;
	if(getsym()==INT) getsym();
	break;
    case SHORT:
	t=CHAR;
	if(getsym()==INT) getsym();
	break;
    case LONG:
	t=INT;
	if(getsym()==INT) getsym();
	break;
    default:
	if(sym==IDENT) {
	    if(nptr->sc==TYPE) {	
		t=nptr->ty;
		getsym();
		break;
	    } else if(nptr->sc==EMPTY && gnptr->sc==TYPE) {	
		t=gnptr->ty;
		getsym();
		break;
	    }
	}
	while (sym==KONST) {
	    getsym();
	}
	if(mode==LDECL) return 0;
	t= INT;
    }
    while (sym==KONST) {
	getsym();
    }
    return t;
}

struct nametable *
decl0(void)
{
    NMTBL *n;
    if(sym==MUL) {	
	getsym();
	n=decl0();
	type=list2(POINTER,type);
	return n;
    }
    return decl1();
}


NMTBL *
decl1(void)
{
    NMTBL *n;
    int i,t;

    if(sym==LPAR) {	
	getsym();
	n=decl0();
	checksym(RPAR);
    } else if (sym == IDENT) {	
	n=nptr;
	getsym();
    } else {
	/* error(DCERR); */
	n= &null_nptr;
    }
    while(1) {
	if(sym==LBRA) {
	    if(getsym()==RBRA) {	
		getsym();
		if(mode==ADECL) {
		    t=type;
		    type=list2(POINTER,type);
		} else if (mode==GDECL) {
		    t=type;
		    type=list3(ARRAY,t,0);
		} else {
		    error(DCERR);
		}
	    } else {	
		t=type;
		i=cexpr(expr());
		checksym(RBRA);
		type=list3(ARRAY,t,i);
	    }
	} else if(sym==LPAR) {	
	    if(mode==GDECL) {
		mode=ADECL;getsym();mode=GDECL; /* ??? */
	    } else 
		getsym();
	    if(sym==RPAR) 
		getsym();
	    else {	
		if (type==CODE) {
		    n->sc=CODE;
		    n->dsp=0;
		    stmode=REGISTER;
		    adecl(n);
		    stmode=0;
		    n->sc=EMPTY;
		    type=list3(CODE,type,cadr(n->ty));
		    return n;
		} else {
		    n->sc=FUNCTION;
		    n->dsp=0;
		    adecl(n);
		    n->sc=EMPTY;
		}
	    }
	    type=list3(FUNCTION,type,cadr(n->ty));
	} else 
	    return n;
    }
}


void
adecl(NMTBL *n)
{
    NMTBL *arg,*sfnptr;
    int sreg_var,t;
    int stype,smode;

    stype=type;
    sfnptr=fnptr;
    fnptr=n;
    sreg_var=reg_var;
    reg_var=0;
    n->dsp=0;
    smode = mode;
    /* if(mode!=GDECL && mode!=ADECL) 
	 error(DCERR);  */
    mode=ADECL;
    args= 0;
    for(;;) {	
	if(sym==IDENT && nptr->sc!=TYPE) {
	    rplacad(n->ty,glist2(INT,cadr(n->ty)));
	    if (stmode==REGISTER && reg_var < MAX_REGISTER_VAR) {
		nptr->ty = INT;
		nptr->sc = REGISTER;
		if ((nptr->dsp = get_register_var())<0)
		    error(-1);
		reg_var++;
	    } else {
		nptr->ty = INT;
		nptr->sc = LVAR;
		nptr->dsp = args ;
		args += size_of_int;
	    }
	    getsym();
	    if(sym==RPAR) break;
	} else {
	    if(sym==DOTS) {
		rplacad(n->ty,glist2(INT,cadr(n->ty)));
		getsym();
		break;
	    } 
	    if((t=typespec())==0) {
		error(DCERR);
		break;
	    }
	    if(sym!=COMMA && sym!=RPAR) {
		if(sym==RPAR) break;
		type=t;
		arg=decl0();
		reverse(t);
		if (arg != &null_nptr) { /* no varname typespec only */
		    def(arg);
		}
	    }
	    rplacad(n->ty,glist2(t,cadr(n->ty)));
	    if(sym==RPAR) break;
	} 
	if (sym!=COMMA) error(DCERR); 
	getsym();
    }
    checksym(RPAR);
    mode=smode;
    reg_var=sreg_var;
    fnptr=sfnptr;
    type=stype;
    return;
}

void 
reverse(int t1)
{
    int t2,t3;
    t2=t1;

    while(type!=t1) {	
	t3=cadr(type);
	rplacad(type,t2);
	t2=type;
	type=t3;
    }
    type = t2;
}

int 
reverse0(int t1)
{
    int t2,t3;

    t2=0;
    while(t1) {	
	t3=cadr(t1);
	rplacad(t1,t2);
	t2=t1;
	t1=t3;
    }
    return t2;
}

int
size(int t)
{
    if(t==CHAR) return 1;
    if(t==VOID) return 0;
    if(scalar(t)) return size_of_int;
    if(car(t)==STRUCT||car(t)==UNION) {	
	if(cadr(t)==-1) error(DCERR);
	return(cadr(t));
    }
    if(car(t)==ARRAY) 
	return(size(cadr(t))*caddr(t));
    else 
	error(DCERR);
    return 0;
}

void
def(NMTBL *n)
{
    int sz,nsc,ndsp,t;

    nsc=ndsp=0;
    if(car(type)==FUNCTION) {	
	fcheck(n);
	return;
    }
    if (n->sc!=EMPTY && 
	    !(n->sc==GVAR&&n->dsp==EXTRN) &&
	    !(n->sc==FUNCTION&&n->dsp==EXTRN) &&
	(mode!=ADECL || n->sc!=LVAR || n->ty!=INT) &&
	(mode!=ADECL || n->sc!=REGISTER || n->ty!=INT) &&
	((mode!=GSDECL&&mode!=LSDECL) || n->sc!=FIELD || n->dsp!=disp) &&
	((mode!=GUDECL&&mode!=LUDECL) || n->sc!=FIELD || n->dsp!=0) )
	 error(DCERR);
    sz = size(n->ty = type);
    switch(mode) {
    case GDECL:
	gen_gdecl(n->nm,gpc);
    case STADECL:
	nsc = GVAR;
	ndsp = gpc;
	if (stmode==EXTRN)
	    n->dsp = EXTRN;
	else
	    n->dsp = ndsp;  /* emit_data will override this */
	n->sc = nsc;
	if (stmode==LDECL) {
	    copy(n,n->nm);
	    cheapp[-1] = '.';
	    ndsp = ++stat_no;
	    while(ndsp>0) {
		*cheapp++ = ndsp%10+'0';
		ndsp /= 10;
	    }
	    *cheapp++ = 0;
	}
	if(sym==ASS) {	
	    decl_data(type,n,0);
	    emit_data_closing(n);
	    /* gpc is incremented by emit_data */
	} else 
	    gpc +=sz;
	return;
    case GSDECL:
	nsc = FIELD;
	ndsp = disp;
	disp += sz;
	break;
    case GUDECL:
	nsc = FIELD;
	ndsp = 0;
	if (disp < sz) disp = sz;
	break;
    case GTDECL:
	nsc = TYPE;
	break;
    case ADECL:
	if (stmode==REGISTER && reg_var <MAX_REGISTER_VAR) {
	    if (type!=CHAR && !scalar(type)) 
		error(TYERR);
	    nptr->sc = REGISTER;
	    reg_var++;
	    if (nptr->dsp==0) {
		if ((nptr->dsp = get_register_var())<0) {
		    error(-1);
		} 
	    } 
	    return;
	}
	nptr->sc = LVAR;
	if(type==CHAR) {
	    /* nptr->ty=INT; */
	    if (nptr->dsp==0) {
		nptr->dsp = args;
		if (endian) 
		    n->dsp += size_of_int-1;
	    }
	    args += size_of_int;
	} else {
	    if (nptr->dsp==0)
		nptr->dsp = args;
	    args += sz;
	}
	if(type==VOID) {
	} else if (!scalar(type)) {
	    if((t=car(type))==STRUCT || t==UNION) {
		nptr->ty = type;
	    } else
		error(TYERR);
	}
	return;
    case LDECL:
	if (stmode==REGISTER && reg_var <=MAX_REGISTER_VAR) {
	    if(!scalar(type)) /* non integer register type ... */
		error(DCERR);
	    nsc = REGISTER;
	    reg_var++;
	    if ((ndsp = get_register_var())<0)
		error(-1);
	} else {
	    nsc = LVAR;
	    ndsp = (disp -= sz);
	}
	n->sc = nsc;
	n->dsp = ndsp;
	if(sym==ASS) {	
	    decl_data(type,n,0);
	}
	return;
    case LSDECL:
	nsc = FIELD;
	ndsp = disp;
	disp += sz;
	break;
    case LUDECL:
	nsc = FIELD;
	ndsp = 0;
	if (disp < sz) disp = sz;
	break;
    case LTDECL:
	nsc = TYPE;
	break;
    default:
	error(DCERR);
    }
    n->sc = nsc;
    if (stmode==EXTRN)
	n->dsp = EXTRN;
    else
	n->dsp = ndsp;
}

void
emit_init_vars(void)
{
    if (!init_vars) return;
    init_vars = reverse0(init_vars);
    while(init_vars) {
	g_expr(car(init_vars));
	init_vars = cadr(init_vars);
    }
}

int
assign_data(int e, int t, NMTBL *n,int offset)
{
    int ass;

    if(mode==GDECL) {
 	emit_data(e,t,n);
	return offset+size(t);
    } else if(mode==LDECL) {
	if(t==CHAR) {
	    ass =list3(CASS,list2(LVAR,n->dsp+offset),rvalue(e));
	} else if (scalar(t)) {
	    ass = list3(ASS,list2(LVAR,n->dsp+offset),rvalue(e));
	} else if (car(t)==STRUCT || car(t)==UNION || car(t)==STRING) {
	    ass = list4(SASS,list2(LVAR,n->dsp+offset),rvalue(e),size(t));
	} else {
	    error(DCERR);
	}
	init_vars = list2(ass,init_vars);
	return offset+size(t);
    } else {
	error(DCERR);
    }
    return 0; /* not reached */
}

int
decl_data(int t, NMTBL *n,int offset)
{
    int t1,e,i,mode_save;

    mode_save = mode;
    mode=STAT;
    getsym();
    if (scalar(t)) {
 	e=expr1();
	mode = mode_save;
 	if(car(e)!=CONST && t==CHAR)
 	    error(TYERR);
 	offset = assign_data(e,t,n,offset);
 	type=t;
	return offset;
    }
    t1 = car(t);
    if (t1==ARRAY) {
	if (sym==LC) {
	    mode = mode_save;
	    t1 = cadr(t);
	    for(i=0;;i++) {
		if (sym!=RC)
		    offset=decl_data(t1,n,offset); /* array of some thing */
		if (sym==COMMA) { continue;
		} else if (sym==RC) {
		    if (caddr(t)==0) {           /* size not defined      */
			heap[t+2]=i+1;           /* define array size     */
		    } else if (caddr(t)!=i+1) {  /* size match?           */
			error(TYERR);
		    }
		    getsym();
		    return offset;
		} else {
		    error(TYERR);
		}
	    }
	} else if (cadr(t)==CHAR) {
	    e=expr1();
	    mode = mode_save;
	    if(car(e)!=STRING)
		error(TYERR);
	    offset=assign_data(e,list3(ARRAY,CHAR,size(type)),n,offset);
	    if (caddr(t)==0) {                  /* size not defined      */
		heap[t+2]=size(type);           /* define array size     */
	    } else if (caddr(t)!=size(type)) {  /* size match?           */
		error(TYERR);
	    }
	} else 
	    error(DCERR);
    } else if (t1==STRUCT) {
	mode = mode_save;
	if(cadr(t)==-1) error(DCERR);
	t1 = caddr(t);  /* list of fields */
	while(t1) {
	    offset = decl_data(car(t1),n,offset);  /* alignment? */
	    t1 = cadr(t1);
	    if ( t1 && sym==COMMA) continue;
	    if (!t1 && sym!=RC) error(DCERR);
	}
	getsym();
	return offset;
    } else {
	mode = mode_save;
 	error(TYERR); /* should be initialization error */
    }
    return offset; /* not reached */
}

int
sdecl(int s)
{
    int smode,sdisp,type0;
    NMTBL *nptr0,*gnptr0;
    int tags;

    smode=mode;
    if (mode==GDECL || mode==GSDECL || mode==GUDECL || mode==GTDECL)
	mode=(s==STRUCT?GSDECL:GUDECL);
    else 
	mode=(s==STRUCT?LSDECL:LUDECL);
    sdisp=disp;
    disp=0;
    if (getsym() == IDENT) {	
	nptr0 = nptr;
	gnptr0 = gnptr;
	if (getsym() == LC) {	
	    if (nptr0->sc != EMPTY) error(DCERR);
	    nptr0->sc = TAG;
	    tags = 0;
	    nptr0->ty = list3(s,-1,tags);
	    while (getsym() != RC) {
		decl();
		tags = list2(type,tags);
	    }
	    getsym();
	    tags=reverse0(tags);
	    heap[nptr0->ty+2]=tags;
	    rplacad(type0 = nptr0->ty,disp);
	} else {	
	    /* struct tag name */
	    if(nptr0->sc == EMPTY) nptr0=gnptr0;
	    if(nptr0->sc == EMPTY) error(UDERR);
	    if(nptr0->sc != TAG) error(TYERR);
	    tags = caddr(nptr0->ty);
	    disp = cadr(nptr0->ty);
	}
	type0 = list3(s,disp,tags);
    } else if(sym==LC) {	
	tags = 0;
	while(getsym() != RC) {
	    decl();
	    tags = list2(type,tags);
	}
	getsym();
	tags=reverse0(tags);
	type0 = list3(s,disp,tags);
    }
    else error(DCERR);
    disp=sdisp;
    mode=smode;
    return type0;
}

void
code_decl(NMTBL *n)
{
    int odisp;

    if (n->sc==EMPTY) n->sc = CODE;
    code_enter(n->nm);
    fnptr=n;
    disp = -args;
    args = 0;
    reg_var=0;
    mode=ADECL;
    stmode=REGISTER;
    while (sym!=LC) { /* argument declaration !ANSI */
	decl(); getsym();
    }
    if (args) disp = -args;
    else args = -disp;
    init_vars=0;
    /* local variable declaration */
    stmode=0;
    mode=STAT;
    init_vars=0;
    odisp=disp;
    while (typeid(getsym()) || sym==STATIC || sym==EXTRN || sym==TYPEDEF) {	
	mode=LDECL;
	decl();
	mode=STAT;
    }
    control=1;
    code_enter1(disp-odisp,args);
    emit_init_vars();
    while(sym!=RC) statement();
    if(control)
	error(STERR);
    control=0;
    code_leave(n->nm);
}

void
fdecl(NMTBL *n)
{
    enter(n->nm);
    fnptr=n;
    retlabel=fwdlabel();
    retcont = 0;

    args=0;
    reg_var=0;
    fcheck(n);
    mode=ADECL;
    while (sym!=LC) { /* argument declaration !ANSI */
	stmode=0;
	decl(); getsym();
    }
    disp=0;
    init_vars=0;
    /* local variable declaration */
    mode=STAT;
    while (typeid(getsym()) || sym==STATIC || sym==EXTRN 
		|| sym==REGISTER || sym==TYPEDEF) {	
	mode=LDECL;
	stmode=0;
	decl();
	mode=STAT;
    }
    control=1;
    enter1(disp);
    emit_init_vars();
    while(sym!=RC) statement();

    leave(control,n->nm);
    retpending = 0;
    control=0;
}

void
fcheck(NMTBL *n)
{
    if(mode!=GDECL||car(type)!=FUNCTION) error(DCERR);
    if(n->sc==FUNCTION) compatible(car(n->ty),cadr(type));
    else {
	if(n->sc!=EMPTY) 
	    error(DCERR);
	else {
	    n->sc=FUNCTION;
	    n->ty=glist2(cadr(type),0);
	}
    }
}

void
compatible(int t1, int t2)
{
    if(integral(t1)) {	
	    if(t1!=t2) error(TYERR);
    }
    else if(car(t1)!=car(t2)) 
	    error(TYERR);
    else if((car(t1)==STRUCT || car(t1)==UNION) && cadr(t1)!=cadr(t2))
	    error(TYERR);
    else if(car(t1)==POINTER || car(t1)==ARRAY ||car(t1)==FUNCTION)
	    compatible(cadr(t1),cadr(t2));
}

int
scalar(int t)
{
    return(integral(t)||car(t)==POINTER);
}

int
integral(int t)
{
    return(t==INT||t==CHAR||t==UNSIGNED);
}

void
checkret(void)
{
    if (retpending) {
	ret();
	control=0;
	retpending=0;
    }
}

void
statement(void)
{
    int slfree;

    if(sym==SM) { 
	getsym(); return; 
    }
    checkret();
    switch(sym) {
    case IF:
	doif();
	return;
    case WHILE:
	dowhile();
	return;
    case DO:
	dodo();
	return;
    case FOR:
	dofor();
	return;
    case SWITCH:
	doswitch();
	return;
    case LC:
	docomp();
	return;
    case BREAK:
	jmp(blabel);
	getsym();
	checksym(SM);
	return;
    case CONTINUE:
	jmp(clabel);
	getsym();
	checksym(SM);
	return;
    case CASE:
	docase();
	statement();
	return;
    case DEFAULT:
	dodefault();
	statement();
	return;
    case RETURN:
	doreturn();
	return;
    case GOTO:
	dogoto();
	return;
    default:
	if(sym==IDENT&&skipspc()==':') {	
	    dolabel();
	    statement();
	} else {	
	    slfree=lfree;
	    gexpr(expr());
	    lfree=slfree;
	    checksym(SM);
	}
    }
}

void
doif(void)
{
    int l1,l2,slfree;
    getsym();
    checksym(LPAR);
    slfree=lfree;
    bexpr(expr(),0,l1=fwdlabel());
    lfree=slfree;
    checksym(RPAR);
    statement();
    checkret();
    if(sym==ELSE) {	
	if ((l2 = control)) 
	    jmp(l2=fwdlabel());
	fwddef(l1);
	getsym();
	statement();
	checkret();
	if (l2) fwddef(l2);
    }
    else fwddef(l1);
}

void
dowhile(void)
{
    int sbreak,scontinue,slfree,e;

    sbreak=blabel;
    scontinue=clabel;
    blabel=fwdlabel();
    clabel=backdef();
    getsym();
    checksym(LPAR);
    slfree=lfree;
    e=expr();
    checksym(RPAR);
    if(sym==SM) {	
	bexpr(e,1,clabel);
	lfree=slfree;
	getsym();
    } else {	
	bexpr(e,0,blabel);
	lfree=slfree;
	statement();
	checkret();
	if(control)
	    jmp(clabel);
    }
    fwddef(blabel);
    clabel=scontinue;
    blabel=sbreak;
}

void
dodo(void)
{
    int sbreak,scontinue,l,slfree;

    sbreak=blabel;
    scontinue=clabel;
    blabel=fwdlabel();
    clabel=fwdlabel();
    l=backdef();
    getsym();
    statement();
    checkret();
    fwddef(clabel);
    checksym(WHILE);
    checksym(LPAR);
    slfree=lfree;
    bexpr(expr(),1,l);
    lfree=slfree;
    checksym(RPAR);
    checksym(SM);
    fwddef(blabel);
    clabel=scontinue;
    blabel=sbreak;
}

void
dofor(void)
{
    int sbreak,scontinue,l,e,slfree;

    sbreak=blabel;
    scontinue=clabel;
    blabel=fwdlabel();
    getsym();
    checksym(LPAR);
    slfree=lfree;
    if(sym!=SM) {	
	gexpr(expr());
	checksym(SM);
    }
    else getsym();
    lfree=slfree;
    l=backdef();
    if(sym!=SM) {	
	bexpr(expr(),0,blabel);
	checksym(SM);
    }
    else getsym();
    lfree=slfree;
    if(sym==RPAR) {	
	clabel=l;
	getsym();
	statement();
	checkret();
    } else {	
	clabel=fwdlabel();
	e=expr();
	checksym(RPAR);
	statement();
	checkret();
	fwddef(clabel);
	gexpr(e);
	lfree=slfree;
    }
    jmp(l);
    fwddef(blabel);
    clabel=scontinue;
    blabel=sbreak;
}

void
doswitch(void)
{
    int sbreak,scase,sdefault,slfree,svalue;

    sbreak=blabel;      /* save parents break label */
    blabel=fwdlabel();
    sdefault=dlabel;    /* save parents default label */
    dlabel=0;
    scase=cslabel;      /* save parents next case label */
    getsym();
    checksym(LPAR);
    slfree=lfree;
    svalue=csvalue1;      /* save parents switch value */
    gexpr(expr());
    csvalue1=csvalue ;
    lfree=slfree;
    checksym(RPAR);
    cslabel = control = 0;
    /* should be case statement but... */
    statement();
    checkret();
    if(dlabel) def_label(cslabel,dlabel);
    else fwddef(cslabel);
    csvalue1=svalue;
    cslabel=scase;
    dlabel=sdefault;
    fwddef(blabel);
    blabel=sbreak;
}

void
docomp(void)
{
    getsym();
    while(sym!=RC) { statement(); checkret();}
    getsym();
}

void
docase(void)
{
    int c,l,slfree;

    c=0;
    slfree=lfree;
    while(sym==CASE) {	
	getsym();
	c=list2(cexpr(expr()),c);
	checksym(COLON);
    }
    l=fwdlabel();
    if (control) {	
	control=0;
	jmp(l);
    }
    if (cslabel) fwddef(cslabel);
    while(cadr(c)) {	
	cmpdimm(car(c),csvalue1);
	jcond(l,0);
	c=cadr(c);
    }
    lfree=slfree;
    cmpdimm(car(c),csvalue1);
    jcond(cslabel=fwdlabel(),1);
    fwddef(l);
}

void
dodefault(void)
{
    getsym();
    checksym(COLON);
    if (dlabel) error(STERR);
    if (!cslabel) jmp(cslabel = fwdlabel());
    dlabel = backdef();
}

void
doreturn(void)
{
    int slfree;

    if(getsym()==SM) {	
	getsym();
	retpending = 1;
	return;
    }
    slfree=lfree;
    gexpr(expr());
    lfree=slfree;
    checksym(SM);
    retpending = 1;
}


void
dogoto(void)
{
    NMTBL *nptr0;
    int t,e1,e2,env;

    getsym();
    e1 = expr();
    t=car(e1);
    if (t==FNAME) {
	nptr0 = (NMTBL *)cadr(e1);
	t = nptr0->sc;
	if (t==EMPTY) {
	    nptr0->sc = FLABEL;
	    jmp(nptr0->dsp = fwdlabel());
	} else if (t==FLABEL||t==BLABEL) {
	    jmp(nptr0->dsp);
	}
	control=0;
	checksym(SM);
	return;
    } 
    if (t==COMMA) {
	env = caddr(e1);
	e1  = cadr(e1);
	t   = car(e1);
    } else {
	env = 0;
    }
    if (t==FUNCTION) {
	e2 = cadr(e1);
	if (car(e2) == FNAME) {     
	    nptr0=(NMTBL *)cadr(e2);
	    nptr0->sc = CODE;
	}
	gexpr(list3(CODE,e1,env));
	control=0;
	checksym(SM);
	return;
    }
    error(STERR);
    return;
}

void
dolabel(void)
{
    if(nptr->sc == FLABEL) 
	fwddef(nptr->dsp);
    else if(nptr->sc != EMPTY) 
	error(TYERR);
    nptr->sc = BLABEL;
    nptr->dsp = backdef();
    getsym();
    checksym(COLON);
}

int
expr(void)
{
    return(rvalue(expr0()));
}

int
expr0(void)
{
    int e;

    e=expr1();
    while(sym==COMMA) {
	getsym();e=list3(COMMA,e,rvalue(expr1()));
    }
    return e;
}

int
expr1(void)
{
    int e1,e2,t,op;
    e1=expr2();
    switch (sym) {
    case ASS:
	lcheck(e1);
	t=type;
	getsym();
	e2=rvalue(expr1());
	if(t==VOID)
	    error(TYERR);
	if(t==CHAR) {
	    type= INT;return(list3(CASS,e1,e2));
	} else if(!scalar(t)&&(car(t)==STRUCT||car(t)==UNION)) {
	    type= t;return(list4(SASS,e1,e2,size(t)));
	}
	type=t;
	return(list3(ASS,e1,e2));
    case ADD+AS: case SUB+AS: case MUL+AS: case DIV+AS: case MOD+AS:
    case RSHIFT+AS: case LSHIFT+AS: case BAND+AS: case EOR+AS: case BOR+AS:
	op = sym-AS;
	lcheck(e1);
	t=type;
	getsym();
	e2=rvalue(expr1());
	if(!integral(type)) error(TYERR);
	if((t==UNSIGNED||type==UNSIGNED)&&
	    (op==MUL||op==DIV||op==MOD||op==RSHIFT||op==LSHIFT))
	    op=op+US;
	if(t==CHAR) {	
	    type= INT;
	    return(list4(CASSOP,e1,e2,op));
	}
	type=t;
	if(integral(t)) return(list4(ASSOP,e1,e2,op));
	if((op!=ADD&&op!=SUB)||car(t)!=POINTER) error(TYERR);
	e2=binop(MUL,e2,list2(CONST,size(cadr(t))),INT,UNSIGNED);
	type=t;
	return list4(ASSOP,e1,e2,op);
    default:
	return(e1);
    }
}

int
expr2(void)
{
    int e1,e2,e3,t;

    e1=expr3();
    if(sym==COND) {	
	e1=rvalue(e1);
	getsym();
	e2=rvalue(expr2());
	t=type;
	checksym(COLON);
	e3=rvalue(expr2());
	if(car(e1)==CONST) {
	    if(cadr(e1)) {
		type=t;return e2;
	    } else 
		return e3;
	}
	if(type==INT||(t!=INT&&type==UNSIGNED)) 
	    type=t;
	return(list4(COND,e1,e2,e3));
    }
    return(e1);
}

int
expr3(void)
{
    int e;

    e=expr4();
    while(sym==LOR) {	
	    e=rvalue(e);
	    getsym();
	    e=list3(LOR,e,rvalue(expr4()));
	    type= INT;
    }
    return(e);
}

int
expr4(void)
{
    int e;

    e=expr5();
    while(sym==LAND) {	
	e=rvalue(e);
	getsym();
	e=list3(LAND,e,rvalue(expr5()));
	type= INT;
    }
    return(e);
}

int
expr5(void)
{
    int e1,e2,t;

    e1=expr6();
    while(sym==BOR) {	
	e1=rvalue(e1);
	t=type;
	getsym();
	e2=rvalue(expr6());
	e1=binop(BOR,e1,e2,t,type);
    }
    return(e1);
}

int
expr6(void)
{
    int e1,e2,t;

    e1=expr7();
    while(sym==EOR) {	
	e1=rvalue(e1);
	t=type;
	getsym();
	e2=rvalue(expr7());
	e1=binop(EOR,e1,e2,t,type);
    }
    return(e1);
}

int
expr7(void)
{
    int e1,e2,t;

    e1=expr8();
    while(sym==BAND) {	
	e1=rvalue(e1);
	t=type;
	getsym();
	e2=rvalue(expr8());
	e1=binop(BAND,e1,e2,t,type);
    }
    return(e1);
}

int
expr8(void)
{
    int e,op;

    e=expr9();
    while((op=sym)==EQ||op==NEQ) {	
	e=rvalue(e);
	getsym();
	e=list3(op,e,rvalue(expr9()));
	type= INT;
    }
    return e;
}

int
expr9(void)
{
    int e1,e2,t,op;

    e1=expr10();
    while((op=sym)==GT||op==GE||op==LT||op==LE) {	
	e1=rvalue(e1);
	t=type;
	getsym();
	e2=rvalue(expr10());
	if(t==INT&&type==INT) 
	    e1=list3(op,e1,e2);
	else 
	    e1=list3(op+US,e1,e2);
	type= INT;
    }
    return e1;
}

int
expr10(void)
{
    int e1,e2,t,op;

    e1=expr11();
    while((op=sym)==RSHIFT||op==LSHIFT) {	
	e1=rvalue(e1);
	t=type;
	getsym();
	e2=rvalue(expr11());
	e1=binop(op,e1,e2,t,type);
    }
    return e1;
}

int
expr11(void)
{
    int e1,e2,t,op;

    e1=expr12();
    while((op=sym)==ADD||op==SUB) {	
	e1=rvalue(e1);
	t=type;
	getsym();
	e2=rvalue(expr12());
	e1=binop(op,e1,e2,t,type);
    }
    return e1;
}

int
expr12(void)
{
    int e1,e2,t,op;

    e1=expr13();
    while((op=sym)==MUL||op==DIV||op==MOD) {	
	e1=rvalue(e1);
	t=type;
	getsym();
	e2=rvalue(expr13());
	e1=binop(op,e1,e2,t,type);
    }
    return e1;
}

int
expr13(void)
{
    int e,op;

    switch (op = sym) {
	case INC: case DEC:
	getsym();
	lcheck(e=expr13());
	if(type==CHAR) {	
	    type= INT;
	    return(list2(op==INC?CPREINC:CPREDEC,e));
	}
	if(integral(type))
	    return(list3(PREINC,e,op==INC?1:-1));
	if(car(type)!=POINTER) 
	    error(TYERR);
	return(list3(PREINC,e,
	    op==INC?size(cadr(type)):-size(cadr(type)) ));
    case MUL:
	getsym();
	e=rvalue(expr13());
	return(indop(e));
    case BAND:
	getsym();
	switch(car(e=expr13())) {
	case INDIRECT:
	    e=cadr(e);
	    break;
	case GVAR:
	case LVAR:
	    e=list2(ADDRESS,e);
	    break;
	case FNAME:
	    return e;
	default:error(LVERR);
	}
	type=list2(POINTER,type);
	return e;
    case SUB:
	getsym();
	e=rvalue(expr13());
	if(!integral(type)) 
	    error(TYERR);
	return(car(e)==CONST?list2(CONST,-cadr(e)):list2(MINUS,e));
    case BNOT:
	getsym();
	e=rvalue(expr13());
	if(!integral(type)) 
	    error(TYERR);
	return(car(e)==CONST?list2(CONST,~cadr(e)):list2(BNOT,e));
    case LNOT:
	getsym();
	e=rvalue(expr13());
	if(!scalar(type)) 
	    error(TYERR);
	return(car(e)==CONST?list2(CONST,!cadr(e)):list2(LNOT,e));
    case SIZEOF:
	if(getsym()==LPAR) {
	    if(typeid(getsym())) {	
		e=list2(CONST,size(typename()));
		type=INT;
		checksym(RPAR);
		return e;
	    } else {	
		e=expr0();
		checksym(RPAR);
		expr16(e);
		if(sym==INC||sym==DEC) {	
		    getsym();
		    if(type==CHAR) type=INT;
		    else if(!scalar(type))
			error(TYERR);
		}
	    }
	} else 
	    expr13();
	e=list2(CONST,size(type));
	type=INT;
	return e;
    }
    e=expr14();
    if((op=sym)==INC||op==DEC) {	
	lcheck(e);
	getsym();
	if(type==CHAR) {	
	    type= INT;
	    return(list2(op==INC?CPOSTINC:CPOSTDEC,e));
	}
	if(integral(type))
	    return(list3(POSTINC,e,op==INC?1:-1));
	if(car(type)!=POINTER) 
	    error(TYERR);
	return (list3(POSTINC,e,
	    op == INC ? size(cadr(type)): -size(cadr(type)) ));
    }
    return e;
}

int
expr14(void)
{
    int e1,t;

    switch(sym) {
    case IDENT:
	switch(nptr->sc) {
	case GVAR:
	    e1=list3(GVAR,nptr->dsp,(int)nptr->nm);
	    type=nptr->ty;
	    getsym();
	    break;
	case LVAR:
	    e1=list2(LVAR,nptr->dsp);
	    type=nptr->ty;
	    getsym();
	    break;
	case REGISTER:
	    e1=list2(REGISTER,nptr->dsp);
	    type=nptr->ty;
	    getsym();
	    break;
	case FMACRO:
	    fmacro();
	    getsym();
	    return expr();
	case FLABEL: case BLABEL:
	case FUNCTION: case CODE:
	    e1=list2(FNAME,(int)nptr);
	    type=list3(nptr->sc,car(nptr->ty),cadr(nptr->ty));
	    getsym();
	    break;
	case EMPTY:
	    if(getsym()==LPAR) {	
		nptr->sc = FUNCTION;
		nptr->ty= glist2(INT,0);
		type= list3(FUNCTION,INT,0);
		e1=expr15(list2(FNAME,(int)nptr));
		break;
	    } else {
		e1=list2(FNAME,(int)nptr);
		type=list3(nptr->sc,nptr->ty,0);
		break;
	    }
	default:error(UDERR);
	}
	break;
    case STRING:
	e1=list3(STRING,(int)sptr,symval);
	type=list3(ARRAY,CHAR,symval);
	getsym();
	break;
    case CONST:
	type= INT;
	e1=list2(CONST,symval);
	getsym();
	break;
    case RETURN:
	if (fnptr->sc != FUNCTION) {
	    error(STERR);
	}
	type=list2(POINTER,CODE);
	e1=list2(RETURN,(int)fnptr);
	getsym();
	break;
    case DEFINED:
	getsym();
	t = mode; mode = IFDEF;
	checksym(LPAR);
	mode = t;
	type= INT;
	e1=list2(CONST,symval);
	getsym();
	checksym(RPAR);
	break;
    case ENVIRONMENT:
	type=list2(POINTER,VOID);
	e1=list2(ENVIRONMENT,0);
	getsym();
	break;
    case LPAR:
	if(typeid(getsym())) {	
	    t=typename();
	    checksym(RPAR);
	    e1=expr13();
	    type=t;
	    return e1;
	}
	e1=expr0();
	checksym(RPAR);
	break;
    default:error(EXERR);
    }
    return expr16(e1);
}

int
expr16(int e1)
{
    int e2,t;

    while(1) {
	if(sym==LBRA) {	
	    e1=rvalue(e1);
	    t=type;
	    getsym();
	    e2=rvalue(expr0());
	    checksym(RBRA);
	    e1=binop(ADD,e1,e2,t,type);
	    e1=indop(e1);
	} else if(sym==LPAR) e1=expr15(e1);
	else if(sym==PERIOD) e1=strop(e1);
	else if(sym==ARROW) e1=strop(indop(rvalue(e1)));
	else break;
    }
    if(car(e1)==FNAME) type=list2(POINTER,type);
    return e1;
}

int
rvalue(int e)
{
    int t;
    if(type==CHAR) {	
	type= INT;
	switch(car(e)) {
	case GVAR:
	    return(list3(CRGVAR,cadr(e),caddr(e)));
	case LVAR:
	    return(list2(CRLVAR,cadr(e)));
	case INDIRECT:
	    return(list2(CRINDIRECT,cadr(e)));
	default:return(e);
	}
    }
    if(!integral(type)&&type!=VOID) {
	if(type==CODE) { return(e);
	} else if((t=car(type))==ARRAY) {	
	    type=list2(POINTER,cadr(type));
	    if(car(e)==INDIRECT) return cadr(e);
	    return list2(ADDRESS,e);
	} else if(t==STRUCT || t==UNION) { return e;
	} else if(t!=POINTER) error(TYERR);
    }
    switch(car(e)) {
    case GVAR:
	return(list3(RGVAR,cadr(e),caddr(e)));
    case LVAR:
	return(list2(RLVAR,cadr(e)));
    case INDIRECT:
	return(list2(RINDIRECT,cadr(e)));
    default:return(e);
    }
}

void
lcheck(int e)
{
    int t;
    if(!scalar(type)||
	(car(e)!=GVAR&&car(e)!=LVAR&&car(e)!=INDIRECT&&car(e)!=REGISTER))
	if ((t=car(type))<0 && t!=STRUCT && t!=UNION)
	    error(LVERR);
}

int
indop(int e)
{
    if(type!=INT&&type!=UNSIGNED) {
	if(car(type)==POINTER) 
	    type=cadr(type);
	else error(TYERR);
    } else 
	type= CHAR;
    if(car(e)==ADDRESS) 
	return(cadr(e));
    return(list2(INDIRECT,e));
}

int
strop(int e)
{
    getsym();
    if (sym!=IDENT||nptr->sc!=FIELD) error(TYERR);
    if (integral(type)||(car(type)!=STRUCT && car(type)!=UNION))
	e=rvalue(e);
    type = nptr->ty;
    switch(car(e)) {
    case GVAR:
	e=list2(INDIRECT,list3(ADD,e,list2(CONST,nptr->dsp)));
	break; 
    case LVAR:
	e=list2(car(e),cadr(e) + nptr->dsp);
	break;
    case INDIRECT:
	if(!nptr->dsp) break;
	e=list2(INDIRECT,list3(ADD,cadr(e),list2(CONST,nptr->dsp)));
	break;
    default:
	e=list2(INDIRECT,list3(ADD,e,list2(CONST,nptr->dsp)));
    }
    getsym();
    return e;
}

int
binop(int op, int e1, int e2, int t1, int t2)
{
    int e;

    if(car(e1)==CONST&&car(e2)==CONST) {	
	e1=cadr(e1);
	e2=cadr(e2);
	type= INT;
	switch(op) {
	case BOR:
	    e=e1|e2;break;
	case EOR:
	    e=e1^e2;break;
	case BAND:
	    e=e1&e2;break;
	case ADD:
	    if(integral(t1)) {	
		if(integral(t2)) {
			e=e1+e2;
		} else {	
			if(car(t2)!=POINTER) error(TYERR);
			e=size(cadr(t2))*e1+e2;
			type=t2;
		}
	    } else {	
		if(car(t1)!=POINTER) error(TYERR);
		e=e1+size(cadr(t1))*e2;
		type=t1;
	    }
	    break;
	case SUB:
	    if(integral(t1)) {
		e=e1-e2;
	    } else {	
		if(car(t1)!=POINTER) error(TYERR);
		e=e1-size(cadr(t1))*e2;
		type=t1;
	    }
	    break;
	case MUL:
	    e=e1*e2;break;
	case DIV:
	    if(!e2) error(EXERR);e=e1/e2;break;
	case MOD:
	    if(!e2) error(EXERR);e=e1%e2;break;
	case RSHIFT:
	    e=e1>>e2;break;
	case LSHIFT:
	    e=e1<<e2;
	}
	return list2(CONST,e);
    }
    if((op==ADD||op==MUL||op==BOR||op==EOR||op==BAND)&&
	(car(e1)==CONST||(car(e2)!=CONST&&
	(car(e1)==RGVAR||car(e1)==RLVAR)))) {
	e=e1;e1=e2;e2=e;e=t1;t1=t2;t2=e;
    }
    if(op==ADD) {	
	if(integral(t1)) {	
	    if(integral(t2)) {	
		if(t1==INT) type=t2;else type=t1;
		return(list3(ADD,e1,e2));
	    }
	    if(car(t2)!=POINTER) error(TYERR);
	    e=binop(MUL,e1,list2(CONST,size(cadr(t2))),t1,INT);
	    type=t2;
	    return(list3(ADD,e,e2));
	}
	if(car(t1)!=POINTER||!integral(t2)) error(TYERR);
	e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT);
	type=t1;
	if(car(e1)==ADDRESS&&car(e)==CONST&&car(cadr(e1))!=GVAR)
	    return(list2(ADDRESS,list2(car(cadr(e1)),
		cadr(cadr(e1))+cadr(e))));
	return(list3(ADD,e1,e));
    }
    if(op==SUB) {	
	if(integral(t1)) {	
	    if(!integral(t2)) error(TYERR);
	    if(t1==INT) type=t2;else type=t1;
	    return(list3(SUB,e1,e2));
	}
	if(car(t1)!=POINTER) error(TYERR);
	if(integral(t2)) {	
	    e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT);
	    type=t1;
	    return(list3(SUB,e1,e));
	}
	if(car(t2)!=POINTER)
	    error(TYERR);
	compatible(t1,t2);
	e=list3(SUB,e1,e2);
	e=binop(DIV,e,list2(CONST,size(cadr(t1))),UNSIGNED,INT);
	type= INT;
	return e;
    }
    if(!integral(t1)||!integral(t2)) error(TYERR);
    if(t1==INT) type=t2;else type=t1;
    if((op==MUL||op==DIV)&&car(e2)==CONST&&cadr(e2)==1) return e1;
    if(op==BOR||op==EOR||op==BAND) return(list3(op,e1,e2));
    return(list3(type==UNSIGNED?op+US:op,e1,e2));
}

int
expr15(int e1)
{
    int t,arglist,e;

    t=type;
    if(integral(t)|| (car(t)!=FUNCTION && car(t)!=CODE))
	error(TYERR);
    getsym();
    arglist=0;
    while(sym!=RPAR) {	
	e=rvalue(expr1());
	arglist=list3(e,arglist,type);
	if(sym!=COMMA) break;
	getsym();
    }
    checksym(RPAR);
    if(car(t)!=CODE) {
	t=cadr(t);
	if(t==CHAR) type= INT;else type=t;
    }
    return list3(FUNCTION,e1,arglist);
}

int
typeid(int s)
{
    return (integral(s) || s==CODE || s==SHORT || s==LONG || s==STRUCT || s==UNION ||
    (s==IDENT && nptr->sc==TYPE));
}

int
typename(void)
{
    int t;

    type=t=typespec();
    ndecl0();
    reverse(t);
    return type;
}

int
ndecl0(void)
{
    if(sym==MUL) {	
	getsym();
	return type=list2(POINTER,ndecl0());
    }
    return ndecl1();
}

int
ndecl1(void)
{
    int i,t,arglist;

    if(sym==LPAR) {
	if(getsym()==RPAR) {
	    type=list3(FUNCTION,type,0); getsym();
	} else {	
	    ndecl0();
	    checksym(RPAR);
	}
    }
    while(1) {
	if(sym==LBRA) {	
	    getsym();
	    t=type;
	    i=cexpr(expr());
	    checksym(RBRA);
	    type=list3(ARRAY,t,i);
	} else if(sym==LPAR) {	
	    t = type;
	    getsym();
	    arglist=0;
	    while(sym!=RPAR) {	
		ndecl0();
		arglist=list2(type,arglist);
		if(sym!=COMMA) break;
		getsym();
	    }
	    checksym(RPAR);
	    type=list3(FUNCTION,t,arglist);
	}
	else return type;
    }
}

int
cexpr(int e)
{       
    if (car(e) != CONST) error(CNERR);
    return (cadr(e));
}

int in_comment = 0;

int
getsym(void)
{
    NMTBL *nptr0,*nptr1,*nptrm;
    int i,macro_type;
    char c,*macro;

    if (alpha(skipspc())) {	
	i = hash = 0;
	name = namebuf;
	while (alpha(ch) || digit(ch)) {	
	    if (i < LBUFSIZE-1) 
		hash=(7*hash ^ (name[i++]=ch));
	    getch();
	}
	name[i++] = '\0'; 

	nptrm=msearch(name);
	if (mode==MDECL) {
	    nptr = nptrm;
	    return (sym==MACRO);
	}
	if (mode==IFDEF) {
	    if (nptrm->sc == MACRO||nptrm->sc==FMACRO) {	
		return (symval=1);
	    } else {
		return (symval=0);
	    }
	}
	if (nptrm->sc!=EMPTY && !recursive_macro((char *)car((nptrm->dsp)))) {
	    if (nptrm->sc == FMACRO) {
		nptr = nptrm;
		sym = IDENT;
		return sym;
	    }
	    if ((macro_type = nptrm->ty)!=0) {
		macro = (char *)(car(nptrm->dsp));
		while (!(macro_type<=0||cadddr(macro_type)==mflag)) {
		    macro = (char *)car(caddr(macro_type));
		    macro_type = cadr(macro_type);
		}
		if (macro_type) {
/* fprintf(stderr,"%d: macro %s save: ch=%c chptr=%s\n",lineno,name,ch,chptr); */
		    chptrsave = list4((int)chptr,chptrsave,ch,
			list2((int)nptrm,(int)macro));
		    if (macro_type!=-1) {
			mflag--;
		    }
		    chptr = macro;
		    getch();
		    sym =  getsym();
		    if (macro_type!=-1) {
			mflag++;
		    }
		    return sym;
		}
	    }	/* else diffrent depth level localmacro leave it alone */
	}

	nptr0 = gsearch();
	if (nptr0->sc == RESERVE) return sym = nptr0->dsp;
	sym = IDENT;
	gnptr=nptr=nptr0;
	if (mode==ADECL && nptr0->sc ==TYPE) return sym;
	if (mode==GDECL || mode==GSDECL || mode==GUDECL ||
	    mode==GTDECL || mode==TOP) {
	    return sym;
	}
	nptr1=lsearch(nptr0->nm);
	if (mode==STAT) {
	    if (nptr1->sc == EMPTY) return sym;
	}
	nptr=nptr1;
	return sym;
    } else if (digit(ch)) {	
	symval=0;
	if (ch == '0') {	
	    if (getch() == 'x' || ch == 'X') {
		while(1) {
		    if(digit(getch()))
			symval=symval*16+ch-'0';
		    else if('a'<=ch&&ch<='f')
			symval=symval*16+ch-'a'+10;
		    else if('A'<=ch&&ch<='F')
			symval=symval*16+ch-'A'+10;
		    else break;
		}
	    } else {
		while (digit(ch)) {
		    symval=symval*8+ch-'0';getch();
		}
	    }
	} else {
	    while(digit(ch)) {
		symval=symval*10+ch-'0';getch();
	    }
	}
	return sym=CONST;
    } else if(ch=='\'') {	
	getch();
	symval=escape();
	if(ch!='\'') error(CHERR);
	getch();
	return sym=CONST;
    } else if(ch=='"') {	
	getstring();
	return sym= STRING;
    }
    c=ch;
    getch();
    switch(c) {
    case '*':
	return postequ(MUL,MUL+AS);
    case '&':
	if(ch=='&') {getch();return sym=LAND;}
	return postequ(BAND,BAND+AS);
    case '-':
	if(ch=='>') {getch();return sym=ARROW;}
	if(ch=='-') {getch();return sym=DEC;}
	return postequ(SUB,SUB+AS);
    case '!':
	return postequ(LNOT,NEQ);
    case '~':
	return sym=BNOT;
    case '+':
	if(ch=='+') {getch();return sym=INC;}
	return postequ(ADD,ADD+AS);
    case '%':
	return postequ(MOD,MOD+AS);
    case '^':
	return postequ(EOR,EOR+AS);
    case '|':
	if(ch=='|') {getch();return sym=LOR;}
	return postequ(BOR,BOR+AS);
    case '=':
	return postequ(ASS,EQ);
    case '>':
	if(ch=='>') {getch();return postequ(RSHIFT,RSHIFT+AS);}
	return postequ(GT,GE);
    case '<':
	if(ch=='<') {getch();return postequ(LSHIFT,LSHIFT+AS);}
	return postequ(LT,LE);
    case '(':
	return sym=LPAR;
    case ')':
	return sym=RPAR;
    case '[':
	return sym=LBRA;
    case ']':
	return sym=RBRA;
    case '{':
	return sym=LC;
    case '}':
	return sym=RC;
    case ',':
	return sym=COMMA;
    case ';':
	return sym=SM;
    case ':':
	return sym=COLON;
    case '?':
	return sym=COND;
    case '.':
	if(ch=='.') {
	    getch();
	    if (ch=='.') {
		getch();
		return sym=DOTS;
	    }
	    error(CHERR);
	    return getsym();
	} else
	    return sym=PERIOD;
    case '/':
	if(ch!='*') return postequ(DIV,DIV+AS);
	in_comment = 1;
	getch();
	while(ch=='*'?getch()!='/':getch());
	in_comment = 0;
	getch();
	return getsym();
    default:
	error(CHERR);
	return getsym();
    }
}

int
postequ(int s1, int s2)
{
    if(ch=='=') {getch();return sym=s2;}
    return sym=s1;
}

int
alpha(char c)
{
    return(('a'<=c&&c<='z')||('A'<=c&&c<='Z')||c=='_');
}

int
digit(char c)
{
    return('0'<=c&&c<='9');
}


NMTBL *
gsearch(void)
{
    NMTBL *nptr,*iptr;

    iptr=nptr= &ntable[hash % GSYMS];
    while(nptr->sc!=0 && neqname(nptr->nm,name)) {	
	if (++nptr== &ntable[GSYMS]) 
	    nptr=ntable;
	if (nptr==iptr) error(GSERR);
    }
    if (nptr->sc == 0) {
	copy(nptr,name);
	nptr->sc=EMPTY;
    }
    return nptr;
}

NMTBL *
lsearch(char *name)
{
    NMTBL *nptr,*iptr;

    iptr=nptr= &ntable[hash%LSYMS+GSYMS];
    while(nptr->sc!=0 && neqname(nptr->nm,name)) {	
	if (++nptr== &ntable[LSYMS+GSYMS]) 
	    nptr= &ntable[GSYMS];
	if (nptr==iptr) error(LSERR);
    }
    if (nptr->sc == 0) {
	nptr->nm=name;  /* already saved in gsearch */
	nptr->sc=EMPTY;
	nptr->dsp=0;
    }
    return nptr;
}

NMTBL *
msearch(char *name)
{
    NMTBL *nptr,*iptr;

    iptr=nptr= &mtable[hash%MSYMS];
    while(nptr->sc!=0 && neqname(nptr->nm,name)) {	
	if (++nptr== &mtable[MSYMS]) 
	    nptr= &mtable[0];
	if (nptr==iptr) error(MSERR);
    }
    if (nptr->sc == 0) {
	copy(nptr,name);
	nptr->sc=EMPTY;
	nptr->dsp=0;
	nptr->ty=0;
    }
    return nptr;
}

NMTBL *
msearch0(char *name)
{
    NMTBL *nptr,*iptr;
    int hash,i;

    i = 0; hash = 0;
    while((name[i])) {
	hash=((7*hash) ^ name[i++]);
    }
    iptr=nptr= &mtable[hash%MSYMS];
    while(nptr->sc!=0 && neqname(nptr->nm,name)) {
	if (++nptr== &mtable[MSYMS]) 
	    nptr= &mtable[0];
	if (nptr==iptr) error(MSERR);
    }
    if (nptr->sc == 0) {
	copy(nptr,name);
	nptr->sc=EMPTY;
	nptr->dsp=0;
	nptr->ty=0;
    }
    return nptr;
}


void
copy(NMTBL *nptr, char *s)
{
    nptr->nm = cheapp;
    while((*cheapp++ = *s++));
}

int
neqname(char *p,char *q)
{
    if (!p)
	return 0;
    while(*p && *p!='.') 
	    if(*p++ != *q++) return 1;
    return (*q!=0);
}

void
getstring(void)
{
    getch();
    symval = 0;
    sptr = cheapp;
    while (ch != '"') {	
	*cheapp++ = escape();
	symval++;
	if (cheapp >= cheap+CHEAPSIZE) error(STRERR);
    }
    getch();
    *cheapp++ = '\0';
    symval++;
}

int
skipspc(void)
{
    while(ch=='\t'||ch=='\n'||ch==' '||ch=='\r') 
	getch();
    return ch;
}

int
getch(void)
{
    NMTBL *nptr0;
    int sargs;
    if(*chptr) return ch = *chptr++;

    while (chptrsave) {
	nptr0=(NMTBL *)car(cadddr(chptrsave));
	if (nptr0->sc==FMACRO) {
	    sargs = cadr(nptr0->dsp);
	    while(sargs) {
		local_undef(car(sargs));
		sargs = cadr(sargs);
	    }
	    mflag--;
	} 
	chptr=(char *)car(chptrsave);
	ch=caddr(chptrsave);
	chptrsave=cadr(chptrsave);
/* fprintf(stderr,"macro end: ch=%c chptr=%s\n",ch,chptr); */
	if (ch)
	    return ch;
    }
    getline();
    return getch();
}

char 
escape(void)
{
    char c;
    if ((c=ch) == '\\') {	
	if (digit(c=getch())) {	
	    c = ch-'0';
	    if (digit(getch())) {	
		c = c*8+ch-'0';
		if (digit(getch())) {
		    c=c*8+ch-'0';getch();
		}
	    }
	    return c;
	}
	getch();
	switch(c) {
	case 'n':
	    return '\n';
	case 't':
	    return '\t';
	case 'b':
	    return '\b';
	case 'r':
	    return '\r';
	case 'f':
	    return '\f';
	case '\n':
	    return escape();
	default:
	    return c;
	}
    }
    if (c == '\n') error(EXERR);
    getch();
    return c;
}

FILE *
getfname(void)
{
    int i;
    char *s,name[LBUFSIZE];
    FILE *fp;

    getch();
    if(skipspc()!='"') error(INCERR);
    for(i=0;(getch()!='"' && ch!='\n');) {
	if(i<LBUFSIZE-1) name[i++]=ch;
    }
    if(ch=='\n') error(INCERR);
    name[i]=0;
    fp = fopen(name,"r") ;
    s = name;
    (filep+1)->name0 = cheapp;
    while((*cheapp++ = *s++));
    return ( (filep+1)->fcb = fp );
}

static int macro_if_depth ;
static int macro_if_current ;
static int macro_if_skip ;

void
getline(void)
{
    int i;
    int c;

    do {
	lineno++;
	glineno++;
	chptr=linebuf;
	i=0;
	while ((*chptr++ = c = getc(filep->fcb)) != '\n') {
	    if (++i > LBUFSIZE-2) error(LNERR);
	    if (c==EOF) {	
		    error(EOFERR);
		    --chptr;
	    }
	}
	*chptr = '\0';
	if (lsrc && !asmf && !macro_if_skip) gen_comment(linebuf);
	if (*(chptr = linebuf) == '#' && !in_comment) {	
	    macro_processing();
	}
    } while(macro_if_skip || linebuf[0] == '#');
}

void
macro_processing()
{
    int i;
    int c;
    int mode_save;

    ++chptr;
    if (macroeq("ifdef") || macroeq("ifndef")) {
	c = (chptr[-4]=='n');
	macro_if_current++;
	if (!macro_if_skip) {
	    mode_save = mode; mode = IFDEF;
	    ch= *chptr;
	    i = getsym();
	    mode = mode_save;
	    macro_if_depth = macro_if_current;
	    macro_if_skip = (!i)^c;
	}
	return;
    } else if (macroeq("if")) {	
	macro_if_current++;
	if (!macro_if_skip) {
            for(c=0;chptr[c];c++);
            chptr[c] = ';';  /* this can't happen in macro expression */
	    ch= *chptr;
	    getsym();
	    i=cexpr(expr());
	    macro_if_depth = macro_if_current;
	    macro_if_skip = !i;
	}
	return;
    } else if (macroeq("else")) {	
	if (macro_if_current==0) {
	    error(MCERR); /* extra #else */
	    return;
	}
	if (macro_if_current == macro_if_depth) 
	    macro_if_skip = !macro_if_skip;
	return;
    } else if (macroeq("endif")) {	
	if (macro_if_current == macro_if_depth) {
	    macro_if_skip = 0;
	    macro_if_depth = --macro_if_current;
	} else {
	    if (macro_if_current<=0) {
		error(MCERR); /* extra #if */
		return;
	    }
	    macro_if_current--;
	}
	return;
    }
    if (macro_if_skip) return;
    if (macroeq("define")) {	
	macro_define0();
	*(chptr = linebuf) = '\0';
    } else if (macroeq("undef")) {	
	i=mode;
	mode=LDECL;
	ch= *chptr;
	if (getsym() == IDENT) {	
	    if (nptr->sc == MACRO) {	
	        nptr->sc = EMPTY;
	    } else if (nptr->sc == FMACRO) {	
	        nptr->sc = EMPTY;
		/* we cannot reclaim it's arg */
	    } else error(MCERR);
	}
	mode=i;
    } else if (macroeq("include")) {	
	if(filep+1 >= filestack + FILES) error(FILERR);
	if ( ((filep+1)->fcb=getfname()) == NULL) error(FILERR);
	(filep+1)->ln=lineno;
	lineno=0;
	++filep;
	*(chptr = linebuf) = '\0';
    } else if (macroeq("asm")) {	
	if (asmf) error(MCERR);
	asmf = 1;
	getline();
	while (asmf) {	
	    gen_source(linebuf);
	    getline();
	}
    } else if (macroeq("endasm")) {	
	if (!asmf) error(MCERR);
	asmf = 0;
    } else if (macroeq(" "))
	getline();
    else error(MCERR);
}

int
macroeq(char *s)
{
    char *p;

    for (p = chptr; *s;) if (*s++ != *p++) return 0;
    chptr = p;
    return 1;
}

void
macro_define(char *macro)
{
    char *chptr_save;
    int chsave;
    chptr_save = chptr;
    chsave = ch;
    chptr = macro;
    ch= *chptr++;
    macro_define0();
    chptr = chptr_save;
    ch = chsave;
}

void
macro_define0()
{
    int i,args,c;
    i=mode;
    mode=MDECL;
    ch= *chptr;
    getsym();
/* fprintf(stderr,"macro def: %s\n",name); */
    if (nptr->sc != EMPTY) { /* override exisiting macro */
    }
    args = 0;
    if (ch=='(') {
	nptr->sc = FMACRO;
	args = macro_args();
    } else {
	nptr->sc = MACRO;
       /* -1 means gloabl macro, 0 means no macro, >0 means local macro */
	nptr->ty = -1; 
    }
    nptr->dsp = glist2((int)cheapp,args);
    while ((*cheapp++ = c = *chptr++)
	&& c != '\n');
    *cheapp++ = '\0';
    if (cheapp >= cheap+CHEAPSIZE) /* too late? */
	error(STRERR);
    mode=i;
}

int 
macro_args()
{
    int c;
    int in_quote = 0;
    int in_wquote = 0;
    int plevel = 0;
    int args = glist2((int)cheapp,0);
    for(;;) {
        *cheapp++ = c = *chptr++;
	if (!c)  {
	    chptr--;
	    error(MCERR);
	    return reverse0(args);
	}
	if (in_quote) {
	    if (c=='\\') {
		if (*chptr != '\n') {
		    *cheapp++ = *chptr++;
		} else {
		    getline();
		}
	    } else if (c=='\'') {
		in_quote = 0;
	    }
	} else if (in_wquote) {
	    if (c=='\\') {
		if (*chptr !='\n') {
		    *cheapp++ = *chptr++;
		} else {
		    *cheapp = '\n';
		    getline();
		}
	    } else if (c=='"') {
		in_wquote = 0;
	    }
	} else if (c=='"') {
	    in_wquote = 1;
	} else if (c=='\'') {
	    in_quote = 1;
	} if (plevel==0) {
	    if (c==',') {
		cheapp[-1] = 0;
		args = glist2((int)cheapp,args);
	    } else if (c==')') {
		cheapp[-1] = 0;
		break;
	    } else if (c=='(') {
		plevel++;
	    } else if (c=='\\') {
		if (*chptr=='\n') {
		    cheapp--;
		    getline();
		}
	    } else if (c==' '||c=='\t') {
		cheapp--;
	    } else if (c=='\n') {
		cheapp--;
		getline();
	    }
	} else if (c==')') {
	    plevel--;
	} else if (c=='\n') {
	    cheapp--;
	    getline();
	}
    }
    ch = *chptr;
    if (ch) chptr++;
    return reverse0(args);
}

void 
fmacro()
{
    int args,values;
    args = cadr(nptr->dsp);
    values = macro_args();
    mflag++;
    while(args) {
	local_define(car(args),car(values));
	args = cadr(args);
	values = cadr(values);
    }
/* fprintf(stderr,"%d: fmacro %s save: ch=%c chptr=%s\n",lineno,nptr->nm,ch,chptr); */
    chptrsave = list4((int)chptr,chptrsave,ch,list2((int)nptr,car(nptr->dsp)));
    chptr = (char *)car(nptr->dsp);
    getch();
}

int
recursive_macro(char *macro)
{
    int save = chptrsave;
    while(save) {
        if (cadr(cadddr(save))==(int)macro) 
	    return 1;
	save = cadr(save);
    }
    return 0;
}

void
local_define(char *macro,char *value)
{
    NMTBL *nptr0;
    nptr0 = msearch0(macro);
    nptr0->ty=list4(nptr0->sc,nptr0->ty,nptr0->dsp,mflag); 
    nptr0->sc=MACRO; 
    nptr0->dsp=list2((int)value,0); 
}

void
local_undef(char *macro)
{
    NMTBL *nptr0;
    int save;
    nptr0 = msearch0(macro);
    save = nptr0->ty;
    nptr0->sc=car(save); 
    nptr0->dsp=caddr(save); 
    nptr0->ty=cadr(save); 
}

int
list2(int e1, int e2)
{
    int e;

    e=getfree(2);
    heap[e]=e1;
    heap[e+1]=e2;
    return e;
}

int
list3(int e1, int e2, int e3)
{
    int e;

    e=getfree(3);
    heap[e]=e1;
    heap[e+1]=e2;
    heap[e+2]=e3;
    return e;
}

int
list4(int e1, int e2, int e3, int e4)
{
    int e;

    e=getfree(4);
    heap[e]=e1;
    heap[e+1]=e2;
    heap[e+2]=e3;
    heap[e+3]=e4;
    return e;
}

int
getfree(int n)
{
    int e;

    switch (mode) {
	case GDECL: case GSDECL: case GUDECL: case GTDECL:
	e=gfree;
	gfree+=n;
	break;
    default:
	lfree-=n;
	e=lfree;
    }
    if(lfree<gfree) error(HPERR);
    return e;
}

int
glist2(int e1,int e2)
{
    int smode,ret;
    smode = mode;
    mode = GDECL;
    ret = list2(e1,e2);
    mode = smode;
    return ret;
}

int
rplacad(int e, int n)
{
    heap[e+1]=n;
    return e;
}

int
rplacadd(int e, int n)
{
    heap[e+2]=n;
    return e;
}


void
display_ntable(NMTBL *n, char *s)
{
    fprintf(stderr,"\n%s %0x %0x ",s,(int)n,(int)ntable); 
    fprintf(stderr,"nptr->sc %d ",n->sc); 
    fprintf(stderr,"nptr->dsp %d ",n->dsp); 
    fprintf(stderr,"nptr->ty %d ",n->ty); 
    fprintf(stderr,"nptr->nm %s\n",n->nm); 
}

/* end */