view mc-tree.c @ 643:f5c0371c9401

*** empty log message ***
author kono
date Wed, 01 Nov 2006 15:55:24 +0900
parents 0e7281ec9007
children 3e1dba5758d8
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"

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

extern void tree_print(int e);
extern void tree_parse(int e);
extern void tree_print_t(int e,int t);
static tree_node_type * find_node(int e);
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);

/* ascendant order for binary search */

static
tree_node_type tree_nodes[] = {
    {DOTS,"...",""},
    {LMACRO,"lmacro",""},
    {FMACRO,"fmacro",""},
    {KONST,"const",""},
    {DEFINED,"defined",""},
    {ENVIRONMENT,"environment",""},
    {CODE,"code",""},
    {REGISTER,"register",""},
    {ASM,"__asm__",""},
    {VOID,"void",""},
    {EXTRN,"extern",""},
    {SHORT,"short",""},
    {USHORT,"unsigned short",""},
    {LONG,"long",""},
    {TYPE,"type",""},
    {VOLATILE,"volatile",""},
    {SIZEOF,"sizeof",""},
    {TYPEDEF,"typedef",""},
    {FLABEL,"flabel",""},
    {BLABEL,"blabel",""},
    {MACRO,"macro",""},
    {STRING,"string",""},
    {IDENT,"ident",""},
    {FIELD,"field",""},
    {TAG,"tag",""},
    {RESERVE,"reserve",""},
    {DEFAULT,"default",""},
    {ATTRIBUTE,"__attribute__",""},
    {CASE,"case",""},
    {SWITCH,"switch",""},
    {WHILE,"while",""},
    {DO,"do",""},
    {FOR,"for",""},
    {ELSE,"else",""},
    {IF,"if",""},
    {CONTINUE,"continue",""},
    {BREAK,"break",""},
    {RETURN,"return",""},
    {GOTO,"goto",""},
    {STATIC,"static",""},
    {EMPTY,"empty",""},
    {FUNCTION,"function","t"},
    {UNION,"union",""},
    {STRUCT,"struct","vt"},
    {ARRAY,"array","tv"},
    {POINTER,"*","t"},
    {UNSIGNED,"unsigned",""},
    {INLINE,"inline",""},
    {SIGNED,"signed",""},
    {CHAR,"char",""},
    {UCHAR,"unsigned char",""},
    {INT,"int",""},
    {FLOAT,"float",""},
    {DOUBLE,"double",""},
    {LONGLONG,"long long",""},
    {ULONGLONG,"unsigned long long",""},

    {GVAR,"gvar","vs"},
    {RGVAR,"rgvar","vs"},
    {CRGVAR,"crgvar","vs"},
    {LVAR,"lvar","v"},
    {RLVAR,"rlvar","v"},
    {CRLVAR,"crlvar","v"},
    {CONST,"const","v"},
    {FNAME,"fname","n"},
    {MUL,"*","e"},
    {RINDIRECT,"rindirect","e"},
    {CRINDIRECT,"crindirect","e"},
    {BAND,"&","e"},
    {MINUS,"-","e"},
    {LNOT,"!","e"},
    {BNOT,"~","e"},
    {INC,"++",""},
    {POSTINC,"postinc","e"},
    {PREINC,"preinc","e"},
    {CPOSTINC,"cpostinc","e"},
    {CPREINC,"cpreinc","e"},
    {DEC,"--",""},
    {DIV,"/","ee"},
    {UDIV,"/","ee"},
    {MUL,"*","ee"},
    {UMUL,"*","ee"},
    {MOD,"%","ee"},
    {UMOD,"%","ee"},
    {ADD,"+","ee"},
    {SUB,"-","ee"},
    {RSHIFT,">>","ee"},
    {URSHIFT,">>","ee"},
    {LSHIFT,"<<","ee"},
    {ULSHIFT,"<<","ee"},
    {GT,">","ee"},
    {UGT,">","ee"},
    {GE,">=","ee"},
    {UGE,">=","ee"},
    {LT,"<","ee"},
    {ULT,"<","ee"},
    {LE,"<=","ee"},
    {ULE,"<=","ee"},
    {EQ,"==","ee"},
    {NEQ,"!=","ee"},
    {BAND,"&","ee"},
    {EOR,"^","ee"},
    {BOR,"|","ee"},
    {LAND,"&&","ee"},
    {LOR,"||","ee"},
    {COND,"?","eee"},
    {ASS,"=","ee"},
    {ASSOP,"assop","eev"},
    {CASSOP,"cassop","eev"},
    {COMMA,",","ee"},
    {LPAR,"(",""},
    {RPAR,")",""},
    {LBRA,"[",""},
    {RBRA,"]",""},
    {LC,"{",""},
    {RC,"}",""},
    {COLON,":","ee"},
    {SM,";",""},
    {PERIOD,".",""},
    {ARROW,"->",""},
    {SASS,"sass",""},
    {RSTRUCT,"rstruct",""},
    {AS+MUL,"*=","ee"},
    {AS+UMUL,"*=","ee"},
    {AS+DIV,"/=","ee"},
    {AS+UDIV,"/=","ee"},
    {AS+MOD,"%=","ee"},
    {AS+UMOD,"%=","ee"},
    {AS+ADD,"+=","ee"},
    {AS+MINUS,"-=","ee"},
    {AS+RSHIFT,">>=","ee"},
    {AS+URSHIFT,">>=","ee"},
    {AS+LSHIFT,"<<=","ee"},
    {AS+ULSHIFT,"<<=","ee"},
    {AS+BAND,"&=","ee"},
    {AS+EOR,"^=","ee"},
    {AS+BOR,"|=","ee"},
};

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 *t;
    int i,j;
    char *s;

    if(e<0) {
	t=find_node(e);
	if(t->tree_type==e) {
	    for(j=0;j<tree_level;j++) putchar(' ');
	    printf("list(%s)",t->tree_name);
	}
    } else {
	i = car(e);
	t=find_node(e);
	if(t->tree_type==i) {
	    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':
		    printf(",%s",((NMTBL *)heap[e+i])->nm); break;
		case 's':
		    printf(",%s",(char *)heap[e+i]); break;
		case 'i':
		    printf(",%d",heap[e+i]); break;
		}
	    }
	    tree_level--;
	    printf(")");
	}
    }
}

tree_node_type *
find_node(int e) {
    int e1,e2;
    int first=0;
    int last=sizeof(tree_nodes)/sizeof(tree_node_type);
    // e2=-1;
    e2=OP(e);
    e1=0;
    while (first!=last) {
#if 0
	e1 = (first+last)/2;
	if(e2==e1) 
	    return 0;
	e2=e1;
	if (tree_nodes[e1].tree_type>e)
	    last = e1;
	else if (tree_nodes[e1].tree_type==e)
	    break;
	else if (tree_nodes[e1].tree_type<e)
	    first = e1;
#else
	if (tree_nodes[first].tree_type==e2)
	    return &tree_nodes[first];
	first++;
#endif
    }
fprintf(stderr,"Unknown ID %d [%d]in find note\n",e2,e);
    return &tree_nodes[e1];
}

void struct_type_print(int type,FILE *out)
{
    NMTBL *n;
    int tags;
    if((n=(NMTBL*)cadddr(type))) {
	fprintf(out,"%s ",n->nm);
	return;
    }
    if((tags=caddr(type))) {
	fprintf(out,"{");
	while(tags) {
	    n=(NMTBL*)caddr(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 (!(tn=find_node(sym))) { error(-1); return; }
    fprintf(out,"%s",tn->tree_name);
}

NMTBL *
typedef_search(int t,int type) 
{
    while(t) {
	if (((NMTBL*)car(t))->ty==type)
	    return (NMTBL*)car(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;
    NMTBL *td;
    int args;

    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 (!(tn=find_node(t))) { error(-1); return; }
	if (!cont)
	    fprintf(out,"%s ",tn->tree_name);
    } else if ((t=car(type))) {
	if (!(tn=find_node(t))) { 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 を印刷する

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

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

    switch (car(e)%SOP) {
    case LVAR:
    case RLVAR:
	if ((nptr = (NMTBL*)caddr(e))) {
	    fprintf(vout,"%s",nptr->nm);
	} else {
	    // anonymous variable
	    fprintf(vout,"_%d",caddr(e));
	}
	break;
    case GVAR:
    case RGVAR:
	if ((nptr = (NMTBL*)caddr(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 = (NMTBL*)caddr(e))) {
	    fprintf(vout,"%s",nptr->nm);
	} else {
	    // anonymous register variable
	    fprintf(vout,"_%d",caddr(e));
	}
        break;
    case IDENT:
        nptr = (NMTBL*)cadr(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 = (NMTBL*)cadr(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 = (NMTBL*)caddr(e);
        fprintf(vout,".%s",n->nm);
	break;
    case ARROW:
        print_expr(cadr(e),vout);
        n = (NMTBL*)caddr(e);
        fprintf(vout,"->%s",n->nm);
        break;
    case INDIRECT:
    case RINDIRECT:
        fprintf(vout,"*");
        print_expr(cadr(e),vout);
        break;
    case FNAME:
        n = (NMTBL*)cadr(e);
        fprintf(vout,"%s",n->nm);
        break;
    case ADD:
        fprintf(vout,"(");
        print_expr(cadr(e),vout);
        fprintf(vout,"+");
        print_expr(caddr(e),vout);
        fprintf(vout,")");
        break;
    default:
        error(-1);
    }
}

/* end */