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:
grischka 2023-04-24 21:58:50 +02:00
parent 40131b7e0f
commit a045400501
5 changed files with 118 additions and 123 deletions

View File

@ -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
View File

@ -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);

View File

@ -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;
} }

View File

@ -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
View File

@ -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(&macro_equal_buf);
TOK_GET(&t, &a, &cv); TOK_GET(&t, &a, &cv);
cstr_cat(&macro_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(&macro_equal_buf);
tok_str_free_str(tokstr_buf.str); tok_str_free_str(tokstr_buf.str);
/* free allocators */ /* free allocators */