changeset 445:5ec2a88b9f4d const-attribute

const
author kono
date Sun, 21 Nov 2004 19:20:18 +0900
parents 8bec605d1701
children 6654aa80851b
files .gdbinit Changes Makefile mc-code-arm.c mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-codegen.c mc-codegen.h mc-parse.c mc-parse.h mc.h
diffstat 12 files changed, 209 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Sun Nov 21 11:20:56 2004 +0900
+++ b/.gdbinit	Sun Nov 21 19:20:18 2004 +0900
@@ -1,5 +1,5 @@
 tb main
-run  -s test/arg.c
+run  -s test/inline.c
 # run  -s mc-parse.c
 # run  -s mc-codegen.c
 # run  -s nkf203/nkf.c
--- a/Changes	Sun Nov 21 11:20:56 2004 +0900
+++ b/Changes	Sun Nov 21 19:20:18 2004 +0900
@@ -6695,3 +6695,26 @@
 unsigned になったり。
 
 size < int のstruct の値の渡し方がおかしい
+
+Sun Nov 21 13:02:09 JST 2004
+
+gexpr に parse = list2(expr,parse); するオプションを付ければ、
+inline の手間は少なくてすむかも。
+
+static でないと実体も出力する必要があるわけね。
+
+const, volatile がないと大した最適化ができない。まぁ、あんまり
+やらないつもりなんだけど。
+
+const, volatile は型にするとめんどー。だけど、C にそうなら型だろう。
+storage class でいいなら簡単なんだけど。sc を bitmask にするか。
+       extern (or static)
+       extern used
+       const
+
+attr には、INLINE, CONST, VOLATILE がとりあえずはいる。
+
+定数の大域変数と局所変数の初期化された値をどこかにとっておく必要がある。
+どこ? dsp? attr?
+
+address の引き算が間違ってる。
--- a/Makefile	Sun Nov 21 11:20:56 2004 +0900
+++ b/Makefile	Sun Nov 21 19:20:18 2004 +0900
@@ -5,6 +5,7 @@
 # LDFLAGS = -pg
 # for Linux Zaurus
 # CFLAGS = -fsigned-char -pipe -g -I. -I/home/zaurus/develop/include
+CFLAGS1 = -g  -I.
 BASE=0
 STAGE=1
 MFLAGS=$(MFALGS) BASE=$(BASE) STAGE=$(STAGE)
@@ -118,7 +119,7 @@
 #	-./$(MC) -Itest/ -s $(TARGET).c
 
 check: $(MC) $(TARGET).c
-	-gcc $(CFLAGS) $(STDFLAG) $(TARGET).c -o b.out $(MLIB)
+	-gcc $(CFLAGS1) $(STDFLAG) $(TARGET).c -o b.out $(MLIB)
 	-./b.out > $(TARGET).gcc.out
 	-./$(MC) -s $(TARGET).c
 	-gcc $(TARGET).s $(MLIB)
--- a/mc-code-arm.c	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-code-arm.c	Sun Nov 21 19:20:18 2004 +0900
@@ -851,7 +851,7 @@
 	}
     }
 not_found:
-    return list2(LVAR,new_lvar(SIZE_OF_LONGLONG));
+    return list3(LVAR,new_lvar(SIZE_OF_LONGLONG),0);
 }
 
 void
@@ -1161,7 +1161,7 @@
 	    return list3(REGISTER,j,(int)n); 
 	}
     }
-    return list2(LVAR,new_lvar(SIZE_OF_INT));
+    return list3(LVAR,new_lvar(SIZE_OF_INT),0);
 }
 
 #define freg_var_num(i) (FREG_VAR_BASE+i+FREG_OFFSET)
@@ -1181,7 +1181,7 @@
 	    }
 	}
     }
-    return list2(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT));
+    return list3(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT),0);
 }
 
 int
@@ -2211,7 +2211,7 @@
 	    len = size(n->ty); len = round4(len);
 	    for(;len>0 && reg_var<MAX_INPUT_REGISTER_VAR;len-=SIZE_OF_INT) {
 		reg_var++;
-		g_expr_u(assign_expr0(list2(LVAR,offset),
+		g_expr_u(assign_expr0(list3(LVAR,offset,0),
 			list3(REGISTER,reg_var,0),INT,INT));
 		arg_on_register += SIZE_OF_INT;
 		free_register(reg);
@@ -2222,7 +2222,7 @@
     if (dots) {
         while ((reg = get_input_register_var(reg_var,0,0))) {
             g_expr_u(assign_expr0(
-                list2(LVAR,offset),reg,INT,INT));
+                list3(LVAR,offset,0),reg,INT,INT));
             offset+=SIZE_OF_INT;
             reg_var++;
 	    arg_on_register += SIZE_OF_INT;
@@ -2436,35 +2436,35 @@
 	if (mode==AS_SAVE) {
 	    return get_register_var(0);
 	} else if (reg_arg+1>MAX_INPUT_REGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else 
 	    return get_input_register_var(reg_arg,0,0);
     } else if (t==LONGLONG||t==ULONGLONG) {
 	if (mode==AS_SAVE) {
 	    return get_lregister_var(0);
 	} else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR)  {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_lregister_var(reg_arg,0,0);
     } else if (t==FLOAT) {
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,0);
 	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_dregister_var(freg_arg,0,0,0);
     } else if (t==DOUBLE) {
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,1);
 	} else if (reg_arg+1>=MAX_INPUT_DREGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_dregister_var(reg_arg,0,0,1);
     } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
 	if (mode==AS_SAVE) {
 	    return get_register_var(0);
 	} else
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
     } else {
 	error(-1);
 	return get_register_var(0);
@@ -2628,7 +2628,7 @@
 	//  half register case writes *(sp-1) but it will be Ok.
 	if (max_func_args<4) max_func_args=4;
 	g_expr_u(assign_expr0(list3(REGISTER,4,0),
-		list2(LVAR,caller_arg_offset_v(3)),INT,INT));
+		list3(LVAR,caller_arg_offset_v(3)),INT,INT),0);
 	use_input_reg(4,1);
     }
     nargs = reg_arg = freg_arg = 0;
--- a/mc-code-ia32.c	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-code-ia32.c	Sun Nov 21 19:20:18 2004 +0900
@@ -413,7 +413,7 @@
 	reg_var=2; regvar[0]=h; regvar[1]=l;
 	return list2(LREGISTER,REG_L);
     }
-    return list2(LVAR,new_lvar(SIZE_OF_LONGLONG));
+    return list3(LVAR,new_lvar(SIZE_OF_LONGLONG),0);
 }
 
 int 
@@ -605,13 +605,13 @@
             return list3(REGISTER,i,(int)nptr); /* その場所を表す番号を返す */
         }
     }
-    return list2(LVAR,new_lvar(SIZE_OF_INT));
+    return list3(LVAR,new_lvar(SIZE_OF_INT),0);
 }
 
 int
 get_dregister_var(NMTBL *nptr,int d)
 {
-    return list2(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT));
+    return list3(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT),0);
 }
 
 void 
@@ -717,14 +717,14 @@
     if (type==INT) {
         xreg = reg_stack[reg_sp];
         if (xreg<= -REG_LVAR_OFFSET) {
-            return list2(LVAR,REG_LVAR_OFFSET+xreg);
+            return list3(LVAR,REG_LVAR_OFFSET+xreg,0);
         } else {
             return list2(REGISTER,xreg);
         }
     } else {
         xreg = freg_stack[freg_sp];
         if (xreg<= -REG_LVAR_OFFSET) {
-            return list2(LVAR,REG_LVAR_OFFSET+xreg);
+            return list3(LVAR,REG_LVAR_OFFSET+xreg,0);
         } else {
             return list2(DREGISTER,xreg);
         }
--- a/mc-code-mips.c	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-code-mips.c	Sun Nov 21 19:20:18 2004 +0900
@@ -773,7 +773,7 @@
 	}
     }
 not_found:
-    return list2(LVAR,new_lvar(SIZE_OF_LONGLONG));
+    return list3(LVAR,new_lvar(SIZE_OF_LONGLONG),0);
 }
 
 void
@@ -1094,7 +1094,7 @@
 	    return list3(REGISTER,j,(int)n); 
 	}
     }
-    return list2(LVAR,new_lvar(SIZE_OF_INT));
+    return list3(LVAR,new_lvar(SIZE_OF_INT),0);
 }
 
 #define freg_var_num(i) (FREG_VAR_BASE-i+FREG_OFFSET)
@@ -1121,7 +1121,7 @@
 	    return list3(FREGISTER,j,(int)n); 
         }
     }
-    return list2(LVAR,new_lvar(SIZE_OF_DOUBLE));
+    return list3(LVAR,new_lvar(SIZE_OF_DOUBLE),0);
 }
 
 int
@@ -1815,7 +1815,7 @@
 	    continue;
 	}
 	n->sc  = LVAR;
-	g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),t,t));
+	g_expr_u(assign_expr0(list3(LVAR,n->dsp,0),list3(tag,reg,(int)n),t,t));
 	if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) {
 	    free_register(reg);
 	}
@@ -1823,7 +1823,7 @@
     if (dots) {
         while ((reg = get_input_register_var(reg_var,0,0))) {
             g_expr_u(assign_expr0(
-                list2(LVAR,offset),reg,INT,INT));
+                list3(LVAR,offset,0),reg,INT,INT));
             offset+=SIZE_OF_INT;
             reg_var++;
         }
@@ -1987,7 +1987,7 @@
 	if (mode==AS_SAVE) {
 	    return get_register_var(0);
 	} else if (reg_arg+1>MAX_INPUT_REGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else 
 	    return get_input_register_var(reg_arg,0,0);
     } else if (t==LONGLONG||t==ULONGLONG) {
@@ -1996,14 +1996,14 @@
 	if (mode==AS_SAVE) {
 	    return get_lregister_var(0);
 	} else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR)  {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_lregister_var(reg_arg,0,0);
     } else if (t==FLOAT) {
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,0);
 	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_dregister_var(freg_arg,0,0,0);
     } else if (t==DOUBLE) {
@@ -2012,14 +2012,14 @@
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,1);
 	} else if (reg_arg+1>=MAX_INPUT_DREGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_dregister_var(reg_arg,0,0,1);
     } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
 	if (mode==AS_SAVE) {
 	    return get_register_var(0);
 	} else
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
     } else {
 	error(-1);
 	return get_register_var(0);
--- a/mc-code-powerpc.c	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-code-powerpc.c	Sun Nov 21 19:20:18 2004 +0900
@@ -701,7 +701,7 @@
 	}
     }
 not_found:
-    return list2(LVAR,new_lvar(SIZE_OF_LONGLONG));
+    return list3(LVAR,new_lvar(SIZE_OF_LONGLONG),0);
 }
 
 void
@@ -1005,7 +1005,7 @@
 	    return list3(REGISTER,REG_VAR_BASE-i,(int)n); 
 	}
     }
-    return list2(LVAR,new_lvar(SIZE_OF_INT));
+    return list3(LVAR,new_lvar(SIZE_OF_INT),0);
 }
 
 int
@@ -1021,7 +1021,7 @@
 		FREG_VAR_BASE-i+FREG_OFFSET,(int)n); 
         }
     }
-    return list2(LVAR,new_lvar(SIZE_OF_DOUBLE));
+    return list3(LVAR,new_lvar(SIZE_OF_DOUBLE),0);
 }
 
 int
@@ -1752,9 +1752,9 @@
 	    continue;
 	}
 	n->sc  = LVAR;
-	lvar = list2(LVAR,n->dsp);
+	lvar = list3(LVAR,n->dsp,0);
 	g_expr_u(assign_expr0(
-	    list2(LVAR,n->dsp),list3(tag,reg,(int)n),n->ty,t));
+	    list3(LVAR,n->dsp,0),list3(tag,reg,(int)n),n->ty,t));
 	if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) {
 	    free_register(reg);
 	}
@@ -1762,7 +1762,7 @@
     if (dots) {
 	while ((reg = get_input_register_var(reg_var,0,0))) {
 	    g_expr_u(assign_expr0(
-		list2(LVAR,offset),reg,INT,INT));
+		list3(LVAR,offset,0),reg,INT,INT));
 	    offset+=SIZE_OF_INT;
 	    reg_var++;
 	}
@@ -1884,35 +1884,35 @@
 	if (mode==AS_SAVE) {
 	    return get_register_var(0);
 	} else if (reg_arg>=MAX_INPUT_REGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else 
 	    return get_input_register_var(reg_arg,0,0);
     } else if (t==LONGLONG||t==ULONGLONG) {
 	if (mode==AS_SAVE) {
 	    return get_lregister_var(0);
 	} else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR)  {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_lregister_var(reg_arg,0,0);
     } else if (t==FLOAT) {
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,0);
 	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_dregister_var(freg_arg,0,0,0);
     } else if (t==DOUBLE) {
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,1);
 	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
 	} else
 	    return get_input_dregister_var(freg_arg,0,0,1);
     } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
 	if (mode==AS_SAVE) {
 	    return get_register_var(0);
 	} else
-	    return list2(LVAR,caller_arg_offset_v(nargs));
+	    return list3(LVAR,caller_arg_offset_v(nargs),0);
     } else {
 	error(-1);
 	return get_register_var(0);
@@ -2107,11 +2107,11 @@
 		if (dots) {
 		    if (car(e4)==DRLVAR) {
 			special_lvar = cadr(e4);
-			e5 = list2(LVAR,special_lvar);
+			e5 = list3(LVAR,special_lvar,0);
 		    } else {
 			special_lvar = new_lvar(SIZE_OF_DOUBLE);
 			g_expr(assign_expr0(
-			    (e5=list2(LVAR,special_lvar)),e4,DOUBLE,t));
+			    (e5=list3(LVAR,special_lvar,0)),e4,DOUBLE,t));
 			reg_arg_list = list2(e5,reg_arg_list);
 			e4 = list2(DREGISTER,freg);
 			/* freg should not change until XXX */
@@ -2128,7 +2128,7 @@
 		    reg_arg_list = list2(r1,reg_arg_list);
 		    arg_assign = list2( assign_expr0(r0,e5,INT,INT), arg_assign);
 		    arg_assign = list2( assign_expr0(r1,
-			    list2(LVAR,special_lvar+SIZE_OF_INT),
+			    list3(LVAR,special_lvar+SIZE_OF_INT,0),
 			    INT,INT), arg_assign);
 		}
 	    }
@@ -2138,7 +2138,7 @@
                    stack value. You are crazy.
                  */
 		arg_assign = list2(
-		    assign_expr0(list2(LVAR,caller_arg_offset_v(nargs)),
+		    assign_expr0(list3(LVAR,caller_arg_offset_v(nargs),0),
 			    get_input_dregister_var(freg_arg,0,0,1),t,t),
 		    arg_assign);
 	    }
--- a/mc-codegen.c	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-codegen.c	Sun Nov 21 19:20:18 2004 +0900
@@ -786,8 +786,8 @@
 	error(-1);
     }
     n->sc  = LVAR;
-    lvar = list2(LVAR,n->dsp);
-    g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),t,t));
+    lvar = list3(LVAR,n->dsp,(int)n);
+    g_expr_u(assign_expr0(list3(LVAR,n->dsp,(int)n),list3(tag,reg,(int)n),t,t));
     if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) {
 	free_register(reg);
     return g_expr0(lvar);
@@ -928,7 +928,7 @@
 	*target = append4(*target,t,ty,e1);
 #endif
     } else {
-	g_expr_u(assign_expr0((e1=list2(LVAR,new_lvar(sz))),s,ty,ty));
+	g_expr_u(assign_expr0((e1=list3(LVAR,new_lvar(sz),0)),s,ty,ty));
 	*target = append4(*target,t,ty,e1);
 	*use=list3(t,*use,e1);
     }
@@ -1132,7 +1132,7 @@
 	    target=list4(r, target,ty,e2); regs+=2;
 	} else {
 	    while(car(e2)==RSTRUCT) e2=cadr(e2);
-	    target=list4(list2(LVAR,0), target,ty,e2);
+	    target=list4(list3(LVAR,0,0), target,ty,e2);
 	}
         /* keep arg space for register variables */
         arg_size += sz;
@@ -1161,7 +1161,7 @@
 	}
         arg_size-=sz;
 	if (!is_simple(car(s0))) {
-	    g_expr_u(assign_expr0((e4=list2(LVAR,new_lvar(sz))),s0,ty,ty));
+	    g_expr_u(assign_expr0((e4=list3(LVAR,new_lvar(sz),0)),s0,ty,ty));
 	    use=list3(ty,use,e1);
 	    cadddr(e2)=e4;
 	    s0=e4;
@@ -1201,8 +1201,8 @@
 		    default: caddr(e2) = UNSIGNED; r = 4;
 		    }
 		    if (e4==4) e3=cadr(e2);
-		    car(e2) =  list2(LVAR,cadr(t0)+e4);
-		    cadddr(e2) = list2(LVAR,cadr(s0)+e4);
+		    car(e2) =  list3(LVAR,cadr(t0)+e4,0);
+		    cadddr(e2) = list3(LVAR,cadr(s0)+e4,0);
 		    source=list3( cadddr(e2), source,r);
 		    e4 += r;
 #if DEBUG_PARALLEL_ASSIGN
@@ -2071,7 +2071,7 @@
 	}
 	/*  new = &e2 */
 	/*  *new = *new op e3 */
-	n = list2(LVAR,new_lvar(size_of_int));
+	n = list3(LVAR,new_lvar(size_of_int),0);
 	g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT));
 	g_expr(assign_expr0(list2(INDIRECT,n),list3(op,n,e3),t,t));
 	free_lvar(cadr(n));
@@ -2161,7 +2161,7 @@
 	}
 	/*  new = &e2 */
 	/*  *new = *new op e3 */
-	n = list2(LVAR,new_lvar(size_of_int));
+	n = list3(LVAR,new_lvar(size_of_int),0);
 	g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT));
 	g_expr(assign_expr0(list2(INDIRECT,n),
 			list3(op,list2(LRINDIRECT,n),e3),t,t));
@@ -2442,7 +2442,7 @@
  */
 
 extern NMTBL *
-def(NMTBL *n)
+def(NMTBL *n,int ctmode)
 {
     int sz,nsc,ndsp;
     int sbit_f = bit_field_disp;
@@ -2458,14 +2458,16 @@
     if(type>0&&(car(type)==FUNCTION || car(type)==CODE)) {
 	if ((mode==GDECL)) {
 	    fcheck(n);
+	    n->attr = ctmode;
 	    return n;
 	    /* function and code segment are defined using fdecl/code_decl */
             /* in decl() */
 	}
     }
     if (mode==GSDECL||mode==LSDECL) {
-          /* Struct fields name lists are in the struct type or tag. */
-          /* Only name in the table is used. Do not set n->ty! */
+        /* Struct fields name lists are in the struct type or tag. */
+        /* Only name in the table is used. Do not set n->ty! */
+	/* Struct field may volatile... where do I put? list2(VOLATILE,type)? */
 	if (car(type)==BIT_FIELD) {
 	    bit_field_disp=sbit_f;   // default is 0, recover only here.
             //        type = list4(BIT_FIELD,value type,
@@ -2526,6 +2528,7 @@
 	    }
 	}
 	gpc +=sz;
+	n->attr = list2(ctmode,0);
 	return n;
     case GSDECL: case LSDECL:
 	disp += sz;
@@ -2578,6 +2581,7 @@
 	} else {
 	    n->ty = type;
 	}
+	n->attr = ctmode;
 	return n;
     case STAT: /* return (struct hoge)f() case? */
     case LDECL:
@@ -2603,12 +2607,14 @@
 	}
 	n->sc = nsc;
 	n->dsp = ndsp;
+	n->attr = list2(ctmode,0);
 	return n;
     default:
 	error(DCERR);
     }
     n->sc = nsc;
     n->dsp = ndsp;
+    n->attr = list2(ctmode,0);
     if (stmode==EXTRN)
 	n->sc = EXTRN;
     return n;
@@ -2723,10 +2729,13 @@
 	    /* empty space in partial initialization */
 	    return offset+cadr(e);
 	}
+	/* If this is a local declared constant, we don't have to assign.
+           But some one may take it's address. We have to generate assign.
+         */
 	ass = assign_expr0(
     (n->sc==REGISTER||n->sc==DREGISTER||n->sc==FREGISTER||n->sc==LREGISTER)?
 	    list3(n->sc,n->dsp,(int)n):
-	    list2(LVAR,n->dsp+offset),
+	    list3(LVAR,n->dsp+offset,0),
 	e,t,type);
 	init_vars = list2(ass,init_vars);
     } else if(mode==SFDINIT) {
@@ -2744,6 +2753,10 @@
 #endif
 	return offset+sz;
     }
+    /* constant value field */
+    if (offset==0 && n && car(n->attr)==KONST) {
+	cadr(n->attr) = e;
+    }
     return offset+((t==EMPTY)?cadr(e):size(t));
 }
 
@@ -2799,6 +2812,7 @@
 	    n1->dsp = n->dsp;
 	    n->ty =  n1->ty;
 	    n->sc =  n1->sc;
+	    n->attr =  n1->attr;
 	    cadddr(j)=sz= cadddr(i);
 	    if (sz==1||sz==size_of_short) sz = size_of_int;
 	    dsp += sz;
@@ -2847,8 +2861,8 @@
 	if ((sz=size(cadr(fntype)))==-1) error(TYERR);
 	else {
 	    args = 0;
-	    def(&str_ret);
-	    struct_return = list3(list2(LVAR,str_ret.dsp),sz,type);
+	    def(&str_ret,0);
+	    struct_return = list3(list3(LVAR,str_ret.dsp,0),sz,type);
 	    caddr(fnptr->ty) = glist2(POINTER,caddr(fnptr->ty));
 	}
 	type = type_save;
@@ -2954,6 +2968,7 @@
 rvalue(int e)
 {
     int op;
+    NMTBL *n;    
 
     if (e==0) error(-1);
     op = 0;
@@ -3000,9 +3015,17 @@
     }
     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);
+	}
 	return(list3(RGVAR+op,cadr(e),caddr(e)));
     case LVAR:
-	return(list2(RLVAR+op,cadr(e)));
+	n = (NMTBL*)caddr(e);
+	if (n && car(n->attr)==KONST) {
+	    if (cadr(n->attr)) return cadr(n->attr);
+	}
+	return(list3(RLVAR+op,cadr(e),caddr(e)));
     case INDIRECT:
 	return(indirect(RINDIRECT+op,cadr(e)));
     default:return(e); /* idempotent case? */
@@ -3096,7 +3119,7 @@
 	    e=list3(GVAR,cadr(e)+dsp,caddr(e));
 	    break;
 	case LVAR:
-	    e=list2(LVAR,cadr(e) + dsp);
+	    e=list3(LVAR,cadr(e) + dsp,0);  /* may have attribute */
 	    break;
 	case INDIRECT:
 	    e=list2(INDIRECT,list3(ADD,cadr(e),list2(CONST,dsp)));
@@ -3337,8 +3360,13 @@
     int e=0;
     int us = 0;
 
-    if(t1>0&&car(t1)==POINTER) { type = t2; e2= int_value(e2); t2=INT; }
-    else if(t2>0&&car(t2)==POINTER) { type = t1; e1= int_value(e1); t1=INT; }
+    if(t1>0&&car(t1)==POINTER) { 
+	if(!(op==SUB && t2>0&&car(t2)==POINTER))  {
+	    type = t2; e2= int_value(e2); t2=INT; 
+	}
+    } else if(t2>0&&car(t2)==POINTER) { 
+	type = t1; e1= int_value(e1); t1=INT; 
+    }
 #if FLOAT_CODE
     else if(t1==DOUBLE||t2==DOUBLE)
 	return dbinop(op,e1,e2,t1,t2);
@@ -3387,8 +3415,13 @@
 		e=e1-e2; type=INT;
 	    } else {
 		if(car(t1)!=POINTER) error(TYERR);
-		e=e1-size(cadr(t1))*e2;
-		type=t1;
+		if(integral(t2)) {
+		    e=e1-size(cadr(t1))*e2;
+		    type=t1;
+		} else {
+		    e=(e1-e2)/size(cadr(t1));
+		    type=INT;
+		}
 	    }
 	    break;
 	case MUL:
@@ -3462,8 +3495,11 @@
 	if (car(e)==CONST) {
 	    if(car(e1)==ADDRESS) {
 		if (car(cadr(e1))!=GVAR) {
+		    // must be lvar
+		    if (car(cadr(e1))!=LVAR) error(-1);
 		    return(list2(ADDRESS,
-			list2(car(cadr(e1)),cadr(cadr(e1))+cadr(e))));
+			list3(car(cadr(e1)),cadr(cadr(e1))+cadr(e),
+				caddr(cadr(e1)))));
 		} else {
 		    return(list2(ADDRESS,
 			list3(GVAR,cadr(cadr(e1))+cadr(e),caddr(cadr(e1)))));
@@ -3471,7 +3507,7 @@
 	    } else if(car(e1)==GVAR) {
 		return(list3(GVAR,cadr(e1)+cadr(e),caddr(e1)));
 	    } else if(car(e1)==LVAR) {
-		return(list2(LVAR,cadr(e1)+cadr(e)));
+		return(list3(LVAR,cadr(e1)+cadr(e),0));
 	    }
 	}
 	return(list3(ADD,e1,e));
@@ -3632,11 +3668,11 @@
     if (lo) {
 #if LONGLONG_CODE
 	if (post) {
-	    n1 = list2(LVAR,new_lvar(size_of_longlong));
+	    n1 = list3(LVAR,new_lvar(size_of_longlong),0);
 	    code_lassign_lvar(cadr(n1),USE_CREG);
 	}
 	if (!code_lassop_p) {
-	    n2 = list2(LVAR,new_lvar(size_of_longlong));
+	    n2 = list3(LVAR,new_lvar(size_of_longlong),0);
 	    code_lassign_lvar(cadr(n2),USE_CREG);
 	    lassign(list4(LASSOP,n2,e3,op+LOP));
 	} else {
@@ -3649,7 +3685,7 @@
 #endif
     } else {
 	if (post) {
-	    n1 = list2(LVAR,new_lvar(size_of_int));
+	    n1 = list3(LVAR,new_lvar(size_of_int),0);
 	    code_assign_lvar(cadr(n1),USE_CREG,0);
 	}
 	emit_push();
--- a/mc-codegen.h	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-codegen.h	Sun Nov 21 19:20:18 2004 +0900
@@ -20,7 +20,7 @@
 /* used by mc-parse */
 
 
-extern NMTBL * def(NMTBL *n);
+extern NMTBL * def(NMTBL *n,int ctmode);
 extern int arg_reorder(int arg,int new_arg);
 extern int assign_data(int e, int t, NMTBL *n,int offset);
 extern int assign_expr(int e1,int e2,int t);
--- a/mc-parse.c	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-parse.c	Sun Nov 21 19:20:18 2004 +0900
@@ -64,7 +64,7 @@
 int retlabel,retpending,retcont;
 int pending_jmp;
 int struct_return;
-int sym,type,mode,stmode;
+int sym,type,mode,stmode,ctmode,inmode;
 int typedefed;
 int decl_str_init;
 
@@ -101,7 +101,7 @@
 static int adecl(NMTBL *n);
 static void code_decl(NMTBL *n);
 static void decl(void);
-static int typespec(void);
+static int typespec(int *ctmode);
 static void docase(void);
 static void docomp(int);
 static void dodefault(void);
@@ -130,12 +130,12 @@
 static void decl_data_field(int type,NMTBL *n,int offset);
 static int decl_data(int t, NMTBL *n,int offset,int skip);
 static int typeid(int s);
-static int typename(void);
 extern NMTBL * get_name_from_chptr();
 static NMTBL * hash_search(char *name,struct cheap *scheap,int len,unsigned int hash,int mode);
 extern NMTBL * make_local_scope(NMTBL *nlist,NMTBL *nptr1,int sc);
 static NMTBL * make_top_scope(NMTBL *nlist,NMTBL *nptr1,int sc);
 static void extrn_use(NMTBL *nptr);
+static void top_init();
 
 static struct cheap * new_cheap();
 
@@ -174,7 +174,6 @@
 int
 main(int argc, char **argv)
 {
-    int i;
 
 /*
      option handling
@@ -220,33 +219,42 @@
     init();
     /* top level */
     while(1) {
-	mode=TOP;
-	if (gfree > heapsize-30000) {
-	    heapsize *= 2;
-#if HEAP_REPORT
-	    fprintf(stderr,"** heap extended to %d\n",heapsize);
-#endif
-	    heap = realloc(heap,heapsize*sizeof(int));
-	}
-	lfree= heapsize;
-	codegen_decl_init();
-	while (chptrsave!=0) {
-	    i = cadr(chptrsave); free_glist2(chptrsave); chptrsave = i;
-	}
-	while (chsave!=0) {
-	    i = cadr(chsave); free_glist2(chsave); chsave = i;
-	}
-	// a in previous extern f(a) is in current scope, release it
-	leave_scope();
+	top_init();
 	while(getsym(0)==SM) conv->sm_();
 	mode=GDECL;
-	stmode=0;
+	stmode=0; inmode=0;
 	args=0;
 	decl();
     }
     /*NOTREACHED*/
 }
 
+static void
+top_init()
+{
+    int i;
+
+    mode=TOP;
+    if (gfree > heapsize-HEAPSIZE) {
+	heapsize *= 2;
+#if HEAP_REPORT
+	fprintf(stderr,"** heap extended to %d\n",heapsize);
+#endif
+	heap = realloc(heap,heapsize*sizeof(int));
+	if(!heap) { error(MMERR); exit(1); }
+    }
+    lfree= heapsize;
+    codegen_decl_init();
+    while (chptrsave!=0) {
+	i = cadr(chptrsave); free_glist2(chptrsave); chptrsave = i;
+    }
+    while (chsave!=0) {
+	i = cadr(chsave); free_glist2(chsave); chsave = i;
+    }
+    // a in previous extern f(a) is in current scope, release it
+    leave_scope();
+}
+
 /*
     error handler
     when EOF, process next file
@@ -607,6 +615,7 @@
 {
     if(sym==VOLATILE) {
 	getsym(0);
+	ctmode=VOLATILE;
     }
     switch(sym) {
     case STATIC:
@@ -661,6 +670,10 @@
 		error(DCERR);
 	break;
     }
+    if(sym==INLINE) {
+	getsym(0);
+	inmode = INLINE;
+    }
 }
 
 /*
@@ -676,10 +689,10 @@
 decl(void)
 {
     NMTBL *n;
-    int t,sd;
+    int t,sd,ctmode=0;
     if (mode==GDECL) { typedefed=0;  }
     storage_class();
-    if((t=typespec())==0) return;
+    if((t=typespec(&ctmode))==0) return;
     if(sym==SM) {
 	conv->return_type_(t,0,stypedecl);
 	conv->sm_(); return;
@@ -704,7 +717,7 @@
 	} else error(DCERR);
     } else {
 	conv->return_type_(type,n,sd);
-	n = def(n);
+	n = def(n,ctmode);
 	if (sym==ASS && n!=&null_nptr) { 
 	    decl_data(type,n,0,0); data_closing(n); 
 	}
@@ -720,7 +733,7 @@
 		    error(DCERR);
 	    }
 	    conv->return_type_(type,n,1);
-	    def(n);
+	    def(n,ctmode);
 	    if (sym==ASS && n!=&null_nptr) {
 		decl_data(type,n,0,0);data_closing(n);
 	    }
@@ -738,7 +751,7 @@
       type specification
  */
 static int
-typespec(void)
+typespec(int *ctmode)
 {
     int t = INT;
     int slfree;
@@ -747,9 +760,7 @@
 
     while (sym==KONST) {
 	getsym(0);
-    }
-    if (sym==INLINE) {
-	getsym(0);  // should be static?
+	*ctmode = KONST;
     }
     switch(sym) {
     case VOID:
@@ -809,6 +820,9 @@
     case SHORT:
 	t=SHORT;
 	if(getsym(0)==INT) getsym(0);
+	else if(sym==UNSIGNED) {
+	    getsym(0); t = USHORT;
+	}
 	break;
     case LONG:
 	t=INT;
@@ -829,7 +843,7 @@
 	checksym(LPAR);
 	slfree=lfree; stype=type;
 	smode = mode; mode = LDECL;
-	if((t=typespec())==0) {
+	if((t=typespec(ctmode))==0) {
 	    mode = STAT;
 	    expr(0); 
 	    t = type;
@@ -851,14 +865,18 @@
 		break;
 	    }
 	}
+if(0) {
 	while (sym==KONST) {
 	    getsym(0);
+	    *ctmode = KONST;
 	}
+}
 	if(mode==LDECL) return 0;
 	t= INT;
     }
     while (sym==KONST) {
 	getsym(0);
+	*ctmode = KONST;
     }
     return t;
 }
@@ -992,6 +1010,7 @@
     int t;
     int stype,smode,sd,sargs,sstmode;
     int argtypes;
+    int ctmode=0;
 
     sstmode=stmode; stmode=REGISTER; /* nobody use this? */
     stype=type;
@@ -1007,7 +1026,7 @@
     for(;;) {
 	if(sym==IDENT && nptr->sc!=TYPE) {
 	    type=INT;  /* naked argument, old K&R C */
-	    def(nptr);
+	    def(nptr,ctmode);
 	    getsym(0);
 	    if(sym==RPAR) break;
 	} else {
@@ -1016,7 +1035,7 @@
 		getsym(0);
 		break;
 	    }
-	    if((t=typespec())==0) {
+	    if((t=typespec(&ctmode))==0) {
 		error(DCERR);
 		break;
 	    }
@@ -1028,7 +1047,7 @@
 		reverse(t);
 		if (arg != &null_nptr) {
 		    if (smode==GDECL)
-			def(arg);
+			def(arg,ctmode);
 		}
 	    }
 	    argtypes=list2(type,argtypes);
@@ -1209,7 +1228,7 @@
 	mode=STADECL;
 	decl_data_field(type,nptr0,offset);
 	init_vars = list2(
-	    list4(STASS,list2(LVAR,n->dsp+offset),
+	    list4(STASS,list3(LVAR,n->dsp+offset,0),
 		list3(RSTRUCT,list3(GVAR,0,(int)nptr0),e),e),
 	    init_vars);
 	return;
@@ -1271,13 +1290,19 @@
 {
     int t1,e,i,mode_save;
 
-    if (offset==0 && n->sc==GVAR && n->dsp==-1) {
-	/* duplicate initialization */
-	error(INERR);
-    }
     conv->decl_data_();
     mode_save = mode;
     mode=STAT;
+    if (offset==0) {
+	if (n->sc==GVAR && n->dsp==-1) {
+	    /* duplicate initialization */
+	    error(INERR);
+	} else {
+	    if (mode_save==GDECL && n->attr && car(n->attr)==KONST) {
+		mode=GDECL;
+	    }
+	}
+    }
     if (!skip) getsym(0);
     if (sym==RC) {  /* premature end (not necessary?) */
 	conv->decl_data_end_();
@@ -1313,7 +1338,7 @@
 		    if (caddr(t)==0) {           /* size not defined      */
 			caddr(t)=i+1;           /* define array size     */
 		    } else if (caddr(t)!=i+1) {  /* size match?           */
-			if (caddr(t) < i ) {   /* too many data */
+			if (caddr(t) < i+1 ) {   /* too many data */
 			    // this check is sligtly odd (fix me)
 			    // error(INERR);
 			} else
@@ -2783,7 +2808,7 @@
 	case FUNCTION: case CODE:
 	    return fname(nptr);
 	case LVAR:
-	    e1=list2(LVAR,nptr->dsp);
+	    e1=list3(LVAR,nptr->dsp,(int)nptr);
 	    type=nptr->ty;
 	    getsym(0);
 	    break;
@@ -3025,12 +3050,12 @@
 		disp -= tmp_struct->dsp-sz;
 		tmp_struct->dsp = disp;
 	    } else {
-		tmp_struct = def(0);
+		tmp_struct = def(0,0);
 	    }
 	} else {
-	    tmp_struct = def(0);
+	    tmp_struct = def(0,0);
 	}
-	e = list2(LVAR,tmp_struct->dsp);
+	e = list3(LVAR,tmp_struct->dsp,0);
 
 	/* pass the pointer as an argument */
 	/* this is recognized by called function declaration */
@@ -3059,8 +3084,9 @@
 typename(void)
 {
     int t;
-
-    type=t=typespec();
+    int ctmode=0;
+
+    type=t=typespec(&ctmode);
     ndecl0();
     reverse(t);
     return type;
@@ -3636,6 +3662,7 @@
 	free_nptr_list = (NMTBL *)free_nptr_list->dsp;
 	ret->sc = 0;
 	ret->dsp = 0;
+	ret->attr = 0;
 	return ret;
     }
     if (nptr_pool->ptr >= nptr_pool->last) {
@@ -3652,6 +3679,7 @@
     ret = ((NMTBL *)nptr_pool->ptr)++;
     ret->sc = 0;
     ret->dsp = 0;
+    ret->attr = 0;
     return ret;
 }
 
@@ -3703,6 +3731,7 @@
     n->nm = hash->nm;
     n->sc = EMPTY;
     n->dsp = 0;
+    n->attr = 0;
     return n;
 }
 
--- a/mc-parse.h	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc-parse.h	Sun Nov 21 19:20:18 2004 +0900
@@ -1,6 +1,6 @@
 /* for mc-parse.c */
 
-extern int sym,type,mode,stmode;
+extern int sym,type,mode,stmode,ctmode;
 extern int labelno,gpc,disp;
 extern int args,init_vars;
 extern int cslabel,control;
--- a/mc.h	Sun Nov 21 11:20:56 2004 +0900
+++ b/mc.h	Sun Nov 21 19:20:18 2004 +0900
@@ -427,7 +427,8 @@
 typedef struct nametable {
         char *nm;
 	struct nametable *next;
-        int sc,ty,dsp; } NMTBL;
+        int sc,attr;
+	int ty,dsp; } NMTBL;
 
 extern int *heap;
 extern NMTBL *global_list,*local_static_list;