view mc-tree.c @ 856:d9dd3e6e7c5f

macro compatibility
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 22 Nov 2011 05:44:49 +0900
parents bf94c295d763
children c005a392e27e
line wrap: on
line source

/* Micro-C tree print routine */

/************************************************************************
** Copyright (C) 2006 Shinji Kono
** 連絡先: 琉球大学情報工学科 河野 真治  
** (E-Mail Address: kono@ie.u-ryukyu.ac.jp)
**
**    このソースのいかなる複写,改変,修正も許諾します。ただし、
**    その際には、誰が貢献したを示すこの部分を残すこと。
**    再配布や雑誌の付録などの問い合わせも必要ありません。
**    営利利用も上記に反しない範囲で許可します。
**    バイナリの配布の際にはversion messageを保存することを条件とします。
**    このプログラムについては特に何の保証もしない、悪しからず。
**
**    Everyone is permitted to do anything on this program 
**    including copying, modifying, improving,
**    as long as you don't try to pretend that you wrote it.
**    i.e., the above copyright notice has to appear in all copies.  
**    Binary distribution requires original version messages.
**    You don't have to ask before copying, redistribution or publishing.
**    THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
***********************************************************************/

#include <stdio.h>
#include "mc.h"
#include "mc-parse.h"
#include "mc-codegen.h"

extern void tree_print(int e);
extern void tree_parse(int e);
extern void tree_print_t(int e,int t);
extern void type_print(int type,NMTBL *n,FILE *out);
extern void type_print1(int type,NMTBL *n,FILE *out,int cont);
extern void sym_print(int type,FILE *out);
static void print_function_call(int e, FILE *out);
static void print_operator(int e, FILE *vout);
static void print_statement(int e, FILE *vout);

/* ascendant order for binary search */

typedef
struct tree_node {
    int tree_type;
    char *tree_name;
    char *tree_args;
    int tree_order;
} tree_node_type;

static int
tree_nodes(int id, char **name, char **args, int *order) {
    int found = 1;
    switch(id%SOP) {
    case DOTS: *name = "..."; *args=""; *order=-1; break;
    case LMACRO: *name = "lmacro"; *args=""; *order=-1; break;
    case FMACRO: *name = "fmacro"; *args=""; *order=-1; break;
    case KONST: *name = "const"; *args=""; *order=-1; break;
    case DEFINED: *name = "defined"; *args=""; *order=14; break;
    case ENVIRONMENT: *name = "environment"; *args=""; *order=14; break;
    case CODE: *name = "code"; *args=""; *order=-1; break;
    case C_FILE: *name = "__FILE__"; *args=""; *order=14; break;
    case C_FUNCTION: *name = "__FUNCTION__"; *args=""; *order=14; break;
    case C_LINE: *name = "__LINE__"; *args=""; *order=14; break;
    case REGISTER: *name = "register"; *args=""; *order=-1; break;
    case CAST: *name = "cast"; *args="e"; *order=14; break;
    case ASM: *name = "__asm__"; *args="eeee"; *order=-1; break;
    case ST_ASM: *name = "__asm__"; *args="eeee"; *order=-1; break;
    case VOID: *name = "void"; *args=""; *order=-1; break;
    case EXTRN: *name = "extern"; *args=""; *order=14; break;
    case EXTRN1: *name = "extern"; *args=""; *order=14; break;
    case SHORT: *name = "short"; *args=""; *order=-1; break;
    case USHORT: *name = "unsigned short"; *args=""; *order=-1; break;
    case LONG: *name = "long"; *args=""; *order=-1; break;
    case TYPE: *name = "type"; *args=""; *order=-1; break;
    case VOLATILE: *name = "volatile"; *args=""; *order=-1; break;
    case SIZEOF: *name = "sizeof"; *args="e"; *order=13; break;
    case TYPEDEF: *name = "typedef"; *args=""; *order=-1; break;
    case FLABEL: *name = "flabel"; *args=""; *order=-1; break;
    case BLABEL: *name = "blabel"; *args=""; *order=-1; break;
    case LABEL: *name = "label"; *args="e"; *order=-1; break;
    case ST_LABEL: *name = "label"; *args="e"; *order=-1; break;
    case MACRO: *name = "macro"; *args=""; *order=-1; break;
    case STRING: *name = "string"; *args=""; *order=14; break;
    case IDENT: *name = "ident"; *args=""; *order=14; break;
    case ENUM: *name = "enum"; *args=""; *order=14; break;
    case FIELD: *name = "field"; *args=""; *order=-1; break;
    case TAG: *name = "tag"; *args=""; *order=-1; break;
    case RESERVE: *name = "reserve"; *args=""; *order=-1; break;
    case ST_DEFAULT: *name = "default"; *args=""; *order=-1; break;
    case ATTRIBUTE: *name = "__attribute__"; *args=""; *order=-1; break;
    case ST_CASE: *name = "case"; *args=""; *order=-1; break;
    case ST_SWITCH: *name = "switch"; *args=""; *order=-1; break;
    case ST_WHILE: *name = "while"; *args=""; *order=-1; break;
    case ST_DO: *name = "do"; *args=""; *order=-1; break;
    case ST_FOR: *name = "for"; *args=""; *order=-1; break;
    case ELSE: *name = "else"; *args=""; *order=-1; break;
    case ST_IF: *name = "if"; *args=""; *order=-1; break;
    case CONTINUE: *name = "continue"; *args=""; *order=-1; break;
    case BREAK: *name = "break"; *args=""; *order=-1; break;
    case ST_RETURN: *name = "return"; *args="e"; *order=-1; break;
    case RETURN: *name = "return"; *args=""; *order=14; break;
    case ST_GOTO: *name = "goto"; *args=""; *order=-1; break;
    case JUMP: *name = "goto"; *args=""; *order=-1; break;
    case STATIC: *name = "static"; *args=""; *order=14; break;
    case EMPTY: *name = "empty"; *args=""; *order=-1; break;
    case FUNCTION: *name = "function"; *args="t"; *order=15; break;
    case UNION: *name = "union"; *args=""; *order=-1; break;
    case STRUCT: *name = "struct"; *args="vt"; *order=-1; break;
    case ARRAY: *name = "array"; *args="tv"; *order=16; break;
    case POINTER: *name = "*"; *args="t"; *order=-1; break;
    case UNSIGNED: *name = "unsigned"; *args=""; *order=-1; break;
    case INLINE: *name = "inline"; *args=""; *order=-1; break;
    case SIGNED: *name = "signed"; *args=""; *order=-1; break;
    case CHAR: *name = "char"; *args=""; *order=-1; break;
    case UCHAR: *name = "unsigned char"; *args=""; *order=-1; break;
    case INT: *name = "int"; *args=""; *order=-1; break;
    case FLOAT: *name = "float"; *args=""; *order=-1; break;
    case DOUBLE: *name = "double"; *args=""; *order=-1; break;
    case LONGLONG: *name = "long long"; *args=""; *order=-1; break;
    case ULONGLONG: *name = "unsigned long long"; *args=""; *order=-1; break;

    case GVAR: *name = "gvar"; *args="vs"; *order=14; break;
    case IVAR: *name = "ivar"; *args="vs"; *order=14; break;
    case RGVAR: *name = "rgvar"; *args="vs"; *order=14; break;
    case CRGVAR: *name = "crgvar"; *args="vs"; *order=14; break;
    case LVAR: *name = "lvar"; *args="v"; *order=14; break;
    case RLVAR: *name = "rlvar"; *args="v"; *order=14; break;
    case CRLVAR: *name = "crlvar"; *args="v"; *order=14; break;
    case CONST: *name = "const"; *args="v"; *order=14; break;
    case FNAME: *name = "fname"; *args="n"; *order=14; break;
    case MUL: *name = "*"; *args="e"; *order=-1; break;
    case RINDIRECT: *name = "*"; *args="e"; *order=13; break;
    case CRINDIRECT: *name = "*"; *args="e"; *order=13; break;
    case ADDRESS: *name = "&"; *args="e"; *order=13; break;
    case BAND: *name = "&"; *args="e"; *order=7; break;
    case MINUS: *name = "-"; *args="e"; *order=13; break;
    case LNOT: *name = "!"; *args="e"; *order=13; break;
    case BNOT: *name = "~"; *args="e"; *order=13; break;
    case INC: *name = "++"; *args=""; *order=13; break;
    case ALLOCA: *name = "alloca"; *args="e"; *order=13; break;
    case BUILTINP: *name = "__builtinp"; *args="e"; *order=13; break;
    case BUILTIN_EXPECT: *name = "__builtin_expect"; *args="ee"; *order=13; break;
    case BUILTIN_FABSF: *name = "__builtin_fabsf"; *args="e"; *order=13; break;
    case BUILTIN_FABS: *name = "__builtin_fbas"; *args="e"; *order=13; break;
    case BUILTIN_FABSL: *name = "__builtin_fbasl"; *args="e"; *order=13; break;
    case BUILTIN_INFF: *name = "__builtin_inff"; *args=""; *order=13; break;
    case BUILTIN_INF: *name = "__builtin_inf"; *args=""; *order=13; break;
    case BUILTIN_INFL: *name = "__builtin_infl"; *args=""; *order=13; break;
    case POSTINC: *name = "++"; *args="ee"; *order=13; break;
    case BPOSTINC: *name = "++"; *args="ee"; *order=13; break;
    case PREINC: *name = "++"; *args="ee"; *order=13; break;
    case CPOSTINC: *name = "++"; *args="ee"; *order=13; break;
    case CPREINC: *name = "++"; *args="ee"; *order=13; break;
    case DEC: *name = "--"; *args="e"; *order=13; break;
    case DIV: *name = "/"; *args="ee"; *order=12; break;
    case UDIV: *name = "/"; *args="ee"; *order=12; break;

    case UMUL: *name = "*"; *args="ee"; *order=12; break;
    case MOD: *name = "%"; *args="ee"; *order=12; break;
    case UMOD: *name = "%"; *args="ee"; *order=12; break;
    case ADD: *name = "+"; *args="ee"; *order=11; break;
    case SUB: *name = "-"; *args="ee"; *order=11; break;
    case RSHIFT: *name = ">>"; *args="ee"; *order=10; break;
    case URSHIFT: *name = ">>"; *args="ee"; *order=10; break;
    case LSHIFT: *name = "<<"; *args="ee"; *order=10; break;
    case ULSHIFT: *name = "<<"; *args="ee"; *order=10; break;
    case GT: *name = ">"; *args="ee"; *order=9; break;
    case UGT: *name = ">"; *args="ee"; *order=9; break;
    case GE: *name = ">="; *args="ee"; *order=9; break;
    case UGE: *name = ">="; *args="ee"; *order=9; break;
    case LT: *name = "<"; *args="ee"; *order=9; break;
    case ULT: *name = "<"; *args="ee"; *order=9; break;
    case LE: *name = "<="; *args="ee"; *order=9; break;
    case ULE: *name = "<="; *args="ee"; *order=9; break;
    case EQ: *name = "=="; *args="ee"; *order=8; break;
    case NEQ: *name = "!="; *args="ee"; *order=8; break;

    case EOR: *name = "^"; *args="ee"; *order=6; break;
    case BOR: *name = "|"; *args="ee"; *order=5; break;
    case LAND: *name = "&&"; *args="ee"; *order=4; break;
    case LOR: *name = "||"; *args="ee"; *order=-1; break;
    case COND: *name = "?"; *args="eee"; *order=2; break;
    case ASS: *name = "="; *args="ee"; *order=1; break;
    case ASSOP: *name = "assop"; *args="eev"; *order=1; break;
    case CASSOP: *name = "cassop"; *args="eev"; *order=1; break;
    case COMMA: *name = "; *args=","ee"; *order=0; break;
    case LPAR: *name = "("; *args=""; *order=-1; break;
    case RPAR: *name = ")"; *args=""; *order=-1; break;
    case LBRA: *name = "["; *args=""; *order=-1; break;
    case RBRA: *name = "]"; *args=""; *order=-1; break;
    case LC: *name = "{"; *args=""; *order=-1; break;
    case RC: *name = "}"; *args=""; *order=-1; break;
    case COLON: *name = ":"; *args="ee"; *order=-1; break;
    case SM: *name = ";"; *args=""; *order=-1; break;
    case PERIOD: *name = "."; *args=""; *order=16; break;
    case ARROW: *name = "->"; *args=""; *order=16; break;
    case SASS: *name = "sass"; *args=""; *order=-1; break;
    case RSTRUCT: *name = "rstruct"; *args=""; *order=-1; break;
    case AS+MUL: *name = "*="; *args="ee"; *order=1; break;
    case AS+UMUL: *name = "*="; *args="ee"; *order=1; break;
    case AS+DIV: *name = "/="; *args="ee"; *order=1; break;
    case AS+UDIV: *name = "/="; *args="ee"; *order=1; break;
    case AS+MOD: *name = "%="; *args="ee"; *order=1; break;
    case AS+UMOD: *name = "%="; *args="ee"; *order=1; break;
    case AS+ADD: *name = "+="; *args="ee"; *order=1; break;
    case AS+MINUS: *name = "-="; *args="ee"; *order=1; break;
    case AS+RSHIFT: *name = ">>="; *args="ee"; *order=1; break;
    case AS+URSHIFT: *name = ">>="; *args="ee"; *order=1; break;
    case AS+LSHIFT: *name = "<<="; *args="ee"; *order=1; break;
    case AS+ULSHIFT: *name = "<<="; *args="ee"; *order=1; break;
    case AS+BAND: *name = "&="; *args="ee"; *order=1; break;
    case AS+EOR: *name = "^="; *args="ee"; *order=1; break;
    case AS+BOR: *name = "|="; *args="ee"; *order=1; break;
    default: found = 0;
fprintf(stderr,"Unknown ID %d [%d]in find node\n",id,OP(id));

    }
    return found;
}

static int
attr_print(int t)
{
    while (t>0 && car(t)==ATTRIBUTE) {
	switch (caddr(t)) {
	case KONST: printf( "const"); break;
	case VOLATILE: printf( "volatile"); break;
	case RESTRICT: printf( "restrict"); break;
	case INLINE: printf( "inline"); break;
	}
	t = cadr(t);
    }
    return t;
}

void
tree_print_t(int e,int t)
{
    printf("# type: ");
    tree_print(t);
    printf("expr: ");
    tree_print(e);
    printf("\n");
}

void
tree_print(int e)
{
    printf("* generate code on type:\n* ");
    tree_parse(type);
    printf("\n* expr:\n* ");
    tree_parse(e);
    printf("\n");
}

static
int tree_level;

void
tree_parse(int e)
{
    tree_node_type node_type,*t;
    int i,j;
    char *s, **p;
    NMTBL **n;

    t = &node_type; t->tree_type=e;

    if(e<0) {
	if (tree_nodes(e,&t->tree_name,&t->tree_args,&t->tree_order)) {
	    for(j=0;j<tree_level;j++) putchar(' ');
	    printf("list(%s)",t->tree_name);
	}
    } else {
	i = car(e);
	if (tree_nodes(e,&t->tree_name,&t->tree_args,&t->tree_order)) {
	    tree_level++;
	    for(j=0;j<tree_level;j++) putchar(' ');
	    printf("list(%s",t->tree_name);
	    for(i=1,s=t->tree_args;*s;s++,i++) {
		switch(*s) {
		case 'e':
		case 't':
		    printf(",\n*");
		    tree_parse(heap[e+i]); break;
		case 'v':
		    printf(",%d",heap[e+i]); break;
		case 'n':
		    n = (NMTBL**)&(heap[e+i]);
		    printf(",%s",(*n)->nm); break;
		case 's':
		    p = (char**)&(heap[e+i]);
		    printf(",%s",*p); break;
		case 'i':
		    printf(",%d",heap[e+i]); break;
		}
	    }
	    tree_level--;
	    printf(")");
	}
    }
}

void struct_type_print(int type,FILE *out)
{
    NMTBL *n;
    int tags;
    if((n=ncadddr(type))) {
	fprintf(out,"%s ",n->nm);
	return;
    }
    if((tags=caddr(type))) {
	fprintf(out,"{");
	while(tags) {
	    n=ncaddr(tags);
	    type_print(car(tags),n,out);
	    fprintf(out,";");
	    tags = cadr(tags);
	}
	fprintf(out,"}");
    }
}

void function_type_print1(int type,NMTBL *n,FILE *out,int cont)
{
    int args;
    type_print1(cadr(type),0,out,cont);
    if(n) fprintf(out," %s",n->nm);
    fprintf(out,"(");
    if((args=caddr(type))) {
	while (args) {
	    type_print(car(args),0,out);
	    args=cadr(args);
	    if (args) fprintf(out,",");
	}
    }
    fprintf(out,")");
}

void function_type_print(int type,NMTBL *n,FILE *out)
{
    function_type_print1(type,n,out,0);
}

void sym_print(int sym,FILE *out)
{
    tree_node_type tn;
    if (!(tree_nodes(sym,&tn.tree_name,&tn.tree_args,&tn.tree_order))) { error(-1); return; }
    fprintf(out,"%s",tn.tree_name);
}

NMTBL *
typedef_search(int t,int type) 
{
    while(t) {
	if ((ncaddr(t))->ty==type)
	    return ncaddr(t);
	t=cadr(t);
    }
    return 0;
}

static void n_attr_print(int attr, FILE *out)
{
    for(;attr;attr=cadr(attr)) {
	switch(car(attr)) {
	case INLINE: fprintf(out,"inline "); break;
	case CONST: fprintf(out,"const "); break;
	case VOLATILE: fprintf(out,"const "); break;
	case RESTRICT: fprintf(out,"const "); break;
	}
    }
}

void type_print1(int type,NMTBL *n,FILE *out,int cont)
{
    int t; 
    tree_node_type *tn,tn0;
    NMTBL *td;
    int args;
    tn = &tn0;

    if (n) {
	if (n->attr) n_attr_print(n->attr,out);
	while(type>0 && car(type)==ATTRIBUTE) type=cadr(type);
    } else
	type = attr_print(type);
    if(type>0&&(td=typedef_search(typedefed,type))) {
	if (!cont)
	    fprintf(out,"%s ",td->nm);
    } else if(type>0&&(td=typedef_search(gtypedefed,type))) {
	if (!cont)
	    fprintf(out,"%s ",td->nm);
    } else if (type<0) {
	t=type;
	if (!(tree_nodes(t,&tn->tree_name,&tn->tree_args,&tn->tree_order))) { error(-1); return; }
	if (!cont)
	    fprintf(out,"%s ",tn->tree_name);
    } else if ((t=car(type))) {
	if (!(tree_nodes(t,&tn->tree_name,&tn->tree_args,&tn->tree_order))) { error(-1); return; }
	if(t==STRUCT||t==UNION) {
	    if (!cont) {
		fprintf(out,"%s ",tn->tree_name);
		struct_type_print(type,out);
	    }
	} else if(t==CODE) {
	    // if (!cont) { fprintf(out,"%s ",tn->tree_name); }
	    function_type_print1(type,n,out,cont);
	    return;
	} else if(t==FUNCTION) {
	    function_type_print1(type,n,out,cont);
	    return;
	} else if(t==ARRAY) {
	    type_print1(cadr(type),n,out,cont);
	    if (caddr(type))
		fprintf(out,"[%d]",caddr(type));
	    else
		fprintf(out,"[]");
	    return;
	} else if(t==POINTER) {
	    t=cadr(type);
	    if(t<0) {
		type_print1(t,0,out,cont);
		fprintf(out,"*");
	    } else if(car(t)==FUNCTION) {
		type_print1(cadr(t),0,out,cont);
		fprintf(out,"(*");
		if(n) fprintf(out,"%s",n->nm);
		fprintf(out,")");
		fprintf(out,"(");
		if((args=caddr(t))) {
		    while (args) {
			type_print(car(args),0,out);
			args=cadr(args);
			if (args) fprintf(out,",");
		    }
		}
		fprintf(out,")");
		return;
	    } else if(car(t)==CODE) {
		type_print1(cadr(t),0,out,cont);
		fprintf(out,"(*");
		if(n) fprintf(out,"%s",n->nm);
		fprintf(out,")");
		fprintf(out,"(");
		if((args=caddr(t))) {
		    while (args) {
			type_print(car(args),0,out);
			args=cadr(args);
			if (args) fprintf(out,",");
		    }
		}
		fprintf(out,")");
		return;
	    } else if(car(t)==ARRAY) {
		fprintf(out,"(*");
		type_print(cadr(t),n,out);
		if (caddr(type))
		    fprintf(out,")[%d]",caddr(type));
		else
		    fprintf(out,")[]");
		return;
	    } else {
		type_print1(t,0,out,cont);
		fprintf(out,"*");
	    }
	}
    }
    if(n) fprintf(out,"%s",n->nm);
}

void type_print(int type,NMTBL *n,FILE *out)
{
    type_print1(type,n,out,0);
}

/*
    parse tree を印刷する

    正しく括弧とかを付けるアルゴリズムが不明...
    先読みして、優先順位を判別する必要があるはず。

    そういえば、cast とかは、落ちて変換コードに変わっている
    はず。cast を木にしないとだめか。
 */

void
print_expr(int e, FILE *vout)
{
    NMTBL *nptr,*n;

    if (e==0) {
	// can't happen in normal C language
	fprintf(vout,"#");
	return;
    }
    switch (car(e)%SOP) {
    case LVAR:
    case RLVAR:
    case URLVAR:
	if ((nptr = ncaddr(e))) {
	    fprintf(vout,"%s",nptr->nm);
	} else {
	    // anonymous variable
	    fprintf(vout,"_%d",caddr(e));
	}
	break;
    case GVAR:
    case RGVAR:
    case URGVAR:
	if ((nptr = ncaddr(e))) {
	    fprintf(vout,"%s",nptr->nm);
	} else {
	    // anonymous variable
	    fprintf(vout,"_%d",caddr(e));
	}
	if (cadr(e)) {
	    // offset
	    // certainly this is wrong
	    fprintf(vout,"+%d",caddr(e));
	}
        break;
    case REGISTER:
	if ((nptr = ncaddr(e))) {
	    fprintf(vout,"%s",nptr->nm);
	} else {
	    // anonymous register variable
	    fprintf(vout,"_%d",caddr(e));
	}
        break;
    case IDENT:
        nptr = ncaddr(e);
        fprintf(vout,"%s",nptr->nm); break;
    case CONST:
	switch(car(e)) {
	case CONST:
	    fprintf(vout,"%d",cadr(e)); break;
#if FLOAT_CODE
	case FCONST:
	    fprintf(vout,"%g",dcadr(e)); break;
	case DCONST:
	    fprintf(vout,"%g",dcadr(e)); break;
#endif
#if LONGLONG_CODE
	case LCONST:
	    fprintf(vout,"%lld",lcadr(e)); break;
#endif
	}
	break;
    case ADDRESS:
	if (car(cadr(e))!=STRING) {
	    fprintf(vout,"&");
	    print_expr(cadr(e),vout);
	    break;
	}
    case STRING:
        { 
            int c; char *s; int i;
            nptr = ncaddr(e); s = nptr->nm;i=nptr->dsp;
            fprintf(vout,"\"");
            while(--i>0) {
                c=*s++;
                if(c=='\n') fprintf(vout,"\\n");
                else if(c=='\r') fprintf(vout,"\\r");
                else if(c=='\t') fprintf(vout,"\\t");
                else if(c=='\e') fprintf(vout,"\\e");
                else if(c=='"') fprintf(vout,"\\\"");
                else if(c=='\\') fprintf(vout,"\\\\");
                else if(!(' '<=c&&c<=0x7f)) fprintf(vout,"\\%03o",c);
                else fprintf(vout,"%c",c);
            }   
            fprintf(vout,"\"");
        }
        break;
    case ARRAY:
        print_expr(cadr(e),vout);
        fprintf(vout,"[");
        print_expr(caddr(e),vout);
        fprintf(vout,"]");
        break;
    case PERIOD:
        print_expr(cadr(e),vout);
        n = ncaddr(e);
        fprintf(vout,".%s",n->nm);
	break;
    case ARROW:
        print_expr(cadr(e),vout);
        n = ncaddr(e);
        fprintf(vout,"->%s",n->nm);
        break;
    case INDIRECT:
    case RINDIRECT:
    case URINDIRECT:
        fprintf(vout,"*");
        print_expr(cadr(e),vout);
        break;
    case FNAME:
        n = ncaddr(e);
        fprintf(vout,"%s",n->nm);
        break;
    case FUNCTION:
	print_function_call(e,vout);
        break;
/*
    case ADD:
        fprintf(vout,"(");
        print_expr(cadr(e),vout);
        fprintf(vout,"+");
        print_expr(caddr(e),vout);
        fprintf(vout,")");
        break;
  */
    case RSTRUCT:
        print_expr(cadr(e),vout);
        break;
    default:
	print_operator(e, vout);
    }
}

static void
print_expr_paren(int order,char *args,int e)
{
}

static void
print_operator(int e, FILE *vout)
{
    char *name; char *args; int order ;
    if (tree_nodes(car(e), &name, &args, &order) ) {
	if (order>0) {
	    int i = 0;
	    for(;*args;args++,i++) {
		print_expr_paren(order,args,heap[e+i]);
	    }
	} else {
	    print_statement(e, vout);
	}
    }
}

static void
print_decl(int e, FILE *vout)
{
    NMTBL *n = ncaddr(e);
    int e1 = cadddr(e);
    // int mode = car(e1);
    int stmode = cadr(e1);
    int ctmode = caddr(e1);

    if (n==&null_nptr) {
	error(-1); // can't happen
	return;
    }
    if (stmode==STATIC) {
	fprintf(vout,"static "); 
    } else if (stmode==EXTRN||stmode==EXTRN1) {
	fprintf(vout,"extern "); 
    }
    type_print(n->ty,n,vout);
    if (ctmode & KONST_BIT) {
	fprintf(vout,"const "); 
    }
    if (ctmode & VOLATILE_BIT) {
	fprintf(vout,"volatile "); 
    }
    if (ctmode & RESTRICT_BIT) {
	fprintf(vout,"restrict "); 
    }
    fprintf(vout,"%s; ",nptr->nm); 
}

static void
print_statement(int e, FILE *vout)
{
    int e1;
    NMTBL *n;
    for (;e!=0; e = cadr(e)) {
	switch (car(e)) {
	case ST_DECL:
	    print_decl(e, vout); break;
	case ST_IF:
	    fprintf(vout,"if "); break;
	case ST_DO:
	    fprintf(vout,"do "); break;
	case ST_WHILE:
	    fprintf(vout,"while "); break;
	case ST_FOR:
	    fprintf(vout,"for "); break;
	case ST_SWITCH:
	    fprintf(vout,"switch "); break;
	case ST_COMP:
	    fprintf(vout,"{");
	    fprintf(vout,"}");
	    break;
	case ST_BREAK:
	    fprintf(vout,"break; "); break;
	case ST_CONTINUE:
	    fprintf(vout,"continue; "); break;
	case ST_CASE:
	    for(e1 = caddr(e);e1;e1 = cadr(e1)) {
		fprintf(vout,"case "); 
		fprintf(vout,"%d: ",car(e1)); 
	    }
	    break;
	case ST_DEFAULT:
	    fprintf(vout,"default: "); break;
	case ST_RETURN:
	    fprintf(vout,"return "); 
	    if (( e1 = caddr(e))) {
		print_expr(e1,vout);
	    }
	    fprintf(vout,"; "); 
	    break;
	case ST_GOTO:
	    fprintf(vout,"goto "); break;
	case ST_ASM:
	    fprintf(vout,"__asm__ "); break;
	case ST_LABEL:
	    n = ncaddr(caddr(e));
	    fprintf(vout,"%s:", n->nm); break;
	case ST_OP:
	    e1 = caddr(e);
	    print_expr(list3(cadr(e),car(e1),cadr(e1)),vout);
	    break;
	case ST_COMMENT:
	    fprintf(vout,"\n# %s\n",scaddr(e)); 
	    break;
	default:
	    fprintf(stderr,"Unknown Statement ID %d\n",car(e));
	}
    }
}

static void
print_function_call(int e1,FILE *vout)
{
    int e2,e3;
    NMTBL *fn = 0;

    e2 = cadr(e1);
    if (car(e2) == FNAME) {     
        fn=ncaddr(e2);
        fprintf(vout,"%s",fn->nm);
    } else {    
        if (car(e2)==INDIRECT) e2=cadr(e2); // (*func)(i) case
        fprintf(vout,"(");
        print_expr(e2,vout);
        fprintf(vout,")");
    }

    fprintf(vout,"(");
    for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {    
        print_expr(car(e3),vout);
	if (cadr(e3)) {
	    fprintf(vout,",");
	}
    }
    fprintf(vout,")");
    reverse0(e1); // make it normal order

}


/* end */