Unified · Split
| @@ -264,7 +264,7 @@ int expr_const(); · 263 unmodified lines | |||
| 264 | void expr_eq(); | 264 | void expr_eq(); |
| 265 | void expr(); | 265 | void expr(); |
| 266 | void decl(); | 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 | int gv(); | 268 | int gv(); |
| 269 | void move_reg(); | 269 | void move_reg(); |
| 270 | void save_reg(); | 270 | void save_reg(); |
| @@ -1168,7 +1168,7 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) · 897 unmodified lines | |||
| 1168 | tok_add(&str, &len, t); | 1168 | tok_add(&str, &len, t); |
| 1169 | } | 1169 | } |
| 1170 | } else if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR) { | 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 | } else { | 1172 | } else { |
| 1173 | s = sym_find2(args, t); | 1173 | s = sym_find2(args, t); |
| 1174 | if (s) { | 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 | /* t is the array or struct type. c is the array or struct | 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 */ | 2909 | address. cur_index/cur_field is the pointer to the current |
| 2910 | void decl_designator(int t, int c, int *cur_index, Sym **cur_field) | 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 | Sym *s, *f; | 2914 | Sym *s, *f; |
| 2913 | int notfirst, index, align; | 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 | c += f->c; | 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 | /* 't' contains the type and storage info. c is the address of the | 2997 | /* 't' contains the type and storage info. c is the address of the |
| 2971 | object. 'first' is true if array '{' must be read (multi dimension | 2998 | object. 'first' is true if array '{' must be read (multi dimension |
| 2972 | implicit array init handling). */ | 2999 | implicit array init handling). 'size_only' is true if size only |
| 2973 | void decl_assign(int t, int c, int first) | 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 | Sym *s, *f; | 3004 | Sym *s, *f; |
| 2977 | TokenSym *ts; | 3005 | TokenSym *ts; |
| 2978 | 3006 | ||
| 2979 | if (t & VT_ARRAY) { | 3007 | if (t & VT_ARRAY) { |
| 2980 | s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT)); | 3008 | s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT)); |
| 2981 | n = s->c; | 3009 | n = s->c; |
| 2982 | index_max = 0; | 3010 | array_length = 0; |
| 2983 | if (tok == TOK_STR) { | 3011 | if (tok == TOK_STR) { |
| 2984 | t1 = pointed_type(t); | 3012 | t1 = pointed_type(t); |
| 2985 | if (!(t1 & VT_BYTE)) | 3013 | if (!(t1 & VT_BYTE)) |
| 2986 | error("invalid type"); | 3014 | error("invalid type"); |
| 2987 | if ((t & VT_VALMASK) == VT_CONST) { | 3015 | /* XXX: move multiple string parsing in parser ? */ |
| 2988 | while (tok == TOK_STR) { | 3016 | while (tok == TOK_STR) { |
| 2989 | ts = (TokenSym *)tokc; | 3017 | ts = (TokenSym *)tokc; |
| 2990 | memcpy((void *)c, ts->str, ts->len); | 3018 | /* compute maximum number of chars wanted */ |
| 2991 | c += ts->len; | 3019 | nb = ts->len; |
| 2992 | index_max += ts->len; | 3020 | if (n >= 0 && nb > (n - array_length)) |
| 2993 | next(); | 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; | 3030 | array_length += nb; |
| 2996 | } else { | 3031 | next(); |
| 2997 | error("local string init not handled"); | 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 | } else { | 3042 | } else { |
| 3001 | no_oblock = 0; | 3043 | no_oblock = 0; |
| 3002 | if (!first && tok != '{') | 3044 | if (!first && tok != '{') |
| @@ -3005,12 +3047,12 @@ void decl_assign(int t, int c, int first) · 2 unmodified lines | |||
| 3005 | skip('{'); | 3047 | skip('{'); |
| 3006 | index = 0; | 3048 | index = 0; |
| 3007 | while (tok != '}') { | 3049 | while (tok != '}') { |
| 3008 | decl_designator(t, c, &index, NULL); | 3050 | decl_designator(t, c, &index, NULL, size_only); |
| 3009 | if (n >= 0 && index >= n) | 3051 | if (n >= 0 && index >= n) |
| 3010 | error("index too large"); | 3052 | error("index too large"); |
| 3011 | if (index > index_max) | ||
| 3012 | index_max = index; | ||
| 3013 | index++; | 3053 | index++; |
| 3054 | if (index > array_length) | ||
| 3055 | array_length = index; | ||
| 3014 | /* special test for multi dimensional arrays (may not | 3056 | /* special test for multi dimensional arrays (may not |
| 3015 | be strictly correct if designators are used at the | 3057 | be strictly correct if designators are used at the |
| 3016 | same time) */ | 3058 | same time) */ |
| @@ -3025,45 +3067,43 @@ void decl_assign(int t, int c, int first) · 8 unmodified lines | |||
| 3025 | } | 3067 | } |
| 3026 | /* patch type size if needed */ | 3068 | /* patch type size if needed */ |
| 3027 | if (n < 0) | 3069 | if (n < 0) |
| 3028 | s->c = index_max + 1; | 3070 | s->c = array_length; |
| 3029 | } else if (t & VT_STRUCT) { | 3071 | } else if (t & VT_STRUCT) { |
| 3030 | /* XXX: union needs only one init */ | 3072 | /* XXX: union needs only one init */ |
| 3031 | skip('{'); | 3073 | skip('{'); |
| 3032 | s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT); | 3074 | s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT); |
| 3033 | f = s->next; | 3075 | f = s->next; |
| 3034 | while (tok != '}') { | 3076 | while (tok != '}') { |
| 3035 | decl_designator(t, c, NULL, &f); | 3077 | decl_designator(t, c, NULL, &f, size_only); |
| 3036 | if (tok == '}') | 3078 | if (tok == '}') |
| 3037 | break; | 3079 | break; |
| 3038 | skip(','); | 3080 | skip(','); |
| 3039 | f = f->next; | 3081 | f = f->next; |
| 3040 | } | 3082 | } |
| 3041 | skip('}'); | 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 | } else { | 3095 | } else { |
| 3043 | if ((t & VT_VALMASK) == VT_CONST) { | 3096 | init_putv(t, c, 0, 1); |
| 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 | } | ||
| 3058 | } | 3097 | } |
| 3059 | } | 3098 | } |
| 3060 | 3099 | ||
| 3061 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ | 3100 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ |
| 3062 | void decl(l) | 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 | Sym *sym; | 3104 | Sym *sym; |
| 3066 | 3105 | int *init_str, init_len, level, *saved_macro_ptr; | |
| 3106 | |||
| 3067 | while (b = ist()) { | 3107 | while (b = ist()) { |
| 3068 | if ((b & (VT_ENUM | VT_STRUCT)) && tok == ';') { | 3108 | if ((b & (VT_ENUM | VT_STRUCT)) && tok == ';') { |
| 3069 | /* we accept no variable after */ | 3109 | /* we accept no variable after */ |
| @@ -3130,16 +3170,67 @@ void decl(l) · 60 unmodified lines | |||
| 3130 | u = VT_CONST; | 3170 | u = VT_CONST; |
| 3131 | u |= t; | 3171 | u |= t; |
| 3132 | size = type_size(t, &align); | 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 | if ((u & VT_VALMASK) == VT_LOCAL) { | 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 | loc = (loc - size) & -align; | 3224 | loc = (loc - size) & -align; |
| 3139 | addr = loc; | 3225 | addr = loc; |
| 3140 | } else { | 3226 | } else { |
| 3141 | glo = (glo + align - 1) & -align; | 3227 | glo = (glo + align - 1) & -align; |
| 3142 | addr = glo; | 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 | if (tok == '=') { | 3235 | if (tok == '=') { |
| 3145 | next(); | 3236 | next(); |
| @@ -3149,20 +3240,17 @@ void decl(l) · 3 unmodified lines | |||
| 3149 | n = 1; | 3240 | n = 1; |
| 3150 | next(); | 3241 | next(); |
| 3151 | } | 3242 | } |
| 3152 | decl_assign(u, addr, 1); | 3243 | decl_initializer(u, addr, 1, 0); |
| 3153 | if (n) | 3244 | if (n) |
| 3154 | skip('}'); | 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 | sym_push(v, u, addr); | 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 | if (tok != ',') { | 3256 | if (tok != ',') { |