main
   1#ifndef NOTLIBC_HEADER_INCLUDED
   2#define NOTLIBC_HEADER_INCLUDED
   3
   4/******************************************************************************/
   5/*                           PLATFORM  CORE                                   */
   6/******************************************************************************/
   7
   8
   9/*===================== Name/ID macros for important things ==================*/
  10
  11/* -DBUILD_TYPE */
  12#define BUILD_DEBUG 1
  13#define BUILD_RELEASE 2
  14
  15#define ARCH_I386 1
  16#define ARCH_X86_64 2
  17
  18#define OS_NONE 0
  19#define OS_LINUX 1
  20#define OS_WINDOWS 2
  21
  22#define COMPILER_GCC 1
  23#define COMPILER_CLANG 2
  24#define COMPILER_TCC 3
  25#define COMPILER_MSVC 4
  26
  27#define HEAP_HEADER_GUARD_NUMBER  0xc0dedeaddeadc0de
  28#define HEAP_OVERRUN_GUARD_NUMBER 0xeeeedeaddeadeeee
  29#define HEAP_XOR_KEY              0x0e1e2e3e4e5e6e7e
  30
  31#define ARRAY_XOR_KEY 0x0a1a2a3a4a5a6a7a
  32
  33#define MAGIC_UNINITIALIZED_MEM 0xf0
  34#define MAGIC_POISONED_MEM 0xfc
  35#define MAGIC_FREED_MEM 0xfe
  36
  37
  38/*============================== Build info =================================*/
  39
  40#ifndef BUILD_TYPE
  41#define BUILD_TYPE 0
  42#endif
  43
  44#if BUILD_TYPE == 1
  45	#define BUILD BUILD_DEBUG
  46	#define DEBUG(...) __VA_ARGS__
  47	#define RELEASE(...) 
  48#elif BUILD_TYPE == 2
  49	#define BUILD BUILD_RELEASE
  50	#define RELEASE(...) __VA_ARGS__
  51	#define DEBUG(...) 
  52#else
  53	#error No build type was specified. There is no defaulting to debug builds.
  54#endif
  55
  56
  57/*========================== Architecture info ==============================*/
  58
  59#ifndef ARCH
  60	#if defined(__x86_64__) || defined(_M_X64)
  61		#define ARCH ARCH_X86_64
  62		#define ARCH_NAME "x86_64"
  63		#define X86_64(...) __VA_ARGS__
  64	#elif defined(__i386__) || defined(_M_IX86)
  65		#define ARCH ARCH_I386
  66		#define ARCH_NAME "i386"
  67		#define I386(...) __VA_ARGS__
  68	#endif
  69#endif
  70
  71#if !defined(ARCH) || !defined(ARCH_NAME)
  72	#error Failed to identify architecture. Please specify it via -DARCH=number (choose the most compatible option from above) and -DARCH_NAME=name to override the automatic detection.
  73#endif
  74
  75/* These are only for in-macro use, in case they are absolutely necessary. Not to be abused. They lead to messy code in debuggers */
  76#ifndef X86_64
  77#define X86_64(...)
  78#endif
  79
  80#ifndef I386
  81#define I386(...)
  82#endif
  83
  84
  85/*======================== Operating System Info =============================*/
  86
  87#ifndef OS
  88	#if defined(__linux__)
  89		#define OS OS_LINUX
  90		#define OS_NAME "linux"
  91
  92	#elif defined(_WIN32) || defined(_WIN64) 
  93		#define OS OS_WINDOWS
  94		#define OS_NAME "windows"
  95
  96	#endif
  97#endif
  98
  99#if !defined(OS) || !defined(OS_NAME)
 100	#error Failed to identify operating system. Please specify it via \
 101	-DOS=number (choose the most compatible option from above) and \
 102	-DOS_NAME=name to override the automatic detection.
 103#endif
 104
 105
 106/*====================== Compiler-specific abstractions ======================*/
 107
 108#ifndef COMPILER /* skip if -DCOMPILER=<something> was used */
 109	#if defined(__clang__) || defined(__llvm__)
 110		#define COMPILER COMPILER_CLANG
 111		#define COMPILER_NAME "clang"
 112
 113	#elif defined(__GNUC__) && !defined(__clang__) && \
 114	   !defined(__llvm__) && !defined(__INTEL_COMPILER)
 115		#define COMPILER COMPILER_GCC
 116		#define COMPILER_NAME "gcc"
 117
 118	#elif defined(__TINYC__)
 119		#define COMPILER COMPILER_TCC
 120		#define COMPILER_NAME "tcc"
 121
 122	#elif defined( _MSC_VER )
 123		#define COMPILER_MSVC
 124		#define COMPILER_NAME "msvc"
 125	#endif
 126#endif
 127
 128#if !defined(COMPILER) || !defined(COMPILER_NAME)
 129	#error Failed to identify compiler. Please specify it via \
 130	-DCOMPILER=number (choose the most compatible option from above) and \
 131	-DCOMPILER_NAME=name to override the automatic detection.
 132#endif
 133
 134#if COMPILER == COMPILER_GCC
 135	#define PRESERVE_WITH_LTO __attribute__((used))
 136#else
 137	#define PRESERVE_WITH_LTO
 138#endif
 139
 140/*                          Struct and union macros                           */
 141#define STRUCT( name, ...) \
 142typedef struct _##name { \
 143	__VA_ARGS__ \
 144} name
 145
 146
 147/* Packed struct */
 148#if COMPILER == COMPILER_GCC || COMPILER == COMPILER_CLANG \
 149   || COMPILER == COMPILER_TCC
 150	#define PACKED_STRUCT( name, ...) \
 151		typedef struct __attribute__((packed)) _##name { \
 152			__VA_ARGS__ \
 153		} name
 154#elif COMPILER == COMPILER_MSVC
 155	#define PACKED_STRUCT( name, ...) \
 156		PRAGMA(pack(push, 1)) \
 157		typedef struct _##name { \
 158			__VA_ARGS__ \
 159		} name; \
 160		PRAGMA(pack(pop))
 161#else
 162	#error PACKED_STRUCT macro undefined.
 163#endif
 164
 165#define STRUCT_FIELD_OFFSET( T, fieldname ) \
 166	((usize)&(((T*)0)->fieldname))
 167
 168
 169#define UNION( name, ...) \
 170typedef union _##name { \
 171	__VA_ARGS__ \
 172} name
 173
 174
 175/* Warnings and errors */
 176
 177#if COMPILER == COMPILER_GCC || COMPILER == COMPILER_CLANG
 178	#define PRAGMA(pragma) _Pragma(#pragma)
 179#elif COMPILER == COMPILER_MSVC
 180	#define PRAGMA(pragma) __pragma(pragma)
 181#endif
 182
 183#if COMPILER == COMPILER_GCC || COMPILER == COMPILER_CLANG
 184	#define WARNING(...) PRAGMA(GCC warning __VA_ARGS__)
 185	#define ERROR(...) PRAGMA(GCC error __VA_ARGS__)
 186#elif COMPILER == COMPILER_TCC
 187	#define WARN(...)
 188	#define ERROR(...) (*(void*)0 = 0)
 189	#ifndef NOTLIBC_SILENCE
 190	#warning Compiling with tcc. Pragmas are not supported, \
 191	so warnings will just not be printed and errors will give an \
 192	'assignment to void' error, but the line number should \
 193	still point to the right location.
 194	#endif
 195#else
 196	#define WARNING(...)
 197	#ifndef NOTLIBC_SILENCE
 198		#warning No warning directive is implemented for this compiler. \
 199		No warnings will be emitted from the code.
 200	#endif
 201	#error No error directive is implemented for this compiler, \
 202	thus errors can not be emitted.
 203#endif
 204
 205
 206#if COMPILER == COMPILER_GCC || COMPILER == COMPILER_CLANG
 207	#define UNREACHABLE __builtin_unreachable()
 208#elif COMPILER == COPMILER_MSVC
 209	#define UNREACHABLE __assume(0)
 210#else
 211	#if !defined(NOTLIBC_SILENCE)
 212		#warning UNREACHABLE is not defined for the current compiler. \
 213		Compiler may not perform all optimizations it could based on \
 214		unreachability in some special cases.
 215	#endif
 216	#define UNREACHABLE
 217#endif
 218
 219
 220/*============================= Macro Tricks =================================*/
 221
 222#define MACRO_EMPTY()
 223
 224#define MACRO_DEFER( macro ) macro MACRO_EMPTY()
 225#define MACRO_OBSTRUCT( ... ) __VA_ARGS__ MACRO_DEFER( MACRO_EMPTY )()
 226#define MACRO_EXPAND( ... ) __VA_ARGS__
 227
 228#define MACRO_STRING_JOIN( str1, str2 ) str1##str2
 229
 230#define UNIQUE_NAME( name ) \
 231	MACRO_EXPAND(MACRO_DEFER(MACRO_STRING_JOIN)(name, __LINE__))
 232
 233/* Compile-time assertion */
 234#define ASSERT( ... )                                                   \
 235	typedef char UNIQUE_NAME(compile_time_assert)[(__VA_ARGS__)? 1 : -1]
 236
 237
 238/*=========================== Core Datatypes =================================*/
 239
 240#if OS == OS_LINUX || OS == OS_WINDOWS
 241	typedef unsigned char      u8;
 242	typedef unsigned short     u16;
 243	typedef unsigned int       u32;
 244	typedef unsigned long long u64;
 245
 246	typedef signed char      s8;
 247	typedef signed short     s16;
 248	typedef signed int       s32;
 249	typedef signed long long s64;
 250
 251	typedef float  f32;
 252	typedef double f64;
 253#endif
 254
 255#if ARCH == ARCH_X86_64
 256
 257	typedef u64 usize;
 258	typedef s64 ssize;
 259
 260	typedef struct _Page {
 261		u8 data[4096];
 262	} Page;
 263
 264#elif ARCH == ARCH_I386
 265
 266	typedef u32 usize;
 267	typedef s32 ssize;
 268
 269	typedef struct _Page {
 270		u8 data[4096];
 271	} Page;
 272
 273#endif
 274
 275ASSERT( sizeof( u8 ) == 1 );
 276ASSERT( sizeof( u16 ) == 2 );
 277ASSERT( sizeof( u32 ) == 4 );
 278ASSERT( sizeof( u64 ) == 8 );
 279
 280ASSERT( sizeof( s8 ) == 1 );
 281ASSERT( sizeof( s16 ) == 2 );
 282ASSERT( sizeof( s32 ) == 4 );
 283ASSERT( sizeof( s64 ) == 8 );
 284
 285ASSERT( sizeof( f32 ) == 4 );
 286ASSERT( sizeof( f64 ) == 8 );
 287
 288
 289void *memset( void* ptr, int value, unsigned long count );
 290void *memcpy( void *dest, const void *src, unsigned long n );
 291
 292
 293
 294/*========================== Derived Datatypes ===============================*/
 295
 296
 297/*                                 Pointers                                   */
 298
 299#define GEN_POINTER_TYPE( T ) \
 300typedef T* T##p
 301
 302GEN_POINTER_TYPE( u8 );
 303GEN_POINTER_TYPE( u16 );
 304GEN_POINTER_TYPE( u32 );
 305GEN_POINTER_TYPE( u64 );
 306GEN_POINTER_TYPE( usize );
 307
 308GEN_POINTER_TYPE( void );
 309
 310GEN_POINTER_TYPE( s8 );
 311GEN_POINTER_TYPE( s16 );
 312GEN_POINTER_TYPE( s32 );
 313GEN_POINTER_TYPE( s64 );
 314GEN_POINTER_TYPE( ssize );
 315
 316GEN_POINTER_TYPE( f32 );
 317GEN_POINTER_TYPE( f64 );
 318
 319
 320/*                                  Status                                    */
 321
 322/* Errors work in a very specific way in this library.
 323 * All function that can fail take a Status * as their first argument.
 324 * If this is already a failure, they must return, usually 0.
 325 * Otherwise they execute and optionally store their own errors into 
 326 * that Status value.
 327 * NOTE: When the operation is mutating an object no mutation should be done
 328 * if an error is already present, but if the function is expected to return
 329 * a reference to the mutated object it should directly return the original.
 330 *
 331 * Moreover, any _create function (constructor) must return a fully zeroed
 332 * return value in such an error case. Also, all types MUST support just
 333 * being zeroed. If really necessary there could be an exception here,
 334 * but mainly if hardware dictates a different default value.
 335 *
 336 * All _destroy functions must check their args and if they are all zero 
 337 * (or default value) then they must just return. Otherwise they must 
 338 * free said resources, even if the error is set beforehand.
 339 * Destroy functions can also set the error if the resource could not be 
 340 * freed for some reason. (invalid non-zero reference, some other
 341 * state got messed up along the way or whatever reason).
 342 *
 343 * These simple rules allow for very nice error-directed control flow, where
 344 * the first failure leads to falling through the rest, but still allowing for
 345 * guaranteed resource cleanup.
 346 *
 347 * Normally such behaviour would be difficult to debug, this is why in debug
 348 * mode any error setting code should breakpoint() before returning 0.
 349 *
 350 * Under the Erroring function helpers below you will find some helper macros
 351 * for this creating these functions more easily.
 352 *
 353 * */
 354
 355typedef u32 Status;
 356
 357#define S_MASK (3 << 30)
 358
 359/* Requested action performed. */
 360#define S_SUCCESS (1 << 30)
 361/* Action didn't need to be performed - desired state is already present/active. */
 362#define S_COMPLETION (0 << 30)
 363/* Action failed. */
 364#define S_FAILURE (2 << 30)
 365
 366#define S_SOURCE_MASK (0x3ff << 20)
 367enum _ErrorSources {
 368
 369	ERRSRC_ARG_1 =  (0x1 << 20),
 370	ERRSRC_ARG_2 =  (0x2 << 20),
 371	ERRSRC_ARG_3 =  (0x3 << 20),
 372	ERRSRC_ARG_4 =  (0x4 << 20),
 373	ERRSRC_ARG_5 =  (0x5 << 20),
 374	ERRSRC_ARG_6 =  (0x6 << 20),
 375	ERRSRC_ARG_7 =  (0x7 << 20),
 376	ERRSRC_ARG_8 =  (0x8 << 20),
 377	ERRSRC_ARG_9 =  (0x9 << 20),
 378	ERRSRC_ARG_10 = (0xa << 20),
 379	ERRSRC_ARG_11 = (0xb << 20),
 380	ERRSRC_ARG_12 = (0xc << 20),
 381
 382	ERRSRC_PLATFORM = (0x10 << 20), /* The error resulted inside platform code. */
 383};
 384
 385#define S_REASON_MASK (0xfffff)
 386enum _ErrorReasons {
 387	/* Even numbers are for the implementations, odd are for user-defined errors */
 388	ERR_GENERIC = 0x0,
 389
 390	ERR_INVALID_ARGUMENT = 0x2,
 391
 392	ERR_OVERFLOW = 0x4,
 393
 394/* a value is out of bounds or the operation would violate certain bounds \
 395 * with the current arguments */
 396	ERR_OUT_OF_BOUND = 0x6, 
 397
 398	ERR_PERMISSION_DENIED = 0x8,
 399
 400
 401	ERR_MEM_MAP_FAILURE = 0x100,
 402	ERR_MEM_UNMAP_FAILURE = 0x102,
 403	ERR_MEM_SETPERM_FAILURE = 0x104,
 404	ERR_MEM_SETHINT_FAILURE = 0x106,
 405
 406	ERR_FILE_ALREADY_EXISTS = 0x110,
 407	ERR_FILE_DOESNT_EXIST = 0x112,
 408
 409	ERR_NO_DISK_SPACE = 0x114,
 410
 411};
 412
 413#define S_OK(...) ( ((__VA_ARGS__) & S_MASK) != (Status)S_FAILURE ) /* != FAILURE, cause otherwise the expression will appear twice, which is a great footgun when it's stateful... we are having none of that here */
 414#define S_NOK(...) ( ((__VA_ARGS__) & S_MASK) == (Status)S_FAILURE )
 415
 416#define S_SUCCESSFUL(...) ( ((__VA_ARGS__) & S_MASK) == (Status)S_SUCCESS )
 417#define S_COMPLETED(...) ( ((__VA_ARGS__) & S_MASK) == (Status)S_COMPLETION )
 418#define S_FAILED(...) ( ((__VA_ARGS__) & S_MASK) == (Status)S_FAILURE )
 419
 420#define TRY(...) do {             \
 421	Status _res = (__VA_ARGS__); \
 422	if( S_NOK(_res) ) {          \
 423		return _res;            \
 424	}                            \
 425} while(0)
 426
 427/* Erroring function helpers */
 428
 429/* If the error is already set turn into a no-op.
 430 * None of the parameters are usable in this case.
 431 * All of them could be just garbage.
 432 * */
 433#define ERRORING_PROLOGUE( status_varname, ret_type ) \
 434	if( S_NOK( *status_varname ) ) {                 \
 435		return (ret_type){0};                       \
 436	}
 437
 438/* Destructors must always destroy non-zero values and
 439 * never overwrite errors with success.
 440 * Success can be overwritten by completion.
 441 * Ignoring a zero reference is considered completion.
 442 * */
 443#define ERRORING_DESTRUCTOR_PROLOGUE( status_varname, destroyed_value ) \
 444	if( destroyed_value == 0 ) {                                                 \
 445		if( S_OK( *status_varname ) ) {                                         \
 446			*status_varname = S_COMPLETION;                                    \
 447		}                                                                       \
 448		return;                                                                 \
 449	}
 450
 451/* On failure a breakpoint must be raised in debug builds. */
 452#define ERRORING_FAIL( value ) \
 453	DEBUG(breakpoint(););                               \
 454	*s = value;                            \
 455
 456#define ENCHAIN( status_expr, ... ) \
 457	if( S_OK(status_expr) ) {      \
 458		__VA_ARGS__               \
 459	}
 460
 461#define GEN_VALUE_BY_STATUS( T ) \
 462	static inline T T##_by_status( Status *s, T v1, T v2 ) { \
 463		return (S_OK(*s))? v1 : v2;                         \
 464	}
 465
 466#define END_IF_NOK( status_value )  \
 467	if( S_NOK( status_value ) ) {  \
 468		goto end;                 \
 469	}
 470
 471GEN_VALUE_BY_STATUS( u8 )
 472GEN_VALUE_BY_STATUS( u16 )
 473GEN_VALUE_BY_STATUS( u32 )
 474GEN_VALUE_BY_STATUS( u64 )
 475GEN_VALUE_BY_STATUS( usize )
 476GEN_VALUE_BY_STATUS( voidp )
 477
 478GEN_VALUE_BY_STATUS( s8 )
 479GEN_VALUE_BY_STATUS( s16 )
 480GEN_VALUE_BY_STATUS( s32 )
 481GEN_VALUE_BY_STATUS( s64 )
 482GEN_VALUE_BY_STATUS( ssize )
 483
 484
 485/*                         Generic function types                              */
 486
 487typedef s8 (CmpFunc)(const void*, const void*);
 488GEN_POINTER_TYPE( CmpFunc );
 489
 490typedef usize (SearchFunc)( Status *s, const void *restrict el, usize el_size, const void *restrict data, usize count, CmpFunc *cmp );
 491/* Returns the index and S_SUCCESS if the element was found.
 492 * Returns the index after which a given element would belong and S_COMPLETION if the element was not found */
 493GEN_POINTER_TYPE( SearchFunc );
 494
 495typedef void (SortFunc)(Status *s, void *const data, usize count, usize el_size, CmpFunc *cmp);
 496GEN_POINTER_TYPE( SortFunc );
 497
 498typedef void (FallbackingSortFunc)(Status *s, void *const data, usize count, usize el_size, CmpFunc *cmp, usize fallback_at_count, SortFunc* fallback_algo);
 499GEN_POINTER_TYPE( FallbackingSortFunc );
 500
 501
 502/******************************************************************************/
 503/*                                 MATH STUFF                                 */
 504/******************************************************************************/
 505
 506#define  u8_MIN 0
 507#define u16_MIN 0
 508#define u32_MIN 0
 509#define u64_MIN 0
 510
 511#define  u8_MAX ((u8)-1)
 512#define u16_MAX ((u16)-1)
 513#define u32_MAX ((u32)-1)
 514#define u64_MAX ((u64)-1)
 515
 516/* We assume 2's complement */
 517ASSERT( (-1^1) == -2 );
 518
 519#define  s8_MAX ((s8)( (u8)-1 >> 1))
 520#define s16_MAX ((s16)((u16)-1 >> 1))
 521#define s32_MAX ((s32)((u32)-1 >> 1))
 522#define s64_MAX ((s64)((u64)-1 >> 1))
 523
 524#define  s8_MIN (- s8_MAX - 1)
 525#define s16_MIN (-s16_MAX - 1)
 526#define s32_MIN (-s32_MAX - 1)
 527#define s64_MIN (-s64_MAX - 1)
 528
 529
 530/* Ensure limit sanity - at least for unsigned */
 531ASSERT( u64_MAX == 0xffffffffffffffff );
 532ASSERT( u32_MAX == 0xffffffff );
 533ASSERT( u16_MAX == 0xffff );
 534ASSERT( u8_MAX == 0xff );
 535
 536/*                                   Addition                                 */
 537
 538#define GEN_ADD_DECLARATION( T ) \
 539	static inline T T##_add( Status *s, T n1, T n2 );
 540
 541GEN_ADD_DECLARATION( u8 )
 542GEN_ADD_DECLARATION( u16 )
 543GEN_ADD_DECLARATION( u32 )
 544GEN_ADD_DECLARATION( u64 )
 545
 546GEN_ADD_DECLARATION( s8 )
 547GEN_ADD_DECLARATION( s16 )
 548GEN_ADD_DECLARATION( s32 )
 549GEN_ADD_DECLARATION( s64 )
 550
 551static inline usize usize_add( Status *s, usize n1, usize n2 ) {
 552	#if ARCH == ARCH_X86_64
 553		return u64_add( s, n1, n2 );
 554	#elif ARCH == ARCH_I386
 555		return u32_add( s, n1, n2 );
 556	#endif
 557}
 558
 559static inline ssize ssize_add( Status *s, ssize n1, ssize n2 ) {
 560	#if ARCH == ARCH_X86_64
 561		return u64_add( s, n1, n2 );
 562	#elif ARCH == ARCH_I386
 563		return u32_add( s, n1, n2 );
 564	#endif
 565}
 566
 567#if COMPILER == COMPILER_GCC || COMPILER == COMPILER_CLANG
 568	#define GEN_UADD_DEFINITION( T ) \
 569		static inline T T##_add( Status *s, T n1, T n2 ) {                           \
 570			ERRORING_PROLOGUE( s, T );                                              \
 571			T out;                                                                  \
 572			if( __builtin_add_overflow( n1, n2, &out ) ) {                          \
 573				 *s = S_FAILURE | ERR_OVERFLOW;                        \
 574				 return 0;                                                         \
 575			}                                                                       \
 576			*s = S_SUCCESS;                                                         \
 577			return out;                                                             \
 578		}
 579
 580	#define GEN_SADD_DEFINITION( T ) GEN_UADD_DEFINITION( T )
 581
 582	#define GEN_USUB_DEFINITION( T ) \
 583		static inline T T##_sub( Status *s, T n1, T n2 ) {                           \
 584			ERRORING_PROLOGUE( s, T );                                              \
 585			T out;                                                                  \
 586			if( __builtin_sub_overflow( n1, n2, &out ) ) {                          \
 587				 *s = S_FAILURE | ERR_OVERFLOW;                                    \
 588				 return 0;                                                         \
 589			}                                                                       \
 590			*s = S_SUCCESS;                                                         \
 591			return out;                                                             \
 592		}
 593
 594	#define GEN_SSUB_DEFINITION( T ) GEN_USUB_DEFINITION( T )
 595
 596	#define GEN_UMUL_DEFINITION( T )                                                  \
 597		static inline T T##_mul( Status *s, T n1, T n2 ) {                           \
 598			ERRORING_PROLOGUE( s, T );                                              \
 599			T out;                                                                  \
 600			if( __builtin_mul_overflow( n1, n2, &out ) ) {                          \
 601				 *s = S_FAILURE | ERR_OVERFLOW;                        \
 602				 return 0;                                                         \
 603			}                                                                       \
 604			*s = S_SUCCESS;                                                         \
 605			return out;                                                             \
 606		}
 607
 608	#define GEN_SMUL_DEFINITION( T ) GEN_UMUL_DEFINITION( T )
 609
 610#else
 611
 612	#define GEN_UADD_DEFINITION( T )                                                  \
 613		static inline T T##_add( Status *s, T n1, T n2 ) {                           \
 614			ERRORING_PROLOGUE( s, T );                                              \
 615			if( n1 > (T##_MAX) - n2 ) {                                             \
 616				 *s = S_FAILURE | ERR_OVERFLOW;                        \
 617				 return 0;                                                         \
 618			}                                                                       \
 619			*s = S_SUCCESS;                                                         \
 620			return n1 + n2;                                                         \
 621		}
 622
 623	#define GEN_USUB_DEFINITION( T )                                                  \
 624		static inline T T##_sub( Status *s, T n1, T n2 ) {                           \
 625			ERRORING_PROLOGUE( s, T );                                              \
 626			if( n2 > n1 ) {                                                         \
 627				 *s = S_FAILURE | ERR_OVERFLOW;                        \
 628				 return 0;                                                         \
 629			}                                                                       \
 630			*s = S_SUCCESS;                                                         \
 631			return n1 - n2;                                                         \
 632		}
 633
 634	#define GEN_SADD_DEFINITION( T ) \
 635	static inline T T##_add( Status *s, T n1, T n2 ) {                                \
 636			ERRORING_PROLOGUE( s, T );                                              \
 637			if( (n1 >= 0 && n2 > T##_MAX - n1) || (n1 < 0 && n2 < T##_MIN - n1) ) { \
 638				*s = S_FAILURE | ERR_OVERFLOW;                         \
 639				return 0;                                                          \
 640			}                                                                       \
 641			return n1 + n2;                                                         \
 642		}
 643
 644	#define GEN_SSUB_DEFINITION( T )                                                  \
 645	static inline T T##_sub( Status *s, T n1, T n2 ) {                                \
 646		if( (n2 > 0 && n1 < T##_MIN + n2) || (n2 < 0 && n1 > T##_MAX + n2) ) {       \
 647			*s = S_FAILURE | ERR_OVERFLOW;                              \
 648			return 0;                                                               \
 649		}                                                                            \
 650		return n1 - n2;                                                              \
 651	}
 652
 653	#define GEN_UMUL_DEFINITION( T )                                                  \
 654		static inline T T##_mul( Status *s, T n1, T n2 ) {                           \
 655			if( n1 && n2 > (T##_MAX/n1) ) {                                         \
 656				 *s = S_FAILURE | ERR_OVERFLOW;                        \
 657				 return 0;                                                         \
 658			}                                                                       \
 659			*s = S_SUCCESS;                                                         \
 660			return n1*n2;                                                           \
 661		}
 662
 663	#define GEN_SMUL_DEFINITION( T )                                                  \
 664		static inline T T##_mul( Status *s, T n1, T n2 ) {                           \
 665			ERRORING_PROLOGUE( s, T );                                              \
 666			if(                                                                     \
 667				( n2 > 0 && n1 >= T##_MIN/n2 && n1 <= T##_MAX/n2 ) ||              \
 668				( n2 == 0 ) ||                                                     \
 669				( n2 == -1 && n1 >= -T##_MAX ) ||                                  \
 670				( n2 < -1 && n1 >= T##_MAX/n2 && n1 <= T##_MIN/n2 )                \
 671			) {                                                                     \
 672				return n1*n2;                                                      \
 673				*s = S_SUCCESS;                                                    \
 674			}                                                                       \
 675			*s = S_FAILURE | ERR_OVERFLOW;                              \
 676			return 0;                                                               \
 677		}
 678#endif
 679
 680
 681/*                                 Subtraction                                */
 682
 683#define GEN_SUB_DECLARATION( T ) \
 684	static inline T T##_sub( Status *s, T n1, T n2 );
 685
 686GEN_SUB_DECLARATION( u8 )
 687GEN_SUB_DECLARATION( u16 )
 688GEN_SUB_DECLARATION( u32 )
 689GEN_SUB_DECLARATION( u64 )
 690
 691GEN_SUB_DECLARATION( s8 )
 692GEN_SUB_DECLARATION( s16 )
 693GEN_SUB_DECLARATION( s32 )
 694GEN_SUB_DECLARATION( s64 )
 695
 696static inline usize usize_sub( Status *s, usize n1, usize n2 ) {
 697	#if ARCH == ARCH_X86_64
 698		return u64_sub( s, n1, n2 );
 699	#elif ARCH == ARCH_I386
 700		return u32_sub( s, n1, n2 );
 701	#endif
 702}
 703
 704static inline ssize ssize_sub( Status *s, ssize n1, ssize n2 ) {
 705	#if ARCH == ARCH_X86_64
 706		return u64_sub( s, n1, n2 );
 707	#elif ARCH == ARCH_I386
 708		return u32_sub( s, n1, n2 );
 709	#endif
 710}
 711
 712
 713/*                                Multiplication                              */
 714
 715#define GEN_MUL_DECLARATION( T ) \
 716	static inline T T##_mul( Status *s, T n1, T n2 );
 717
 718GEN_MUL_DECLARATION( u8 )
 719GEN_MUL_DECLARATION( u16 )
 720GEN_MUL_DECLARATION( u32 )
 721GEN_MUL_DECLARATION( u64 )
 722
 723GEN_MUL_DECLARATION( s8 )
 724GEN_MUL_DECLARATION( s16 )
 725GEN_MUL_DECLARATION( s32 )
 726GEN_MUL_DECLARATION( s64 )
 727
 728static inline usize usize_mul( Status *s, usize n1, usize n2 ) {
 729	#if ARCH == ARCH_X86_64
 730		return u64_mul( s, n1, n2 );
 731	#elif ARCH == ARCH_I386
 732		return u32_mul( s, n1, n2 );
 733	#endif
 734}
 735
 736static inline ssize ssize_mul( Status *s, ssize n1, ssize n2 ) {
 737	#if ARCH == ARCH_X86_64
 738		return u64_mul( s, n1, n2 );
 739	#elif ARCH == ARCH_I386
 740		return u32_mul( s, n1, n2 );
 741	#endif
 742}
 743
 744
 745/*                                   Maximum                                  */
 746
 747#define GEN_MAX_DEFINITION( T )              \
 748	static inline T T##_max( T n1, T n2 ) { \
 749		return (n1 >= n2)? n1 : n2;        \
 750	}
 751
 752GEN_MAX_DEFINITION( u8 )
 753GEN_MAX_DEFINITION( u16 )
 754GEN_MAX_DEFINITION( u32 )
 755GEN_MAX_DEFINITION( u64 )
 756GEN_MAX_DEFINITION( usize )
 757
 758GEN_MAX_DEFINITION( s8 )
 759GEN_MAX_DEFINITION( s16 )
 760GEN_MAX_DEFINITION( s32 )
 761GEN_MAX_DEFINITION( s64 )
 762GEN_MAX_DEFINITION( ssize )
 763
 764
 765/*                                   Minimum                                  */
 766
 767#define GEN_MIN_DEFINITION( T )              \
 768	static inline T T##_min( T n1, T n2 ) { \
 769		return (n2 >= n1)? n1 : n2;        \
 770	}
 771
 772GEN_MIN_DEFINITION( u8 )
 773GEN_MIN_DEFINITION( u16 )
 774GEN_MIN_DEFINITION( u32 )
 775GEN_MIN_DEFINITION( u64 )
 776GEN_MIN_DEFINITION( usize )
 777
 778GEN_MIN_DEFINITION( s8 )
 779GEN_MIN_DEFINITION( s16 )
 780GEN_MIN_DEFINITION( s32 )
 781GEN_MIN_DEFINITION( s64 )
 782GEN_MIN_DEFINITION( ssize )
 783
 784
 785/*                                 Round Down                                 */
 786
 787#define GEN_UROUND_DOWN_DECLARATION( T )                                               \
 788	static inline T T##_round_down( Status *s, T number, T multiple );
 789
 790#define GEN_UROUND_DOWN_DEFINITION( T )                                                \
 791	static inline T T##_round_down( Status *s, T number, T multiple ) {               \
 792		ERRORING_PROLOGUE( s, T );                                                   \
 793		if( multiple == 0 ) {                                                        \
 794			 ERRORING_FAIL( S_FAILURE | ERRSRC_ARG_2 | ERR_INVALID_ARGUMENT );      \
 795			 return (T){0};                                                         \
 796		};                                                                           \
 797		*s = S_SUCCESS;                                                              \
 798		return number - (number%multiple);                                           \
 799	}
 800
 801GEN_UROUND_DOWN_DECLARATION( u8 )
 802GEN_UROUND_DOWN_DECLARATION( u16 )
 803GEN_UROUND_DOWN_DECLARATION( u32 )
 804GEN_UROUND_DOWN_DECLARATION( u64 )
 805GEN_UROUND_DOWN_DECLARATION( usize )
 806
 807
 808/*                                   Round Up                                 */
 809
 810#define GEN_UROUND_UP_DECLARATION( T ) \
 811	static inline T T##_round_up( Status *s, T number, T multiple );
 812
 813#define GEN_UROUND_UP_DEFINITION( T )                                                  \
 814	static inline T T##_round_up( Status *s, T number, T multiple ) {                 \
 815		if( multiple == 0 ) {                                                        \
 816			ERRORING_FAIL( S_FAILURE | ERRSRC_ARG_2 | ERR_INVALID_ARGUMENT );       \
 817			return 0;                                                               \
 818		}                                                                            \
 819		T rem = number%multiple;                                                     \
 820		if( rem == 0 ) {                                                             \
 821			*s = S_SUCCESS;                                                         \
 822			return number;                                                          \
 823		} else {                                                                     \
 824			return T##_add( s, number, multiple - rem );                            \
 825		}                                                                            \
 826	}
 827
 828GEN_UROUND_UP_DECLARATION( u8 )
 829GEN_UROUND_UP_DECLARATION( u16 )
 830GEN_UROUND_UP_DECLARATION( u32 )
 831GEN_UROUND_UP_DECLARATION( u64 )
 832GEN_UROUND_UP_DECLARATION( usize )
 833
 834/*                               Is Power Of Two                              */
 835
 836#define GEN_IS_POWER_OF_TWO( T ) \
 837static inline u8 T##_is_power_of_two( T num ) { \
 838	return num && !(num & (num - 1));            \
 839}
 840
 841GEN_IS_POWER_OF_TWO(u8)
 842GEN_IS_POWER_OF_TWO(u16)
 843GEN_IS_POWER_OF_TWO(u32)
 844GEN_IS_POWER_OF_TWO(u64)
 845GEN_IS_POWER_OF_TWO(usize)
 846
 847
 848/*                                  Arena                                     */
 849
 850STRUCT( Arena,
 851	Page *start;  /* The address where the arena starts */
 852	usize claimed;  /* Total size of the arena */
 853	usize occupied; /* The actually occupied (backed) range */
 854	usize taken;    /* The top of the arena */
 855);
 856
 857Arena Arena_create( Status *s, usize size );
 858void Arena_destroy( Status *s, Arena *a );
 859
 860void*  Arena_take( Status *s, Arena *a, usize amount );
 861void   Arena_give( Status *s, Arena *a, usize amount );
 862void  Arena_align( Status *s, Arena *a, usize alignment );
 863
 864/*                                   Heap                                     */
 865
 866#if BUILD_TYPE == BUILD_RELEASE
 867	STRUCT( HeapEntry,
 868		usize size; /* The next pointer is stored in the data when the block
 869			is added to the freelist */
 870	);
 871
 872	STRUCT( Heap,
 873		Arena arena; /* Heap is built on top of arena. It's just an arena + 
 874			a freelist with metadata */
 875		HeapEntry freelist;
 876		HeapEntry *freelist_data;
 877	);
 878
 879#elif BUILD_TYPE == BUILD_DEBUG
 880	STRUCT( HeapEntry,
 881		u64 header_start_guard;
 882		usize allowed_size;
 883		struct _HeapEntry *next; /* unlike in release, in debug we have
 884			a separate next pointer for linking into the freelist */
 885		u64 checksum; /* size xor'd with next, allowed size and the
 886			guard magic number - (likely) detects overwriting of metadata */
 887		usize size;
 888		u64 header_end_guard;
 889	);
 890
 891	STRUCT( Heap,
 892		Arena arena; /* Heap is built on top of arena. It's just an arena +
 893			a freelist with metadata */
 894		HeapEntry freelist;
 895		HeapEntry blocklist; /* The existing blocks in a list */
 896	);
 897#endif
 898ASSERT( sizeof(HeapEntry)%sizeof(usize) == 0 );
 899
 900Heap Heap_create( Status *s, usize size ); /* size - size of underlying arena.
 901	The heap will hold less, due to bookkeeping overhead for allocations. */
 902void Heap_destroy( Status *s, Heap *h );
 903
 904void* Heap_alloc( Status *s, Heap *h, usize amount );
 905void Heap_free(  Status *s, Heap *h, void *ptr );
 906
 907usize Heap_get_asize( Heap *h, const void *ptr );
 908
 909/*                                  Arrays                                    */
 910
 911#define ARR_FOREACH( T, varname, arr) \
 912	for( T *varname = &arr->data[0]; varname < &arr->data[arr->a.len]; varname += 1 )
 913
 914STRUCT( AnyArr,
 915	usize len;
 916	DEBUG(
 917		Heap *heap;
 918		usize checksum;
 919		u32 
 920			sorted : 1;
 921			CmpFunc *sortfunc;
 922	)
 923);
 924
 925AnyArr* AnyArr_create( Status *s, usize count, Heap *h, usize elem_size );
 926void AnyArr_destroy( Status *s, AnyArr** arr, Heap *h );
 927
 928AnyArr* AnyArr_inflate( Status *s, AnyArr *arr, usize additional_count, Heap *h, usize elem_size );
 929AnyArr* AnyArr_deflate( Status *s, AnyArr *arr, Heap *h, usize elem_size ); /* reallocate to just fit the currently contained elements - we assume it's on the same heap */
 930
 931void AnyArr_truncate( Status *s, AnyArr *arr, usize cutlen, usize elem_size );
 932
 933
 934AnyArr* AnyArr_push( Status *s, AnyArr *restrict arr, void *restrict el, Heap *h, usize elem_size );
 935void AnyArr_pop( Status *s, AnyArr *restrict arr, void *restrict el_out, usize elem_size );
 936
 937AnyArr* AnyArr_insert_at( Status *s, AnyArr *arr, usize index, const void *element, Heap *h, usize elem_size);
 938
 939AnyArr* AnyArr_dup( Status *s, const AnyArr *arr, Heap *h, usize elem_size );
 940
 941void AnyArr_sort( Status *s, AnyArr *arr, CmpFunc *cmp, usize elem_size );
 942AnyArr* AnyArr_insert_sorted( Status *s, AnyArr *arr, const void *elem, CmpFunc *cmp, Heap *h, usize elem_size );
 943
 944DEBUG(
 945	void _AnyArr_update_checksum( AnyArr *arr );
 946	void _AnyArr_validate( const AnyArr *arr );
 947)
 948
 949#define GEN_ARRAY_TYPE( T )                                                         \
 950	STRUCT( T##s,                                                                  \
 951		usize len;                                                                \
 952		DEBUG(                                                                    \
 953			Heap *heap;                                                          \
 954			usize checksum;                                                      \
 955			u32                                                                  \
 956				sorted : 1;                                                     \
 957			CmpFunc *sortfunc;                                                   \
 958		)                                                                         \
 959		T data[];                                                                 \
 960	);                                                                             \
 961	ASSERT( sizeof(T##s)%sizeof(usize) == 0 );                                     \
 962	ASSERT( sizeof(T##s) == sizeof(AnyArr) );                                      \
 963                                                                                    \
 964static inline T##s* T##s_create( Status *s, Heap *h, usize count ) {                \
 965	return (T##s*)AnyArr_create( s, count, h, sizeof(T) );                         \
 966}                                                                                   \
 967                                                                                    \
 968static inline void T##s_destroy( Status *s, T##s **arr, Heap *h ) {                 \
 969	AnyArr_destroy( s, (AnyArr**)arr, h );                                         \
 970}                                                                                   \
 971                                                                                    \
 972static inline T##s* T##s_push( Status *s, T##s *arr, T* el, Heap *h ) {             \
 973	return (T##s*)AnyArr_push( s, (AnyArr*)arr, el, h, sizeof(T) );                \
 974}                                                                                   \
 975                                                                                    \
 976static inline void T##s_pop( Status *s, T##s *arr, T* el ) {                        \
 977	AnyArr_pop( s, (AnyArr*)arr, el, sizeof(T) );                                  \
 978}                                                                                   \
 979                                                                                    \
 980static inline void T##s_truncate( Status *s, T##s *arr, usize cutlen ) {            \
 981	AnyArr_truncate( s, (AnyArr*)arr, cutlen, sizeof(T) );                         \
 982}                                                                                   \
 983                                                                                    \
 984static inline T##s* T##s_inflate( Status *s, T##s *arr, usize additional_count, Heap *h ) {   \
 985	return (T##s*)AnyArr_inflate( s, (AnyArr*)arr, additional_count, h, sizeof(T) ); \
 986}                                                                                   \
 987                                                                                    \
 988static inline T##s* T##s_deflate( Status *s, T##s *arr, Heap *h ) {                 \
 989	return (T##s*)AnyArr_deflate( s, (AnyArr*)arr, h, sizeof(T) );                 \
 990}                                                                                   \
 991                                                                                    \
 992static inline T##s* T##s_dup( Status *s, const T##s *arr, Heap *h ) {               \
 993	return (T##s*)AnyArr_dup( s, (AnyArr*)arr, h, sizeof(T) );                     \
 994}                                                                                   \
 995                                                                                    \
 996static inline T##s* T##s_insert_at( Status *s, T##s *arr, usize index, T *element, Heap *h ) { \
 997	return (T##s*)AnyArr_insert_at( s, (AnyArr*)arr, index, element, h, sizeof(T) );          \
 998}                                                                                              \
 999                                                                                               \
1000static inline void T##s_sort( Status *s, T##s *arr, s8 (*cmp)(const T* el1, const T* el2) ) {  \
1001	AnyArr_sort( s, (AnyArr*)arr, (CmpFunc *)cmp, sizeof(T) );                                 \
1002}                                                                                              \
1003                                                                                               \
1004static inline T##s* T##s_insert_sorted( Status *s, T##s *arr, const T *elem, s8 (*cmp)(const T* el1, const T* el2), Heap *h ) { \
1005	return (T##s*)AnyArr_insert_sorted( s, (AnyArr*)arr, elem, (CmpFunc *)cmp, h, sizeof(T) );                            \
1006}                                                                                                                         \
1007                                                                                                                          \
1008
1009GEN_ARRAY_TYPE( u8 )
1010GEN_ARRAY_TYPE( u16 )
1011GEN_ARRAY_TYPE( u32 )
1012GEN_ARRAY_TYPE( u64 )
1013GEN_ARRAY_TYPE( usize )
1014
1015GEN_ARRAY_TYPE( s8 )
1016GEN_ARRAY_TYPE( s16 )
1017GEN_ARRAY_TYPE( s32 )
1018GEN_ARRAY_TYPE( s64 )
1019GEN_ARRAY_TYPE( ssize )
1020
1021GEN_ARRAY_TYPE( f32 )
1022GEN_ARRAY_TYPE( f64 )
1023
1024GEN_ARRAY_TYPE( u8p )
1025GEN_ARRAY_TYPE( u16p )
1026GEN_ARRAY_TYPE( u32p )
1027GEN_ARRAY_TYPE( u64p )
1028GEN_ARRAY_TYPE( usizep )
1029
1030GEN_ARRAY_TYPE( s8p )
1031GEN_ARRAY_TYPE( s16p )
1032GEN_ARRAY_TYPE( s32p )
1033GEN_ARRAY_TYPE( s64p )
1034GEN_ARRAY_TYPE( ssizep )
1035
1036GEN_ARRAY_TYPE( f32p )
1037GEN_ARRAY_TYPE( f64p )
1038
1039
1040
1041
1042/*                                  String                                    */
1043
1044STRUCT( Str,
1045	usize len;
1046	u8 data[];
1047);
1048
1049GEN_POINTER_TYPE( Str );
1050GEN_ARRAY_TYPE( Strp )
1051
1052STRUCT( StrSlc,
1053	usize len;
1054	const u8 *data;
1055);
1056
1057GEN_ARRAY_TYPE( StrSlc )
1058
1059/* On typical platforms that already have/need nul-termination we keep the
1060 * nul-termination alongside the explicit length notation.
1061 * Hacky, but no one wants to copy strings/paths for syscalls.
1062 * NOTE: on these platforms len MUST NOT include the NUL-terminator.
1063 * It is the indexable length of the string. */
1064#if PLATFORM == PLATFORM_LINUX || PLATFORM == PLATFORM_WINDOWS
1065
1066#define STRING( varname, string )                                               \
1067	struct {                                                                   \
1068		u64 len;                                                              \
1069		u8  data[sizeof(string)];                                             \
1070	} varname = { .len = sizeof(string)-1, .data = string }
1071
1072#define STRING_SLICE( varname, stringname, start_index, len )                   \
1073	StrSlc varname = { .len = len, .data = &stringname[start_index] };
1074
1075#define STRING_SLICE_LITERAL( varname, literal)                                 \
1076	u8 varname_data[] = literal;                                               \
1077	StrSlc varname = { .len = sizeof(literal) - 1, .data = &varname_data[0] };
1078#else
1079	#error Str not implemented for current platform. 
1080
1081/* For bare metal, when we get there: */
1082
1083#define STATIC( varname, str )                                    \
1084	const struct {                                               \
1085		u64 len;                                                \
1086		u8  data[sizeof( str ) - 1] __attribute__((nonstring)); \
1087	} varname = { .len = sizeof(str) - 1, .data = str }
1088
1089#endif
1090
1091u8 Str_equals( const Str *s1, const Str *s2 );
1092
1093StrSlc StrSlc_from_Str( Status *s, const Str *str, usize start, usize len );
1094
1095u8 StrSlc_equals( const StrSlc sl1, const StrSlc sl2 );
1096u8 StrSlc_equals_by_ref( const StrSlc *sl1, const StrSlc *sl2 );
1097
1098u8 StrSlc_equals_Str( const StrSlc sl, const Str* s );
1099u8 StrSlc_equals_Str_by_ref( const StrSlc *sl, const Str *s );
1100
1101StrSlcs* StrSlc_split_by_u8( Status *s, const StrSlc *sl, u8 separator, Heap *h );
1102
1103/* String assembler */
1104STRUCT( StrAsm,
1105	Arena a;
1106);
1107
1108StrAsm StrAsm_create( Status *s, usize max_size );
1109void StrAsm_reset( Status *s, StrAsm *sa );
1110void StrAsm_destroy( Status *s, StrAsm *sa );
1111
1112void StrAsm_store_into_arena( Status *s, StrAsm *sa, Arena *dst, Str **out );
1113void StrAsm_store_onto_heap( Status *s, StrAsm *sa, Heap *dst, Str **out );
1114StrSlc StrAsm_as_StrSlc( const StrAsm *sa );
1115
1116/* String, character */
1117void StrAsm_cat_char ( Status *s, StrAsm *sa, u8 value );
1118void StrAsm_cat_Str( Status *s, StrAsm *sa, const Str *str );
1119void StrAsm_cat_StrSlc( Status *s, StrAsm *sa, StrSlc sl );
1120void StrAsm_cat_StrSlc_by_ref( Status *s, StrAsm *sa, const StrSlc *sl );
1121
1122extern u8 _halfbyte_to_hex_ascii[16];
1123
1124static inline void _bin_to_hex_ascii( u8 *data, u8 *out, usize count ) {
1125	#if ARCH == ARCH_X86_64 || ARCH == ARCH_I386
1126		for( u64 i = 0; i < count; ++i ) {
1127			u8 byte = data[count - i - 1];
1128
1129			out[2 * i] = _halfbyte_to_hex_ascii[( byte >> 4 ) & 0x0f];
1130			out[2 * i + 1] = _halfbyte_to_hex_ascii[byte & 0x0f];
1131		}
1132	#else
1133		#error Unimpleneted for big endian.
1134	#endif
1135}
1136
1137/* Hex */
1138void StrAsm_fmtx_u8 ( Status *s, StrAsm *sa,  u8 value);
1139void StrAsm_fmtx_u16( Status *s, StrAsm *sa, u16 value);
1140void StrAsm_fmtx_u32( Status *s, StrAsm *sa, u32 value);
1141void StrAsm_fmtx_u64( Status *s, StrAsm *sa, u64 value);
1142
1143static inline void StrAsm_fmtx_usize( Status *s, StrAsm *sa, usize value) {
1144	#if ARCH == ARCH_X86_64
1145		StrAsm_fmtx_u64( s, sa, value );
1146	#elif ARCH == ARCH_I386
1147		StrAsm_fmtx_u32( s, sa, value );
1148	#else
1149		#error Unimplemented for current arch.
1150	#endif
1151}
1152
1153/* Decimal */
1154void StrAsm_fmtd_u8 ( Status *s, StrAsm *sa,  u8 value);
1155void StrAsm_fmtd_u16( Status *s, StrAsm *sa, u16 value);
1156void StrAsm_fmtd_u32( Status *s, StrAsm *sa, u32 value);
1157void StrAsm_fmtd_u64( Status *s, StrAsm *sa, u64 value);
1158void StrAsm_fmtd_usize( Status *s, StrAsm *sa, usize value) {
1159	#if ARCH == ARCH_X86_64
1160		StrAsm_fmtd_u64( s, sa, value );
1161	#elif ARCH == ARCH_I386
1162		StrAsm_fmtd_u32( s, sa, value );
1163	#else
1164		#error Unimplemented for current arch.
1165	#endif
1166}
1167
1168void StrAsm_fmtd_s8 ( Status *s, StrAsm *sa,  s8 value);
1169void StrAsm_fmtd_s16( Status *s, StrAsm *sa, s16 value);
1170void StrAsm_fmtd_s32( Status *s, StrAsm *sa, s32 value);
1171void StrAsm_fmtd_s64( Status *s, StrAsm *sa, s64 value);
1172void StrAsm_fmtd_ssize( Status *s, StrAsm *sa, ssize value) {
1173	#if ARCH == ARCH_X86_64
1174		StrAsm_fmtd_s64( s, sa, value );
1175	#elif ARCH == ARCH_I386
1176		StrAsm_fmtd_s32( s, sa, value );
1177	#else
1178		#error Unimplemented for current arch.
1179	#endif
1180}
1181
1182
1183/*                                   File                                     */
1184
1185#if OS == OS_LINUX
1186	STRUCT( File,
1187		s32 fd;
1188	);
1189#else
1190	#error File not defined.
1191#endif
1192
1193
1194enum FileOpenFlags {
1195
1196	FILE_ACCESS_READ   = ((usize)1 << 1),
1197	FILE_ACCESS_WRITE  = ((usize)1 << 2),
1198	FILE_ACCESS_APPEND = ((usize)1 << 3),
1199
1200	FILE_ACCESS_MASK =
1201		(FILE_ACCESS_READ | FILE_ACCESS_WRITE | FILE_ACCESS_APPEND),
1202
1203	FILE_EXISTING_OPEN     = ((usize)1 << 4),
1204	FILE_EXISTING_TRUNCATE = ((usize)1 << 5),
1205	FILE_EXISTING_FAIL     = ((usize)1 << 6),
1206
1207	FILE_EXISTING_MASK =
1208		(FILE_EXISTING_OPEN | FILE_EXISTING_TRUNCATE | FILE_EXISTING_FAIL),
1209
1210	FILE_MISSING_CREATE = ((usize)1 << 7),
1211	FILE_MISSING_FAIL   = ((usize)1 << 8),
1212
1213	FILE_MISSING_MASK = (FILE_MISSING_CREATE | FILE_MISSING_FAIL),
1214
1215	FILE_LINK_FOLLOW = ((usize)1 << 9),
1216	FILE_LINK_FAIL = ((usize)1 << 10), /* os-dependent option -
1217		whatever the os guarantees. O_NOFOLLOW on linux. */
1218
1219	FILE_LINK_MASK = (FILE_LINK_FOLLOW | FILE_LINK_FAIL),
1220
1221};
1222
1223static inline void File_open_validate_flags( Status *s, usize flags, Status err_source );
1224
1225File File_open( Status *s, const Str *name, usize flags );
1226void File_close( Status *s, File *f );
1227
1228usize File_read( Status *s, const File *f, usize max_amount, u8 *out );
1229usize File_write( Status *s, const File *f, usize amount, const u8 *buf );
1230
1231void File_seek( Status *s, const File *f, usize position );
1232
1233void File_delete( Status *s, const Str *name );
1234
1235STRUCT( FileView,
1236	File file;
1237	Page *start;
1238	usize claimed;
1239	usize filesize;
1240	usize flags;
1241);
1242
1243enum FileViewFlags {
1244	FILEVIEW_OWN_FILE = (1 << 1),
1245/*	FILEVIEW_PAGE_ALIGNED_EXTEND = (1 << 2), */
1246};
1247
1248FileView FileView_from_file( Status *s, File *file, usize claim_amount, usize flags );
1249/* if claim_amount == 0 => claims exact filesize */
1250
1251/* This is for quick and easy mmaping of files. If you actually want
1252 * control over the opening flags use FileView_from_file */
1253FileView FileView_from_path( Status *s, const Str *path, usize claim_amount, usize flags );
1254
1255StrSlc FileView_as_StrSlc( const FileView *fv );
1256
1257/* Extend the file's end by amount */
1258void FileView_extend_file( Status *s, FileView *fv, usize amount );
1259
1260void FileView_destroy( Status *s, FileView *fv );
1261
1262
1263/*=========================== Core functions =================================*/
1264
1265void terminate(u32 code); /* aka exit */
1266
1267/* force exit, fault, anything that terminates forcefully */
1268void terminate_forced(void);
1269
1270/* raise a debug breakpoint, if possible on the target */
1271void breakpoint(void);
1272
1273static inline void assert( usize condition ) {
1274	if( !condition ) {
1275		breakpoint();
1276	}
1277}
1278
1279/*=============================== Memory =====================================*/
1280#define KiB(n) ((u64)(n) << 10)
1281#define MiB(n) ((u64)(n) << 20)
1282#define GiB(n) ((u64)(n) << 30)
1283#define TiB(n) ((u64)(n) << 40)
1284
1285static inline void mem_copy( const void *restrict source, void *restrict destination, u64 len ) {
1286	const u8 *src = source;
1287	u8 *dst = destination;
1288	u64 i = 0;
1289
1290	for( ; i < len; ++i ) {
1291		dst[i] = src[i];
1292	}
1293}
1294
1295static inline void mem_move( const void *source, void *destination, u64 len ) {
1296	const u8 *src = source;
1297	u8 *dst = destination;
1298	u64 i;
1299
1300	if( src > dst ) {
1301		for( i = 0; i < len; ++i ) {
1302			dst[i] = src[i];
1303		}
1304	} else {
1305		for( i = len; i >= 1; --i ) {
1306			dst[i - 1] = src[i - 1];
1307		}
1308	}
1309}
1310
1311static inline void* mem_set( void *start, u64 len, u8 value ) {
1312	assert(start != 0);
1313	u8 *s = start;
1314	u64 i = 0;
1315
1316	for( ; i < len; ++i ) {
1317		s[i] = value;
1318	}
1319
1320	return &s[len];
1321}
1322
1323/* Request virtual memory range */
1324Page* mem_claim( Status *s, u32 page_count );
1325/* Free virtual memory range */
1326void mem_relinquish( Status *s, Page *start, u32 page_count );
1327
1328/* Set up physical backing */
1329void mem_occupy( Status *s, Page *start, u32 page_count );
1330/* Allow removal of physical backing */
1331void mem_vacate( Status *s, Page *start, u32 page_count );
1332
1333/*                               Bits and pieces                              */
1334static inline void swap( void *restrict el1, void *restrict el2, usize el_size );
1335
1336#define SWAP_STACK_BUFFER_SIZE 128
1337static inline void swap( void *restrict el1, void *restrict el2, usize el_size ) {
1338	register u64 tmp;
1339	switch( el_size ) {
1340		case sizeof(u8):
1341			tmp = *(u8*)el1;
1342			*(u8*)el1 = *(u8*)el2;
1343			*(u8*)el2 = (u8)tmp;
1344			break;
1345		case sizeof(u16):
1346			tmp = *(u16*)el1;
1347			*(u16*)el1 = *(u16*)el2;
1348			*(u16*)el2 = (u16)tmp;
1349			break;
1350		case sizeof(u32):
1351			tmp = *(u32*)el1;
1352			*(u32*)el1 = *(u32*)el2;
1353			*(u32*)el2 = (u32)tmp;
1354			break;
1355		case sizeof(u64):
1356			tmp = *(u64*)el1;
1357			*(u64*)el1 = *(u64*)el2;
1358			*(u64*)el2 = (u64)tmp;
1359			break;
1360
1361		default: {
1362			u8 local[SWAP_STACK_BUFFER_SIZE];
1363
1364			while( el_size >= SWAP_STACK_BUFFER_SIZE ) {
1365				u64 offset = el_size - SWAP_STACK_BUFFER_SIZE;
1366				mem_copy( (u8*)el1 + offset, local, SWAP_STACK_BUFFER_SIZE );
1367				mem_copy( (u8*)el2 + offset, (u8*)el1 + offset, SWAP_STACK_BUFFER_SIZE );
1368				mem_copy( local, (u8*)el2 + offset, SWAP_STACK_BUFFER_SIZE );
1369				el_size -= SWAP_STACK_BUFFER_SIZE;
1370			}
1371
1372			if( el_size ) {
1373				mem_copy( (u8*)el1, local, el_size );
1374				mem_copy( (u8*)el2, (u8*)el1, el_size );
1375				mem_copy( local, (u8*)el2, el_size );
1376			}
1377		}
1378	}
1379}
1380
1381/*                                 Algorithms                                 */
1382
1383SearchFunc algo_binary_search;
1384SortFunc algo_sort_generic;
1385SortFunc algo_insertionsort;
1386FallbackingSortFunc algo_quicksort;
1387
1388
1389/******************************************************************************/
1390/*                     COMMON PLATFORM IMPLEMENTATION                         */
1391/******************************************************************************/
1392
1393static inline void File_open_validate_flags( Status *s, usize flags, Status err_source ) {
1394	END_IF_NOK( *s );
1395
1396	usize existing_flags = flags & FILE_EXISTING_MASK;
1397	usize existing_flags_multiple_set = !usize_is_power_of_two( existing_flags );
1398
1399	usize missing_flags = flags & FILE_MISSING_MASK;
1400	usize missing_flags_multiple_set = !usize_is_power_of_two( missing_flags );
1401
1402	usize link_flags = flags & FILE_LINK_MASK;
1403	usize link_flags_multiple_set = !usize_is_power_of_two( link_flags );
1404
1405	usize write_append_flags = flags & (FILE_ACCESS_WRITE | FILE_ACCESS_APPEND);
1406	usize write_append_flags_multiple_set = !usize_is_power_of_two( write_append_flags );
1407
1408	if( existing_flags_multiple_set |
1409	    missing_flags_multiple_set |
1410	    link_flags_multiple_set |
1411	    (write_append_flags && write_append_flags_multiple_set)
1412	) {
1413		DEBUG(breakpoint());
1414		ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | err_source );
1415		return;
1416	}
1417
1418end:
1419	return;
1420}
1421
1422/******************************************************************************/
1423/*                           MATH STUFF IMPLEMENTATION                        */
1424/******************************************************************************/
1425
1426GEN_UADD_DEFINITION( u8 )
1427GEN_UADD_DEFINITION( u16 )
1428GEN_UADD_DEFINITION( u32 )
1429GEN_UADD_DEFINITION( u64 )
1430
1431GEN_SADD_DEFINITION( s8 )
1432GEN_SADD_DEFINITION( s16 )
1433GEN_SADD_DEFINITION( s32 )
1434GEN_SADD_DEFINITION( s64 )
1435
1436GEN_USUB_DEFINITION( u8 )
1437GEN_USUB_DEFINITION( u16 )
1438GEN_USUB_DEFINITION( u32 )
1439GEN_USUB_DEFINITION( u64 )
1440
1441GEN_SSUB_DEFINITION( s8 )
1442GEN_SSUB_DEFINITION( s16 )
1443GEN_SSUB_DEFINITION( s32 )
1444GEN_SSUB_DEFINITION( s64 )
1445
1446GEN_UMUL_DEFINITION( u8 )
1447GEN_UMUL_DEFINITION( u16 )
1448GEN_UMUL_DEFINITION( u32 )
1449GEN_UMUL_DEFINITION( u64 )
1450
1451GEN_SMUL_DEFINITION( s8 )
1452GEN_SMUL_DEFINITION( s16 )
1453GEN_SMUL_DEFINITION( s32 )
1454GEN_SMUL_DEFINITION( s64 )
1455
1456GEN_UROUND_DOWN_DEFINITION( u8 )
1457GEN_UROUND_DOWN_DEFINITION( u16 )
1458GEN_UROUND_DOWN_DEFINITION( u32 )
1459GEN_UROUND_DOWN_DEFINITION( u64 )
1460GEN_UROUND_DOWN_DEFINITION( usize )
1461
1462GEN_UROUND_UP_DEFINITION( u8 )
1463GEN_UROUND_UP_DEFINITION( u16 )
1464GEN_UROUND_UP_DEFINITION( u32 )
1465GEN_UROUND_UP_DEFINITION( u64 )
1466GEN_UROUND_UP_DEFINITION( usize )
1467
1468
1469#if OS == OS_LINUX
1470/******************************************************************************/
1471/*                      LINUX PLATFORM IMPLEMENTATION                         */
1472/******************************************************************************/
1473
1474
1475/*============================= Entrypoint ===================================*/
1476
1477extern u8* _linux_startup_sp;
1478extern void entry(void);
1479
1480#ifndef NOTLIBC_NOMAIN
1481	extern Heap _linux_heap;
1482	extern Status c_main( StrSlcs *args, StrSlcs *env );
1483#endif
1484
1485/*============================ Linux defines =================================*/
1486
1487#define LINUX_SYSCALL_ERROR_RANGE_START ((usize)-4095)
1488#define LINUX_SYSCALL_ERROR(value) ((usize)value >= LINUX_SYSCALL_ERROR_RANGE_START)
1489
1490#define EPERM           1 /* Operation not permitted */
1491#define ENOENT          2 /* No such file or directory */
1492#define ESRCH           3 /* No such process */
1493#define EINTR           4 /* Interrupted system call */
1494#define EIO             5 /* I/O error */
1495#define ENXIO           6 /* No such device or address */
1496#define E2BIG           7 /* Argument list too long */
1497#define ENOEXEC         8 /* Exec format error */
1498#define EBADF           9 /* Bad file number */
1499#define ECHILD          10 /* No child processes */
1500#define EAGAIN          11 /* Try again */
1501#define ENOMEM          12 /* Out of memory */
1502#define EACCES          13 /* Permission denied */
1503#define EFAULT          14 /* Bad address */
1504#define ENOTBLK         15 /* Block device required */
1505#define EBUSY           16 /* Device or resource busy */
1506#define EEXIST          17 /* File exists */
1507#define EXDEV           18 /* Cross-device link */
1508#define ENODEV          19 /* No such device */
1509#define ENOTDIR         20 /* Not a directory */
1510#define EISDIR          21 /* Is a directory */
1511#define EINVAL          22 /* Invalid argument */
1512#define ENFILE          23 /* File table overflow */
1513#define EMFILE          24 /* Too many open files */
1514#define ENOTTY          25 /* Not a typewriter */
1515#define ETXTBSY         26 /* Text file busy */
1516#define EFBIG           27 /* File too large */
1517#define ENOSPC          28 /* No space left on device */
1518#define ESPIPE          29 /* Illegal seek */
1519#define EROFS           30 /* Read-only file system */
1520#define EMLINK          31 /* Too many links */
1521#define EPIPE           32 /* Broken pipe */
1522#define EDOM            33 /* Math argument out of domain of func */
1523#define ERANGE          34 /* Math result not representable */
1524#define EDEADLK         35 /* Resource deadlock would occur */
1525#define ENAMETOOLONG    36 /* File name too long */
1526#define ENOLCK          37 /* No record locks available */
1527#define ENOSYS          38 /* Invalid system call number */
1528#define ENOTEMPTY       39 /* Directory not empty */
1529#define ELOOP           40 /* Too many symbolic links encountered */
1530#define EWOULDBLOCK     EAGAIN /* Operation would block */
1531#define ENOMSG          42 /* No message of desired type */
1532#define EIDRM           43 /* Identifier removed */
1533#define ECHRNG          44 /* Channel number out of range */
1534#define EL2NSYNC        45 /* Level 2 not synchronized */
1535#define EL3HLT          46 /* Level 3 halted */
1536#define EL3RST          47 /* Level 3 reset */
1537#define ELNRNG          48 /* Link number out of range */
1538#define EUNATCH         49 /* Protocol driver not attached */
1539#define ENOCSI          50 /* No CSI structure available */
1540#define EL2HLT          51 /* Level 2 halted */
1541#define EBADE           52 /* Invalid exchange */
1542#define EBADR           53 /* Invalid request descriptor */
1543#define EXFULL          54 /* Exchange full */
1544#define ENOANO          55 /* No anode */
1545#define EBADRQC         56 /* Invalid request code */
1546#define EBADSLT         57 /* Invalid slot */
1547#define EDEADLOCK       EDEADLK
1548#define EBFONT          59 /* Bad font file format */
1549#define ENOSTR          60 /* Device not a stream */
1550#define ENODATA         61 /* No data available */
1551#define ETIME           62 /* Timer expired */
1552#define ENOSR           63 /* Out of streams resources */
1553#define ENONET          64 /* Machine is not on the network */
1554#define ENOPKG          65 /* Package not installed */
1555#define EREMOTE         66 /* Object is remote */
1556#define ENOLINK         67 /* Link has been severed */
1557#define EADV            68 /* Advertise error */
1558#define ESRMNT          69 /* Srmount error */
1559#define ECOMM           70 /* Communication error on send */
1560#define EPROTO          71 /* Protocol error */
1561#define EMULTIHOP       72 /* Multihop attempted */
1562#define EDOTDOT         73 /* RFS specific error */
1563#define EBADMSG         74 /* Not a data message */
1564#define EFSBADCRC       EBADMSG /* Bad CRC detected */
1565#define EOVERFLOW       75 /* Value too large for defined data type */
1566#define ENOTUNIQ        76 /* Name not unique on network */
1567#define EBADFD          77 /* File descriptor in bad state */
1568#define EREMCHG         78 /* Remote address changed */
1569#define ELIBACC         79 /* Can not access a needed shared library */
1570#define ELIBBAD         80 /* Accessing a corrupted shared library */
1571#define ELIBSCN         81 /* .lib section in a.out corrupted */
1572#define ELIBMAX         82 /* Attempting to link in too many shared libraries */
1573#define ELIBEXEC        83 /* Cannot exec a shared library directly */
1574#define EILSEQ          84 /* Illegal byte sequence */
1575#define ERESTART        85 /* Interrupted system call should be restarted */
1576#define ESTRPIPE        86 /* Streams pipe error */
1577#define EUSERS          87 /* Too many users */
1578#define ENOTSOCK        88 /* Socket operation on non-socket */
1579#define EDESTADDRREQ    89 /* Destination address required */
1580#define EMSGSIZE        90 /* Message too long */
1581#define EPROTOTYPE      91 /* Protocol wrong type for socket */
1582#define ENOPROTOOPT     92 /* Protocol not available */
1583#define EPROTONOSUPPORT 93 /* Protocol not supported */
1584#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
1585#define EOPNOTSUPP      95 /* Operation not supported on transport endpoint */
1586#define EPFNOSUPPORT    96 /* Protocol family not supported */
1587#define EAFNOSUPPORT    97 /* Address family not supported by protocol */
1588#define EADDRINUSE      98 /* Address already in use */
1589#define EADDRNOTAVAIL   99 /* Cannot assign requested address */
1590#define ENETDOWN        100 /* Network is down */
1591#define ENETUNREACH     101 /* Network is unreachable */
1592#define ENETRESET       102 /* Network dropped connection because of reset */
1593#define ECONNABORTED    103 /* Software caused connection abort */
1594#define ECONNRESET      104 /* Connection reset by peer */
1595#define ENOBUFS         105 /* No buffer space available */
1596#define EISCONN         106 /* Transport endpoint is already connected */
1597#define ENOTCONN        107 /* Transport endpoint is not connected */
1598#define ESHUTDOWN       108 /* Cannot send after transport endpoint shutdown */
1599#define ETOOMANYREFS    109 /* Too many references: cannot splice */
1600#define ETIMEDOUT       110 /* Connection timed out */
1601#define ECONNREFUSED    111 /* Connection refused */
1602#define EHOSTDOWN       112 /* Host is down */
1603#define EHOSTUNREACH    113 /* No route to host */
1604#define EALREADY        114 /* Operation already in progress */
1605#define EINPROGRESS     115 /* Operation now in progress */
1606#define ESTALE          116 /* Stale file handle */
1607#define EUCLEAN         117 /* Structure needs cleaning */
1608#define EFSCORRUPTED    EUCLEAN /* Filesystem is corrupted */
1609#define ENOTNAM         118 /* Not a XENIX named type file */
1610#define ENAVAIL         119 /* No XENIX semaphores available */
1611#define EISNAM          120 /* Is a named type file */
1612#define EREMOTEIO       121 /* Remote I/O error */
1613#define EDQUOT          122 /* Quota exceeded */
1614#define ENOMEDIUM       123 /* No medium found */
1615#define EMEDIUMTYPE     124 /* Wrong medium type */
1616#define ECANCELED       125 /* Operation Canceled */
1617#define ENOKEY          126 /* Required key not available */
1618#define EKEYEXPIRED     127 /* Key has expired */
1619#define EKEYREVOKED     128 /* Key has been revoked */
1620#define EKEYREJECTED    129 /* Key was rejected by service */
1621#define EOWNERDEAD      130 /* Owner died */
1622#define ENOTRECOVERABLE 131 /* State not recoverable */
1623#define ERFKILL         132 /* Operation not possible due to RF-kill */
1624#define EHWPOISON       133 /* Memory page has hardware error */
1625
1626/* Copied from some header included by linux/fcntl */
1627#define O_RDONLY     00
1628#define O_WRONLY     01
1629#define O_RDWR       02
1630#define O_ACCMODE    03
1631#define O_CREAT      0100
1632#define O_EXCL       0200
1633#define O_NOCTTY     0400
1634#define O_TRUNC      01000
1635#define O_APPEND     02000
1636#define O_NONBLOCK   04000
1637#define O_DSYNC      010000
1638#define FASYNC       020000
1639#define O_DIRECT     040000
1640#define O_LARGEFILE  0100000
1641#define O_DIRECTORY  0200000
1642#define O_NOFOLLOW   0400000
1643#define O_NOATIME    01000000
1644#define O_CLOEXEC    02000000
1645#define __O_SYNC     04000000
1646#define O_SYNC       (__O_SYNC|O_DSYNC)
1647#define O_PATH       010000000
1648#define __O_TMPFILE  020000000
1649#define O_TMPFILE    (__O_TMPFILE | O_DIRECTORY)
1650
1651#define SEEK_SET 0
1652#define SEEK_CUR 1
1653#define SEEK_END 2
1654
1655#if ARCH == ARCH_X86_64
1656struct stat {
1657    u64 st_dev;
1658    u64 st_ino;
1659    u64 st_nlink;
1660
1661    u32 st_mode;
1662    u32 st_uid;
1663    u32 st_gid;
1664    u32 __pad0;
1665
1666    u64 st_rdev;
1667
1668    s64 st_size;
1669    s64 st_blksize;
1670    s64 st_blocks;
1671
1672    u64 st_atime;
1673    u64 st_atime_nsec;
1674    u64 st_mtime;
1675    u64 st_mtime_nsec;
1676    u64 st_ctime;
1677    u64 st_ctime_nsec;
1678
1679    s64 __unused[3];
1680};
1681
1682#else 
1683	#error struct stat is not defined
1684#endif
1685
1686#define LINUX_PROT_NONE (0x0)
1687#define LINUX_PROT_READ (0x1)
1688#define LINUX_PROT_WRITE (0x2)
1689#define LINUX_PROT_EXEC (0x4)
1690
1691#define MMAP_MAP_SHARED (0x1)
1692#define MMAP_MAP_PRIVATE (0x2)
1693#define MMAP_MAP_SHARED_VALIDATE (0x3)
1694#define MMAP_MAP_SHARED_DROPPABLE (0x08)
1695#define MMAP_MAP_FIXED (0x10)
1696#define MMAP_MAP_ANONYMOUS (0x20)
1697
1698#define MMAP_MAP_FAILED ((void *)-1)
1699
1700#define MADV_NORMAL 0
1701#define MADV_RANDOM 1
1702#define MADV_SEQUENTIAL 2
1703#define MADV_WILLNEED 3
1704#define MADV_DONTNEED 4
1705#define MADV_FREE 8
1706#define MADV_REMOVE 9
1707#define MADV_DONTFORK 10
1708#define MADV_DOFORK 11
1709#define MADV_MERGEABLE 12
1710#define MADV_UNMERGEABLE 13
1711#define MADV_HUGEPAGE 14
1712#define MADV_NOHUGEPAGE 15
1713#define MADV_DONTDUMP 16
1714#define MADV_DODUMP 17
1715#define MADV_WIPEONFORK 18
1716#define MADV_KEEPONFORK 19
1717#define MADV_COLD 20
1718#define MADV_PAGEOUT 21
1719#define MADV_POPULATE_READ 22
1720#define MADV_POPULATE_WRITE 23
1721#define MADV_DONTNEED_LOCKED 24
1722#define MADV_COLLAPSE 25
1723#define MADV_HWPOISON 100
1724#define MADV_GUARD_INSTALL 102
1725#define MADV_GUARD_REMOVE 103
1726
1727
1728/*============================ System calls ==================================*/
1729
1730/* System call assembly wrappers */
1731ssize linux_syscall1(usize num, usize arg1);
1732ssize linux_syscall2(usize num, usize arg1, usize arg2);
1733ssize linux_syscall3(usize num, usize arg1, usize arg2, usize arg3);
1734ssize linux_syscall4(usize num, usize arg1, usize arg2, usize arg3, usize arg4);
1735ssize linux_syscall5(usize num, usize arg1, usize arg2, usize arg3, usize arg4, usize arg5);
1736ssize linux_syscall6(usize num, usize arg1, usize arg2, usize arg3, usize arg4, usize arg5, usize arg6);
1737
1738/* Actual system calls */
1739Status linux_read( u32 fd, usize max_amount, usize *out_amount, u8 *out  );
1740Status linux_write( u32 fd, usize amount, usize *out_amount, const u8 *buf );
1741Status linux_open( const u8* path, s32 flags, s32 mode, s32 *out_fd );
1742Status linux_close( s32 *fd );
1743Status linux_lseek( u32 fd, usize offset, usize whence );
1744ssize linux_stat( const char* path, struct stat *statbuf );
1745Status linux_fstat( s32 fd, struct stat *statbuf );
1746void linux_exit( s32 exitcode );
1747Status linux_mmap( usize addr, usize len, usize prot, usize flags, usize fd, usize offset, void **out );
1748Status linux_munmap( usize start, usize len );
1749Status linux_mprotect( usize start, usize len, usize prot );
1750Status linux_madvise( usize start, usize len, s32 behaviour );
1751ssize linux_unlink( const u8 *path );
1752Status linux_fallocate( s32 fd, s32 mode, usize offset, usize len );
1753
1754#endif
1755
1756#endif
1757