diff --git a/programs/develop/ktcc/trunk/bin/lib/libc.def b/programs/develop/ktcc/trunk/bin/lib/libc.def index 37549fcf3..f3896503a 100644 --- a/programs/develop/ktcc/trunk/bin/lib/libc.def +++ b/programs/develop/ktcc/trunk/bin/lib/libc.def @@ -47,11 +47,13 @@ vsscanf ungetc ;____STDLIB____ abs +abort atoi atol atoll atof calloc +_exit exit free itoa diff --git a/programs/develop/ktcc/trunk/libc.obj/.gitignore b/programs/develop/ktcc/trunk/libc.obj/.gitignore new file mode 100644 index 000000000..8211fe2bd --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/.gitignore @@ -0,0 +1,4 @@ +.tup +*.o +*.obj +*.kex \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc.obj/include/stdlib.h b/programs/develop/ktcc/trunk/libc.obj/include/stdlib.h index bd868f070..4863dcb45 100644 --- a/programs/develop/ktcc/trunk/libc.obj/include/stdlib.h +++ b/programs/develop/ktcc/trunk/libc.obj/include/stdlib.h @@ -48,7 +48,13 @@ DLLAPI void free(void* ptr); DLLAPI long int strtol(const char* str, char** endptr, int base); +DLLAPI void _exit(int status); +#ifndef _Exit +#define _Exit(status) _exit(status); +#endif + DLLAPI void exit(int status); +DLLAPI void abort(); DLLAPI void srand(unsigned s); DLLAPI int rand(void); diff --git a/programs/develop/ktcc/trunk/libc.obj/samples/Makefile b/programs/develop/ktcc/trunk/libc.obj/samples/Makefile index 49725be3d..020298237 100644 --- a/programs/develop/ktcc/trunk/libc.obj/samples/Makefile +++ b/programs/develop/ktcc/trunk/libc.obj/samples/Makefile @@ -27,7 +27,8 @@ BIN = \ libc_test.kex \ pipe.kex \ defgen.kex \ - futex.kex + futex.kex \ + atexit_test.kex all: $(BIN) diff --git a/programs/develop/ktcc/trunk/libc.obj/samples/atexit_test.c b/programs/develop/ktcc/trunk/libc.obj/samples/atexit_test.c new file mode 100644 index 000000000..3bf8609d0 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/samples/atexit_test.c @@ -0,0 +1,18 @@ +#include +#include + +void f() +{ + static int c = 1; + printf("exit #%d\n", c); + c++; +} + +int main() +{ + atexit(&f); + atexit(&f); + atexit(&f); + + return 0; +} diff --git a/programs/develop/ktcc/trunk/libc.obj/samples/build_all.sh b/programs/develop/ktcc/trunk/libc.obj/samples/build_all.sh index fb6e57cf7..4a75e9da9 100644 --- a/programs/develop/ktcc/trunk/libc.obj/samples/build_all.sh +++ b/programs/develop/ktcc/trunk/libc.obj/samples/build_all.sh @@ -23,5 +23,6 @@ cp clayer/logo.png /tmp0/1/tcc_samples/logo.png ../tcc defgen.c -o /tmp0/1/tcc_samples/defgen ../tcc pipe.c -o /tmp0/1/tcc_samples/pipe ../tcc futex.c -o /tmp0/1/tcc_samples/futex +../tcc atexit_test.c -o /tmp0/1/tcc_samples/atexit_test "/sys/File managers/Eolite" /tmp0/1/tcc_samples exit diff --git a/programs/develop/ktcc/trunk/libc.obj/source/crt/crt0.asm b/programs/develop/ktcc/trunk/libc.obj/source/crt/crt0.asm index 596fba564..ecfa9f00c 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/crt/crt0.asm +++ b/programs/develop/ktcc/trunk/libc.obj/source/crt/crt0.asm @@ -14,6 +14,7 @@ public start public start as '_start' extrn main +extrn exit include '../../../../../../proc32.inc' include '../../../../../../macros.inc' @@ -38,36 +39,36 @@ start: call push_param ; retrieving parameters mov esi, params - xor edx, edx ; dl - идёт параметр(1) или разделители(0) - ; dh - символ с которого начался параметр (1 кавычки, 0 остальное) + xor edx, edx ; dl - is it a parameter (1) or delimiters (0) + ; dh - character with which the parameter started (1 quotes, 0 everything else) mov ecx, 1 ; cl = 1 - ; ch = 0 просто ноль + ; ch = 0 just zero .parse: lodsb test al, al jz .run test dl, dl jnz .findendparam - ;{если был разделитель + ;{if it was a delimiter cmp al, ' ' - jz .parse ;загружен пробел, грузим следующий символ - mov dl, cl ;начинается параметр + jz .parse ; space loaded, load next character + mov dl, cl ; parameter starts cmp al, '"' - jz @f ;загружены кавычки - mov dh, ch ;параметр без кавычек + jz @f ; quotes loaded + mov dh, ch ; parameter without quotes dec esi call push_param inc esi jmp .parse @@: - mov dh, cl ;параметр в кавычеках - call push_param ;если не пробел значит начинается какой то параметр - jmp .parse ;если был разделитель} + mov dh, cl ; parameter in quotes + call push_param ; if not a space, then some parameter starts + jmp .parse ; if it was a delimiter} .findendparam: test dh, dh - jz @f ; без кавычек + jz @f ; without quotes cmp al, '"' jz .clear jmp .parse @@ -86,10 +87,9 @@ start: push [argc] call main .exit: - xor eax,eax - dec eax - int 0x40 - dd -1 + push eax + call dword [exit] + dd -1 .crash: jmp .exit ;============================ diff --git a/programs/develop/ktcc/trunk/libc.obj/source/libc.c b/programs/develop/ktcc/trunk/libc.obj/source/libc.c index 5f1123eca..c269045b5 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/libc.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/libc.c @@ -82,6 +82,7 @@ #include "string/strstr.c" #include "string/strtok.c" #include "string/strxfrm.c" + #include "stdlib/abs.c" #include "stdlib/assert.c" #include "stdlib/atof.c" @@ -89,7 +90,9 @@ #include "stdlib/atol.c" #include "stdlib/atoll.c" #include "stdlib/calloc.c" +#include "stdlib/atexit.c" #include "stdlib/exit.c" +#include "stdlib/_exit.c" #include "stdlib/free.c" #include "stdlib/itoa.c" #include "stdlib/labs.c" @@ -100,6 +103,7 @@ #include "stdlib/realloc.c" #include "stdlib/strtod.c" #include "stdlib/strtol.c" +#include "stdlib/abort.c" #include "math/acosh.c" #include "math/asinh.c" @@ -170,7 +174,9 @@ ksys_dll_t EXPORTS[] = { { "atoll", &atoll }, { "atof", &atof }, { "calloc", &calloc }, + { "_exit", &_exit }, { "exit", &exit }, + { "abort", &abort }, { "free", &free }, { "itoa", &itoa }, { "labs", &labs }, diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.c new file mode 100644 index 000000000..5382cc62f --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.c @@ -0,0 +1,26 @@ +#include +#include +#include + +void _exit(int status) +{ + __libc_exit(status, NULL); +} + +void __libc_exit(int status, void (*before_exit)(int status)) +{ + // return error and this is not abort + if (status && status != 128) { + fprintf(stderr, "\nexit code: %d\n", status); + } + + if (before_exit) { + before_exit(status); + } + + if (__con_is_load) { + con_exit(0); + } + + _ksys_exit(); +} diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c new file mode 100644 index 000000000..a494f357f --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c @@ -0,0 +1,17 @@ +/* +* SPDX-License-Identifier: GPL-2.0-only +* Copyright (C) 2026 KolibriOS team +*/ + +#include +#include +#include + +void abort() +{ + ksys_thread_t t; + _ksys_thread_info(&t, -1); + fprintf(stderr, "\nAbort in %d\n", t.pid); + + _exit(128); +} diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c new file mode 100644 index 000000000..89c2a6682 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c @@ -0,0 +1,40 @@ +/* +* SPDX-License-Identifier: GPL-2.0-only +* Copyright (C) 2026 KolibriOS team +*/ + +#include + +struct atexit_n { + struct atexit_n* last; + void (*func)(void); +}; + +static struct atexit_n* __last_n = NULL; + +int atexit(void (*func)(void)) +{ + struct atexit_n* n = malloc(sizeof(struct atexit_n)); + + if (n == NULL) { + return 1; + } + + n->last = __last_n; + n->func = func; + + __last_n = n; + + return 0; +} + +void __run_atexit() +{ + struct atexit_n* n = __last_n; + while (n != NULL) { + n->func(); + struct atexit_n* to_free = n; + n = n->last; + free(to_free); + } +} diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/exit.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/exit.c index 1e3bebdc0..f23ff7433 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/exit.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/exit.c @@ -1,12 +1,32 @@ -/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ +/* +* SPDX-License-Identifier: GPL-2.0-only +* Copyright (C) 2021 Logaev Maxim +* Copyright (C) 2026 KolibriOS team +*/ -#include +#include #include +#include "_exit.h" + +/* +TODO +static void __close_all() +{ +} + +static void __free_all_mem() +{ +} +*/ + +void __normal_exit(int status) +{ + __run_atexit(); + __close_all(); + __free_all_mem(); +} void exit(int status) { - if (__con_is_load) { - con_exit(status); - } - _ksys_exit(); + __libc_exit(status, &__normal_exit); }