diff --git a/libtcc.c b/libtcc.c index 383e5a5..c9505d6 100644 --- a/libtcc.c +++ b/libtcc.c @@ -92,8 +92,6 @@ static int nb_sym_pools; static SValue vstack[VSTACK_SIZE], *vtop; /* some predefined types */ static CType char_pointer_type, func_old_type, int_type; -/* true if isid(c) || isnum(c) */ -static unsigned char isidnum_table[256-CH_EOF]; /* display some information during compilation */ static int verbose = 0; @@ -105,9 +103,6 @@ static int do_debug = 0; static int do_bounds_check = 0; /* display benchmark infos */ -#if !defined(LIBTCC) -static int do_bench = 0; -#endif static int total_lines; static int total_bytes; @@ -251,34 +246,6 @@ static char *pstrcat(char *buf, int buf_size, const char *s) return buf; } -#ifndef LIBTCC -static int strstart(const char *str, const char *val, const char **ptr) -{ - const char *p, *q; - p = str; - q = val; - while (*q != '\0') { - if (*p != *q) - return 0; - p++; - q++; - } - if (ptr) - *ptr = p; - return 1; -} -#endif - -#ifdef _WIN32 -#define IS_PATHSEP(c) (c == '/' || c == '\\') -#define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2]))) -#define PATHCMP stricmp -#else -#define IS_PATHSEP(c) (c == '/') -#define IS_ABSPATH(p) IS_PATHSEP(p[0]) -#define PATHCMP strcmp -#endif - /* extract the basename of a file */ static char *tcc_basename(const char *name) { @@ -556,8 +523,6 @@ Section *find_section(TCCState *s1, const char *name) return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC); } -#define SECTION_ABS ((void *)1) - /* update sym->c so that it points to an external symbol in section 'section' with value 'value' */ static void put_extern_sym2(Sym *sym, Section *section, @@ -809,66 +774,6 @@ static void test_lvalue(void) expect("lvalue"); } -/* allocate a new token */ -static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) -{ - TokenSym *ts, **ptable; - int i; - - if (tok_ident >= SYM_FIRST_ANOM) - error("memory full"); - - /* expand token table if needed */ - i = tok_ident - TOK_IDENT; - if ((i % TOK_ALLOC_INCR) == 0) { - ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *)); - if (!ptable) - error("memory full"); - table_ident = ptable; - } - - ts = tcc_malloc(sizeof(TokenSym) + len); - table_ident[i] = ts; - ts->tok = tok_ident++; - ts->sym_define = NULL; - ts->sym_label = NULL; - ts->sym_struct = NULL; - ts->sym_identifier = NULL; - ts->len = len; - ts->hash_next = NULL; - memcpy(ts->str, str, len); - ts->str[len] = '\0'; - *pts = ts; - return ts; -} - -#define TOK_HASH_INIT 1 -#define TOK_HASH_FUNC(h, c) ((h) * 263 + (c)) - -/* find a token and add it if not found */ -static TokenSym *tok_alloc(const char *str, int len) -{ - TokenSym *ts, **pts; - int i; - unsigned int h; - - h = TOK_HASH_INIT; - for(i=0;ilen == len && !memcmp(ts->str, str, len)) - return ts; - pts = &(ts->hash_next); - } - return tok_alloc_new(pts, str, len); -} - /* CString handling */ static void cstr_realloc(CString *cstr, int new_size) @@ -958,108 +863,6 @@ static void add_char(CString *cstr, int c) } } -/* XXX: buffer overflow */ -/* XXX: float tokens */ -char *get_tok_str(int v, CValue *cv) -{ - static char buf[STRING_MAX_SIZE + 1]; - static CString cstr_buf; - CString *cstr; - unsigned char *q; - char *p; - int i, len; - - /* NOTE: to go faster, we give a fixed buffer for small strings */ - cstr_reset(&cstr_buf); - cstr_buf.data = buf; - cstr_buf.size_allocated = sizeof(buf); - p = buf; - - switch(v) { - case TOK_CINT: - case TOK_CUINT: - /* XXX: not quite exact, but only useful for testing */ - sprintf(p, "%u", cv->ui); - break; - case TOK_CLLONG: - case TOK_CULLONG: - /* XXX: not quite exact, but only useful for testing */ - sprintf(p, "%Lu", cv->ull); - break; - case TOK_LCHAR: - cstr_ccat(&cstr_buf, 'L'); - case TOK_CCHAR: - cstr_ccat(&cstr_buf, '\''); - add_char(&cstr_buf, cv->i); - cstr_ccat(&cstr_buf, '\''); - cstr_ccat(&cstr_buf, '\0'); - break; - case TOK_PPNUM: - cstr = cv->cstr; - len = cstr->size - 1; - for(i=0;idata)[i]); - cstr_ccat(&cstr_buf, '\0'); - break; - case TOK_LSTR: - cstr_ccat(&cstr_buf, 'L'); - case TOK_STR: - cstr = cv->cstr; - cstr_ccat(&cstr_buf, '\"'); - if (v == TOK_STR) { - len = cstr->size - 1; - for(i=0;idata)[i]); - } else { - len = (cstr->size / sizeof(nwchar_t)) - 1; - for(i=0;idata)[i]); - } - cstr_ccat(&cstr_buf, '\"'); - cstr_ccat(&cstr_buf, '\0'); - break; - case TOK_LT: - v = '<'; - goto addv; - case TOK_GT: - v = '>'; - goto addv; - case TOK_DOTS: - return strcpy(p, "..."); - case TOK_A_SHL: - return strcpy(p, "<<="); - case TOK_A_SAR: - return strcpy(p, ">>="); - default: - if (v < TOK_IDENT) { - /* search in two bytes table */ - q = tok_two_chars; - while (*q) { - if (q[2] == v) { - *p++ = q[0]; - *p++ = q[1]; - *p = '\0'; - return buf; - } - q += 3; - } - addv: - *p++ = v; - *p = '\0'; - } else if (v < tok_ident) { - return table_ident[v - TOK_IDENT]->str; - } else if (v >= SYM_FIRST_ANOM) { - /* special name for anonymous symbol */ - sprintf(p, "L.%u", v - SYM_FIRST_ANOM); - } else { - /* should never happen */ - return NULL; - } - break; - } - return cstr_buf.data; -} - /* push, without hashing */ static Sym *sym_push2(Sym **ps, int v, int t, long c) { @@ -1220,21 +1023,6 @@ void tcc_close(BufferedFile *bf) #include "tccpp.c" #include "tccgen.c" -/* better than nothing, but needs extension to handle '-E' option - correctly too */ -static void preprocess_init(TCCState *s1) -{ - s1->include_stack_ptr = s1->include_stack; - /* XXX: move that before to avoid having to initialize - file->ifdef_stack_ptr ? */ - s1->ifdef_stack_ptr = s1->ifdef_stack; - file->ifdef_stack_ptr = s1->ifdef_stack_ptr; - - /* XXX: not ANSI compliant: bound checking says error */ - vtop = vstack - 1; - s1->pack_stack[0] = 0; - s1->pack_stack_ptr = s1->pack_stack; -} /* compile the C file opened in 'file'. Return non zero if errors. */ static int tcc_compile(TCCState *s1) @@ -1342,48 +1130,6 @@ static int tcc_compile(TCCState *s1) return s1->nb_errors != 0 ? -1 : 0; } -/* Preprocess the current file */ -static int tcc_preprocess(TCCState *s1) -{ - Sym *define_start; - BufferedFile *file_ref; - int token_seen, line_ref; - - preprocess_init(s1); - define_start = define_stack; - ch = file->buf_ptr[0]; - tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; - parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS | - PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES; - token_seen = 0; - line_ref = 0; - file_ref = NULL; - - for (;;) { - next(); - if (tok == TOK_EOF) { - break; - } else if (tok == TOK_LINEFEED) { - if (!token_seen) - continue; - ++line_ref; - token_seen = 0; - } else if (!token_seen) { - int d = file->line_num - line_ref; - if (file != file_ref || d < 0 || d >= 8) - fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename); - else - while (d) - fputs("\n", s1->outfile), --d; - line_ref = (file_ref = file)->line_num; - token_seen = 1; - } - fputs(get_tok_str(tok, &tokc), s1->outfile); - } - free_defines(define_start); - return 0; -} - #ifdef LIBTCC int tcc_compile_string(TCCState *s, const char *str) { @@ -1909,10 +1655,7 @@ static void tcc_cleanup(void) TCCState *tcc_new(void) { - const char *p, *r; TCCState *s; - TokenSym *ts; - int i, c; tcc_cleanup(); @@ -1922,26 +1665,7 @@ TCCState *tcc_new(void) tcc_state = s; s->output_type = TCC_OUTPUT_MEMORY; - /* init isid table */ - for(i=CH_EOF;i<256;i++) - isidnum_table[i-CH_EOF] = isid(i) || isnum(i); - - /* add all tokens */ - table_ident = NULL; - memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); - - tok_ident = TOK_IDENT; - p = tcc_keywords; - while (*p) { - r = p; - for(;;) { - c = *r++; - if (c == '\0') - break; - } - ts = tok_alloc(p, r - p - 1); - p = r; - } + preprocess_new(); /* we add dummy defines for some special macros to speed up tests and to have working defined() */ diff --git a/tcc.c b/tcc.c index 599f210..556ca38 100644 --- a/tcc.c +++ b/tcc.c @@ -22,19 +22,6 @@ #if !defined(LIBTCC) -static int64_t getclock_us(void) -{ -#ifdef _WIN32 - struct _timeb tb; - _ftime(&tb); - return (tb.time * 1000LL + tb.millitm) * 1000LL; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000LL + tv.tv_usec; -#endif -} - void help(void) { printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n" @@ -76,6 +63,15 @@ void help(void) ); } +static char **files; +static int nb_files, nb_libraries; +static int multiple_files; +static int print_search_dirs; +static int output_type; +static int reloc_output; +static const char *outfile; +static int do_bench = 0; + #define TCC_OPTION_HAS_ARG 0x0001 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */ @@ -157,6 +153,35 @@ static const TCCOption tcc_options[] = { { NULL }, }; +static int64_t getclock_us(void) +{ +#ifdef _WIN32 + struct _timeb tb; + _ftime(&tb); + return (tb.time * 1000LL + tb.millitm) * 1000LL; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000LL + tv.tv_usec; +#endif +} + +static int strstart(const char *str, const char *val, const char **ptr) +{ + const char *p, *q; + p = str; + q = val; + while (*q != '\0') { + if (*p != *q) + return 0; + p++; + q++; + } + if (ptr) + *ptr = p; + return 1; +} + /* convert 'str' into an array of space separated strings */ static int expand_args(char ***pargv, const char *str) { @@ -184,14 +209,6 @@ static int expand_args(char ***pargv, const char *str) return argc; } -static char **files; -static int nb_files, nb_libraries; -static int multiple_files; -static int print_search_dirs; -static int output_type; -static int reloc_output; -static const char *outfile; - int parse_args(TCCState *s, int argc, char **argv) { int optind; diff --git a/tcc.h b/tcc.h index c074505..2890493 100644 --- a/tcc.h +++ b/tcc.h @@ -210,6 +210,9 @@ typedef struct Sym { the other ones */ #define SHF_PRIVATE 0x80000000 +/* special flag, too */ +#define SECTION_ABS ((void *)1) + typedef struct Section { unsigned long data_offset; /* current data offset */ unsigned char *data; /* section data */ @@ -580,9 +583,6 @@ struct TCCState { #define countof(tab) (sizeof(tab) / sizeof((tab)[0])) #endif -/* WARNING: the content of this string encodes token numbers */ -static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; - #define TOK_EOF (-1) /* end of file */ #define TOK_LINEFEED 10 /* line feed */ @@ -655,12 +655,6 @@ enum tcc_token { #undef DEF }; -static const char tcc_keywords[] = -#define DEF(id, str) str "\0" -#include "tcctok.h" -#undef DEF -; - #define TOK_UIDENT TOK_DEFINE #ifdef _WIN32 @@ -688,6 +682,16 @@ extern float strtof (const char *__nptr, char **__endptr); extern long double strtold (const char *__nptr, char **__endptr); #endif +#ifdef _WIN32 +#define IS_PATHSEP(c) (c == '/' || c == '\\') +#define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2]))) +#define PATHCMP stricmp +#else +#define IS_PATHSEP(c) (c == '/') +#define IS_ABSPATH(p) IS_PATHSEP(p[0]) +#define PATHCMP strcmp +#endif + static char *pstrcpy(char *buf, int buf_size, const char *s); static char *pstrcat(char *buf, int buf_size, const char *s); static char *tcc_basename(const char *name); diff --git a/tccpp.c b/tccpp.c index 6bc7814..0c14c24 100644 --- a/tccpp.c +++ b/tccpp.c @@ -18,6 +18,182 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +static const char tcc_keywords[] = +#define DEF(id, str) str "\0" +#include "tcctok.h" +#undef DEF +; + +/* WARNING: the content of this string encodes token numbers */ +static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; + +/* true if isid(c) || isnum(c) */ +static unsigned char isidnum_table[256-CH_EOF]; + + +/* allocate a new token */ +static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) +{ + TokenSym *ts, **ptable; + int i; + + if (tok_ident >= SYM_FIRST_ANOM) + error("memory full"); + + /* expand token table if needed */ + i = tok_ident - TOK_IDENT; + if ((i % TOK_ALLOC_INCR) == 0) { + ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *)); + if (!ptable) + error("memory full"); + table_ident = ptable; + } + + ts = tcc_malloc(sizeof(TokenSym) + len); + table_ident[i] = ts; + ts->tok = tok_ident++; + ts->sym_define = NULL; + ts->sym_label = NULL; + ts->sym_struct = NULL; + ts->sym_identifier = NULL; + ts->len = len; + ts->hash_next = NULL; + memcpy(ts->str, str, len); + ts->str[len] = '\0'; + *pts = ts; + return ts; +} + +#define TOK_HASH_INIT 1 +#define TOK_HASH_FUNC(h, c) ((h) * 263 + (c)) + +/* find a token and add it if not found */ +static TokenSym *tok_alloc(const char *str, int len) +{ + TokenSym *ts, **pts; + int i; + unsigned int h; + + h = TOK_HASH_INIT; + for(i=0;ilen == len && !memcmp(ts->str, str, len)) + return ts; + pts = &(ts->hash_next); + } + return tok_alloc_new(pts, str, len); +} + +/* XXX: buffer overflow */ +/* XXX: float tokens */ +char *get_tok_str(int v, CValue *cv) +{ + static char buf[STRING_MAX_SIZE + 1]; + static CString cstr_buf; + CString *cstr; + unsigned char *q; + char *p; + int i, len; + + /* NOTE: to go faster, we give a fixed buffer for small strings */ + cstr_reset(&cstr_buf); + cstr_buf.data = buf; + cstr_buf.size_allocated = sizeof(buf); + p = buf; + + switch(v) { + case TOK_CINT: + case TOK_CUINT: + /* XXX: not quite exact, but only useful for testing */ + sprintf(p, "%u", cv->ui); + break; + case TOK_CLLONG: + case TOK_CULLONG: + /* XXX: not quite exact, but only useful for testing */ + sprintf(p, "%Lu", cv->ull); + break; + case TOK_LCHAR: + cstr_ccat(&cstr_buf, 'L'); + case TOK_CCHAR: + cstr_ccat(&cstr_buf, '\''); + add_char(&cstr_buf, cv->i); + cstr_ccat(&cstr_buf, '\''); + cstr_ccat(&cstr_buf, '\0'); + break; + case TOK_PPNUM: + cstr = cv->cstr; + len = cstr->size - 1; + for(i=0;idata)[i]); + cstr_ccat(&cstr_buf, '\0'); + break; + case TOK_LSTR: + cstr_ccat(&cstr_buf, 'L'); + case TOK_STR: + cstr = cv->cstr; + cstr_ccat(&cstr_buf, '\"'); + if (v == TOK_STR) { + len = cstr->size - 1; + for(i=0;idata)[i]); + } else { + len = (cstr->size / sizeof(nwchar_t)) - 1; + for(i=0;idata)[i]); + } + cstr_ccat(&cstr_buf, '\"'); + cstr_ccat(&cstr_buf, '\0'); + break; + case TOK_LT: + v = '<'; + goto addv; + case TOK_GT: + v = '>'; + goto addv; + case TOK_DOTS: + return strcpy(p, "..."); + case TOK_A_SHL: + return strcpy(p, "<<="); + case TOK_A_SAR: + return strcpy(p, ">>="); + default: + if (v < TOK_IDENT) { + /* search in two bytes table */ + q = tok_two_chars; + while (*q) { + if (q[2] == v) { + *p++ = q[0]; + *p++ = q[1]; + *p = '\0'; + return buf; + } + q += 3; + } + addv: + *p++ = v; + *p = '\0'; + } else if (v < tok_ident) { + return table_ident[v - TOK_IDENT]->str; + } else if (v >= SYM_FIRST_ANOM) { + /* special name for anonymous symbol */ + sprintf(p, "L.%u", v - SYM_FIRST_ANOM); + } else { + /* should never happen */ + return NULL; + } + break; + } + return cstr_buf.data; +} + /* fill input buffer and peek next char */ static int tcc_peekc_slow(BufferedFile *bf) { @@ -2661,3 +2837,89 @@ static inline void unget_tok(int last_tok) } +/* better than nothing, but needs extension to handle '-E' option + correctly too */ +static void preprocess_init(TCCState *s1) +{ + s1->include_stack_ptr = s1->include_stack; + /* XXX: move that before to avoid having to initialize + file->ifdef_stack_ptr ? */ + s1->ifdef_stack_ptr = s1->ifdef_stack; + file->ifdef_stack_ptr = s1->ifdef_stack_ptr; + + /* XXX: not ANSI compliant: bound checking says error */ + vtop = vstack - 1; + s1->pack_stack[0] = 0; + s1->pack_stack_ptr = s1->pack_stack; +} + +void preprocess_new() +{ + int i, c; + const char *p, *r; + TokenSym *ts; + + /* init isid table */ + for(i=CH_EOF;i<256;i++) + isidnum_table[i-CH_EOF] = isid(i) || isnum(i); + + /* add all tokens */ + table_ident = NULL; + memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); + + tok_ident = TOK_IDENT; + p = tcc_keywords; + while (*p) { + r = p; + for(;;) { + c = *r++; + if (c == '\0') + break; + } + ts = tok_alloc(p, r - p - 1); + p = r; + } +} + +/* Preprocess the current file */ +static int tcc_preprocess(TCCState *s1) +{ + Sym *define_start; + BufferedFile *file_ref; + int token_seen, line_ref; + + preprocess_init(s1); + define_start = define_stack; + ch = file->buf_ptr[0]; + tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; + parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS | + PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES; + token_seen = 0; + line_ref = 0; + file_ref = NULL; + + for (;;) { + next(); + if (tok == TOK_EOF) { + break; + } else if (tok == TOK_LINEFEED) { + if (!token_seen) + continue; + ++line_ref; + token_seen = 0; + } else if (!token_seen) { + int d = file->line_num - line_ref; + if (file != file_ref || d < 0 || d >= 8) + fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename); + else + while (d) + fputs("\n", s1->outfile), --d; + line_ref = (file_ref = file)->line_num; + token_seen = 1; + } + fputs(get_tok_str(tok, &tokc), s1->outfile); + } + free_defines(define_start); + return 0; +} +