changeset 778:a177c65f3e37

large string (STRINGS) register usage fix LNOT on float
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 19 Nov 2010 04:39:47 +0900
parents be917edcb671
children a0f84a0a990a
files Changes mc-code-arm.c mc-code-i64.c mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-code-spu.c mc-code.h mc-codegen.c mc-inline.c mc-parse.c mc.h
diffstat 12 files changed, 398 insertions(+), 189 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Thu Nov 18 23:44:35 2010 +0900
+++ b/Changes	Fri Nov 19 04:39:47 2010 +0900
@@ -9877,8 +9877,8 @@
 Intel64 が mmx を save しないのは、そういう噂があったからだろうけど、
 ばかげた話だ。
 
-
-
-
-
-
+string の長さを無制限にするのは難しそう。でも、i64.c でははみ出てる。
+
+
+
+
--- a/mc-code-arm.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-code-arm.c	Fri Nov 19 04:39:47 2010 +0900
@@ -1925,6 +1925,30 @@
     set_attr(n,LABEL,lb);
 }
 
+void
+emit_strings(NMTBL *n)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = n->dsp; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    emit_label(l);
+}
+
+void
+code_strings(int e2,int reg)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = e2; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    text_mode(2);
+    code_label_value(l,reg);
+}
+
+
 #define MAX_COPY_LEN 20
 
 void
--- a/mc-code-i64.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-code-i64.c	Fri Nov 19 04:39:47 2010 +0900
@@ -260,7 +260,6 @@
 
 static int creg;
 static int ireg;
-static int lreg;
 
 extern int lp64;
 
@@ -675,6 +674,8 @@
 	printf(move_op,reg_name_q[reg0],reg_name_q[reg1]);
 	if (!regs[reg1]) regs[reg1]=USING_REG;
     } 
+    if (reg0!=reg1)
+	free_register(reg1);
     return reg0;
 }
 
@@ -699,7 +700,6 @@
     if (regs[i]==PTRC_REG) clear_ptr_cache_reg(i);
 #endif
     if (!i||!ireg||!is_data_reg(i)) {
-        if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; }
         if (!ireg) {
 	    ireg = get_data_register();
 	}
@@ -753,7 +753,6 @@
             }
         }
         if (creg>0 && regs[creg]!=REG_VAR) free_register(creg);
-        if (creg==lreg) lreg = 0;
     }
     creg = ireg = reg;
     if (!regs[reg]) regs[reg]=USING_REG;
@@ -774,7 +773,6 @@
 int use_float0() { 
   int i = creg;
   if (!is_float_reg(i)) {
-    if (lreg) { if (regs[lreg]!=REG_VAR) free_register(lreg); lreg = 0; }
     if (!freg) freg = get_dregister(0);
     else if (freg!=i) if (regs[i]!=REG_VAR) free_register(i);
     i = freg;
@@ -787,7 +785,6 @@
 int use_double0() { 
   int i = creg;
   if (!is_float_reg(i)) {
-    if (lreg) { if (regs[lreg]!=REG_VAR) free_register(lreg); lreg = 0; }
     if (!freg) freg = get_dregister(1);
     else if (freg!=i) if (regs[i]!=REG_VAR) free_register(i);
     i = freg;
@@ -866,7 +863,8 @@
 {    /* 使われていないレジスタを調べる */
     int i,reg,j;
     for(i=REG_EDI;i<MAX_REGISTER+1;i++) {
-	if (! regs[i]) {    /* 使われていないなら */
+	if (i!=REG_EDX && ! regs[i]) {    /* 使われていないなら */
+	    // REG_EDX は使わない
 	    regs_line[i]=glineno;
 	    regs[i]=1;      /* そのレジスタを使うことを宣言し */
 	    return i;       /* その場所を表す番号を返す */
@@ -934,6 +932,7 @@
 void 
 free_register(int i) {    /* いらなくなったレジスタを開放 */
     regs[i]=0;
+    regs_line[i]=0;
 }
 
 extern void
@@ -1080,7 +1079,7 @@
     for(i=1;i<REAL_MAX_REGISTER+REAL_MAX_DREGISTER;i++) {
 	regs[i]=0;
     }
-    lreg = creg = ireg = 0;
+    creg = ireg = 0;
     return;
 }
 
@@ -1304,12 +1303,14 @@
 {
     int i;
     for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) {
-        if (! regs[REG_VAR_BASE-i]) {       /* 使われていないなら */
+	int reg = REG_VAR_BASE-i;
+        if (! regs[reg]) {       /* 使われていないなら */
             /* そのレジスタを使うことを宣言し */
-            regs[REG_VAR_BASE-i]=REG_VAR; 
+            regs[reg]=REG_VAR; 
+            regs_line[reg]=glineno; 
             if (i>max_reg_var) max_reg_var=i;
             /* その場所を表す番号を返す */
-            return list3n(REGISTER,REG_VAR_BASE-i,nptr); 
+            return list3n(REGISTER,reg,nptr); 
         }
     }
     return list3n(LVAR,new_lvar(SIZE_OF_INT),0);
@@ -1323,6 +1324,7 @@
         int reg = FREG_VAR_BASE-i;
         if (! regs[reg]) {       /* 使われていないなら */
             regs[reg]=REG_VAR; /*そのレジスタを使うことを宣言し*/
+            regs_line[reg]=glineno; 
             if (i>max_freg_var) max_freg_var=i;
             /* その場所を表す番号を返す */
             return list3n(DREGISTER, reg,nptr); 
@@ -1822,6 +1824,33 @@
     set_attr(n,LABEL,lb);
 }
 
+void
+emit_strings(NMTBL *n)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = n->dsp; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    emit_label(l);
+}
+
+void
+code_strings(int e2,int reg)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = e2; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    if (output_mode==TEXT_EMIT_MODE) {
+	printf(".text\n");
+    } else {
+	text_mode(0);
+    }
+    code_label_value(l,reg);
+}
+
 #define MAX_COPY_LEN 64
 
 /*  ARG_ORDER==1 case do not allow library call in emit_copy
@@ -2143,11 +2172,9 @@
     int stargs;
 #if (ARG_ORDER==1)
     int save_delayed_arg = delayed_arg;
-    int as_save = AS_ARG;  // 1st pushed argment will evaluate at the last
     delayed_arg = 0;
-#else
+#endif
     const int as_save = AS_SAVE;
-#endif
 
     ret_type = function_type(cadddr(e1),&dots);
     if (caddr(cadddr(e1))==0) dots=1;
@@ -2180,9 +2207,6 @@
             if (complex_) {
                 arg = get_input_arg(caddr(complex_),as_save,
                                         pnargs,preg_arg,pfreg_arg);
-#if ARG_ORDER==1
-		as_save = AS_SAVE;
-#endif
                 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
             }
             // memorise last complex arg parameter
@@ -4372,7 +4396,7 @@
     use_register(reg0,REG_EAX,1);
 
     printf("\tcltq\n"); // printf("\tmovslq %s,%s\n", reg, reg);
-    lreg = creg = REG_EAX;
+    set_ireg(REG_EAX,0);
 }
 
 void code_i2ull(int reg)
@@ -4948,13 +4972,13 @@
 	/* make and-mask  */
 	oprtc(BOR,reg,list2(CONST,~mask));
 	/* do conjunction  */
-	printf("\tandl %s,%s\n",register_name(reg,SIZE_OF_INT),register_name(lreg,SIZE_OF_INT));
+	printf("\tandl %s,%s\n",register_name(reg,SIZE_OF_INT),register_name(ireg,SIZE_OF_INT));
 	/* make or-mask  */
 	printf("\tpopl %s\n",register_name(reg,SIZE_OF_INT));
 	oprtc(BAND,reg,list2(CONST,mask));
 	/* do disjunction  */
-	printf("\torl %s,%s\n",register_name(reg,SIZE_OF_INT),register_name(lreg,SIZE_OF_INT));
-	printf("\txchg %s,%s\n",register_name(reg,SIZE_OF_INT),register_name(lreg,SIZE_OF_INT));
+	printf("\torl %s,%s\n",register_name(reg,SIZE_OF_INT),register_name(ireg,SIZE_OF_INT));
+	printf("\txchg %s,%s\n",register_name(reg,SIZE_OF_INT),register_name(ireg,SIZE_OF_INT));
 }
 
 static void
@@ -4965,13 +4989,13 @@
 	/* make and-mask  */
 	loprtc(BOR,reg,llist2(CONST,~mask));
 	/* do conjunction  */
-	printf("\tandq %s,%s\n",register_name(reg,0),register_name(lreg,0));
+	printf("\tandq %s,%s\n",register_name(reg,0),register_name(ireg,0));
 	/* make or-mask  */
 	printf("\tpopq %s\n",register_name(reg,0));
 	oprtc(BAND,reg,list2(CONST,mask));
 	/* do disjunction  */
-	printf("\torq %s,%s\n",register_name(reg,0),register_name(lreg,0));
-	printf("\txchgq %s,%s\n",register_name(reg,0),register_name(lreg,0));
+	printf("\torq %s,%s\n",register_name(reg,0),register_name(ireg,0));
+	printf("\txchgq %s,%s\n",register_name(reg,0),register_name(ireg,0));
 }
 
 extern void
--- a/mc-code-ia32.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-code-ia32.c	Fri Nov 19 04:39:47 2010 +0900
@@ -1535,6 +1535,33 @@
     set_attr(n,LABEL,lb);
 }
 
+void
+emit_strings(NMTBL *n)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = n->dsp; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    emit_label(l);
+}
+
+void
+code_strings(int e2,int reg)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = e2; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    if (output_mode==TEXT_EMIT_MODE) {
+	printf(".text\n");
+    } else {
+	text_mode(0);
+    }
+    code_label_value(l,reg);
+}
+
 #define MAX_COPY_LEN 20
 
 /*  ARG_ORDER==1 case do not allow library call in emit_copy
--- a/mc-code-mips.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-code-mips.c	Fri Nov 19 04:39:47 2010 +0900
@@ -1571,6 +1571,30 @@
     set_attr(n,LABEL,lb);
 }
 
+void
+emit_strings(NMTBL *n)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = n->dsp; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    emit_label(l);
+}
+
+void
+code_strings(int e2,int reg)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = e2; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    text_mode(2);
+    code_label_value(l,reg);
+}
+
+
 #define MAX_COPY_LEN 20
 
 void
--- a/mc-code-powerpc.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-code-powerpc.c	Fri Nov 19 04:39:47 2010 +0900
@@ -1923,6 +1923,34 @@
     set_attr(n,LABEL,lb);
 }
 
+
+void
+emit_strings(NMTBL *n)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = n->dsp; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    emit_label(l);
+}
+
+void
+code_strings(int e2,int reg)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = e2; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    if (output_mode==TEXT_EMIT_MODE) {
+	printf(".text\n");
+    } else {
+	text_mode(0);
+    }
+    code_label_value(l,reg);
+}
+
 #define MAX_COPY_LEN 20
 // #define MAX_COPY_LEN 10
 
--- a/mc-code-spu.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-code-spu.c	Fri Nov 19 04:39:47 2010 +0900
@@ -1415,6 +1415,30 @@
     set_attr(n,LABEL,lb);
 }
 
+void
+emit_strings(NMTBL *n)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = n->dsp; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    emit_label(l);
+}
+
+void
+code_strings(int e2,int reg)
+{
+    int l = emit_string_label();
+    int i;
+    for(i = e2; i; i = cadr(i)) {
+        ascii(scaddr(i));
+    }
+    text_mode(2);
+    code_label_value(l,reg);
+}
+
+
 #define MAX_COPY_LEN 20
 
 void
--- a/mc-code.h	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-code.h	Fri Nov 19 04:39:47 2010 +0900
@@ -181,6 +181,8 @@
 extern void emit_label(int labelno);
 extern int emit_string_label();
 extern void emit_string(char *,int type);
+void emit_strings(NMTBL *n);
+void code_strings(int e2,int reg);
 
 extern void code_i2c(int reg);
 extern void code_i2s(int reg);
--- a/mc-codegen.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-codegen.c	Fri Nov 19 04:39:47 2010 +0900
@@ -282,6 +282,9 @@
 	code_lconst(e1,USE_CREG);
 	return LONGLONG;
 #endif
+    case STRINGS:
+	code_strings(e2,USE_CREG) ;
+	return ADDRESS;
     case STRING:
 	code_string(e1,USE_CREG);
 	return ADDRESS;
@@ -893,7 +896,7 @@
 	case ADDRESS:
 	    e = cadr(e);
 	    return (car(e)==GVAR||car(e)==FNAME||car(e)==LVAR);
-	case STRING: case GVAR: 
+	case STRINGS: case STRING: case GVAR: 
 	// case FUNCTION: case CODE: 
 	case EXTRN: case EXTRN1: case FNAME:
 	case CONST: case LCONST: case FCONST: case DCONST:
@@ -1921,10 +1924,13 @@
     case CONST:    code_const(cadr(e4),reg); return;
     case ADDRESS: 
 	if (car(cadr(e4))==STRING) code_string(cadr(e4),reg);
-	else code_gvar(cadr(e4),reg);   
+	if (car(cadr(e4))==STRINGS) {
+	    code_strings(cadr(e4),reg);
+	} else code_gvar(cadr(e4),reg);   
 	return;
     case FNAME:    code_fname(ncaddr(e4),reg); return;
     case STRING:   code_string(e4,reg); return;
+    case STRINGS:   code_strings(cadr(e4),reg); return;
     default: error(-1);
     }
 }
@@ -1950,14 +1956,14 @@
 	} else if (car(e2)==REGISTER||car(e2)==LREGISTER) {
 	    switch(e5) {
 	    case ADDRESS:
-		if (!((car(cadr(e4))==STRING) || car(cadr(e4))==GVAR)) 
+		if (!((car(cadr(e4))==STRING)|| (car(cadr(e4))==STRINGS) || car(cadr(e4))==GVAR)) 
 		    break; 
 	    case  CRGVAR  : case  CRLVAR  : case  RGVAR  : case  RLVAR :
 	    case  URGVAR  : case  URLVAR :
 	    case  CURGVAR  : case  CURLVAR  :
 	    case  SURGVAR  : case  SURLVAR  :
 	    case  GVAR  : case  LVAR :
-	    case  CONST   : case  FNAME  : case  STRING :
+	    case  CONST   : case  FNAME  : case  STRING : case STRINGS:
 		assign_opt(e5,e2,e4,byte);
 		return;
 	    }
@@ -3144,6 +3150,7 @@
 	    case DCONST: e=dlist2(car(e),dcadr(e)); break;
 	    case LCONST: e=llist2(car(e),lcadr(e)); break;
 	    case STRING: e=list3n(car(e),cadr(e),ncaddr(e)); break;
+	    case STRINGS: e=list3s(car(e),cadr(e),scaddr(e)); break;
 	    case STRUCT:  // for udpcl
 		e=glist3(car(e),copy_expr(cadr(e)),copy_expr(caddr(e))); break;
 	    case ARRAY:
@@ -3196,6 +3203,8 @@
 		    e = glist3n(car(e),cadr(e),ncaddr(e)); break;
 		case STRING:
 		    e = glist3n(car(e),cadr(e),ncaddr(e)); break;
+		case STRINGS:
+		    e = glist3s(car(e),cadr(e),scaddr(e)); break;
 		case CONST: 
 		    switch(car(e)) {
 		    case CONST:
@@ -3597,6 +3606,10 @@
     NMTBL *str; 
     if (n->attr) {
 	if ((e=attr_value(n,ASM))) {
+	    if (car(e)==STRINGS) {
+		// first element only
+		return scaddr(str->dsp); // may non terminated
+	    }
 	    if (car(e)!=STRING) error(-1);
 	    str = ncaddr(e);
 	    return str->nm;
@@ -3655,11 +3668,15 @@
 	case STRING:
 	    emit_string((ncaddr(e))->nm,n->ty);
 	    return 1;
+	case STRINGS:
+	    emit_strings(ncaddr(e));
+	    return 1;
 	}
     // if (lsrc)fprintf(stderr,"## type= %d\n",t);
 	return 0;
 }
 
+
 static void
 emit_data(int e, int t, NMTBL *n)
 {
--- a/mc-inline.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-inline.c	Fri Nov 19 04:39:47 2010 +0900
@@ -1222,6 +1222,7 @@
     case DCONST: case FCONST:
     case LCONST:
     case STRING:
+    case STRINGS:
     case FNAME:
     case FLABEL:
     case BUILTIN_INF:
--- a/mc-parse.c	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc-parse.c	Fri Nov 19 04:39:47 2010 +0900
@@ -171,7 +171,7 @@
 #endif
 static void errmsg(void);
 static void fdecl(NMTBL *n);
-static void getstring(void);
+static int getstring(void);
 static void init(void);
 static void newfile(void);
 static void reserve(char *s, int d, int sc);
@@ -320,6 +320,25 @@
 }
 
 static void
+print_string(char *s, int i)
+{
+    int c;
+    printf("\"");
+    while(--i>0) {
+	c=*s++;
+	if(c=='\n') printf("\\n");
+	else if(c=='\r') printf("\\r");
+	else if(c=='\t') printf("\\t");
+	else if(c=='\e') printf("\\e");
+	else if(c=='"') printf("\\\"");
+	else if(c=='\\') printf("\\\\");
+	else if(!(' '<=c&&c<=0x7f)) printf("\\%03o",c);
+	else printf("%c",c);
+    }
+    printf("\"");
+}
+
+static void
 macro_convert()
 {
     init();
@@ -341,22 +360,17 @@
 	case LCONST:
 	    printf("%lld",lsymval); break;
 #endif
+	case STRINGS:
+	    {
+		int i;
+		for(i = nptr->dsp;i; i = cadr(i)) {
+		    print_string(scaddr(i), car(i));
+		    printf("\n");
+		}
+		break;
+	    }
 	case STRING:
-	    { int c; char *s = nptr->nm; int i=nptr->dsp;
-		printf("\"");
-		while(--i>0) {
-		    c=*s++;
-		    if(c=='\n') printf("\\n");
-		    else if(c=='\r') printf("\\r");
-		    else if(c=='\t') printf("\\t");
-		    else if(c=='\e') printf("\\e");
-		    else if(c=='"') printf("\\\"");
-		    else if(c=='\\') printf("\\\\");
-		    else if(!(' '<=c&&c<=0x7f)) printf("\\%03o",c);
-		    else printf("%c",c);
-		}
-		printf("\"");
-	    }
+	    print_string(nptr->nm, nptr->dsp);
 	    break;
 	default:
 	    sym_print(sym,stdout);
@@ -1796,7 +1810,7 @@
 	} else if (type_value(cadr(t0))==CHAR) {
 	    e=expr1();
 	    mode = mode_save;
-	    if(car(e)!=STRING)
+	    if(car(e)!=STRING && car(e)!=STRINGS)
 		error(TYERR);
 	    if (inmode) {
 		offset = list3(DECL_DATA,e,type);
@@ -3302,8 +3316,8 @@
     qualifiers();
     checksym(LPAR);
     // asm string
-    if (sym!=STRING) error(DCERR);
-    asm0=list3n(STRING,nptr->dsp,nptr);
+    if (sym!=STRING && sym!=STRINGS) error(DCERR);
+    asm0=list3n(sym,nptr->dsp,nptr);
     getsym(0);
     if (sym!=COLON) {
 #if 0
@@ -3318,8 +3332,8 @@
 	// output expression
 	getsym(0);
 	if (sym==COLON) break;
-	if (sym!=STRING) error(DCERR);
-	out=list2(list3n(STRING,nptr->dsp,nptr),out);
+	if (sym!=STRING && sym!=STRINGS) error(DCERR);
+	out=list2(list3n(sym,nptr->dsp,nptr),out);
 	getsym(0);
 	e1=list2(e=expr1(),e1);
 	lcheck(e);
@@ -3329,8 +3343,8 @@
 	    // input expression
 	    getsym(0);
 	    if (sym==COLON) break;
-	    if (sym!=STRING) error(DCERR);
-	    input=list2(list3n(STRING,nptr->dsp,nptr),input);
+	    if (sym!=STRING && sym!=STRINGS) error(DCERR);
+	    input=list2(list3n(sym,nptr->dsp,nptr),input);
 	    getsym(0);
 	    e1=list2(expr1(),e1);
 	} while(sym==COMMA);
@@ -3339,8 +3353,8 @@
 	do {
 	    // option string
 	    getsym(0);
-	    if (sym!=STRING) error(DCERR);
-	    opt=list2(list3n(STRING,nptr->dsp,nptr),opt);
+	    if (sym!=STRING && sym != STRINGS) error(DCERR);
+	    opt=list2(list3n(sym,nptr->dsp,nptr),opt);
 	    getsym(0);
 	} while(sym==COMMA);
     }
@@ -3754,7 +3768,6 @@
 	conv->prefix_(sym);
 	getsym(0);
 	e=rvalue(expr13());
-	type=INT;
 #if FLOAT_CODE
 	if (car(e)==DCONST||car(e)==FCONST) return list2(CONST,!dcadr(e));
 #endif
@@ -3762,9 +3775,10 @@
 	if (car(e)==LCONST) return list2(CONST,!lcadr(e));
 #endif
 	if (car(e)==CONST) return list2(CONST,!cadr(e));
-	if(!scalar(type))
-	    error(TYERR);
-	return list2(LNOT,e);
+	if (scalar(type)) return list2(LNOT,e);
+	if (type==FLOAT||type==DOUBLE) return binop(EQ,e,dlist2(FCONST,0),type,FLOAT);
+	error(TYERR);
+	return list2(CONST,1);
     case ALLOCA:
 	conv->prefix_(sym);
 	getsym(0);
@@ -4054,6 +4068,11 @@
 	default:error(UDERR);
 	}
 	break;
+    case STRINGS:
+	e1=list3n(STRINGS,nptr->dsp,nptr);
+	type=list3(ARRAY,CHAR,symval);
+	getsym(0);
+	break;
     case STRING:
 	conv-> string_(nptr->nm,nptr->dsp);
 	e1=list3n(STRING,nptr->dsp,nptr);
@@ -4719,13 +4738,14 @@
      All strings are kept in hash table, and shared.
           float/long long should be shared too.
  */
-static void
+static int
 getstring(void)
 {
     char *name = cheap->ptr;
     int i= 0;
     int c;
     unsigned int hash = 0;
+    int strings = 0;
     struct cheap scheap;
 
     save_cheap(&scheap,cheap);
@@ -4734,7 +4754,12 @@
 	    in_quote = 1;
 	    getch();  
 	    while (ch != '"') {
-		if (i>STRSIZE) error(STRERR);
+		if (i>STRSIZE-1) {
+		    strings = glist3s(i,strings,name);
+		    save_cheap(&scheap,cheap);
+		    i = 0;
+		    name = cheap->ptr;
+		}
 		if ((c = escape())==0 && ch=='"') {
 		    in_quote = 0;
 		    getch();
@@ -4753,11 +4778,24 @@
     *cheap->ptr = 0;
     cheap = increment_cheap(cheap,&name);
     i++;
+    if (strings) {
+	// too long string is stored in glist3
+	strings = glist3s(i,strings,name);
+	nptr = get_nptr();
+	nptr->dsp = reverse0(strings);
+	int j;
+	for(j = strings, i = 0; j ; j = car(j)) {
+	    i += car(j);
+	}
+	symval = i;
+	return STRINGS;
+    }
     nptr = name_space_search(hash_search(name,&scheap,i,hash,DEF),STRING);
     // if we already have this, hash_search will reset cheap
     //    should do the same thing for float/double constant
     nptr->dsp = i;
     symval = i;
+    return STRING;
 }
 
 /*
@@ -4993,8 +5031,7 @@
 	getch();
 	return sym=CONST;
     } else if(ch=='"') {
-	getstring();
-	return sym= STRING;
+	return sym= getstring();
     } 
     /* 2 letters literal */
     c=ch;
--- a/mc.h	Thu Nov 18 23:44:35 2010 +0900
+++ b/mc.h	Fri Nov 19 04:39:47 2010 +0900
@@ -195,27 +195,28 @@
 #define BUILTIN_INFF	17
 #define BUILTIN_INFL	18
 #define LABEL  	19
+#define STRINGS	20
 
 #define NULLARY_ARGS(i) (i==RETURN||i==ENVIRONMENT||i==LCALL||i==REGISTER||i==DREGISTER||i==FREGISTER||i==LREGISTER||(GVAR<=(i%SOP)&&(i%SOP)<=LABEL))
 
 /* unary  argments */
 
-#define ADDRESS	20
-#define MINUS  	21
-#define LNOT   	22
-#define BNOT   	23
-#define INC    	24
-#define PERIOD 	25
-#define ARROW  	26
-#define POSTINC	27
-#define UPOSTINC       	28
-#define PREINC 	29
-#define UPREINC	30
-#define POSTDEC	31
-#define UPOSTDEC       	32
-#define PREDEC 	33
-#define UPREDEC	34
-#define DEC    	35
+#define ADDRESS	21
+#define MINUS  	22
+#define LNOT   	23
+#define BNOT   	24
+#define INC    	25
+#define PERIOD 	26
+#define ARROW  	27
+#define POSTINC	28
+#define UPOSTINC       	29
+#define PREINC 	30
+#define UPREINC	31
+#define POSTDEC	32
+#define UPOSTDEC       	33
+#define PREDEC 	34
+#define UPREDEC	35
+#define DEC    	36
 #define CPOSTINC (COP+POSTINC)
 #define CUPOSTINC (COP+UPOSTINC)
 #define CPREINC (COP+PREINC)
@@ -240,9 +241,9 @@
 #define LPREINC (LOP+PREINC)
 #define LUPOSTINC       (LOP+UPOSTINC)
 #define LUPREINC        (LOP+UPREINC)
-#define INDIRECT       	36
-#define RINDIRECT      	37
-#define URINDIRECT     	38
+#define INDIRECT       	37
+#define RINDIRECT      	38
+#define URINDIRECT     	39
 #define CRINDIRECT      (COP+RINDIRECT)
 #define CURINDIRECT     (COP+URINDIRECT)
 #define SRINDIRECT      (SOP+RINDIRECT)
@@ -251,63 +252,63 @@
 #define DRINDIRECT      (DOP+RINDIRECT)
 #define LRINDIRECT      (LOP+RINDIRECT)
 #define LURINDIRECT     (LOP+URINDIRECT)
-#define RSTRUCT	39
-#define ALLOCA 	40
-#define BUILTINP 	41
-#define BUILTIN_EXPECT 	42
-#define BUILTIN_FABS	43
-#define BUILTIN_FABSF	44
-#define BUILTIN_FABSL	45
-#define ATTRIBUTE 	46
-#define BIT_FIELD 	47
-#define RBIT_FIELD 	48
-#define BPREINC 	49
-#define BPOSTINC 	50
-#define CAST 	51
-#define DECL_DATA      	52
-#define CONV   	53
+#define RSTRUCT	40
+#define ALLOCA 	41
+#define BUILTINP 	42
+#define BUILTIN_EXPECT 	43
+#define BUILTIN_FABS	44
+#define BUILTIN_FABSF	45
+#define BUILTIN_FABSL	46
+#define ATTRIBUTE 	47
+#define BIT_FIELD 	48
+#define RBIT_FIELD 	49
+#define BPREINC 	50
+#define BPOSTINC 	51
+#define CAST 	52
+#define DECL_DATA      	53
+#define CONV   	54
 
 #define UNARY_ARGS(i) (ADDRESS<=(i%SOP)&&(i%SOP)<=CONV)
 
 /* binary  argments */
 
-#define MUL    	54
-#define UMUL   	55
-#define DIV    	56
-#define UDIV   	57
-#define MOD    	58
-#define UMOD   	59
-#define ADD    	60
-#define SUB    	61
-#define CMP    	62      
-#define RSHIFT 	63
-#define URSHIFT	64
-#define LSHIFT 	65
-#define ULSHIFT	66
-#define GT     	67
-#define UGT    	68
-#define GE     	69
-#define UGE    	70
-#define LT     	71
-#define ULT    	72
-#define LE     	73
-#define ULE    	74
-#define EQ     	75
-#define NEQ    	76
-#define BAND   	77
-#define EOR    	78
-#define BOR    	79
-#define LAND   	80
-#define LOR    	81
-#define ASS    	82
-#define UCMP   	83
-#define UCMPGE 	84
-#define CMPGE  	85
-#define CMPEQ  	86
-#define CMPNEQ 	87
-#define ASSOP  	88
-#define UASSOP 	89
-#define COMMA  	90
+#define MUL    	55
+#define UMUL   	56
+#define DIV    	57
+#define UDIV   	58
+#define MOD    	59
+#define UMOD   	60
+#define ADD    	61
+#define SUB    	62
+#define CMP    	63      
+#define RSHIFT 	64
+#define URSHIFT	65
+#define LSHIFT 	66
+#define ULSHIFT	67
+#define GT     	68
+#define UGT    	69
+#define GE     	70
+#define UGE    	71
+#define LT     	72
+#define ULT    	73
+#define LE     	74
+#define ULE    	75
+#define EQ     	76
+#define NEQ    	77
+#define BAND   	78
+#define EOR    	79
+#define BOR    	80
+#define LAND   	81
+#define LOR    	82
+#define ASS    	83
+#define UCMP   	84
+#define UCMPGE 	85
+#define CMPGE  	86
+#define CMPEQ  	87
+#define CMPNEQ 	88
+#define ASSOP  	89
+#define UASSOP 	90
+#define COMMA  	91
 
 #define CASS   	(COP+ASS)
 #define CASSOP 	(COP+ASSOP)
@@ -367,24 +368,24 @@
 #define LEOR    (LOP+EOR)
 #define LBOR    (LOP+BOR)
 
-#define BASS   	91
-#define BASSOP 	92
-#define BFD_REPL 	93
+#define BASS   	92
+#define BASSOP 	93
+#define BFD_REPL 	94
 
-#define JUMP 	94
-#define DECL_DATA_ARRAY    	95
-#define DECL_DATA_LIST    	96
-#define DECL_DATA_FIELD    	97
+#define JUMP 	95
+#define DECL_DATA_ARRAY    	96
+#define DECL_DATA_LIST    	97
+#define DECL_DATA_FIELD    	98
 
-#define STASS  	98
+#define STASS  	99
 
 
 #define BINARY_ARGS(i) ((MUL<=(i%SOP)&&(i%SOP)<=STASS)||i==ARRAY)
 
 /* ternary  argments */
 
-#define COND   	99
-#define UCOND  	100
+#define COND   	100
+#define UCOND  	101
 #define SCOND   (SOP+COND)
 #define SUCOND   (SOP+UCOND)
 #define DCOND   (DOP+COND)
@@ -396,33 +397,33 @@
 
 /* not appeared as tags */
 
-#define LPAR   	101
-#define RPAR   	102
-#define LBRA   	103
-#define RBRA   	104
-#define LC     	105
-#define RC     	106
-#define COLON  	107
-#define SM     	108
-#define CNAME  	109
+#define LPAR   	102
+#define RPAR   	103
+#define LBRA   	104
+#define RBRA   	105
+#define LC     	106
+#define RC     	107
+#define COLON  	108
+#define SM     	109
+#define CNAME  	110
 
-#define I2C  	110
-#define I2S  	111
-#define I2I    	112
-#define I2U    	113
-#define I2D    	114
-#define I2F    	115
-#define I2LL   	116
-#define I2ULL  	117
+#define I2C  	111
+#define I2S  	112
+#define I2I    	113
+#define I2U    	114
+#define I2D    	115
+#define I2F    	116
+#define I2LL   	117
+#define I2ULL  	118
 
-#define U2UC  	118
-#define U2US  	119
-#define U2I    	120
-#define U2U    	121
-#define U2D    	122
-#define U2F    	123
-#define U2LL   	124
-#define U2ULL  	125
+#define U2UC  	119
+#define U2US  	120
+#define U2I    	121
+#define U2U    	122
+#define U2D    	123
+#define U2F    	124
+#define U2LL   	125
+#define U2ULL  	126
 
 
 #define D2I     (DOP+I2I)
@@ -457,27 +458,27 @@
 
 /* statement start */
 
-#define ST_DECL		126
-#define ST_IF		127
-#define ST_DO		128
-#define ST_WHILE	129
-#define ST_FOR		130
-#define ST_SWITCH	131
-#define ST_COMP		132
-#define ST_BREAK	133
-#define ST_CONTINUE	134
-#define ST_CASE		135
-#define ST_DEFAULT	136
-#define ST_RETURN	137
-#define ST_GOTO		138
-#define ST_ASM		139
-#define ST_LABEL	140
-#define ST_OP		141
-#define ST_COMMENT	142
+#define ST_DECL		127
+#define ST_IF		128
+#define ST_DO		129
+#define ST_WHILE	130
+#define ST_FOR		131
+#define ST_SWITCH	132
+#define ST_COMP		133
+#define ST_BREAK	134
+#define ST_CONTINUE	135
+#define ST_CASE		136
+#define ST_DEFAULT	137
+#define ST_RETURN	138
+#define ST_GOTO		139
+#define ST_ASM		140
+#define ST_LABEL	141
+#define ST_OP		142
+#define ST_COMMENT	143
 
 #define IS_STATEMENT(i) (i==INLINE||(ST_DECL<=i&&i<=ST_COMMENT))
 
-#define HAS_ADDRESS	143
+#define HAS_ADDRESS	144
 
 /* statement end */