History

completed initializer handlign (compute size before storing initializers if unknown size - macro subst fix

bellard committed 24 years ago

Commit 0c6b2dc1 parent 34a14a01 file · +144 −56Browse files

Unified · Split

tcc.c+144−56
@@ -264,7 +264,7 @@ int expr_const(); · 263 unmodified lines
264264 void expr_eq();
265265 void expr();
266266 void decl();
267−void decl_assign(int t, int c, int first);
267+void decl_initializer(int t, int c, int first, int size_only);
268268 int gv();
269269 void move_reg();
270270 void save_reg();
@@ -1168,7 +1168,7 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) · 897 unmodified lines
11681168 tok_add(&str, &len, t);
11691169 }
11701170 } else if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR) {
1171− tok_add2(&str, &len, t, *macro_ptr++);
1171+ tok_add2(&str, &len, t, *macro_str++);
11721172 } else {
11731173 s = sym_find2(args, t);
11741174 if (s) {
@@ -2906,8 +2906,10 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) · 1731 unmodified lines
29062906 }
29072907
29082908 /* t is the array or struct type. c is the array or struct
2909− address. cur_index/cur_field is the pointer to the current value */
2910−void decl_designator(int t, int c, int *cur_index, Sym **cur_field)
2909+ address. cur_index/cur_field is the pointer to the current
2910+ value. 'size_only' is true if only size info is needed (only used
2911+ in arrays) */
2912+void decl_designator(int t, int c, int *cur_index, Sym **cur_field, int size_only)
29112913 {
29122914 Sym *s, *f;
29132915 int notfirst, index, align;
@@ -2964,39 +2966,79 @@ void decl_designator(int t, int c, int *cur_index, Sym **cur_field) · 50 unmodified lines
29642966 c += f->c;
29652967 }
29662968 }
2967− decl_assign(t, c, 0);
2969+ decl_initializer(t, c, 0, size_only);
2970+}
2971+
2972+/* store a value or an expression directly in global data or in local array */
2973+
2974+void init_putv(int t, int c, int v, int is_expr)
2975+{
2976+ if ((t & VT_VALMASK) == VT_CONST) {
2977+ if (is_expr)
2978+ v = expr_const();
2979+ if (t & VT_BYTE)
2980+ *(char *)c = v;
2981+ else if (t & VT_SHORT)
2982+ *(short *)c = v;
2983+ else
2984+ *(int *)c = v;
2985+ } else {
2986+ vt = t;
2987+ vc = c;
2988+ vpush();
2989+ if (is_expr)
2990+ expr_eq();
2991+ else
2992+ vset(VT_CONST, v);
2993+ vstore();
2994+ }
29682995 }
29692996
29702997 /* 't' contains the type and storage info. c is the address of the
29712998 object. 'first' is true if array '{' must be read (multi dimension
2972− implicit array init handling). */
2973−void decl_assign(int t, int c, int first)
2999+ implicit array init handling). 'size_only' is true if size only
3000+ evaluation is wanted (only for arrays). */
3001+void decl_initializer(int t, int c, int first, int size_only)
29743002 {
2975− int v, index, index_max, t1, n, no_oblock;
3003+ int index, array_length, t1, n, no_oblock, nb, parlevel, i;
29763004 Sym *s, *f;
29773005 TokenSym *ts;
29783006
29793007 if (t & VT_ARRAY) {
29803008 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
29813009 n = s->c;
2982− index_max = 0;
3010+ array_length = 0;
29833011 if (tok == TOK_STR) {
29843012 t1 = pointed_type(t);
29853013 if (!(t1 & VT_BYTE))
29863014 error("invalid type");
2987− if ((t & VT_VALMASK) == VT_CONST) {
2988− while (tok == TOK_STR) {
2989− ts = (TokenSym *)tokc;
2990− memcpy((void *)c, ts->str, ts->len);
2991− c += ts->len;
2992− index_max += ts->len;
2993− next();
3015+ /* XXX: move multiple string parsing in parser ? */
3016+ while (tok == TOK_STR) {
3017+ ts = (TokenSym *)tokc;
3018+ /* compute maximum number of chars wanted */
3019+ nb = ts->len;
3020+ if (n >= 0 && nb > (n - array_length))
3021+ nb = n - array_length;
3022+ if (!size_only) {
3023+ if (ts->len > nb)
3024+ warning("initializer-string for array is too long");
3025+ for(i=0;i<nb;i++) {
3026+ init_putv(t1, c, ts->str[i], 0);
3027+ c++;
3028+ }
29943029 }
2995− *(char *)c++ = 0;
2996− } else {
2997− error("local string init not handled");
3030+ array_length += nb;
3031+ next();
3032+ }
3033+ /* only add trailing zero if enough storage (no
3034+ warning in this case since it is standard) */
3035+ if (n < 0 || array_length < n) {
3036+ if (!size_only) {
3037+ init_putv(t1, c, 0, 0);
3038+ c++;
3039+ }
3040+ array_length++;
29983041 }
2999− /* string init */
30003042 } else {
30013043 no_oblock = 0;
30023044 if (!first && tok != '{')
@@ -3005,12 +3047,12 @@ void decl_assign(int t, int c, int first) · 2 unmodified lines
30053047 skip('{');
30063048 index = 0;
30073049 while (tok != '}') {
3008− decl_designator(t, c, &index, NULL);
3050+ decl_designator(t, c, &index, NULL, size_only);
30093051 if (n >= 0 && index >= n)
30103052 error("index too large");
3011− if (index > index_max)
3012− index_max = index;
30133053 index++;
3054+ if (index > array_length)
3055+ array_length = index;
30143056 /* special test for multi dimensional arrays (may not
30153057 be strictly correct if designators are used at the
30163058 same time) */
@@ -3025,45 +3067,43 @@ void decl_assign(int t, int c, int first) · 8 unmodified lines
30253067 }
30263068 /* patch type size if needed */
30273069 if (n < 0)
3028− s->c = index_max + 1;
3070+ s->c = array_length;
30293071 } else if (t & VT_STRUCT) {
30303072 /* XXX: union needs only one init */
30313073 skip('{');
30323074 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
30333075 f = s->next;
30343076 while (tok != '}') {
3035− decl_designator(t, c, NULL, &f);
3077+ decl_designator(t, c, NULL, &f, size_only);
30363078 if (tok == '}')
30373079 break;
30383080 skip(',');
30393081 f = f->next;
30403082 }
30413083 skip('}');
3084+ } else if (size_only) {
3085+ /* just skip expression */
3086+ parlevel = 0;
3087+ while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
3088+ tok != -1) {
3089+ if (tok == '(')
3090+ parlevel++;
3091+ else if (tok == ')')
3092+ parlevel--;
3093+ next();
3094+ }
30423095 } else {
3043− if ((t & VT_VALMASK) == VT_CONST) {
3044− v = expr_const();
3045− if (t & VT_BYTE)
3046− *(char *)c = v;
3047− else if (t & VT_SHORT)
3048− *(short *)c = v;
3049− else
3050− *(int *)c = v;
3051− } else {
3052− vt = t;
3053− vc = c;
3054− vpush();
3055− expr_eq();
3056− vstore();
3057− }
3096+ init_putv(t, c, 0, 1);
30583097 }
30593098 }
30603099
30613100 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
30623101 void decl(l)
30633102 {
3064− int *a, t, b, size, align, v, u, n, addr;
3103+ int *a, t, b, size, align, v, u, n, addr, tok1;
30653104 Sym *sym;
3066−
3105+ int *init_str, init_len, level, *saved_macro_ptr;
3106+
30673107 while (b = ist()) {
30683108 if ((b & (VT_ENUM | VT_STRUCT)) && tok == ';') {
30693109 /* we accept no variable after */
@@ -3130,16 +3170,67 @@ void decl(l) · 60 unmodified lines
31303170 u = VT_CONST;
31313171 u |= t;
31323172 size = type_size(t, &align);
3173+ /* If unknown size, we must evaluate it before
3174+ evaluating initializers because
3175+ initializers can generate global data too
3176+ (e.g. string pointers or ISOC99 compound
3177+ literals). It also simplifies local
3178+ initializers handling */
3179+ init_len = 0;
3180+ init_str = NULL;
3181+ saved_macro_ptr = NULL; /* avoid warning */
3182+ tok1 = 0;
3183+ if (size < 0) {
3184+ if (tok != '=')
3185+ error("unknown size for '%s'", get_tok_str(v, 0));
3186+ tok_add2(&init_str, &init_len, tok, tokc);
3187+ next();
3188+ /* get all init string */
3189+ level = 0;
3190+ while (level > 0 || (tok != ',' && tok != ';')) {
3191+ if (tok < 0)
3192+ error("unexpect end of file in initializer for '%s'",
3193+ get_tok_str(v, 0));
3194+ tok_add2(&init_str, &init_len, tok, tokc);
3195+ if (tok == '{')
3196+ level++;
3197+ else if (tok == '}') {
3198+ if (level == 0)
3199+ break;
3200+ level--;
3201+ }
3202+ next();
3203+ }
3204+ tok1 = tok;
3205+ tok_add(&init_str, &init_len, -1);
3206+ tok_add(&init_str, &init_len, 0);
3207+
3208+ /* compute size */
3209+ saved_macro_ptr = macro_ptr;
3210+ macro_ptr = init_str;
3211+ next();
3212+ skip('=');
3213+ decl_initializer(u, 0, 1, 1);
3214+ /* prepare second initializer parsing */
3215+ macro_ptr = init_str;
3216+ next();
3217+
3218+ /* if still unknown size, error */
3219+ size = type_size(t, &align);
3220+ if (size < 0)
3221+ error("unknown size for '%s'", get_tok_str(v, 0));
3222+ }
31333223 if ((u & VT_VALMASK) == VT_LOCAL) {
3134− /* XXX: cannot use implicit size for local
3135− storage */
3136− if (size < 0)
3137− error("size must be known for locals");
31383224 loc = (loc - size) & -align;
31393225 addr = loc;
31403226 } else {
31413227 glo = (glo + align - 1) & -align;
31423228 addr = glo;
3229+ /* very important to increment global
3230+ pointer at this time because
3231+ initializers themselves can create new
3232+ initializers */
3233+ glo += size;
31433234 }
31443235 if (tok == '=') {
31453236 next();
@@ -3149,20 +3240,17 @@ void decl(l) · 3 unmodified lines
31493240 n = 1;
31503241 next();
31513242 }
3152− decl_assign(u, addr, 1);
3243+ decl_initializer(u, addr, 1, 0);
31533244 if (n)
31543245 skip('}');
3246+ /* restore parse state if needed */
3247+ if (init_str) {
3248+ free(init_str);
3249+ macro_ptr = saved_macro_ptr;
3250+ tok = tok1;
3251+ }
31553252 }
31563253 sym_push(v, u, addr);
3157− /* if global, add size */
3158− if ((u & VT_VALMASK) == VT_CONST) {
3159− /* must recompute size if it was an array
3160− with implicit size */
3161− size = type_size(t, &align);
3162− if (size < 0)
3163− error("invalid size");
3164− glo += size;
3165− }
31663254 }
31673255 }
31683256 if (tok != ',') {