| @@ -54,6 +54,9 @@ static rt_context g_rtctxt; · 53 unmodified lines |
| 54 | 54 | static void set_exception_handler(void); |
| 55 | 55 | static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); |
| 56 | 56 | static void rt_exit(int code); |
| 57 | +static void init_atexit(void); |
| 58 | +static void run_atexit(void); |
| 59 | +static int rt_atexit(void (*function)(void)); |
| 57 | 60 | #endif /* CONFIG_TCC_BACKTRACE */ |
| 58 | 61 | |
| 59 | 62 | /* defined when included from lib/bt-exe.c */ |
| @@ -169,6 +172,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 109 unmodified lines |
| 169 | 172 | if (s1->do_debug) |
| 170 | 173 | tcc_add_symbol(s1, "exit", rt_exit); |
| 171 | 174 | #endif |
| 175 | + tcc_add_symbol(s1, "atexit", rt_atexit); |
| 172 | 176 | if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) |
| 173 | 177 | return -1; |
| 174 | 178 | prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1); |
| @@ -215,6 +219,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 40 unmodified lines |
| 215 | 219 | errno = 0; /* clean errno value */ |
| 216 | 220 | fflush(stdout); |
| 217 | 221 | fflush(stderr); |
| 222 | + init_atexit(); |
| 218 | 223 | /* These aren't C symbols, so don't need leading underscore handling. */ |
| 219 | 224 | run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp); |
| 220 | 225 | #ifdef CONFIG_TCC_BACKTRACE |
| @@ -224,6 +229,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 3 unmodified lines |
| 224 | 229 | ret = prog_main(argc, argv, envp); |
| 225 | 230 | } |
| 226 | 231 | run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL); |
| 232 | + run_atexit(); |
| 227 | 233 | if ((s1->dflag & 16) && ret) |
| 228 | 234 | fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp); |
| 229 | 235 | return ret; |
| @@ -1022,6 +1028,29 @@ static void rt_exit(int code) · 792 unmodified lines |
| 1022 | 1028 | exit(code); |
| 1023 | 1029 | } |
| 1024 | 1030 | |
| 1031 | +#define NR_AT_EXIT 32 |
| 1032 | + |
| 1033 | +static int nr_atexit = 0; |
| 1034 | +static void (*at_exitfunc[NR_AT_EXIT])(void); |
| 1035 | + |
| 1036 | +static void init_atexit(void) |
| 1037 | +{ |
| 1038 | + nr_atexit = 0; |
| 1039 | +} |
| 1040 | + |
| 1041 | +static void run_atexit(void) |
| 1042 | +{ |
| 1043 | + while (nr_atexit) |
| 1044 | + at_exitfunc[--nr_atexit](); |
| 1045 | +} |
| 1046 | + |
| 1047 | +static int rt_atexit(void (*function)(void)) |
| 1048 | +{ |
| 1049 | + if (nr_atexit < NR_AT_EXIT) |
| 1050 | + at_exitfunc[nr_atexit++] = function; |
| 1051 | + return 1; |
| 1052 | +} |
| 1053 | + |
| 1025 | 1054 | /* ------------------------------------------------------------- */ |
| 1026 | 1055 | |
| 1027 | 1056 | #ifndef _WIN32 |