This can be used by StreetLISP in order to automatically generate bindings for C libraries at run time rather than compile time.
Unified · Split
| @@ -704,6 +704,18 @@ LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc · 703 unmodified lines | ||
| 704 | 704 | s->error_func = error_func; |
| 705 | 705 | } |
| 706 | 706 | |
| 707 | +LIBTCCAPI void tcc_set_decl_func(TCCState *s, void *decl_opaque, TCCDeclFunc *decl_func) | |
| 708 | +{ | |
| 709 | + s->decl_opaque = decl_opaque; | |
| 710 | + s->decl_func = decl_func; | |
| 711 | +} | |
| 712 | + | |
| 713 | +LIBTCCAPI void tcc_set_define_func(TCCState *s, void *define_opaque, TCCDefineFunc *define_func) | |
| 714 | +{ | |
| 715 | + s->define_opaque = define_opaque; | |
| 716 | + s->define_func = define_func; | |
| 717 | +} | |
| 718 | + | |
| 707 | 719 | /* error without aborting current compilation */ |
| 708 | 720 | PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) |
| 709 | 721 | { |
| @@ -30,6 +30,13 @@ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); · 29 unmodified lines | ||
| 30 | 30 | typedef void TCCErrorFunc(void *opaque, const char *msg); |
| 31 | 31 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func); |
| 32 | 32 | |
| 33 | +typedef struct CType CType; | |
| 34 | +typedef void TCCDeclFunc(void *opaque, const char *file, int line, int v, int l, CType *type); | |
| 35 | +LIBTCCAPI void tcc_set_decl_func(TCCState *s, void *decl_opaque, TCCDeclFunc *decl_func); | |
| 36 | + | |
| 37 | +typedef void TCCDefineFunc(void *opaque, const char *file, int line, int v, int macro_type, int *str); | |
| 38 | +LIBTCCAPI void tcc_set_define_func(TCCState *s, void *define_opaque, TCCDefineFunc *define_func); | |
| 39 | + | |
| 33 | 40 | /* set options as from command line (multiple supported) */ |
| 34 | 41 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str); |
| 35 | 42 | |
| @@ -843,6 +843,12 @@ struct TCCState { · 842 unmodified lines | ||
| 843 | 843 | /* -include options */ |
| 844 | 844 | CString cmdline_incl; |
| 845 | 845 | |
| 846 | + /* user callbacks */ | |
| 847 | + void *decl_opaque; | |
| 848 | + void (*decl_func)(void *opaque, const char *filename, int line, int v, int l, CType *type); | |
| 849 | + void *define_opaque; | |
| 850 | + void (*define_func)(void *opaque, const char *filename, int line, int v, int macro_type, int *str); | |
| 851 | + | |
| 846 | 852 | /* error handling */ |
| 847 | 853 | void *error_opaque; |
| 848 | 854 | void (*error_func)(void *opaque, const char *msg); |
| @@ -8790,9 +8790,10 @@ static int decl(int l) · 8789 unmodified lines | ||
| 8790 | 8790 | |
| 8791 | 8791 | while (1) { /* iterate thru each declaration */ |
| 8792 | 8792 | type = btype; |
| 8793 | − ad = adbase; | |
| 8793 | + ad = adbase; | |
| 8794 | 8794 | type_decl(&type, &ad, &v, l == VT_CMP ? TYPE_DIRECT | TYPE_PARAM : TYPE_DIRECT); |
| 8795 | 8795 | /*ptype("decl", &type, v);*/ |
| 8796 | + | |
| 8796 | 8797 | if ((type.t & VT_BTYPE) == VT_FUNC) { |
| 8797 | 8798 | if ((type.t & VT_STATIC) && (l != VT_CONST)) |
| 8798 | 8799 | tcc_error("function without file scope cannot be static"); |
| @@ -8878,6 +8879,8 @@ static int decl(int l) · 79 unmodified lines | ||
| 8878 | 8879 | cur_text_section->sh_flags = text_section->sh_flags; |
| 8879 | 8880 | gen_function(sym); |
| 8880 | 8881 | } |
| 8882 | + if (tcc_state->decl_func) | |
| 8883 | + tcc_state->decl_func(tcc_state->decl_opaque, file->filename, file->line_num, v, l, &type); | |
| 8881 | 8884 | break; |
| 8882 | 8885 | } else { |
| 8883 | 8886 | has_init = 0; |
| @@ -8969,6 +8972,8 @@ static int decl(int l) · 85 unmodified lines | ||
| 8969 | 8972 | esym->st_value, esym->st_size, 1); |
| 8970 | 8973 | } |
| 8971 | 8974 | } |
| 8975 | + if (tcc_state->decl_func) | |
| 8976 | + tcc_state->decl_func(tcc_state->decl_opaque, file->filename, file->line_num, v, l, &type); | |
| 8972 | 8977 | if (tok != ',') { |
| 8973 | 8978 | if (l == VT_JMP) |
| 8974 | 8979 | return has_init ? v : 1; |
| @@ -1266,6 +1266,7 @@ static int macro_is_equal(const int *a, const int *b) · 1265 unmodified lines | ||
| 1266 | 1266 | /* defines handling */ |
| 1267 | 1267 | ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) |
| 1268 | 1268 | { |
| 1269 | + TCCState *s1 = tcc_state; | |
| 1269 | 1270 | Sym *s, *o; |
| 1270 | 1271 | |
| 1271 | 1272 | o = define_find(v); |
| @@ -1274,8 +1275,11 @@ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) · 2 unmodified lines | ||
| 1274 | 1275 | s->next = first_arg; |
| 1275 | 1276 | table_ident[v - TOK_IDENT]->sym_define = s; |
| 1276 | 1277 | |
| 1278 | + if (s1->define_func != NULL) | |
| 1279 | + s1->define_func(s1->define_opaque, file->filename, file->line_num, v, macro_type, str); | |
| 1280 | + | |
| 1277 | 1281 | if (o && !macro_is_equal(o->d, s->d)) |
| 1278 | − tcc_warning("%s redefined", get_tok_str(v, NULL)); | |
| 1282 | + tcc_warning("%s redefined", get_tok_str(v, NULL)); | |
| 1279 | 1283 | } |
| 1280 | 1284 | |
| 1281 | 1285 | /* undefined a define symbol. Its name is just set to zero */ |