From 17818cd1bfa09c4e513b4ab465f20291477bf65e Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 5 Apr 2010 17:39:09 +0200 Subject: [PATCH] Add support for C99 VLA Add support for C99 Variable-Length Arrays --- tcc.h | 4 +++- tccgen.c | 43 ++++++++++++++++++++++++++++++++++++++++--- tccpp.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/tcc.h b/tcc.h index 3481f64..093b84c 100644 --- a/tcc.h +++ b/tcc.h @@ -146,7 +146,7 @@ typedef int BOOL; #define TOK_HASH_SIZE 8192 /* must be a power of two */ #define TOK_ALLOC_INCR 512 /* must be a power of two */ -#define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */ +#define TOK_MAX_SIZE 31 /* token max size in int unit when stored in string */ /* token symbol management */ typedef struct TokenSym { @@ -1041,6 +1041,8 @@ ST_FUNC void expr_prod(void); ST_FUNC void expr_sum(void); ST_FUNC void gexpr(void); ST_FUNC int expr_const(void); +/* varray */ +ST_FUNC int expr_check_const(void); ST_FUNC void gen_inline_functions(void); ST_FUNC void decl(int l); #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67 diff --git a/tccgen.c b/tccgen.c index be8d80f..8359827 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3016,9 +3016,33 @@ static void post_type(CType *type, AttributeDef *ad) next(); n = -1; if (tok != ']') { - n = expr_const(); - if (n < 0) - error("invalid array size"); + /* varray */ + if (expr_check_const()) { + n = vtop->c.i; + vpop(); + if (n < 0) + error("invalid array size"); + } else { + put_user_tok_start(); + put_user_tok('='); + put_user_tok(TOK_alloca); + put_user_tok('('); + while(tok != ']') { + put_user_tok(tok); + next(); + } + put_user_tok(')'); + skip(']'); + if (tok != ';') + error("not support varray type"); + put_user_tok(tok); + put_user_tok_end(); + next(); + s = sym_push(SYM_FIELD, type, 0, -1); + type->t = (VT_PTR | VT_CONSTANT); + type->ref = s; + return; + } } skip(']'); /* parse next post type */ @@ -4041,6 +4065,19 @@ ST_FUNC int expr_const(void) return c; } +/* varray */ +static int expr_check_const(void) +{ + int last_tok = tok; + expr_const1(); + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) { + unget_tok(last_tok); + return(FALSE); + } + return(TRUE); +} +/* ~varray */ + /* return the label token if current token is a label, otherwise return zero */ static int is_label(void) diff --git a/tccpp.c b/tccpp.c index f6f8a6a..a3babc4 100644 --- a/tccpp.c +++ b/tccpp.c @@ -54,6 +54,8 @@ ST_DATA TokenSym **table_ident; /* ------------------------------------------------------------------------- */ static int *macro_ptr_allocated; +static int *user_macro_ptr; +static int user_saved_buffer[TOK_MAX_SIZE + 1]; static const int *unget_saved_macro_ptr; static int unget_saved_buffer[TOK_MAX_SIZE + 1]; static int unget_buffer_enabled; @@ -2960,6 +2962,37 @@ ST_INLN void unget_tok(int last_tok) tok = last_tok; } +/* varray */ +ST_INLN void put_user_tok_start() +{ + user_macro_ptr = user_saved_buffer; +} + +ST_INLN void put_user_tok_end() +{ + const int user_tok_size = (uint32_t)user_macro_ptr - (uint32_t)user_saved_buffer; + + *user_macro_ptr = 0; + unget_buffer_enabled = 1; + if (macro_ptr) { + memmove((uint8_t*)macro_ptr+user_tok_size, macro_ptr, user_tok_size-1); + memcpy(macro_ptr, user_saved_buffer, user_tok_size-1); + } else { + macro_ptr = user_saved_buffer; + } +} + +ST_INLN void put_user_tok(int last_tok) +{ + int i, n; + + *user_macro_ptr++ = last_tok; + n = tok_ext_size(tok) - 1; + for(i=0;i