reorganize, random fixes

This commit is contained in:
bumbread 2022-06-16 23:36:35 +11:00
parent cca63462fc
commit b414343f52
53 changed files with 185 additions and 173 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
build
bin
*.exe
*.lib
*.obj

View File

@ -19,37 +19,30 @@ set PLATFORM=win
if "%1"=="test" (
goto :skip_crt_compilation
)
:: For each C file in code/ we check whether it's OS-dependent.
:: If so, we check whether the platform is the chosen one. If not, we ignore
:: that file (set ok=0). Otherwise we compile it.
:: Man, batch files are sure scary, when you try to do something serious
:: it took me a lot of time to figure out how to write this if it breaks
:: im gonna be seriously disappointed :kekw:
del ciabatta.lib 2> nul
for /R code %%F in (*.c) do (
set ok=1
set os_dependent=0
set is_cur_os=0
echo %%F | findstr /c:"%~pd0code\os" > nul
if !errorlevel! neq 1 (
set os_dependent=1
)
echo %%F | findstr /c:"%~pd0code\os\%PLATFORM%" > nul
if !errorlevel! neq 1 (
set is_cur_os=1
)
if "!os_dependent!"=="1" if "!is_cur_os!"=="0" (
set ok=0
)
if "!ok!"=="1" (
echo %%F
clang -c -o build\%%~nF.obj %%F %CIABATTA_OPTIONS%
)
if not exist src\code\unicode\unicode_data.h (
py src\code\unicode\unicode_compile.py
)
llvm-ar rc ciabatta.lib build\*.obj
del build\*.obj
if exist bin rd/s/q bin
mkdir bin
mkdir bin\%PLATFORM%
del ciabatta.lib 2> nul
for /R src\%PLATFORM% %%F in (*.c) do (
echo %%F
clang -c -o bin\%PLATFORM%\%%~nF.obj %%F %CIABATTA_OPTIONS%
)
for /R src\code %%F in (*.c) do (
echo %%F
clang -c -o bin\%%~nF.obj %%F %CIABATTA_OPTIONS%
)
llvm-ar rc ciabatta.lib bin\*.obj bin\%PLATFORM%\*.obj
:skip_crt_compilation
echo Compiling test..
clang -fno-builtin test\test_math.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS%
if "%TEST%"=="" set TEST=assert
echo Compiling test_%TEST%.c
clang -fno-builtin test\test_%TEST%.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS%
::cl test\test_math.c /Iinc -D_CRT_SECURE_NO_WARNINGS /Z7 /link ciabatta.lib kernel32.lib user32.lib shell32.lib -nostdlib -nodefaultlibs

View File

@ -1,12 +1,18 @@
@echo off
setlocal enabledelayedexpansion
if not exist src\code\unicode\unicode_data.h (
py src\code\unicode\unicode_compile.py
)
set PLATFORM=win
set CIABATTA_OPTIONS=--crt none -I %% -I inc
del ciabatta.lib
cuik %CIABATTA_OPTIONS% code\*.c code\os\%PLATFORM%\*.c -c -o ciabatta.obj
cuik %CIABATTA_OPTIONS% src\code\*.c src\%PLATFORM%\*.c -c -o ciabatta.obj
lib /out:ciabatta.lib ciabatta.obj
cuik test\test.c --lib ciabatta.lib,kernel32.lib,user32.lib,shell32.lib %CIABATTA_OPTIONS%
if "%TEST%"=="" set TEST=assert
cuik test\test_%TEST%.c --lib ciabatta.lib,kernel32.lib,user32.lib,shell32.lib %CIABATTA_OPTIONS%
del ciabatta.obj

View File

@ -1,24 +0,0 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <_compiler.h>
#include <_os.h>
// TODO: use abort() to break
extern void _assert_error(
char *cond,
char const *func,
char const *file,
char const *line
) {
printf("Assertion failed: %s\n", cond);
if(*func != 0) {
printf("\tFunction: %s\n", func);
}
printf("\tFile: %s\n", file);
printf("\tLine: %s\n", line);
abort();
}

View File

@ -1,69 +0,0 @@
// TODO: X-macros
// TODO: data race possible (see 7.11.1.1 p. 5)
// TODO: something about restoring locales (see 7.11.1.1 p. 8)
#include <locale.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
#define _LC_FIRST 0
#define _LC_LAST 5
static struct lconv _locale;
static char _locale_str[16];
// Even if the user doesn't enable LIB_EXT1 we still have it existing
size_t strnlen_s(const char *s, size_t maxsize);
char *setlocale(int category, const char *locale) {
if (_LC_FIRST <= category && category <= _LC_LAST) return NULL;
if (locale == NULL) return _locale_str;
// Validate the string a bit
size_t locale_len = strnlen_s(locale, sizeof(_locale_str));
if (locale_len == 0 || locale_len >= sizeof(_locale_str)) return NULL;
if(strcmp(locale, "C") == 0) {
switch (category) {
case LC_ALL: {
_locale.decimal_point = ".";
_locale.thousands_sep = "";
_locale.grouping = "";
_locale.mon_decimal_point = "";
_locale.mon_thousands_sep = "";
_locale.mon_grouping = "";
_locale.positive_sign = "";
_locale.negative_sign = "";
_locale.currency_symbol = "";
_locale.frac_digits = CHAR_MAX;
_locale.p_cs_precedes = CHAR_MAX;
_locale.n_cs_precedes = CHAR_MAX;
_locale.p_sep_by_space = CHAR_MAX;
_locale.n_sep_by_space = CHAR_MAX;
_locale.p_sign_posn = CHAR_MAX;
_locale.n_sign_posn = CHAR_MAX;
_locale.int_curr_symbol = "";
_locale.int_frac_digits = CHAR_MAX;
_locale.int_p_cs_precedes = CHAR_MAX;
_locale.int_n_cs_precedes = CHAR_MAX;
_locale.int_p_sep_by_space = CHAR_MAX;
_locale.int_n_sep_by_space = CHAR_MAX;
_locale.int_p_sign_posn = CHAR_MAX;
_locale.int_n_sign_posn = CHAR_MAX;
break;
}
default: return NULL;
}
} else {
return NULL;
}
memcpy(_locale_str, locale, locale_len);
return _locale_str;
}
struct lconv *localeconv(void) {
return &_locale;
}

View File

@ -6,7 +6,7 @@
#endif
#if defined(__GNUC__) && !defined(__clang__)
#define _compiler_gnu
#define _compiler_gcc
#endif
#if defined(__clang__)
@ -18,17 +18,9 @@
#endif
#if !(defined(_compiler_msvc) \
|| defined(_compiler_gnu) \
|| defined(_compiler_gcc) \
|| defined(_compiler_cuik) \
|| defined(_compiler_clang))
#error "Unsupported Compiler"
#endif
#if defined(_compiler_msvc) || defined(_compiler_cuik)
#include <intrin.h>
#define _compiler_brk __debugbreak
#elif defined(_compiler_gcc) || defined(_compiler_clang)
#define _compiler_brk __builtin_trap
#else
#error "_compiler_brk is not implemented for this compiler"
#endif

View File

@ -1,9 +0,0 @@
#pragma once
#define _str_(x) #x
#define _str(x) _str_(x)
#define _con(a,b) a ## b
#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0]))

View File

@ -4,9 +4,6 @@
#if defined(_WIN32)
#define _os_win
// Weird hack because this function is used by a weird function windows.h defines
int _wcsicmp(wchar_t const* s1, wchar_t const* s2);
#endif
#if defined(__linux__) && !defined(__ANDROID__)

View File

@ -4,14 +4,11 @@
#define __func__ __FUNCTION__
#endif
#define _assert_str_(x) #x
#define _assert_str(x) _assert_str_(x)
extern void _assert_error(
char *cond,
void _Noreturn _assert(
char const *cond,
char const *func,
char const *file,
char const *line
int line
);
#if defined(NDEBUG)
@ -21,11 +18,7 @@ extern void _assert_error(
#define assert(condition) \
do { \
if(!(condition)) { \
_assert_error( \
#condition, \
__func__, \
__FILE__, \
_assert_str(__LINE__)); \
_assert(#condition, __func__, __FILE__, __LINE__); \
} \
} while(0)
#endif

View File

@ -1,3 +1,4 @@
#pragma once
int isalnum(int c);

View File

@ -4,12 +4,12 @@
typedef unsigned fexcept_t;
typedef unsigned fenv_t;
// These constants correspond to bits in MXCSR register
#define FE_INVALID (1 << 0)
#define FE_DIVBYZERO (1 << 2)
#define FE_OVERFLOW (1 << 3)
#define FE_UNDERFLOW (1 << 4)
#define FE_INEXACT (1 << 5)
// Implementation-defined flags
#define FE_DENORM (1 << 1)
#define FE_DAZ (1 << 6)
@ -22,6 +22,7 @@ typedef unsigned fenv_t;
| FE_DENORM \
| FE_DAZ )
// These constants correspond to the rounding field in MXCSR register
#define FE_TONEAREST 0x00
#define FE_DOWNWARD 0x01
#define FE_UPWARD 0x02
@ -56,6 +57,6 @@ int _feenabletraps(int excepts);
int _fedisabletraps(int excepts);
#if defined(_CIABATTA_EXT)
#define feenabletraps _feenabletraps
#define _fedisabletraps _fedisabletraps
#define feenabletraps _feenabletraps
#define fedisabletraps _fedisabletraps
#endif

View File

@ -1,5 +1,9 @@
local lake = require 'lakebuild'
-- NOTE(bumbread): change this to reflect the fact that
-- now platform-independent stuff is in src/code and
-- platform-dependent stuff is in src/$PALTFORM
local function buildcmd(target)
local deps = ""
if target.userdata.add_deps then

18
src/code/assert.c Normal file
View File

@ -0,0 +1,18 @@
#include <assert.h>
#include <stdio.h> // printf
#include <stdlib.h> // abort
void _Noreturn _assert(
char const *cond,
char const *func,
char const *file,
int line
) {
printf("Assertion failed: %s\n", cond);
printf(" Function: %s\n", func);
printf(" File: %s\n", file);
printf(" Line: %d\n", line);
abort();
}

View File

@ -1,9 +1,5 @@
// TODO: table-driven?
// TODO: other locales
#include <ctype.h>
#include <locale.h>
#define in_range(low, v, high) ((low <= v) && (v <= high))

View File

@ -6,10 +6,9 @@
#define fe_flags(excepts) ((fexcept_t)(excepts))
#define fe_excepts(masks) ((int)(masks >> 7))
fenv_t _fe_dfl_env = 0x1f80; // Based (on my machine)
fenv_t _fe_dfl_env = 0x1f80;
int feclearexcept(int excepts)
{
int feclearexcept(int excepts) {
if((excepts & FE_ALL_EXCEPT) != excepts) {
return 1;
}

69
src/code/locale.c Normal file
View File

@ -0,0 +1,69 @@
// TODO: X-macros
// TODO: data race possible (see 7.11.1.1 p. 5)
// TODO: something about restoring locales (see 7.11.1.1 p. 8)
#include <locale.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
#define _LC_FIRST 0
#define _LC_LAST 5
static struct lconv _locale;
static char _locale_str[16];
// Even if the user doesn't enable LIB_EXT1 we still have it existing
size_t strnlen_s(const char *s, size_t maxsize);
char *setlocale(int category, const char *locale) {
if (_LC_FIRST <= category && category <= _LC_LAST) return NULL;
if (locale == NULL) return _locale_str;
// Validate the string a bit
size_t locale_len = strnlen_s(locale, sizeof(_locale_str));
if (locale_len == 0 || locale_len >= sizeof(_locale_str)) return NULL;
if(strcmp(locale, "C") == 0) {
switch (category) {
case LC_ALL: {
_locale.decimal_point = ".";
_locale.thousands_sep = "";
_locale.grouping = "";
_locale.mon_decimal_point = "";
_locale.mon_thousands_sep = "";
_locale.mon_grouping = "";
_locale.positive_sign = "";
_locale.negative_sign = "";
_locale.currency_symbol = "";
_locale.frac_digits = CHAR_MAX;
_locale.p_cs_precedes = CHAR_MAX;
_locale.n_cs_precedes = CHAR_MAX;
_locale.p_sep_by_space = CHAR_MAX;
_locale.n_sep_by_space = CHAR_MAX;
_locale.p_sign_posn = CHAR_MAX;
_locale.n_sign_posn = CHAR_MAX;
_locale.int_curr_symbol = "";
_locale.int_frac_digits = CHAR_MAX;
_locale.int_p_cs_precedes = CHAR_MAX;
_locale.int_n_cs_precedes = CHAR_MAX;
_locale.int_p_sep_by_space = CHAR_MAX;
_locale.int_n_sep_by_space = CHAR_MAX;
_locale.int_p_sign_posn = CHAR_MAX;
_locale.int_n_sign_posn = CHAR_MAX;
break;
}
default: return NULL;
}
} else {
return NULL;
}
memcpy(_locale_str, locale, locale_len);
return _locale_str;
}
struct lconv *localeconv(void) {
return &_locale;
}

View File

@ -6,7 +6,7 @@ abspath = os.path.abspath(sys.argv[0])
dname = os.path.dirname(abspath)
os.chdir(dname)
with open('unicode.h', 'w') as header:
with open('unicode_data.h', 'w') as header:
header.write('\n');
header.write('#pragma once\n\n');
header.write('#define Cc 0\n');

View File

@ -2,7 +2,7 @@
#include <wctype.h>
#include <string.h>
#include "unicode.h"
#include "unicode_data.h"
static inline int char_cat(wint_t wc) {
return uni_codepoints[wc].cat;
@ -86,13 +86,26 @@ int iswpunct(wint_t wc) {
case Pi:
case Po:
case Ps:
case Sk:
case Sc:
case Sm:
case So:
return 1;
}
return 0;
}
int iswspace(wint_t wc) {
return char_cat(wc) == Zs;
switch(wc) {
case ' ':
case '\t':
case '\v':
case '\r':
case '\n':
case '\f':
return 1;
}
return 0;
}
int iswupper(wint_t wc) {

View File

@ -6,7 +6,8 @@
#include <signal.h>
#include <stddef.h>
#include <_macros.h>
#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0]))
typedef struct SignalMapping {
DWORD code;

7
test/test_assert.c Normal file
View File

@ -0,0 +1,7 @@
#include <assert.h>
int main() {
assert(2+2 == 4);
assert(0 != 0); // Bad case of assert
}

24
test/test_ctype.c Normal file
View File

@ -0,0 +1,24 @@
#include <ctype.h>
#include <wctype.h>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
int main() {
float start = (float)clock()/CLOCKS_PER_SEC;
for(int i = 0; i != 1000000; ++i) {
int c = rand() % 128;
assert(ispunct(c) == iswpunct((wint_t)c));
assert(isalpha(c) == iswalpha((wint_t)c));
assert(isspace(c) == iswspace((wint_t)c));
assert(isgraph(c) == iswgraph((wint_t)c));
assert(iscntrl(c) == iswcntrl((wint_t)c));
}
float end = (float)clock()/CLOCKS_PER_SEC;
float elaps = end-start;
printf("Elapsed: %f\n", elaps);
return 0;
}