diff --git a/libtcc.c b/libtcc.c index b10a2a7..cebeddd 100644 --- a/libtcc.c +++ b/libtcc.c @@ -711,27 +711,22 @@ ST_FUNC int tcc_open(TCCState *s1, const char *filename) return fd; } -/* compile the C file opened in 'file'. Return non zero if errors. */ -static int tcc_compile(TCCState *s1) +/* initialize compilation */ +static void tcc_compile_init(TCCState *s1) { - Sym *define_start; - SValue *pvtop; char buf[512]; - volatile int section_sym; -#ifdef INC_DEBUG - printf("%s: **** new file\n", file->filename); -#endif preprocess_init(s1); cur_text_section = NULL; funcname = ""; anon_sym = SYM_FIRST_ANOM; + /* file info: full path + filename */ - section_sym = 0; /* avoid warning */ + s1->section_sym = 0; /* avoid warning */ if (s1->do_debug) { - section_sym = put_elf_sym(symtab_section, 0, 0, + s1->section_sym = put_elf_sym(symtab_section, 0, 0, ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, text_section->sh_num, NULL); getcwd(buf, sizeof(buf)); @@ -740,10 +735,11 @@ static int tcc_compile(TCCState *s1) #endif pstrcat(buf, sizeof(buf), "/"); put_stabs_r(buf, N_SO, 0, 0, - text_section->data_offset, text_section, section_sym); + text_section->data_offset, text_section, s1->section_sym); put_stabs_r(file->filename, N_SO, 0, 0, - text_section->data_offset, text_section, section_sym); + text_section->data_offset, text_section, s1->section_sym); } + /* an elf symbol of type STT_FILE must be put so that STB_LOCAL symbols can be safely used */ put_elf_sym(symtab_section, 0, 0, @@ -781,8 +777,23 @@ static int tcc_compile(TCCState *s1) sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); } #endif + s1->define_start = define_stack; +} + +/* compile the C file opened in 'file'. Return non zero if errors. */ +static int tcc_compile(TCCState *s1, int final) +{ + SValue *pvtop; + + if (! s1->compile) { + tcc_compile_init(s1); + s1->compile++; + } + +#ifdef INC_DEBUG + printf("%s: **** new file\n", file->filename); +#endif - define_start = define_stack; nocode_wanted = 1; if (setjmp(s1->error_jmp_buf) == 0) { @@ -801,38 +812,47 @@ static int tcc_compile(TCCState *s1) tcc_warning("internal compiler error: vstack leak? (%d)", vtop - pvtop); /* end of translation unit info */ - if (s1->do_debug) { + if (final && s1->do_debug) { put_stabs_r(NULL, N_SO, 0, 0, - text_section->data_offset, text_section, section_sym); + text_section->data_offset, text_section, s1->section_sym); } } s1->error_set_jmp_enabled = 0; - /* reset define stack, but leave -Dsymbols (may be incorrect if - they are undefined) */ - free_defines(define_start); - - gen_inline_functions(); + if (s1->nb_errors || final) { + /* reset define stack, but leave -Dsymbols (may be incorrect if + they are undefined) */ + free_defines(s1->define_start); + gen_inline_functions(); - sym_pop(&global_stack, NULL); + sym_pop(&global_stack, NULL); + s1->compile = -1; + } sym_pop(&local_stack, NULL); return s1->nb_errors != 0 ? -1 : 0; } -LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str) +LIBTCCAPI int tcc_compile_string_partial(TCCState *s, const char *str, int final) { int len, ret; len = strlen(str); tcc_open_bf(s, "", len); memcpy(file->buffer, str, len); - ret = tcc_compile(s); + ret = tcc_compile(s, final); tcc_close(); return ret; } + +LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str) +{ + return tcc_compile_string_partial(s, str, 1); +} + + /* define a preprocessor symbol. A value can also be provided with the '=' operator */ LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) { @@ -1039,9 +1059,10 @@ LIBTCCAPI TCCState *tcc_new(void) return s; } -LIBTCCAPI void tcc_delete(TCCState *s1) +LIBTCCAPI void *tcc_delete_ret_code(TCCState *s1) { int i; + void *p = NULL; tcc_cleanup(); @@ -1090,11 +1111,21 @@ LIBTCCAPI void tcc_delete(TCCState *s1) munmap (s1->write_mem, s1->mem_size); munmap (s1->runtime_mem, s1->mem_size); # else - tcc_free(s1->runtime_mem); + p = s1->runtime_mem; # endif #endif + tcc_free(s1->api_data); tcc_free(s1); + return p; +} + +LIBTCCAPI void tcc_delete(TCCState *s1) +{ + void *p; + p = tcc_delete_ret_code(s1); + if (p != NULL) + tcc_free(p); } LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) @@ -1145,7 +1176,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) if (!ext[0] || !PATHCMP(ext, "c")) { /* C file assumed */ - ret = tcc_compile(s1); + ret = tcc_compile(s1, 1); goto the_end; } @@ -1978,3 +2009,187 @@ PUB_FUNC void tcc_set_environment(TCCState *s) tcc_add_library_path(s, path); } } + +/****************************/ +typedef struct Symbol { + Sym *symbol; + Sym *assoc_sym; + int kind; + char name[256]; /* struct or macro name */ +} Symbol; + + +/* numptr is the * count after the pointed-to type */ +static CType *pointer_type(CType *type, int *numptr) +{ + Sym *sym; + int n = 0; + while ((type->t & VT_BTYPE) == VT_PTR) { + n++; + if (! (sym = type->ref)) + return NULL; + type = &(sym->type); + } + if (numptr) + *numptr = n; + return type; +} + +/* return 0 if no more left, else 1 */ +LIBTCCAPI int tcc_next_assoc_symbol(const TCCSymbol *q) +{ + Symbol *sm = (Symbol *) q; + Sym *sym, *sym1; + if (! sm || (sm->kind == TCC_MACRO_DEF)) + return 0; + sym = sm->symbol; + if (! sm->assoc_sym) { + if (sm->kind == TCC_STRUCT_DEF) /* struct definition */ + sym1 = sym->next; /* first field */ + else if ((sym->type.t & VT_BTYPE) == VT_FUNC) /* return type */ + sym1 = sym->type.ref; + else + sym1 = sym->next; + sm->assoc_sym = sym1; + return !!sym1; + } + sym1 = sm->assoc_sym; + /* next parameter or field */ + sym1 = sym1->next; + sm->assoc_sym = sym1; + return !!sym1; +} + +/* always the current symbol */ +LIBTCCAPI const char *tcc_get_symbol_name(const TCCSymbol *q) +{ + Symbol *sm = (Symbol *) q; + Sym *sym; + if (! sm) + tcc_error("tcc_get_symbol_name: invalid usage"); + if (sm->kind == TCC_MACRO_DEF) + return sm->name; /* macro name */ + sym = sm->symbol; + if (sm->kind == TCC_STRUCT_DEF) { + if (! (sym = sm->assoc_sym)) + return sm->name; /* struct name */ + return get_tok_str(sym->v & ~SYM_FIELD, NULL); /* field name */ + } + if (sm->assoc_sym) + sym = sm->assoc_sym; + if (! (sym && sym->v)) + tcc_error("tcc_get_symbol_name: invalid usage"); /* ? */ + return get_tok_str(sym->v, NULL); +} + +/* always the current symbol; 'ptrcnt' not meaningful for struct/macro definition */ +LIBTCCAPI int tcc_get_symbol_type(const TCCSymbol *q, int *ptrcnt) +{ + Symbol *sm = (Symbol *) q; + Sym *sym; + CType *type; + if (! sm) + tcc_error("tcc_get_symbol_type: invalid usage"); + if (sm->kind == TCC_MACRO_DEF) + return TCC_MACRO_DEF; + sym = sm->symbol; + if (sm->kind == TCC_STRUCT_DEF) { + if (! (sym = sm->assoc_sym)) + return TCC_STRUCT_DEF; /* struct definition */ + } else if (sm->assoc_sym) + sym = sm->assoc_sym; + if ((sym->type.t & VT_BTYPE) == VT_FUNC) + return VT_FUNC; + type = pointer_type(& (sym->type), ptrcnt); + return (type->t & VT_BTYPE); +} + +/* return the type name, for a struct include it's name */ +LIBTCCAPI const char *tcc_get_type_name(const TCCSymbol *q) +{ + Symbol *sm = (Symbol *) q; + Sym *sym = NULL; + static char buf[256]; + if (! sm || ! (sym = sm->assoc_sym) || (sm->kind == TCC_MACRO_DEF)) + tcc_error("tcc_get_type_name: invalid usage"); + type_to_str(buf, sizeof(buf), & (sym->type), NULL); + return buf; +} + +/* return a declared symbol, struct or macro definition */ +LIBTCCAPI const TCCSymbol *tcc_find_symbol(TCCState *s, const char *name, int kind) +{ + Symbol *sm; + TokenSym *ts; + Sym *sym; + + if (! s->api_data) + s->api_data = sm = tcc_mallocz(sizeof(Symbol)); + else { + sm = s->api_data; + memset(sm, 0, sizeof(Symbol)); + } + if (! name || name[0] == '\0') + return NULL; + if (! (ts = tok_find(name, strlen(name)))) + return NULL; + switch (kind) { + case TCC_STRUCT_DEF: + if ((sym = struct_find(ts->tok))) { + sm->symbol = sym; + sm->kind = kind; + pstrcat(sm->name, sizeof(sm->name), name); + return sm; + } + return NULL; + case TCC_MACRO_DEF: + if ((sym = define_find(ts->tok))) { + sm->symbol = sym; + sm->kind = kind; + pstrcat(sm->name, sizeof(sm->name), name); + return sm; + } + return NULL; + default: + if ((sym = sym_find(ts->tok))) { + sm->symbol = sym; + sm->kind = TCC_SYM_DECL; + return sm; + } + } + return NULL; +} + +/* get the value of an object-like macro after substitution */ +LIBTCCAPI const char *tcc_get_define_value(const TCCSymbol *q) +{ + Symbol *sm = (Symbol *) q; + Sym *sym; + if (! sm || ! (sm->kind == TCC_MACRO_DEF)) + tcc_error("tcc_get_define_value: invalid usage, not a defined symbol"); + sym = sm->symbol; + if (sym->type.t == MACRO_FUNC) + tcc_error("tcc_get_define_value: cannot get value of a function-like macro"); + return macro_expand(sym); +} + +/* storage type for a declared symbol */ +LIBTCCAPI int tcc_get_symbol_storage(const TCCSymbol *q) +{ + Symbol *sm = (Symbol *) q; + Sym *sym; + if (! sm || sm->kind == TCC_MACRO_DEF || sm->kind == TCC_STRUCT_DEF) + tcc_error("tcc_get_symbol_storage: invalid usage"); + sym = sm->symbol; + return (sym->type.t & VT_STORAGE); +} + +/* only valid for a struct */ +LIBTCCAPI long tcc_get_symbol_offset(const TCCSymbol *q) +{ + Symbol *sm = (Symbol *) q; + Sym *sym = NULL; + if (! sm || sm->kind != TCC_STRUCT_DEF || ! (sym = sm->assoc_sym)) + tcc_error("tcc_get_symbol_offset: invalid usage, not a struct field"); + return sym->c; +} diff --git a/libtcc.h b/libtcc.h index e69cc6b..593154d 100644 --- a/libtcc.h +++ b/libtcc.h @@ -9,6 +9,8 @@ extern "C" { #endif +#include "types.h" + struct TCCState; typedef struct TCCState TCCState; @@ -19,6 +21,9 @@ LIBTCCAPI TCCState *tcc_new(void); /* free a TCC compilation context */ LIBTCCAPI void tcc_delete(TCCState *s); +/* free a TCC compilation context and return code (memory) */ +LIBTCCAPI void *tcc_delete_ret_code(TCCState *s); + /* set CONFIG_TCCDIR at runtime */ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); @@ -53,6 +58,8 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename); /* compile a string containing a C source. Return -1 if error. */ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); +LIBTCCAPI int tcc_compile_string_partial(TCCState *s, const char *buf, int final); + /*****************************/ /* linking commands */ @@ -93,6 +100,45 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr); /* return symbol value or NULL if not found */ LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); +/****************************/ +/* inspecting declarations, struct or macro definitions */ + +typedef void TCCSymbol; + +/* find the named symbol, return NULL if not there. Possible values for 'kind': + TCC_STRUCT_DEF -- lookup a struct definition. + TCC_MACRO_DEF -- lookup a macro definition. + TCC_SYM_DECL -- lookup a declared symbol. + */ +LIBTCCAPI const TCCSymbol *tcc_find_symbol(TCCState *s, const char *name, int kind); + +/* get the name of the symbol or struct field (associted symbol). */ +LIBTCCAPI const char *tcc_get_symbol_name(const TCCSymbol *q); + +/* inspect the next associated symbol or type. For a function declaration, + return type is first, followed by the parameters. For a structure, it is a + field. Not valid for a macro definition. Returns 0 if no more associations, 1 + otherwise. */ +LIBTCCAPI int tcc_next_assoc_symbol(const TCCSymbol *q); + +/* return the type associated with a symbol. See types.h for the + * valid values (the ones with the prefix TCC). */ +LIBTCCAPI int tcc_get_symbol_type(const TCCSymbol *q, int *ptrcnt); + +/* return the type name. */ +LIBTCCAPI const char *tcc_get_type_name(const TCCSymbol *q); + +/* return storage flag (extern, static etc.). See types.h for + the legal values. */ +LIBTCCAPI int tcc_get_symbol_storage(const TCCSymbol *q); + +/* get the value of an object-like macro after substitution + without any expression evalution. */ +LIBTCCAPI const char *tcc_get_define_value(const TCCSymbol *q); + +/* return the offset of a struct field. */ +LIBTCCAPI long tcc_get_symbol_offset(const TCCSymbol *q); + #ifdef __cplusplus } #endif diff --git a/tcc.h b/tcc.h index 859d4fd..8fa4116 100644 --- a/tcc.h +++ b/tcc.h @@ -608,6 +608,8 @@ struct TCCState { int nb_target_deps; /* compilation */ + int compile; + void *api_data; BufferedFile *include_stack[INCLUDE_STACK_SIZE]; BufferedFile **include_stack_ptr; @@ -643,6 +645,9 @@ struct TCCState { /* give the correspondance from symtab indexes to dynsym indexes */ int *symtab_to_dynsym; + /* debugging */ + int section_sym; + /* temporary dynamic symbol sections (for dll loading) */ Section *dynsymtab_section; /* exported dynamic symbol section */ @@ -652,6 +657,9 @@ struct TCCState { /* tiny assembler state */ Sym *asm_labels; + /* define stack bottom */ + Sym *define_start; + #ifdef TCC_TARGET_PE /* PE info */ int pe_subsystem; @@ -715,46 +723,7 @@ struct TCCState { #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED) /* types */ -#define VT_BTYPE 0x000f /* mask for basic type */ -#define VT_INT 0 /* integer type */ -#define VT_BYTE 1 /* signed byte type */ -#define VT_SHORT 2 /* short type */ -#define VT_VOID 3 /* void type */ -#define VT_PTR 4 /* pointer */ -#define VT_ENUM 5 /* enum definition */ -#define VT_FUNC 6 /* function type */ -#define VT_STRUCT 7 /* struct/union definition */ -#define VT_FLOAT 8 /* IEEE float */ -#define VT_DOUBLE 9 /* IEEE double */ -#define VT_LDOUBLE 10 /* IEEE long double */ -#define VT_BOOL 11 /* ISOC99 boolean type */ -#define VT_LLONG 12 /* 64 bit integer */ -#define VT_LONG 13 /* long integer (NEVER USED as type, only - during parsing) */ -#define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */ -#define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */ -#define VT_UNSIGNED 0x0010 /* unsigned type */ -#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ -#define VT_BITFIELD 0x0040 /* bitfield modifier */ -#define VT_CONSTANT 0x0800 /* const modifier */ -#define VT_VOLATILE 0x1000 /* volatile modifier */ -#define VT_SIGNED 0x2000 /* signed type */ -#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */ - -/* storage */ -#define VT_EXTERN 0x00000080 /* extern definition */ -#define VT_STATIC 0x00000100 /* static variable */ -#define VT_TYPEDEF 0x00000200 /* typedef definition */ -#define VT_INLINE 0x00000400 /* inline definition */ -#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ -#define VT_EXPORT 0x00008000 /* win32: data exported from dll */ -#define VT_WEAK 0x00010000 /* weak symbol */ - -#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values (max: 32 - 2*6) */ - -/* type mask (except storage) */ -#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK) -#define VT_TYPE (~(VT_STORAGE)) +#include "types.h" /* token values */ @@ -1107,6 +1076,7 @@ ST_DATA TokenSym **table_ident; #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */ +ST_FUNC TokenSym *tok_find(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 void save_parse_state(ParseState *s); @@ -1132,6 +1102,7 @@ ST_FUNC void preprocess_new(void); ST_FUNC int tcc_preprocess(TCCState *s1); ST_FUNC void skip(int c); ST_FUNC void expect(const char *msg); +ST_FUNC const char *macro_expand(Sym *s); /* ------------ tccgen.c ------------ */ @@ -1217,6 +1188,7 @@ ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsign #if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE ST_FUNC int classify_x86_64_va_arg(CType *ty); #endif +PUB_FUNC void type_to_str(char *buf, int buf_size, CType *type, const char *varstr); /* ------------ tccelf.c ------------ */ diff --git a/tccgen.c b/tccgen.c index 4849b6c..a1f4960 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2224,7 +2224,7 @@ static int is_compatible_parameter_types(CType *type1, CType *type2) printed in the type */ /* XXX: union */ /* XXX: add array and function pointers */ -static void type_to_str(char *buf, int buf_size, +PUB_FUNC void type_to_str(char *buf, int buf_size, CType *type, const char *varstr) { int bt, v, t; diff --git a/tccpp.c b/tccpp.c index aeaf6be..4d7aa3d 100644 --- a/tccpp.c +++ b/tccpp.c @@ -224,8 +224,8 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) #define TOK_HASH_INIT 1 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c)) -/* find a token and add it if not found */ -ST_FUNC TokenSym *tok_alloc(const char *str, int len) +/* find a token, install if not found and add_if_not_found is true */ +static TokenSym *tok_lookup(const char *str, int len, int add_if_not_found) { TokenSym *ts, **pts; int i; @@ -239,8 +239,11 @@ ST_FUNC TokenSym *tok_alloc(const char *str, int len) pts = &hash_ident[h]; for(;;) { ts = *pts; - if (!ts) - break; + if (!ts) { + if (add_if_not_found) + break; + return NULL; + } if (ts->len == len && !memcmp(ts->str, str, len)) return ts; pts = &(ts->hash_next); @@ -248,6 +251,18 @@ ST_FUNC TokenSym *tok_alloc(const char *str, int len) return tok_alloc_new(pts, str, len); } +/* find a token, return NULL if not found */ +ST_FUNC TokenSym *tok_find(const char *str, int len) +{ + return tok_lookup(str, len, 0); +} + +/* find a token and add it if not found */ +ST_FUNC TokenSym *tok_alloc(const char *str, int len) +{ + return tok_lookup(str, len, 1); +} + /* XXX: buffer overflow */ /* XXX: float tokens */ ST_FUNC char *get_tok_str(int v, CValue *cv) @@ -353,6 +368,7 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) return cstr_buf.data; } + /* fill input buffer and peek next char */ static int tcc_peekc_slow(BufferedFile *bf) { @@ -2941,6 +2957,35 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, tok_str_free(macro_str1); } +/* return the string value of a macro after substitution */ + +ST_FUNC const char *macro_expand(Sym *s) +{ + Sym *nested_list; + TokenString str; + struct macro_level *ml; + static char buf[STRING_MAX_SIZE + 1]; + + tok_str_new(&str); + nested_list = NULL; + ml = NULL; + buf[0] = '\0'; + if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) { + /* substitution done, NOTE: maybe empty */ + int t; + CValue cval; + + tok_str_add(&str, 0); + while (1) { + TOK_GET(&t, (const int **) & str.str, &cval); + if (!t) + break; + pstrcat(buf, sizeof buf, get_tok_str(t, &cval)); + } + } + return buf; +} + /* return next token with macro substitution */ ST_FUNC void next(void) { diff --git a/tccrun.c b/tccrun.c index d858ae6..71d5f51 100644 --- a/tccrun.c +++ b/tccrun.c @@ -51,6 +51,9 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) { int ret; + if (s1->compile > 0) + tcc_error("invalid usage of tcc_compile_string"); + if (TCC_RELOCATE_AUTO != ptr) return tcc_relocate_ex(s1, ptr); diff --git a/tests/libtcc_test.c b/tests/libtcc_test.c index bead0ff..4a9f189 100644 --- a/tests/libtcc_test.c +++ b/tests/libtcc_test.c @@ -16,7 +16,12 @@ int add(int a, int b) } char my_program[] = -"int fib(int n)\n" +"#include \n" +"#define YY 888\n" +"#define XX YY+111\n" +"struct Biz { char *p; double q; };\n" +"struct Bar { int x; double y; struct Biz *b;};\n" +"static int fib(int n)\n" "{\n" " if (n <= 2)\n" " return 1;\n" @@ -24,6 +29,9 @@ char my_program[] = " return fib(n-1) + fib(n-2);\n" "}\n" "\n" +"static int *goo = NULL;\n" +"extern double **foo1(char *, double *, struct Bar *);\n" +"static int *fn(char *);\n" "int foo(int n)\n" "{\n" " printf(\"Hello World!\\n\");\n" @@ -32,6 +40,46 @@ char my_program[] = " return 0;\n" "}\n"; +static void +inspect_symbols(TCCState *s, void *data) +{ + const TCCSymbol *ts; + int ptr_count, type; + printf("function foo1:\n"); + ts = tcc_find_symbol(s, "foo1", TCC_SYM_DECL); + if (ts && tcc_get_symbol_type(ts, &ptr_count) == TCC_FUNC) { + while (tcc_next_assoc_symbol(ts)) { + type = tcc_get_symbol_type(ts, &ptr_count); + printf("name = %s, type = %d, #ptr = %d\n", + tcc_get_type_name(ts), type, ptr_count); + } + } + printf("\nfunction sleep:\n"); + ts = tcc_find_symbol(s, "sleep", TCC_SYM_DECL); + if (ts && tcc_get_symbol_type(ts, &ptr_count) == TCC_FUNC) { + while (tcc_next_assoc_symbol(ts)) { + type = tcc_get_symbol_type(ts, &ptr_count); + printf("name = %s, type = %d, #ptr = %d\n", + tcc_get_type_name(ts), type, ptr_count); + } + } + printf("\nstruct Bar:\n"); + ts = tcc_find_symbol(s, "Bar", TCC_STRUCT_DEF); + if (ts) { + while (tcc_next_assoc_symbol(ts)) { + type = tcc_get_symbol_type(ts, & ptr_count); + printf("%s %s: type = %d, #ptr = %d, offset = %ld\n", + tcc_get_type_name(ts), tcc_get_symbol_name(ts), + type, ptr_count, tcc_get_symbol_offset(ts)); + } + } + printf("\ndefine XX:\n"); + ts = tcc_find_symbol(s, "XX", TCC_MACRO_DEF); + if (ts) + printf("XX = %s\n\n", tcc_get_define_value(ts)); +} + + int main(int argc, char **argv) { TCCState *s; @@ -50,7 +98,12 @@ int main(int argc, char **argv) /* MUST BE CALLED before any compilation */ tcc_set_output_type(s, TCC_OUTPUT_MEMORY); - if (tcc_compile_string(s, my_program) == -1) + if (tcc_compile_string_partial(s, my_program, 0) == -1) + return 1; + + inspect_symbols(s, NULL); + + if (tcc_compile_string_partial(s, "", 1) == -1) return 1; /* as a test, we add a symbol that the compiled program can use. @@ -72,5 +125,18 @@ int main(int argc, char **argv) /* delete the state */ tcc_delete(s); +#if 0 + { + long mem_size = tcc_relocate(s, NULL); + void *mem = malloc(mem_size); + tcc_relocate(s, mem); + func = tcc_get_symbol(s, "foo"); + if (!func) + return 1; + tcc_delete_ret_code(s); + func(32); + free(mem); + } +#endif return 0; } diff --git a/types.h b/types.h new file mode 100644 index 0000000..9426c88 --- /dev/null +++ b/types.h @@ -0,0 +1,72 @@ +/* types */ +#define VT_BTYPE 0x000f /* mask for basic type */ +#define VT_INT 0 /* integer type */ +#define VT_BYTE 1 /* signed byte type */ +#define VT_SHORT 2 /* short type */ +#define VT_VOID 3 /* void type */ +#define VT_PTR 4 /* pointer */ +#define VT_ENUM 5 /* enum definition */ +#define VT_FUNC 6 /* function type */ +#define VT_STRUCT 7 /* struct/union definition */ +#define VT_FLOAT 8 /* IEEE float */ +#define VT_DOUBLE 9 /* IEEE double */ +#define VT_LDOUBLE 10 /* IEEE long double */ +#define VT_BOOL 11 /* ISOC99 boolean type */ +#define VT_LLONG 12 /* 64 bit integer */ +#define VT_LONG 13 /* long integer (NEVER USED as type, only + during parsing) */ +#define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */ +#define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */ +#define VT_UNSIGNED 0x0010 /* unsigned type */ +#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ +#define VT_BITFIELD 0x0040 /* bitfield modifier */ +#define VT_CONSTANT 0x0800 /* const modifier */ +#define VT_VOLATILE 0x1000 /* volatile modifier */ +#define VT_SIGNED 0x2000 /* signed type */ +#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */ + +/* storage */ +#define VT_EXTERN 0x00000080 /* extern definition */ +#define VT_STATIC 0x00000100 /* static variable */ +#define VT_TYPEDEF 0x00000200 /* typedef definition */ +#define VT_INLINE 0x00000400 /* inline definition */ +#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ +#define VT_EXPORT 0x00008000 /* win32: data exported from dll */ +#define VT_WEAK 0x00010000 /* weak symbol */ + +#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values (max: 32 - 2*6) */ + +/* type mask (except storage) */ +#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK) +#define VT_TYPE (~(VT_STORAGE)) + + +/* types (not flag values), only used by the libtcc API */ +#define TCC_INT VT_INT +#define TCC_CHAR VT_BYTE +#define TCC_SHORT VT_SHORT +#define TCC_VOID VT_VOID +#define TCC_PTR VT_PTR +#define TCC_ENUM VT_ENUM +#define TCC_FUNC VT_FUNC +#define TCC_STRUCT VT_STRUCT +#define TCC_FLOAT VT_FLOAT +#define TCC_DOUBLE VT_DOUBLE +#define TCC_LDOUBLE VT_LDOUBLE +#define TCC_BOOL VT_BOOL +#define TCC_LLONG VT_LLONG +#define TCC_LONG VT_LONG +#define TCC_QLONG VT_QLONG +#define TCC_QFLOAT VT_QFLOAT +#define TCC_NUM_TYPES (VT_QFLOAT + 1) /* # of basic types */ +#define TCC_STRUCT_DEF TCC_NUM_TYPES /* struct definition */ +#define TCC_MACRO_DEF (TCC_NUM_TYPES + 1) /* macro definition */ +#define TCC_SYM_DECL (TCC_NUM_TYPES + 2) /* declaration */ +/* storage flags */ +#define TCC_EXTERN VT_EXTERN +#define TCC_STATIC VT_STATIC +#define TCC_TYPEDEF VT_TYPEDEF +#define TCC_INLINE VT_INLINE +#define TCC_IMPORT VT_IMPORT +#define TCC_EXPORT VT_EXPORT +#define TCC_WEAK VT_WEAK