Unified · Split
| @@ -264,7 +264,7 @@ int expr_const(); · 263 unmodified lines | ||
| 264 | 264 | void expr_eq(); |
| 265 | 265 | void expr(); |
| 266 | 266 | 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); | |
| 268 | 268 | int gv(); |
| 269 | 269 | void move_reg(); |
| 270 | 270 | void save_reg(); |
| @@ -1168,7 +1168,7 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) · 897 unmodified lines | ||
| 1168 | 1168 | tok_add(&str, &len, t); |
| 1169 | 1169 | } |
| 1170 | 1170 | } 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++); | |
| 1172 | 1172 | } else { |
| 1173 | 1173 | s = sym_find2(args, t); |
| 1174 | 1174 | if (s) { |
| @@ -2906,8 +2906,10 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) · 1731 unmodified lines | ||
| 2906 | 2906 | } |
| 2907 | 2907 | |
| 2908 | 2908 | /* 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) | |
| 2911 | 2913 | { |
| 2912 | 2914 | Sym *s, *f; |
| 2913 | 2915 | int notfirst, index, align; |
| @@ -2964,39 +2966,79 @@ void decl_designator(int t, int c, int *cur_index, Sym **cur_field) · 50 unmodified lines | ||
| 2964 | 2966 | c += f->c; |
| 2965 | 2967 | } |
| 2966 | 2968 | } |
| 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 | + } | |
| 2968 | 2995 | } |
| 2969 | 2996 | |
| 2970 | 2997 | /* 't' contains the type and storage info. c is the address of the |
| 2971 | 2998 | 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) | |
| 2974 | 3002 | { |
| 2975 | − int v, index, index_max, t1, n, no_oblock; | |
| 3003 | + int index, array_length, t1, n, no_oblock, nb, parlevel, i; | |
| 2976 | 3004 | Sym *s, *f; |
| 2977 | 3005 | TokenSym *ts; |
| 2978 | 3006 | |
| 2979 | 3007 | if (t & VT_ARRAY) { |
| 2980 | 3008 | s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT)); |
| 2981 | 3009 | n = s->c; |
| 2982 | − index_max = 0; | |
| 3010 | + array_length = 0; | |
| 2983 | 3011 | if (tok == TOK_STR) { |
| 2984 | 3012 | t1 = pointed_type(t); |
| 2985 | 3013 | if (!(t1 & VT_BYTE)) |
| 2986 | 3014 | 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 | + } | |
| 2994 | 3029 | } |
| 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++; | |
| 2998 | 3041 | } |
| 2999 | − /* string init */ | |
| 3000 | 3042 | } else { |
| 3001 | 3043 | no_oblock = 0; |
| 3002 | 3044 | if (!first && tok != '{') |
| @@ -3005,12 +3047,12 @@ void decl_assign(int t, int c, int first) · 2 unmodified lines | ||
| 3005 | 3047 | skip('{'); |
| 3006 | 3048 | index = 0; |
| 3007 | 3049 | while (tok != '}') { |
| 3008 | − decl_designator(t, c, &index, NULL); | |
| 3050 | + decl_designator(t, c, &index, NULL, size_only); | |
| 3009 | 3051 | if (n >= 0 && index >= n) |
| 3010 | 3052 | error("index too large"); |
| 3011 | − if (index > index_max) | |
| 3012 | − index_max = index; | |
| 3013 | 3053 | index++; |
| 3054 | + if (index > array_length) | |
| 3055 | + array_length = index; | |
| 3014 | 3056 | /* special test for multi dimensional arrays (may not |
| 3015 | 3057 | be strictly correct if designators are used at the |
| 3016 | 3058 | same time) */ |
| @@ -3025,45 +3067,43 @@ void decl_assign(int t, int c, int first) · 8 unmodified lines | ||
| 3025 | 3067 | } |
| 3026 | 3068 | /* patch type size if needed */ |
| 3027 | 3069 | if (n < 0) |
| 3028 | − s->c = index_max + 1; | |
| 3070 | + s->c = array_length; | |
| 3029 | 3071 | } else if (t & VT_STRUCT) { |
| 3030 | 3072 | /* XXX: union needs only one init */ |
| 3031 | 3073 | skip('{'); |
| 3032 | 3074 | s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT); |
| 3033 | 3075 | f = s->next; |
| 3034 | 3076 | while (tok != '}') { |
| 3035 | − decl_designator(t, c, NULL, &f); | |
| 3077 | + decl_designator(t, c, NULL, &f, size_only); | |
| 3036 | 3078 | if (tok == '}') |
| 3037 | 3079 | break; |
| 3038 | 3080 | skip(','); |
| 3039 | 3081 | f = f->next; |
| 3040 | 3082 | } |
| 3041 | 3083 | 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 | + } | |
| 3042 | 3095 | } 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); | |
| 3058 | 3097 | } |
| 3059 | 3098 | } |
| 3060 | 3099 | |
| 3061 | 3100 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ |
| 3062 | 3101 | void decl(l) |
| 3063 | 3102 | { |
| 3064 | − int *a, t, b, size, align, v, u, n, addr; | |
| 3103 | + int *a, t, b, size, align, v, u, n, addr, tok1; | |
| 3065 | 3104 | Sym *sym; |
| 3066 | − | |
| 3105 | + int *init_str, init_len, level, *saved_macro_ptr; | |
| 3106 | + | |
| 3067 | 3107 | while (b = ist()) { |
| 3068 | 3108 | if ((b & (VT_ENUM | VT_STRUCT)) && tok == ';') { |
| 3069 | 3109 | /* we accept no variable after */ |
| @@ -3130,16 +3170,67 @@ void decl(l) · 60 unmodified lines | ||
| 3130 | 3170 | u = VT_CONST; |
| 3131 | 3171 | u |= t; |
| 3132 | 3172 | 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 | + } | |
| 3133 | 3223 | 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"); | |
| 3138 | 3224 | loc = (loc - size) & -align; |
| 3139 | 3225 | addr = loc; |
| 3140 | 3226 | } else { |
| 3141 | 3227 | glo = (glo + align - 1) & -align; |
| 3142 | 3228 | 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; | |
| 3143 | 3234 | } |
| 3144 | 3235 | if (tok == '=') { |
| 3145 | 3236 | next(); |
| @@ -3149,20 +3240,17 @@ void decl(l) · 3 unmodified lines | ||
| 3149 | 3240 | n = 1; |
| 3150 | 3241 | next(); |
| 3151 | 3242 | } |
| 3152 | − decl_assign(u, addr, 1); | |
| 3243 | + decl_initializer(u, addr, 1, 0); | |
| 3153 | 3244 | if (n) |
| 3154 | 3245 | 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 | + } | |
| 3155 | 3252 | } |
| 3156 | 3253 | 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 | − } | |
| 3166 | 3254 | } |
| 3167 | 3255 | } |
| 3168 | 3256 | if (tok != ',') { |