forked from Mirrors/tinycc
added wide char and string parsing - added zero init of auto initializers
parent
0c6b2dcdfe
commit
4298fccb0c
161
tcc.c
161
tcc.c
|
@ -126,6 +126,7 @@ int nb_include_paths;
|
||||||
(only used for functions) */
|
(only used for functions) */
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
|
#define VT_INT 0
|
||||||
#define VT_VOID 0x00040
|
#define VT_VOID 0x00040
|
||||||
#define VT_BYTE 0x00080 /* signed byte type */
|
#define VT_BYTE 0x00080 /* signed byte type */
|
||||||
#define VT_PTR 0x00100 /* pointer increment */
|
#define VT_PTR 0x00100 /* pointer increment */
|
||||||
|
@ -173,8 +174,9 @@ int nb_include_paths;
|
||||||
#define TOK_NUM 0xb3 /* number in tokc */
|
#define TOK_NUM 0xb3 /* number in tokc */
|
||||||
#define TOK_CCHAR 0xb4 /* char constant in tokc */
|
#define TOK_CCHAR 0xb4 /* char constant in tokc */
|
||||||
#define TOK_STR 0xb5 /* pointer to string in tokc */
|
#define TOK_STR 0xb5 /* pointer to string in tokc */
|
||||||
|
|
||||||
#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
|
#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
|
||||||
|
#define TOK_LCHAR 0xb7
|
||||||
|
#define TOK_LSTR 0xb8
|
||||||
|
|
||||||
#define TOK_SHL 0x01 /* shift left */
|
#define TOK_SHL 0x01 /* shift left */
|
||||||
#define TOK_SAR 0x02 /* signed shift right */
|
#define TOK_SAR 0x02 /* signed shift right */
|
||||||
|
@ -425,14 +427,14 @@ char *get_tok_str(int v, int c)
|
||||||
if (v == TOK_NUM) {
|
if (v == TOK_NUM) {
|
||||||
sprintf(buf, "%d", c);
|
sprintf(buf, "%d", c);
|
||||||
return buf;
|
return buf;
|
||||||
} else if (v == TOK_CCHAR) {
|
} else if (v == TOK_CCHAR || v == TOK_LCHAR) {
|
||||||
p = buf;
|
p = buf;
|
||||||
*p++ = '\'';
|
*p++ = '\'';
|
||||||
add_char(&p, c);
|
add_char(&p, c);
|
||||||
*p++ = '\'';
|
*p++ = '\'';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return buf;
|
return buf;
|
||||||
} else if (v == TOK_STR) {
|
} else if (v == TOK_STR || v == TOK_LSTR) {
|
||||||
ts = (TokenSym *)c;
|
ts = (TokenSym *)c;
|
||||||
p = buf;
|
p = buf;
|
||||||
*p++ = '\"';
|
*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)
|
void tok_add(int **tok_str, int *tok_len, int t)
|
||||||
{
|
{
|
||||||
int len, *str;
|
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)
|
void tok_add2(int **tok_str, int *tok_len, int t, int c)
|
||||||
{
|
{
|
||||||
tok_add(tok_str, tok_len, t);
|
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);
|
tok_add(tok_str, tok_len, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,7 +730,7 @@ void tok_print(int *str)
|
||||||
if (!t)
|
if (!t)
|
||||||
break;
|
break;
|
||||||
c = 0;
|
c = 0;
|
||||||
if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR)
|
if (is_long_tok(t))
|
||||||
c = *str++;
|
c = *str++;
|
||||||
printf(" %s", get_tok_str(t, c));
|
printf(" %s", get_tok_str(t, c));
|
||||||
}
|
}
|
||||||
|
@ -1018,10 +1027,14 @@ void next_nomacro1()
|
||||||
if (q[-1] == 'L') {
|
if (q[-1] == 'L') {
|
||||||
/* XXX: not supported entirely (needs different
|
/* XXX: not supported entirely (needs different
|
||||||
preprocessor architecture) */
|
preprocessor architecture) */
|
||||||
if (ch == '\'')
|
if (ch == '\'') {
|
||||||
|
tok = TOK_LCHAR;
|
||||||
goto char_const;
|
goto char_const;
|
||||||
if (ch == '\"')
|
}
|
||||||
|
if (ch == '\"') {
|
||||||
|
tok = TOK_LSTR;
|
||||||
goto str_const;
|
goto str_const;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (isid(ch) | isnum(ch)) {
|
while (isid(ch) | isnum(ch)) {
|
||||||
if (q >= token_buf + STRING_MAX_SIZE)
|
if (q >= token_buf + STRING_MAX_SIZE)
|
||||||
|
@ -1052,14 +1065,15 @@ void next_nomacro1()
|
||||||
cinp();
|
cinp();
|
||||||
tok = TOK_NUM;
|
tok = TOK_NUM;
|
||||||
} else if (ch == '\'') {
|
} else if (ch == '\'') {
|
||||||
|
tok = TOK_CCHAR;
|
||||||
char_const:
|
char_const:
|
||||||
minp();
|
minp();
|
||||||
tokc = getq();
|
tokc = getq();
|
||||||
tok = TOK_CCHAR;
|
|
||||||
if (ch != '\'')
|
if (ch != '\'')
|
||||||
expect("\'");
|
expect("\'");
|
||||||
minp();
|
minp();
|
||||||
} else if (ch == '\"') {
|
} else if (ch == '\"') {
|
||||||
|
tok = TOK_STR;
|
||||||
str_const:
|
str_const:
|
||||||
minp();
|
minp();
|
||||||
q = token_buf;
|
q = token_buf;
|
||||||
|
@ -1073,7 +1087,6 @@ void next_nomacro1()
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
tokc = (int)tok_alloc(token_buf, q - token_buf);
|
tokc = (int)tok_alloc(token_buf, q - token_buf);
|
||||||
tok = TOK_STR;
|
|
||||||
minp();
|
minp();
|
||||||
} else {
|
} else {
|
||||||
q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
|
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;
|
tok = *macro_ptr;
|
||||||
if (tok) {
|
if (tok) {
|
||||||
macro_ptr++;
|
macro_ptr++;
|
||||||
if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_STR)
|
if (is_long_tok(tok))
|
||||||
tokc = *macro_ptr++;
|
tokc = *macro_ptr++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1153,7 +1166,7 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
||||||
strcat(token_buf, " ");
|
strcat(token_buf, " ");
|
||||||
t = *st++;
|
t = *st++;
|
||||||
c = 0;
|
c = 0;
|
||||||
if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR)
|
if (is_long_tok(t))
|
||||||
c = *st++;
|
c = *st++;
|
||||||
strcat(token_buf, get_tok_str(t, c));
|
strcat(token_buf, get_tok_str(t, c));
|
||||||
notfirst = 1;
|
notfirst = 1;
|
||||||
|
@ -1167,7 +1180,7 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
||||||
} else {
|
} else {
|
||||||
tok_add(&str, &len, t);
|
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++);
|
tok_add2(&str, &len, t, *macro_str++);
|
||||||
} else {
|
} else {
|
||||||
s = sym_find2(args, t);
|
s = sym_find2(args, t);
|
||||||
|
@ -1212,7 +1225,7 @@ int *macro_twosharps(int *macro_str)
|
||||||
if (t) {
|
if (t) {
|
||||||
macro_ptr++;
|
macro_ptr++;
|
||||||
c = 0;
|
c = 0;
|
||||||
if (t == TOK_NUM || t == TOK_CCHAR || t == TOK_STR)
|
if (is_long_tok(t))
|
||||||
c = *macro_ptr++;
|
c = *macro_ptr++;
|
||||||
/* XXX: we handle only most common cases:
|
/* XXX: we handle only most common cases:
|
||||||
ident + ident or ident + number */
|
ident + ident or ident + number */
|
||||||
|
@ -2314,10 +2327,10 @@ void indir()
|
||||||
|
|
||||||
void unary()
|
void unary()
|
||||||
{
|
{
|
||||||
int n, t, ft, fc, p, r;
|
int n, t, ft, fc, p, r, align;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
if (tok == TOK_NUM || tok == TOK_CCHAR) {
|
if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
|
||||||
vset(VT_CONST, tokc);
|
vset(VT_CONST, tokc);
|
||||||
next();
|
next();
|
||||||
} else if (tok == TOK___FUNC__) {
|
} else if (tok == TOK___FUNC__) {
|
||||||
|
@ -2326,17 +2339,22 @@ void unary()
|
||||||
vset(VT_CONST | mk_pointer(VT_BYTE), glo);
|
vset(VT_CONST | mk_pointer(VT_BYTE), glo);
|
||||||
strcpy((void *)glo, funcname);
|
strcpy((void *)glo, funcname);
|
||||||
glo += strlen(funcname) + 1;
|
glo += strlen(funcname) + 1;
|
||||||
|
} else if (tok == TOK_LSTR) {
|
||||||
|
t = VT_INT;
|
||||||
|
goto str_init;
|
||||||
} else if (tok == TOK_STR) {
|
} else if (tok == TOK_STR) {
|
||||||
TokenSym *ts;
|
/* string parsing */
|
||||||
/* generate (char *) type */
|
t = VT_BYTE;
|
||||||
vset(VT_CONST | mk_pointer(VT_BYTE), glo);
|
str_init:
|
||||||
while (tok == TOK_STR) {
|
type_size(t, &align);
|
||||||
ts = (TokenSym *)tokc;
|
glo = (glo + align - 1) & -align;
|
||||||
memcpy((void *)glo, ts->str, ts->len);
|
fc = glo;
|
||||||
glo += ts->len;
|
/* we must declare it as an array first to use initializer parser */
|
||||||
next();
|
t = VT_CONST | VT_ARRAY | mk_pointer(t);
|
||||||
}
|
decl_initializer(t, glo, 1, 0);
|
||||||
*(char *)glo++ = 0;
|
glo += type_size(t, &align);
|
||||||
|
/* put it as pointer */
|
||||||
|
vset(t & ~VT_ARRAY, fc);
|
||||||
} else {
|
} else {
|
||||||
t = tok;
|
t = tok;
|
||||||
next();
|
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
|
address. cur_index/cur_field is the pointer to the current
|
||||||
value. 'size_only' is true if only size info is needed (only used
|
value. 'size_only' is true if only size info is needed (only used
|
||||||
in arrays) */
|
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;
|
Sym *s, *f;
|
||||||
int notfirst, index, align;
|
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
|
/* 't' contains the type and storage info. c is the address of the
|
||||||
object. 'first' is true if array '{' must be read (multi dimension
|
object. 'first' is true if array '{' must be read (multi dimension
|
||||||
implicit array init handling). 'size_only' is true if size only
|
implicit array init handling). 'size_only' is true if size only
|
||||||
evaluation is wanted (only for arrays). */
|
evaluation is wanted (only for arrays). */
|
||||||
void decl_initializer(int t, int c, int first, int size_only)
|
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;
|
Sym *s, *f;
|
||||||
TokenSym *ts;
|
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));
|
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
|
||||||
n = s->c;
|
n = s->c;
|
||||||
array_length = 0;
|
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))
|
if (!(t1 & VT_BYTE))
|
||||||
error("invalid type");
|
error("invalid type");
|
||||||
|
str_init:
|
||||||
/* XXX: move multiple string parsing in parser ? */
|
/* XXX: move multiple string parsing in parser ? */
|
||||||
while (tok == TOK_STR) {
|
while (tok == TOK_STR || tok == TOK_LSTR) {
|
||||||
ts = (TokenSym *)tokc;
|
ts = (TokenSym *)tokc;
|
||||||
/* compute maximum number of chars wanted */
|
/* compute maximum number of chars wanted */
|
||||||
nb = ts->len;
|
nb = ts->len;
|
||||||
|
@ -3023,8 +3073,8 @@ void decl_initializer(int t, int c, int first, int size_only)
|
||||||
if (ts->len > nb)
|
if (ts->len > nb)
|
||||||
warning("initializer-string for array is too long");
|
warning("initializer-string for array is too long");
|
||||||
for(i=0;i<nb;i++) {
|
for(i=0;i<nb;i++) {
|
||||||
init_putv(t1, c, ts->str[i], 0);
|
init_putv(t1, c + (array_length + i) * size1,
|
||||||
c++;
|
ts->str[i], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array_length += nb;
|
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) */
|
warning in this case since it is standard) */
|
||||||
if (n < 0 || array_length < n) {
|
if (n < 0 || array_length < n) {
|
||||||
if (!size_only) {
|
if (!size_only) {
|
||||||
init_putv(t1, c, 0, 0);
|
init_putv(t1, c + (array_length * size1), 0, 0);
|
||||||
c++;
|
|
||||||
}
|
}
|
||||||
array_length++;
|
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);
|
decl_designator(t, c, &index, NULL, size_only);
|
||||||
if (n >= 0 && index >= n)
|
if (n >= 0 && index >= n)
|
||||||
error("index too large");
|
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++;
|
index++;
|
||||||
if (index > array_length)
|
if (index > array_length)
|
||||||
array_length = index;
|
array_length = index;
|
||||||
|
@ -3065,6 +3120,11 @@ void decl_initializer(int t, int c, int first, int size_only)
|
||||||
if (!no_oblock)
|
if (!no_oblock)
|
||||||
skip('}');
|
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 */
|
/* patch type size if needed */
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
s->c = array_length;
|
s->c = array_length;
|
||||||
|
@ -3073,13 +3133,34 @@ void decl_initializer(int t, int c, int first, int size_only)
|
||||||
skip('{');
|
skip('{');
|
||||||
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
|
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
|
||||||
f = s->next;
|
f = s->next;
|
||||||
|
array_length = 0;
|
||||||
|
index = 0;
|
||||||
|
n = s->c;
|
||||||
while (tok != '}') {
|
while (tok != '}') {
|
||||||
decl_designator(t, c, NULL, &f, size_only);
|
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 == '}')
|
if (tok == '}')
|
||||||
break;
|
break;
|
||||||
skip(',');
|
skip(',');
|
||||||
f = f->next;
|
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('}');
|
skip('}');
|
||||||
} else if (size_only) {
|
} else if (size_only) {
|
||||||
/* just skip expression */
|
/* just skip expression */
|
||||||
|
@ -3091,7 +3172,7 @@ void decl_initializer(int t, int c, int first, int size_only)
|
||||||
else if (tok == ')')
|
else if (tok == ')')
|
||||||
parlevel--;
|
parlevel--;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
init_putv(t, c, 0, 1);
|
init_putv(t, c, 0, 1);
|
||||||
}
|
}
|
||||||
|
@ -3114,7 +3195,7 @@ void decl(l)
|
||||||
t = type_decl(&v, b, TYPE_DIRECT);
|
t = type_decl(&v, b, TYPE_DIRECT);
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
if (!(t & VT_FUNC))
|
if (!(t & VT_FUNC))
|
||||||
expect("function defintion");
|
expect("function definition");
|
||||||
/* patch forward references */
|
/* patch forward references */
|
||||||
if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
|
if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
|
||||||
gsym(sym->c);
|
gsym(sym->c);
|
||||||
|
@ -3234,15 +3315,7 @@ void decl(l)
|
||||||
}
|
}
|
||||||
if (tok == '=') {
|
if (tok == '=') {
|
||||||
next();
|
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);
|
decl_initializer(u, addr, 1, 0);
|
||||||
if (n)
|
|
||||||
skip('}');
|
|
||||||
/* restore parse state if needed */
|
/* restore parse state if needed */
|
||||||
if (init_str) {
|
if (init_str) {
|
||||||
free(init_str);
|
free(init_str);
|
||||||
|
|
Loading…
Reference in New Issue