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); }