mirror of
https://github.com/frida/tinycc
synced 2025-01-16 16:29:22 +03:00
Fixes include the double quotes bug
Added push_macro, pop_macro support Fix pack bug, when output with-E will pack the bug
This commit is contained in:
parent
5b52a44b52
commit
6c8207633f
6
libtcc.c
6
libtcc.c
@ -868,6 +868,7 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
|
|||||||
static void tcc_cleanup(void)
|
static void tcc_cleanup(void)
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
|
CSym *def;
|
||||||
if (NULL == tcc_state)
|
if (NULL == tcc_state)
|
||||||
return;
|
return;
|
||||||
tcc_state = NULL;
|
tcc_state = NULL;
|
||||||
@ -877,8 +878,11 @@ static void tcc_cleanup(void)
|
|||||||
|
|
||||||
/* free tokens */
|
/* free tokens */
|
||||||
n = tok_ident - TOK_IDENT;
|
n = tok_ident - TOK_IDENT;
|
||||||
for(i = 0; i < n; i++)
|
for(i = 0; i < n; i++){
|
||||||
|
def = &table_ident[i]->sym_define;
|
||||||
|
tcc_free(def->data);
|
||||||
tcc_free(table_ident[i]);
|
tcc_free(table_ident[i]);
|
||||||
|
}
|
||||||
tcc_free(table_ident);
|
tcc_free(table_ident);
|
||||||
|
|
||||||
/* free sym_pools */
|
/* free sym_pools */
|
||||||
|
12
tcc.h
12
tcc.h
@ -305,15 +305,22 @@
|
|||||||
#define VSTACK_SIZE 256
|
#define VSTACK_SIZE 256
|
||||||
#define STRING_MAX_SIZE 1024
|
#define STRING_MAX_SIZE 1024
|
||||||
#define PACK_STACK_SIZE 8
|
#define PACK_STACK_SIZE 8
|
||||||
|
#define MACRO_STACK_SIZE 4
|
||||||
|
|
||||||
#define TOK_HASH_SIZE 8192 /* must be a power of two */
|
#define TOK_HASH_SIZE 8192 /* must be a power of two */
|
||||||
#define TOK_ALLOC_INCR 512 /* 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 4 /* token max size in int unit when stored in string */
|
||||||
|
|
||||||
|
typedef struct CSym {
|
||||||
|
int off;
|
||||||
|
int size;/* size in *sym */
|
||||||
|
struct Sym **data; /* if non NULL, data has been malloced */
|
||||||
|
} CSym;
|
||||||
|
|
||||||
/* token symbol management */
|
/* token symbol management */
|
||||||
typedef struct TokenSym {
|
typedef struct TokenSym {
|
||||||
struct TokenSym *hash_next;
|
struct TokenSym *hash_next;
|
||||||
struct Sym *sym_define; /* direct pointer to define */
|
struct CSym sym_define; /* direct pointer to define */
|
||||||
struct Sym *sym_label; /* direct pointer to label */
|
struct Sym *sym_label; /* direct pointer to label */
|
||||||
struct Sym *sym_struct; /* direct pointer to structure */
|
struct Sym *sym_struct; /* direct pointer to structure */
|
||||||
struct Sym *sym_identifier; /* direct pointer to identifier */
|
struct Sym *sym_identifier; /* direct pointer to identifier */
|
||||||
@ -1129,7 +1136,8 @@ ST_DATA TokenSym **table_ident;
|
|||||||
token. line feed is also
|
token. line feed is also
|
||||||
returned at eof */
|
returned at eof */
|
||||||
#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
|
#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
|
||||||
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
|
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
|
||||||
|
#define PARSE_FLAG_PACK 0x0020 /* #pragma pack */
|
||||||
|
|
||||||
ST_FUNC TokenSym *tok_alloc(const char *str, int len);
|
ST_FUNC TokenSym *tok_alloc(const char *str, int len);
|
||||||
ST_FUNC char *get_tok_str(int v, CValue *cv);
|
ST_FUNC char *get_tok_str(int v, CValue *cv);
|
||||||
|
6
tccgen.c
6
tccgen.c
@ -5244,13 +5244,13 @@ static void init_putz(CType *t, Section *sec, unsigned long c, int size)
|
|||||||
#ifndef TCC_TARGET_X86_64
|
#ifndef TCC_TARGET_X86_64
|
||||||
vpush_global_sym(&func_old_type, TOK_memset);
|
vpush_global_sym(&func_old_type, TOK_memset);
|
||||||
vseti(VT_LOCAL, c);
|
vseti(VT_LOCAL, c);
|
||||||
#ifdef TCC_TARGET_ARM
|
# ifdef TCC_TARGET_ARM
|
||||||
vpushs(size);
|
vpushs(size);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
#else
|
# else
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
vpushs(size);
|
vpushs(size);
|
||||||
#endif
|
# endif
|
||||||
gfunc_call(3);
|
gfunc_call(3);
|
||||||
#else
|
#else
|
||||||
vseti(VT_LOCAL, c);
|
vseti(VT_LOCAL, c);
|
||||||
|
302
tccpp.c
302
tccpp.c
@ -233,7 +233,10 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
|
|||||||
ts = tcc_malloc(sizeof(TokenSym) + len);
|
ts = tcc_malloc(sizeof(TokenSym) + len);
|
||||||
table_ident[i] = ts;
|
table_ident[i] = ts;
|
||||||
ts->tok = tok_ident++;
|
ts->tok = tok_ident++;
|
||||||
ts->sym_define = NULL;
|
ts->sym_define.data = tcc_malloc(sizeof(Sym**));
|
||||||
|
ts->sym_define.off = 0;
|
||||||
|
ts->sym_define.data[0] = NULL;
|
||||||
|
ts->sym_define.size = 1;
|
||||||
ts->sym_label = NULL;
|
ts->sym_label = NULL;
|
||||||
ts->sym_struct = NULL;
|
ts->sym_struct = NULL;
|
||||||
ts->sym_identifier = NULL;
|
ts->sym_identifier = NULL;
|
||||||
@ -1052,52 +1055,62 @@ static int macro_is_equal(const int *a, const int *b)
|
|||||||
ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
|
ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
CSym *def;
|
||||||
s = define_find(v);
|
s = define_find(v);
|
||||||
if (s && !macro_is_equal(s->d, str))
|
if (s && !macro_is_equal(s->d, str))
|
||||||
tcc_warning("%s redefined", get_tok_str(v, NULL));
|
tcc_warning("%s redefined", get_tok_str(v, NULL));
|
||||||
|
|
||||||
s = sym_push2(&define_stack, v, macro_type, 0);
|
s = sym_push2(&define_stack, v, macro_type, 0);
|
||||||
s->d = str;
|
s->d = str;
|
||||||
s->next = first_arg;
|
s->next = first_arg;
|
||||||
table_ident[v - TOK_IDENT]->sym_define = s;
|
def = &table_ident[v - TOK_IDENT]->sym_define;
|
||||||
|
def->data[def->off] = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undefined a define symbol. Its name is just set to zero */
|
/* undefined a define symbol. Its name is just set to zero */
|
||||||
ST_FUNC void define_undef(Sym *s)
|
ST_FUNC void define_undef(Sym *s)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
v = s->v;
|
CSym *def;
|
||||||
if (v >= TOK_IDENT && v < tok_ident)
|
v = s->v - TOK_IDENT;
|
||||||
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
if ((unsigned)v < (unsigned)(tok_ident - TOK_IDENT)){
|
||||||
s->v = 0;
|
def = &table_ident[v]->sym_define;
|
||||||
|
def->data[def->off] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_INLN Sym *define_find(int v)
|
ST_INLN Sym *define_find(int v)
|
||||||
{
|
{
|
||||||
|
CSym *def;
|
||||||
v -= TOK_IDENT;
|
v -= TOK_IDENT;
|
||||||
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
||||||
return NULL;
|
return NULL;
|
||||||
return table_ident[v]->sym_define;
|
def = &table_ident[v]->sym_define;
|
||||||
|
return def->data[def->off];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free define stack until top reaches 'b' */
|
/* free define stack until top reaches 'b' */
|
||||||
ST_FUNC void free_defines(Sym *b)
|
ST_FUNC void free_defines(Sym *b)
|
||||||
{
|
{
|
||||||
Sym *top, *top1;
|
Sym *top, *tmp;
|
||||||
int v;
|
int v;
|
||||||
|
CSym *def;
|
||||||
|
|
||||||
top = define_stack;
|
top = define_stack;
|
||||||
while (top != b) {
|
while (top != b) {
|
||||||
top1 = top->prev;
|
tmp = top->prev;
|
||||||
/* do not free args or predefined defines */
|
/* do not free args or predefined defines */
|
||||||
if (top->d)
|
if (top->d)
|
||||||
tok_str_free(top->d);
|
tok_str_free(top->d);
|
||||||
v = top->v;
|
v = top->v - TOK_IDENT;
|
||||||
if (v >= TOK_IDENT && v < tok_ident)
|
if ((unsigned)v < (unsigned)(tok_ident - TOK_IDENT)){
|
||||||
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
def = &table_ident[v]->sym_define;
|
||||||
|
if(def->off)
|
||||||
|
def->off = 0;
|
||||||
|
if(def->data[0])
|
||||||
|
def->data[0] = NULL;
|
||||||
|
}
|
||||||
sym_free(top);
|
sym_free(top);
|
||||||
top = top1;
|
top = tmp;
|
||||||
}
|
}
|
||||||
define_stack = b;
|
define_stack = b;
|
||||||
}
|
}
|
||||||
@ -1338,66 +1351,18 @@ static inline void add_cached_include(TCCState *s1, const char *filename, int if
|
|||||||
s1->cached_includes_hash[h] = s1->nb_cached_includes;
|
s1->cached_includes_hash[h] = s1->nb_cached_includes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pragma_parse(TCCState *s1)
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
|
|
||||||
next();
|
|
||||||
if (tok == TOK_pack) {
|
|
||||||
/*
|
|
||||||
This may be:
|
|
||||||
#pragma pack(1) // set
|
|
||||||
#pragma pack() // reset to default
|
|
||||||
#pragma pack(push,1) // push & set
|
|
||||||
#pragma pack(pop) // restore previous
|
|
||||||
*/
|
|
||||||
next();
|
|
||||||
skip('(');
|
|
||||||
if (tok == TOK_ASM_pop) {
|
|
||||||
next();
|
|
||||||
if (s1->pack_stack_ptr <= s1->pack_stack) {
|
|
||||||
stk_error:
|
|
||||||
tcc_error("out of pack stack");
|
|
||||||
}
|
|
||||||
s1->pack_stack_ptr--;
|
|
||||||
} else {
|
|
||||||
val = 0;
|
|
||||||
if (tok != ')') {
|
|
||||||
if (tok == TOK_ASM_push) {
|
|
||||||
next();
|
|
||||||
if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
|
|
||||||
goto stk_error;
|
|
||||||
s1->pack_stack_ptr++;
|
|
||||||
skip(',');
|
|
||||||
}
|
|
||||||
if (tok != TOK_CINT) {
|
|
||||||
pack_error:
|
|
||||||
tcc_error("invalid pack pragma");
|
|
||||||
}
|
|
||||||
val = tokc.i;
|
|
||||||
if (val < 1 || val > 16 || (val & (val - 1)) != 0)
|
|
||||||
goto pack_error;
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
*s1->pack_stack_ptr = val;
|
|
||||||
skip(')');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is_bof is true if first non space token at beginning of file */
|
/* is_bof is true if first non space token at beginning of file */
|
||||||
ST_FUNC void preprocess(int is_bof)
|
ST_FUNC void preprocess(int is_bof)
|
||||||
{
|
{
|
||||||
TCCState *s1 = tcc_state;
|
TCCState *s1 = tcc_state;
|
||||||
int i, c, n, saved_parse_flags;
|
int i, c, n, saved_parse_flags;
|
||||||
char buf[1024], *q;
|
uint8_t buf[1024], *p;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
saved_parse_flags = parse_flags;
|
saved_parse_flags = parse_flags;
|
||||||
parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
|
parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_LINEFEED;
|
||||||
PARSE_FLAG_LINEFEED;
|
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
redo:
|
redo:
|
||||||
switch(tok) {
|
switch(tok) {
|
||||||
case TOK_DEFINE:
|
case TOK_DEFINE:
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
@ -1420,19 +1385,21 @@ ST_FUNC void preprocess(int is_bof)
|
|||||||
goto read_name;
|
goto read_name;
|
||||||
} else if (ch == '\"') {
|
} else if (ch == '\"') {
|
||||||
c = ch;
|
c = ch;
|
||||||
read_name:
|
read_name:
|
||||||
inp();
|
inp();
|
||||||
q = buf;
|
p = buf;
|
||||||
while (ch != c && ch != '\n' && ch != CH_EOF) {
|
while (ch != c && ch != '\n' && ch != CH_EOF) {
|
||||||
if ((q - buf) < sizeof(buf) - 1)
|
if ((p - buf) < sizeof(buf) - 1)
|
||||||
*q++ = ch;
|
*p++ = ch;
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
if (handle_stray_noerror() == 0)
|
if (handle_stray_noerror() == 0)
|
||||||
--q;
|
--p;
|
||||||
} else
|
} else
|
||||||
inp();
|
inp();
|
||||||
}
|
}
|
||||||
*q = '\0';
|
if (ch != c)
|
||||||
|
goto include_syntax;
|
||||||
|
*p = '\0';
|
||||||
minp();
|
minp();
|
||||||
#if 0
|
#if 0
|
||||||
/* eat all spaces and comments after include */
|
/* eat all spaces and comments after include */
|
||||||
@ -1470,6 +1437,8 @@ ST_FUNC void preprocess(int is_bof)
|
|||||||
c = '>';
|
c = '>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!buf[0])
|
||||||
|
tcc_error(" empty filename in #include");
|
||||||
|
|
||||||
if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
|
if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
|
||||||
tcc_error("#include recursion too deep");
|
tcc_error("#include recursion too deep");
|
||||||
@ -1536,8 +1505,7 @@ include_trynext:
|
|||||||
printf("%s: including %s\n", file->prev->filename, file->filename);
|
printf("%s: including %s\n", file->prev->filename, file->filename);
|
||||||
#endif
|
#endif
|
||||||
/* update target deps */
|
/* update target deps */
|
||||||
dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
|
dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, tcc_strdup(buf1));
|
||||||
tcc_strdup(buf1));
|
|
||||||
/* push current file in stack */
|
/* push current file in stack */
|
||||||
++s1->include_stack_ptr;
|
++s1->include_stack_ptr;
|
||||||
/* add include file debug info */
|
/* add include file debug info */
|
||||||
@ -1570,7 +1538,7 @@ include_done:
|
|||||||
file->ifndef_macro = tok;
|
file->ifndef_macro = tok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c = (define_find(tok) != 0) ^ c;
|
c = !!define_find(tok) ^ c;
|
||||||
do_if:
|
do_if:
|
||||||
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
|
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
|
||||||
tcc_error("memory full (ifdef)");
|
tcc_error("memory full (ifdef)");
|
||||||
@ -1594,12 +1562,12 @@ include_done:
|
|||||||
goto skip;
|
goto skip;
|
||||||
c = expr_preprocess();
|
c = expr_preprocess();
|
||||||
s1->ifdef_stack_ptr[-1] = c;
|
s1->ifdef_stack_ptr[-1] = c;
|
||||||
test_else:
|
test_else:
|
||||||
if (s1->ifdef_stack_ptr == file->ifdef_stack_ptr + 1)
|
if (s1->ifdef_stack_ptr == file->ifdef_stack_ptr + 1)
|
||||||
file->ifndef_macro = 0;
|
file->ifndef_macro = 0;
|
||||||
test_skip:
|
test_skip:
|
||||||
if (!(c & 1)) {
|
if (!(c & 1)) {
|
||||||
skip:
|
skip:
|
||||||
preprocess_skip();
|
preprocess_skip();
|
||||||
is_bof = 0;
|
is_bof = 0;
|
||||||
goto redo;
|
goto redo;
|
||||||
@ -1617,11 +1585,11 @@ include_done:
|
|||||||
/* need to set to zero to avoid false matches if another
|
/* need to set to zero to avoid false matches if another
|
||||||
#ifndef at middle of file */
|
#ifndef at middle of file */
|
||||||
file->ifndef_macro = 0;
|
file->ifndef_macro = 0;
|
||||||
while (tok != TOK_LINEFEED)
|
|
||||||
next_nomacro();
|
|
||||||
tok_flags |= TOK_FLAG_ENDIF;
|
tok_flags |= TOK_FLAG_ENDIF;
|
||||||
goto the_end;
|
|
||||||
}
|
}
|
||||||
|
next_nomacro();
|
||||||
|
if (tok != TOK_LINEFEED)
|
||||||
|
tcc_warning("Ignoring: %s", get_tok_str(tok, &tokc));
|
||||||
break;
|
break;
|
||||||
case TOK_LINE:
|
case TOK_LINE:
|
||||||
next();
|
next();
|
||||||
@ -1632,8 +1600,7 @@ include_done:
|
|||||||
if (tok != TOK_LINEFEED) {
|
if (tok != TOK_LINEFEED) {
|
||||||
if (tok != TOK_STR)
|
if (tok != TOK_STR)
|
||||||
tcc_error("#line");
|
tcc_error("#line");
|
||||||
pstrcpy(file->filename, sizeof(file->filename),
|
pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.cstr->data);
|
||||||
(char *)tokc.cstr->data);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_ERROR:
|
case TOK_ERROR:
|
||||||
@ -1641,24 +1608,161 @@ include_done:
|
|||||||
c = tok;
|
c = tok;
|
||||||
ch = file->buf_ptr[0];
|
ch = file->buf_ptr[0];
|
||||||
skip_spaces();
|
skip_spaces();
|
||||||
q = buf;
|
p = buf;
|
||||||
while (ch != '\n' && ch != CH_EOF) {
|
while (ch != '\n' && ch != CH_EOF) {
|
||||||
if ((q - buf) < sizeof(buf) - 1)
|
if ((p - buf) < sizeof(buf) - 1)
|
||||||
*q++ = ch;
|
*p++ = ch;
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
if (handle_stray_noerror() == 0)
|
if (handle_stray_noerror() == 0)
|
||||||
--q;
|
--p;
|
||||||
} else
|
} else
|
||||||
inp();
|
inp();
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*p = '\0';
|
||||||
if (c == TOK_ERROR)
|
if (c == TOK_ERROR)
|
||||||
tcc_error("#error %s", buf);
|
tcc_error("#error %s", buf);
|
||||||
else
|
else
|
||||||
tcc_warning("#warning %s", buf);
|
tcc_warning("#warning %s", buf);
|
||||||
break;
|
break;
|
||||||
case TOK_PRAGMA:
|
case TOK_PRAGMA:
|
||||||
pragma_parse(s1);
|
next();
|
||||||
|
if (tok == TOK_pack && parse_flags & PARSE_FLAG_PACK) {
|
||||||
|
/*
|
||||||
|
This may be:
|
||||||
|
#pragma pack(1) // set
|
||||||
|
#pragma pack() // reset to default
|
||||||
|
#pragma pack(push,1) // push & set
|
||||||
|
#pragma pack(pop) // restore previous
|
||||||
|
*/
|
||||||
|
next();
|
||||||
|
skip('(');
|
||||||
|
if (tok == TOK_ASM_pop) {
|
||||||
|
next();
|
||||||
|
if (s1->pack_stack_ptr <= s1->pack_stack) {
|
||||||
|
stk_error:
|
||||||
|
tcc_error("out of pack stack");
|
||||||
|
}
|
||||||
|
s1->pack_stack_ptr--;
|
||||||
|
} else {
|
||||||
|
int val = 0;
|
||||||
|
if (tok != ')') {
|
||||||
|
if (tok == TOK_ASM_push) {
|
||||||
|
next();
|
||||||
|
s1->pack_stack_ptr++;
|
||||||
|
if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE)
|
||||||
|
goto stk_error;
|
||||||
|
skip(',');
|
||||||
|
}
|
||||||
|
if (tok != TOK_CINT) {
|
||||||
|
pack_error:
|
||||||
|
tcc_error("invalid pack pragma");
|
||||||
|
}
|
||||||
|
val = tokc.i;
|
||||||
|
if (val < 1 || val > 16)
|
||||||
|
goto pack_error;
|
||||||
|
if (val < 1 || val > 16)
|
||||||
|
tcc_error("Value must be greater than 1 is less than or equal to 16");
|
||||||
|
if ((val & (val - 1)) != 0)
|
||||||
|
tcc_error("Value must be a power of 2 curtain");
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
*s1->pack_stack_ptr = val;
|
||||||
|
skip(')');
|
||||||
|
}
|
||||||
|
}else if (tok == TOK_PUSH_MACRO || tok == TOK_POP_MACRO) {
|
||||||
|
TokenSym *ts;
|
||||||
|
CSym *def;
|
||||||
|
uint8_t *p1;
|
||||||
|
int len, t;
|
||||||
|
t = tok;
|
||||||
|
ch = file->buf_ptr[0];
|
||||||
|
skip_spaces();
|
||||||
|
if (ch != '(')
|
||||||
|
goto macro_xxx_syntax;
|
||||||
|
/* XXX: incorrect if comments : use next_nomacro with a special mode */
|
||||||
|
inp();
|
||||||
|
skip_spaces();
|
||||||
|
if (ch == '\"'){
|
||||||
|
inp();
|
||||||
|
p = buf;
|
||||||
|
while (ch != '\"' && ch != '\n' && ch != CH_EOF) {
|
||||||
|
if ((p - buf) < sizeof(buf) - 1)
|
||||||
|
*p++ = ch;
|
||||||
|
if (ch == CH_EOB) {
|
||||||
|
--p;
|
||||||
|
handle_stray();
|
||||||
|
}else
|
||||||
|
inp();
|
||||||
|
}
|
||||||
|
if(ch != '\"')
|
||||||
|
goto macro_xxx_syntax;
|
||||||
|
*p = '\0';
|
||||||
|
minp();
|
||||||
|
next();
|
||||||
|
}else{
|
||||||
|
/* computed #pragma macro_xxx for #define xxx */
|
||||||
|
next();
|
||||||
|
buf[0] = '\0';
|
||||||
|
while (tok != ')') {
|
||||||
|
if (tok != TOK_STR) {
|
||||||
|
macro_xxx_syntax:
|
||||||
|
tcc_error("'macro_xxx' expects (\"NAME\")");
|
||||||
|
}
|
||||||
|
pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip (')');
|
||||||
|
if(!buf[0])
|
||||||
|
tcc_error(" empty string in #pragma");
|
||||||
|
/* find TokenSym */
|
||||||
|
p = buf;
|
||||||
|
while (is_space(*p))
|
||||||
|
p++;
|
||||||
|
p1 = p;
|
||||||
|
for(;;){
|
||||||
|
if (!isidnum_table[p[0] - CH_EOF])
|
||||||
|
break;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
len = p - p1;
|
||||||
|
while (is_space(*p))
|
||||||
|
p++;
|
||||||
|
if(!p) //'\0'
|
||||||
|
tcc_error("unrecognized string: %s", buf);
|
||||||
|
ts = tok_alloc(p1, len);
|
||||||
|
if(ts){
|
||||||
|
def = &ts->sym_define;
|
||||||
|
if(t == TOK_PUSH_MACRO){
|
||||||
|
void *tmp = def->data[def->off];
|
||||||
|
if(tmp){
|
||||||
|
def->off++;
|
||||||
|
if(def->off >= def->size){
|
||||||
|
int size = def->size;
|
||||||
|
size *= 2;
|
||||||
|
if (size >= MACRO_STACK_SIZE)
|
||||||
|
tcc_error("stack full");
|
||||||
|
def->data = tcc_realloc(def->data, size*sizeof(Sym**));
|
||||||
|
def->size = size;
|
||||||
|
}
|
||||||
|
def->data[def->off] = tmp;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(def->off){
|
||||||
|
--def->off;
|
||||||
|
}else{
|
||||||
|
tcc_warning("stack empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
fputs("#pragma ", s1->ppfp);
|
||||||
|
while (tok != TOK_LINEFEED){
|
||||||
|
fputs(get_tok_str(tok, &tokc), s1->ppfp);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_PPNUM) {
|
if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_PPNUM) {
|
||||||
@ -1678,7 +1782,7 @@ include_done:
|
|||||||
/* ignore other preprocess commands or #! for C scripts */
|
/* ignore other preprocess commands or #! for C scripts */
|
||||||
while (tok != TOK_LINEFEED)
|
while (tok != TOK_LINEFEED)
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
the_end:
|
the_end:
|
||||||
parse_flags = saved_parse_flags;
|
parse_flags = saved_parse_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3030,12 +3134,13 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
|
|||||||
ch = file->buf_ptr[0];
|
ch = file->buf_ptr[0];
|
||||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||||
parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
|
parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
|
||||||
PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
|
PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
|
||||||
token_seen = 0;
|
token_seen = 0;
|
||||||
line_ref = 0;
|
line_ref = 0;
|
||||||
file_ref = NULL;
|
file_ref = NULL;
|
||||||
iptr = s1->include_stack_ptr;
|
iptr = s1->include_stack_ptr;
|
||||||
|
tok = TOK_LINEFEED; /* print line */
|
||||||
|
goto print_line;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
next();
|
next();
|
||||||
if (tok == TOK_EOF) {
|
if (tok == TOK_EOF) {
|
||||||
@ -3043,11 +3148,11 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
|
|||||||
} else if (file != file_ref) {
|
} else if (file != file_ref) {
|
||||||
goto print_line;
|
goto print_line;
|
||||||
} else if (tok == TOK_LINEFEED) {
|
} else if (tok == TOK_LINEFEED) {
|
||||||
if (!token_seen)
|
if (token_seen)
|
||||||
continue;
|
continue;
|
||||||
++line_ref;
|
++line_ref;
|
||||||
token_seen = 0;
|
token_seen = 1;
|
||||||
} else if (!token_seen) {
|
} else if (token_seen) {
|
||||||
d = file->line_num - line_ref;
|
d = file->line_num - line_ref;
|
||||||
if (file != file_ref || d < 0 || d >= 8) {
|
if (file != file_ref || d < 0 || d >= 8) {
|
||||||
print_line:
|
print_line:
|
||||||
@ -3055,8 +3160,7 @@ print_line:
|
|||||||
s = iptr_new > iptr ? " 1"
|
s = iptr_new > iptr ? " 1"
|
||||||
: iptr_new < iptr ? " 2"
|
: iptr_new < iptr ? " 2"
|
||||||
: iptr_new > s1->include_stack ? " 3"
|
: iptr_new > s1->include_stack ? " 3"
|
||||||
: ""
|
: "";
|
||||||
;
|
|
||||||
iptr = iptr_new;
|
iptr = iptr_new;
|
||||||
fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
|
fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
|
||||||
} else {
|
} else {
|
||||||
@ -3064,8 +3168,8 @@ print_line:
|
|||||||
fputs("\n", s1->ppfp), --d;
|
fputs("\n", s1->ppfp), --d;
|
||||||
}
|
}
|
||||||
line_ref = (file_ref = file)->line_num;
|
line_ref = (file_ref = file)->line_num;
|
||||||
token_seen = tok != TOK_LINEFEED;
|
token_seen = tok == TOK_LINEFEED;
|
||||||
if (!token_seen)
|
if (token_seen)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fputs(get_tok_str(tok, &tokc), s1->ppfp);
|
fputs(get_tok_str(tok, &tokc), s1->ppfp);
|
||||||
|
2
tcctok.h
2
tcctok.h
@ -138,6 +138,8 @@
|
|||||||
|
|
||||||
/* pragma */
|
/* pragma */
|
||||||
DEF(TOK_pack, "pack")
|
DEF(TOK_pack, "pack")
|
||||||
|
DEF(TOK_PUSH_MACRO, "push_macro")
|
||||||
|
DEF(TOK_POP_MACRO, "pop_macro")
|
||||||
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64)
|
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64)
|
||||||
/* already defined for assembler */
|
/* already defined for assembler */
|
||||||
DEF(TOK_ASM_push, "push")
|
DEF(TOK_ASM_push, "push")
|
||||||
|
@ -235,7 +235,7 @@ void intdiv_test(void)
|
|||||||
|
|
||||||
void macro_test(void)
|
void macro_test(void)
|
||||||
{
|
{
|
||||||
printf("macro:\n");
|
printf("macro:\n");
|
||||||
pf("N=%d\n", N);
|
pf("N=%d\n", N);
|
||||||
printf("aaa=%d\n", AAA);
|
printf("aaa=%d\n", AAA);
|
||||||
|
|
||||||
@ -379,6 +379,23 @@ comment
|
|||||||
/* And again when the name and parenthes are separated by a
|
/* And again when the name and parenthes are separated by a
|
||||||
comment. */
|
comment. */
|
||||||
TEST2 /* the comment */ ();
|
TEST2 /* the comment */ ();
|
||||||
|
/* macro_push and macro_pop test */
|
||||||
|
#define MACRO_TEST "macro_test1\n"
|
||||||
|
#pragma push_macro("MACRO_TEST")
|
||||||
|
#undef MACRO_TEST
|
||||||
|
#define MACRO_TEST "macro_test2\n"
|
||||||
|
printf(MACRO_TEST);
|
||||||
|
#pragma pop_macro("MACRO_TEST")
|
||||||
|
printf(MACRO_TEST);
|
||||||
|
/* gcc does not support
|
||||||
|
#define MACRO_TEST_MACRO "MACRO_TEST"
|
||||||
|
#pragma push_macro(MACRO_TEST_MACRO)
|
||||||
|
#undef MACRO_TEST
|
||||||
|
#define MACRO_TEST "macro_test3\n"
|
||||||
|
printf(MACRO_TEST);
|
||||||
|
#pragma pop_macro(MACRO_TEST_MACRO)
|
||||||
|
printf(MACRO_TEST);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2167,14 +2184,15 @@ void whitespace_test(void)
|
|||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
#if 1
|
|
||||||
|
#if 1
|
||||||
pri\
|
pri\
|
||||||
ntf("whitspace:\n");
|
ntf("whitspace:\n");
|
||||||
#endif
|
#endif
|
||||||
pf("N=%d\n", 2);
|
pf("N=%d\n", 2);
|
||||||
|
|
||||||
#ifdef CORRECT_CR_HANDLING
|
#ifdef CORRECT_CR_HANDLING
|
||||||
pri\
|
pri\
|
||||||
ntf("aaa=%d\n", 3);
|
ntf("aaa=%d\n", 3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2186,11 +2204,12 @@ ntf("min=%d\n", 4);
|
|||||||
printf("len1=%d\n", strlen("
|
printf("len1=%d\n", strlen("
|
||||||
"));
|
"));
|
||||||
#ifdef CORRECT_CR_HANDLING
|
#ifdef CORRECT_CR_HANDLING
|
||||||
str = "
|
str = "
|
||||||
";
|
";
|
||||||
printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
|
printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
|
||||||
#endif
|
#endif
|
||||||
printf("len1=%d\n", strlen("
a
|
printf("len1=%d\n", strlen("
|
||||||
|
a
|
||||||
"));
|
"));
|
||||||
#endif /* ACCEPT_CR_IN_STRINGS */
|
#endif /* ACCEPT_CR_IN_STRINGS */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user