move minor things from libtcc.c to other files

tcc-xref
grischka 2009-05-05 20:30:39 +02:00
parent 92204e8818
commit b8f6e1ae30
4 changed files with 314 additions and 307 deletions

278
libtcc.c
View File

@ -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;i<len;i++)
h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
h &= (TOK_HASH_SIZE - 1);
pts = &hash_ident[h];
for(;;) {
ts = *pts;
if (!ts)
break;
if (ts->len == 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;i<len;i++)
add_char(&cstr_buf, ((unsigned char *)cstr->data)[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;i<len;i++)
add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
} else {
len = (cstr->size / sizeof(nwchar_t)) - 1;
for(i=0;i<len;i++)
add_char(&cstr_buf, ((nwchar_t *)cstr->data)[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() */

59
tcc.c
View File

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

22
tcc.h
View File

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

262
tccpp.c
View File

@ -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;i<len;i++)
h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
h &= (TOK_HASH_SIZE - 1);
pts = &hash_ident[h];
for(;;) {
ts = *pts;
if (!ts)
break;
if (ts->len == 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;i<len;i++)
add_char(&cstr_buf, ((unsigned char *)cstr->data)[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;i<len;i++)
add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
} else {
len = (cstr->size / sizeof(nwchar_t)) - 1;
for(i=0;i<len;i++)
add_char(&cstr_buf, ((nwchar_t *)cstr->data)[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;
}