mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-10 08:50:07 +08:00
CStrings leakless
avoid memory leaks with lost CStrings on stack after errors. tccpp.c: - use/abuse static Cstring tokcstr where possible tccgen.c: - use/abuse static Cstring initstr where possible tcc.h/libtcc.a: - add 'stk_data' array to track memory pointer on stack - add macros stk_push/pop() and cstr_new/free_s() tccasm.c: - use that - use char[16] instead of char* for op.constraint
This commit is contained in:
parent
40131b7e0f
commit
a045400501
8
libtcc.c
8
libtcc.c
@ -68,6 +68,9 @@
|
|||||||
/* XXX: get rid of this ASAP (or maybe not) */
|
/* XXX: get rid of this ASAP (or maybe not) */
|
||||||
ST_DATA struct TCCState *tcc_state;
|
ST_DATA struct TCCState *tcc_state;
|
||||||
TCC_SEM(static tcc_compile_sem);
|
TCC_SEM(static tcc_compile_sem);
|
||||||
|
/* an array of pointers to memory to be free'd after errors */
|
||||||
|
ST_DATA void** stk_data;
|
||||||
|
ST_DATA int nb_stk_data;
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -609,9 +612,12 @@ static void error1(int mode, const char *fmt, va_list ap)
|
|||||||
cstr_free(&cs);
|
cstr_free(&cs);
|
||||||
if (mode != ERROR_WARN)
|
if (mode != ERROR_WARN)
|
||||||
s1->nb_errors++;
|
s1->nb_errors++;
|
||||||
if (mode == ERROR_ERROR && s1->error_set_jmp_enabled)
|
if (mode == ERROR_ERROR && s1->error_set_jmp_enabled) {
|
||||||
|
while (nb_stk_data)
|
||||||
|
tcc_free(*(void**)stk_data[--nb_stk_data]);
|
||||||
longjmp(s1->error_jmp_buf, 1);
|
longjmp(s1->error_jmp_buf, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func)
|
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func)
|
||||||
{
|
{
|
||||||
|
17
tcc.h
17
tcc.h
@ -495,6 +495,7 @@ typedef struct CString {
|
|||||||
int size; /* size in bytes */
|
int size; /* size in bytes */
|
||||||
int size_allocated;
|
int size_allocated;
|
||||||
void *data; /* either 'char *' or 'nwchar_t *' */
|
void *data; /* either 'char *' or 'nwchar_t *' */
|
||||||
|
struct CString *prev;
|
||||||
} CString;
|
} CString;
|
||||||
|
|
||||||
/* type definition */
|
/* type definition */
|
||||||
@ -733,7 +734,7 @@ typedef struct ExprValue {
|
|||||||
#define MAX_ASM_OPERANDS 30
|
#define MAX_ASM_OPERANDS 30
|
||||||
typedef struct ASMOperand {
|
typedef struct ASMOperand {
|
||||||
int id; /* GCC 3 optional identifier (0 if number only supported) */
|
int id; /* GCC 3 optional identifier (0 if number only supported) */
|
||||||
char *constraint;
|
char constraint[16];
|
||||||
char asm_str[16]; /* computed asm string for operand */
|
char asm_str[16]; /* computed asm string for operand */
|
||||||
SValue *vt; /* C value of the expression */
|
SValue *vt; /* C value of the expression */
|
||||||
int ref_index; /* if >= 0, gives reference to a output constraint */
|
int ref_index; /* if >= 0, gives reference to a output constraint */
|
||||||
@ -1208,6 +1209,8 @@ enum tcc_token {
|
|||||||
/* ------------ libtcc.c ------------ */
|
/* ------------ libtcc.c ------------ */
|
||||||
|
|
||||||
ST_DATA struct TCCState *tcc_state;
|
ST_DATA struct TCCState *tcc_state;
|
||||||
|
ST_DATA void** stk_data;
|
||||||
|
ST_DATA int nb_stk_data;
|
||||||
|
|
||||||
/* public functions currently used by the tcc main function */
|
/* public functions currently used by the tcc main function */
|
||||||
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
|
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
|
||||||
@ -1257,11 +1260,17 @@ ST_FUNC void cstr_free(CString *cstr);
|
|||||||
ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3);
|
ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||||
ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
|
ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
|
||||||
ST_FUNC void cstr_reset(CString *cstr);
|
ST_FUNC void cstr_reset(CString *cstr);
|
||||||
|
|
||||||
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
|
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
|
||||||
ST_FUNC int tcc_open(TCCState *s1, const char *filename);
|
ST_FUNC int tcc_open(TCCState *s1, const char *filename);
|
||||||
ST_FUNC void tcc_close(void);
|
ST_FUNC void tcc_close(void);
|
||||||
|
|
||||||
|
/* mark a memory pointer on stack for cleanup after errors */
|
||||||
|
#define stk_push(p) dynarray_add(&stk_data, &nb_stk_data, p)
|
||||||
|
#define stk_pop() (--nb_stk_data)
|
||||||
|
/* mark CString on stack for cleanup errors */
|
||||||
|
#define cstr_new_s(cstr) (cstr_new(cstr), stk_push(&(cstr)->data))
|
||||||
|
#define cstr_free_s(cstr) (cstr_free(cstr), stk_pop())
|
||||||
|
|
||||||
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
|
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
|
||||||
/* flags: */
|
/* flags: */
|
||||||
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
|
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
|
||||||
@ -1483,8 +1492,8 @@ ST_FUNC int type_size(CType *type, int *a);
|
|||||||
ST_FUNC void mk_pointer(CType *type);
|
ST_FUNC void mk_pointer(CType *type);
|
||||||
ST_FUNC void vstore(void);
|
ST_FUNC void vstore(void);
|
||||||
ST_FUNC void inc(int post, int c);
|
ST_FUNC void inc(int post, int c);
|
||||||
ST_FUNC void parse_mult_str (CString *astr, const char *msg);
|
ST_FUNC CString* parse_mult_str(const char *msg);
|
||||||
ST_FUNC void parse_asm_str(CString *astr);
|
ST_FUNC CString* parse_asm_str(void);
|
||||||
ST_FUNC void indir(void);
|
ST_FUNC void indir(void);
|
||||||
ST_FUNC void unary(void);
|
ST_FUNC void unary(void);
|
||||||
ST_FUNC void gexpr(void);
|
ST_FUNC void gexpr(void);
|
||||||
|
48
tccasm.c
48
tccasm.c
@ -1064,15 +1064,12 @@ ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
||||||
CString *out_str, CString *in_str)
|
CString *out_str, const char *str)
|
||||||
{
|
{
|
||||||
int c, index, modifier;
|
int c, index, modifier;
|
||||||
const char *str;
|
|
||||||
ASMOperand *op;
|
ASMOperand *op;
|
||||||
SValue sv;
|
SValue sv;
|
||||||
|
|
||||||
cstr_new(out_str);
|
|
||||||
str = in_str->data;
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
c = *str++;
|
c = *str++;
|
||||||
if (c == '%') {
|
if (c == '%') {
|
||||||
@ -1118,11 +1115,11 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||||||
{
|
{
|
||||||
ASMOperand *op;
|
ASMOperand *op;
|
||||||
int nb_operands;
|
int nb_operands;
|
||||||
|
char* astr;
|
||||||
|
|
||||||
if (tok != ':') {
|
if (tok != ':') {
|
||||||
nb_operands = *nb_operands_ptr;
|
nb_operands = *nb_operands_ptr;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
CString astr;
|
|
||||||
if (nb_operands >= MAX_ASM_OPERANDS)
|
if (nb_operands >= MAX_ASM_OPERANDS)
|
||||||
tcc_error("too many asm operands");
|
tcc_error("too many asm operands");
|
||||||
op = &operands[nb_operands++];
|
op = &operands[nb_operands++];
|
||||||
@ -1135,10 +1132,8 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||||||
next();
|
next();
|
||||||
skip(']');
|
skip(']');
|
||||||
}
|
}
|
||||||
parse_mult_str(&astr, "string constant");
|
astr = parse_mult_str("string constant")->data;
|
||||||
op->constraint = tcc_malloc(astr.size);
|
pstrcpy(op->constraint, sizeof op->constraint, astr);
|
||||||
strcpy(op->constraint, astr.data);
|
|
||||||
cstr_free(&astr);
|
|
||||||
skip('(');
|
skip('(');
|
||||||
gexpr();
|
gexpr();
|
||||||
if (is_output) {
|
if (is_output) {
|
||||||
@ -1171,7 +1166,8 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||||||
/* parse the GCC asm() instruction */
|
/* parse the GCC asm() instruction */
|
||||||
ST_FUNC void asm_instr(void)
|
ST_FUNC void asm_instr(void)
|
||||||
{
|
{
|
||||||
CString astr, astr1;
|
CString astr, *astr1;
|
||||||
|
|
||||||
ASMOperand operands[MAX_ASM_OPERANDS];
|
ASMOperand operands[MAX_ASM_OPERANDS];
|
||||||
int nb_outputs, nb_operands, i, must_subst, out_reg, nb_labels;
|
int nb_outputs, nb_operands, i, must_subst, out_reg, nb_labels;
|
||||||
uint8_t clobber_regs[NB_ASM_REGS];
|
uint8_t clobber_regs[NB_ASM_REGS];
|
||||||
@ -1183,7 +1179,11 @@ ST_FUNC void asm_instr(void)
|
|||||||
|| tok == TOK_GOTO) {
|
|| tok == TOK_GOTO) {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
parse_asm_str(&astr);
|
|
||||||
|
astr1 = parse_asm_str();
|
||||||
|
cstr_new_s(&astr);
|
||||||
|
cstr_cat(&astr, astr1->data, astr1->size);
|
||||||
|
|
||||||
nb_operands = 0;
|
nb_operands = 0;
|
||||||
nb_outputs = 0;
|
nb_outputs = 0;
|
||||||
nb_labels = 0;
|
nb_labels = 0;
|
||||||
@ -1273,13 +1273,14 @@ ST_FUNC void asm_instr(void)
|
|||||||
printf("asm: \"%s\"\n", (char *)astr.data);
|
printf("asm: \"%s\"\n", (char *)astr.data);
|
||||||
#endif
|
#endif
|
||||||
if (must_subst) {
|
if (must_subst) {
|
||||||
subst_asm_operands(operands, nb_operands + nb_labels, &astr1, &astr);
|
cstr_reset(astr1);
|
||||||
cstr_free(&astr);
|
cstr_cat(astr1, astr.data, astr.size);
|
||||||
} else {
|
cstr_reset(&astr);
|
||||||
astr1 = astr;
|
subst_asm_operands(operands, nb_operands + nb_labels, &astr, astr1->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASM_DEBUG
|
#ifdef ASM_DEBUG
|
||||||
printf("subst_asm: \"%s\"\n", (char *)astr1.data);
|
printf("subst_asm: \"%s\"\n", (char *)astr.data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* generate loads */
|
/* generate loads */
|
||||||
@ -1290,7 +1291,8 @@ ST_FUNC void asm_instr(void)
|
|||||||
bleed out to surrounding code. */
|
bleed out to surrounding code. */
|
||||||
sec = cur_text_section;
|
sec = cur_text_section;
|
||||||
/* assemble the string with tcc internal assembler */
|
/* assemble the string with tcc internal assembler */
|
||||||
tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1, 0);
|
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 0);
|
||||||
|
cstr_free_s(&astr);
|
||||||
if (sec != cur_text_section) {
|
if (sec != cur_text_section) {
|
||||||
tcc_warning("inline asm tries to change current section");
|
tcc_warning("inline asm tries to change current section");
|
||||||
use_section1(tcc_state, sec);
|
use_section1(tcc_state, sec);
|
||||||
@ -1305,23 +1307,20 @@ ST_FUNC void asm_instr(void)
|
|||||||
|
|
||||||
/* free everything */
|
/* free everything */
|
||||||
for(i=0;i<nb_operands;i++) {
|
for(i=0;i<nb_operands;i++) {
|
||||||
ASMOperand *op;
|
|
||||||
op = &operands[i];
|
|
||||||
tcc_free(op->constraint);
|
|
||||||
vpop();
|
vpop();
|
||||||
}
|
}
|
||||||
cstr_free(&astr1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_global_instr(void)
|
ST_FUNC void asm_global_instr(void)
|
||||||
{
|
{
|
||||||
CString astr;
|
CString *astr;
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
|
|
||||||
/* Global asm blocks are always emitted. */
|
/* Global asm blocks are always emitted. */
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
next();
|
next();
|
||||||
parse_asm_str(&astr);
|
astr = parse_asm_str();
|
||||||
skip(')');
|
skip(')');
|
||||||
/* NOTE: we do not eat the ';' so that we can restore the current
|
/* NOTE: we do not eat the ';' so that we can restore the current
|
||||||
token after the assembler parsing */
|
token after the assembler parsing */
|
||||||
@ -1335,14 +1334,13 @@ ST_FUNC void asm_global_instr(void)
|
|||||||
ind = cur_text_section->data_offset;
|
ind = cur_text_section->data_offset;
|
||||||
|
|
||||||
/* assemble the string with tcc internal assembler */
|
/* assemble the string with tcc internal assembler */
|
||||||
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 1);
|
tcc_assemble_inline(tcc_state, astr->data, astr->size - 1, 1);
|
||||||
|
|
||||||
cur_text_section->data_offset = ind;
|
cur_text_section->data_offset = ind;
|
||||||
|
|
||||||
/* restore the current C token */
|
/* restore the current C token */
|
||||||
next();
|
next();
|
||||||
|
|
||||||
cstr_free(&astr);
|
|
||||||
nocode_wanted = saved_nocode_wanted;
|
nocode_wanted = saved_nocode_wanted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
74
tccgen.c
74
tccgen.c
@ -402,7 +402,6 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
|||||||
ST_FUNC void tccgen_finish(TCCState *s1)
|
ST_FUNC void tccgen_finish(TCCState *s1)
|
||||||
{
|
{
|
||||||
tcc_debug_end(s1); /* just in case of errors: free memory */
|
tcc_debug_end(s1); /* just in case of errors: free memory */
|
||||||
cstr_free(&initstr);
|
|
||||||
free_inline_functions(s1);
|
free_inline_functions(s1);
|
||||||
sym_pop(&global_stack, NULL, 0);
|
sym_pop(&global_stack, NULL, 0);
|
||||||
sym_pop(&local_stack, NULL, 0);
|
sym_pop(&local_stack, NULL, 0);
|
||||||
@ -412,6 +411,8 @@ ST_FUNC void tccgen_finish(TCCState *s1)
|
|||||||
dynarray_reset(&sym_pools, &nb_sym_pools);
|
dynarray_reset(&sym_pools, &nb_sym_pools);
|
||||||
sym_free_first = NULL;
|
sym_free_first = NULL;
|
||||||
global_label_stack = local_label_stack = NULL;
|
global_label_stack = local_label_stack = NULL;
|
||||||
|
cstr_free(&initstr);
|
||||||
|
dynarray_reset(&stk_data, &nb_stk_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@ -3756,18 +3757,19 @@ ST_FUNC void inc(int post, int c)
|
|||||||
vpop(); /* if post op, return saved value */
|
vpop(); /* if post op, return saved value */
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void parse_mult_str (CString *astr, const char *msg)
|
ST_FUNC CString* parse_mult_str (const char *msg)
|
||||||
{
|
{
|
||||||
/* read the string */
|
/* read the string */
|
||||||
if (tok != TOK_STR)
|
if (tok != TOK_STR)
|
||||||
expect(msg);
|
expect(msg);
|
||||||
cstr_new(astr);
|
cstr_reset(&initstr);
|
||||||
while (tok == TOK_STR) {
|
while (tok == TOK_STR) {
|
||||||
/* XXX: add \0 handling too ? */
|
/* XXX: add \0 handling too ? */
|
||||||
cstr_cat(astr, tokc.str.data, -1);
|
cstr_cat(&initstr, tokc.str.data, -1);
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
cstr_ccat(astr, '\0');
|
cstr_ccat(&initstr, '\0');
|
||||||
|
return &initstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If I is >= 1 and a power of two, returns log2(i)+1.
|
/* If I is >= 1 and a power of two, returns log2(i)+1.
|
||||||
@ -3792,7 +3794,7 @@ ST_FUNC int exact_log2p1(int i)
|
|||||||
static void parse_attribute(AttributeDef *ad)
|
static void parse_attribute(AttributeDef *ad)
|
||||||
{
|
{
|
||||||
int t, n;
|
int t, n;
|
||||||
CString astr;
|
char *astr;
|
||||||
|
|
||||||
redo:
|
redo:
|
||||||
if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2)
|
if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2)
|
||||||
@ -3839,37 +3841,33 @@ redo:
|
|||||||
case TOK_SECTION1:
|
case TOK_SECTION1:
|
||||||
case TOK_SECTION2:
|
case TOK_SECTION2:
|
||||||
skip('(');
|
skip('(');
|
||||||
parse_mult_str(&astr, "section name");
|
astr = parse_mult_str("section name")->data;
|
||||||
ad->section = find_section(tcc_state, (char *)astr.data);
|
ad->section = find_section(tcc_state, astr);
|
||||||
skip(')');
|
skip(')');
|
||||||
cstr_free(&astr);
|
|
||||||
break;
|
break;
|
||||||
case TOK_ALIAS1:
|
case TOK_ALIAS1:
|
||||||
case TOK_ALIAS2:
|
case TOK_ALIAS2:
|
||||||
skip('(');
|
skip('(');
|
||||||
parse_mult_str(&astr, "alias(\"target\")");
|
astr = parse_mult_str("alias(\"target\")")->data;
|
||||||
ad->alias_target = /* save string as token, for later */
|
/* save string as token, for later */
|
||||||
tok_alloc((char*)astr.data, astr.size-1)->tok;
|
ad->alias_target = tok_alloc_const(astr);
|
||||||
skip(')');
|
skip(')');
|
||||||
cstr_free(&astr);
|
|
||||||
break;
|
break;
|
||||||
case TOK_VISIBILITY1:
|
case TOK_VISIBILITY1:
|
||||||
case TOK_VISIBILITY2:
|
case TOK_VISIBILITY2:
|
||||||
skip('(');
|
skip('(');
|
||||||
parse_mult_str(&astr,
|
astr = parse_mult_str("visibility(\"default|hidden|internal|protected\")")->data;
|
||||||
"visibility(\"default|hidden|internal|protected\")");
|
if (!strcmp (astr, "default"))
|
||||||
if (!strcmp (astr.data, "default"))
|
|
||||||
ad->a.visibility = STV_DEFAULT;
|
ad->a.visibility = STV_DEFAULT;
|
||||||
else if (!strcmp (astr.data, "hidden"))
|
else if (!strcmp (astr, "hidden"))
|
||||||
ad->a.visibility = STV_HIDDEN;
|
ad->a.visibility = STV_HIDDEN;
|
||||||
else if (!strcmp (astr.data, "internal"))
|
else if (!strcmp (astr, "internal"))
|
||||||
ad->a.visibility = STV_INTERNAL;
|
ad->a.visibility = STV_INTERNAL;
|
||||||
else if (!strcmp (astr.data, "protected"))
|
else if (!strcmp (astr, "protected"))
|
||||||
ad->a.visibility = STV_PROTECTED;
|
ad->a.visibility = STV_PROTECTED;
|
||||||
else
|
else
|
||||||
expect("visibility(\"default|hidden|internal|protected\")");
|
expect("visibility(\"default|hidden|internal|protected\")");
|
||||||
skip(')');
|
skip(')');
|
||||||
cstr_free(&astr);
|
|
||||||
break;
|
break;
|
||||||
case TOK_ALIGNED1:
|
case TOK_ALIGNED1:
|
||||||
case TOK_ALIGNED2:
|
case TOK_ALIGNED2:
|
||||||
@ -4818,26 +4816,25 @@ static inline void convert_parameter_type(CType *pt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void parse_asm_str(CString *astr)
|
ST_FUNC CString* parse_asm_str(void)
|
||||||
{
|
{
|
||||||
skip('(');
|
skip('(');
|
||||||
parse_mult_str(astr, "string constant");
|
return parse_mult_str("string constant");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse an asm label and return the token */
|
/* Parse an asm label and return the token */
|
||||||
static int asm_label_instr(void)
|
static int asm_label_instr(void)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
CString astr;
|
char *astr;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
parse_asm_str(&astr);
|
astr = parse_asm_str()->data;
|
||||||
skip(')');
|
skip(')');
|
||||||
#ifdef ASM_DEBUG
|
#ifdef ASM_DEBUG
|
||||||
printf("asm_alias: \"%s\"\n", (char *)astr.data);
|
printf("asm_alias: \"%s\"\n", astr);
|
||||||
#endif
|
#endif
|
||||||
v = tok_alloc(astr.data, astr.size - 1)->tok;
|
v = tok_alloc_const(astr);
|
||||||
cstr_free(&astr);
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8357,28 +8354,22 @@ static void free_inline_functions(TCCState *s)
|
|||||||
dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
|
dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_Static_assert(void){
|
static void do_Static_assert(void)
|
||||||
CString error_str;
|
{
|
||||||
int c;
|
int c;
|
||||||
|
const char *msg;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
skip('(');
|
skip('(');
|
||||||
c = expr_const();
|
c = expr_const();
|
||||||
|
msg = "_Static_assert fail";
|
||||||
if (tok == ')') {
|
if (tok == ',') {
|
||||||
if (!c)
|
|
||||||
tcc_error("_Static_assert fail");
|
|
||||||
next();
|
next();
|
||||||
goto static_assert_out;
|
msg = parse_mult_str("string constant")->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip(',');
|
|
||||||
parse_mult_str(&error_str, "string constant");
|
|
||||||
if (c == 0)
|
|
||||||
tcc_error("%s", (char *)error_str.data);
|
|
||||||
cstr_free(&error_str);
|
|
||||||
skip(')');
|
skip(')');
|
||||||
static_assert_out:
|
if (c == 0)
|
||||||
|
tcc_error("%s", msg);
|
||||||
skip(';');
|
skip(';');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8393,6 +8384,7 @@ static int decl(int l)
|
|||||||
AttributeDef ad, adbase;
|
AttributeDef ad, adbase;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
if (tok == TOK_STATIC_ASSERT) {
|
if (tok == TOK_STATIC_ASSERT) {
|
||||||
do_Static_assert();
|
do_Static_assert();
|
||||||
continue;
|
continue;
|
||||||
|
82
tccpp.c
82
tccpp.c
@ -45,7 +45,6 @@ ST_DATA TokenSym **table_ident;
|
|||||||
static TokenSym *hash_ident[TOK_HASH_SIZE];
|
static TokenSym *hash_ident[TOK_HASH_SIZE];
|
||||||
static char token_buf[STRING_MAX_SIZE + 1];
|
static char token_buf[STRING_MAX_SIZE + 1];
|
||||||
static CString cstr_buf;
|
static CString cstr_buf;
|
||||||
static CString macro_equal_buf;
|
|
||||||
static TokenString tokstr_buf;
|
static TokenString tokstr_buf;
|
||||||
static unsigned char isidnum_table[256 - CH_EOF];
|
static unsigned char isidnum_table[256 - CH_EOF];
|
||||||
static int pp_debug_tok, pp_debug_symv;
|
static int pp_debug_tok, pp_debug_symv;
|
||||||
@ -399,7 +398,6 @@ ST_FUNC void cstr_new(CString *cstr)
|
|||||||
ST_FUNC void cstr_free(CString *cstr)
|
ST_FUNC void cstr_free(CString *cstr)
|
||||||
{
|
{
|
||||||
tcc_free(cstr->data);
|
tcc_free(cstr->data);
|
||||||
cstr_new(cstr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset string to empty */
|
/* reset string to empty */
|
||||||
@ -1273,12 +1271,11 @@ static int macro_is_equal(const int *a, const int *b)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
while (*a && *b) {
|
while (*a && *b) {
|
||||||
/* first time preallocate macro_equal_buf, next time only reset position to start */
|
cstr_reset(&tokcstr);
|
||||||
cstr_reset(¯o_equal_buf);
|
|
||||||
TOK_GET(&t, &a, &cv);
|
TOK_GET(&t, &a, &cv);
|
||||||
cstr_cat(¯o_equal_buf, get_tok_str(t, &cv), 0);
|
cstr_cat(&tokcstr, get_tok_str(t, &cv), 0);
|
||||||
TOK_GET(&t, &b, &cv);
|
TOK_GET(&t, &b, &cv);
|
||||||
if (strcmp(macro_equal_buf.data, get_tok_str(t, &cv)))
|
if (strcmp(tokcstr.data, get_tok_str(t, &cv)))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return !(*a || *b);
|
return !(*a || *b);
|
||||||
@ -1348,14 +1345,15 @@ search_cached_include(TCCState *s1, const char *filename, int add);
|
|||||||
static int parse_include(TCCState *s1, int do_next, int test)
|
static int parse_include(TCCState *s1, int do_next, int test)
|
||||||
{
|
{
|
||||||
int c, i;
|
int c, i;
|
||||||
CString cs;
|
|
||||||
char name[1024], buf[1024], *p;
|
char name[1024], buf[1024], *p;
|
||||||
CachedInclude *e;
|
CachedInclude *e;
|
||||||
|
|
||||||
cstr_new(&cs);
|
|
||||||
c = skip_spaces();
|
c = skip_spaces();
|
||||||
if (c == '<' || c == '\"') {
|
if (c == '<' || c == '\"') {
|
||||||
file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &cs);
|
cstr_reset(&tokcstr);
|
||||||
|
file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &tokcstr);
|
||||||
|
i = tokcstr.size;
|
||||||
|
pstrncpy(name, tokcstr.data, i >= sizeof name ? sizeof name - 1 : i);
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
} else {
|
} else {
|
||||||
/* computed #include : concatenate tokens until result is one of
|
/* computed #include : concatenate tokens until result is one of
|
||||||
@ -1363,24 +1361,22 @@ static int parse_include(TCCState *s1, int do_next, int test)
|
|||||||
parse_flags = PARSE_FLAG_PREPROCESS
|
parse_flags = PARSE_FLAG_PREPROCESS
|
||||||
| PARSE_FLAG_LINEFEED
|
| PARSE_FLAG_LINEFEED
|
||||||
| (parse_flags & PARSE_FLAG_ASM_FILE);
|
| (parse_flags & PARSE_FLAG_ASM_FILE);
|
||||||
|
name[0] = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
next();
|
next();
|
||||||
p = cs.data, i = cs.size - 1;
|
p = name, i = strlen(p) - 1;
|
||||||
if (i > 0
|
if (i > 0
|
||||||
&& ((p[0] == '"' && p[i] == '"')
|
&& ((p[0] == '"' && p[i] == '"')
|
||||||
|| (p[0] == '<' && p[i] == '>')))
|
|| (p[0] == '<' && p[i] == '>')))
|
||||||
break;
|
break;
|
||||||
if (tok == TOK_LINEFEED)
|
if (tok == TOK_LINEFEED)
|
||||||
tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
|
tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
|
||||||
cstr_cat(&cs, get_tok_str(tok, &tokc), -1);
|
pstrcat(name, sizeof name, get_tok_str(tok, &tokc));
|
||||||
}
|
}
|
||||||
c = p[0];
|
c = p[0];
|
||||||
/* remove '<>|""' */
|
/* remove '<>|""' */
|
||||||
memmove(p, p + 1, cs.size -= 2);
|
memmove(p, p + 1, i - 1), p[i - 1] = 0;
|
||||||
}
|
}
|
||||||
cstr_ccat(&cs, '\0');
|
|
||||||
pstrcpy(name, sizeof name, cs.data);
|
|
||||||
cstr_free(&cs);
|
|
||||||
|
|
||||||
i = do_next ? file->include_next_index : -1;
|
i = do_next ? file->include_next_index : -1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -2934,7 +2930,6 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
|||||||
Sym *s;
|
Sym *s;
|
||||||
CValue cval;
|
CValue cval;
|
||||||
TokenString str;
|
TokenString str;
|
||||||
CString cstr;
|
|
||||||
|
|
||||||
tok_str_new(&str);
|
tok_str_new(&str);
|
||||||
t0 = t1 = 0;
|
t0 = t1 = 0;
|
||||||
@ -2949,8 +2944,8 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
|||||||
goto bad_stringy;
|
goto bad_stringy;
|
||||||
s = sym_find2(args, t);
|
s = sym_find2(args, t);
|
||||||
if (s) {
|
if (s) {
|
||||||
cstr_new(&cstr);
|
cstr_reset(&tokcstr);
|
||||||
cstr_ccat(&cstr, '\"');
|
cstr_ccat(&tokcstr, '\"');
|
||||||
st = s->d;
|
st = s->d;
|
||||||
spc = 0;
|
spc = 0;
|
||||||
while (*st >= 0) {
|
while (*st >= 0) {
|
||||||
@ -2961,24 +2956,23 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
|||||||
const char *s = get_tok_str(t, &cval);
|
const char *s = get_tok_str(t, &cval);
|
||||||
while (*s) {
|
while (*s) {
|
||||||
if (t == TOK_PPSTR && *s != '\'')
|
if (t == TOK_PPSTR && *s != '\'')
|
||||||
add_char(&cstr, *s);
|
add_char(&tokcstr, *s);
|
||||||
else
|
else
|
||||||
cstr_ccat(&cstr, *s);
|
cstr_ccat(&tokcstr, *s);
|
||||||
++s;
|
++s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cstr.size -= spc;
|
tokcstr.size -= spc;
|
||||||
cstr_ccat(&cstr, '\"');
|
cstr_ccat(&tokcstr, '\"');
|
||||||
cstr_ccat(&cstr, '\0');
|
cstr_ccat(&tokcstr, '\0');
|
||||||
#ifdef PP_DEBUG
|
#ifdef PP_DEBUG
|
||||||
printf("\nstringize: <%s>\n", (char *)cstr.data);
|
printf("\nstringize: <%s>\n", (char *)tokcstr.data);
|
||||||
#endif
|
#endif
|
||||||
/* add string */
|
/* add string */
|
||||||
cval.str.size = cstr.size;
|
cval.str.size = tokcstr.size;
|
||||||
cval.str.data = cstr.data;
|
cval.str.data = tokcstr.data;
|
||||||
tok_str_add2(&str, TOK_PPSTR, &cval);
|
tok_str_add2(&str, TOK_PPSTR, &cval);
|
||||||
cstr_free(&cstr);
|
|
||||||
} else {
|
} else {
|
||||||
bad_stringy:
|
bad_stringy:
|
||||||
expect("macro parameter after '#'");
|
expect("macro parameter after '#'");
|
||||||
@ -3047,19 +3041,19 @@ static char const ab_month_name[12][4] =
|
|||||||
|
|
||||||
static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
|
static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
|
||||||
{
|
{
|
||||||
CString cstr;
|
|
||||||
int n, ret = 1;
|
int n, ret = 1;
|
||||||
|
|
||||||
cstr_new(&cstr);
|
cstr_reset(&tokcstr);
|
||||||
if (t1 != TOK_PLCHLDR)
|
if (t1 != TOK_PLCHLDR)
|
||||||
cstr_cat(&cstr, get_tok_str(t1, v1), -1);
|
cstr_cat(&tokcstr, get_tok_str(t1, v1), -1);
|
||||||
n = cstr.size;
|
n = tokcstr.size;
|
||||||
if (t2 != TOK_PLCHLDR)
|
if (t2 != TOK_PLCHLDR)
|
||||||
cstr_cat(&cstr, get_tok_str(t2, v2), -1);
|
cstr_cat(&tokcstr, get_tok_str(t2, v2), -1);
|
||||||
cstr_ccat(&cstr, '\0');
|
cstr_ccat(&tokcstr, '\0');
|
||||||
|
//printf("paste <%s>\n", (char*)tokcstr.data);
|
||||||
|
|
||||||
tcc_open_bf(tcc_state, ":paste:", cstr.size);
|
tcc_open_bf(tcc_state, ":paste:", tokcstr.size);
|
||||||
memcpy(file->buffer, cstr.data, cstr.size);
|
memcpy(file->buffer, tokcstr.data, tokcstr.size);
|
||||||
tok_flags = 0;
|
tok_flags = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
next_nomacro1();
|
next_nomacro1();
|
||||||
@ -3068,13 +3062,11 @@ static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
|
|||||||
if (is_space(tok))
|
if (is_space(tok))
|
||||||
continue;
|
continue;
|
||||||
tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid"
|
tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid"
|
||||||
" preprocessing token", n, (char *)cstr.data, (char*)cstr.data + n);
|
" preprocessing token", n, file->buffer, file->buffer + n);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tcc_close();
|
tcc_close();
|
||||||
//printf("paste <%s>\n", (char*)cstr.data);
|
|
||||||
cstr_free(&cstr);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3214,7 +3206,6 @@ static int macro_subst_tok(
|
|||||||
TokenString str;
|
TokenString str;
|
||||||
char *cstrval;
|
char *cstrval;
|
||||||
CValue cval;
|
CValue cval;
|
||||||
CString cstr;
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
/* if symbol is a macro, prepare substitution */
|
/* if symbol is a macro, prepare substitution */
|
||||||
@ -3245,12 +3236,11 @@ static int macro_subst_tok(
|
|||||||
add_cstr:
|
add_cstr:
|
||||||
t1 = TOK_STR;
|
t1 = TOK_STR;
|
||||||
add_cstr1:
|
add_cstr1:
|
||||||
cstr_new(&cstr);
|
cstr_reset(&tokcstr);
|
||||||
cstr_cat(&cstr, cstrval, 0);
|
cstr_cat(&tokcstr, cstrval, 0);
|
||||||
cval.str.size = cstr.size;
|
cval.str.size = tokcstr.size;
|
||||||
cval.str.data = cstr.data;
|
cval.str.data = tokcstr.data;
|
||||||
tok_str_add2(tok_str, t1, &cval);
|
tok_str_add2(tok_str, t1, &cval);
|
||||||
cstr_free(&cstr);
|
|
||||||
} else if (s->d) {
|
} else if (s->d) {
|
||||||
int saved_parse_flags = parse_flags;
|
int saved_parse_flags = parse_flags;
|
||||||
int *joined_str = NULL;
|
int *joined_str = NULL;
|
||||||
@ -3634,7 +3624,6 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
|
|||||||
ST_FUNC void preprocess_start(TCCState *s1, int filetype)
|
ST_FUNC void preprocess_start(TCCState *s1, int filetype)
|
||||||
{
|
{
|
||||||
int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP));
|
int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP));
|
||||||
CString cstr;
|
|
||||||
|
|
||||||
tccpp_new(s1);
|
tccpp_new(s1);
|
||||||
|
|
||||||
@ -3652,6 +3641,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype)
|
|||||||
set_idnum('.', is_asm ? IS_ID : 0);
|
set_idnum('.', is_asm ? IS_ID : 0);
|
||||||
|
|
||||||
if (!(filetype & AFF_TYPE_ASM)) {
|
if (!(filetype & AFF_TYPE_ASM)) {
|
||||||
|
CString cstr;
|
||||||
cstr_new(&cstr);
|
cstr_new(&cstr);
|
||||||
tcc_predefs(s1, &cstr, is_asm);
|
tcc_predefs(s1, &cstr, is_asm);
|
||||||
if (s1->cmdline_defs.size)
|
if (s1->cmdline_defs.size)
|
||||||
@ -3710,6 +3700,7 @@ ST_FUNC void tccpp_new(TCCState *s)
|
|||||||
memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
|
memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
|
||||||
memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash);
|
memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash);
|
||||||
|
|
||||||
|
cstr_new(&tokcstr);
|
||||||
cstr_new(&cstr_buf);
|
cstr_new(&cstr_buf);
|
||||||
cstr_realloc(&cstr_buf, STRING_MAX_SIZE);
|
cstr_realloc(&cstr_buf, STRING_MAX_SIZE);
|
||||||
tok_str_new(&tokstr_buf);
|
tok_str_new(&tokstr_buf);
|
||||||
@ -3755,7 +3746,6 @@ ST_FUNC void tccpp_delete(TCCState *s)
|
|||||||
/* free static buffers */
|
/* free static buffers */
|
||||||
cstr_free(&tokcstr);
|
cstr_free(&tokcstr);
|
||||||
cstr_free(&cstr_buf);
|
cstr_free(&cstr_buf);
|
||||||
cstr_free(¯o_equal_buf);
|
|
||||||
tok_str_free_str(tokstr_buf.str);
|
tok_str_free_str(tokstr_buf.str);
|
||||||
|
|
||||||
/* free allocators */
|
/* free allocators */
|
||||||
|
Loading…
Reference in New Issue
Block a user