Compare commits

...

8 Commits

Author SHA1 Message Date
Sylvain PILLOT 4d7787db01 bug correction for the case ' %[^\n]' 2023-03-08 22:40:39 +01:00
Sylvain PILLOT 492b074759 Merge remote-tracking branch 'upstream/dev' into dev 2023-03-08 20:47:56 +01:00
Yann MAGNIN e82160c78c add shared lib generation support for Vhex 2023-01-08 16:07:43 +01:00
Yann MAGNIN 9ff2574e28 update vxSDK integration 2023-01-08 13:11:13 +01:00
Lephenixnoir 8d7d37cd77
dso: dynamically allocate destructor table
This saves static memory on mono targets where it's scarce.
2023-01-01 19:23:08 +01:00
Lephenixnoir d6432a9af2
alloca: provide <alloca.h> 2022-10-30 11:19:26 +01:00
Lephenixnoir 4358a16b92
dso, stdlib: __cxa_atexit(), __dso_handle, atexit() (TEST) 2022-09-07 21:03:53 +02:00
Lephenixnoir 547a52737d
stdlib: add fileno (DONE) 2022-09-07 21:02:01 +02:00
13 changed files with 201 additions and 39 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
/prefix
*.txt
!CMakeLists.txt
.vxsdk/
# GiteaPC config files
giteapc-config.make

View File

@ -15,7 +15,9 @@ if(FXLIBC_TARGET STREQUAL vhex-sh)
list(APPEND TARGET_FOLDERS vhex sh-generic)
set(FXLIBC_ARCH sh)
add_definitions(-D__SUPPORT_VHEX_KERNEL)
set(CMAKE_INSTALL_PREFIX "${FXSDK_COMPILER_INSTALL}" CACHE PATH "..." FORCE)
set(CMAKE_INSTALL_PREFIX "${VXSDK_COMPILER_INSTALL}" CACHE PATH "..." FORCE)
set(INCDIR "${VXSDK_COMPILER_INSTALL}/include")
set(LIBDIR "${VXSDK_COMPILER_INSTALL}/lib")
endif()
if(FXLIBC_TARGET STREQUAL gint)
@ -70,6 +72,8 @@ set(SOURCES
3rdparty/grisu2b_59_56/grisu2b_59_56.c
3rdparty/tinymt32/rand.c
3rdparty/tinymt32/tinymt32.c
# C++ API details
src/dso.c
# assert
src/assert/assert.c
# ctype
@ -112,6 +116,7 @@ set(SOURCES
src/stdio/fgetc.c
src/stdio/fgetpos.c
src/stdio/fgets.c
src/stdio/fileno.c
src/stdio/fileutil.c
src/stdio/fopen.c
src/stdio/fprintf.c
@ -162,6 +167,7 @@ set(SOURCES
# stdlib
src/stdlib/abort.c
src/stdlib/abs.c
src/stdlib/atexit.c
src/stdlib/atof.c
src/stdlib/atoi.c
src/stdlib/atol.c
@ -261,22 +267,43 @@ if(gint IN_LIST TARGET_FOLDERS)
src/time/target/gint/time.c)
endif()
# TODO: All targets
add_library(fxlibc ${SOURCES})
target_include_directories(fxlibc PRIVATE include/)
foreach(FOLDER IN LISTS TARGET_FOLDERS)
target_include_directories(fxlibc PRIVATE include/target/${FOLDER}/)
#---
# Handle "target-specific" fxlibc output format
#---
if(FXLIBC_TARGET STREQUAL vhex-sh)
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
add_library(fxlibcStatic STATIC ${SOURCES})
add_library(fxlibcShared SHARED ${SOURCES})
set(FXLIBC_TARGET_LIBS "fxlibcStatic;fxlibcShared")
else()
add_library(fxlibcStatic STATIC ${SOURCES})
set(FXLIBC_TARGET_LIBS "fxlibcStatic")
endif()
foreach(FXLIBC_LIB IN LISTS FXLIBC_TARGET_LIBS)
target_include_directories(${FXLIBC_LIB} PRIVATE include/)
foreach(FOLDER IN LISTS TARGET_FOLDERS)
target_include_directories(${FXLIBC_LIB} PRIVATE include/target/${FOLDER}/)
endforeach()
set_target_properties(${FXLIBC_LIB} PROPERTIES OUTPUT_NAME "c")
install(TARGETS ${FXLIBC_LIB} DESTINATION ${LIBDIR})
endforeach()
set_target_properties(fxlibc PROPERTIES
OUTPUT_NAME "c") # libc.a
# Install
install(TARGETS fxlibc DESTINATION ${LIBDIR})
#---
# Do not forget to install headers
#---
install(DIRECTORY include/ DESTINATION ${INCDIR} PATTERN "target" EXCLUDE)
foreach(FOLDER IN LISTS TARGET_FOLDERS)

8
STATUS
View File

@ -99,6 +99,7 @@ TEST: Function/symbol/macro needs to be tested
7.19.5.4 freopen -
7.19.5.5 setbuf -
7.19.5.6 setvbuf -
(EXT) fileno -
7.19.6.1 fprintf -
7.19.6.2 fscanf TODO
@ -161,7 +162,7 @@ TEST: Function/symbol/macro needs to be tested
7.20.3.3 malloc - (gint)
7.20.3.4 realloc - (gint)
7.20.4.1 abort - (stream flushing/closing/etc?)
7.20.4.2 atexit TODO
7.20.4.2 atexit TEST
7.20.4.3 exit - (stream flushing/closing/etc?)
7.20.4.4 _Exit - (gint)
7.20.4.5 getenv TODO
@ -172,6 +173,8 @@ TEST: Function/symbol/macro needs to be tested
7.20.6.2 div, ldiv, lldiv -
7.20.7 Multibyte/wide char conv TODO
7.20.8 Multibyte/wide string conv TODO
(EXT) __cxa_atexit TEST
(EXT) __cxa_finalize TEST
7.21 <string.h>
7.21.2.1 memcpy -
@ -222,6 +225,9 @@ TEST: Function/symbol/macro needs to be tested
7.25 <wctype.h> TODO (not a priority)
(EXT) <alloca.h>
(EXT) alloca -
# Supporting locales
What if we wanted to support more locales?

View File

@ -12,16 +12,13 @@ set(CMAKE_CXX_FLAGS_INIT "")
add_compile_options(-nostdlib)
add_link_options(-nostdlib)
link_libraries(-lgcc)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Determine compiler install path
execute_process(
COMMAND ${CMAKE_C_COMPILER} --print-file-name=.
OUTPUT_VARIABLE FXSDK_COMPILER_INSTALL
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT DEFINED ENV{VXSDK_COMPILER_SYSROOT})
message(FATAL_ERROR "You should use the vxSDK to build this project")
endif()
set(VXSDK_COMPILER_INSTALL $ENV{VXSDK_COMPILER_SYSROOT})

21
include/alloca.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef __ALLOCA_H__
# define __ALLOCA_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#undef alloca
/* Allocate a block of memory on the stack. */
extern void *alloca(size_t __size);
#define alloca(size) __builtin_alloca(size)
#ifdef __cplusplus
}
#endif
#endif /*__ALLOCA_H__*/

View File

@ -187,6 +187,7 @@ extern void setbuf(FILE * __restrict__ __fp, char * __restrict__ __buf);
extern int setvbuf(FILE * __restrict__ __fp, char * __restrict__ __buf,
int __mode, size_t __size);
/* Return the file descriptor associated with __fp. */
extern int fileno(FILE *__fp);
/*

View File

@ -38,6 +38,7 @@ extern void free(void *__ptr);
__attribute__((noreturn))
extern void abort(void);
/* Register a function to be called at program exit. */
extern int atexit(void (*__func)(void));
/* Exit; calls handlers, flushes and closes streams and temporary files. */

68
src/dso.c Normal file
View File

@ -0,0 +1,68 @@
#include <stdlib.h>
/* We don't support shared object loading, so provide a single handle */
__attribute__((visibility("hidden")))
void *__dso_handle = (void *)&__dso_handle;
/* Number of atexit() calls supported, must be at least 32 (7.20.4.2§3).*/
#define ATEXIT_MAX 32
struct dtor {
void (*f)(void *);
void *p;
void *d;
};
static struct dtor *_dtors;
static int _dtor_count = 0;
__attribute__((constructor))
static void alloc_dtors(void)
{
_dtors = malloc(ATEXIT_MAX * sizeof *_dtors);
}
int __cxa_atexit(void (*f)(void *), void *p, void *d)
{
if(!_dtors || _dtor_count >= ATEXIT_MAX)
return 1;
_dtors[_dtor_count++] = (struct dtor){ f, p, d };
return 0;
}
/* We walk the destructor list in reverse order. Destructors may themselves
call __cxa_atexit(), causing new destructors to be added. When that
happens, we must call the new ones first before resuming (7.20.4.3§3). We
track changes in _dtor_count to detect this situation.
This function calls destructs in the interval [low..high) that match DSO
handle d, plus any other destructors registered as a consequence.
_dtor_count may increase. */
static void call_dtors_in_interval(void *d, int low, int high)
{
int end = _dtor_count;
for(int i = high - 1; i >= low; i--) {
if(d == NULL || _dtors[i].d == d)
_dtors[i].f(_dtors[i].p);
if(_dtor_count > end) {
call_dtors_in_interval(d, end, _dtor_count);
end = _dtor_count;
}
}
}
void __cxa_finalize(void *d)
{
call_dtors_in_interval(d, 0, _dtor_count);
/* Re-compact the array to keep only destructors we didn't call. */
int j = 0;
for(int i = 0; i < _dtor_count; i++) {
if(d == NULL || _dtors[i].d == d)
continue;
_dtors[j++] = _dtors[i];
}
_dtor_count = j;
}

6
src/stdio/fileno.c Normal file
View File

@ -0,0 +1,6 @@
#include <stdio.h>
int fileno(FILE *fp)
{
return fp->fd;
}

View File

@ -41,7 +41,7 @@ void __scanf_end(struct __scanf_input *in)
enum
{
MODskip,
MODSKIP,
MODCHAR,
MODSHORT,
MODNORMAL,
@ -60,7 +60,7 @@ void __purge_space( struct __scanf_input * __restrict__ in )
void __scanf_store_i(int64_t value, int size, va_list *args)
{
if(size == MODskip) return;
if(size == MODSKIP) return;
if(size == MODCHAR)
*va_arg(*args, int8_t *) = value;
@ -80,7 +80,7 @@ void __scanf_store_i(int64_t value, int size, va_list *args)
void __scanf_store_d(long double value, int size, va_list *args)
{
if (size==MODskip) return;
if (size==MODSKIP) return;
if(size == MODLONG)
*va_arg(*args, double *) = value;
@ -95,7 +95,8 @@ void __scanf_store_d(long double value, int size, va_list *args)
// XX = not done yet (but will be done)
// OK = OK, done and tested
// -- = not applicable
// NO = not supported (and will not be done)
// NO = not supported (and will not be done) only for %lc as long char are not supported by gint
/*************************************************************************************************************/
/* Specifier * Explanation * num * hh * h *none* l * ll * j * z * t * L */
@ -125,26 +126,32 @@ void __scanf_store_d(long double value, int size, va_list *args)
/* f,F * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */
/* g,G * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */
/*************************************************************************************************************/
/* p * mathc a pointer * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */
/* p * match a pointer * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */
/*************************************************************************************************************/
// %ms and %m[set] are not implemented (with memory allocation while parsing a chain or a set of characters)
/* list of allowed char given by a set %[], this is updated at every set */
bool __asciiallowed[256] = { true };
/* unallow all the char for the current set */
void __unallow_all_set( void )
{
for(int u =0; u<=255; u++)
__asciiallowed[u]=false;
}
/* allow all the char for the current set */
void __allow_all_set( void )
{
for(int u =0; u<=255; u++)
__asciiallowed[u]=true;
}
/* allo a range of char for the current set */
/* note1 : c1 and c2 do not to be sorted */
/* note2 : not sur if C standard requires to be ordered or not */
void __define_set_range( char c1, char c2, bool value )
{
char beg = (c1 < c2 ? c1 : c2 );
@ -154,13 +161,14 @@ void __define_set_range( char c1, char c2, bool value )
__asciiallowed[u] = value;
}
/* return true if the char is in the allowed set or false otherwise */
bool __is_allowed( const unsigned char c )
{
return __asciiallowed[ c ];
}
// return 0 if Ok or -1 if syntax err in the set format
/* return 0 if Ok or -1 if syntax err in the set format */
int __scanset(char const * __restrict__ format, int *pos )
{
int __sor = 0;
@ -256,8 +264,11 @@ int __scanf(
__allow_all_set();
if( format[pos] == ' ' ) {
__purge_space(in);
}
// we will have to manage a given format
if( format[pos] == '%' ) {
else if( format[pos] == '%' ) {
in->readmaxlength = -1;
// main loop
@ -444,7 +455,7 @@ int __scanf(
long long int temp;
err = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol
if (err != 0) return validrets;
if (skip) __scanf_store_i( temp, MODskip, args );
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
@ -456,7 +467,7 @@ int __scanf(
long long int temp;
err = __strto_int( in, 0, NULL, &temp, false ); // base is 0 as for strtol
if (err != 0) return validrets;
if (skip) __scanf_store_i( temp, MODskip, args );
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
@ -468,7 +479,7 @@ int __scanf(
long long int temp;
err = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol - use_unsigned must be false (validated with glibc6.2 behaviour)
if (err != 0) return validrets;
if (skip) __scanf_store_i( temp, MODskip, args );
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
@ -480,7 +491,7 @@ int __scanf(
long long int temp;
err = __strto_int( in, 8, NULL, &temp, true ); // base is 8 as for strtol
if (err != 0) return validrets;
if (skip) __scanf_store_i( temp, MODskip, args );
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
@ -493,7 +504,7 @@ int __scanf(
long long int temp;
err = __strto_int( in, 16, NULL, &temp, true ); // base is 16 as for strtol
if (err != 0) return validrets;
if (skip) __scanf_store_i( temp, MODskip, args );
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
@ -512,7 +523,7 @@ int __scanf(
long double temp;
err = __strto_fp( in, NULL, NULL, &temp );
if (err != 0) return validrets;
if (skip) __scanf_store_d( temp, MODskip, args );
if (skip) __scanf_store_d( temp, MODSKIP, args );
else __scanf_store_d( temp, MOD, args );
validrets++;
break;
@ -648,7 +659,7 @@ int __scanf(
__scanf_in( in );
pos++;
}
return validrets; // else we return the number of valid read
else return validrets; // else we return the number of valid read
}
pos++;
}

8
src/stdlib/atexit.c Normal file
View File

@ -0,0 +1,8 @@
#include <stdlib.h>
extern int __cxa_atexit(void (*f)(void *), void *p, void *d);
int atexit(void (*f)(void))
{
return __cxa_atexit((void (*)(void *))f, NULL, NULL);
}

View File

@ -1,8 +1,11 @@
#include <stdlib.h>
extern void __cxa_finalize(void *d);
void exit(int rc)
{
/* TODO: invoke atexit callbacks */
__cxa_finalize(NULL);
/* TODO: exit: Flush all streams */
/* TODO: exit: Close all streams */
/* TODO: exit: Remove temporary files */

View File

@ -1,14 +1,26 @@
[project]
name = 'fxlibc'
version = '1.4.1'
type = 'app'
target = [
'superh'
]
[build]
configure = 'cmake -DFXLIBC_PIC=1 -DFXLIBC_TARGET=vhex-sh -B build-vhex -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-vhex.cmake'
build = 'make -C build-vhex'
install = 'make -C build-vhex install'
[superh.build]
configure = """ \
cmake \
-B build-vhex \
-DFXLIBC_PIC=1 \
-DFXLIBC_TARGET=vhex-sh \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-vhex.cmake
"""
build = 'cmake --build build-vhex'
install = 'cmake --install build-vhex'
uninstall = """ \
if [ -e build-vhex/install_manifest.txt ]; then \
xargs rm -f < build-vhex/install_manifest.txt; \
fi \
"""
[superh.dependencies]
vxOpenLibm = 'master@superh'
sh-elf-vhex = 'master@superh'