From 4298fccb0c7f33fd3cc9465d06b5d81160d85c9e Mon Sep 17 00:00:00 2001 From: bellard Date: Wed, 28 Nov 2001 22:48:43 +0000 Subject: [PATCH] added wide char and string parsing - added zero init of auto initializers --- tcc.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 44 deletions(-) diff --git a/tcc.c b/tcc.c index ca22f839..2eecc0e7 100644 --- a/tcc.c +++ b/tcc.c @@ -126,6 +126,7 @@ int nb_include_paths; (only used for functions) */ /* types */ +#define VT_INT 0 #define VT_VOID 0x00040 #define VT_BYTE 0x00080 /* signed byte type */ #define VT_PTR 0x00100 /* pointer increment */ @@ -173,8 +174,9 @@ int nb_include_paths; #define TOK_NUM 0xb3 /* number in tokc */ #define TOK_CCHAR 0xb4 /* char constant in tokc */ #define TOK_STR 0xb5 /* pointer to string in tokc */ - #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */ +#define TOK_LCHAR 0xb7 +#define TOK_LSTR 0xb8 #define TOK_SHL 0x01 /* shift left */ #define TOK_SAR 0x02 /* signed shift right */ @@ -425,14 +427,14 @@ char *get_tok_str(int v, int c) if (v == TOK_NUM) { sprintf(buf, "%d", c); return buf; - } else if (v == TOK_CCHAR) { + } else if (v == TOK_CCHAR || v == TOK_LCHAR) { p = buf; *p++ = '\''; add_char(&p, c); *p++ = '\''; *p = '\0'; return buf; - } else if (v == TOK_STR) { + } else if (v == TOK_STR || v == TOK_LSTR) { ts = (TokenSym *)c; p = buf; *p++ = '\"'; @@ -649,6 +651,13 @@ void preprocess_skip() } } +inline int is_long_tok(int t) +{ + return (t == TOK_NUM || + t == TOK_CCHAR || t == TOK_LCHAR || + t == TOK_STR || t == TOK_LSTR); +} + void tok_add(int **tok_str, int *tok_len, int t) { int len, *str; @@ -667,7 +676,7 @@ void tok_add(int **tok_str, int *tok_len, int t) void tok_add2(int **tok_str, int *tok_len, int t, int c) { tok_add(tok_str, tok_len, t); - if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR) + if (is_long_tok(t)) tok_add(tok_str, tok_len, c); } @@ -721,7 +730,7 @@ void tok_print(int *str) if (!t) break; c = 0; - if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR) + if (is_long_tok(t)) c = *str++; printf(" %s", get_tok_str(t, c)); } @@ -1018,10 +1027,14 @@ void next_nomacro1() if (q[-1] == 'L') { /* XXX: not supported entirely (needs different preprocessor architecture) */ - if (ch == '\'') + if (ch == '\'') { + tok = TOK_LCHAR; goto char_const; - if (ch == '\"') + } + if (ch == '\"') { + tok = TOK_LSTR; goto str_const; + } } while (isid(ch) | isnum(ch)) { if (q >= token_buf + STRING_MAX_SIZE) @@ -1052,14 +1065,15 @@ void next_nomacro1() cinp(); tok = TOK_NUM; } else if (ch == '\'') { + tok = TOK_CCHAR; char_const: minp(); tokc = getq(); - tok = TOK_CCHAR; if (ch != '\'') expect("\'"); minp(); } else if (ch == '\"') { + tok = TOK_STR; str_const: minp(); q = token_buf; @@ -1073,7 +1087,6 @@ void next_nomacro1() } *q = '\0'; tokc = (int)tok_alloc(token_buf, q - token_buf); - tok = TOK_STR; minp(); } else { q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266"; @@ -1115,7 +1128,7 @@ void next_nomacro() tok = *macro_ptr; if (tok) { macro_ptr++; - if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_STR) + if (is_long_tok(tok)) tokc = *macro_ptr++; } } else { @@ -1153,7 +1166,7 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) strcat(token_buf, " "); t = *st++; c = 0; - if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR) + if (is_long_tok(t)) c = *st++; strcat(token_buf, get_tok_str(t, c)); notfirst = 1; @@ -1167,7 +1180,7 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) } else { tok_add(&str, &len, t); } - } else if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR) { + } else if (is_long_tok(t)) { tok_add2(&str, &len, t, *macro_str++); } else { s = sym_find2(args, t); @@ -1212,7 +1225,7 @@ int *macro_twosharps(int *macro_str) if (t) { macro_ptr++; c = 0; - if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR) + if (is_long_tok(t)) c = *macro_ptr++; /* XXX: we handle only most common cases: ident + ident or ident + number */ @@ -2314,10 +2327,10 @@ void indir() void unary() { - int n, t, ft, fc, p, r; + int n, t, ft, fc, p, r, align; Sym *s; - if (tok == TOK_NUM || tok == TOK_CCHAR) { + if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) { vset(VT_CONST, tokc); next(); } else if (tok == TOK___FUNC__) { @@ -2326,17 +2339,22 @@ void unary() vset(VT_CONST | mk_pointer(VT_BYTE), glo); strcpy((void *)glo, funcname); glo += strlen(funcname) + 1; + } else if (tok == TOK_LSTR) { + t = VT_INT; + goto str_init; } else if (tok == TOK_STR) { - TokenSym *ts; - /* generate (char *) type */ - vset(VT_CONST | mk_pointer(VT_BYTE), glo); - while (tok == TOK_STR) { - ts = (TokenSym *)tokc; - memcpy((void *)glo, ts->str, ts->len); - glo += ts->len; - next(); - } - *(char *)glo++ = 0; + /* string parsing */ + t = VT_BYTE; + str_init: + type_size(t, &align); + glo = (glo + align - 1) & -align; + fc = glo; + /* we must declare it as an array first to use initializer parser */ + t = VT_CONST | VT_ARRAY | mk_pointer(t); + decl_initializer(t, glo, 1, 0); + glo += type_size(t, &align); + /* put it as pointer */ + vset(t & ~VT_ARRAY, fc); } else { t = tok; next(); @@ -2909,7 +2927,9 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) address. cur_index/cur_field is the pointer to the current value. 'size_only' is true if only size info is needed (only used in arrays) */ -void decl_designator(int t, int c, int *cur_index, Sym **cur_field, int size_only) +void decl_designator(int t, int c, + int *cur_index, Sym **cur_field, + int size_only) { Sym *s, *f; int notfirst, index, align; @@ -2994,13 +3014,37 @@ void init_putv(int t, int c, int v, int is_expr) } } +/* put zeros for variable based init */ +void init_putz(int t, int c, int size) +{ + int memset_addr, r; + + if ((t & VT_VALMASK) == VT_CONST) { + /* nothing to do because global are already set to zero */ + } else { + vset(VT_CONST, size); + r = gv(); + o(0x50 + r); + vset(VT_CONST, 0); + r = gv(); + o(0x50 + r); + vset(VT_LOCAL, c); + r = gv(); + o(0x50 + r); + memset_addr = (int)&memset; + oad(0xe8, memset_addr - ind - 5); + oad(0xc481, 3 * 4); + } +} + /* 't' contains the type and storage info. c is the address of the object. 'first' is true if array '{' must be read (multi dimension implicit array init handling). 'size_only' is true if size only evaluation is wanted (only for arrays). */ void decl_initializer(int t, int c, int first, int size_only) { - int index, array_length, t1, n, no_oblock, nb, parlevel, i; + int index, array_length, n, no_oblock, nb, parlevel, i; + int t1, size1, align1; Sym *s, *f; TokenSym *ts; @@ -3008,12 +3052,18 @@ void decl_initializer(int t, int c, int first, int size_only) s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT)); n = s->c; array_length = 0; - if (tok == TOK_STR) { - t1 = pointed_type(t); + t1 = pointed_type(t); + size1 = type_size(t1, &align1); + if (tok == TOK_LSTR) { + if ((t1 & VT_TYPE & ~VT_UNSIGNED) != VT_INT) + error("invalid type"); + goto str_init; + } else if (tok == TOK_STR) { if (!(t1 & VT_BYTE)) error("invalid type"); + str_init: /* XXX: move multiple string parsing in parser ? */ - while (tok == TOK_STR) { + while (tok == TOK_STR || tok == TOK_LSTR) { ts = (TokenSym *)tokc; /* compute maximum number of chars wanted */ nb = ts->len; @@ -3023,8 +3073,8 @@ void decl_initializer(int t, int c, int first, int size_only) if (ts->len > nb) warning("initializer-string for array is too long"); for(i=0;istr[i], 0); - c++; + init_putv(t1, c + (array_length + i) * size1, + ts->str[i], 0); } } array_length += nb; @@ -3034,8 +3084,7 @@ void decl_initializer(int t, int c, int first, int size_only) warning in this case since it is standard) */ if (n < 0 || array_length < n) { if (!size_only) { - init_putv(t1, c, 0, 0); - c++; + init_putv(t1, c + (array_length * size1), 0, 0); } array_length++; } @@ -3050,6 +3099,12 @@ void decl_initializer(int t, int c, int first, int size_only) decl_designator(t, c, &index, NULL, size_only); if (n >= 0 && index >= n) error("index too large"); + /* must put zero in holes (note that doing it that way + ensures that it even works with designators) */ + if (!size_only && array_length < index) { + init_putz(t1, c + array_length * size1, + (index - array_length) * size1); + } index++; if (index > array_length) array_length = index; @@ -3065,6 +3120,11 @@ void decl_initializer(int t, int c, int first, int size_only) if (!no_oblock) skip('}'); } + /* put zeros at the end */ + if (!size_only && n >= 0 && array_length < n) { + init_putz(t1, c + array_length * size1, + (n - array_length) * size1); + } /* patch type size if needed */ if (n < 0) s->c = array_length; @@ -3073,13 +3133,34 @@ void decl_initializer(int t, int c, int first, int size_only) skip('{'); s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT); f = s->next; + array_length = 0; + index = 0; + n = s->c; while (tok != '}') { decl_designator(t, c, NULL, &f, size_only); + /* fill with zero between fields */ + index = f->c; + if (!size_only && array_length < index) { + init_putz(t, c + array_length, + index - array_length); + } + index = index + type_size(f->t, &align1); + if (index > array_length) + array_length = index; if (tok == '}') break; skip(','); f = f->next; } + /* put zeros at the end */ + if (!size_only && array_length < n) { + init_putz(t, c + array_length, + n - array_length); + } + skip('}'); + } else if (tok == '{') { + next(); + decl_initializer(t, c, first, size_only); skip('}'); } else if (size_only) { /* just skip expression */ @@ -3091,7 +3172,7 @@ void decl_initializer(int t, int c, int first, int size_only) else if (tok == ')') parlevel--; next(); - } + } } else { init_putv(t, c, 0, 1); } @@ -3114,7 +3195,7 @@ void decl(l) t = type_decl(&v, b, TYPE_DIRECT); if (tok == '{') { if (!(t & VT_FUNC)) - expect("function defintion"); + expect("function definition"); /* patch forward references */ if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) { gsym(sym->c); @@ -3234,15 +3315,7 @@ void decl(l) } if (tok == '=') { next(); - /* special case for non array types */ - n = 0; - if (tok == '{' && (u & (VT_ARRAY | VT_STRUCT)) == 0) { - n = 1; - next(); - } decl_initializer(u, addr, 1, 0); - if (n) - skip('}'); /* restore parse state if needed */ if (init_str) { free(init_str); -- 2.11.4.GIT