Added C11 mutexes

This commit is contained in:
NeGate 2022-06-14 18:46:14 -04:00
parent effd0acb63
commit 7936d0c633
7 changed files with 509 additions and 4 deletions

View File

@ -14,6 +14,14 @@ extern int main(int argc, char** argv);
DECLSPEC_IMPORT LPWSTR GetCommandLineW(); DECLSPEC_IMPORT LPWSTR GetCommandLineW();
DECLSPEC_IMPORT LPWSTR* CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs); DECLSPEC_IMPORT LPWSTR* CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs);
int _wcsicmp(wchar_t const* s1, wchar_t const* s2) {
int diff;
do {
diff = *s1 - *s2;
} while(diff != 0 && *s1 != 0 && *s2 != 0);
return diff;
}
static size_t count_wide_chars(const wchar_t* str) { static size_t count_wide_chars(const wchar_t* str) {
size_t len = 0; size_t len = 0;
while (str[len] != 0) len++; while (str[len] != 0) len++;

138
code/os/win/win_mutex.c Normal file
View File

@ -0,0 +1,138 @@
// NOTE: debug mutexes will follow the recursive logic but error if they
// actually recurse, this is slower than doing plain logic but it helps
// debug weird mutex errors.
//
// Based on these posts:
// https://preshing.com/20120305/implementing-a-recursive-mutex/
// https://preshing.com/20120226/roll-your-own-lightweight-mutex/
#include "win.h"
#include "threads.h"
void mtx_destroy(mtx_t *mtx) {
CloseHandle(mtx->semaphore);
}
int mtx_init(mtx_t *mtx, int type) {
*mtx = (mtx_t){
.type = type,
.semaphore = CreateSemaphore(NULL, 0, 1, NULL)
};
if (type == mtx_timed) {
// TODO(NeGate): implement timed mutexes
return thrd_error;
}
return thrd_success;
}
int mtx_lock(mtx_t *mtx) {
bool try_recursive = (mtx->type == mtx_recursive);
#ifdef _DEBUG
try_recursive = true;
#endif
if (try_recursive) {
DWORD tid = GetCurrentThreadId();
if (atomic_fetch_add_explicit(&mtx->counter, 1, memory_order_acquire) > 1) {
if (tid != mtx->owner) {
WaitForSingleObject(mtx->semaphore, INFINITE);
} else {
// we recursive and already locked
#ifdef _DEBUG
if (mtx->type != mtx_recursive) {
return thrd_error;
}
#endif
}
}
mtx->owner = tid;
mtx->recursion++;
} else {
if (atomic_fetch_add_explicit(&mtx->counter, 1, memory_order_acquire) > 1) {
WaitForSingleObject(mtx->semaphore, INFINITE);
}
}
return thrd_success;
}
int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts) {
return thrd_error;
}
int mtx_trylock(mtx_t *mtx) {
bool try_recursive = (mtx->type == mtx_recursive);
#ifdef _DEBUG
try_recursive = true;
#endif
if (try_recursive) {
DWORD tid = GetCurrentThreadId();
// Do we own this mutex on this thread already?
if (mtx->owner == tid) {
#ifdef _DEBUG
if (mtx->type != mtx_recursive) {
return thrd_error;
}
#endif
atomic_fetch_add(&mtx->counter, 1);
} else {
int expected = 1;
if (!atomic_compare_exchange_strong(&mtx->counter, &expected, 0)) {
return thrd_busy;
}
mtx->owner = tid;
}
mtx->recursion++;
return thrd_success;
} else {
int expected = 1;
if (!atomic_compare_exchange_strong(&mtx->counter, &expected, 0)) {
return thrd_busy;
}
return thrd_success;
}
}
int mtx_unlock(mtx_t *mtx) {
bool try_recursive = (mtx->type == mtx_recursive);
#if _DEBUG
try_recursive = true;
#endif
if (try_recursive) {
DWORD tid = GetCurrentThreadId();
if (tid != mtx->owner) return thrd_error;
unsigned long recur = --mtx->recursion;
if (recur == 0) {
mtx->owner = 0;
}
if (atomic_fetch_sub_explicit(&mtx->counter, 1, memory_order_release) > 0) {
if (recur == 0) ReleaseSemaphore(mtx->semaphore, 1, NULL);
else {
#ifdef _DEBUG
if (mtx->type != mtx_recursive) {
return thrd_error;
}
#endif
}
}
} else {
// release?
if (atomic_fetch_sub_explicit(&mtx->counter, 1, memory_order_release) > 0) {
ReleaseSemaphore(mtx->semaphore, 1, NULL);
}
}
return thrd_success;
}

View File

@ -1,8 +1,12 @@
#pragma once #pragma once
#include <stddef.h>
#if defined(_WIN32) #if defined(_WIN32)
#define _os_win #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 #endif
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)

View File

@ -1,7 +1,8 @@
#pragma once #pragma once
#include <time.h> #include <time.h>
#include <stdbool.h>
#include <stdatomic.h>
#define thread_local _Thread_local #define thread_local _Thread_local
#define ONCE_FLAG_INIT 1 #define ONCE_FLAG_INIT 1
@ -13,7 +14,11 @@ typedef struct cnd_t {
} cnd_t; } cnd_t;
typedef struct thrd_t { typedef struct thrd_t {
int idk_yet; #if defined(_WIN32)
HANDLE handle;
#else
#error "C11 thread has not been implemented on this platform"
#endif
} thrd_t; } thrd_t;
typedef struct tss_t { typedef struct tss_t {
@ -21,7 +26,16 @@ typedef struct tss_t {
} tss_t; } tss_t;
typedef struct mtx_t { typedef struct mtx_t {
int idk_yet; #if defined(_WIN32)
int type;
// Done to handle recursive mutexes
unsigned long recursion;
unsigned long owner;
atomic_int counter;
void* semaphore;
#else
#error "C11 mutex has not been implemented on this platform"
#endif
} mtx_t; } mtx_t;
typedef void(*tss_dtor_t)(void*); typedef void(*tss_dtor_t)(void*);
@ -45,18 +59,21 @@ enum {
}; };
void call_once(once_flag *flag, void (*func)(void)); void call_once(once_flag *flag, void (*func)(void));
int cnd_broadcast(cnd_t *cond); int cnd_broadcast(cnd_t *cond);
void cnd_destroy(cnd_t *cond); void cnd_destroy(cnd_t *cond);
int cnd_init(cnd_t *cond); int cnd_init(cnd_t *cond);
int cnd_signal(cnd_t *cond); int cnd_signal(cnd_t *cond);
int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts); int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts);
int cnd_wait(cnd_t *cond, mtx_t *mtx); int cnd_wait(cnd_t *cond, mtx_t *mtx);
void mtx_destroy(mtx_t *mtx); void mtx_destroy(mtx_t *mtx);
int mtx_init(mtx_t *mtx, int type); int mtx_init(mtx_t *mtx, int type);
int mtx_lock(mtx_t *mtx); int mtx_lock(mtx_t *mtx);
int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts); int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts);
int mtx_trylock(mtx_t *mtx); int mtx_trylock(mtx_t *mtx);
int mtx_unlock(mtx_t *mtx); int mtx_unlock(mtx_t *mtx);
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg); int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
thrd_t thrd_current(void); thrd_t thrd_current(void);
int thrd_detach(thrd_t thr); int thrd_detach(thrd_t thr);
@ -65,6 +82,7 @@ _Noreturn void thrd_exit(int res);
int thrd_join(thrd_t thr, int *res); int thrd_join(thrd_t thr, int *res);
int thrd_sleep(const struct timespec *duration, struct timespec *remaining); int thrd_sleep(const struct timespec *duration, struct timespec *remaining);
void thrd_yield(void); void thrd_yield(void);
int tss_create(tss_t *key, tss_dtor_t dtor); int tss_create(tss_t *key, tss_dtor_t dtor);
void tss_delete(tss_t key); void tss_delete(tss_t key);
void *tss_get(tss_t key); void *tss_get(tss_t key);

27
lakefile.lua Normal file
View File

@ -0,0 +1,27 @@
local lake = require 'lakebuild'
local function buildcmd(target)
local deps = ""
if target.userdata.add_deps then
deps = table.concat(target.deps, " ")
end
local buildline = table.concat({"clang", target.userdata.flags, target.files[1], "-o", target.name, deps}, " ")
print(buildline)
os.execute(buildline)
end
-- build all loose C files other than main.c into object files
local files = lake.glob_combined(".", false, nil, function(_, n) return lake.endswith(n, ".c") and not lake.endswith(n, "main.c") end)
local objects = {}
for _,file in ipairs(files) do
local name = file[1] .. '.o'
lake:add_target(name, {file[2]}, buildcmd, {flags="-c", add_deps=false})
table.insert(objects, name)
end
-- build main.c
lake:add_chain("main.exe", {"main.c"}, objects, buildcmd, {flags="-O2", add_deps=true})
lake:request_build("main.exe")

310
test/test.i Normal file
View File

@ -0,0 +1,310 @@
#line 3 "w:/workspace/cuik/crt/include/xmmintrin.h"
/* line 3 */ typedef _Vector ( float , 4 ) __m128 ;
/* line 4 */ typedef _Vector ( unsigned char , 16 ) __m128i ;
/* line 7 */ float __builtin_ia32_sqrtss ( __m128 a ) ;
/* line 8 */ __m128 __builtin_ia32_sqrtps ( __m128 a ) ;
/* line 9 */ float __builtin_ia32_rsqrtss ( __m128 a ) ;
/* line 10 */ __m128 __builtin_ia32_rsqrtps ( __m128 a ) ;
/* line 11 */ __m128 __builtin_ia32_rcpss ( __m128 a , __m128 b ) ;
/* line 12 */ __m128 __builtin_ia32_rcpps ( __m128 a , __m128 b ) ;
/* line 13 */ __m128 __builtin_ia32_minss ( __m128 a , __m128 b ) ;
/* line 14 */ __m128 __builtin_ia32_minps ( __m128 a , __m128 b ) ;
/* line 15 */ __m128 __builtin_ia32_maxss ( __m128 a , __m128 b ) ;
/* line 16 */ __m128 __builtin_ia32_maxps ( __m128 a , __m128 b ) ;
/* line 18 */ static inline __m128 _mm_add_ss ( __m128 a , __m128 b ) {
/* line 19 */ a [ 0 ] += b [ 0 ] ;
/* line 20 */ return a ;
/* line 21 */ }
/* line 23 */ static inline __m128 _mm_sub_ss ( __m128 a , __m128 b ) {
/* line 24 */ a [ 0 ] -= b [ 0 ] ;
/* line 25 */ return a ;
/* line 26 */ }
/* line 28 */ static inline __m128 _mm_mul_ss ( __m128 a , __m128 b ) {
/* line 29 */ a [ 0 ] *= b [ 0 ] ;
/* line 30 */ return a ;
/* line 31 */ }
/* line 33 */ static inline __m128 _mm_div_ss ( __m128 a , __m128 b ) {
/* line 34 */ a [ 0 ] /= b [ 0 ] ;
/* line 35 */ return a ;
/* line 36 */ }
/* line 38 */ static inline __m128 _mm_add_ps ( __m128 a , __m128 b ) { return a + b ; }
/* line 39 */ static inline __m128 _mm_sub_ps ( __m128 a , __m128 b ) { return a - b ; }
/* line 40 */ static inline __m128 _mm_mul_ps ( __m128 a , __m128 b ) { return a * b ; }
/* line 41 */ static inline __m128 _mm_div_ps ( __m128 a , __m128 b ) { return a / b ; }
/* line 42 */ static inline __m128 _mm_and_ps ( __m128 a , __m128 b ) { return a & b ; }
/* line 43 */ static inline __m128 _mm_or_ps ( __m128 a , __m128 b ) { return a | b ; }
/* line 44 */ static inline __m128 _mm_xor_ps ( __m128 a , __m128 b ) { return a ^ b ; }
/* line 45 */ static inline __m128 _mm_andnot_ps ( __m128 a , __m128 b ) { return ~ ( a & b ) ; }
/* line 47 */ static inline __m128 _mm_sqrt_ss ( __m128 a ) { return ( __m128 ) __builtin_ia32_sqrtss ( a ) ; }
/* line 48 */ static inline __m128 _mm_sqrt_ps ( __m128 a ) { return __builtin_ia32_sqrtps ( a ) ; }
/* line 50 */ static inline __m128 _mm_rsqrt_ss ( __m128 a ) { return ( __m128 ) __builtin_ia32_rsqrtss ( a ) ; }
/* line 51 */ static inline __m128 _mm_rsqrt_ps ( __m128 a ) { return __builtin_ia32_rsqrtps ( a ) ; }
/* line 53 */ static inline __m128 _mm_rcp_ss ( __m128 a ) { return ( __m128 ) __builtin_ia32_rcpss ( a ) ; }
/* line 54 */ static inline __m128 _mm_rcp_ps ( __m128 a ) { return __builtin_ia32_rcpps ( a ) ; }
/* line 56 */ static inline __m128 _mm_min_ss ( __m128 a , __m128 b ) { return __builtin_ia32_minss ( a , b ) ; }
/* line 57 */ static inline __m128 _mm_min_ps ( __m128 a , __m128 b ) { return __builtin_ia32_minps ( a , b ) ; }
/* line 58 */ static inline __m128 _mm_max_ss ( __m128 a , __m128 b ) { return __builtin_ia32_maxss ( a , b ) ; }
/* line 59 */ static inline __m128 _mm_max_ps ( __m128 a , __m128 b ) { return __builtin_ia32_maxps ( a , b ) ; }
/* line 61 */ static inline __m128 _mm_setr_ps ( float z , float y , float x , float w ) { return ( __m128 ) { z , y , x , w } ; }
/* line 62 */ static inline __m128 _mm_setzero_ps ( void ) { return ( __m128 ) { 0 } ; }
/* line 65 */ static inline __m128i _mm_loadu_si128 ( const __m128i * src ) { return * src ; }
/* line 66 */ static inline __m128i _mm_load_si128 ( const __m128i * src ) { return * src ; }
/* line 67 */ static inline void _mm_store_si128 ( __m128i * dst , __m128i src ) { * dst = src ; }
#line 3 "w:/workspace/cuik/crt/include/intrin.h"
/* line 3 */ extern void __debugbreak ( void ) ;
#line 5 "w:/workspace/ciabatta/inc/assert.h"
/* line 5 */ extern void _assert_error (
/* line 6 */ char * cond ,
/* line 7 */ char const * func ,
/* line 8 */ char const * file ,
/* line 9 */ char const * line
/* line 10 */ ) ;
#line 3 "w:/workspace/ciabatta/inc/ctype.h"
/* line 3 */ int isalnum ( int c ) ;
/* line 4 */ int isalpha ( int c ) ;
/* line 5 */ int isblank ( int c ) ;
/* line 6 */ int iscntrl ( int c ) ;
/* line 7 */ int isdigit ( int c ) ;
/* line 8 */ int isgraph ( int c ) ;
/* line 9 */ int islower ( int c ) ;
/* line 10 */ int isprint ( int c ) ;
/* line 11 */ int ispunct ( int c ) ;
/* line 12 */ int isspace ( int c ) ;
/* line 13 */ int isupper ( int c ) ;
/* line 14 */ int isxdigit ( int c ) ;
/* line 15 */ int tolower ( int c ) ;
/* line 16 */ int toupper ( int c ) ;
#line 3 "w:/workspace/cuik/crt/include/stdint.h"
/* line 3 */ typedef signed char int8_t ;
/* line 4 */ typedef short int16_t ;
/* line 5 */ typedef int int32_t ;
/* line 6 */ typedef long long int64_t ;
/* line 7 */ typedef unsigned char uint8_t ;
/* line 8 */ typedef unsigned short uint16_t ;
/* line 9 */ typedef unsigned int uint32_t ;
/* line 10 */ typedef unsigned long long uint64_t ;
/* line 12 */ typedef signed char int_least8_t ;
/* line 13 */ typedef short int_least16_t ;
/* line 14 */ typedef int int_least32_t ;
/* line 15 */ typedef long long int_least64_t ;
/* line 16 */ typedef unsigned char uint_least8_t ;
/* line 17 */ typedef unsigned short uint_least16_t ;
/* line 18 */ typedef unsigned int uint_least32_t ;
/* line 19 */ typedef unsigned long long uint_least64_t ;
/* line 21 */ typedef signed char int_fast8_t ;
/* line 22 */ typedef int int_fast16_t ;
/* line 23 */ typedef int int_fast32_t ;
/* line 24 */ typedef long long int_fast64_t ;
/* line 25 */ typedef unsigned char uint_fast8_t ;
/* line 26 */ typedef unsigned int uint_fast16_t ;
/* line 27 */ typedef unsigned int uint_fast32_t ;
/* line 28 */ typedef unsigned long long uint_fast64_t ;
/* line 30 */ typedef long long intmax_t ;
/* line 31 */ typedef unsigned long long uintmax_t ;
#line 3 "w:/workspace/cuik/crt/include/stdarg.h"
/* line 3 */ typedef char * va_list ;
#line 6 "w:/workspace/ciabatta/inc/stdio.h"
/* line 6 */ typedef struct FILE FILE ;
/* line 7 */ typedef int64_t fpos_t ;
/* line 9 */ typedef struct div_t div_t ;
/* line 10 */ typedef struct ldiv_t ldiv_t ;
/* line 11 */ typedef struct lldiv_t lldiv_t ;
/* line 19 */ typedef int errno_t ;
/* line 20 */ typedef size_t rsize_t ;
/* line 57 */ extern FILE * stdout , * stderr , * stdin ;
/* line 59 */ int remove ( const char * filename ) ;
/* line 60 */ int rename ( const char * oldname , const char * newname ) ;
/* line 61 */ FILE * tmpfile ( void ) ;
/* line 62 */ char * tmpnam ( char * s ) ;
/* line 63 */ int fclose ( FILE * stream ) ;
/* line 64 */ int fflush ( FILE * stream ) ;
/* line 65 */ FILE * fopen ( const char * restrict filename , const char * restrict mode ) ;
/* line 66 */ FILE * freopen ( const char * restrict filename , const char * restrict mode , FILE * restrict stream ) ;
/* line 67 */ void setbuf ( FILE * restrict stream , char * restrict buf ) ;
/* line 68 */ int setvbuf ( FILE * restrict stream , char * restrict buf , int mode , size_t size ) ;
/* line 69 */ int fprintf ( FILE * restrict stream , const char * restrict format , ... ) ;
/* line 70 */ int fscanf ( FILE * restrict stream , const char * restrict format , ... ) ;
/* line 71 */ int printf ( const char * restrict format , ... ) ;
/* line 72 */ int scanf ( const char * restrict format , ... ) ;
/* line 73 */ int snprintf ( char * restrict s , size_t n , const char * restrict format , ... ) ;
/* line 74 */ int sprintf ( char * restrict s , const char * restrict format , ... ) ;
/* line 75 */ int sscanf ( const char * restrict s , const char * restrict format , ... ) ;
/* line 76 */ int vfprintf ( FILE * restrict stream , const char * restrict format , va_list arg ) ;
/* line 77 */ int vfscanf ( FILE * restrict stream , const char * restrict format , va_list arg ) ;
/* line 78 */ int vprintf ( const char * restrict format , va_list arg ) ;
/* line 79 */ int vscanf ( const char * restrict format , va_list arg ) ;
/* line 80 */ int vsnprintf ( char * restrict s , size_t n , const char * restrict format , va_list arg ) ;
/* line 81 */ int vsprintf ( char * restrict s , const char * restrict format , va_list arg ) ;
/* line 82 */ int vsscanf ( const char * restrict s , const char * restrict format , va_list arg ) ;
/* line 83 */ int fgetc ( FILE * stream ) ;
/* line 84 */ char * fgets ( char * restrict s , int n , FILE * restrict stream ) ;
/* line 85 */ int fputc ( int c , FILE * stream ) ;
/* line 86 */ int fputs ( const char * restrict s , FILE * restrict stream ) ;
/* line 87 */ int getc ( FILE * stream ) ;
/* line 88 */ int getchar ( void ) ;
/* line 89 */ int putc ( int c , FILE * stream ) ;
/* line 90 */ int putchar ( int c ) ;
/* line 91 */ int puts ( const char * s ) ;
/* line 92 */ int ungetc ( int c , FILE * stream ) ;
/* line 93 */ size_t fread ( void * restrict ptr , size_t size , size_t nmemb , FILE * restrict stream ) ;
/* line 94 */ size_t fwrite ( const void * restrict ptr , size_t size , size_t nmemb , FILE * restrict stream ) ;
/* line 95 */ int fgetpos ( FILE * restrict stream , fpos_t * restrict pos ) ;
/* line 96 */ int fseek ( FILE * stream , long int offset , int whence ) ;
/* line 97 */ int fsetpos ( FILE * stream , const fpos_t * pos ) ;
/* line 98 */ long int ftell ( FILE * stream ) ;
/* line 99 */ void rewind ( FILE * stream ) ;
/* line 100 */ void clearerr ( FILE * stream ) ;
/* line 101 */ int feof ( FILE * stream ) ;
/* line 102 */ int ferror ( FILE * stream ) ;
/* line 103 */ void perror ( const char * s ) ;
#line 13 "w:/workspace/cuik/crt/include/stddef.h"
/* line 13 */ typedef long long ptrdiff_t ;
/* line 14 */ typedef unsigned long long size_t ;
/* line 15 */ typedef long double max_align_t ;
/* line 18 */ typedef short wchar_t ;
#line 18 "w:/workspace/ciabatta/inc/stdlib.h" typedef struct div_t {
/* line 19 */ int quot ;
/* line 20 */ int rem ;
/* line 21 */ } div_t ;
/* line 23 */ typedef struct ldiv_t {
/* line 24 */ long quot ;
/* line 25 */ long rem ;
/* line 26 */ } ldiv_t ;
/* line 28 */ typedef struct lldiv_t {
/* line 29 */ long long quot ;
/* line 30 */ long long rem ;
/* line 31 */ } lldiv_t ;
/* line 44 */ double atof ( const char * nptr ) ;
/* line 45 */ int atoi ( const char * nptr ) ;
/* line 46 */ long int atol ( const char * nptr ) ;
/* line 47 */ long long int atoll ( const char * nptr ) ;
/* line 48 */ double strtod ( const char * restrict nptr , char * * restrict endptr ) ;
/* line 49 */ float strtof ( const char * restrict nptr , char * * restrict endptr ) ;
/* line 50 */ long double strtold ( const char * restrict nptr , char * * restrict endptr ) ;
/* line 51 */ long int strtol ( const char * restrict nptr , char * * restrict endptr , int base ) ;
/* line 52 */ long long int strtoll ( const char * restrict nptr , char * * restrict endptr , int base ) ;
/* line 53 */ unsigned long int strtoul ( const char * restrict nptr , char * * restrict endptr , int base ) ;
/* line 54 */ unsigned long long int strtoull ( const char * restrict nptr , char * * restrict endptr , int base ) ;
/* line 55 */ int rand ( void ) ;
/* line 56 */ void srand ( unsigned int seed ) ;
/* line 58 */ typedef struct _os_heap _os_heap ;
/* line 59 */ void _heap_setup ( _os_heap * heap ) ;
/* line 60 */ void * aligned_alloc ( size_t alignment , size_t size ) ;
/* line 61 */ void * calloc ( size_t nmemb , size_t size ) ;
/* line 62 */ void free ( void * ptr ) ;
/* line 63 */ void * malloc ( size_t size ) ;
/* line 64 */ void * realloc ( void * ptr , size_t size ) ;
/* line 66 */ _Noreturn void abort ( void ) ;
/* line 67 */ int atexit ( void ( * func ) ( void ) ) ;
/* line 69 */ _Noreturn void exit ( int status ) ;
/* line 70 */ _Noreturn void _Exit ( int status ) ;
/* line 71 */ char * getenv ( const char * name ) ;
/* line 73 */ int system ( const char * string ) ;
/* line 74 */ const void * bsearch ( const void * key , const void * base , size_t nmemb , size_t size , int ( * compar ) ( const void * , const void * ) ) ;
#line 9 "w:/workspace/ciabatta/inc/errno.h"
/* line 9 */ extern int errno ;
#line 708 "w:/windows kits/10/include/10.0.22000.0/shared/sal.h"
/* line 708 */ _Pragma ( "region Input Buffer SAL 1 compatibility macros" )
/* line 1472 */ _Pragma ( "endregion Input Buffer SAL 1 compatibility macros" )
#line 15 "w:/visual studio/2019/community/vc/tools/msvc/14.29.30133/include/vadefs.h"
/* line 15 */ _Pragma ( "pack(push, _CRT_PACKING)" )
/* line 47 */ _Pragma ( "warning(push)" )
/* line 48 */ _Pragma ( "warning(disable: _VCRUNTIME_DISABLED_WARNINGS)" )
/* line 61 */ typedef unsigned
/* line 1 */ long long
/* line 61 */ uintptr_t ;
/* line 72 */ typedef char * va_list ;
/* line 155 */ void __cdecl __va_start ( va_list * , ... ) ;
/* line 207 */ _Pragma ( "warning(pop)" )
/* line 208 */ _Pragma ( "pack(pop)" )
#line 60 "w:/visual studio/2019/community/vc/tools/msvc/14.29.30133/include/vcruntime.h"
/* line 60 */ _Pragma ( "warning(push)" )
/* line 61 */ _Pragma ( "warning(disable: _VCRUNTIME_DISABLED_WARNINGS)" )
/* line 1 */ _Pragma ( "pack(push, _CRT_PACKING)" )
/* line 193 */ typedef unsigned
/* line 1 */ long long
/* line 193 */ size_t ;
/* line 194 */ typedef
/* line 1 */ long long
/* line 194 */ ptrdiff_t ;
/* line 195 */ typedef
/* line 1 */ long long
/* line 195 */ intptr_t ;
/* line 209 */ typedef _Bool __vcrt_bool ;
/* line 228 */ typedef unsigned short wchar_t ;
/* line 342 */ void __cdecl __security_init_cookie ( void ) ;
/* line 351 */ void __cdecl __security_check_cookie ( uintptr_t _StackCookie ) ;
/* line 352 */ __declspec ( noreturn ) void __cdecl __report_gsfailure ( uintptr_t _StackCookie ) ;
/* line 356 */ extern uintptr_t __security_cookie ;
/* line 1 */ _Pragma ( "pack(pop)" )
/* line 366 */ _Pragma ( "warning(pop)" )
#line 13 "w:/visual studio/2019/community/vc/tools/msvc/14.29.30133/include/limits.h"
/* line 13 */ _Pragma ( "warning(push)" )
/* line 14 */ _Pragma ( "warning(disable: _VCRUNTIME_DISABLED_WARNINGS)" )
/* line 1 */ _Pragma ( "pack(push, _CRT_PACKING)" ) _Pragma ( "pack(pop)" )
/* line 78 */ _Pragma ( "warning(pop)" )
#line 27 "w:/workspace/ciabatta/inc/string.h"
/* line 27 */ void * memcpy ( void * restrict s1 , const void * restrict s2 , size_t n ) ;
/* line 28 */ void * memmove ( void * s1 , const void * s2 , size_t n ) ;
/* line 29 */ char * strcpy ( char * restrict s1 , const char * restrict s2 ) ;
/* line 30 */ char * strncpy ( char * restrict s1 , const char * restrict s2 , size_t n ) ;
/* line 31 */ char * strcat ( char * restrict s1 , const char * restrict s2 ) ;
/* line 32 */ char * strncat ( char * restrict s1 , const char * restrict s2 , size_t n ) ;
/* line 33 */ int memcmp ( const void * s1 , const void * s2 , size_t n ) ;
/* line 34 */ int strcmp ( const char * s1 , const char * s2 ) ;
/* line 35 */ int strcoll ( const char * s1 , const char * s2 ) ;
/* line 36 */ int strncmp ( const char * s1 , const char * s2 , size_t n ) ;
/* line 37 */ size_t strxfrm ( char * restrict s1 , const char * restrict s2 , size_t n ) ;
/* line 38 */ void * memchr ( const void * s , int c , size_t n ) ;
/* line 39 */ char * strchr ( const char * s , int c ) ;
/* line 40 */ size_t strcspn ( const char * s1 , const char * s2 ) ;
/* line 41 */ char * strpbrk ( const char * s1 , const char * s2 ) ;
/* line 42 */ char * strrchr ( const char * s , int c ) ;
/* line 43 */ size_t strspn ( const char * s1 , const char * s2 ) ;
/* line 44 */ char * strstr ( const char * s1 , const char * s2 ) ;
/* line 45 */ char * strtok ( char * restrict s1 , const char * restrict s2 ) ;
/* line 46 */ void * memset ( void * s , int c , size_t n ) ;
/* line 47 */ char * strerror ( int errnum ) ;
/* line 48 */ size_t strlen ( const char * s ) ;
/* line 51 */ char * strtok_r ( char * restrict s1 , const char * restrict s2 , char * * restrict ctx ) ;
#line 4 "w:/workspace/ciabatta/inc/signal.h"
/* line 4 */ typedef int sig_atomic_t ;
/* line 25 */ void ( * signal ( int sig , void ( * func ) ( int ) ) ) ( int ) ;
/* line 26 */ int raise ( int sig ) ;
#line 13 "test/test.c"
/* line 13 */ int test ( ) {
/* line 14 */ static int a = 2 ;
/* line 15 */ a += 1 ;
/* line 16 */ return a ;
/* line 17 */ }
/* line 19 */ void wack ( ) {
/* line 20 */ printf ( "BYE!!!\n" ) ;
/* line 21 */ }
/* line 23 */ int main ( int argc , char * * argv ) {
/* line 24 */ atexit ( wack ) ;
/* line 26 */ char * path_env = getenv ( "PATH" ) ;
/* line 27 */ char * ctx , * path_token = strtok_r ( path_env , ";" , & ctx ) ;
/* line 28 */ while ( path_token ) {
/* line 29 */ printf ( "%s\n" , path_token ) ;
/* line 30 */ path_token = strtok_r (
/* line 1 */ ( ( void * ) 0 )
/* line 30 */ , ";" , & ctx ) ;
/* line 31 */ }
/* line 33 */ test ( ) ;
/* line 34 */ char input [ ] = "A bird came down the walk" ;
/* line 35 */ printf ( "Parsing the input string '%s'\n" , input ) ;
/* line 36 */ char * token = strtok ( input , " " ) ;
/* line 37 */ while ( token ) {
/* line 38 */ printf ( "%s\n" , token ) ;
/* line 39 */ token = strtok (
/* line 1 */ ( ( void * ) 0 )
/* line 39 */ , " " ) ;
/* line 40 */ }
/* line 42 */ printf ( "Contents of the input string now: '" ) ;
/* line 43 */ for ( size_t n = 0 ; n < sizeof input ; ++ n )
/* line 44 */ input [ n ] ? printf ( "%c" , input [ n ] ) : printf ( "\\0" ) ;
/* line 45 */ printf ( "'" ) ;
/* line 46 */ return 0 ;
/* line 47 */ }
/* line 1 */