/* * atexit + exit + _exit. * * atexit(fn) — register fn to be called at normal termination (max 8). * exit(code) — run the atexit chain in LIFO, then ESTEX EXIT. * _exit(code) — POSIX raw exit: skip the chain, go straight to ESTEX. * * These functions own termination entirely; crt0.s only does inline RST * 10h #41 when main returns without an explicit exit(). That path skips * the atexit chain — programs that need handlers should call exit() at * the bottom of main (or return through a wrapper). */ #include #include #define ATEXIT_MAX 8 static void (*atexit_stack[ATEXIT_MAX])(void); static int atexit_top = 0; int atexit(void (*fn)(void)) { if (atexit_top >= ATEXIT_MAX) { return -1; } atexit_stack[atexit_top++] = fn; return 0; } /* exit() — runs the chain, then performs the raw ESTEX EXIT. */ void exit(int code) { while (atexit_top > 0) { void (*fn)(void) = atexit_stack[--atexit_top]; if (fn) { fn(); } } _exit(code); /* falls into the inline-asm raw exit below */ } /* _exit() — POSIX raw termination, no atexit chain. */ void _exit(int code) __naked { (void)code; __asm ;; HL = code (single int arg). ld a, l ld b, a ld c, #0x41 ; ESTEX EXIT rst #0x10 ;; Should not return. 1$: halt jr 1$ __endasm; }