changeset 453:1e5ca85d3f97

inline on going...
author kono
date Tue, 30 Nov 2004 02:20:42 +0900
parents 8e3284b0a8c9
children 214272c8f2da
files .gdbinit Changes Makefile mc-code-powerpc.c mc-codegen.c mc-codegen.h mc-h-renum.pl mc-parse.c mc-parse.h mc.h
diffstat 10 files changed, 954 insertions(+), 178 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Mon Nov 29 04:15:38 2004 +0900
+++ b/.gdbinit	Tue Nov 30 02:20:42 2004 +0900
@@ -9,7 +9,7 @@
 # run  -s test/basic.c
 # run -s test/code-gen-all.c
 # run -s test/tmp7.c
-run -s test/tmp1.c
+run -s test/inline.c
 define regs 
 printf "pc =%08x lr =%08x r0 =%08x r1 =%08x r3= %08x r4= %08x\n",$pc,$lr,$r0,$r1,$r3,$r4
 printf "r10=%08x r11=%08x r12=%08x r13=%08x r14=%08x r15=%08x\n",$r10,$r11,$r12,$r13,$r14,$r15
--- a/Changes	Mon Nov 29 04:15:38 2004 +0900
+++ b/Changes	Tue Nov 30 02:20:42 2004 +0900
@@ -6618,23 +6618,27 @@
 よし、inline やるか。
 
    inline function (or parsed tree)
-       list4(INLINE,name,type)
+       // list4(INLINE,name,type)
+       sc = INLINE
+       attr = parse
    declaration (argument, local, static)
-       list4(DECL,next,init,NMTBL *nptr)        done by def (?)
+       list4(ST_DECL,next,NMTBL *nptr,stmode)        done by def (?)
    statement
-       list3(IF,next,list3(cond,then,else))
-       list3(DO,next,list2(cond,while))
-       list3(FOR,next,list4(A,B,C,body))
-       list4(SWITCH,next,expr,body)
-       list3(COMP,next,body)
-       list2(BREAK,next)
-       list2(CONTINUE,next)
-       list3(CASE,next,label)
+       list3(ST_IF,next,list3(cond,then,else))
+       list4(ST_DO,next,cond,while)
+       list4(ST_WHILE,next,cond,while)
+       list3(ST_FOR,next,list4(A,B,C,body))
+       list4(ST_SWITCH,next,expr,body)
+       list3(ST_COMP,next,body)
+       list2(ST_BREAK,next)
+       list2(ST_CONTINUE,next)
+       list3(ST_CASE,next,label)
+       list3(ST_DEFAULT,next)
        list3(ST_RETURN,next,expr)
-       list3(GOTO,next,expr,env)
-       list3(ST_ASM,next,list4(A,B,C,D))
+       list3(ST_GOTO,next,expr,env)
+       list3(ST_ASM,next,list4(A,B,C,D),e1)
        list3(ST_LABEL,next,label)
-       list3(COMMENT,next,comment)  (?)
+       list3(ST_COMMENT,next,comment)  (?)
 
   いくつかはexprと重なるけど... (まずい?) RETURN, ASM
 
@@ -6933,3 +6937,29 @@
 	  int arg0,...argn;
       }
    }
+
+Mon Nov 29 11:55:14 JST 2004
+
+attr は、連想リストにするべきか。
+
+partial evaluation を、どの段階で行うかっていう問題があるのか。
+
+expr15 (function call)
+
+inline 木作成の最中に展開すると繰り返し展開することになる。
+しなくても良いが... しかも、ST_* が expr の中に残ってしまう
+ので、g_expr で、ST_* を扱うことが必須。ってことは変更が結構
+大きい。ここで展開すると binop の最適化にひっかかるので簡単。
+docomp と同じ扱いが必要?
+
+function (codegen)
+
+ここで展開すると、代入とかが変数扱いしかしなくなる。手遅れ。
+
+ってことは、expr15 で、partial evalucation はやる。inline
+中は展開しないとして、残った ST_* は、g_expr で処理する
+ってことですね。
+
+static でもポインタを取られたりすると関数を生成する必要がある。
+extern なら、なおさら。それは、自分でやらないとダメ。まぁ、
+inline の関数リストを作るのが良いんだろうけど。
--- a/Makefile	Mon Nov 29 04:15:38 2004 +0900
+++ b/Makefile	Tue Nov 30 02:20:42 2004 +0900
@@ -15,7 +15,7 @@
 PRINTF= # printf.c
 CONVERTER=conv/c.o conv/null.o
 # conv/c2cbc.o conv/cbc2c.o
-COMPLIB = mc-parse.o mc-codegen.o mc-switch.o mc-macro.o mc-tree.o
+COMPLIB = mc-parse.o mc-codegen.o mc-switch.o mc-macro.o mc-tree.o mc-inline.o
 # CODE=mc-code-ia32.c
 CODE=mc-code-$(ARCH).c
 #
@@ -31,6 +31,7 @@
 		mc-macro.c \
 		mc-parse.c mc-tree.c mc-switch.c mc-switch.h \
 		mc.h conv/c.c conv/c.h \
+		mc-inline.h mc-inline.c \
 		conv/conv.h conv/convdef.h conv/null.c
 
 mc-powerpc : mc-code-powerpc.o $(COMPLIB) $(CONVERTER)
@@ -93,6 +94,7 @@
 	make check TARGET=test/cext
 	make check TARGET=test/const
 	make check TARGET=test/void_code
+	make check TARGET=test/inline
 #	make check TARGET=test/scope STDFLAG="-std=gnu99"
 #MK =-make
 MK=
@@ -163,11 +165,11 @@
 clean :
 	-rm -f mc mc-ia32 mc-powerpc mc-mips mc-arm *.bak *.s *.o *.cc mc mc1 mc2 a.out *~ core* */*.o *.bak test/*.s test/*.cc test/*.o test/*.bak test/*~ conv/*.s conv/*.cc conv/*.o conv/*.bak conv/*~ *.out */*.out *.i */*.i
 
-mc1 : b00.s b01.s mc-codegen.o mc-tree.o mc-switch.o mc-macro.o $(CONVERTER)
-	$(CC) -g -o $@ $(PRINTF) b00.s b01.s mc-codegen.o mc-tree.o mc-switch.o mc-macro.o $(CONVERTER)
+mc1 : b00.s b01.s mc-codegen.o mc-tree.o mc-switch.o mc-macro.o mc-inline.o $(CONVERTER)
+	$(CC) -g -o $@ $(PRINTF) b00.s b01.s mc-codegen.o mc-tree.o mc-switch.o mc-macro.o mc-inline.o $(CONVERTER)
 
-mc2 : b00.s b01.s b02.s b03.s mc-macro.o  $(CONVERTER)
-	$(CC) -g -o $@ $(PRINTF) b00.s b01.s b02.s b03.s b04.s mc-macro.o $(CONVERTER)
+mc2 : b00.s b01.s b02.s b03.s mc-macro.o  mc-inline.o $(CONVERTER)
+	$(CC) -g -o $@ $(PRINTF) b00.s b01.s b02.s b03.s b04.s mc-macro.o mc-inline.o $(CONVERTER)
 
 b00.s : mc-parse.c $(MC)
 	./$(MC) -s -ob00.s mc-parse.c
--- a/mc-code-powerpc.c	Mon Nov 29 04:15:38 2004 +0900
+++ b/mc-code-powerpc.c	Tue Nov 30 02:20:42 2004 +0900
@@ -3165,7 +3165,9 @@
     }
     init = 0;
     for(n = global_list;n!=&null_nptr;n = n->next) {
-//	if (is_code(n)||is_function(n)) continue;
+	if ((is_code(n)||is_function(n))&& 
+	    !has_attr(n,FNAME))   // not used as value
+		continue;
 	if (n->sc==EXTRN1) {
 	    if(init==0) {
 		printf(".data\n");
--- a/mc-codegen.c	Mon Nov 29 04:15:38 2004 +0900
+++ b/mc-codegen.c	Tue Nov 30 02:20:42 2004 +0900
@@ -6,6 +6,7 @@
 #include "mc-parse.h"
 #include "mc-codegen.h"
 #include "mc-code.h"
+#include "mc-inline.h"
 
 int use;       /* generated value will be used */
 char *init_src;
@@ -56,6 +57,22 @@
 static int bassop(int e1,int e2,int op,int t,int post);
 #endif
 
+static void st_decl(int e1);
+static void st_if(int e1);
+static void st_do(int e1);
+static void st_while(int e1);
+static void st_for(int e1);
+static void st_switch(int e1);
+static void st_compj(int e1);
+static void st_break(int e1);
+static void st_continue(int e1);
+static void st_case(int e1);
+static void st_default(int e1);
+static void st_return(int e1);
+static void st_goto(int e1);
+static void st_asm(int e1);
+static void st_label(int e1);
+static void st_comment(int e1);
 
 extern void
 codegen_init()
@@ -127,14 +144,15 @@
 extern int
 g_expr0(int e1)
 {
-    int e2,e3,t,d,t1;
-    NMTBL *n;
-
-    if (mode==INLINE) {
-	return (parse = list2(e1,parse));
-    }
-    if (!control) return VOID;
-
+  int e2,e3,t,d,t1;
+  NMTBL *n;
+
+  if (mode==INLINE) {
+	return (parse = list3(ST_COMP,parse,e1));
+  }
+  if (!control) return VOID;
+
+  for(;e1;e1=e2) {
     code_gexpr(e1);
 
     e2 = cadr(e1);
@@ -505,10 +523,28 @@
         /*        asm    in (str) out (str) opt(str)   expr */
 	return VOID;
 #endif
+    case ST_DECL:         st_decl(e1);	break;
+    case ST_IF:           st_if(e1);	break;
+    case ST_DO:           st_do(e1);	break;
+    case ST_WHILE:        st_while(e1);	break;
+    case ST_FOR:          st_for(e1);	break;
+    case ST_SWITCH:       st_switch(e1);	break;
+    case ST_COMP:         st_comp(e1);	break;
+    case ST_BREAK:        st_break(e1);	break;
+    case ST_CONTINUE:     st_continue(e1);	break;
+    case ST_CASE:         st_case(e1);	break;
+    case ST_DEFAULT:      st_default(e1);	break;
+    case ST_RETURN:       st_return(e1);	break;
+    case ST_GOTO:         st_goto(e1);	break;
+    case ST_ASM:          st_asm(e1);	break;
+    case ST_LABEL:        st_label(e1);	break;
+    case ST_COMMENT:      st_comment(e1);	break;
     default:
 	code_bool(e1,USE_CREG); /* type? */
 	return INT;
     }
+  }
+  return VOID;
 }
 
 static int
@@ -744,6 +780,12 @@
 }
 
 extern int 
+is_inline(NMTBL *f)
+{
+    return (f && attr_value(f,INLINE));
+}
+
+extern int 
 function_type(int e1,int *dots)
 {
     int ret_type,t;
@@ -2370,6 +2412,13 @@
 extern void
 closing()
 {
+    int e;
+    NMTBL *n;
+    for(e=inline_funcs;e;e=cadr(e)) {
+	n = (NMTBL*)car(e);
+	if (1 || n->sc==EXTRN || has_attr(n,FNAME))  // global or used as pointer
+	    pfdecl(n);
+    }
     if (!chk)
 	code_closing();
 }
@@ -2601,7 +2650,7 @@
     if(type>0&&(car(type)==FUNCTION || car(type)==CODE)) {
 	if ((mode==GDECL)) {
 	    fcheck(n);
-	    n->attr = ctmode;
+	    if (ctmode) set_attr(n,KONST,0);
 	    return n;
 	    /* function and code segment are defined using fdecl/code_decl */
             /* in decl() */
@@ -2671,7 +2720,7 @@
 	    }
 	}
 	gpc +=sz;
-	n->attr = list2(ctmode,0);
+	if (ctmode) set_attr(n,KONST,0);
 	return n;
     case GSDECL: case LSDECL:
 	disp += sz;
@@ -2688,7 +2737,8 @@
 	break;
     case LLDECL:
 	nsc = FLABEL;
-	ndsp = fwdlabel();
+	if (!inmode)
+	    ndsp = fwdlabel();
 	break;
     case ADECL:
 	if(!integral(type)&&(car(type)==FUNCTION||car(type)==CODE)) {
@@ -2724,11 +2774,11 @@
 	} else {
 	    n->ty = type;
 	}
-	n->attr = ctmode;
+	if (ctmode) set_attr(n,KONST,0);
 	return n;
     case STAT: /* return (struct hoge)f() case? */
     case LDECL:
-	if (stmode==REGISTER) {
+	if (stmode==REGISTER && !inmode) {
 	    if(scalar(type)) {
 		ndsp = get_register_var(n);
 #if FLOAT_CODE
@@ -2750,14 +2800,14 @@
 	}
 	n->sc = nsc;
 	n->dsp = ndsp;
-	n->attr = list2(ctmode,0);
+	if (ctmode) set_attr(n,KONST,0);
 	return n;
     default:
 	error(DCERR);
     }
     n->sc = nsc;
     n->dsp = ndsp;
-    n->attr = list2(ctmode,0);
+    if (ctmode) set_attr(n,KONST,0);
     if (stmode==EXTRN)
 	n->sc = EXTRN;
     return n;
@@ -2904,8 +2954,8 @@
 	return offset+sz;
     }
     /* constant value field */
-    if (offset==0 && n && car(n->attr)==KONST) {
-	cadr(n->attr) = e;
+    if (offset==0 && (has_attr(n,KONST))) {
+	set_attr(n,KONST,e);
     }
     return offset+((t==EMPTY)?cadr(e):size(t));
 }
@@ -3117,7 +3167,7 @@
 extern int
 rvalue(int e)
 {
-    int op;
+    int op,c;
     NMTBL *n;    
 
     if (e==0) error(-1);
@@ -3166,14 +3216,14 @@
     switch(car(e)) {
     case GVAR:
 	n = (NMTBL*)caddr(e);
-	if (cadr(e)==0 && n->attr && car(n->attr)==KONST) {
-	    if (cadr(n->attr)) return cadr(n->attr);
+	if (cadr(e)==0 && (c=attr_value(n,KONST))) {
+	    return c;
 	}
 	return(list3(RGVAR+op,cadr(e),caddr(e)));
     case LVAR:
 	n = (NMTBL*)caddr(e);
-	if (n && car(n->attr)==KONST) {
-	    if (cadr(n->attr)) return cadr(n->attr);
+	if (n && (c=attr_value(n,KONST))) {
+	    return c;
 	}
 	return(list3(RLVAR+op,cadr(e),caddr(e)));
     case INDIRECT:
@@ -4147,4 +4197,370 @@
     return 0;
 }
 
+static void
+st_decl(int e1){
+    NMTBL *n = (NTMBL *)caddr(e1);
+    int stmode = cadddr(e1);
+}
+
+ 
+static void
+st_if(int e1){
+    int l1,l2,slfree;
+    int e2=caddr(e1),e3;
+    // conv->if_();
+    slfree=lfree;
+    checkret();
+    l1 = bexpr(car(e2),0,fwdlabel());
+    // conv->if_then_();
+    checkret();
+    g_expr_u(cadr(e2));
+    if ((e3=caddr(e2))) {  // else
+        // conv->if_else_();
+	if ((l2 = control))
+	    gen_jmp(l2=fwdlabel());
+	fwddef(l1);
+	g_expr_u(e3);
+	checkret();
+	if (l2) fwddef(l2);
+    } else {
+	fwddef(l1);
+    }
+    // conv->if_endif_();
+}
+
+ 
+static void
+st_do(int e1){
+    int sbreak,scontinue,l;
+
+    sbreak=blabel;
+    scontinue=clabel;
+    blabel=fwdlabel();
+    clabel=fwdlabel();
+    control=1;
+    checkret();
+    l=backdef();
+    // conv->dowhile_();
+    g_expr_u(cadddr(e1));
+    checkret();
+    // conv->dowhile_cond_();
+    bexpr(caddr(e1),1,l);
+    // conv->dowhile_end_();
+    fwddef(blabel);
+    clabel=scontinue;
+    blabel=sbreak;
+}
+
+ 
+static void
+st_while(int e1){
+    int sbreak,scontinue,e;
+
+    sbreak=blabel;
+    scontinue=clabel;
+    blabel=fwdlabel();
+    control=1;
+    checkret();
+    clabel=backdef();
+    // conv->while_();
+    // conv->while_body_();
+    if(!(e=cadddr(e1))) {
+	bexpr(caddr(e1),1,clabel);
+        // conv->sm_();
+    } else {
+	bexpr(caddr(e1),0,blabel);
+	g_expr_u(e);
+	checkret();
+	if(control)
+	    gen_jmp(clabel);
+    }
+    // conv->while_end_();
+    fwddef(blabel);
+    clabel=scontinue;
+    blabel=sbreak;
+}
+
+ 
+static void
+st_for(int e1){
+    int p0,p1,p2,body;
+    int l,e,dflag=0;
+    int sbreak=blabel;
+    int slimit = lfree_type_limit;
+    int scontinue=clabel;
+
+    e = caddr(e1); 
+    p0 = car(e); p1 = cadr(e); p2 = caddr(e); body = cadddr(e);
+
+    blabel=fwdlabel();
+    // conv->for_();
+    if (p0) {
+	checkret();
+	g_expr_u(p0);
+    }
+    // conv->for1_();
+    control=1;
+    checkret();
+    l=backdef();
+    if (p1) {
+	bexpr(p1,0,blabel);
+    }
+    // conv->for2_();
+    // conv->for_body_();
+    if (!p2) {
+        clabel=l;
+	g_expr_u(body);
+	checkret();
+    } else {
+        clabel=fwdlabel();
+	g_expr_u(body);
+	checkret();
+	fwddef(clabel);
+	g_expr_u(p2);
+    }
+    // conv->for_end_();
+    gen_jmp(l);
+    fwddef(blabel);
+    clabel=scontinue;
+    blabel=sbreak;
+}
+
+ 
+static void
+st_switch(int e1){
+    int sbreak,scase,sdefault,slfree,svalue,slist;
+
+    checkret();
+    slist = cslist;
+    cslist = 0;
+    sbreak=blabel;      /* save parents break label */
+    blabel=fwdlabel();
+    sdefault=dlabel;    /* save parents default label */
+    dlabel=0;
+    scase=cslabel;      /* save parents next case label */
+    // conv->switch_();
+    slfree=lfree;
+    svalue=csvalue1;      /* save parents switch value */
+    gexpr(caddr(e1),1);
+    csvalue1=csvalue() ;
+    // conv->switch_body_();
+    cslabel = control = 0;
+    g_expr_u(cadddr(e1));
+    // conv->switch_end_();
+    checkret();
+#if CASE_CODE
+    if (control) gen_jmp(blabel);
+    genswitch(cslist,cslabel);
+#else
+    if(dlabel) def_label(cslabel,dlabel);
+    else fwddef(cslabel);
+#endif
+    csvalue1=svalue;
+    cslabel=scase;
+    dlabel=sdefault;
+    fwddef(blabel);
+    blabel=sbreak;
+    cslist = slist;
+}
+
+ 
+static void
+st_comp(int e1){
+    g_expr_u(e1);
+}
+
+ 
+static void
+st_break(int e1){
+    checkret();
+    // conv->break_();
+    if (control)
+	gen_jmp(blabel);
+}
+
+ 
+static void
+st_continue(int e1){
+    checkret();
+    // conv->continue_();
+    if (control) gen_jmp(clabel);
+}
+
+ 
+static void
+st_case(int e1){
+#if CASE_CODE
+    int l,clist=caddr(e1),c;
+    l = fwdlabel();
+    // conv->case_begin_(0,0);
+    // conv->case_(0,0);
+    if (retpending) {
+        ret(); retpending=0;
+    }
+    if (!cslabel) {
+        if (!control) {
+            cmpdimm(car(clist),csvalue1,cslabel=fwdlabel(),1);
+            caddr(clist)=0;
+        } else {
+            error(-1);
+        }
+    }
+    while(clist) {
+        clist = cadr(c=clist); cadr(c) = 0;  // insert destroy cadr of clist
+        cslist=insert_ascend(cslist,c,docase_eq);
+    }
+    fwddef(l);
+    control=1;
+#else
+    /* casading branch implementation */
+    int c,l;
+    c = caddr(e1);
+    if (retpending) {
+	ret(); retpending=0;
+    }
+    // conv->case_begin_(0,0);
+    // conv->case_(0,0);
+    l=fwdlabel();
+    if (control) {
+        control=0;
+        gen_jmp(l);
+    }
+    if (cslabel) fwddef(cslabel);
+    while(cadr(c)) {
+        cmpdimm(car(c),csvalue1,l,0);
+        c=cadr(c);
+    }
+    cmpdimm(car(c),csvalue1,cslabel=fwdlabel(),1);
+    if (l) fwddef(l);
+#endif
+}
+
+ 
+static void
+st_default(int e1){
+    control=1;
+    checkret();
+    if (dlabel) error(STERR);  // double default:
+    dlabel = backdef();
+    // conv->case_(0,1);
+}
+
+ 
+static void
+st_return(int e1){
+    int e,e1;
+
+    if (!cslabel) gen_jmp(cslabel = fwdlabel());
+    if(!(e=caddr(e1))) {
+        // conv->return_();
+        // conv->return_end_();
+        retpending = 1;
+        return;
+    }
+    // conv->return_();
+    if (struct_return) {
+	if ((car(type)==STRUCT || car(type)==UNION)&&
+		size(type)==cadr(struct_return)) {
+	    if(car(e)==RSTRUCT && car(cadr(e))==FUNCTION) {
+		/* pass the return pointer to the called function */
+		replace_return_struct(cadr(e),
+		    rvalue_t(car(struct_return),caddr(struct_return)));
+		replace_return_struct(cadr(e),
+		    rvalue_t(car(struct_return),caddr(struct_return)));
+		gexpr(cadr(e),0);
+	    } else {
+		type = caddr(struct_return);
+		// e1 = rvalue_t(cadr(struct_return),INT); /* size */
+		e1 = cadr(struct_return); /* size */
+		gexpr(list4(STASS,rvalue(car(struct_return)),e,e1),0);
+	    }
+	} else {
+	    error(TYERR); /* should check compatible */
+	}
+    } else {
+	gexpr(correct_type(e,cadr(fnptr->ty)),1);
+    }
+    // conv->return_end_();
+    retpending = 1;
+}
+
+ 
+static void
+st_goto(int e){
+    NMTBL *nptr0;
+    int t,e1,e2,env;
+
+    checkret();
+    // conv->goto_();
+    e1 = caddr(e);
+    if (car(e1)==RINDIRECT) {
+	gen_indirect_goto(cadr(e1));
+	return;
+    } else if (car(e1)!=CODE) {
+        nptr0 = (NMTBL *)cadr(e1);
+        t = nptr0->sc;
+        if (t==EMPTY||t==EXTRN1||t==EXTRN) {
+            // error check?
+            nptr0->sc=EMPTY;
+            nptr0=l_top_search(nptr0->nm,0);
+            nptr0->sc = FLABEL;
+            nptr0->dsp = fwdlabel();
+        } else if (!(t==FLABEL||t==BLABEL)) {
+            error(STERR);
+        }
+	gen_jmp(nptr0->dsp);
+        control=0;
+        // conv->sm_();
+        // conv->goto_label_(nptr0);
+        return;
+    } else {
+	/*   CbC continuation */
+	// conv->jump_(env);
+	e2 = cadr(e1);
+	env = caddr(e1);
+	if (car(e2) == FNAME) {
+	    nptr0=(NMTBL *)cadr(e2);
+	    if (nptr0->sc==EMPTY)
+		nptr0->sc = EXTRN1;
+	    else if(nptr0->sc==FUNCTION)
+		nptr0->sc = CODE;
+	    if (nptr0->ty>0&&car(nptr0->ty)==FUNCTION)
+		car(nptr0->ty)=CODE;
+	}
+	gexpr(list3(CODE,e1,env),0);
+	control=0;
+	// conv->sm_();
+	return;
+    }
+}
+
+
+#if ASM_CODE
+static void
+st_asm(int e1){
+    checkret();
+    gexpr(list3(ASM,caddr(e1),cadddr(e1)),0);
+}
+#endif
+
+ 
+static void
+st_label(int e1){
+    NMTBL *nptr = (NMTBL*)caddr(e1);
+    control=1;
+    checkret();
+    if(nptr->sc == FLABEL) {
+	fwddef(nptr->dsp);
+    } else if(nptr->sc == BLABEL) {
+	nptr->dsp = backdef();
+    } else error(TYERR);
+    // conv->label_();
+}
+
+static void
+st_comment(int e1){
+    gen_comment((char *)car(e1));
+}
+
 /* end */
--- a/mc-codegen.h	Mon Nov 29 04:15:38 2004 +0900
+++ b/mc-codegen.h	Tue Nov 30 02:20:42 2004 +0900
@@ -89,6 +89,7 @@
 extern int g_expr_u(int e1);
 extern int is_code(NMTBL *fnptr);
 extern int is_function(NMTBL *fnptr);
+extern int is_inline(NMTBL *fnptr);
 extern int scalar(int t);
 extern int make_mask(int from,int to);
 
--- a/mc-h-renum.pl	Mon Nov 29 04:15:38 2004 +0900
+++ b/mc-h-renum.pl	Tue Nov 30 02:20:42 2004 +0900
@@ -16,6 +16,8 @@
     elsif(m+/\* error number end \*/+) { $mode = 0; }
     elsif(m+/\* mode start \*/+) { $mode = 4; }
     elsif(m+/\* mode end \*/+) { $mode = 0; }
+    elsif(m+/\* statement start \*/+) { $mode = 5; }
+    elsif(m+/\* statement end \*/+) { $mode = 0; }
     else {
 	if ($mode==0) { ; }
 	elsif ($mode==1) {
@@ -26,6 +28,8 @@
 	    s/(\d+)/$error++/e;
 	} elsif ($mode==4) {
 	    s/(\d+)/$modenum++/e;
+	} elsif ($mode==5) {
+	    s/(\d+)/$tags++/e;
 	}
     }
     print;
--- a/mc-parse.c	Mon Nov 29 04:15:38 2004 +0900
+++ b/mc-parse.c	Tue Nov 30 02:20:42 2004 +0900
@@ -6,6 +6,7 @@
 #include "mc-codegen.h"
 #include "mc-switch.h"
 #include "mc-macro.h"
+#include "mc-inline.h"
 #include "conv/conv.h"
 
 #define FILES 10
@@ -36,6 +37,7 @@
 static NMTBL *free_nptr_list;
 
 static int current_scope;
+int inline_funcs;
 
 char linebuf[LBUFSIZE];
 char *chptr;
@@ -313,7 +315,8 @@
 	(n==RGERR) ? "too many register usage (internal error)" :
 	(n==REG_ERR) ? "illegal register var" :
 	(n==INERR) ? "bad initialization" :
-	(n==CODE_ERR) ? "goto code is necessary" :
+	(n==CODE_ERR) ? "goto is necessary" :
+	(n==ILERR) ? "inline error" :
 	"Bug of compiler");
     errmsg();
     exit(1);
@@ -729,6 +732,9 @@
     } else {
 	conv->return_type_(type,n,sd);
 	n = def(n,ctmode);
+	if (inmode) {
+	    parse = list4(ST_DECL,parse,(int)n,stmode);
+	}
 	if (sym==ASS && n!=&null_nptr) { 
 	    decl_data(type,n,0,0); data_closing(n); 
 	}
@@ -745,6 +751,9 @@
 	    }
 	    conv->return_type_(type,n,1);
 	    def(n,ctmode);
+	    if (inmode) {
+		parse = list4(ST_DECL,parse,(int)n,stmode);
+	    }
 	    if (sym==ASS && n!=&null_nptr) {
 		decl_data(type,n,0,0);data_closing(n);
 	    }
@@ -1312,7 +1321,7 @@
 	    /* duplicate initialization */
 	    error(INERR);
 	} else {
-	    if (mode_save==GDECL && n->attr && car(n->attr)==KONST) {
+	    if (mode_save==GDECL && has_attr(n,KONST)) {
 		mode=GDECL;
 	    }
 	}
@@ -1540,6 +1549,7 @@
     int t,arglist;
 
     if(!chk) gen_code_enter(n->nm);
+    if (inmode) error(ILERR);
     extrn_use(n);
     local_static_list = &null_nptr;
     fnptr=n;
@@ -1623,14 +1633,18 @@
 {
     int sd = stypedecl;
     int arglist;
-    if(!chk) gen_enter(n->nm);
-    extrn_use(n);
+    if (!inmode) {
+	if(!chk) gen_enter(n->nm);
+	extrn_use(n);
+	retlabel=fwdlabel();
+    } else {
+	if (parse) error(-1);
+    }
     local_static_list = &null_nptr;
     fnptr=n;
-    retlabel=fwdlabel();
     retcont = 0;
-    if (tmp_struct) { tmp_struct->sc = 0; tmp_struct->nm = 0; }
-    tmp_struct = 0; /* a = f().filed  */
+    // if (tmp_struct) { tmp_struct->sc = 0; tmp_struct->nm = 0; } // why?
+    tmp_struct = 0; /* a = f().field  */
 
     n->ty = type;
     fcheck(n);
@@ -1639,7 +1653,7 @@
     if (sym!=LC) {
 	arglist = fnptr->dsp;
 	fnptr->dsp =args=0; 
-	while (sym!=LC) { /* argument declaration !ANSI */
+	while (sym!=LC) { /* K&R sytle argument declaration */
 	    stmode=0;
 	    decl(); getsym(0);
 	}
@@ -1651,7 +1665,8 @@
     fnptr->dsp=reverse0(fnptr->dsp);
     fdecl_struct(fnptr->ty); /* insert extra argument for struct passing */
     disp=0;
-    arg_register(fnptr);
+    if (!inmode)
+	arg_register(fnptr);
     typedefed=0;
     conv->function_(fnptr,sd); conv->lc_();
     init_vars=0;
@@ -1660,20 +1675,59 @@
     local_decl();
     control=1;
     cslabel = -1;
-    if(!chk) gen_enter1();
+    if (!inmode && !chk) gen_enter1();
     emit_init_vars();
     lfree_type_limit  = lfree;
     while(sym!=RC) statement(0);
     leave_scope();
 
     conv->function_end_(); conv->rc_();
-    if(!chk) gen_leave(control,n->nm);
+    if (inmode) {
+	set_attr(n,INLINE,reverse0(parse)); parse = 0;
+	inline_funcs = list2((int)n,inline_funcs);
+    } else {
+	if(!chk) gen_leave(control,n->nm);
+    }
     retpending = 0;
     control=0;
     arglist=0;
     lfree_type_limit  = 0;
 }
 
+/* generate function from parse tree */
+
+extern void
+pfdecl(NMTBL *n)
+{
+    int sd = stypedecl;
+
+    if(!chk) gen_enter(n->nm);
+    extrn_use(n);
+    local_static_list = &null_nptr;
+    retlabel=fwdlabel();
+
+    fnptr=n;
+    retcont = 0;
+    tmp_struct = 0;
+
+    arg_register(fnptr);
+    typedefed=0;
+    conv->function_(fnptr,sd); conv->lc_();
+    init_vars=0;
+
+    if(!chk) gen_enter1();
+
+    control=1;
+    cslabel = -1;
+
+    g_expr_u(pexpr(attr_value(n,INLINE)));
+    conv->function_end_(); conv->rc_();
+    if(!chk) gen_leave(control,n->nm);
+
+    retpending = 0;
+    control=0;
+}
+
 /*
     basic C statement
  */
@@ -1709,7 +1763,13 @@
     case BREAK:
 	checkret();
 	conv->break_();
-	if (control) gen_jmp(blabel);
+	if (control) {
+	    if (inmode) {
+		parse = list2(ST_BREAK,parse);
+	    } else {
+		gen_jmp(blabel);
+	    }
+	}
 	getsym(0);
 	checksym(SM);
 	return;
@@ -1738,21 +1798,25 @@
 	return;
 #endif
     default:
-	checkret();
+	if (!inmode)
+	    checkret();
 	if(sym==IDENT&&skipspc()==':') {
 	    dolabel();
 	    statement(use);
 	} else {
-	    if (use) {
-		lastexp = expr(0);
-		return;
+	    if (inmode) {
+		parse = list3(ST_COMP,parse,expr(0));
 	    } else {
-		slfree=lfree;
-		gexpr(expr(0),use);
-		set_lfree(slfree);
-		conv->sm_();
-		checksym(SM);
+		if (use) {
+		    lastexp = expr(0);
+		} else {
+		    slfree=lfree;
+		    gexpr(expr(0),use);
+		    set_lfree(slfree);
+		}
 	    }
+	    conv->sm_();
+	    checksym(SM);
 	}
     }
 }
@@ -1760,43 +1824,67 @@
 static void
 doif(void)
 {
-    int l1,l2,slfree;
+    int l1,l2,slfree,pparse;
     getsym(0);
     checksym(LPAR);
     conv->if_();
     slfree=lfree;
-    checkret();
-    l1 = bexpr(expr(0),0,fwdlabel());
+    if (inmode) {
+	pparse = parse; parse = 0;
+	l1 = expr(0);
+    } else {
+	checkret();
+	l1 = bexpr(expr(0),0,fwdlabel());
+    }
     set_lfree(slfree);
     conv->if_then_();
     checksym(RPAR);
     statement(0);
-    checkret();
+    if (inmode) {
+	l2 = reverse0(parse); parse = 0;
+    } else {
+	checkret();
+    }
     if(sym==ELSE) {
 	conv->if_else_();
-	if ((l2 = control))
-	    gen_jmp(l2=fwdlabel());
-	fwddef(l1);
-	getsym(0);
-	statement(0);
-	checkret();
-	if (l2) fwddef(l2);
+	if (inmode) {
+	    getsym(0);
+	    statement(0);
+	    parse = list3(ST_IF,pparse,list3(l1,l2,reverse0(parse)));
+	} else {
+	    if ((l2 = control))
+		gen_jmp(l2=fwdlabel());
+	    fwddef(l1);
+	    getsym(0);
+	    statement(0);
+	    checkret();
+	    if (l2) fwddef(l2);
+	}
+    } else {
+	if (inmode) {
+	    parse = list3(ST_IF,pparse,list3(l1,l2,0));
+	} else {
+	    fwddef(l1);
+	}
     }
-    else fwddef(l1);
     conv->if_endif_();
 }
 
 static void
 dowhile(void)
 {
-    int sbreak,scontinue,slfree,e;
+    int sbreak,scontinue,slfree,e,pparse;
 
     sbreak=blabel;
     scontinue=clabel;
-    blabel=fwdlabel();
-    control=1;
-    checkret();
-    clabel=backdef();
+    if (inmode) {
+	pparse = parse; parse=0;
+    } else {
+	blabel=fwdlabel();
+	control=1;
+	checkret();
+	clabel=backdef();
+    }
     conv->while_();
     getsym(0);
     checksym(LPAR);
@@ -1805,20 +1893,31 @@
     checksym(RPAR);
     conv->while_body_();
     if(sym==SM) {
-	bexpr(e,1,clabel);
+	if (inmode) {
+	    parse = list4(ST_WHILE,pparse,e,0);
+	} else {
+	    bexpr(e,1,clabel);
+	}
 	set_lfree(slfree);
 	conv->sm_();
 	getsym(0);
     } else {
-	bexpr(e,0,blabel);
+	if (!inmode) {
+	    bexpr(e,0,blabel);
+	}
 	set_lfree(slfree);
 	statement(0);
-	checkret();
-	if(control)
-	    gen_jmp(clabel);
+	if (inmode) {
+	    parse = list4(ST_WHILE,pparse,e,reverse0(parse));
+	} else {
+	    checkret();
+	    if(control)
+		gen_jmp(clabel);
+	}
     }
     conv->while_end_();
-    fwddef(blabel);
+    if (!inmode)
+	fwddef(blabel);
     clabel=scontinue;
     blabel=sbreak;
 }
@@ -1826,30 +1925,43 @@
 static void
 dodo(void)
 {
-    int sbreak,scontinue,l,slfree;
+    int sbreak,scontinue,l,slfree,pparse;
 
     sbreak=blabel;
     scontinue=clabel;
-    blabel=fwdlabel();
-    clabel=fwdlabel();
-    control=1;
-    checkret();
-    l=backdef();
+    if (inmode) {
+	parse = pparse; parse = 0;
+    } else {
+	blabel=fwdlabel();
+	clabel=fwdlabel();
+	control=1;
+	checkret();
+	l=backdef();
+    }
     conv->dowhile_();
     getsym(0);
     statement(0);
-    checkret();
-    fwddef(clabel);
+    if (inmode) {
+	l = reverse0(parse); parse =0;
+    } else {
+	checkret();
+	fwddef(clabel);
+    }
     checksym(WHILE);
     checksym(LPAR);
     slfree=lfree;
     conv->dowhile_cond_();
-    bexpr(expr(0),1,l);
+    if (inmode) {
+	parse = list4(ST_DO,pparse,expr(0),l);
+    } else {
+	bexpr(expr(0),1,l);
+    }
     set_lfree(slfree);
     checksym(RPAR);
     conv->dowhile_end_();
     checksym(SM);
-    fwddef(blabel);
+    if (!inmode)
+	fwddef(blabel);
     clabel=scontinue;
     blabel=sbreak;
 }
@@ -1857,6 +1969,7 @@
 static void
 dofor(void)
 {
+    int pparse,p0,p1;
     int l,e,slfree,dflag=0;
     int sbreak=blabel;
     int slimit = lfree_type_limit;
@@ -1864,7 +1977,11 @@
     int scontinue=clabel;
     init_vars = 0;
 
-    blabel=fwdlabel();
+    if (inmode) {
+	pparse = parse; parse=0;
+    } else {
+	blabel=fwdlabel();
+    }
     conv->for_();
     getsym(0);
     checksym(LPAR);
@@ -1876,28 +1993,44 @@
 	lfree_type_limit = lfree;
 	decl();
 	mode=STAT;
-	checkret();
+	if (inmode) {
+	    p0 = reverse0(parse); parse = 0;
+	} else {
+	    checkret();
+	}
 	emit_init_vars();
 	getsym(0);
     } else if(sym!=SM) {
-	checkret();
-	gexpr(expr(0),0);
+	if (inmode) {
+	    p0 = expr(0);
+	} else {
+	    checkret();
+	    gexpr(expr(0),0);
+	}
 	checksym(SM);
 	conv->for1_();
     } else {
+	p0 = 0;
 	conv->for1_();
 	getsym(0);
     }
     set_lfree(slfree);
     control=1;
-    checkret();
-    l=backdef();
+    if (!inmode) {
+	checkret();
+	l=backdef();
+    }
     if(sym!=SM) {
-	bexpr(expr(0),0,blabel);
+	if (inmode) {
+	    p1 = expr(0);
+	} else {
+	    bexpr(expr(0),0,blabel);
+	}
 	checksym(SM);
 	conv->for2_();
     } else {
 	conv->for2_();
+	p1 = 0;
 	getsym(0);
     }
     set_lfree(slfree);
@@ -1906,23 +2039,33 @@
 	conv->for_body_();
 	getsym(0);
 	statement(0);
-	checkret();
+	if (inmode) {
+	    e = 0;
+	} else {
+	    checkret();
+	}
     } else {
 	clabel=fwdlabel();
 	e=expr(0);
 	conv->for_body_();
 	checksym(RPAR);
 	statement(0);
-	checkret();
-	fwddef(clabel);
-	gexpr(e,0);
+	if (!inmode) {
+	    checkret();
+	    fwddef(clabel);
+	    gexpr(e,0);
+	}
 	set_lfree(slfree);
     }
     lfree_type_limit = slimit ;
     if (dflag) leave_scope();
     conv->for_end_();
-    gen_jmp(l);
-    fwddef(blabel);
+    if (inmode) {
+	parse = list3(ST_FOR,pparse,list4(p0,p1,e,reverse0(parse)));
+    } else {
+	gen_jmp(l);
+	fwddef(blabel);
+    }
     clabel=scontinue;
     blabel=sbreak;
     init_vars=sinit_vars;
@@ -1936,7 +2079,11 @@
 {
     int slimit = lfree_type_limit ;
     int sinit_vars = init_vars;
+    int pparse = parse;
     conv->lc_();
+    if (inmode) {
+	parse = 0;
+    }
     local_decl();
     emit_init_vars();
     lfree_type_limit = lfree;
@@ -1945,6 +2092,9 @@
     lfree_type_limit = slimit; 
     init_vars = sinit_vars;
     leave_scope();
+    if (inmode) {
+	parse = list3(ST_COMP,pparse,reverse0(parse));
+    }
     getsym(0);
 }
 
@@ -1956,12 +2106,18 @@
 doswitch(void)
 {
     int sbreak,scase,sdefault,slfree,svalue,slist;
-
-    checkret();
+    int pparse = parse,v;
+
+    if (inmode) {
+	parse = 0;
+    } else {
+	checkret();
+    }
     slist = cslist;
     cslist = 0;
     sbreak=blabel;      /* save parents break label */
-    blabel=fwdlabel();
+    if (!inmode)
+	blabel=fwdlabel();
     sdefault=dlabel;    /* save parents default label */
     dlabel=0;
     scase=cslabel;      /* save parents next case label */
@@ -1970,9 +2126,14 @@
     checksym(LPAR);
     slfree=lfree;
     svalue=csvalue1;      /* save parents switch value */
-    gexpr(expr(0),1);
+    if (inmode) {
+	v = expr(0);
+    } else {
+	gexpr(expr(0),1);
+    }
     if (!scalar(type)) error(EXERR);
-    csvalue1=csvalue() ;
+    if (!inmode)
+	csvalue1=csvalue() ;
     set_lfree(slfree);
     checksym(RPAR);
     conv->switch_body_();
@@ -1992,18 +2153,23 @@
     */
     statement(0);
     conv->switch_end_();
-    checkret();
+    if (inmode) {
+	parse = list4(ST_SWITCH,pparse,v,reverse0(parse));
+    } else {
+	checkret();
 #if CASE_CODE
-    if (control) gen_jmp(blabel);
-    genswitch(cslist,cslabel);
+	if (control) gen_jmp(blabel);
+	genswitch(cslist,cslabel);
 #else
-    if(dlabel) def_label(cslabel,dlabel);
-    else fwddef(cslabel);
+	if(dlabel) def_label(cslabel,dlabel);
+	else fwddef(cslabel);
 #endif
+    }
     csvalue1=svalue;
     cslabel=scase;
     dlabel=sdefault;
-    fwddef(blabel);
+    if (!inmode)
+	fwddef(blabel);
     blabel=sbreak;
     cslist = slist;
 }
@@ -2023,14 +2189,22 @@
 {
 #if CASE_CODE
     int l,clist=0,c;
-    l = fwdlabel();
+    if (!inmode)
+	l = fwdlabel();
     while(sym==CASE) {
 	conv->case_begin_(0,0);
 	getsym(0);
-	clist=glist3(cexpr(expr(1)),clist,l);
+	if (inmode)
+	    clist=list2(cexpr(expr(1)),clist);
+	else
+	    clist=glist3(cexpr(expr(1)),clist,l);
 	conv->case_(0,0);
 	checksym(COLON);
     }
+    if (inmode) {
+	parse = list3(ST_CASE,parse,clist);
+	return;
+    }
     if (retpending) {
 	ret(); retpending=0;
     }
@@ -2064,8 +2238,10 @@
     /* casading branch implementation */
     int c,l,slfree;
     l = 0;
-    if (retpending) { 
-	ret(); retpending=0;
+    if (!inmode) {
+	if (retpending) { 
+	    ret(); retpending=0;
+	}
     }
     slfree=lfree;
     c=0;
@@ -2076,6 +2252,10 @@
 	conv->case_(c,0);
 	checksym(COLON);
     }
+    if (inmode) {
+	parse = list3(ST_CASE,parse,clist);
+	return;
+    }
     l=fwdlabel();
     if (control) {
 	control=0;
@@ -2096,11 +2276,16 @@
 dodefault(void)
 {
     control=1;
-    checkret();
+    if (!inmode)
+	checkret();
     getsym(0);
     checksym(COLON);
     if (dlabel) error(STERR);  // double default:
-    dlabel = backdef();
+    if (inmode) {
+	parse = list2(ST_DEFAULT,parse);
+    } else {
+	dlabel = backdef();
+    }
     conv->case_(0,1);
 }
 
@@ -2109,39 +2294,45 @@
 {
     int slfree,e,e1;
 
-    if (!cslabel) gen_jmp(cslabel = fwdlabel());
+    if (!inmode && !cslabel) gen_jmp(cslabel = fwdlabel());
     if(getsym(0)==SM) {
 	// should check fnptr have no return value
 	conv->return_();
 	conv->return_end_();
 	getsym(0);
+	if (inmode)
+	    parse = list3(ST_RETURN,parse,0);
 	retpending = 1;
 	return;
     }
     conv->return_();
-    slfree=lfree;
-    if (struct_return) {
-	e = expr(0);
-	if ((car(type)==STRUCT || car(type)==UNION)&&
-		size(type)==cadr(struct_return)) {
-	    if(car(e)==RSTRUCT && car(cadr(e))==FUNCTION) {
-                /* pass the return pointer to the called function */
-		replace_return_struct(cadr(e),
-		    rvalue_t(car(struct_return),caddr(struct_return)));
-		gexpr(cadr(e),0);
+    if (!inmode) {
+	slfree=lfree;
+	if (struct_return) {
+	    e = expr(0);
+	    if ((car(type)==STRUCT || car(type)==UNION)&&
+		    size(type)==cadr(struct_return)) {
+		if(car(e)==RSTRUCT && car(cadr(e))==FUNCTION) {
+		    /* pass the return pointer to the called function */
+		    replace_return_struct(cadr(e),
+			rvalue_t(car(struct_return),caddr(struct_return)));
+		    gexpr(cadr(e),0);
+		} else {
+		    type = caddr(struct_return);
+		    // e1 = rvalue_t(cadr(struct_return),INT); /* size */
+		    e1 = cadr(struct_return); /* size */
+		    gexpr(list4(STASS,rvalue(car(struct_return)),e,e1),0);
+		}
 	    } else {
-		type = caddr(struct_return);
-		// e1 = rvalue_t(cadr(struct_return),INT); /* size */
-		e1 = cadr(struct_return); /* size */
-		gexpr(list4(STASS,rvalue(car(struct_return)),e,e1),0);
+		error(TYERR); /* should check compatible */
 	    }
 	} else {
-	    error(TYERR); /* should check compatible */
+	    gexpr(correct_type(expr(0),cadr(fnptr->ty)),1);
 	}
+	set_lfree(slfree);
     } else {
-	gexpr(correct_type(expr(0),cadr(fnptr->ty)),1);
+	parse = list3(ST_RETURN,parse,expr(0));
     }
-    set_lfree(slfree);
     conv->return_end_();
     checksym(SM);
     /* control = 0; still control continue until pending return emission */
@@ -2154,14 +2345,19 @@
     NMTBL *nptr0;
     int t,e1,e2,env;
 
-    checkret();
+    if (!inmode)
+	checkret();
     conv->goto_();
     getsym(0);
     e1 = expr(0);
     t=car(e1);
     if (type==VOID) {
 	if (car(e1)==RINDIRECT) {
-	    gen_indirect_goto(cadr(e1));
+	    if (inmode) {
+		parse = list3(ST_GOTO,parse,e1);
+	    } else {
+		gen_indirect_goto(cadr(e1));
+	    }
 	} else error(TYERR);
 	checksym(SM);
 	return;
@@ -2170,11 +2366,17 @@
 	nptr0 = (NMTBL *)cadr(e1);
 	t = nptr0->sc;
 	if (t==EMPTY||t==EXTRN1||t==EXTRN) {
+	    // error check?
 	    nptr0->sc=EMPTY;
 	    nptr0=l_top_search(nptr0->nm,0);
 	    nptr0->sc = FLABEL;
-	    gen_jmp(nptr0->dsp = fwdlabel());
-	} else if (t==FLABEL||t==BLABEL) {
+	    nptr0->dsp = fwdlabel();
+	} else if (!(t==FLABEL||t==BLABEL)) {
+	    error(STERR);
+	}
+	if (inmode) {
+	    parse = list3(ST_GOTO,parse,e1);
+	} else {
 	    gen_jmp(nptr0->dsp);
 	}
 	control=0;
@@ -2203,7 +2405,11 @@
 	    if (nptr0->ty>0&&car(nptr0->ty)==FUNCTION)
 		car(nptr0->ty)=CODE;
 	}
-	gexpr(list3(CODE,e1,env),0);
+	if (inmode) {
+	    parse = list3(ST_GOTO,parse,list3(CODE,e1,env));
+	} else {
+	    gexpr(list3(CODE,e1,env),0);
+	}
 	control=0;
 	conv->sm_();
 	checksym(SM);
@@ -2218,15 +2424,25 @@
 {
     NMTBL *nptr1;
     control=1;
-    checkret();
-    if(nptr->sc == FLABEL)
-	fwddef(nptr->dsp);
-    else if(nptr->sc != EMPTY && nptr->sc != EXTRN1)
+    if (!inmode)
+	checkret();
+    if(nptr->sc == FLABEL) {
+	if (inmode)
+	    parse = list3(ST_LABEL,parse,(int)nptr);
+	else
+	    fwddef(nptr->dsp);
+    } else if(nptr->sc != EMPTY && nptr->sc != EXTRN1)
 	error(TYERR);
-    nptr->sc=EMPTY;
-    nptr1=l_top_search(nptr->nm,0);
-    nptr1->sc = BLABEL;
-    nptr1->dsp = backdef();
+    } else {
+	nptr->sc=EMPTY;
+	nptr1=l_top_search(nptr->nm,0);
+	nptr1->sc = BLABEL;
+	if (inmode) {
+	    parse = list3(ST_LABEL,parse,(int)nptr1);
+	} else {
+	    nptr1->dsp = backdef();
+	}
+    }
     conv->label_();
     getsym(0);
     checksym(COLON);
@@ -2243,7 +2459,8 @@
     int e1 = 0, asm0 = 0, input = 0, out = 0, opt = 0;
     int e;
 
-    checkret();
+    if (!inmode)
+	checkret();
     getsym(0);
     if (sym==VOLATILE) getsym(0);
     checksym(LPAR);
@@ -2283,7 +2500,11 @@
 	} while(sym==COMMA);
     }
     checksym(RPAR);
-    gexpr(list3(ASM,list4(asm0,input,out,opt),e1),0);
+    if (inmode) {
+	parse = list4(ST_ASM,parse,list4(asm0,input,out,opt),e1);
+    } else {
+	gexpr(list3(ASM,list4(asm0,input,out,opt),e1),0);
+    }
     checksym(SM);
 }
 #endif
@@ -2972,18 +3193,25 @@
             // l2 is not defined and generates undefined error.
 	    // cntl may prevent this.
 	    int l,b,l2,cntl=control;
-	    if (cntl) {
-		gen_jmp(l=fwdlabel());
-	    } else l = 0;
-	    b = backdef();
-	    docomp(1);
-	    if (cntl) {
-		gen_jmp(l2=fwdlabel());
-	    } else l2 = 0;
-	    e1 = list3(COMMA,list3(LCALL,b,l2),lastexp);
-	    lastexp = 0;
-	    if (l) fwddef(l);
-	    control=cntl;
+	    if (inmode) {
+		int sparse = parse; parse = 0;
+		docomp(1);
+		e1 = list3(ST_COMP,0,parse);
+		parse = sparse;
+	    } else {
+		if (cntl) {
+		    gen_jmp(l=fwdlabel());
+		} else l = 0;
+		b = backdef();
+		docomp(1);
+		if (cntl) {
+		    gen_jmp(l2=fwdlabel());
+		} else l2 = 0;
+		e1 = list3(COMMA,list3(LCALL,b,l2),lastexp);
+		lastexp = 0;
+		if (l) fwddef(l);
+		control=cntl;
+	    }
 	} else {
 	    e1=expr0();
 	    conv->rpar_();
@@ -3025,7 +3253,10 @@
 	    getsym(0);
 	} else break;
     }
-    if(car(e1)==FNAME) type=list2(POINTER,type);
+    if(car(e1)==FNAME) {
+	set_attr((NMTBL*)cadr(e1),FNAME,1);
+	type=list2(POINTER,type);
+    }
     return e1;
 }
 
@@ -3079,7 +3310,8 @@
     /* return type */
 
     type = cadr(ftype); 
-    if(type==CHAR) type=INT;
+    if(type==CHAR||type==SHORT) type=INT;
+    else if(type==UCHAR||type==USHORT) type=UNSIGNED;
     else if(car(type)==STRUCT||car(type)==UNION) {
 	/* make temporary struct for return value */
 	/* but it is better to see we can reuse old one */
@@ -3105,6 +3337,14 @@
 
 	arglist = append3(arglist,list2(ADDRESS,e),list2(POINTER,type));
     }
+    if (car(e1)==FNAME) {
+	if (is_inline((NMTBL *)cadr(e1))) {
+	    if (inmode)
+		return list4(INLINE,e1,arglist,ftype);
+	    else /* partial evaluation */
+		return pexpr(list4(INLINE,e1,arglist,ftype));
+	}
+    }
     return list4(FUNCTION,e1,arglist,ftype);
 }
 
@@ -4070,13 +4310,17 @@
     switch (mode) {
 	case GDECL: case GSDECL: case GUDECL: case GTDECL:
 	case MDECL: case ADECL: case LSDECL: case LUDECL: case GEDECL:
-	case INLINE:
-	e=gfree;
-	gfree+=n;
+	    e=gfree;
+	    gfree+=n;
 	break;
     default:
-	lfree-=n;
-	e=lfree;
+	if (inmode) {
+	    e=gfree;
+	    gfree+=n;
+	} else {
+	    lfree-=n;
+	    e=lfree;
+	}
     }
     if(lfree<gfree) error(HPERR);
     return e;
@@ -4247,6 +4491,53 @@
     return p1;
 }
 
+extern int
+has_attr(NMTBL *n,int attr)
+{
+    int e;
+    if (!n) return 0;
+    e = n->attr;
+    for(;e;e=cadr(e)) {
+	if (car(e)==attr) return 1;
+    }
+    return 0;
+}
+
+extern int
+attr_value(NMTBL *n,int attr)
+{
+    int e;
+    if (!n) return 0;
+    e = n->attr;
+    for(;e;e=cadr(e)) {
+	if (car(e)==attr) return caddr(e);
+    }
+    return 0;
+}
+
+extern void
+set_attr(NMTBL *n,int attr,int value)
+{
+    int e;
+    if (!n) error(-1);
+    e = n->attr;
+    for(;e;e=cadr(e)) {
+	if (car(e)==attr) {
+	    caddr(e) = value;
+	    return;
+	}
+    }
+    switch (n->sc) {
+    case LVAR:
+	n->attr = list3(attr,n->attr,value);
+	break;
+    default:
+	n->attr = glist3(attr,n->attr,value);
+	break;
+    }
+    return;
+}
+
 extern void
 display_ntable(NMTBL *n, char *s)
 {
--- a/mc-parse.h	Mon Nov 29 04:15:38 2004 +0900
+++ b/mc-parse.h	Tue Nov 30 02:20:42 2004 +0900
@@ -27,6 +27,7 @@
 extern int lastexp;         /* last expression in statement expressoin */
 extern int debug;           /* debug flag */
 extern int decl_str_init;   /* partial structure initializer */
+extern int inline_funcs;    /* inline function list */
 
 extern int parse;   /* parse tree */
 
@@ -110,6 +111,10 @@
 extern void extern_define(char *s,int d,int type,int use);
 extern void set_lfree(int save);
 
+extern int has_attr(NMTBL *n,int attr);
+extern int attr_value(NMTBL *n,int attr);
+extern void set_attr(NMTBL *n,int attr,int value);
+
 #if LONGLONG_CODE
 extern int llist2(int e1, long long d1);
 #endif
@@ -144,5 +149,6 @@
 extern struct cheap * increment_cheap(struct cheap *cheap,char **save);
 extern void save_cheap(struct cheap *scheap,struct cheap *cheap);
 extern struct cheap * reset_cheap(struct cheap *scheap);
+extern void pfdecl(NMTBL *nptr);
 
 /* end */
--- a/mc.h	Mon Nov 29 04:15:38 2004 +0900
+++ b/mc.h	Tue Nov 30 02:20:42 2004 +0900
@@ -386,6 +386,29 @@
 
 /* tree node tags end */
 
+/* statement start */
+
+#define ST_DECL		110
+#define ST_IF		111
+#define ST_DO		112
+#define ST_WHILE	113
+#define ST_FOR		114
+#define ST_SWITCH	115
+#define ST_COMP		116
+#define ST_BREAK	117
+#define ST_CONTINUE	118
+#define ST_CASE		119
+#define ST_DEFAULT	120
+#define ST_RETURN	121
+#define ST_GOTO		122
+#define ST_ASM		123
+#define ST_LABEL	124
+#define ST_COMMENT	125
+
+#define IS_STATEMENT(i) (ST_DECL<=i&&i<=ST_COMMENT)
+
+/* statement end */
+
 /* error number start */
 
 #define FILERR  1
@@ -416,6 +439,7 @@
 #define NMERR   26
 #define MMERR   27
 #define INERR   28
+#define ILERR   29
 
 /* error number end */