libc.obj: update exit (#340)

## New functions:
+ implement `_exit`/`_Exit`.
+ implement `atexit`.
+ implement `abort`.
`abort` write `Aborted pid: %d` to debug board

## Changes:

### call `exit` after main.
Just calling `exit`

### `exit` write exit code
If exit code isn't 0 `exit` will write exit code to debug board.

### use `con_exit(0)`
use
```c
con_exit(0)
```
instead of
```c
con_exit(status);
```
[from console.obj readme](310999dcc4/programs/develop/libraries/console_coff/console_en.txt (L15)).
I think the console window shouldn't be so dependent on the exit code. It's must only always close or always stay on screen

### `exit` writing exit code to debug board
Since the exit code is not used anywhere right now, I think it's better to just show it on the debug board.

for auto rebuild `crt0.o` need #339

from #311

---------

Co-authored-by: Burer <burer@kolibrios.org>
Reviewed-on: #340
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: Egor00f <y.yarin@inbox.ru>
Co-committed-by: Egor00f <y.yarin@inbox.ru>
This commit was merged in pull request #340.
This commit is contained in:
2026-05-19 10:30:46 +00:00
committed by Burer
parent 310999dcc4
commit d486c6b33a
13 changed files with 161 additions and 23 deletions
+3
View File
@@ -52,7 +52,10 @@ atol
atoll
atof
calloc
atexit
exit
_exit
abort
free
itoa
labs
@@ -48,8 +48,17 @@ DLLAPI void free(void* ptr);
DLLAPI long int strtol(const char* str, char** endptr, int base);
DLLAPI int atexit(void (*func)(void));
DLLAPI void exit(int status);
DLLAPI void _exit(int status);
#ifndef _Exit
#define _Exit(status) _exit(status)
#endif
DLLAPI void abort(void);
DLLAPI void srand(unsigned s);
DLLAPI int rand(void);
@@ -27,7 +27,9 @@ BIN = \
libc_test.kex \
pipe.kex \
defgen.kex \
futex.kex
futex.kex \
atexit_test.kex \
abort_test.kex
all: $(BIN)
@@ -0,0 +1,7 @@
#include <stdlib.h>
int main()
{
abort();
return 0;
}
@@ -0,0 +1,18 @@
#include <stdlib.h>
#include <stdio.h>
void f()
{
static int c = 1;
printf("exit #%d\n", c);
c++;
}
int main()
{
atexit(&f);
atexit(&f);
atexit(&f);
return 0;
}
@@ -23,5 +23,7 @@ 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
../tcc abort_test.c -o /tmp0/1/tcc_samples/abort_test
"/sys/File managers/Eolite" /tmp0/1/tcc_samples
exit
@@ -1,8 +1,6 @@
; SPDX-License-Identifier: NOASSERTION
;
; Text encoded with Code Page 1251 - Cyrillic
;
; 2021, Edited by Coldy
;
@@ -19,6 +17,7 @@ public start
public start as '_start'
extrn main
extrn exit
include '../../../../../proc32.inc'
include '../../../../../macros.inc'
@@ -43,36 +42,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
@@ -91,9 +90,8 @@ start:
push [argc]
call main
.exit:
xor eax,eax
dec eax
int 0x40
push eax
call dword [exit]
dd -1
.crash:
jmp .exit
@@ -90,6 +90,9 @@
#include "stdlib/atoll.c"
#include "stdlib/calloc.c"
#include "stdlib/exit.c"
#include "stdlib/_exit.c"
#include "stdlib/atexit.c"
#include "stdlib/abort.c"
#include "stdlib/free.c"
#include "stdlib/itoa.c"
#include "stdlib/labs.c"
@@ -171,6 +174,9 @@ ksys_dll_t EXPORTS[] = {
{ "atof", &atof },
{ "calloc", &calloc },
{ "exit", &exit },
{ "_exit", &_exit },
{ "atexit", &atexit },
{ "abort", &abort},
{ "free", &free },
{ "itoa", &itoa },
{ "labs", &labs },
@@ -0,0 +1,11 @@
#include <conio.h>
#include <sys/ksys.h>
void _exit(int status)
{
if (__con_is_load) {
con_exit(0);
}
_ksys_exit();
}
@@ -0,0 +1,17 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
* Copyright (C) 2026 KolibriOS team
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/ksys.h>
void abort(void)
{
ksys_thread_t t;
_ksys_thread_info(&t, -1);
fprintf(stderr, "\nAborted pid: %d\n", t.pid);
_exit(128);
}
@@ -0,0 +1,40 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
* Copyright (C) 2026 KolibriOS team
*/
#include <stdlib.h>
struct atexit_n {
struct atexit_n* last;
void (*func)(void);
};
static struct atexit_n* __last_atexit_node = NULL;
int atexit(void (*func)(void))
{
struct atexit_n* n = malloc(sizeof(struct atexit_n));
if (n == NULL) {
return 1;
}
n->last = __last_atexit_node;
n->func = func;
__last_atexit_node = n;
return 0;
}
void __run_atexit()
{
struct atexit_n* n = __last_atexit_node;
while (n != NULL) {
n->func();
struct atexit_n* to_free = n;
n = n->last;
free(to_free);
}
}
@@ -0,0 +1,6 @@
#ifndef STDLIB_ATEXIT_H
#define STDLIB_ATEXIT_H
void __run_atexit();
#endif
@@ -1,12 +1,31 @@
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
#include <conio.h>
#include <sys/ksys.h>
#include <stdlib.h>
#include <stdio.h>
#include "atexit.h"
/*
TODO
static void __close_all()
{
}
static void __free_all_mem()
{
}
*/
void exit(int status)
{
if (__con_is_load) {
con_exit(status);
__run_atexit();
if(status)
{
fprintf(stderr, "Exit code: %d\n", status);
}
_ksys_exit();
//__close_all();
//__free_all_mem();
_exit(status);
}