From 0319a2d7cb258afa76411dfc65cc3ab15f21a062 Mon Sep 17 00:00:00 2001 From: Egor00f Date: Sun, 22 Feb 2026 13:35:37 +0500 Subject: [PATCH 1/5] libc.obj: add call `exit` after main && translate `crt0.asm` and convert it to UTF-8 --- .../ktcc/trunk/libc.obj/source/crt/crt0.asm | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) 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..460938b27 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 ;============================ -- 2.49.1 From ba8747e2abbeee3123b0ee44d33ab14edbce480c Mon Sep 17 00:00:00 2001 From: Egor00f Date: Sun, 22 Feb 2026 13:56:25 +0500 Subject: [PATCH 2/5] libc.obj: add `atexit` and normal exit. add exit code save/read --- .../develop/ktcc/trunk/libc.obj/.gitignore | 4 ++ .../develop/ktcc/trunk/libc.obj/source/libc.c | 4 ++ .../ktcc/trunk/libc.obj/source/stdlib/_exit.c | 29 ++++++++ .../ktcc/trunk/libc.obj/source/stdlib/_exit.h | 69 +++++++++++++++++++ .../trunk/libc.obj/source/stdlib/atexit.c | 35 ++++++++++ .../ktcc/trunk/libc.obj/source/stdlib/exit.c | 23 +++++-- 6 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 programs/develop/ktcc/trunk/libc.obj/.gitignore create mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.c create mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.h create mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c 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/source/libc.c b/programs/develop/ktcc/trunk/libc.obj/source/libc.c index 5f1123eca..6be9ea3f7 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" @@ -170,6 +173,7 @@ ksys_dll_t EXPORTS[] = { { "atoll", &atoll }, { "atof", &atof }, { "calloc", &calloc }, + { "_exit", &_exit }, { "exit", &exit }, { "free", &free }, { "itoa", &itoa }, 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..3709bd43e --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include "_exit.h" + +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); + } + + WRITE_EXIT_CODE(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/_exit.h b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.h new file mode 100644 index 000000000..0e0865a15 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.h @@ -0,0 +1,69 @@ +#ifndef __STDLIB_EXIT_H__ +#define __STDLIB_EXIT_H__ + +#include +#include +#include + +#define __PATH_TO_STATUS_FILE "/tmp0/1/.libc" +#define __STATUS_FILE_EXTENSION ".status" +#define __STATUS_FILE_FORMAT "%d" +#define __FULL_STATUS_FILE_NAME __PATH_TO_STATUS_FILE "/%d" __STATUS_FILE_EXTENSION +#define __FULL_STATUS_FILE_NAME_SIZE (sizeof(__PATH_TO_STATUS_FILE) + 32 + sizeof(__STATUS_FILE_EXTENSION)) + +void __libc_exit(int status, void (*before_exit)(int status)); + +// Save exit code +inline void WRITE_EXIT_CODE(int status) +{ + mkdir(__PATH_TO_STATUS_FILE); + + char buff[__FULL_STATUS_FILE_NAME_SIZE]; + ksys_thread_t t; + + _ksys_thread_info(&t, -1); + snprintf(buff, sizeof(buff), __FULL_STATUS_FILE_NAME, t.pid); + + FILE* f = fopen(buff, "w"); + + if (f) { + snprintf(buff, sizeof(buff), __STATUS_FILE_FORMAT, status); + fputs(buff, f); + fflush(f); + fclose(f); + } else { + _ksys_debug_puts("error while write status\n"); + } +} + +// Read exit code +inline int READ_EXIT_CODE(int pid, ksys_thread_t* t) +{ + char buff[__FULL_STATUS_FILE_NAME_SIZE]; + int status = 0; + bool free_t = false; + + if (!t) { + t = malloc(sizeof(ksys_thread_t)); + _ksys_thread_info(t, -1); + free_t = true; + } + snprintf(buff, sizeof(buff), __FULL_STATUS_FILE_NAME, t->pid); + + FILE* f = fopen(buff, "r"); + if (f) { + fscanf(f, __STATUS_FILE_FORMAT, &status); + fclose(f); + } else if (t && t->slot_state == 4) // it was stopped before it created status file + { + status = -1; + } + + if (free_t) { + free(t); + } + + return status; +} + +#endif // __STDLIB_EXIT_H__ 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..f06d1578e --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c @@ -0,0 +1,35 @@ +#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..3f6afd26e 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,25 @@ /* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ -#include +#include #include +#include "_exit.h" + +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); } -- 2.49.1 From f675fd31b7bef3ec10d8ddb99694998e4bc75a87 Mon Sep 17 00:00:00 2001 From: Egor00f Date: Sun, 22 Feb 2026 14:03:16 +0500 Subject: [PATCH 3/5] libc.obj: add `abort` && add `exit` and `_exit` to `stdlib.h` and `libc.def` --- programs/develop/ktcc/trunk/bin/lib/libc.def | 2 ++ .../develop/ktcc/trunk/libc.obj/include/stdlib.h | 6 ++++++ programs/develop/ktcc/trunk/libc.obj/source/libc.c | 2 ++ .../ktcc/trunk/libc.obj/source/stdlib/abort.c | 12 ++++++++++++ 4 files changed, 22 insertions(+) create mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c 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/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/source/libc.c b/programs/develop/ktcc/trunk/libc.obj/source/libc.c index 6be9ea3f7..c269045b5 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/libc.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/libc.c @@ -103,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" @@ -175,6 +176,7 @@ ksys_dll_t EXPORTS[] = { { "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/abort.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c new file mode 100644 index 000000000..884da55d4 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c @@ -0,0 +1,12 @@ +#include +#include +#include + +void abort() +{ + ksys_thread_t t; + _ksys_thread_info(&t, -1); + fprintf(stderr, "\nAbort in %d\n", t.pid); + + _exit(128); +} -- 2.49.1 From 275401c06aeb96193f0a0c35dc3bbb916d8b5fdc Mon Sep 17 00:00:00 2001 From: Egor00f Date: Sun, 22 Feb 2026 14:07:38 +0500 Subject: [PATCH 4/5] libc.obj: add `atexit` test --- .../ktcc/trunk/libc.obj/samples/Makefile | 3 ++- .../ktcc/trunk/libc.obj/samples/atexit_test.c | 18 ++++++++++++++++++ .../ktcc/trunk/libc.obj/samples/build_all.sh | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 programs/develop/ktcc/trunk/libc.obj/samples/atexit_test.c 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 -- 2.49.1 From aa619aa602b482a9e60f8a742ebf339846392833 Mon Sep 17 00:00:00 2001 From: Egor00f Date: Sat, 7 Mar 2026 21:51:58 +0500 Subject: [PATCH 5/5] libc.obj: add copyright & delete `_exit.h` & fix tabs in `crt0.asm` --- .../ktcc/trunk/libc.obj/source/crt/crt0.asm | 2 +- .../ktcc/trunk/libc.obj/source/stdlib/_exit.c | 5 +- .../ktcc/trunk/libc.obj/source/stdlib/_exit.h | 69 ------------------- .../ktcc/trunk/libc.obj/source/stdlib/abort.c | 5 ++ .../trunk/libc.obj/source/stdlib/atexit.c | 5 ++ .../ktcc/trunk/libc.obj/source/stdlib/exit.c | 9 ++- 6 files changed, 20 insertions(+), 75 deletions(-) delete mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.h 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 460938b27..ecfa9f00c 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/crt/crt0.asm +++ b/programs/develop/ktcc/trunk/libc.obj/source/crt/crt0.asm @@ -55,7 +55,7 @@ start: mov dl, cl ; parameter starts cmp al, '"' jz @f ; quotes loaded - mov dh, ch ; parameter without quotes + mov dh, ch ; parameter without quotes dec esi call push_param inc esi 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 3709bd43e..5382cc62f 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.c @@ -1,7 +1,6 @@ #include #include #include -#include "_exit.h" void _exit(int status) { @@ -14,9 +13,7 @@ void __libc_exit(int status, void (*before_exit)(int status)) if (status && status != 128) { fprintf(stderr, "\nexit code: %d\n", status); } - - WRITE_EXIT_CODE(status); - + if (before_exit) { before_exit(status); } diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.h b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.h deleted file mode 100644 index 0e0865a15..000000000 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_exit.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef __STDLIB_EXIT_H__ -#define __STDLIB_EXIT_H__ - -#include -#include -#include - -#define __PATH_TO_STATUS_FILE "/tmp0/1/.libc" -#define __STATUS_FILE_EXTENSION ".status" -#define __STATUS_FILE_FORMAT "%d" -#define __FULL_STATUS_FILE_NAME __PATH_TO_STATUS_FILE "/%d" __STATUS_FILE_EXTENSION -#define __FULL_STATUS_FILE_NAME_SIZE (sizeof(__PATH_TO_STATUS_FILE) + 32 + sizeof(__STATUS_FILE_EXTENSION)) - -void __libc_exit(int status, void (*before_exit)(int status)); - -// Save exit code -inline void WRITE_EXIT_CODE(int status) -{ - mkdir(__PATH_TO_STATUS_FILE); - - char buff[__FULL_STATUS_FILE_NAME_SIZE]; - ksys_thread_t t; - - _ksys_thread_info(&t, -1); - snprintf(buff, sizeof(buff), __FULL_STATUS_FILE_NAME, t.pid); - - FILE* f = fopen(buff, "w"); - - if (f) { - snprintf(buff, sizeof(buff), __STATUS_FILE_FORMAT, status); - fputs(buff, f); - fflush(f); - fclose(f); - } else { - _ksys_debug_puts("error while write status\n"); - } -} - -// Read exit code -inline int READ_EXIT_CODE(int pid, ksys_thread_t* t) -{ - char buff[__FULL_STATUS_FILE_NAME_SIZE]; - int status = 0; - bool free_t = false; - - if (!t) { - t = malloc(sizeof(ksys_thread_t)); - _ksys_thread_info(t, -1); - free_t = true; - } - snprintf(buff, sizeof(buff), __FULL_STATUS_FILE_NAME, t->pid); - - FILE* f = fopen(buff, "r"); - if (f) { - fscanf(f, __STATUS_FILE_FORMAT, &status); - fclose(f); - } else if (t && t->slot_state == 4) // it was stopped before it created status file - { - status = -1; - } - - if (free_t) { - free(t); - } - - return status; -} - -#endif // __STDLIB_EXIT_H__ diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c index 884da55d4..a494f357f 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/abort.c @@ -1,3 +1,8 @@ +/* +* SPDX-License-Identifier: GPL-2.0-only +* Copyright (C) 2026 KolibriOS team +*/ + #include #include #include diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c index f06d1578e..89c2a6682 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/atexit.c @@ -1,3 +1,8 @@ +/* +* SPDX-License-Identifier: GPL-2.0-only +* Copyright (C) 2026 KolibriOS team +*/ + #include struct atexit_n { 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 3f6afd26e..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,9 +1,15 @@ -/* 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 "_exit.h" +/* +TODO static void __close_all() { } @@ -11,6 +17,7 @@ static void __close_all() static void __free_all_mem() { } +*/ void __normal_exit(int status) { -- 2.49.1