diff --git a/src/libraries/libc/arch/x86_64/_Exit.s b/src/libraries/libc/arch/x86_64/_Exit.s deleted file mode 100644 index 7dd6c2e..0000000 --- a/src/libraries/libc/arch/x86_64/_Exit.s +++ /dev/null @@ -1,5 +0,0 @@ -extern j6_process_exit -global _PDCLIB_Exit -_PDCLIB_Exit: - ; arg should already be in rdi - jmp j6_process_exit diff --git a/src/libraries/libc/arch/x86_64/crt0.s b/src/libraries/libc/arch/x86_64/crt0.s deleted file mode 100644 index d059a8b..0000000 --- a/src/libraries/libc/arch/x86_64/crt0.s +++ /dev/null @@ -1,17 +0,0 @@ -extern main -extern exit -extern _init_libj6 - -global _start:function (_start.end - _start) -_start: - mov rbp, rsp - mov rdi, rsp - call _init_libj6 - - pop rdi - mov rsi, rsp - call main - - mov rdi, rax - call exit -.end: diff --git a/src/libraries/libc/assert.h b/src/libraries/libc/assert.h deleted file mode 100644 index 6a58880..0000000 --- a/src/libraries/libc/assert.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -/* Diagnostics - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/aux.h" -#include "j6libc/cpp.h" - -CPP_CHECK_BEGIN - -void _PDCLIB_assert( const char * const, const char * const, const char * const, unsigned ); - -/* If NDEBUG is set, assert() is a null operation. */ -#undef assert - -#ifdef NDEBUG -#define assert( ignore ) ( (void) 0 ) -#else -#define assert( expression ) ( ( expression ) ? (void) 0 \ - : _PDCLIB_assert( #expression, __func__, __FILE__, __LINE__ ) ) -#endif - -CPP_CHECK_END diff --git a/src/libraries/libc/ctype.h b/src/libraries/libc/ctype.h deleted file mode 100644 index 5f68dd7..0000000 --- a/src/libraries/libc/ctype.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once -/* Character handling - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" -#include "j6libc/cpp.h" - -CPP_CHECK_BEGIN - -/* Character classification functions */ - -/* Note that there is a difference between "whitespace" (any printing, non- - graph character, like horizontal and vertical tab), and "blank" (the literal - ' ' space character). - - There will be masking macros for each of these later on, but right now I - focus on the functions only. -*/ - -/* Returns isalpha( c ) || isdigit( c ) */ -int isalnum( int c ); - -/* Returns isupper( c ) || islower( c ) in the "C" locale. - In any other locale, also returns true for a locale-specific set of - alphabetic characters which are neither control characters, digits, - punctation, or whitespace. -*/ -int isalpha( int c ); - -/* Returns true if the character isspace() and used for seperating words within - a line of text. In the "C" locale, only ' ' and '\t' are considered blanks. -*/ -int isblank( int c ); - -/* Returns true if the character is a control character. */ -int iscntrl( int c ); - -/* Returns true if the character is a decimal digit. Locale-independent. */ -int isdigit( int c ); - -/* Returns true for every printing character except space (' '). - NOTE: This definition differs from that of iswgraph() in , - which considers any iswspace() character, not only ' '. -*/ -int isgraph( int c ); - -/* Returns true for lowercase letters in the "C" locale. - In any other locale, also returns true for a locale-specific set of - characters which are neither control characters, digits, punctation, or - space (' '). In a locale other than the "C" locale, a character might test - true for both islower() and isupper(). -*/ -int islower( int c ); - -/* Returns true for every printing character including space (' '). */ -int isprint( int c ); - -/* Returns true for a locale-specific set of punctuation charcters; these - may not be whitespace or alphanumeric. In the "C" locale, returns true - for every printing character that is not whitespace or alphanumeric. -*/ -int ispunct( int c ); - -/* Returns true for every standard whitespace character (' ', '\f', '\n', '\r', - '\t', '\v') in the "C" locale. In any other locale, also returns true for a - locale-specific set of characters for which isalnum() is false. -*/ -int isspace( int c ); - -/* Returns true for uppercase letters in the "C" locale. - In any other locale, also returns true for a locale-specific set of - characters which are neither control characters, digits, punctation, or - space (' '). In a locale other than the "C" locale, a character might test - true for both islower() and isupper(). -*/ -int isupper( int c ); - -/* Returns true for any hexadecimal-digit character. Locale-independent. */ -int isxdigit( int c ); - -/* Character case mapping functions */ - -/* Converts an uppercase letter to a corresponding lowercase letter. Input that - is not an uppercase letter remains unchanged. -*/ -int tolower( int c ); - -/* Converts a lowercase letter to a corresponding uppercase letter. Input that - is not a lowercase letter remains unchanged. -*/ -int toupper( int c ); - -CPP_CHECK_END diff --git a/src/libraries/libc/ctype/isalnum.c b/src/libraries/libc/ctype/isalnum.c deleted file mode 100644 index 6836bcd..0000000 --- a/src/libraries/libc/ctype/isalnum.c +++ /dev/null @@ -1,13 +0,0 @@ -/* isalnum( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isalnum( int c ) -{ - return ( isdigit( c ) || isalpha( c ) ); -} diff --git a/src/libraries/libc/ctype/isalpha.c b/src/libraries/libc/ctype/isalpha.c deleted file mode 100644 index 7ece916..0000000 --- a/src/libraries/libc/ctype/isalpha.c +++ /dev/null @@ -1,13 +0,0 @@ -/* isalpha( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isalpha( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_ALPHA ); -} diff --git a/src/libraries/libc/ctype/isblank.c b/src/libraries/libc/ctype/isblank.c deleted file mode 100644 index 0d10fbf..0000000 --- a/src/libraries/libc/ctype/isblank.c +++ /dev/null @@ -1,13 +0,0 @@ -/* isblank( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isblank( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_BLANK ); -} diff --git a/src/libraries/libc/ctype/iscntrl.c b/src/libraries/libc/ctype/iscntrl.c deleted file mode 100644 index 5b4652c..0000000 --- a/src/libraries/libc/ctype/iscntrl.c +++ /dev/null @@ -1,13 +0,0 @@ -/* iscntrl( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int iscntrl( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_CNTRL ); -} diff --git a/src/libraries/libc/ctype/isdigit.c b/src/libraries/libc/ctype/isdigit.c deleted file mode 100644 index e3147c8..0000000 --- a/src/libraries/libc/ctype/isdigit.c +++ /dev/null @@ -1,13 +0,0 @@ -/* isdigit( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isdigit( int c ) -{ - return ( c >= _PDCLIB_lc_ctype.digits_low && c <= _PDCLIB_lc_ctype.digits_high ); -} diff --git a/src/libraries/libc/ctype/isgraph.c b/src/libraries/libc/ctype/isgraph.c deleted file mode 100644 index 838e771..0000000 --- a/src/libraries/libc/ctype/isgraph.c +++ /dev/null @@ -1,13 +0,0 @@ -/* isgraph( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isgraph( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_GRAPH ); -} diff --git a/src/libraries/libc/ctype/islower.c b/src/libraries/libc/ctype/islower.c deleted file mode 100644 index e7a3ef5..0000000 --- a/src/libraries/libc/ctype/islower.c +++ /dev/null @@ -1,13 +0,0 @@ -/* islower( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int islower( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_LOWER ); -} diff --git a/src/libraries/libc/ctype/isprint.c b/src/libraries/libc/ctype/isprint.c deleted file mode 100644 index efa3c14..0000000 --- a/src/libraries/libc/ctype/isprint.c +++ /dev/null @@ -1,14 +0,0 @@ -/* isprint( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isprint( int c ) -{ - /* FIXME: Space as of current locale charset, not source charset. */ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_GRAPH ) || ( c == ' ' ); -} diff --git a/src/libraries/libc/ctype/ispunct.c b/src/libraries/libc/ctype/ispunct.c deleted file mode 100644 index e14eda0..0000000 --- a/src/libraries/libc/ctype/ispunct.c +++ /dev/null @@ -1,13 +0,0 @@ -/* ispunct( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int ispunct( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_PUNCT ); -} diff --git a/src/libraries/libc/ctype/isspace.c b/src/libraries/libc/ctype/isspace.c deleted file mode 100644 index dc8abba..0000000 --- a/src/libraries/libc/ctype/isspace.c +++ /dev/null @@ -1,13 +0,0 @@ -/* isspace( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isspace( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_SPACE ); -} diff --git a/src/libraries/libc/ctype/isupper.c b/src/libraries/libc/ctype/isupper.c deleted file mode 100644 index 6aa01f2..0000000 --- a/src/libraries/libc/ctype/isupper.c +++ /dev/null @@ -1,13 +0,0 @@ -/* isupper( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isupper( int c ) -{ - return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_UPPER ); -} diff --git a/src/libraries/libc/ctype/isxdigit.c b/src/libraries/libc/ctype/isxdigit.c deleted file mode 100644 index 70d05c9..0000000 --- a/src/libraries/libc/ctype/isxdigit.c +++ /dev/null @@ -1,15 +0,0 @@ -/* isxdigit( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int isxdigit( int c ) -{ - return ( isdigit( c ) - || ( c >= _PDCLIB_lc_ctype.Xdigits_low && c <= _PDCLIB_lc_ctype.Xdigits_high ) - || ( c >= _PDCLIB_lc_ctype.xdigits_low && c <= _PDCLIB_lc_ctype.xdigits_high ) ); -} diff --git a/src/libraries/libc/ctype/tolower.c b/src/libraries/libc/ctype/tolower.c deleted file mode 100644 index f43652a..0000000 --- a/src/libraries/libc/ctype/tolower.c +++ /dev/null @@ -1,13 +0,0 @@ -/* tolower( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int tolower( int c ) -{ - return _PDCLIB_lc_ctype.entry[c].lower; -} diff --git a/src/libraries/libc/ctype/toupper.c b/src/libraries/libc/ctype/toupper.c deleted file mode 100644 index b48d534..0000000 --- a/src/libraries/libc/ctype/toupper.c +++ /dev/null @@ -1,13 +0,0 @@ -/* toupper( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int toupper( int c ) -{ - return _PDCLIB_lc_ctype.entry[c].upper; -} diff --git a/src/libraries/libc/errno.h b/src/libraries/libc/errno.h deleted file mode 100644 index b2d5423..0000000 --- a/src/libraries/libc/errno.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -/* Errors - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" - -#define errno (*_PDCLIB_errno_func()) - -#define ERANGE _PDCLIB_ERANGE -#define EDOM _PDCLIB_EDOM -#define ENOMEM _PDCLIB_ENOMEM -#define EINVAL _PDCLIB_EINVAL diff --git a/src/libraries/libc/float.h b/src/libraries/libc/float.h deleted file mode 100644 index 70f72c0..0000000 --- a/src/libraries/libc/float.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once -/* Characteristics of floating types - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/config.h" - -#define FLT_ROUNDS _PDCLIB_FLT_ROUNDS -#define FLT_EVAL_METHOD _PDCLIB_FLT_EVAL_METHOD -#define DECIMAL_DIG _PDCLIB_DECIMAL_DIG - - /* Radix of exponent representation */ -#define FLT_RADIX __FLT_RADIX__ - /* Number of base-FLT_RADIX digits in the significand of a float */ -#define FLT_MANT_DIG __FLT_MANT_DIG__ - /* Number of decimal digits of precision in a float */ -#define FLT_DIG __FLT_DIG__ - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#define FLT_EPSILON __FLT_EPSILON__ - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#define FLT_MIN_EXP __FLT_MIN_EXP__ - /* Minimum normalised float */ -#define FLT_MIN __FLT_MIN__ - /* Minimum int x such that 10**x is a normalised float */ -#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__ - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#define FLT_MAX_EXP __FLT_MAX_EXP__ - /* Maximum float */ -#define FLT_MAX __FLT_MAX__ - /* Maximum int x such that 10**x is a representable float */ -#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__ - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#define DBL_MANT_DIG __DBL_MANT_DIG__ - /* Number of decimal digits of precision in a double */ -#define DBL_DIG __DBL_DIG__ - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#define DBL_EPSILON __DBL_EPSILON__ - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#define DBL_MIN_EXP __DBL_MIN_EXP__ - /* Minimum normalised double */ -#define DBL_MIN __DBL_MIN__ - /* Minimum int x such that 10**x is a normalised double */ -#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__ - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#define DBL_MAX_EXP __DBL_MAX_EXP__ - /* Maximum double */ -#define DBL_MAX __DBL_MAX__ - /* Maximum int x such that 10**x is a representable double */ -#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#define LDBL_MANT_DIG __LDBL_MANT_DIG__ - /* Number of decimal digits of precision in a long double */ -#define LDBL_DIG __LDBL_DIG__ - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#define LDBL_EPSILON __LDBL_EPSILON__ - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#define LDBL_MIN_EXP __LDBL_MIN_EXP__ - /* Minimum normalised long double */ -#define LDBL_MIN __LDBL_MIN__ - /* Minimum int x such that 10**x is a normalised long double */ -#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#define LDBL_MAX_EXP __LDBL_MAX_EXP__ - /* Maximum long double */ -#define LDBL_MAX __LDBL_MAX__ - /* Maximum int x such that 10**x is a representable long double */ -#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ diff --git a/src/libraries/libc/inttypes.h b/src/libraries/libc/inttypes.h deleted file mode 100644 index f2ad82c..0000000 --- a/src/libraries/libc/inttypes.h +++ /dev/null @@ -1,250 +0,0 @@ -#pragma once -/* Format conversion of integer types - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/cpp.h" -#include - -CPP_CHECK_BEGIN - -typedef struct _PDCLIB_imaxdiv_t imaxdiv_t; - -#define PRId8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) ) -#define PRId16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) ) -#define PRId32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) ) -#define PRId64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) ) - -#define PRIdLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) ) -#define PRIdLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) ) -#define PRIdLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) ) -#define PRIdLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) ) - -#define PRIdFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, d ) ) -#define PRIdFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, d ) ) -#define PRIdFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, d ) ) -#define PRIdFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, d ) ) - -#define PRIdMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, d ) ) -#define PRIdPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, d ) ) - -#define PRIi8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) ) -#define PRIi16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) ) -#define PRIi32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) ) -#define PRIi64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) ) - -#define PRIiLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) ) -#define PRIiLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) ) -#define PRIiLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) ) -#define PRIiLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) ) - -#define PRIiFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, i ) ) -#define PRIiFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, i ) ) -#define PRIiFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, i ) ) -#define PRIiFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, i ) ) - -#define PRIiMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, i ) ) -#define PRIiPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, i ) ) - -#define PRIo8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) ) -#define PRIo16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) ) -#define PRIo32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) ) -#define PRIo64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) ) - -#define PRIoLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) ) -#define PRIoLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) ) -#define PRIoLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) ) -#define PRIoLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) ) - -#define PRIoFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, o ) ) -#define PRIoFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, o ) ) -#define PRIoFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, o ) ) -#define PRIoFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, o ) ) - -#define PRIoMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, o ) ) -#define PRIoPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, o ) ) - -#define PRIu8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) ) -#define PRIu16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) ) -#define PRIu32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) ) -#define PRIu64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) ) - -#define PRIuLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) ) -#define PRIuLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) ) -#define PRIuLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) ) -#define PRIuLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) ) - -#define PRIuFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, u ) ) -#define PRIuFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, u ) ) -#define PRIuFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, u ) ) -#define PRIuFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, u ) ) - -#define PRIuMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, u ) ) -#define PRIuPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, u ) ) - -#define PRIx8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) ) -#define PRIx16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) ) -#define PRIx32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) ) -#define PRIx64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) ) - -#define PRIxLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) ) -#define PRIxLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) ) -#define PRIxLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) ) -#define PRIxLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) ) - -#define PRIxFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, x ) ) -#define PRIxFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, x ) ) -#define PRIxFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, x ) ) -#define PRIxFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, x ) ) - -#define PRIxMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, x ) ) -#define PRIxPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, x ) ) - -#define PRIX8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, X ) ) -#define PRIX16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, X ) ) -#define PRIX32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, X ) ) -#define PRIX64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, X ) ) - -#define PRIXLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, X ) ) -#define PRIXLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, X ) ) -#define PRIXLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, X ) ) -#define PRIXLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, X ) ) - -#define PRIXFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, X ) ) -#define PRIXFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, X ) ) -#define PRIXFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, X ) ) -#define PRIXFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, X ) ) - -#define PRIXMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, X ) ) -#define PRIXPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, X ) ) - -#define SCNd8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) ) -#define SCNd16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) ) -#define SCNd32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) ) -#define SCNd64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) ) - -#define SCNdLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) ) -#define SCNdLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) ) -#define SCNdLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) ) -#define SCNdLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) ) - -#define SCNdFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, d ) ) -#define SCNdFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, d ) ) -#define SCNdFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, d ) ) -#define SCNdFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, d ) ) - -#define SCNdMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, d ) ) -#define SCNdPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, d ) ) - -#define SCNi8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) ) -#define SCNi16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) ) -#define SCNi32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) ) -#define SCNi64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) ) - -#define SCNiLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) ) -#define SCNiLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) ) -#define SCNiLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) ) -#define SCNiLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) ) - -#define SCNiFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, i ) ) -#define SCNiFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, i ) ) -#define SCNiFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, i ) ) -#define SCNiFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, i ) ) - -#define SCNiMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, i ) ) -#define SCNiPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, i ) ) - -#define SCNo8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) ) -#define SCNo16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) ) -#define SCNo32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) ) -#define SCNo64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) ) - -#define SCNoLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) ) -#define SCNoLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) ) -#define SCNoLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) ) -#define SCNoLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) ) - -#define SCNoFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, o ) ) -#define SCNoFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, o ) ) -#define SCNoFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, o ) ) -#define SCNoFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, o ) ) - -#define SCNoMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, o ) ) -#define SCNoPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, o ) ) - -#define SCNu8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) ) -#define SCNu16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) ) -#define SCNu32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) ) -#define SCNu64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) ) - -#define SCNuLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) ) -#define SCNuLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) ) -#define SCNuLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) ) -#define SCNuLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) ) - -#define SCNuFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, u ) ) -#define SCNuFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, u ) ) -#define SCNuFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, u ) ) -#define SCNuFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, u ) ) - -#define SCNuMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, u ) ) -#define SCNuPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, u ) ) - -#define SCNx8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) ) -#define SCNx16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) ) -#define SCNx32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) ) -#define SCNx64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) ) - -#define SCNxLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) ) -#define SCNxLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) ) -#define SCNxLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) ) -#define SCNxLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) ) - -#define SCNxFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, x ) ) -#define SCNxFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, x ) ) -#define SCNxFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, x ) ) -#define SCNxFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, x ) ) - -#define SCNxMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, x ) ) -#define SCNxPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, x ) ) - -/* 7.8.2 Functions for greatest-width integer types */ - -/* Calculate the absolute value of j */ -intmax_t imaxabs( intmax_t j ); - -/* Return quotient (quot) and remainder (rem) of an integer division in the - imaxdiv_t struct. -*/ -imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom ); - -/* Seperate the character array nptr into three parts: A (possibly empty) - sequence of whitespace characters, a character representation of an integer - to the given base, and trailing invalid characters (including the terminating - null character). If base is 0, assume it to be 10, unless the integer - representation starts with 0x / 0X (setting base to 16) or 0 (setting base to - 8). If given, base can be anything from 0 to 36, using the 26 letters of the - base alphabet (both lowercase and uppercase) as digits 10 through 35. - The integer representation is then converted into the return type of the - function. It can start with a '+' or '-' sign. If the sign is '-', the result - of the conversion is negated. - If the conversion is successful, the converted value is returned. If endptr - is not a NULL pointer, a pointer to the first trailing invalid character is - returned in *endptr. - If no conversion could be performed, zero is returned (and nptr in *endptr, - if endptr is not a NULL pointer). If the converted value does not fit into - the return type, the functions return INTMAX_MIN, INTMAX_MAX, or UINTMAX_MAX, - respectively, depending on the sign of the integer representation and the - return type, and errno is set to ERANGE. -*/ -/* This function is equivalent to strtol() / strtoul() in , but on - the potentially larger type. -*/ -intmax_t strtoimax( const char * restrict nptr, char * * restrict endptr, int base ); -uintmax_t strtoumax( const char * restrict nptr, char * * restrict endptr, int base ); - -/* TODO: wcstoimax(), wcstoumax() */ - -CPP_CHECK_END diff --git a/src/libraries/libc/inttypes/imaxabs.c b/src/libraries/libc/inttypes/imaxabs.c deleted file mode 100644 index 5d5232b..0000000 --- a/src/libraries/libc/inttypes/imaxabs.c +++ /dev/null @@ -1,12 +0,0 @@ -/* imaxabs( intmax_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -intmax_t imaxabs( intmax_t j ) -{ - return ( j >= 0 ) ? j : -j; -} diff --git a/src/libraries/libc/inttypes/imaxdiv.c b/src/libraries/libc/inttypes/imaxdiv.c deleted file mode 100644 index d70c0c1..0000000 --- a/src/libraries/libc/inttypes/imaxdiv.c +++ /dev/null @@ -1,15 +0,0 @@ -/* lldiv( long long int, long long int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom ) -{ - imaxdiv_t rc; - rc.quot = numer / denom; - rc.rem = numer % denom; - return rc; -} diff --git a/src/libraries/libc/inttypes/strtoimax.c b/src/libraries/libc/inttypes/strtoimax.c deleted file mode 100644 index a8b871d..0000000 --- a/src/libraries/libc/inttypes/strtoimax.c +++ /dev/null @@ -1,27 +0,0 @@ -/* strtoimax( const char *, char * *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -intmax_t strtoimax( const char * restrict nptr, char ** restrict endptr, int base ) -{ - intmax_t rc; - char sign = '+'; - const char * p = _PDCLIB_strtox_prelim( nptr, &sign, &base ); - if ( base < 2 || base > 36 ) return 0; - if ( sign == '+' ) - { - rc = (intmax_t)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)INTMAX_MAX, (uintmax_t)( INTMAX_MAX / base ), (int)( INTMAX_MAX % base ), &sign ); - } - else - { - rc = (intmax_t)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)INTMAX_MIN, (uintmax_t)( INTMAX_MIN / -base ), (int)( -( INTMAX_MIN % base ) ), &sign ); - } - if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) nptr; - return ( sign == '+' ) ? rc : -rc; -} diff --git a/src/libraries/libc/inttypes/strtoumax.c b/src/libraries/libc/inttypes/strtoumax.c deleted file mode 100644 index 38be1c3..0000000 --- a/src/libraries/libc/inttypes/strtoumax.c +++ /dev/null @@ -1,20 +0,0 @@ -/* strtoumax( const char *, char * *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -uintmax_t strtoumax( const char * restrict nptr, char ** restrict endptr, int base ) -{ - uintmax_t rc; - char sign = '+'; - const char * p = _PDCLIB_strtox_prelim( nptr, &sign, &base ); - if ( base < 2 || base > 36 ) return 0; - rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)UINTMAX_MAX, (uintmax_t)( UINTMAX_MAX / base ), (int)( UINTMAX_MAX % base ), &sign ); - if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) nptr; - return ( sign == '+' ) ? rc : -rc; -} diff --git a/src/libraries/libc/iso646.h b/src/libraries/libc/iso646.h deleted file mode 100644 index 8564902..0000000 --- a/src/libraries/libc/iso646.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -/* Alternative spellings - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#define and && -#define and_eq &= -#define bitand & -#define bitor | -#define compl ~ -#define not ! -#define not_eq != -#define or || -#define or_eq |= -#define xor ^ -#define xor_eq ^= diff --git a/src/libraries/libc/j6libc/Readme.txt b/src/libraries/libc/j6libc/Readme.txt deleted file mode 100644 index 13ad05c..0000000 --- a/src/libraries/libc/j6libc/Readme.txt +++ /dev/null @@ -1,10 +0,0 @@ -This directory holds various "internals" of PDCLib: - -- definitions of helper functions not specified by the standard (hidden in the - _PDCLIB_* namespace); - -- definitions of data objects, both internal (like _PDCLIB_digits) and specified by - the standard (_PDCLIB_errno); - -- test drivers for functionality that does not have its own implementation - file to put the test driver in (stdarg). diff --git a/src/libraries/libc/j6libc/allocpages.c b/src/libraries/libc/j6libc/allocpages.c deleted file mode 100644 index f638ba3..0000000 --- a/src/libraries/libc/j6libc/allocpages.c +++ /dev/null @@ -1,16 +0,0 @@ -/* _PDCLIB_allocpages( int const ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_allocpages() fit for use with - POSIX kernels. -*/ - -#include "j6libc/glue.h" - -void * _PDCLIB_allocpages( int const n ) -{ - return 0; -} diff --git a/src/libraries/libc/j6libc/assert.c b/src/libraries/libc/j6libc/assert.c deleted file mode 100644 index 2aa8c94..0000000 --- a/src/libraries/libc/j6libc/assert.c +++ /dev/null @@ -1,18 +0,0 @@ -/* _PDCLIB_assert( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -#include "j6libc/aux.h" - -void _PDCLIB_assert( const char * const message, const char * const function, const char * const file, unsigned line ) -{ - fprintf( stderr, "Assertion failed: %s, function %s, file %s, line %d.%s", - message, function, file, line, _PDCLIB_endl ); - abort(); -} diff --git a/src/libraries/libc/j6libc/atomax.c b/src/libraries/libc/j6libc/atomax.c deleted file mode 100644 index 2a7e949..0000000 --- a/src/libraries/libc/j6libc/atomax.c +++ /dev/null @@ -1,25 +0,0 @@ -/* _PDCLIB_atomax( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -intmax_t _PDCLIB_atomax( const char * s ) -{ - intmax_t rc = 0; - char sign = '+'; - const char * x; - /* TODO: In other than "C" locale, additional patterns may be defined */ - while ( isspace( *s ) ) ++s; - if ( *s == '+' ) ++s; - else if ( *s == '-' ) sign = *(s++); - /* TODO: Earlier version was missing tolower() but was not caught by tests */ - while ( ( x = memchr( _PDCLIB_digits, tolower(*(s++)), 10 ) ) != NULL ) - { - rc = rc * 10 + ( x - _PDCLIB_digits ); - } - return ( sign == '+' ) ? rc : -rc; -} diff --git a/src/libraries/libc/j6libc/aux.h b/src/libraries/libc/j6libc/aux.h deleted file mode 100644 index 7d876b8..0000000 --- a/src/libraries/libc/j6libc/aux.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -/* Auxiliary PDCLib code - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* -------------------------------------------------------------------------- */ -/* You should not have to edit anything in this file; if you DO have to, it */ -/* would be considered a bug / missing feature: notify the author(s). */ -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -/* Standard Version */ -/* -------------------------------------------------------------------------- */ - -/* Many a compiler gets this wrong, so you might have to hardcode it instead. */ - -#if __STDC__ != 1 -#error Compiler does not define _ _STDC_ _ to 1 (not standard-compliant)! -#endif - -#ifdef __cplusplus -#define restrict __restrict__ -#endif - -#ifndef __STDC_HOSTED__ -#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)! -#elif __STDC_HOSTED__ == 0 -#define _PDCLIB_HOSTED 0 -#elif __STDC_HOSTED__ == 1 -#define _PDCLIB_HOSTED 1 -#else -#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)! -#endif - -/* -------------------------------------------------------------------------- */ -/* Helper macros: */ -/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending */ -/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */ -/* _PDCLIB_static_assert( e, m ) does a compile-time assertion of expression */ -/* e, with m as the failure message. */ -/* _PDCLIB_TYPE_SIGNED( type ) resolves to true if type is signed. */ -/* _PDCLIB_TWOS_COMPLEMENT( type ) resolves to true if two's complement is */ -/* used for type. */ -/* -------------------------------------------------------------------------- */ - -#define _PDCLIB_cc( x, y ) x ## y -#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y ) - -#define _PDCLIB_static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) } - -#define _PDCLIB_TYPE_SIGNED( type ) (((type) -1) < 0) -#define _PDCLIB_TWOS_COMPLEMENT( type ) ((type) ~ (type) 0 < 0 ) - -#define _PDCLIB_symbol2value( x ) #x -#define _PDCLIB_symbol2string( x ) _PDCLIB_symbol2value( x ) diff --git a/src/libraries/libc/j6libc/close.c b/src/libraries/libc/j6libc/close.c deleted file mode 100644 index 362bae4..0000000 --- a/src/libraries/libc/j6libc/close.c +++ /dev/null @@ -1,16 +0,0 @@ -/* _PDCLIB_close( _PDCLIB_fd_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_close() fit for use with POSIX - kernels. -*/ - -#include "j6libc/glue.h" - -int _PDCLIB_close( int fd ) -{ - return -1; -} diff --git a/src/libraries/libc/j6libc/closeall.c b/src/libraries/libc/j6libc/closeall.c deleted file mode 100644 index 7031a2e..0000000 --- a/src/libraries/libc/j6libc/closeall.c +++ /dev/null @@ -1,21 +0,0 @@ -/* _PDCLIB_closeall( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -void _PDCLIB_closeall( void ) -{ - struct _PDCLIB_file_t * stream = _PDCLIB_filelist; - struct _PDCLIB_file_t * next; - while ( stream != NULL ) - { - next = stream->next; - fclose( stream ); - stream = next; - } -} diff --git a/src/libraries/libc/j6libc/config.h b/src/libraries/libc/j6libc/config.h deleted file mode 100644 index 3913389..0000000 --- a/src/libraries/libc/j6libc/config.h +++ /dev/null @@ -1,336 +0,0 @@ -#pragma once -/* Internal PDCLib configuration - (Generic Template) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -/* -------------------------------------------------------------------------- */ -/* Misc */ -/* -------------------------------------------------------------------------- */ - -/* The character (sequence) your platform uses as newline. */ -#define _PDCLIB_endl "\n" - -/* exit() can signal success to the host environment by the value of zero or */ -/* the constant EXIT_SUCCESS. Failure is signaled by EXIT_FAILURE. Note that */ -/* any other return value is "implementation-defined", i.e. your environment */ -/* is not required to handle it gracefully. Set your definitions here. */ -#define _PDCLIB_SUCCESS 0 -#define _PDCLIB_FAILURE -1 - -/* qsort() in requires a function that swaps two memory areas. */ -/* Below is a naive implementation that can be improved significantly for */ -/* specific platforms, e.g. by swapping int instead of char. */ -#define _PDCLIB_memswp( i, j, size ) char tmp; do { tmp = *i; *i++ = *j; *j++ = tmp; } while ( --size ); - -/* -------------------------------------------------------------------------- */ -/* Integers */ -/* -------------------------------------------------------------------------- */ -/* Assuming 8-bit char, two's-complement architecture here. 'short' being */ -/* 16 bit, 'int' being either 16, 32 or 64 bit, 'long' being either 32 or 64 */ -/* bit (but 64 bit only if 'int' is 32 bit), and 'long long' being 64 bit if */ -/* 'long' is not, 64 or 128 bit otherwise. */ -/* Author is quite willing to support other systems but would like to hear of */ -/* interest in such support and details on the to-be-supported architecture */ -/* first, before going to lengths about it. */ -/* -------------------------------------------------------------------------- */ - -/* Set to 0 if your 'char' type is unsigned. */ -#ifdef __CHAR_UNSIGNED__ -#define _PDCLIB_CHAR_SIGNED 0 -#else -#define _PDCLIB_CHAR_SIGNED 1 -#endif - -/* Width of the integer types short, int, long, and long long, in bytes. */ -/* SHRT == 2, INT >= SHRT, LONG >= INT >= 4, LLONG >= LONG - check your */ -/* compiler manuals. */ -#define _PDCLIB_SHRT_BYTES 2 -#define _PDCLIB_INT_BYTES 4 -#ifdef __LP64__ -#define _PDCLIB_LONG_BYTES 8 -#else -#define _PDCLIB_LONG_BYTES 4 -#endif -#define _PDCLIB_LLONG_BYTES 8 - -/* defines the div() function family that allows taking quotient */ -/* and remainder of an integer division in one operation. Many platforms */ -/* support this in hardware / opcode, and the standard permits ordering of */ -/* the return structure in any way to fit the hardware. That is why those */ -/* structs can be configured here. */ - -struct _PDCLIB_div_t -{ - int quot; - int rem; -}; - -struct _PDCLIB_ldiv_t -{ - long int quot; - long int rem; -}; - -struct _PDCLIB_lldiv_t -{ - long long int quot; - long long int rem; -}; - -/* defines imaxdiv(), which is equivalent to the div() function */ -/* family (see further above) with intmax_t as basis. */ - -struct _PDCLIB_imaxdiv_t -{ - intmax_t quot; - intmax_t rem; -}; - -/* -------------------------------------------------------------------------- */ -/* Time types */ -/* -------------------------------------------------------------------------- */ - -/* See for a couple of comments on these types and their semantics. */ - -#define _PDCLIB_time long - -#define _PDCLIB_clock long -#define _PDCLIB_CLOCKS_PER_SEC 1000000 - -#define _PDCLIB_TIME_UTC 1 - -/* -------------------------------------------------------------------------- */ -/* Floating Point */ -/* -------------------------------------------------------------------------- */ - -/* Whether the implementation rounds toward zero (0), to nearest (1), toward - positive infinity (2), or toward negative infinity (3). (-1) signifies - indeterminable rounding, any other value implementation-specific rounding. -*/ -#define _PDCLIB_FLT_ROUNDS -1 - -/* Whether the implementation uses exact-width precision (0), promotes float - to double (1), or promotes float and double to long double (2). (-1) - signifies indeterminable behaviour, any other value implementation-specific - behaviour. -*/ -#define _PDCLIB_FLT_EVAL_METHOD -1 - -/* "Number of the decimal digits (n), such that any floating-point number in the - widest supported floating type with p(max) radix (b) digits can be rounded to - a floating-point number with (n) decimal digits and back again without change - to the value p(max) log(10)b if (b) is a power of 10, [1 + p(max) log(10)b] - otherwise." - 64bit IEC 60559 double format (53bit mantissa) is DECIMAL_DIG 17. - 80bit IEC 60559 double-extended format (64bit mantissa) is DECIMAL_DIG 21. -*/ -#define _PDCLIB_DECIMAL_DIG 17 - -/* -------------------------------------------------------------------------- */ -/* Platform-dependent macros defined by the standard headers. */ -/* -------------------------------------------------------------------------- */ - -/* The offsetof macro - Contract: Expand to an integer constant expression of type size_t, which - represents the offset in bytes to the structure member from the beginning - of the structure. If the specified member is a bitfield, behaviour is - undefined. - There is no standard-compliant way to do this. - This implementation casts an integer zero to 'pointer to type', and then - takes the address of member. This is undefined behaviour but should work on - most compilers. -*/ -#define _PDCLIB_offsetof( type, member ) ( (size_t) &( ( (type *) 0 )->member ) ) - -/* Variable Length Parameter List Handling () - The macros defined by are highly dependent on the calling - conventions used, and you probably have to replace them with builtins of - your compiler. -*/ - -#if defined( __i386 ) - -/* The following generic implementation works only for pure - stack-based architectures, and only if arguments are aligned to pointer - type. Credits to Michael Moody, who contributed this to the Public Domain. -*/ - -/* Internal helper macro. va_round is not part of . */ -#define _PDCLIB_va_round( type ) ( (sizeof(type) + sizeof(void *) - 1) & ~(sizeof(void *) - 1) ) - -typedef char * _PDCLIB_va_list; -#define _PDCLIB_va_arg( ap, type ) ( (ap) += (_PDCLIB_va_round(type)), ( *(type*) ( (ap) - (_PDCLIB_va_round(type)) ) ) ) -#define _PDCLIB_va_copy( dest, src ) ( (dest) = (src), (void)0 ) -#define _PDCLIB_va_end( ap ) ( (ap) = (void *)0, (void)0 ) -#define _PDCLIB_va_start( ap, parmN ) ( (ap) = (char *) &parmN + ( _PDCLIB_va_round(parmN) ), (void)0 ) - -#elif defined( __x86_64 ) || defined( __arm__ ) - -/* No way to cover x86_64 or arm with a generic implementation, as it uses - register-based parameter passing. Using compiler builtins here. -*/ -typedef __builtin_va_list _PDCLIB_va_list; -#define _PDCLIB_va_arg( ap, type ) ( __builtin_va_arg( ap, type ) ) -#define _PDCLIB_va_copy( dest, src ) ( __builtin_va_copy( dest, src ) ) -#define _PDCLIB_va_end( ap ) ( __builtin_va_end( ap ) ) -#define _PDCLIB_va_start( ap, parmN ) ( __builtin_va_start( ap, parmN ) ) - -#else - -#error Please create your own config.h. Using the existing one as-is will not work. - -#endif - -/* -------------------------------------------------------------------------- */ -/* OS "glue", part 1 */ -/* These are values and data type definitions that you would have to adapt to */ -/* the capabilities and requirements of your OS. */ -/* The actual *functions* of the OS interface are declared in glue.h. */ -/* -------------------------------------------------------------------------- */ - -/* Memory management -------------------------------------------------------- */ - -/* Set this to the page size of your OS. If your OS does not support paging, set - to an appropriate value. (Too small, and malloc() will call the kernel too - often. Too large, and you will waste memory.) -*/ -#define _PDCLIB_PAGESIZE 4096 - -/* Set this to the minimum memory node size. Any malloc() for a smaller size - will be satisfied by a malloc() of this size instead (to avoid excessive - fragmentation). -*/ -#define _PDCLIB_MINALLOC 8 - -/* I/O ---------------------------------------------------------------------- */ - -/* The type of the file descriptor returned by _PDCLIB_open(). */ -typedef int _PDCLIB_fd_t; - -/* The value (of type _PDCLIB_fd_t) returned by _PDCLIB_open() if the operation - failed. -*/ -#define _PDCLIB_NOHANDLE ( (_PDCLIB_fd_t) -1 ) - -/* The default size for file buffers. Must be at least 256. */ -#define _PDCLIB_BUFSIZ 1024 - -/* The minimum number of files the implementation can open simultaneously. Must - be at least 8. Depends largely on how the bookkeeping is done by fopen() / - freopen() / fclose(). The example implementation limits the number of open - files only by available memory. -*/ -#define _PDCLIB_FOPEN_MAX 8 - -/* Length of the longest filename the implementation guarantees to support. */ -#define _PDCLIB_FILENAME_MAX 128 - -/* Maximum length of filenames generated by tmpnam(). (See tmpfile.c.) */ -#define _PDCLIB_L_tmpnam 46 - -/* Number of distinct file names that can be generated by tmpnam(). */ -#define _PDCLIB_TMP_MAX 50 - -/* The values of SEEK_SET, SEEK_CUR and SEEK_END, used by fseek(). - Since at least one platform (POSIX) uses the same symbols for its own "seek" - function, we use whatever the host defines (if it does define them). -*/ -#define _PDCLIB_SEEK_SET 0 -#define _PDCLIB_SEEK_CUR 1 -#define _PDCLIB_SEEK_END 2 - -/* The number of characters that can be buffered with ungetc(). The standard - guarantees only one (1); anything larger would make applications relying on - this capability dependent on implementation-defined behaviour (not good). -*/ -#define _PDCLIB_UNGETCBUFSIZE 1 - -/* errno -------------------------------------------------------------------- */ - -/* These are the values that _PDCLIB_errno can be set to by the library. - - By keeping PDCLib's errno in the _PDCLIB_* namespace, the library is capable - to "translate" between errno values used by the hosting operating system and - those used and passed out by the library. - - Example: In the example platform, the remove() function uses the unlink() - system call as backend. Linux sets its errno to EISDIR if you try to unlink() - a directory, but POSIX demands EPERM. Within the remove() function, you can - catch the 'errno == EISDIR', and set '_PDCLIB_errno = _PDCLIB_EPERM'. Anyone - using PDCLib's will "see" EPERM instead of EISDIR (the _PDCLIB_* - prefix removed by mechanics). - - If you do not want that kind of translation, you might want to "match" the - values used by PDCLib with those used by the host OS, as to avoid confusion. - - The standard only defines three distinct errno values: ERANGE, EDOM, and - EILSEQ. The standard leaves it up to "the implementation" whether there are - any more beyond those three. There is some controversy as to whether errno is - such a good idea at all, so you might want to come up with a different error - reporting facility for your platform. Since errno values beyond the three - defined by the standard are not portable anyway (unless you look at POSIX), - having your own error reporting facility would not hurt anybody either. -*/ -#define _PDCLIB_ERANGE 1 -#define _PDCLIB_EDOM 2 -#define _PDCLIB_EILSEQ 3 -#define _PDCLIB_ENOMEM 12 -#define _PDCLIB_EINVAL 22 - -/* The following is not strictly "configuration", but there is no better place - to explain it than here. - - PDCLib strives to be as generic as possible, so by default it does NOT define - any values beyond the three standard ones above, even where it would have - been prudent and convenient to do so. Any errno "caught" from the host OS, - and some internal error conditions as well, are all lumped together into the - value of '_PDCLIB_ERROR'. - - '_PDCLIB_ERROR' is STRICLY meant as a PLACEHOLDER only. - - You should NEVER ship an adaption of PDCLib still using that particular - value. You should NEVER write code that *tests* for that value. Indeed it is - not even conforming, since errno values should be defined as beginning with - an uppercase 'E', and there is no mechanics in to unmask that - particular value (for exactly that reason). - - There also is no error message available for this value through either the - strerror() or perror() functions. It is being reported as "unknown" error. - - The idea is that you scan the source of PDCLib for occurrences of this macro - and replace _PDCLIB_ERROR with whatever additional errno value you came up - with for your platform. - - If you cannot find it within you to do that, tell your clients to check for - an errno value larger than zero. That, at least, would be standard compliant - (and fully portable). -*/ -#define _PDCLIB_ERROR 4 - -/* The maximum value that errno can be set to. This is used to set the size */ -/* of the array in struct _PDCLIB_lc_text_t holding error messages for the */ -/* strerror() and perror() functions. (If you change this value because you */ -/* are using additional errno values, you *HAVE* to provide appropriate error */ -/* messages for *ALL* locales.) */ -/* Default is 4 (0, ERANGE, EDOM, EILSEQ). */ -#define _PDCLIB_ERRNO_MAX 4 - -/* locale data -------------------------------------------------------------- */ - -/* The default path where PDCLib should look for its locale data. */ -/* Must end with the appropriate separator character. */ -#define _PDCLIB_LOCALE_PATH "/usr/share/pdclib/i18n" - -/* The name of the environment variable that can be used to override that */ -/* path setting. */ -#define _PDCLIB_LOCALE_PATH_ENV PDCLIB_I18N - -#ifdef __CYGWIN__ -typedef unsigned int wint_t; -#endif - diff --git a/src/libraries/libc/j6libc/cpp.h b/src/libraries/libc/j6libc/cpp.h deleted file mode 100644 index b14a5ef..0000000 --- a/src/libraries/libc/j6libc/cpp.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#ifdef __cplusplus -#define CPP_CHECK_BEGIN extern "C" { -#define CPP_CHECK_END } -#else -#define CPP_CHECK_BEGIN -#define CPP_CHECK_END -#endif diff --git a/src/libraries/libc/j6libc/digits.c b/src/libraries/libc/j6libc/digits.c deleted file mode 100644 index 86d4ce9..0000000 --- a/src/libraries/libc/j6libc/digits.c +++ /dev/null @@ -1,12 +0,0 @@ -/* _PDCLIB_digits - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" - -const char _PDCLIB_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - -/* For _PDCLIB/print.c only; obsolete with ctype.h */ -const char _PDCLIB_Xdigits[] = "0123456789ABCDEF"; diff --git a/src/libraries/libc/j6libc/errno.c b/src/libraries/libc/j6libc/errno.c deleted file mode 100644 index 26e8605..0000000 --- a/src/libraries/libc/j6libc/errno.c +++ /dev/null @@ -1,14 +0,0 @@ -/* _PDCLIB_errno - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" - -int _PDCLIB_errno = 0; - -int * _PDCLIB_errno_func() -{ - return &_PDCLIB_errno; -} diff --git a/src/libraries/libc/j6libc/filemode.c b/src/libraries/libc/j6libc/filemode.c deleted file mode 100644 index 0249a14..0000000 --- a/src/libraries/libc/j6libc/filemode.c +++ /dev/null @@ -1,54 +0,0 @@ -/* _PDCLIB_filemode( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -/* Helper function that parses the C-style mode string passed to fopen() into - the PDCLib flags FREAD, FWRITE, FAPPEND, FRW (read-write) and FBIN (binary - mode). -*/ -unsigned int _PDCLIB_filemode( const char * const mode ) -{ - unsigned rc = 0; - size_t i; - switch ( mode[0] ) - { - case 'r': - rc |= _PDCLIB_FREAD; - break; - case 'w': - rc |= _PDCLIB_FWRITE; - break; - case 'a': - rc |= _PDCLIB_FAPPEND | _PDCLIB_FWRITE; - break; - default: - /* Other than read, write, or append - invalid */ - return 0; - } - for ( i = 1; i < 4; ++i ) - { - switch ( mode[i] ) - { - case '+': - if ( rc & _PDCLIB_FRW ) return 0; /* Duplicates are invalid */ - rc |= _PDCLIB_FRW; - break; - case 'b': - if ( rc & _PDCLIB_FBIN ) return 0; /* Duplicates are invalid */ - rc |= _PDCLIB_FBIN; - break; - case '\0': - /* End of mode */ - return rc; - default: - /* Other than read/write or binary - invalid. */ - return 0; - } - } - /* Longer than three chars - invalid. */ - return 0; -} diff --git a/src/libraries/libc/j6libc/fillbuffer.c b/src/libraries/libc/j6libc/fillbuffer.c deleted file mode 100644 index 5176e5f..0000000 --- a/src/libraries/libc/j6libc/fillbuffer.c +++ /dev/null @@ -1,19 +0,0 @@ -/* _PDCLIB_fillbuffer( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_fillbuffer() fit for - use with POSIX kernels. -*/ - -#include -#include "j6libc/glue.h" - -int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) -{ - _PDCLIB_errno = _PDCLIB_ERROR; - stream->status |= _PDCLIB_ERRORFLAG; - return EOF; -} diff --git a/src/libraries/libc/j6libc/flushbuffer.c b/src/libraries/libc/j6libc/flushbuffer.c deleted file mode 100644 index 0ef7b07..0000000 --- a/src/libraries/libc/j6libc/flushbuffer.c +++ /dev/null @@ -1,19 +0,0 @@ -/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_flushbuffer() fit for - use with POSIX kernels. -*/ - -#include -#include "j6libc/glue.h" - -int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ) -{ - _PDCLIB_errno = _PDCLIB_ERROR; - stream->status |= _PDCLIB_ERRORFLAG; - return EOF; -} diff --git a/src/libraries/libc/j6libc/glue.h b/src/libraries/libc/j6libc/glue.h deleted file mode 100644 index 7c817cb..0000000 --- a/src/libraries/libc/j6libc/glue.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -/* OS glue functions declaration - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" - -/* -------------------------------------------------------------------------- */ -/* OS "glue", part 2 */ -/* These are the functions you will have to touch, as they are where PDCLib */ -/* interfaces with the operating system. */ -/* They operate on data types partially defined by config.h. */ -/* -------------------------------------------------------------------------- */ - -/* stdlib.h */ - -/* A system call that terminates the calling process, returning a given status - to the environment. -*/ -_Noreturn void _PDCLIB_Exit( int status ); - -/* A system call that adds n pages of memory to the process heap (if n is - positive), or releases n pages from the process heap (if n is negative). - Return a (void *) pointing to the *former* end-of-heap if successful, NULL - otherwise. -*/ -void * _PDCLIB_allocpages( int n ); - - -/* stdio.h */ - -/* A system call that opens a file identified by name in a given mode. Return - a file descriptor uniquely identifying that file. - (The mode is the return value of the _PDCLIB_filemode() function.) -*/ -_PDCLIB_fd_t _PDCLIB_open( const char * const filename, unsigned int mode ); - -/* A system call that writes a stream's buffer. - Returns 0 on success, EOF on write error. - Sets stream error flags and errno appropriately on error. -*/ -int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ); - -/* A system call that fills a stream's buffer. - Returns 0 on success, EOF on read error / EOF. - Sets stream EOF / error flags and errno appropriately on error. -*/ -int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ); - -/* A system call that repositions within a file. Returns new offset on success, - -1 / errno on error. -*/ -int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, int64_t offset, int whence ); - -/* A system call that closes a file identified by given file descriptor. Return - zero on success, non-zero otherwise. -*/ -int _PDCLIB_close( _PDCLIB_fd_t fd ); - -/* A system call that renames a file from given old name to given new name. - Return zero on success, non-zero otherwise. In case of failure, the file - must still be accessible by old name. Any handling of open files etc. is - done by standard rename() already. -*/ -int _PDCLIB_rename( const char * old, const char * new ); diff --git a/src/libraries/libc/j6libc/int.h b/src/libraries/libc/j6libc/int.h deleted file mode 100644 index fb04780..0000000 --- a/src/libraries/libc/j6libc/int.h +++ /dev/null @@ -1,347 +0,0 @@ -#pragma once -/* PDCLib internal integer logic - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* -------------------------------------------------------------------------- */ -/* You should not have to edit anything in this file; if you DO have to, it */ -/* would be considered a bug / missing feature: notify the author(s). */ -/* -------------------------------------------------------------------------- */ - -#include - -#include "j6libc/config.h" -#include "j6libc/cpp.h" -#include "j6libc/aux.h" -#include "j6libc/int_widths.h" -#include "j6libc/size_t.h" -#include "j6libc/wchar_t.h" - -CPP_CHECK_BEGIN - -/* -------------------------------------------------------------------------- */ -/* Various internals */ -/* -------------------------------------------------------------------------- */ - -/* Flags for representing mode (see fopen()). Note these must fit the same - status field as the _IO?BF flags in and the internal flags below. -*/ -#define _PDCLIB_FREAD 8u -#define _PDCLIB_FWRITE 16u -#define _PDCLIB_FAPPEND 32u -#define _PDCLIB_FRW 64u -#define _PDCLIB_FBIN 128u - -/* Internal flags, made to fit the same status field as the flags above. */ -/* -------------------------------------------------------------------------- */ -/* free() the buffer memory on closing (false for user-supplied buffer) */ -#define _PDCLIB_FREEBUFFER 512u -/* stream has encountered error / EOF */ -#define _PDCLIB_ERRORFLAG 1024u -#define _PDCLIB_EOFFLAG 2048u -/* stream is wide-oriented */ -#define _PDCLIB_WIDESTREAM 4096u -/* stream is byte-oriented */ -#define _PDCLIB_BYTESTREAM 8192u -/* file associated with stream should be remove()d on closing (tmpfile()) */ -#define _PDCLIB_DELONCLOSE 16384u -/* stream handle should not be free()d on close (stdin, stdout, stderr) */ -#define _PDCLIB_STATIC 32768u - -/* Position / status structure for getpos() / fsetpos(). */ -struct _PDCLIB_fpos_t -{ - uint64_t offset; /* File position offset */ - int status; /* Multibyte parsing state (unused, reserved) */ -}; - -/* FILE structure */ -struct _PDCLIB_file_t -{ - _PDCLIB_fd_t handle; /* OS file handle */ - char * buffer; /* Pointer to buffer memory */ - size_t bufsize; /* Size of buffer */ - size_t bufidx; /* Index of current position in buffer */ - size_t bufend; /* Index of last pre-read character in buffer */ - struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */ - size_t ungetidx; /* Number of ungetc()'ed characters */ - unsigned char * ungetbuf; /* ungetc() buffer */ - unsigned int status; /* Status flags; see above */ - /* multibyte parsing status to be added later */ - char * filename; /* Name the current stream has been opened with */ - struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */ -}; - -/* -------------------------------------------------------------------------- */ -/* Various internals */ -/* -------------------------------------------------------------------------- */ - -typedef _PDCLIB_time _PDCLIB_time_t; -typedef _PDCLIB_clock _PDCLIB_clock_t; - -/* -------------------------------------------------------------------------- */ -/* Internal data types */ -/* -------------------------------------------------------------------------- */ - -/* Structure required by both atexit() and exit() for handling atexit functions */ -struct _PDCLIB_exitfunc_t -{ - struct _PDCLIB_exitfunc_t * next; - void (*func)( void ); -}; - -/* Structures required by malloc(), realloc(), and free(). */ -struct _PDCLIB_headnode_t -{ - struct _PDCLIB_memnode_t * first; - struct _PDCLIB_memnode_t * last; -}; - -struct _PDCLIB_memnode_t -{ - size_t size; - struct _PDCLIB_memnode_t * next; -}; - -/* Status structure required by _PDCLIB_print(). */ -struct _PDCLIB_status_t -{ - int base; /* base to which the value shall be converted */ - int_fast32_t flags; /* flags and length modifiers */ - size_t n; /* print: maximum characters to be written */ - /* scan: number matched conversion specifiers */ - size_t i; /* number of characters read/written */ - size_t current;/* chars read/written in the CURRENT conversion */ - char * s; /* *sprintf(): target buffer */ - /* *sscanf(): source string */ - size_t width; /* specified field width */ - int prec; /* specified field precision */ - struct _PDCLIB_file_t * stream; /* *fprintf() / *fscanf() stream */ - _PDCLIB_va_list arg; /* argument stack */ -}; - -/* -------------------------------------------------------------------------- */ -/* Declaration of helper functions (implemented in functions/_PDCLIB). */ -/* -------------------------------------------------------------------------- */ - -/* This is the main function called by atoi(), atol() and atoll(). */ -intmax_t _PDCLIB_atomax( const char * s ); - -/* Two helper functions used by strtol(), strtoul() and long long variants. */ -const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base ); -uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limval, int limdigit, char * sign ); - -/* Digits arrays used by various integer conversion functions */ -extern const char _PDCLIB_digits[]; -extern const char _PDCLIB_Xdigits[]; - -/* The worker for all printf() type of functions. The pointer spec should point - to the introducing '%' of a conversion specifier. The status structure is to - be that of the current printf() function, of which the members n, s, stream - and arg will be preserved; i will be updated; and all others will be trashed - by the function. - Returns a pointer to the first character not parsed as conversion specifier. -*/ -const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status ); - -/* The worker for all scanf() type of functions. The pointer spec should point - to the introducing '%' of a conversion specifier. The status structure is to - be that of the current scanf() function, of which the member stream will be - preserved; n, i, and s will be updated; and all others will be trashed by - the function. - Returns a pointer to the first character not parsed as conversion specifier, - or NULL in case of error. - FIXME: Should distinguish between matching and input error -*/ -const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ); - -/* Parsing any fopen() style filemode string into a number of flags. */ -unsigned int _PDCLIB_filemode( const char * mode ); - -/* Sanity checking and preparing of read buffer, should be called first thing - by any stdio read-data function. - Returns 0 on success, EOF on error. - On error, EOF / error flags and errno are set appropriately. -*/ -int _PDCLIB_prepread( struct _PDCLIB_file_t * stream ); - -/* Sanity checking, should be called first thing by any stdio write-data - function. - Returns 0 on success, EOF on error. - On error, error flags and errno are set appropriately. -*/ -int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream ); - -/* Closing all streams on program exit */ -void _PDCLIB_closeall( void ); - -/* Check if a given year is a leap year. Parameter is offset to 1900. */ -int _PDCLIB_is_leap( int year_offset ); - -/* Read a specified number of lines from a file stream; return a pointer to - allocated memory holding the lines (newlines replaced with zero terminators) - or NULL in case of error. -*/ -char * _PDCLIB_load_lines( struct _PDCLIB_file_t * fh, size_t lines ); - -/* -------------------------------------------------------------------------- */ -/* errno */ -/* -------------------------------------------------------------------------- */ - -/* If PDCLib would call its error number "errno" directly, there would be no way - to catch its value from underlying system calls that also use it (i.e., POSIX - operating systems). That is why we use an internal name, providing a means to - access it through . -*/ -extern int _PDCLIB_errno; - -/* A mechanism for delayed evaluation. (Not sure if this is really necessary, so - no detailed documentation on the "why".) -*/ -int * _PDCLIB_errno_func( void ); - -/* -------------------------------------------------------------------------- */ -/* support */ -/* -------------------------------------------------------------------------- */ - -#define _PDCLIB_LC_ALL 0 -#define _PDCLIB_LC_COLLATE 1 -#define _PDCLIB_LC_CTYPE 2 -#define _PDCLIB_LC_MONETARY 3 -#define _PDCLIB_LC_NUMERIC 4 -#define _PDCLIB_LC_TIME 5 -#define _PDCLIB_LC_MESSAGES 6 -#define _PDCLIB_LC_COUNT 7 - -#define _PDCLIB_CTYPE_ALPHA 1 -#define _PDCLIB_CTYPE_BLANK 2 -#define _PDCLIB_CTYPE_CNTRL 4 -#define _PDCLIB_CTYPE_GRAPH 8 -#define _PDCLIB_CTYPE_PUNCT 16 -#define _PDCLIB_CTYPE_SPACE 32 -#define _PDCLIB_CTYPE_LOWER 64 -#define _PDCLIB_CTYPE_UPPER 128 - -#define _PDCLIB_CHARSET_SIZE ( 1 << __CHAR_BIT__ ) - -struct _PDCLIB_lc_lconv_numeric_t -{ - char * decimal_point; - char * thousands_sep; - char * grouping; -}; - -struct _PDCLIB_lc_lconv_monetary_t -{ - char * mon_decimal_point; - char * mon_thousands_sep; - char * mon_grouping; - char * positive_sign; - char * negative_sign; - char * currency_symbol; - char * int_curr_symbol; - char frac_digits; - char p_cs_precedes; - char n_cs_precedes; - char p_sep_by_space; - char n_sep_by_space; - char p_sign_posn; - char n_sign_posn; - char int_frac_digits; - char int_p_cs_precedes; - char int_n_cs_precedes; - char int_p_sep_by_space; - char int_n_sep_by_space; - char int_p_sign_posn; - char int_n_sign_posn; -}; - -struct _PDCLIB_lc_numeric_monetary_t -{ - struct lconv * lconv; - int numeric_alloced; - int monetary_alloced; -}; - -extern struct _PDCLIB_lc_numeric_monetary_t _PDCLIB_lc_numeric_monetary; - -struct _PDCLIB_lc_collate_t -{ - int alloced; - /* 1..3 code points */ - /* 1..8, 18 collation elements of 3 16-bit integers */ -}; - -extern struct _PDCLIB_lc_collate_t _PDCLIB_lc_collate; - -struct _PDCLIB_lc_ctype_entry_t -{ - uint16_t flags; - unsigned char upper; - unsigned char lower; -}; - -struct _PDCLIB_lc_ctype_t -{ - int alloced; - int digits_low; - int digits_high; - int Xdigits_low; - int Xdigits_high; - int xdigits_low; - int xdigits_high; - struct _PDCLIB_lc_ctype_entry_t * entry; -}; - -extern struct _PDCLIB_lc_ctype_t _PDCLIB_lc_ctype; - -struct _PDCLIB_lc_messages_t -{ - int alloced; - char * errno_texts[_PDCLIB_ERRNO_MAX]; /* strerror() / perror() */ -}; - -extern struct _PDCLIB_lc_messages_t _PDCLIB_lc_messages; - -struct _PDCLIB_lc_time_t -{ - int alloced; - char * month_name_abbr[12]; /* month names, abbreviated */ - char * month_name_full[12]; /* month names, full */ - char * day_name_abbr[7]; /* weekday names, abbreviated */ - char * day_name_full[7]; /* weekday names, full */ - char * date_time_format; /* date / time format for strftime( "%c" ) */ - char * time_format_12h; /* 12-hour time format for strftime( "%r" ) */ - char * date_format; /* date format for strftime( "%x" ) */ - char * time_format; /* time format for strftime( "%X" ) */ - char * am_pm[2]; /* AM / PM designation */ -}; - -extern struct _PDCLIB_lc_time_t _PDCLIB_lc_time; - -struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale ); -struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale ); -struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale ); -struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale ); -struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale ); -struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale ); - -/* -------------------------------------------------------------------------- */ -/* Sanity checks */ -/* -------------------------------------------------------------------------- */ - -_PDCLIB_static_assert( sizeof( short ) == _PDCLIB_SHRT_BYTES, "Compiler disagrees on _PDCLIB_SHRT_BYTES." ); -_PDCLIB_static_assert( sizeof( int ) == _PDCLIB_INT_BYTES, "Compiler disagrees on _PDCLIB_INT_BYTES." ); -_PDCLIB_static_assert( sizeof( long ) == _PDCLIB_LONG_BYTES, "Compiler disagrees on _PDCLIB_LONG_BYTES." ); -_PDCLIB_static_assert( sizeof( long long ) == _PDCLIB_LLONG_BYTES, "Compiler disagrees on _PDCLIB_LLONG_BYTES." ); - -_PDCLIB_static_assert( ( (char)-1 < 0 ) == _PDCLIB_CHAR_SIGNED, "Compiler disagrees on _PDCLIB_CHAR_SIGNED." ); - -_PDCLIB_static_assert( sizeof( sizeof( int ) ) == sizeof( size_t ), "Compiler disagrees on size_t." ); -_PDCLIB_static_assert( sizeof( wchar_t ) == sizeof( L'x' ), "Compiler disagrees on _PDCLIB_wchar." ); -_PDCLIB_static_assert( sizeof( void * ) == sizeof( intptr_t ), "Compiler disagrees on intptr." ); -_PDCLIB_static_assert( sizeof( &_PDCLIB_digits[1] - &_PDCLIB_digits[0] ) == sizeof( ptrdiff_t ), "Compiler disagrees on ptrdiff_t." ); - -CPP_CHECK_END diff --git a/src/libraries/libc/j6libc/int_widths.h b/src/libraries/libc/j6libc/int_widths.h deleted file mode 100644 index 9889c4d..0000000 --- a/src/libraries/libc/j6libc/int_widths.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -/* Type definitions: fixed-width integral types */ - -/* 7.18.1.1 Exact-width integer types. */ - -typedef __INT8_TYPE__ int8_t; -typedef __INT16_TYPE__ int16_t; -typedef __INT32_TYPE__ int32_t; -typedef __INT64_TYPE__ int64_t; - -typedef __UINT8_TYPE__ uint8_t; -typedef __UINT16_TYPE__ uint16_t; -typedef __UINT32_TYPE__ uint32_t; -typedef __UINT64_TYPE__ uint64_t; - -/* 7.18.1.2 Minimum-width integer types */ - -/* You are allowed to add more types here, e.g. int_least24_t. For the standard - types, int_leastN_t is equivalent to the corresponding exact type intN_t by - definition. -*/ - -typedef __INT_LEAST8_TYPE__ int_least8_t; -typedef __INT_LEAST16_TYPE__ int_least16_t; -typedef __INT_LEAST32_TYPE__ int_least32_t; -typedef __INT_LEAST64_TYPE__ int_least64_t; - -typedef __UINT_LEAST8_TYPE__ uint_least8_t; -typedef __UINT_LEAST16_TYPE__ uint_least16_t; -typedef __UINT_LEAST32_TYPE__ uint_least32_t; -typedef __UINT_LEAST64_TYPE__ uint_least64_t; - -/* 7.18.1.3 Fastest minimum-width integer types */ - -/* You are allowed to add more types here, e.g. int_fast24_t. */ - -typedef __INT_FAST8_TYPE__ int_fast8_t; -typedef __INT_FAST16_TYPE__ int_fast16_t; -typedef __INT_FAST32_TYPE__ int_fast32_t; -typedef __INT_FAST64_TYPE__ int_fast64_t; - -typedef __UINT_FAST8_TYPE__ uint_fast8_t; -typedef __UINT_FAST16_TYPE__ uint_fast16_t; -typedef __UINT_FAST32_TYPE__ uint_fast32_t; -typedef __UINT_FAST64_TYPE__ uint_fast64_t; - -/* 7.18.1.4 Integer types capable of holding object pointers */ - -typedef __INTPTR_TYPE__ intptr_t; -typedef __UINTPTR_TYPE__ uintptr_t; -typedef __PTRDIFF_TYPE__ ptrdiff_t; - -/* 7.18.1.5 Greatest-width integer types */ - -typedef __INTMAX_TYPE__ intmax_t; -typedef __UINTMAX_TYPE__ uintmax_t; - diff --git a/src/libraries/libc/j6libc/is_leap.c b/src/libraries/libc/j6libc/is_leap.c deleted file mode 100644 index 97edd5a..0000000 --- a/src/libraries/libc/j6libc/is_leap.c +++ /dev/null @@ -1,14 +0,0 @@ -/* _PDCLIB_is_leap( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" - -int _PDCLIB_is_leap( int year_offset ) -{ - /* year given as offset from 1900, matching tm.tm_year in */ - long long year = year_offset + 1900ll; - return ( ( year % 4 ) == 0 && ( ( year % 25 ) != 0 || ( year % 400 ) == 0 ) ); -} diff --git a/src/libraries/libc/j6libc/load_lc_collate.c b/src/libraries/libc/j6libc/load_lc_collate.c deleted file mode 100644 index b4cc362..0000000 --- a/src/libraries/libc/j6libc/load_lc_collate.c +++ /dev/null @@ -1,44 +0,0 @@ -/* _PDCLIB_load_lc_collate( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include - -#include "j6libc/int.h" - -struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale ) -{ - struct _PDCLIB_lc_collate_t * rc = NULL; - const char * extension = "_collate.dat"; - char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 ); - - if ( file ) - { - FILE * fh; - - strcpy( file, path ); - strcat( file, locale ); - strcat( file, extension ); - - if ( ( fh = fopen( file, "rb" ) ) != NULL ) - { - if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_collate_t ) ) ) != NULL ) - { - /* TODO: Collation data */ - - rc->alloced = 1; - } - - fclose( fh ); - } - - free( file ); - } - - return rc; -} diff --git a/src/libraries/libc/j6libc/load_lc_ctype.c b/src/libraries/libc/j6libc/load_lc_ctype.c deleted file mode 100644 index 6abeb85..0000000 --- a/src/libraries/libc/j6libc/load_lc_ctype.c +++ /dev/null @@ -1,74 +0,0 @@ -/* _PDCLIB_load_lc_ctype( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "j6libc/int.h" - -struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale ) -{ - struct _PDCLIB_lc_ctype_t * rc = NULL; - const char * extension = "_ctype.dat"; - char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 ); - - if ( file ) - { - FILE * fh; - - strcpy( file, path ); - strcat( file, locale ); - strcat( file, extension ); - - if ( ( fh = fopen( file, "rb" ) ) != NULL ) - { - if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_ctype_t ) ) ) != NULL ) - { - struct _PDCLIB_lc_ctype_entry_t * entry; - - if ( ( entry = malloc( sizeof( struct _PDCLIB_lc_ctype_entry_t ) * _PDCLIB_CHARSET_SIZE + 1 ) ) != NULL ) - { - rc->entry = entry + 1; - rc->entry[ -1 ].flags = rc->entry[ -1 ].upper = rc->entry[ -1 ].lower = 0; - - if ( fscanf( fh, "%x %x %x %x %x %x", &rc->digits_low, &_PDCLIB_lc_ctype.digits_high, &_PDCLIB_lc_ctype.Xdigits_low, &_PDCLIB_lc_ctype.Xdigits_high, &_PDCLIB_lc_ctype.xdigits_low, &_PDCLIB_lc_ctype.xdigits_high ) == 6 ) - { - size_t i; - - for ( i = 0; i < _PDCLIB_CHARSET_SIZE; ++i ) - { - if ( fscanf( fh, "%hx %hhx %hhx", &rc->entry[ i ].flags, &rc->entry[ i ].upper, &rc->entry[ i ].lower ) != 3 ) - { - fclose( fh ); - free( file ); - free( rc->entry - 1 ); - free( rc ); - return NULL; - } - } - } - - rc->alloced = 1; - } - else - { - free( rc ); - } - } - - fclose( fh ); - } - - free( file ); - } - - return rc; -} diff --git a/src/libraries/libc/j6libc/load_lc_messages.c b/src/libraries/libc/j6libc/load_lc_messages.c deleted file mode 100644 index b429745..0000000 --- a/src/libraries/libc/j6libc/load_lc_messages.c +++ /dev/null @@ -1,60 +0,0 @@ -/* _PDCLIB_load_lc_messages( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include - -#include "j6libc/int.h" - -struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale ) -{ - struct _PDCLIB_lc_messages_t * rc = NULL; - const char * extension = "_messages.dat"; - char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 ); - - if ( file ) - { - FILE * fh; - - strcpy( file, path ); - strcat( file, locale ); - strcat( file, extension ); - - if ( ( fh = fopen( file, "rb" ) ) != NULL ) - { - if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_messages_t ) ) ) != NULL ) - { - char * data = _PDCLIB_load_lines( fh, _PDCLIB_ERRNO_MAX ); - - if ( data != NULL ) - { - size_t i; - - for ( i = 0; i < _PDCLIB_ERRNO_MAX; ++i ) - { - rc->errno_texts[ i ] = data; - data += strlen( data ) + 1; - } - - rc->alloced = 1; - } - else - { - free( rc ); - rc = NULL; - } - } - - fclose( fh ); - } - - free( file ); - } - - return rc; -} diff --git a/src/libraries/libc/j6libc/load_lc_monetary.c b/src/libraries/libc/j6libc/load_lc_monetary.c deleted file mode 100644 index e0a7d74..0000000 --- a/src/libraries/libc/j6libc/load_lc_monetary.c +++ /dev/null @@ -1,90 +0,0 @@ -/* _PDCLIB_load_lc_monetary( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include -#include - -#include "j6libc/int.h" - -struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale ) -{ - struct _PDCLIB_lc_lconv_monetary_t * rc = NULL; - const char * extension = "_monetary.dat"; - char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 ); - - if ( file ) - { - FILE * fh; - - strcpy( file, path ); - strcat( file, locale ); - strcat( file, extension ); - - if ( ( fh = fopen( file, "rb" ) ) != NULL ) - { - if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_lconv_monetary_t ) ) ) != NULL ) - { - char buffer[ 14 ]; - char * data = _PDCLIB_load_lines( fh, 7 ); - - if ( data != NULL ) - { - if ( fread( buffer, 1, 14, fh ) == 14 ) - { - rc->mon_decimal_point = data; - data += strlen( data ) + 1; - rc->mon_thousands_sep = data; - data += strlen( data ) + 1; - rc->mon_grouping = data; - data += strlen( data ) + 1; - rc->positive_sign = data; - data += strlen( data ) + 1; - rc->negative_sign = data; - data += strlen( data ) + 1; - rc->currency_symbol = data; - data += strlen( data ) + 1; - rc->int_curr_symbol = data; - - rc->frac_digits = buffer[ 0 ]; - rc->p_cs_precedes = buffer[ 1 ]; - rc->n_cs_precedes = buffer[ 2 ]; - rc->p_sep_by_space = buffer[ 3 ]; - rc->n_sep_by_space = buffer[ 4 ]; - rc->p_sign_posn = buffer[ 5 ]; - rc->n_sign_posn = buffer[ 6 ]; - rc->int_frac_digits = buffer[ 7 ]; - rc->int_p_cs_precedes = buffer[ 8 ]; - rc->int_n_cs_precedes = buffer[ 9 ]; - rc->int_p_sep_by_space = buffer[ 10 ]; - rc->int_n_sep_by_space = buffer[ 11 ]; - rc->int_p_sign_posn = buffer[ 12 ]; - rc->int_n_sign_posn= buffer[ 13 ]; - } - else - { - free( data ); - free( rc ); - rc = NULL; - } - } - else - { - free( rc ); - rc = NULL; - } - } - - fclose( fh ); - } - - free( file ); - } - - return rc; -} diff --git a/src/libraries/libc/j6libc/load_lc_numeric.c b/src/libraries/libc/j6libc/load_lc_numeric.c deleted file mode 100644 index 5c5f671..0000000 --- a/src/libraries/libc/j6libc/load_lc_numeric.c +++ /dev/null @@ -1,56 +0,0 @@ -/* _PDCLIB_load_lc_numeric( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include - -#include "j6libc/int.h" - -struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale ) -{ - struct _PDCLIB_lc_lconv_numeric_t * rc = NULL; - const char * extension = "_numeric.dat"; - char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 ); - - if ( file ) - { - FILE * fh; - - strcpy( file, path ); - strcat( file, locale ); - strcat( file, extension ); - - if ( ( fh = fopen( file, "rb" ) ) != NULL ) - { - if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_lconv_numeric_t ) ) ) != NULL ) - { - char * data = _PDCLIB_load_lines( fh, 3 ); - - if ( data != NULL ) - { - rc->decimal_point = data; - data += strlen( data ) + 1; - rc->thousands_sep = data; - data += strlen( data ) + 1; - rc->grouping = data; - } - else - { - free( rc ); - rc = NULL; - } - } - - fclose( fh ); - } - - free( file ); - } - - return rc; -} diff --git a/src/libraries/libc/j6libc/load_lc_time.c b/src/libraries/libc/j6libc/load_lc_time.c deleted file mode 100644 index aa17ab2..0000000 --- a/src/libraries/libc/j6libc/load_lc_time.c +++ /dev/null @@ -1,79 +0,0 @@ -/* _PDCLIB_load_lc_time( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include -#include - -#include "j6libc/int.h" - -struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale ) -{ - struct _PDCLIB_lc_time_t * rc = NULL; - const char * extension = "_time.dat"; - char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 ); - - if ( file ) - { - FILE * fh; - - strcpy( file, path ); - strcat( file, locale ); - strcat( file, extension ); - - if ( ( fh = fopen( file, "rb" ) ) != NULL ) - { - if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_time_t ) ) ) != NULL ) - { - char * data = _PDCLIB_load_lines( fh, 44 ); - - if ( data != NULL ) - { - size_t i; - - for ( i = 0; i < 12; ++i ) - { - rc->month_name_abbr[ i ] = data; - data += strlen( data ) + 1; - } - - for ( i = 0; i < 12; ++i ) - { - rc->month_name_full[ i ] = data; - data += strlen( data ) + 1; - } - - for ( i = 0; i < 7; ++i ) - { - rc->day_name_abbr[ i ] = data; - data += strlen( data ) + 1; - } - - for ( i = 0; i < 7; ++i ) - { - rc->day_name_full[ i ] = data; - data += strlen( data ) + 1; - } - - rc->alloced = 1; - } - else - { - free( rc ); - rc = NULL; - } - } - - fclose( fh ); - } - - free( file ); - } - - return rc; -} diff --git a/src/libraries/libc/j6libc/load_lines.c b/src/libraries/libc/j6libc/load_lines.c deleted file mode 100644 index b61a283..0000000 --- a/src/libraries/libc/j6libc/load_lines.c +++ /dev/null @@ -1,48 +0,0 @@ -/* _PDCLIB_load_lines( FILE *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -char * _PDCLIB_load_lines( FILE * fh, size_t lines ) -{ - size_t required = 0; - long pos = ftell( fh ); - char * rc = NULL; - int c; - - /* Count the number of characters */ - while ( lines && ( c = fgetc( fh ) ) != EOF ) - { - if ( c == '\n' ) - { - --lines; - } - - ++required; - } - - if ( ! feof( fh ) ) - { - if ( ( rc = malloc( required ) ) != NULL ) - { - size_t i; - - fseek( fh, pos, SEEK_SET ); - fread( rc, 1, required, fh ); - - for ( i = 0; i < required; ++i ) - { - if ( rc[ i ] == '\n' ) - { - rc[ i ] = '\0'; - } - } - } - } - - return rc; -} diff --git a/src/libraries/libc/j6libc/max_align_t.h b/src/libraries/libc/j6libc/max_align_t.h deleted file mode 100644 index c847953..0000000 --- a/src/libraries/libc/j6libc/max_align_t.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#if __has_include("__stddef_max_align_t.h") -#include "__stddef_max_align_t.h" -#elif __BIGGEST_ALIGNMENT__ == __SIZEOF_LONG_DOUBLE__ -typedef long double max_align_t; -#elif __BIGGEST_ALIGNMENT__ == __SIZEOF_DOUBLE__ -typedef double max_align_t; -#elif __BIGGEST_ALIGNMENT__ == __SIZEOF_LONG_LONG__ -typedef long long max_align_t; -#else -#error Can't figure out size of max_align_t! -#endif - diff --git a/src/libraries/libc/j6libc/null.h b/src/libraries/libc/j6libc/null.h deleted file mode 100644 index d1d53d9..0000000 --- a/src/libraries/libc/j6libc/null.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -/* Constant definition: NULL */ - -#ifndef NULL -#define NULL 0 -#endif diff --git a/src/libraries/libc/j6libc/open.c b/src/libraries/libc/j6libc/open.c deleted file mode 100644 index c6a2804..0000000 --- a/src/libraries/libc/j6libc/open.c +++ /dev/null @@ -1,17 +0,0 @@ -/* _PDCLIB_open( const char * const, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_open() fit for use with POSIX - kernels. -*/ - -#include "j6libc/glue.h" - -int _PDCLIB_open( const char * const filename, unsigned int mode ) -{ - _PDCLIB_errno = _PDCLIB_ERROR; - return -1; -} diff --git a/src/libraries/libc/j6libc/prepread.c b/src/libraries/libc/j6libc/prepread.c deleted file mode 100644 index c60b34c..0000000 --- a/src/libraries/libc/j6libc/prepread.c +++ /dev/null @@ -1,34 +0,0 @@ -/* _PDCLIB_prepread( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#include "j6libc/glue.h" - -int _PDCLIB_prepread( struct _PDCLIB_file_t * stream ) -{ - if ( ( stream->bufidx > stream->bufend ) || - ( stream->status & ( _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_ERRORFLAG | _PDCLIB_WIDESTREAM | _PDCLIB_EOFFLAG ) ) || - ! ( stream->status & ( _PDCLIB_FREAD | _PDCLIB_FRW ) ) ) - { - /* Function called on illegal (e.g. output) stream. - See comments on implementation-defined errno values in - . - */ - _PDCLIB_errno = _PDCLIB_ERROR; - stream->status |= _PDCLIB_ERRORFLAG; - return EOF; - } - stream->status |= _PDCLIB_FREAD | _PDCLIB_BYTESTREAM; - if ( ( stream->bufidx == stream->bufend ) && ( stream->ungetidx == 0 ) ) - { - return _PDCLIB_fillbuffer( stream ); - } - else - { - return 0; - } -} diff --git a/src/libraries/libc/j6libc/prepwrite.c b/src/libraries/libc/j6libc/prepwrite.c deleted file mode 100644 index 3d9e4b4..0000000 --- a/src/libraries/libc/j6libc/prepwrite.c +++ /dev/null @@ -1,25 +0,0 @@ -/* _PDCLIB_prepwrite( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream ) -{ - if ( ( stream->bufidx < stream->bufend ) || ( stream->ungetidx > 0 ) || - ( stream->status & ( _PDCLIB_FREAD | _PDCLIB_ERRORFLAG | _PDCLIB_WIDESTREAM | _PDCLIB_EOFFLAG ) ) || - ! ( stream->status & ( _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) ) - { - /* Function called on illegal (e.g. input) stream. - See the comments on implementation-defined errno values in - . - */ - _PDCLIB_errno = _PDCLIB_ERROR; - stream->status |= _PDCLIB_ERRORFLAG; - return EOF; - } - stream->status |= _PDCLIB_FWRITE | _PDCLIB_BYTESTREAM; - return 0; -} diff --git a/src/libraries/libc/j6libc/print.c b/src/libraries/libc/j6libc/print.c deleted file mode 100644 index 0057a0d..0000000 --- a/src/libraries/libc/j6libc/print.c +++ /dev/null @@ -1,624 +0,0 @@ -/* _PDCLIB_print( const char *, struct _PDCLIB_status_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include -#include -#include - -/* Using an integer's bits as flags for both the conversion flags and length - modifiers. -*/ -/* FIXME: one too many flags to work on a 16-bit machine, join some (e.g. the - width flags) into a combined field. -*/ -#define E_minus (1<<0) -#define E_plus (1<<1) -#define E_alt (1<<2) -#define E_space (1<<3) -#define E_zero (1<<4) -#define E_done (1<<5) - -#define E_char (1<<6) -#define E_short (1<<7) -#define E_long (1<<8) -#define E_llong (1<<9) -#define E_intmax (1<<10) -#define E_size (1<<11) -#define E_ptrdiff (1<<12) -#define E_pointer (1<<13) - -#define E_ldouble (1<<14) - -#define E_lower (1<<15) -#define E_unsigned (1<<16) - -/* This macro delivers a given character to either a memory buffer or a stream, - depending on the contents of 'status' (struct _PDCLIB_status_t). - x - the character to be delivered - i - pointer to number of characters already delivered in this call - n - pointer to maximum number of characters to be delivered in this call - s - the buffer into which the character shall be delivered -*/ -#define PUT( x ) \ -do { \ - int character = x; \ - if ( status->i < status->n ) { \ - if ( status->stream != NULL ) \ - putc( character, status->stream ); \ - else \ - status->s[status->i] = character; \ - } \ - ++(status->i); \ -} while ( 0 ) - - -static void intformat( intmax_t value, struct _PDCLIB_status_t * status ) -{ - /* At worst, we need two prefix characters (hex prefix). */ - char preface[3] = "\0"; - size_t preidx = 0; - if ( status->prec < 0 ) - { - status->prec = 1; - } - if ( ( status->flags & E_alt ) && ( status->base == 16 || status->base == 8 ) && ( value != 0 ) ) - { - /* Octal / hexadecimal prefix for "%#" conversions */ - preface[ preidx++ ] = '0'; - if ( status->base == 16 ) - { - preface[ preidx++ ] = ( status->flags & E_lower ) ? 'x' : 'X'; - } - } - if ( value < 0 ) - { - /* Negative sign for negative values - at all times. */ - preface[ preidx++ ] = '-'; - } - else if ( ! ( status->flags & E_unsigned ) ) - { - /* plus sign / extra space are only for unsigned conversions */ - if ( status->flags & E_plus ) - { - preface[ preidx++ ] = '+'; - } - else if ( status->flags & E_space ) - { - preface[ preidx++ ] = ' '; - } - } - { - /* At this point, status->current has the number of digits queued up. - Determine if we have a precision requirement to pad those. - */ - size_t prec_pads = ( (size_t)status->prec > status->current ) ? ( (size_t)status->prec - status->current ) : 0; - if ( ! ( status->flags & ( E_minus | E_zero ) ) ) - { - /* Space padding is only done if no zero padding or left alignment - is requested. Calculate the number of characters that WILL be - printed, including any prefixes determined above. - */ - /* The number of characters to be printed, plus prefixes if any. */ - /* This line contained probably the most stupid, time-wasting bug - I've ever perpetrated. Greetings to Samface, DevL, and all - sceners at Breakpoint 2006. - */ - size_t characters = preidx + ( ( status->current > (size_t)status->prec ) ? status->current : (size_t)status->prec ); - if ( status->width > characters ) - { - size_t i; - for ( i = 0; i < status->width - characters; ++i ) - { - PUT( ' ' ); - ++(status->current); - } - } - } - /* Now we did the padding, do the prefixes (if any). */ - preidx = 0; - while ( preface[ preidx ] != '\0' ) - { - PUT( preface[ preidx++ ] ); - ++(status->current); - } - /* Do the precision padding if necessary. */ - while ( prec_pads-- > 0 ) - { - PUT( '0' ); - ++(status->current); - } - if ( ( ! ( status->flags & E_minus ) ) && ( status->flags & E_zero ) ) - { - /* If field is not left aligned, and zero padding is requested, do - so. - */ - while ( status->current < status->width ) - { - PUT( '0' ); - ++(status->current); - } - } - } -} - - -static void int2base( intmax_t value, struct _PDCLIB_status_t * status ) -{ - /* This function recursively converts a given integer value to a character - stream. The conversion is done under the control of a given status struct - and written either to a character string or a stream, depending on that - same status struct. The status struct also keeps the function from exceeding - snprintf() limits, and enables any necessary padding / prefixing of the - output once the number of characters to be printed is known, which happens - at the lowermost recursion level. - */ - - /* Special case: zero value, zero precision -- no output (but padding) */ - if ( status->current == 0 && value == 0 && status->prec == 0 ) - { - intformat( value, status ); - } - else - { - /* Registering the character being printed at the end of the function here - already so it will be taken into account when the deepestmost recursion - does the prefix / padding stuff. - */ - ++(status->current); - if ( ( value / status->base ) != 0 ) - { - /* More digits to be done - recurse deeper */ - int2base( value / status->base, status ); - } - else - { - /* We reached the last digit, the deepest point of our recursion, and - only now know how long the number to be printed actually is. Now we - have to do the sign, prefix, width, and precision padding stuff - before printing the numbers while we resurface from the recursion. - */ - intformat( value, status ); - } - - /* Recursion tail - print the current digit. */ - int digit = value % status->base; - if ( digit < 0 ) - { - digit *= -1; - } - if ( status->flags & E_lower ) - { - /* Lowercase letters. Same array used for strto...(). */ - PUT( _PDCLIB_digits[ digit ] ); - } - else - { - /* Uppercase letters. Array only used here, only 0-F. */ - PUT( _PDCLIB_Xdigits[ digit ] ); - } - } -} - -static void uint2base( uintmax_t value, struct _PDCLIB_status_t * status ) -{ - /* This function recursively converts a given integer value to a character - stream. The conversion is done under the control of a given status struct - and written either to a character string or a stream, depending on that - same status struct. The status struct also keeps the function from exceeding - snprintf() limits, and enables any necessary padding / prefixing of the - output once the number of characters to be printed is known, which happens - at the lowermost recursion level. - */ - - /* Special case: zero value, zero precision -- no output (but padding) */ - if ( status->current == 0 && value == 0 && status->prec == 0 ) - { - intformat( value, status ); - } - else - { - /* Registering the character being printed at the end of the function here - already so it will be taken into account when the deepestmost recursion - does the prefix / padding stuff. - */ - ++(status->current); - if ( ( value / status->base ) != 0 ) - { - /* More digits to be done - recurse deeper */ - uint2base( value / status->base, status ); - } - else - { - /* We reached the last digit, the deepest point of our recursion, and - only now know how long the number to be printed actually is. Now we - have to do the sign, prefix, width, and precision padding stuff - before printing the numbers while we resurface from the recursion. - */ - intformat( value, status ); - } - - /* Recursion tail - print the current digit. */ - int digit = value % status->base; - if ( digit < 0 ) - { - digit *= -1; - } - if ( status->flags & E_lower ) - { - /* Lowercase letters. Same array used for strto...(). */ - PUT( _PDCLIB_digits[ digit ] ); - } - else - { - /* Uppercase letters. Array only used here, only 0-F. */ - PUT( _PDCLIB_Xdigits[ digit ] ); - } - } -} - - -static void stringformat( const char * s, struct _PDCLIB_status_t * status ) -{ - if ( status->flags & E_char ) - { - status->prec = 1; - } - else - { - if ( status->prec < 0 ) - { - status->prec = strlen( s ); - } - else - { - int i; - for ( i = 0; i < status->prec; ++i ) - { - if ( s[i] == 0 ) - { - status->prec = i; - break; - } - } - } - } - if ( ! ( status->flags & E_minus ) && ( status->width > (size_t)status->prec ) ) - { - while ( status->current < ( status->width - status->prec ) ) - { - PUT( ' ' ); - ++(status->current); - } - } - while ( status->prec > 0 ) - { - PUT( *(s++) ); - --(status->prec); - ++(status->current); - } - if ( status->flags & E_minus ) - { - while ( status->width > status->current ) - { - PUT( ' ' ); - ++(status->current); - } - } -} - - -const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status ) -{ - const char * orig_spec = spec; - if ( *(++spec) == '%' ) - { - /* %% -> print single '%' */ - PUT( *spec ); - return ++spec; - } - /* Initializing status structure */ - status->flags = 0; - status->base = 0; - status->current = 0; - status->width = 0; - status->prec = EOF; - - /* First come 0..n flags */ - do - { - switch ( *spec ) - { - case '-': - /* left-aligned output */ - status->flags |= E_minus; - ++spec; - break; - case '+': - /* positive numbers prefixed with '+' */ - status->flags |= E_plus; - ++spec; - break; - case '#': - /* alternative format (leading 0x for hex, 0 for octal) */ - status->flags |= E_alt; - ++spec; - break; - case ' ': - /* positive numbers prefixed with ' ' */ - status->flags |= E_space; - ++spec; - break; - case '0': - /* right-aligned padding done with '0' instead of ' ' */ - status->flags |= E_zero; - ++spec; - break; - default: - /* not a flag, exit flag parsing */ - status->flags |= E_done; - break; - } - } while ( ! ( status->flags & E_done ) ); - - /* Optional field width */ - if ( *spec == '*' ) - { - /* Retrieve width value from argument stack */ - int width = va_arg( status->arg, int ); - if ( width < 0 ) - { - status->flags |= E_minus; - status->width = abs( width ); - } - else - { - status->width = width; - } - ++spec; - } - else - { - /* If a width is given, strtol() will return its value. If not given, - strtol() will return zero. In both cases, endptr will point to the - rest of the conversion specifier - just what we need. - */ - status->width = (int)strtol( spec, (char**)&spec, 10 ); - } - - /* Optional precision */ - if ( *spec == '.' ) - { - ++spec; - if ( *spec == '*' ) - { - /* Retrieve precision value from argument stack. A negative value - is as if no precision is given - as precision is initalized to - EOF (negative), there is no need for testing for negative here. - */ - status->prec = va_arg( status->arg, int ); - ++spec; - } - else - { - char * endptr; - status->prec = (int)strtol( spec, &endptr, 10 ); - if ( spec == endptr ) - { - /* Decimal point but no number - equals zero */ - status->prec = 0; - } - spec = endptr; - } - /* Having a precision cancels out any zero flag. */ - status->flags &= ~E_zero; - } - - /* Optional length modifier - We step one character ahead in any case, and step back only if we find - there has been no length modifier (or step ahead another character if it - has been "hh" or "ll"). - */ - switch ( *(spec++) ) - { - case 'h': - if ( *spec == 'h' ) - { - /* hh -> char */ - status->flags |= E_char; - ++spec; - } - else - { - /* h -> short */ - status->flags |= E_short; - } - break; - case 'l': - if ( *spec == 'l' ) - { - /* ll -> long long */ - status->flags |= E_llong; - ++spec; - } - else - { - /* k -> long */ - status->flags |= E_long; - } - break; - case 'j': - /* j -> intmax_t, which might or might not be long long */ - status->flags |= E_intmax; - break; - case 'z': - /* z -> size_t, which might or might not be unsigned int */ - status->flags |= E_size; - break; - case 't': - /* t -> ptrdiff_t, which might or might not be long */ - status->flags |= E_ptrdiff; - break; - case 'L': - /* L -> long double */ - status->flags |= E_ldouble; - break; - default: - --spec; - break; - } - - /* Conversion specifier */ - switch ( *spec ) - { - case 'd': - /* FALLTHROUGH */ - case 'i': - status->base = 10; - break; - case 'o': - status->base = 8; - status->flags |= E_unsigned; - break; - case 'u': - status->base = 10; - status->flags |= E_unsigned; - break; - case 'x': - status->base = 16; - status->flags |= ( E_lower | E_unsigned ); - break; - case 'X': - status->base = 16; - status->flags |= E_unsigned; - break; - case 'f': - case 'F': - case 'e': - case 'E': - case 'g': - case 'G': - break; - case 'a': - case 'A': - break; - case 'c': - /* TODO: wide chars. */ - { - char c[1]; - c[0] = (char)va_arg( status->arg, int ); - status->flags |= E_char; - stringformat( c, status ); - return ++spec; - } - case 's': - /* TODO: wide chars. */ - stringformat( va_arg( status->arg, char * ), status ); - return ++spec; - case 'p': - status->base = 16; - status->flags |= ( E_lower | E_unsigned | E_alt | E_pointer ); - break; - case 'n': - { - int * val = va_arg( status->arg, int * ); - *val = status->i; - return ++spec; - } - default: - /* No conversion specifier. Bad conversion. */ - return orig_spec; - } - - /* Do the actual output based on our findings */ - if ( status->base != 0 ) - { - /* Integer conversions */ - /* TODO: Check for invalid flag combinations. */ - if ( status->flags & E_unsigned ) - { - uintmax_t value; - switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_size | E_pointer | E_intmax ) ) - { - case E_char: - value = (uintmax_t)(unsigned char)va_arg( status->arg, int ); - break; - case E_short: - value = (uintmax_t)(unsigned short)va_arg( status->arg, int ); - break; - case 0: - value = (uintmax_t)va_arg( status->arg, unsigned int ); - break; - case E_long: - value = (uintmax_t)va_arg( status->arg, unsigned long ); - break; - case E_llong: - value = (uintmax_t)va_arg( status->arg, unsigned long long ); - break; - case E_size: - value = (uintmax_t)va_arg( status->arg, size_t ); - break; - case E_pointer: - value = (uintmax_t)(uintptr_t)va_arg( status->arg, void * ); - break; - case E_intmax: - value = va_arg( status->arg, uintmax_t ); - break; - default: - puts( "UNSUPPORTED PRINTF FLAG COMBINATION" ); - return NULL; - } - uint2base(value, status); - } - else - { - intmax_t value; - switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_intmax ) ) - { - case E_char: - value = (intmax_t)(char)va_arg( status->arg, int ); - break; - case E_short: - value = (intmax_t)(short)va_arg( status->arg, int ); - break; - case 0: - value = (intmax_t)va_arg( status->arg, int ); - break; - case E_long: - value = (intmax_t)va_arg( status->arg, long ); - break; - case E_llong: - value = (intmax_t)va_arg( status->arg, long long ); - break; - case E_ptrdiff: - value = (intmax_t)va_arg( status->arg, ptrdiff_t ); - break; - case E_intmax: - value = va_arg( status->arg, intmax_t ); - break; - default: - puts( "UNSUPPORTED PRINTF FLAG COMBINATION" ); - return NULL; - } - int2base(value, status); - } - if ( status->flags & E_minus ) - { - while ( status->current < status->width ) - { - PUT( ' ' ); - ++(status->current); - } - } - if ( status->i >= status->n && status->n > 0 ) - { - status->s[status->n - 1] = '\0'; - } - } - return ++spec; -} diff --git a/src/libraries/libc/j6libc/rename.c b/src/libraries/libc/j6libc/rename.c deleted file mode 100644 index dfafd2c..0000000 --- a/src/libraries/libc/j6libc/rename.c +++ /dev/null @@ -1,18 +0,0 @@ -/* _PDCLIB_rename( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_rename() fit for use with - POSIX kernels. - */ - -#include -#include "j6libc/glue.h" - -int _PDCLIB_rename( const char * old, const char * new ) -{ - _PDCLIB_errno = _PDCLIB_ERROR; - return EOF; -} diff --git a/src/libraries/libc/j6libc/sbrk.c b/src/libraries/libc/j6libc/sbrk.c deleted file mode 100644 index e1c9572..0000000 --- a/src/libraries/libc/j6libc/sbrk.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -//void *sbrk(intptr_t) __attribute__ ((weak)); - -static j6_handle_t __core_handle = j6_handle_invalid; -static intptr_t __core_size = 0; - -static const uintptr_t __core_base = 0x1c0000000; - -static const void *error_val = (void*)-1; - -void *sbrk(intptr_t i) -{ - if (i == 0) - return (void*)__core_base; - - if (__core_size == 0) { - if (i < 0) - return (void*)-1; - - j6_status_t result = j6_vma_create_map(&__core_handle, i, __core_base, 1); - if (result != j6_status_ok) - return (void*)-1; - - __core_size = i; - return (void*)__core_base; - } - - size_t new_size = __core_size + i; - j6_status_t result = j6_vma_resize(__core_handle, &new_size); - if (result != j6_status_ok) - return (void*)-1; - - uintptr_t prev = __core_base + __core_size; - __core_size += i; - - return (void*)prev; -} diff --git a/src/libraries/libc/j6libc/scan.c b/src/libraries/libc/j6libc/scan.c deleted file mode 100644 index 7fbd4df..0000000 --- a/src/libraries/libc/j6libc/scan.c +++ /dev/null @@ -1,595 +0,0 @@ -/* _PDCLIB_scan( const char *, struct _PDCLIB_status_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Using an integer's bits as flags for both the conversion flags and length - modifiers. -*/ -#define E_suppressed 1<<0 -#define E_char 1<<6 -#define E_short 1<<7 -#define E_long 1<<8 -#define E_llong 1<<9 -#define E_intmax 1<<10 -#define E_size 1<<11 -#define E_ptrdiff 1<<12 -#define E_pointer 1<<13 -#define E_ldouble 1<<14 -#define E_unsigned 1<<16 - - -/* Helper function to get a character from the string or stream, whatever is - used for input. When reading from a string, returns EOF on end-of-string - so that handling of the return value can be uniform for both streams and - strings. -*/ -static int GET( struct _PDCLIB_status_t * status ) -{ - int rc = EOF; - if ( status->stream != NULL ) - { - rc = getc( status->stream ); - } - else - { - rc = ( *status->s == '\0' ) ? EOF : (unsigned char)*((status->s)++); - } - if ( rc != EOF ) - { - ++(status->i); - ++(status->current); - } - return rc; -} - - -/* Helper function to put a read character back into the string or stream, - whatever is used for input. -*/ -static void UNGET( int c, struct _PDCLIB_status_t * status ) -{ - if ( status->stream != NULL ) - { - ungetc( c, status->stream ); /* TODO: Error? */ - } - else - { - --(status->s); - } - --(status->i); - --(status->current); -} - - -/* Helper function to check if a character is part of a given scanset */ -static int IN_SCANSET( const char * scanlist, const char * end_scanlist, int rc ) -{ - /* SOLAR */ - int previous = -1; - while ( scanlist != end_scanlist ) - { - if ( ( *scanlist == '-' ) && ( previous != -1 ) ) - { - /* possible scangroup ("a-z") */ - if ( ++scanlist == end_scanlist ) - { - /* '-' at end of scanlist does not describe a scangroup */ - return rc == '-'; - } - while ( ++previous <= (unsigned char)*scanlist ) - { - if ( previous == rc ) - { - return 1; - } - } - previous = -1; - } - else - { - /* not a scangroup, check verbatim */ - if ( rc == (unsigned char)*scanlist ) - { - return 1; - } - previous = (unsigned char)(*scanlist++); - } - } - return 0; -} - - -const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) -{ - /* generic input character */ - int rc; - const char * prev_spec; - const char * orig_spec = spec; - int value_parsed; - if ( *(++spec) == '%' ) - { - /* %% -> match single '%' */ - rc = GET( status ); - switch ( rc ) - { - case EOF: - /* input error */ - if ( status->n == 0 ) - { - status->n = -1; - } - return NULL; - case '%': - return ++spec; - default: - UNGET( rc, status ); - break; - } - } - /* Initializing status structure */ - status->flags = 0; - status->base = -1; - status->current = 0; - status->width = 0; - status->prec = 0; - - /* '*' suppresses assigning parsed value to variable */ - if ( *spec == '*' ) - { - status->flags |= E_suppressed; - ++spec; - } - - /* If a width is given, strtol() will return its value. If not given, - strtol() will return zero. In both cases, endptr will point to the - rest of the conversion specifier - just what we need. - */ - prev_spec = spec; - status->width = (int)strtol( spec, (char**)&spec, 10 ); - if ( spec == prev_spec ) - { - status->width = SIZE_MAX; - } - - /* Optional length modifier - We step one character ahead in any case, and step back only if we find - there has been no length modifier (or step ahead another character if it - has been "hh" or "ll"). - */ - switch ( *(spec++) ) - { - case 'h': - if ( *spec == 'h' ) - { - /* hh -> char */ - status->flags |= E_char; - ++spec; - } - else - { - /* h -> short */ - status->flags |= E_short; - } - break; - case 'l': - if ( *spec == 'l' ) - { - /* ll -> long long */ - status->flags |= E_llong; - ++spec; - } - else - { - /* l -> long */ - status->flags |= E_long; - } - break; - case 'j': - /* j -> intmax_t, which might or might not be long long */ - status->flags |= E_intmax; - break; - case 'z': - /* z -> size_t, which might or might not be unsigned int */ - status->flags |= E_size; - break; - case 't': - /* t -> ptrdiff_t, which might or might not be long */ - status->flags |= E_ptrdiff; - break; - case 'L': - /* L -> long double */ - status->flags |= E_ldouble; - break; - default: - --spec; - break; - } - - /* Conversion specifier */ - - /* whether valid input had been parsed */ - value_parsed = 0; - - switch ( *spec ) - { - case 'd': - status->base = 10; - break; - case 'i': - status->base = 0; - break; - case 'o': - status->base = 8; - status->flags |= E_unsigned; - break; - case 'u': - status->base = 10; - status->flags |= E_unsigned; - break; - case 'x': - status->base = 16; - status->flags |= E_unsigned; - break; - case 'f': - case 'F': - case 'e': - case 'E': - case 'g': - case 'G': - case 'a': - case 'A': - break; - case 'c': - { - char * c = va_arg( status->arg, char * ); - /* for %c, default width is one */ - if ( status->width == SIZE_MAX ) - { - status->width = 1; - } - /* reading until width reached or input exhausted */ - while ( ( status->current < status->width ) && - ( ( rc = GET( status ) ) != EOF ) ) - { - *(c++) = rc; - value_parsed = 1; - } - /* width or input exhausted */ - if ( value_parsed ) - { - ++status->n; - return ++spec; - } - else - { - /* input error, no character read */ - if ( status->n == 0 ) - { - status->n = -1; - } - return NULL; - } - } - case 's': - { - char * c = va_arg( status->arg, char * ); - while ( ( status->current < status->width ) && - ( ( rc = GET( status ) ) != EOF ) ) - { - if ( isspace( rc ) ) - { - UNGET( rc, status ); - if ( value_parsed ) - { - /* matching sequence terminated by whitespace */ - *c = '\0'; - ++status->n; - return ++spec; - } - else - { - /* matching error */ - return NULL; - } - } - else - { - /* match */ - value_parsed = 1; - *(c++) = rc; - } - } - /* width or input exhausted */ - if ( value_parsed ) - { - *c = '\0'; - ++status->n; - return ++spec; - } - else - { - /* input error, no character read */ - if ( status->n == 0 ) - { - status->n = -1; - } - return NULL; - } - } - case '[': - { - const char * endspec = spec; - int negative_scanlist = 0; - char * c; - if ( *(++endspec) == '^' ) - { - negative_scanlist = 1; - ++endspec; - } - spec = endspec; - do - { - /* TODO: This can run beyond a malformed format string */ - ++endspec; - } while ( *endspec != ']' ); - /* read according to scanlist, equiv. to %s above */ - c = va_arg( status->arg, char * ); - while ( ( status->current < status->width ) && - ( ( rc = GET( status ) ) != EOF ) ) - { - if ( negative_scanlist ) - { - if ( IN_SCANSET( spec, endspec, rc ) ) - { - UNGET( rc, status ); - break; - } - } - else - { - if ( ! IN_SCANSET( spec, endspec, rc ) ) - { - UNGET( rc, status ); - break; - } - } - value_parsed = 1; - *(c++) = rc; - } - if ( value_parsed ) - { - *c = '\0'; - ++status->n; - return ++endspec; - } - else - { - if ( rc == EOF ) - { - status->n = -1; - } - return NULL; - } - } - case 'p': - status->base = 16; - status->flags |= E_pointer; - break; - case 'n': - { - int * val = va_arg( status->arg, int * ); - *val = status->i; - return ++spec; - } - default: - /* No conversion specifier. Bad conversion. */ - return orig_spec; - } - - if ( status->base != -1 ) - { - /* integer conversion */ - uintmax_t value = 0; /* absolute value read */ - int prefix_parsed = 0; - int sign = 0; - while ( ( status->current < status->width ) && - ( ( rc = GET( status ) ) != EOF ) ) - { - if ( isspace( rc ) ) - { - if ( sign ) - { - /* matching sequence terminated by whitespace */ - UNGET( rc, status ); - break; - } - else - { - /* leading whitespace not counted against width */ - status->current--; - } - } - else if ( ! sign ) - { - /* no sign parsed yet */ - switch ( rc ) - { - case '-': - sign = -1; - break; - case '+': - sign = 1; - break; - default: - /* not a sign; put back character */ - sign = 1; - UNGET( rc, status ); - break; - } - } - else if ( ! prefix_parsed ) - { - /* no prefix (0x... for hex, 0... for octal) parsed yet */ - prefix_parsed = 1; - if ( rc != '0' ) - { - /* not a prefix; if base not yet set, set to decimal */ - if ( status->base == 0 ) - { - status->base = 10; - } - UNGET( rc, status ); - } - else - { - /* starts with zero, so it might be a prefix. */ - /* check what follows next (might be 0x...) */ - if ( ( status->current < status->width ) && - ( ( rc = GET( status ) ) != EOF ) ) - { - if ( tolower( rc ) == 'x' ) - { - /* 0x... would be prefix for hex base... */ - if ( ( status->base == 0 ) || - ( status->base == 16 ) ) - { - status->base = 16; - } - else - { - /* ...unless already set to other value */ - UNGET( rc, status ); - value_parsed = 1; - } - } - else - { - /* 0... but not 0x.... would be octal prefix */ - UNGET( rc, status ); - if ( status->base == 0 ) - { - status->base = 8; - } - /* in any case we have read a zero */ - value_parsed = 1; - } - } - else - { - /* failed to read beyond the initial zero */ - value_parsed = 1; - break; - } - } - } - else - { - char * digitptr = memchr( _PDCLIB_digits, tolower( rc ), status->base ); - if ( digitptr == NULL ) - { - /* end of input item */ - UNGET( rc, status ); - break; - } - value *= status->base; - value += digitptr - _PDCLIB_digits; - value_parsed = 1; - } - } - /* width or input exhausted, or non-matching character */ - if ( ! value_parsed ) - { - /* out of input before anything could be parsed - input error */ - /* FIXME: if first character does not match, value_parsed is not set - but it is NOT an input error */ - if ( ( status->n == 0 ) && ( rc == EOF ) ) - { - status->n = -1; - } - return NULL; - } - /* convert value to target type and assign to parameter */ - if ( ! ( status->flags & E_suppressed ) ) - { - switch ( status->flags & ( E_char | E_short | E_long | E_llong | - E_intmax | E_size | E_ptrdiff | E_pointer | - E_unsigned ) ) - { - case E_char: - *( va_arg( status->arg, char * ) ) = (char)( value * sign ); - break; - case E_char | E_unsigned: - *( va_arg( status->arg, unsigned char * ) ) = (unsigned char)( value * sign ); - break; - - case E_short: - *( va_arg( status->arg, short * ) ) = (short)( value * sign ); - break; - case E_short | E_unsigned: - *( va_arg( status->arg, unsigned short * ) ) = (unsigned short)( value * sign ); - break; - - case 0: - *( va_arg( status->arg, int * ) ) = (int)( value * sign ); - break; - case E_unsigned: - *( va_arg( status->arg, unsigned int * ) ) = (unsigned int)( value * sign ); - break; - - case E_long: - *( va_arg( status->arg, long * ) ) = (long)( value * sign ); - break; - case E_long | E_unsigned: - *( va_arg( status->arg, unsigned long * ) ) = (unsigned long)( value * sign ); - break; - - case E_llong: - *( va_arg( status->arg, long long * ) ) = (long long)( value * sign ); - break; - case E_llong | E_unsigned: - *( va_arg( status->arg, unsigned long long * ) ) = (unsigned long long)( value * sign ); - break; - - case E_intmax: - *( va_arg( status->arg, intmax_t * ) ) = (intmax_t)( value * sign ); - break; - case E_intmax | E_unsigned: - *( va_arg( status->arg, uintmax_t * ) ) = (uintmax_t)( value * sign ); - break; - - case E_size: - /* E_size always implies unsigned */ - *( va_arg( status->arg, size_t * ) ) = (size_t)( value * sign ); - break; - - case E_ptrdiff: - /* E_ptrdiff always implies signed */ - *( va_arg( status->arg, ptrdiff_t * ) ) = (ptrdiff_t)( value * sign ); - break; - - case E_pointer: - /* E_pointer always implies unsigned */ - *( uintptr_t* )( va_arg( status->arg, void * ) ) = (uintptr_t)( value * sign ); - break; - - default: - puts( "UNSUPPORTED SCANF FLAG COMBINATION" ); - return NULL; /* behaviour unspecified */ - } - ++(status->n); - } - return ++spec; - } - /* TODO: Floats. */ - return NULL; -} diff --git a/src/libraries/libc/j6libc/seed.c b/src/libraries/libc/j6libc/seed.c deleted file mode 100644 index e1df6f9..0000000 --- a/src/libraries/libc/j6libc/seed.c +++ /dev/null @@ -1,7 +0,0 @@ -/* _PDCLIB_seed - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -unsigned long int _PDCLIB_seed = 1; diff --git a/src/libraries/libc/j6libc/seek.c b/src/libraries/libc/j6libc/seek.c deleted file mode 100644 index 70834fc..0000000 --- a/src/libraries/libc/j6libc/seek.c +++ /dev/null @@ -1,18 +0,0 @@ -/* int64_t _PDCLIB_seek( FILE *, int64_t, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_seek() fit for use with POSIX - kernels. - */ - -#include -#include "j6libc/glue.h" - -int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, int64_t offset, int whence ) -{ - _PDCLIB_errno = _PDCLIB_ERROR; - return EOF; -} diff --git a/src/libraries/libc/j6libc/sig_atomic_t.h b/src/libraries/libc/j6libc/sig_atomic_t.h deleted file mode 100644 index 4bce55c..0000000 --- a/src/libraries/libc/j6libc/sig_atomic_t.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -/* Type definition: sig_atomic_t */ - -#if __is_identifier(sig_atomic_t) -#if __SIG_ATOMIC_WIDTH__ == 16 -typedef int16_t sig_atomic_t; -#elif __SIG_ATOMIC_WIDTH__ == 32 -typedef int32_t sig_atomic_t; -#elif __SIG_ATOMIC_WIDTH__ == 64 -typedef int64_t sig_atomic_t; -#else -#error "Unknown size of sig_atomic_t" __SIG_ATOMIC_WIDTH__ -#endif -#endif diff --git a/src/libraries/libc/j6libc/size_t.h b/src/libraries/libc/j6libc/size_t.h deleted file mode 100644 index d698f18..0000000 --- a/src/libraries/libc/j6libc/size_t.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -/* Type definition: size_t */ - -#if __is_identifier(size_t) -typedef __SIZE_TYPE__ size_t; -#endif diff --git a/src/libraries/libc/j6libc/stdinit.c b/src/libraries/libc/j6libc/stdinit.c deleted file mode 100644 index e2b408d..0000000 --- a/src/libraries/libc/j6libc/stdinit.c +++ /dev/null @@ -1,412 +0,0 @@ -/* _PDCLIB_stdinit - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example initialization of stdin, stdout and stderr to the integer - file descriptors 0, 1, and 2, respectively. This applies for a great variety - of operating systems, including POSIX compliant ones. -*/ - -#include -#include -#include - -/* In a POSIX system, stdin / stdout / stderr are equivalent to the (int) file - descriptors 0, 1, and 2 respectively. -*/ -/* TODO: This is proof-of-concept, requires finetuning. */ -static char _PDCLIB_sin_buffer[BUFSIZ]; -static char _PDCLIB_sout_buffer[BUFSIZ]; -static char _PDCLIB_serr_buffer[BUFSIZ]; - -static unsigned char _PDCLIB_sin_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; - -static struct _PDCLIB_file_t _PDCLIB_serr = { 2, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; -static struct _PDCLIB_file_t _PDCLIB_sout = { 1, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; -static struct _PDCLIB_file_t _PDCLIB_sin = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; - -struct _PDCLIB_file_t * stdin = &_PDCLIB_sin; -struct _PDCLIB_file_t * stdout = &_PDCLIB_sout; -struct _PDCLIB_file_t * stderr = &_PDCLIB_serr; - -/* FIXME: This approach is a possible attack vector. */ -struct _PDCLIB_file_t * _PDCLIB_filelist = &_PDCLIB_sin; - -/* "C" locale - defaulting to ASCII-7. - 1 kByte (+ 4 byte) of data. - Each line: flags, lowercase, uppercase, collation. -*/ -static struct _PDCLIB_lc_ctype_entry_t _ctype_entries[ _PDCLIB_CHARSET_SIZE + 1 ] = { - { /* EOF */ 0, 0, 0 }, - { /* NUL */ _PDCLIB_CTYPE_CNTRL, 0x00, 0x00 }, - { /* SOH */ _PDCLIB_CTYPE_CNTRL, 0x01, 0x01 }, - { /* STX */ _PDCLIB_CTYPE_CNTRL, 0x02, 0x02 }, - { /* ETX */ _PDCLIB_CTYPE_CNTRL, 0x03, 0x03 }, - { /* EOT */ _PDCLIB_CTYPE_CNTRL, 0x04, 0x04 }, - { /* ENQ */ _PDCLIB_CTYPE_CNTRL, 0x05, 0x05 }, - { /* ACK */ _PDCLIB_CTYPE_CNTRL, 0x06, 0x06 }, - { /* BEL */ _PDCLIB_CTYPE_CNTRL, 0x07, 0x07 }, - { /* BS */ _PDCLIB_CTYPE_CNTRL, 0x08, 0x08 }, - { /* HT */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_BLANK | _PDCLIB_CTYPE_SPACE, 0x09, 0x09 }, - { /* LF */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0A, 0x0A }, - { /* VT */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0B, 0x0B }, - { /* FF */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0C, 0x0C }, - { /* CR */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0D, 0x0D }, - { /* SO */ _PDCLIB_CTYPE_CNTRL, 0x0E, 0x0E }, - { /* SI */ _PDCLIB_CTYPE_CNTRL, 0x0F, 0x0F }, - { /* DLE */ _PDCLIB_CTYPE_CNTRL, 0x10, 0x10 }, - { /* DC1 */ _PDCLIB_CTYPE_CNTRL, 0x11, 0x11 }, - { /* DC2 */ _PDCLIB_CTYPE_CNTRL, 0x12, 0x12 }, - { /* DC3 */ _PDCLIB_CTYPE_CNTRL, 0x13, 0x13 }, - { /* DC4 */ _PDCLIB_CTYPE_CNTRL, 0x14, 0x14 }, - { /* NAK */ _PDCLIB_CTYPE_CNTRL, 0x15, 0x15 }, - { /* SYN */ _PDCLIB_CTYPE_CNTRL, 0x16, 0x16 }, - { /* ETB */ _PDCLIB_CTYPE_CNTRL, 0x17, 0x17 }, - { /* CAN */ _PDCLIB_CTYPE_CNTRL, 0x18, 0x18 }, - { /* EM */ _PDCLIB_CTYPE_CNTRL, 0x19, 0x19 }, - { /* SUB */ _PDCLIB_CTYPE_CNTRL, 0x1A, 0x1A }, - { /* ESC */ _PDCLIB_CTYPE_CNTRL, 0x1B, 0x1B }, - { /* FS */ _PDCLIB_CTYPE_CNTRL, 0x1C, 0x1C }, - { /* GS */ _PDCLIB_CTYPE_CNTRL, 0x1D, 0x1D }, - { /* RS */ _PDCLIB_CTYPE_CNTRL, 0x1E, 0x1E }, - { /* US */ _PDCLIB_CTYPE_CNTRL, 0x1F, 0x1F }, - { /* SP */ _PDCLIB_CTYPE_BLANK | _PDCLIB_CTYPE_SPACE, 0x20, 0x20 }, - { /* '!' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x21, 0x21 }, - { /* '"' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x22, 0x22 }, - { /* '#' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x23, 0x23 }, - { /* '$' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x24, 0x24 }, - { /* '%' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x25, 0x25 }, - { /* '&' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x26, 0x26 }, - { /* ''' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x27, 0x27 }, - { /* '(' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x28, 0x28 }, - { /* ')' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x29, 0x29 }, - { /* '*' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2A, 0x2A }, - { /* '+' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2B, 0x2B }, - { /* ',' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2C, 0x2C }, - { /* '-' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2D, 0x2D }, - { /* '.' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2E, 0x2E }, - { /* '/' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2F, 0x2F }, - { /* '0' */ _PDCLIB_CTYPE_GRAPH, 0x30, 0x30 }, - { /* '1' */ _PDCLIB_CTYPE_GRAPH, 0x31, 0x31 }, - { /* '2' */ _PDCLIB_CTYPE_GRAPH, 0x32, 0x32 }, - { /* '3' */ _PDCLIB_CTYPE_GRAPH, 0x33, 0x33 }, - { /* '4' */ _PDCLIB_CTYPE_GRAPH, 0x34, 0x34 }, - { /* '5' */ _PDCLIB_CTYPE_GRAPH, 0x35, 0x35 }, - { /* '6' */ _PDCLIB_CTYPE_GRAPH, 0x36, 0x36 }, - { /* '7' */ _PDCLIB_CTYPE_GRAPH, 0x37, 0x37 }, - { /* '8' */ _PDCLIB_CTYPE_GRAPH, 0x38, 0x38 }, - { /* '9' */ _PDCLIB_CTYPE_GRAPH, 0x39, 0x39 }, - { /* ':' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3A, 0x3A }, - { /* ';' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3B, 0x3B }, - { /* '<' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3C, 0x3C }, - { /* '=' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3D, 0x3D }, - { /* '>' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3E, 0x3E }, - { /* '?' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3F, 0x3F }, - { /* '@' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x40, 0x40 }, - { /* 'A' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x41, 0x61 }, - { /* 'B' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x42, 0x62 }, - { /* 'C' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x43, 0x63 }, - { /* 'D' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x44, 0x64 }, - { /* 'E' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x45, 0x65 }, - { /* 'F' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x46, 0x66 }, - { /* 'G' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x47, 0x67 }, - { /* 'H' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x48, 0x68 }, - { /* 'I' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x49, 0x69 }, - { /* 'J' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4A, 0x6A }, - { /* 'K' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4B, 0x6B }, - { /* 'L' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4C, 0x6C }, - { /* 'M' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4D, 0x6D }, - { /* 'N' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4E, 0x6E }, - { /* 'O' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4F, 0x6F }, - { /* 'P' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x50, 0x70 }, - { /* 'Q' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x51, 0x71 }, - { /* 'R' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x52, 0x72 }, - { /* 'S' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x53, 0x73 }, - { /* 'T' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x54, 0x74 }, - { /* 'U' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x55, 0x75 }, - { /* 'V' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x56, 0x76 }, - { /* 'W' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x57, 0x77 }, - { /* 'X' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x58, 0x78 }, - { /* 'Y' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x59, 0x79 }, - { /* 'Z' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x5A, 0x7A }, - { /* '[' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5B, 0x5B }, - { /* '\' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5C, 0x5C }, - { /* ']' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5D, 0x5D }, - { /* '^' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5E, 0x5E }, - { /* '_' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5F, 0x5F }, - { /* '`' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x60, 0x60 }, - { /* 'a' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x41, 0x61 }, - { /* 'b' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x42, 0x62 }, - { /* 'c' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x43, 0x63 }, - { /* 'd' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x44, 0x64 }, - { /* 'e' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x45, 0x65 }, - { /* 'f' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x46, 0x66 }, - { /* 'g' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x47, 0x67 }, - { /* 'h' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x48, 0x68 }, - { /* 'i' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x49, 0x69 }, - { /* 'j' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4A, 0x6A }, - { /* 'k' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4B, 0x6B }, - { /* 'l' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4C, 0x6C }, - { /* 'm' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4D, 0x6D }, - { /* 'n' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4E, 0x6E }, - { /* 'o' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4F, 0x6F }, - { /* 'p' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x50, 0x70 }, - { /* 'q' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x51, 0x71 }, - { /* 'r' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x52, 0x72 }, - { /* 's' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x53, 0x73 }, - { /* 't' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x54, 0x74 }, - { /* 'u' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x55, 0x75 }, - { /* 'v' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x56, 0x76 }, - { /* 'w' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x57, 0x77 }, - { /* 'x' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x58, 0x78 }, - { /* 'y' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x59, 0x79 }, - { /* 'z' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x5A, 0x7A }, - { /* '{' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7B, 0x7B }, - { /* '|' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7C, 0x7C }, - { /* '}' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7D, 0x7D }, - { /* '~' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7E, 0x7E }, - { /* DEL */ _PDCLIB_CTYPE_CNTRL, 0x7F, 0x7F }, - { 0x00, 0x80, 0x80 }, - { 0x00, 0x81, 0x81 }, - { 0x00, 0x82, 0x82 }, - { 0x00, 0x83, 0x83 }, - { 0x00, 0x84, 0x84 }, - { 0x00, 0x85, 0x85 }, - { 0x00, 0x86, 0x86 }, - { 0x00, 0x87, 0x87 }, - { 0x00, 0x88, 0x88 }, - { 0x00, 0x89, 0x89 }, - { 0x00, 0x8A, 0x8A }, - { 0x00, 0x8B, 0x8B }, - { 0x00, 0x8C, 0x8C }, - { 0x00, 0x8D, 0x8D }, - { 0x00, 0x8E, 0x8E }, - { 0x00, 0x8F, 0x8F }, - { 0x00, 0x90, 0x90 }, - { 0x00, 0x91, 0x91 }, - { 0x00, 0x92, 0x92 }, - { 0x00, 0x93, 0x93 }, - { 0x00, 0x94, 0x94 }, - { 0x00, 0x95, 0x95 }, - { 0x00, 0x96, 0x96 }, - { 0x00, 0x97, 0x97 }, - { 0x00, 0x98, 0x98 }, - { 0x00, 0x99, 0x99 }, - { 0x00, 0x9A, 0x9A }, - { 0x00, 0x9B, 0x9B }, - { 0x00, 0x9C, 0x9C }, - { 0x00, 0x9D, 0x9D }, - { 0x00, 0x9E, 0x9E }, - { 0x00, 0x9F, 0x9F }, - { 0x00, 0xA0, 0xA0 }, - { 0x00, 0xA1, 0xA1 }, - { 0x00, 0xA2, 0xA2 }, - { 0x00, 0xA3, 0xA3 }, - { 0x00, 0xA4, 0xA4 }, - { 0x00, 0xA5, 0xA5 }, - { 0x00, 0xA6, 0xA6 }, - { 0x00, 0xA7, 0xA7 }, - { 0x00, 0xA8, 0xA8 }, - { 0x00, 0xA9, 0xA9 }, - { 0x00, 0xAA, 0xAA }, - { 0x00, 0xAB, 0xAB }, - { 0x00, 0xAC, 0xAC }, - { 0x00, 0xAD, 0xAD }, - { 0x00, 0xAE, 0xAE }, - { 0x00, 0xAF, 0xAF }, - { 0x00, 0xB0, 0xB0 }, - { 0x00, 0xB1, 0xB1 }, - { 0x00, 0xB2, 0xB2 }, - { 0x00, 0xB3, 0xB3 }, - { 0x00, 0xB4, 0xB4 }, - { 0x00, 0xB5, 0xB5 }, - { 0x00, 0xB6, 0xB6 }, - { 0x00, 0xB7, 0xB7 }, - { 0x00, 0xB8, 0xB8 }, - { 0x00, 0xB9, 0xB9 }, - { 0x00, 0xBA, 0xBA }, - { 0x00, 0xBB, 0xBB }, - { 0x00, 0xBC, 0xBC }, - { 0x00, 0xBD, 0xBD }, - { 0x00, 0xBE, 0xBE }, - { 0x00, 0xBF, 0xBF }, - { 0x00, 0xC0, 0xC0 }, - { 0x00, 0xC1, 0xC1 }, - { 0x00, 0xC2, 0xC2 }, - { 0x00, 0xC3, 0xC3 }, - { 0x00, 0xC4, 0xC4 }, - { 0x00, 0xC5, 0xC5 }, - { 0x00, 0xC6, 0xC6 }, - { 0x00, 0xC7, 0xC7 }, - { 0x00, 0xC8, 0xC8 }, - { 0x00, 0xC9, 0xC9 }, - { 0x00, 0xCA, 0xCA }, - { 0x00, 0xCB, 0xCB }, - { 0x00, 0xCC, 0xCC }, - { 0x00, 0xCD, 0xCD }, - { 0x00, 0xCE, 0xCE }, - { 0x00, 0xCF, 0xCF }, - { 0x00, 0xD0, 0xD0 }, - { 0x00, 0xD1, 0xD1 }, - { 0x00, 0xD2, 0xD2 }, - { 0x00, 0xD3, 0xD3 }, - { 0x00, 0xD4, 0xD4 }, - { 0x00, 0xD5, 0xD5 }, - { 0x00, 0xD6, 0xD6 }, - { 0x00, 0xD7, 0xD7 }, - { 0x00, 0xD8, 0xD8 }, - { 0x00, 0xD9, 0xD9 }, - { 0x00, 0xDA, 0xDA }, - { 0x00, 0xDB, 0xDB }, - { 0x00, 0xDC, 0xDC }, - { 0x00, 0xDD, 0xDD }, - { 0x00, 0xDE, 0xDE }, - { 0x00, 0xDF, 0xDF }, - { 0x00, 0xE0, 0xE0 }, - { 0x00, 0xE1, 0xE1 }, - { 0x00, 0xE2, 0xE2 }, - { 0x00, 0xE3, 0xE3 }, - { 0x00, 0xE4, 0xE4 }, - { 0x00, 0xE5, 0xE5 }, - { 0x00, 0xE6, 0xE6 }, - { 0x00, 0xE7, 0xE7 }, - { 0x00, 0xE8, 0xE8 }, - { 0x00, 0xE9, 0xE9 }, - { 0x00, 0xEA, 0xEA }, - { 0x00, 0xEB, 0xEB }, - { 0x00, 0xEC, 0xEC }, - { 0x00, 0xED, 0xED }, - { 0x00, 0xEE, 0xEE }, - { 0x00, 0xEF, 0xEF }, - { 0x00, 0xF0, 0xF0 }, - { 0x00, 0xF1, 0xF1 }, - { 0x00, 0xF2, 0xF2 }, - { 0x00, 0xF3, 0xF3 }, - { 0x00, 0xF4, 0xF4 }, - { 0x00, 0xF5, 0xF5 }, - { 0x00, 0xF6, 0xF6 }, - { 0x00, 0xF7, 0xF7 }, - { 0x00, 0xF8, 0xF8 }, - { 0x00, 0xF9, 0xF9 }, - { 0x00, 0xFA, 0xFA }, - { 0x00, 0xFB, 0xFB }, - { 0x00, 0xFC, 0xFC }, - { 0x00, 0xFD, 0xFD }, - { 0x00, 0xFE, 0xFE }, - { 0x00, 0xFF, 0xFF } -}; - -struct _PDCLIB_lc_ctype_t _PDCLIB_lc_ctype = { 0, 0x30, 0x39, 0x41, 0x46, 0x61, 0x66, &_ctype_entries[1] }; - -struct _PDCLIB_lc_collate_t _PDCLIB_lc_collate = { 0 }; - -struct lconv _PDCLIB_lconv = { - /* decimal_point */ (char *)".", - /* thousands_sep */ (char *)"", - /* grouping */ (char *)"", - /* mon_decimal_point */ (char *)"", - /* mon_thousands_sep */ (char *)"", - /* mon_grouping */ (char *)"", - /* positive_sign */ (char *)"", - /* negative_sign */ (char *)"", - /* currency_symbol */ (char *)"", - /* int_curr_symbol */ (char *)"", - /* frac_digits */ CHAR_MAX, - /* p_cs_precedes */ CHAR_MAX, - /* n_cs_precedes */ CHAR_MAX, - /* p_sep_by_space */ CHAR_MAX, - /* n_sep_by_space */ CHAR_MAX, - /* p_sign_posn */ CHAR_MAX, - /* n_sign_posn */ CHAR_MAX, - /* int_frac_digits */ CHAR_MAX, - /* int_p_cs_precedes */ CHAR_MAX, - /* int_n_cs_precedes */ CHAR_MAX, - /* int_p_sep_by_space */ CHAR_MAX, - /* int_n_sep_by_space */ CHAR_MAX, - /* int_p_sign_posn */ CHAR_MAX, - /* int_n_sign_posn */ CHAR_MAX -}; - -struct _PDCLIB_lc_numeric_monetary_t _PDCLIB_lc_numeric_monetary = { - &_PDCLIB_lconv, - 0, /* numeric_allocated */ - 0 /* monetary_allocated */ -}; - -struct _PDCLIB_lc_messages_t _PDCLIB_lc_messages = { - 0, - /* _PDCLIB_errno_texts */ - { - /* no error */ (char *)"", - /* ERANGE */ (char *)"ERANGE (Range error)", - /* EDOM */ (char *)"EDOM (Domain error)", - /* EILSEQ */ (char *)"EILSEQ (Illegal sequence)" - } -}; - -struct _PDCLIB_lc_time_t _PDCLIB_lc_time = { - 0, - /* _PDCLIB_month_name_abbr */ - { - (char *)"Jan", - (char *)"Feb", - (char *)"Mar", - (char *)"Apr", - (char *)"May", - (char *)"Jun", - (char *)"Jul", - (char *)"Aug", - (char *)"Sep", - (char *)"Oct", - (char *)"Now", - (char *)"Dec" - }, - /* _PDCLIB_month_name_full */ - { - (char *)"January", - (char *)"February", - (char *)"March", - (char *)"April", - (char *)"May", - (char *)"June", - (char *)"July", - (char *)"August", - (char *)"September", - (char *)"October", - (char *)"November", - (char *)"December" - }, - /* _PDCLIB_day_name_abbr */ - { - (char *)"Sun", - (char *)"Mon", - (char *)"Tue", - (char *)"Wed", - (char *)"Thu", - (char *)"Fri", - (char *)"Sat" - }, - /* _PDCLIB_day_name_full */ - { - (char *)"Sunday", - (char *)"Monday", - (char *)"Tuesday", - (char *)"Wednesday", - (char *)"Thursday", - (char *)"Friday", - (char *)"Saturday" - }, - /* date / time format */ (char *)"%a %b %e %T %Y", - /* 12h time format */ (char *)"%I:%M:%S %p", - /* date format */ (char *)"%m/%d/%y", - /* time format */ (char *)"%T", - /* AM / PM designation */ - { - (char *)"AM", - (char *)"PM" - } -}; diff --git a/src/libraries/libc/j6libc/strtox_main.c b/src/libraries/libc/j6libc/strtox_main.c deleted file mode 100644 index 0d039ae..0000000 --- a/src/libraries/libc/j6libc/strtox_main.c +++ /dev/null @@ -1,42 +0,0 @@ -/* _PDCLIB_strtox_main( const char * *, int, uintmax_t, uintmax_t, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include - -uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limval, int limdigit, char * sign ) -{ - uintmax_t rc = 0; - int digit = -1; - const char * x; - while ( ( x = memchr( _PDCLIB_digits, tolower(**p), base ) ) != NULL ) - { - digit = x - _PDCLIB_digits; - if ( ( rc < limval ) || ( ( rc == limval ) && ( digit <= limdigit ) ) ) - { - rc = rc * base + (unsigned)digit; - ++(*p); - } - else - { - errno = ERANGE; - /* TODO: Only if endptr != NULL - but do we really want *another* parameter? */ - /* TODO: Earlier version was missing tolower() here but was not caught by tests */ - while ( memchr( _PDCLIB_digits, tolower(**p), base ) != NULL ) ++(*p); - /* TODO: This is ugly, but keeps caller from negating the error value */ - *sign = '+'; - return error; - } - } - if ( digit == -1 ) - { - *p = NULL; - return 0; - } - return rc; -} diff --git a/src/libraries/libc/j6libc/strtox_prelim.c b/src/libraries/libc/j6libc/strtox_prelim.c deleted file mode 100644 index 935632c..0000000 --- a/src/libraries/libc/j6libc/strtox_prelim.c +++ /dev/null @@ -1,50 +0,0 @@ -/* _PDCLIB_strtox_prelim( const char *, char *, int * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base ) -{ - /* skipping leading whitespace */ - while ( isspace( *p ) ) ++p; - /* determining / skipping sign */ - if ( *p != '+' && *p != '-' ) *sign = '+'; - else *sign = *(p++); - /* determining base */ - if ( *p == '0' ) - { - ++p; - if ( ( *base == 0 || *base == 16 ) && ( *p == 'x' || *p == 'X' ) ) - { - *base = 16; - ++p; - /* catching a border case here: "0x" followed by a non-digit should - be parsed as the unprefixed zero. - We have to "rewind" the parsing; having the base set to 16 if it - was zero previously does not hurt, as the result is zero anyway. - */ - if ( memchr( _PDCLIB_digits, tolower(*p), *base ) == NULL ) - { - p -= 2; - } - } - else if ( *base == 0 ) - { - *base = 8; - } - else - { - --p; - } - } - else if ( ! *base ) - { - *base = 10; - } - return ( ( *base >= 2 ) && ( *base <= 36 ) ) ? p : NULL; -} diff --git a/src/libraries/libc/j6libc/wchar_t.h b/src/libraries/libc/j6libc/wchar_t.h deleted file mode 100644 index 5637bbb..0000000 --- a/src/libraries/libc/j6libc/wchar_t.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -/* Type definition: wchar_t */ - -#if __is_identifier(wchar_t) -typedef __WCHAR_TYPE__ wchar_t; -#endif diff --git a/src/libraries/libc/j6libc/wctype_t.h b/src/libraries/libc/j6libc/wctype_t.h deleted file mode 100644 index c9c8dd9..0000000 --- a/src/libraries/libc/j6libc/wctype_t.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -/* Type definitions: wctype_t wctrans_t */ - -typedef uint32_t wctrans_t; -typedef uint32_t wctype_t ; - diff --git a/src/libraries/libc/j6libc/wint_t.h b/src/libraries/libc/j6libc/wint_t.h deleted file mode 100644 index 86b3aa9..0000000 --- a/src/libraries/libc/j6libc/wint_t.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -/* Type definition: wint_t */ - -typedef __WINT_TYPE__ wint_t; - diff --git a/src/libraries/libc/limits.h b/src/libraries/libc/limits.h deleted file mode 100644 index 5c02621..0000000 --- a/src/libraries/libc/limits.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -/* Sizes of integer types - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" - -/* TODO: Defined to 1 as multibyte characters are not supported yet. */ -#define MB_LEN_MAX 1 - -#define SCHAR_MAX __SCHAR_MAX__ -#define SCHAR_MIN ((-SCHAR_MAX) - 1) -#define UCHAR_MAX (((unsigned char)SCHAR_MAX << 1) | 1) - -#define CHAR_BIT __CHAR_BIT__ -#define CHAR_MAX SCHAR_MAX -#define CHAR_MIN SCHAR_MIN - -#define SHRT_MAX __SHRT_MAX__ -#define SHRT_MIN ((-SHRT_MAX) - 1) -#define USHRT_MAX (((unsigned short)SHRT_MAX << 1) | 1) - -#define INT_MAX __INT_MAX__ -#define INT_MIN ((-INT_MAX) - 1) -#define UINT_MAX (((unsigned int)INT_MAX << 1) | 1) - -#define LONG_MAX __LONG_MAX__ -#define LONG_MIN ((-LONG_MAX) - 1) -#define ULONG_MAX (((unsigned long)LONG_MAX << 1) | 1) - -#define LLONG_MAX __LONG_LONG_MAX__ -#define LLONG_MIN ((-LLONG_MAX) - 1) -#define ULLONG_MAX (((unsigned long long)LLONG_MAX << 1) | 1) - diff --git a/src/libraries/libc/locale.h b/src/libraries/libc/locale.h deleted file mode 100644 index e93f21e..0000000 --- a/src/libraries/libc/locale.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once -/* Localization - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/cpp.h" -#include "j6libc/int.h" -#include "j6libc/null.h" - -CPP_CHECK_BEGIN - -/* The structure returned by localeconv(). - - The values for *_sep_by_space: - 0 - no space - 1 - if symbol and sign are adjacent, a space seperates them from the value; - otherwise a space seperates the symbol from the value - 2 - if symbol and sign are adjacent, a space seperates them; otherwise a - space seperates the sign from the value - - The values for *_sign_posn: - 0 - Parentheses surround value and symbol - 1 - sign precedes value and symbol - 2 - sign succeeds value and symbol - 3 - sign immediately precedes symbol - 4 - sign immediately succeeds symbol -*/ -struct lconv -{ - char * decimal_point; /* decimal point character */ /* LC_NUMERIC */ - char * thousands_sep; /* character for seperating groups of digits */ /* LC_NUMERIC */ - char * grouping; /* string indicating the size of digit groups */ /* LC_NUMERIC */ - char * mon_decimal_point; /* decimal point for monetary quantities */ /* LC_MONETARY */ - char * mon_thousands_sep; /* thousands_sep for monetary quantities */ /* LC_MONETARY */ - char * mon_grouping; /* grouping for monetary quantities */ /* LC_MONETARY */ - char * positive_sign; /* string indicating nonnegative mty. qty. */ /* LC_MONETARY */ - char * negative_sign; /* string indicating negative mty. qty. */ /* LC_MONETARY */ - char * currency_symbol; /* local currency symbol (e.g. '$') */ /* LC_MONETARY */ - char * int_curr_symbol; /* international currency symbol (e.g. "USD" */ /* LC_MONETARY */ - char frac_digits; /* fractional digits in local monetary qty. */ /* LC_MONETARY */ - char p_cs_precedes; /* if currency_symbol precedes positive qty. */ /* LC_MONETARY */ - char n_cs_precedes; /* if currency_symbol precedes negative qty. */ /* LC_MONETARY */ - char p_sep_by_space; /* if it is seperated by space from pos. qty. */ /* LC_MONETARY */ - char n_sep_by_space; /* if it is seperated by space from neg. qty. */ /* LC_MONETARY */ - char p_sign_posn; /* positioning of positive_sign for mon. qty. */ /* LC_MONETARY */ - char n_sign_posn; /* positioning of negative_sign for mon. qty. */ /* LC_MONETARY */ - char int_frac_digits; /* Same as above, for international format */ /* LC_MONETARY */ - char int_p_cs_precedes; /* Same as above, for international format */ /* LC_MONETARY */ - char int_n_cs_precedes; /* Same as above, for international format */ /* LC_MONETARY */ - char int_p_sep_by_space; /* Same as above, for international format */ /* LC_MONETARY */ - char int_n_sep_by_space; /* Same as above, for international format */ /* LC_MONETARY */ - char int_p_sign_posn; /* Same as above, for international format */ /* LC_MONETARY */ - char int_n_sign_posn; /* Same as above, for international format */ /* LC_MONETARY */ -}; - -/* First arguments to setlocale(). - NOTE: If you add to / modify these, look at functions/locale/setlocale.c - and keep things in sync. -*/ -/* Entire locale */ -#define LC_ALL _PDCLIB_LC_ALL -/* Collation (strcoll(), strxfrm()) */ -#define LC_COLLATE _PDCLIB_LC_COLLATE -/* Character types (, ) */ -#define LC_CTYPE _PDCLIB_LC_CTYPE -/* Monetary formatting (as returned by localeconv) */ -#define LC_MONETARY _PDCLIB_LC_MONETARY -/* Decimal-point character (for printf() / scanf() functions), string - conversions, nonmonetary formatting as returned by localeconv -*/ -#define LC_NUMERIC _PDCLIB_LC_NUMERIC -/* Time formats (strftime(), wcsftime()) */ -#define LC_TIME _PDCLIB_LC_TIME -/* Messages (not specified but allowed by C99, and specified by POSIX) - (used by perror() / strerror()) -*/ -#define LC_MESSAGES _PDCLIB_LC_MESSAGES - -/* The category parameter can be any of the LC_* macros to specify if the call - to setlocale() shall affect the entire locale or only a portion thereof. - The category locale specifies which locale should be switched to, with "C" - being the minimal default locale, and "" being the locale-specific native - environment. A NULL pointer makes setlocale() return the *current* setting. - Otherwise, returns a pointer to a string associated with the specified - category for the new locale. -*/ -char * setlocale( int category, const char * locale ); - -/* Returns a struct lconv initialized to the values appropriate for the current - locale setting. -*/ -struct lconv * localeconv( void ); - -CPP_CHECK_END diff --git a/src/libraries/libc/locale/localeconv.c b/src/libraries/libc/locale/localeconv.c deleted file mode 100644 index d610c6b..0000000 --- a/src/libraries/libc/locale/localeconv.c +++ /dev/null @@ -1,12 +0,0 @@ -/* localeconv( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -struct lconv * localeconv( void ) -{ - return _PDCLIB_lc_numeric_monetary.lconv; -} diff --git a/src/libraries/libc/locale/setlocale.c b/src/libraries/libc/locale/setlocale.c deleted file mode 100644 index f31aa44..0000000 --- a/src/libraries/libc/locale/setlocale.c +++ /dev/null @@ -1,242 +0,0 @@ -/* setlocale( int, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -#if 0 -static const char * _PDCLIB_LC_category_name[ _PDCLIB_LC_COUNT ] = { NULL, "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC", "LC_TIME", "LC_MESSAGES" }; - -static const char * _PDCLIB_default_locale( int category ) -{ - const char * s; - - if ( ( s = getenv( "LC_ALL" ) ) == NULL ) - { - if ( category == LC_ALL || ( s = getenv( _PDCLIB_LC_category_name[ category ] ) ) == NULL ) - { - if ( ( s = getenv( "LANG" ) ) == NULL ) - { - s = "C"; - } - } - } - - return s; -} -#endif - -char * setlocale( int category, const char * locale ) -{ - /* All below is very much work-in-progress, so we do a dumb-dummy - return here. - */ - if ( locale == NULL || ! strcmp( locale, "C" ) ) - { - return (char *)"C"; - } - else - { - return NULL; - } - -#if 0 - /* Path to locale data files - _PDCLIB_LOCALE_PATH unless overruled - by the environment variable whose name is defined by preprocessor - symbol _PDCLIB_LOCALE_PATH_ENV (defaulting to PDCLIB_I18N). - Both of these definitions are set in config.h. - */ - const char * path = _PDCLIB_LOCALE_PATH; - - struct _PDCLIB_lc_lconv_numeric_t * numeric = NULL; - struct _PDCLIB_lc_lconv_monetary_t * monetary = NULL; - struct _PDCLIB_lc_collate_t * collate = NULL; - struct _PDCLIB_lc_ctype_t * ctype = NULL; - struct _PDCLIB_lc_messages_t * messages = NULL; - struct _PDCLIB_lc_time_t * time = NULL; - - char * rc = (char *)locale; - - if ( category < 0 || category >= _PDCLIB_LC_COUNT ) - { - /* Bad category */ - return NULL; - } - - if ( locale == NULL ) - { - /* NULL - Return current locale settings */ - /* TODO */ - } - - if ( strlen( locale ) == 0 ) - { - /* "" - Use default locale */ - locale = _PDCLIB_default_locale( category ); - } - - if ( getenv( _PDCLIB_symbol2string( _PDCLIB_LOCALE_PATH_ENV ) ) != NULL ) - { - path = getenv( _PDCLIB_symbol2string( _PDCLIB_LOCALE_PATH_ENV ) ); - } - - /* We have to do this in two runs. As we might be facing LC_ALL, we - need to be certain all the loads are successful before we start - to overwrite the current locale settings, because there is no way - this function could report a _partial_ success. - */ - - /* Run One -- get all the data for the new locale setting */ - if ( category == LC_COLLATE || category == LC_ALL ) - { - if ( ! ( collate = _PDCLIB_load_lc_collate( path, locale ) ) ) - { - rc = NULL; - } - } - - if ( category == LC_CTYPE || category == LC_ALL ) - { - if ( ! ( ctype = _PDCLIB_load_lc_ctype( path, locale ) ) ) - { - rc = NULL; - } - } - - if ( category == LC_MONETARY || category == LC_ALL ) - { - if ( ! ( monetary = _PDCLIB_load_lc_monetary( path, locale ) ) ) - { - rc = NULL; - } - } - - if ( category == LC_NUMERIC || category == LC_ALL ) - { - if ( ! ( numeric = _PDCLIB_load_lc_numeric( path, locale ) ) ) - { - rc = NULL; - } - } - - if ( category == LC_TIME || category == LC_ALL ) - { - if ( ! ( time = _PDCLIB_load_lc_time( path, locale ) ) ) - { - rc = NULL; - } - } - - if ( category == LC_MESSAGES || category == LC_ALL ) - { - if ( ! ( messages = _PDCLIB_load_lc_messages( path, locale ) ) ) - { - rc = NULL; - } - } - - /* Run Two -- continue or release resources */ - if ( rc != NULL ) - { - if ( category == LC_COLLATE || category == LC_ALL ) - { - if ( _PDCLIB_lc_collate.alloced ) - { - /* free resources */ - } - - _PDCLIB_lc_collate = *collate; - free( collate ); - } - - if ( category == LC_CTYPE || category == LC_ALL ) - { - if ( _PDCLIB_lc_ctype.alloced ) - { - free( _PDCLIB_lc_ctype.entry - 1 ); - } - - _PDCLIB_lc_ctype = *ctype; - free( ctype ); - } - - if ( category == LC_MONETARY || category == LC_ALL ) - { - if ( _PDCLIB_lc_numeric_monetary.monetary_alloced ) - { - free( _PDCLIB_lc_numeric_monetary.lconv->mon_decimal_point ); - } - - _PDCLIB_lc_numeric_monetary.lconv->mon_decimal_point = monetary->mon_decimal_point; - _PDCLIB_lc_numeric_monetary.lconv->mon_thousands_sep = monetary->mon_thousands_sep; - _PDCLIB_lc_numeric_monetary.lconv->mon_grouping = monetary->mon_grouping; - _PDCLIB_lc_numeric_monetary.lconv->positive_sign = monetary->positive_sign; - _PDCLIB_lc_numeric_monetary.lconv->negative_sign = monetary->negative_sign; - _PDCLIB_lc_numeric_monetary.lconv->currency_symbol = monetary->currency_symbol; - _PDCLIB_lc_numeric_monetary.lconv->int_curr_symbol = monetary->int_curr_symbol; - _PDCLIB_lc_numeric_monetary.lconv->frac_digits = monetary->frac_digits; - _PDCLIB_lc_numeric_monetary.lconv->p_cs_precedes = monetary->p_cs_precedes; - _PDCLIB_lc_numeric_monetary.lconv->n_cs_precedes = monetary->n_cs_precedes; - _PDCLIB_lc_numeric_monetary.lconv->p_sep_by_space = monetary->p_sep_by_space; - _PDCLIB_lc_numeric_monetary.lconv->n_sep_by_space = monetary->n_sep_by_space; - _PDCLIB_lc_numeric_monetary.lconv->p_sign_posn = monetary->p_sign_posn; - _PDCLIB_lc_numeric_monetary.lconv->n_sign_posn = monetary->n_sign_posn; - _PDCLIB_lc_numeric_monetary.lconv->int_frac_digits = monetary->int_frac_digits; - _PDCLIB_lc_numeric_monetary.lconv->int_p_cs_precedes = monetary->int_p_cs_precedes; - _PDCLIB_lc_numeric_monetary.lconv->int_n_cs_precedes = monetary->int_n_cs_precedes; - _PDCLIB_lc_numeric_monetary.lconv->int_p_sep_by_space = monetary->int_p_sep_by_space; - _PDCLIB_lc_numeric_monetary.lconv->int_n_sep_by_space = monetary->int_n_sep_by_space; - _PDCLIB_lc_numeric_monetary.lconv->int_p_sign_posn = monetary->int_p_sign_posn; - _PDCLIB_lc_numeric_monetary.lconv->int_n_sign_posn = monetary->int_n_sign_posn; - - _PDCLIB_lc_numeric_monetary.monetary_alloced = 1; - - free( monetary ); - } - - if ( category == LC_NUMERIC || category == LC_ALL ) - { - if ( _PDCLIB_lc_numeric_monetary.numeric_alloced ) - { - free( _PDCLIB_lc_numeric_monetary.lconv->decimal_point ); - } - - _PDCLIB_lc_numeric_monetary.lconv->decimal_point = numeric->decimal_point; - _PDCLIB_lc_numeric_monetary.lconv->thousands_sep = numeric->thousands_sep; - _PDCLIB_lc_numeric_monetary.lconv->grouping = numeric->grouping; - - _PDCLIB_lc_numeric_monetary.numeric_alloced = 1; - - free( numeric ); - } - - if ( category == LC_TIME || category == LC_ALL ) - { - if ( _PDCLIB_lc_time.alloced ) - { - free( _PDCLIB_lc_time.month_name_abbr[ 0 ] ); - } - - _PDCLIB_lc_time = *time; - free( time ); - } - - if ( category == LC_MESSAGES || category == LC_ALL ) - { - if ( _PDCLIB_lc_messages.alloced ) - { - free( _PDCLIB_lc_messages.errno_texts[ 0 ] ); - } - - _PDCLIB_lc_messages = *messages; - free( messages ); - } - } - - return NULL; -#endif -} diff --git a/src/libraries/libc/signal.h b/src/libraries/libc/signal.h deleted file mode 100644 index 273184a..0000000 --- a/src/libraries/libc/signal.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once -/* Signal handling - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/config.h" -#include "j6libc/cpp.h" -#include "j6libc/sig_atomic_t.h" - -CPP_CHECK_BEGIN - -/* Signals ------------------------------------------------------------------ */ - -/* A word on signals, to the people using PDCLib in their OS projects. - - The definitions of the C standard leave about everything that *could* be - useful to be "implementation defined". Without additional, non-standard - arrangements, it is not possible to turn them into a useful tool. - - This example implementation chose to "not generate any of these signals, - except as a result of explicit calls to the raise function", which is - allowed by the standard but of course does nothing for the usefulness of - . - - A useful signal handling would: - 1) make signal() a system call that registers the signal handler with the OS - 2) make raise() a system call triggering an OS signal to the running process - 3) make provisions that further signals of the same type are blocked until - the signal handler returns (optional for SIGILL) -*/ - -/* These are the values used by Linux. */ - -/* Abnormal termination / abort() */ -#define SIGABRT 6 -/* Arithmetic exception / division by zero / overflow */ -#define SIGFPE 8 -/* Illegal instruction */ -#define SIGILL 4 -/* Interactive attention signal */ -#define SIGINT 2 -/* Invalid memory access */ -#define SIGSEGV 11 -/* Termination request */ -#define SIGTERM 15 - -typedef void (*sighandler_t)(int); - -/* The following should be defined to pointer values that could NEVER point to - a valid signal handler function. (They are used as special arguments to - signal().) Again, these are the values used by Linux. -*/ -#define SIG_DFL (sighandler_t)0 -#define SIG_ERR (sighandler_t)-1 -#define SIG_IGN (sighandler_t)1 - -/* Installs a signal handler "func" for the given signal. - A signal handler is a function that takes an integer as argument (the signal - number) and returns void. - - Note that a signal handler can do very little else than: - 1) assign a value to a static object of type "volatile sig_atomic_t", - 2) call signal() with the value of sig equal to the signal received, - 3) call _Exit(), - 4) call abort(). - Virtually everything else is undefind. - - The signal() function returns the previous installed signal handler, which - at program start may be SIG_DFL or SIG_ILL. (This implementation uses - SIG_DFL for all handlers.) If the request cannot be honored, SIG_ERR is - returned and errno is set to an unspecified positive value. -*/ -sighandler_t signal( int sig, sighandler_t func ); - -/* Raises the given signal (executing the registered signal handler with the - given signal number as parameter). - This implementation does not prevent further signals of the same time from - occuring, but executes signal( sig, SIG_DFL ) before entering the signal - handler (i.e., a second signal before the signal handler re-registers itself - or SIG_IGN will end the program). - Returns zero if successful, nonzero otherwise. */ -int raise( int sig ); - -CPP_CHECK_END diff --git a/src/libraries/libc/signal/raise.c b/src/libraries/libc/signal/raise.c deleted file mode 100644 index 679bb5f..0000000 --- a/src/libraries/libc/signal/raise.c +++ /dev/null @@ -1,63 +0,0 @@ -/* raise( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -extern void (*_PDCLIB_sigabrt)( int ); -extern void (*_PDCLIB_sigfpe)( int ); -extern void (*_PDCLIB_sigill)( int ); -extern void (*_PDCLIB_sigint)( int ); -extern void (*_PDCLIB_sigsegv)( int ); -extern void (*_PDCLIB_sigterm)( int ); - -int raise( int sig ) -{ - void (*sighandler)( int ) = NULL; - const char * message; - switch ( sig ) - { - case SIGABRT: - sighandler = _PDCLIB_sigabrt; - message = "Abnormal termination (SIGABRT)"; - break; - case SIGFPE: - sighandler = _PDCLIB_sigfpe; - message = "Arithmetic exception (SIGFPE)"; - break; - case SIGILL: - sighandler = _PDCLIB_sigill; - message = "Illegal instruction (SIGILL)"; - break; - case SIGINT: - sighandler = _PDCLIB_sigint; - message = "Interactive attention signal (SIGINT)"; - break; - case SIGSEGV: - sighandler = _PDCLIB_sigsegv; - message = "Invalid memory access (SIGSEGV)"; - break; - case SIGTERM: - sighandler = _PDCLIB_sigterm; - message = "Termination request (SIGTERM)"; - break; - default: - fprintf( stderr, "Unknown signal #%d\n", sig ); - _Exit( EXIT_FAILURE ); - } - if ( sighandler == SIG_DFL ) - { - fputs( message, stderr ); - _Exit( EXIT_FAILURE ); - } - else if ( sighandler != SIG_IGN ) - { - sighandler = signal( sig, SIG_DFL ); - sighandler( sig ); - } - return 0; -} diff --git a/src/libraries/libc/signal/signal.c b/src/libraries/libc/signal/signal.c deleted file mode 100644 index 2358f87..0000000 --- a/src/libraries/libc/signal/signal.c +++ /dev/null @@ -1,58 +0,0 @@ -/* signal( int, void (*)( int ) ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -void (*_PDCLIB_sigabrt)( int ) = SIG_DFL; -void (*_PDCLIB_sigfpe)( int ) = SIG_DFL; -void (*_PDCLIB_sigill)( int ) = SIG_DFL; -void (*_PDCLIB_sigint)( int ) = SIG_DFL; -void (*_PDCLIB_sigsegv)( int ) = SIG_DFL; -void (*_PDCLIB_sigterm)( int ) = SIG_DFL; - -void (*signal( int sig, void (*func)( int ) ) )( int ) -{ - void (*oldhandler)( int ); - if ( sig <= 0 || func == SIG_ERR ) - { - return SIG_ERR; - } - switch ( sig ) - { - case SIGABRT: - oldhandler = _PDCLIB_sigabrt; - _PDCLIB_sigabrt = func; - break; - case SIGFPE: - oldhandler = _PDCLIB_sigfpe; - _PDCLIB_sigfpe = func; - break; - case SIGILL: - oldhandler = _PDCLIB_sigill; - _PDCLIB_sigill = func; - break; - case SIGINT: - oldhandler = _PDCLIB_sigint; - _PDCLIB_sigint = func; - break; - case SIGSEGV: - oldhandler = _PDCLIB_sigsegv; - _PDCLIB_sigsegv = func; - break; - case SIGTERM: - oldhandler = _PDCLIB_sigterm; - _PDCLIB_sigterm = func; - break; - default: - /* The standard calls for an unspecified "positive value". You - will probably want to define a specific value for this. - */ - _PDCLIB_errno = 1; - return SIG_ERR; - } - return oldhandler; -} diff --git a/src/libraries/libc/stdalign.h b/src/libraries/libc/stdalign.h deleted file mode 100644 index cd33a9e..0000000 --- a/src/libraries/libc/stdalign.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -/* Alignment - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#ifndef __cplusplus -#define alignas _Alignas -#define alignof _Alignof -#endif - -#define __alignas_is_defined 1 -#define __alignof_is_defined 1 diff --git a/src/libraries/libc/stdarg.h b/src/libraries/libc/stdarg.h deleted file mode 100644 index 92b6ecf..0000000 --- a/src/libraries/libc/stdarg.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -/* Variable arguments - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/config.h" - -typedef _PDCLIB_va_list va_list; - -#define va_arg( ap, type ) _PDCLIB_va_arg( ap, type ) -#define va_copy( dest, src ) _PDCLIB_va_copy( dest, src ) -#define va_end( ap ) _PDCLIB_va_end( ap ) -#define va_start( ap, parmN ) _PDCLIB_va_start( ap, parmN ) diff --git a/src/libraries/libc/stdbool.h b/src/libraries/libc/stdbool.h deleted file mode 100644 index b741dd2..0000000 --- a/src/libraries/libc/stdbool.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -/* Boolean type and values - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#ifndef __cplusplus -#define bool _Bool -#define true 1 -#define false 0 -#endif - -#define __bool_true_false_are_defined 1 diff --git a/src/libraries/libc/stddef.h b/src/libraries/libc/stddef.h deleted file mode 100644 index 10ec849..0000000 --- a/src/libraries/libc/stddef.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -/* Common definitions - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/int.h" -#include "j6libc/null.h" -#include "j6libc/max_align_t.h" -#include "j6libc/size_t.h" -#include "j6libc/wchar_t.h" - -typedef __PTRDIFF_TYPE__ ptrdiff_t; - -#if ! __has_include("__stddef_max_align_t.h") -typedef long double max_align_t; -#endif - -#ifndef offsetof -#define offsetof( type, member ) _PDCLIB_offsetof( type, member ) -#endif diff --git a/src/libraries/libc/stdint.h b/src/libraries/libc/stdint.h deleted file mode 100644 index 298208b..0000000 --- a/src/libraries/libc/stdint.h +++ /dev/null @@ -1,151 +0,0 @@ -#pragma once -/* Integer types - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* 7.18.2 Limits of specified-width integer types */ - -#include -#include - -#ifdef __cplusplus -#ifndef __STDC_LIMIT_MACROS -#define _PDCLIB_NO_LIMIT_MACROS -#endif -#endif - -#ifndef _PDCLIB_NO_LIMIT_MACROS - -/* 7.18.2.1 Limits of exact-width integer types */ - -#define INT8_MAX __INT8_MAX__ -#define INT8_MIN ((-INT8_MAX) - 1) -#define UINT8_MAX __UINT8_MAX__ - -#define INT16_MAX __INT16_MAX__ -#define INT16_MIN ((-INT16_MAX) - 1) -#define UINT16_MAX __UINT16_MAX__ - -#define INT32_MAX __INT32_MAX__ -#define INT32_MIN ((-INT32_MAX) - 1) -#define UINT32_MAX __UINT32_MAX__ - -#define INT64_MAX __INT64_MAX__ -#define INT64_MIN ((-INT64_MAX) - 1) -#define UINT64_MAX __UINT64_MAX__ - -/* 7.18.2.2 Limits of minimum-width integer types */ - -/* For the standard widths, least and exact types are equivalent. - You are allowed to add more types here, e.g. int_least24_t. -*/ - -#define INT_LEAST8_MAX __INT_LEAST8_MAX__ -#define INT_LEAST8_MIN ((-INT_LEAST8_MAX) - 1) -#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__ - -#define INT_LEAST16_MAX __INT_LEAST16_MAX__ -#define INT_LEAST16_MIN ((-INT_LEAST16_MAX) - 1) -#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__ - -#define INT_LEAST32_MAX __INT_LEAST32_MAX__ -#define INT_LEAST32_MIN ((-INT_LEAST32_MAX) - 1) -#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__ - -#define INT_LEAST64_MAX __INT_LEAST64_MAX__ -#define INT_LEAST64_MIN ((-INT_LEAST64_MAX) - 1) -#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__ - -/* 7.18.2.3 Limits of fastest minimum-width integer types */ - -#define INT_FAST8_MAX __INT_FAST8_MAX__ -#define INT_FAST8_MIN ((-INT_FAST8_MAX) - 1) -#define UINT_FAST8_MAX __UINT_FAST8_MAX__ - -#define INT_FAST16_MAX __INT_FAST16_MAX__ -#define INT_FAST16_MIN ((-INT_FAST16_MAX) - 1) -#define UINT_FAST16_MAX __UINT_FAST16_MAX__ - -#define INT_FAST32_MAX __INT_FAST32_MAX__ -#define INT_FAST32_MIN ((-INT_FAST32_MAX) - 1) -#define UINT_FAST32_MAX __UINT_FAST32_MAX__ - -#define INT_FAST64_MAX __INT_FAST64_MAX__ -#define INT_FAST64_MIN ((-INT_FAST64_MAX) - 1) -#define UINT_FAST64_MAX __UINT_FAST64_MAX__ - -/* 7.18.2.4 Limits of integer types capable of holding object pointers */ - -#define INTPTR_MAX __INTPTR_MAX__ -#define INTPTR_MIN ((-INTPTR_MAX) - 1) -#define UINTPTR_MAX __UINTPTR_MAX__ - -/* 7.18.2.5 Limits of greatest-width integer types */ - -#define INTMAX_MAX __INTMAX_MAX__ -#define INTMAX_MIN ((-INTMAX_MAX) - 1) -#define UINTMAX_MAX __UINTMAX_MAX__ - -/* 7.18.3 Limits of other integer types */ - -#define PTRDIFF_MAX __PTRDIFF_MAX__ -#define PTRDIFF_MIN ((-PTRDIFF_MAX) - 1) - -#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ -#define SIG_ATOMIC_MIN ((-SIG_ATOMIC_MAX) - 1) - -#define SIZE_MAX __SIZE_MAX__ - -#define WCHAR_MAX __WCHAR_MAX__ -#define WCHAR_MIN ((-WCHAR_MAX) - 1) - -#define WINT_MAX __WINT_MAX__ -#define WINT_MIN ((-WINT_MAX) - 1) - -#endif - -/* 7.18.4 Macros for integer constants */ - -#ifdef __cplusplus -#ifndef __STDC_CONSTANT_MACROS -#define _PDCLIB_NO_CONSTANT_MACROS -#endif -#endif - -#ifndef _PDCLIB_NO_CONSTANT_MACROS - -/* 7.18.4.1 Macros for minimum-width integer constants */ - -/* As the minimum-width types - for the required widths of 8, 16, 32, and 64 - bits - are expressed in terms of the exact-width types, the mechanism for - these macros is to append the literal of that exact-width type to the macro - parameter. - This is considered a hack, as the author is not sure his understanding of - the requirements of this macro is correct. Any input appreciated. -*/ - -/* Expand to an integer constant of specified value and type int_leastN_t */ - -#define INT8_C( value ) _PDCLIB_concat( value, __INT8_C_SUFFIX__ ) -#define INT16_C( value ) _PDCLIB_concat( value, __INT16_C_SUFFIX__ ) -#define INT32_C( value ) _PDCLIB_concat( value, __INT32_C_SUFFIX__ ) -#define INT64_C( value ) _PDCLIB_concat( value, __INT64_C_SUFFIX__ ) - -/* Expand to an integer constant of specified value and type uint_leastN_t */ - -#define UINT8_C( value ) _PDCLIB_concat( value, __UINT8_C_SUFFIX__ ) -#define UINT16_C( value ) _PDCLIB_concat( value, __UINT16_C_SUFFIX__ ) -#define UINT32_C( value ) _PDCLIB_concat( value, __UINT32_C_SUFFIX__ ) -#define UINT64_C( value ) _PDCLIB_concat( value, __UINT64_C_SUFFIX__ ) - -/* 7.18.4.2 Macros for greatest-width integer constants */ - -/* Expand to an integer constant of specified value and type intmax_t */ -#define INTMAX_C( value ) _PDCLIB_concat( value, __INTMAX_C_SUFFIX__ ) - -/* Expand to an integer constant of specified value and type uintmax_t */ -#define UINTMAX_C( value ) _PDCLIB_concat( value, __UINTMAX_C_SUFFIX__ ) - -#endif diff --git a/src/libraries/libc/stdio.h b/src/libraries/libc/stdio.h deleted file mode 100644 index e1d24bd..0000000 --- a/src/libraries/libc/stdio.h +++ /dev/null @@ -1,779 +0,0 @@ -#pragma once -/* Input/output - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/cpp.h" -#include "j6libc/int.h" -#include "j6libc/null.h" -#include "j6libc/size_t.h" - -CPP_CHECK_BEGIN - -/* See setvbuf(), third argument */ -#define _IOFBF 1 -#define _IOLBF 2 -#define _IONBF 4 - -/* The following are platform-dependant, and defined in config.h. */ -typedef struct _PDCLIB_fpos_t fpos_t; -typedef struct _PDCLIB_file_t FILE; -#define EOF -1 -#define BUFSIZ _PDCLIB_BUFSIZ -#define FOPEN_MAX _PDCLIB_FOPEN_MAX -#define FILENAME_MAX _PDCLIB_FILENAME_MAX -#define L_tmpnam _PDCLIB_L_tmpnam -#define TMP_MAX _PDCLIB_TMP_MAX - -/* See fseek(), third argument */ -#define SEEK_CUR _PDCLIB_SEEK_CUR -#define SEEK_END _PDCLIB_SEEK_END -#define SEEK_SET _PDCLIB_SEEK_SET - -extern FILE * stdin; -extern FILE * stdout; -extern FILE * stderr; - -/* Operations on files */ - -/* Remove the given file. - Returns zero if successful, non-zero otherwise. - This implementation does detect if a file of that name is currently open, - and fails the remove in this case. This does not detect two distinct names - that merely result in the same file (e.g. "/home/user/foo" vs. "~/foo"). -*/ -int remove( const char * filename ); - -/* Rename the given old file to the given new name. - Returns zero if successful, non-zero otherwise. - This implementation does detect if the old filename corresponds to an open - file, and fails the rename in this case. - If there already is a file with the new filename, behaviour is defined by - the glue code (see functions/_PDCLIB/rename.c). -*/ -int rename( const char * src, const char * dst ); - -/* Open a temporary file with mode "wb+", i.e. binary-update. Remove the file - automatically if it is closed or the program exits normally (by returning - from main() or calling exit()). - Returns a pointer to a FILE handle for this file. - This implementation does not remove temporary files if the process aborts - abnormally (e.g. abort()). -*/ -FILE * tmpfile( void ); - -/* Generate a file name that is not equal to any existing filename AT THE TIME - OF GENERATION. Generate a different name each time it is called. - Returns a pointer to an internal static buffer containing the filename if s - is a NULL pointer. (This is not thread-safe!) - Returns s if it is not a NULL pointer (s is then assumed to point to an array - of at least L_tmpnam characters). - Returns NULL if unable to generate a suitable name (because all possible - names already exist, or the function has been called TMP_MAX times already). - Note that this implementation cannot guarantee a file of the name generated - is not generated between the call to this function and a subsequent fopen(). -*/ -char * tmpnam( char * s ); - -/* File access functions */ - -/* Close the file associated with the given stream (after flushing its buffers). - Returns zero if successful, EOF if any errors occur. -*/ -int fclose( FILE * stream ); - -/* Flush the buffers of the given output stream. If the stream is an input - stream, or an update stream with the last operation being an input operation, - behaviour is undefined. - If stream is a NULL pointer, perform the buffer flushing for all applicable - streams. - Returns zero if successful, EOF if a write error occurs. - Sets the error indicator of the stream if a write error occurs. -*/ -int fflush( FILE * stream ); - -/* Open the file with the given filename in the given mode, and return a stream - handle for it in which error and end-of-file indicator are cleared. Defined - values for mode are: - - READ MODES - text files binary files - without update "r" "rb" - with update "r+" "rb+" or "r+b" - - Opening in read mode fails if no file with the given filename exists, or if - cannot be read. - - WRITE MODES - text files binary files - without update "w" "wb" - with update "w+" "wb+" or "w+b" - - With write modes, if a file with the given filename already exists, it is - truncated to zero length. - - APPEND MODES - text files binary files - without update "a" "ab" - with update "a+" "ab+" or "a+b" - - With update modes, if a file with the given filename already exists, it is - not truncated to zero length, but all writes are forced to end-of-file (this - regardless to fseek() calls). Note that binary files opened in append mode - might have their end-of-file padded with '\0' characters. - - Update modes mean that both input and output functions can be performed on - the stream, but output must be terminated with a call to either fflush(), - fseek(), fsetpos(), or rewind() before input is performed, and input must - be terminated with a call to either fseek(), fsetpos(), or rewind() before - output is performed, unless input encountered end-of-file. - - If a text file is opened with update mode, the implementation is at liberty - to open a binary stream instead. This implementation honors the exact mode - given. - - The stream is fully buffered if and only if it can be determined not to - refer to an interactive device. - - If the mode string begins with but is longer than one of the above sequences - the implementation is at liberty to ignore the additional characters, or do - implementation-defined things. This implementation only accepts the exact - modes above. - - Returns a pointer to the stream handle if successfull, NULL otherwise. -*/ -FILE * fopen( const char * restrict filename, const char * restrict mode ); - -/* Close any file currently associated with the given stream. Open the file - identified by the given filename with the given mode (equivalent to fopen()), - and associate it with the given stream. If filename is a NULL pointer, - attempt to change the mode of the given stream. - This implementation allows any mode changes on "real" files, and associating - of the standard streams with files. It does *not* support mode changes on - standard streams. - (Primary use of this function is to redirect stdin, stdout, and stderr.) -*/ -FILE * freopen( const char * restrict filename, const char * restrict mode, FILE * restrict stream ); - -/* If buf is a NULL pointer, call setvbuf( stream, NULL, _IONBF, BUFSIZ ). - If buf is not a NULL pointer, call setvbuf( stream, buf, _IOFBF, BUFSIZ ). -*/ -void setbuf( FILE * restrict stream, char * restrict buf ); - -/* Set the given stream to the given buffering mode. If buf is not a NULL - pointer, use buf as file buffer (of given size). If buf is a NULL pointer, - use a buffer of given size allocated internally. _IONBF causes unbuffered - behaviour, _IOLBF causes line-buffered behaviour, _IOFBF causes fully - buffered behaviour. Calling this function is only valid right after a file is - opened, and before any other operation (except for any unsuccessful calls to - setvbuf()) has been performed. - Returns zero if successful, nonzero otherwise. -*/ -int setvbuf( FILE * restrict stream, char * restrict buf, int mode, size_t size ); - -/* Formatted input/output functions */ - -/* - Write output to the given stream, as defined by the given format string and - 0..n subsequent arguments (the argument stack). - - The format string is written to the given stream verbatim, except for any - conversion specifiers included, which start with the letter '%' and are - documented below. If the given conversion specifiers require more arguments - from the argument stack than provided, behaviour is undefined. Additional - arguments not required by conversion specifiers are evaluated but otherwise - ignored. - - (The standard specifies the format string is allowed to contain multibyte - character sequences as long as it starts and ends in initial shift state, - but this is not yet supported by this implementation, which interprets the - format string as sequence of char.) - TODO: Add multibyte support to printf() functions. - - A conversion specifier consists of: - - Zero or more flags (one of the characters "-+ #0"). - - Optional minimum field width as decimal integer. Default is padding to the - left, using spaces. Note that 0 is taken as a flag, not the beginning of a - field width. Note also that a small field width will not result in the - truncation of a value. - - Optional precision (given as ".#" with # being a decimal integer), - specifying: - - the min. number of digits to appear (diouxX), - - the max. number of digits after the decimal point (aAeEfF), - - the max. number of significant digits (gG), - - the max. number of bytes to be written (s). - - behaviour with other conversion specifiers is undefined. - - Optional length modifier specifying the size of the argument (one of "hh", - "ll", or one of the characters "hljztL"). - - Conversion specifier character specifying the type of conversion to be - applied (and the type of the next argument from the argument stack). One - of the characters "diouxXfFeEgGaAcspn%". - - Minimum field width and/or precision may be given as asterisk ('*') instead - of a decimal integer. In this case, the next argument from the argument - stack is assumed to be an int value specifying the width / precision. A - negative field width is interpreted as flag '-' followed by a positive field - width. A negative precision is interpreted as if no precision was given. - - FLAGS - - Left-justify the conversion result within its field width. - + Prefix a '+' on positive signed conversion results. Prefix a '-' on - floating conversions resulting in negative zero, or negative values - rounding to zero. - space Prefix a space on positive signed conversion results, or if a signed - conversion results in no characters. If both '+' and ' ' are given, - ' ' is ignored. - # Use an "alternative form" for - - 'o' conversion, increasing precision until the first digit of the - result is a zero; - - 'x' or 'X' conversion, prefixing "0x" or "0X" to nonzero results; - - "aAeEfF" conversions, always printing a decimal point even if no - digits are following; - - 'g' or 'G' conversions, always printing a decimal point even if no - digits are following, and not removing trailing zeroes. - - behaviour for other conversions is unspecified. - 0 Use leading zeroes instead of spaces for field width padding. If both - '-' and '0' are given, '0' is ignored. If a precision is specified for - any of the "diouxX" conversions, '0' is ignored. Behaviour is only - defined for "diouxXaAeEfFgG". - - LENGTH MODIFIERS - hh For "diouxX" conversions, the argument from the argument stack is - assumed to be of char width. (It will have been subject to integer - promotion but will be converted back.) For 'n' conversions, the argument - is assumed to be a pointer to signed char. - h For "diouxX" conversions, the argument from the argument stack is - assumed to be of short int width. (It will have been subject to integer - promotion but will be converted back.) For 'n' conversions, the argument - is assumed to be a pointer to short int. - l For "diouxX" conversions, the argument from the argument stack is - assumed to be of long int width. For 'n' conversions, the argument is - assumed to be a pointer to short int. For 'c' conversions, the argument - is assumed to be a wint_t. For 's' conversions, the argument is assumed - to be a pointer to wchar_t. No effect on "aAeEfFgG" conversions. - ll For "diouxX" conversions, the argument from the argument stack is - assumed to be of long long int width. For 'n' conversions, the argument - is assumed to be a pointer to long long int. - j For "diouxX" conversions, the argument from the argument stack is - assumed to be of intmax_t width. For 'n' conversions, the argument is - assumed to be a pointer to intmax_t. - z For "diouxX" conversions, the argument from the argument stack is - assumed to be of size_t width. For 'n' conversions, the argument is - assumed to be a pointer to size_t. - t For "diouxX" conversions, the argument from the argument stack is - assumed to be of ptrdiff_t width. For 'n' conversions, the argument is - assumed to be a pointer to ptrdiff_t. - L For "aAeEfFgG" conversions, the argument from the argument stack is - assumed to be a long double. - Length modifiers appearing for any conversions not mentioned above will have - undefined behaviour. - If a length modifier appears with any conversion specifier other than as - specified above, the behavior is undefined. - - CONVERSION SPECIFIERS - d,i The argument from the argument stack is assumed to be of type int, and - is converted to a signed decimal value with a minimum number of digits - as specified by the precision (default 1), padded with leading zeroes. - A zero value converted with precision zero yields no output. - o The argument from the argument stack is assumed to be of type unsigned - int, and is converted to an unsigned octal value, other behaviour being - as above. - u The argument from the argument stack is assumed to be of type unsigned - int, and converted to an unsigned decimal value, other behaviour being - as above. - x,X The argument from the argument stack is assumed to be of type unsigned - int, and converted to an unsigned hexadecimal value, using lowercase - "abcdef" for 'x' and uppercase "ABCDEF" for 'X' conversion, other - behaviour being as above. - f,F The argument from the argument stack is assumed to be of type double, - and converted to a decimal floating point in decimal-point notation, - with the number of digits after the decimal point as specified by the - precision (default 6) and the value being rounded appropriately. If - precision is zero (and the '#' flag is not given), no decimal point is - printed. At least one digit is always printed before the decimal point. - For 'f' conversions, an infinity value is printed as either [-]inf or - [-]infinity (, depending on the configuration of this implementation. A - NaN value is printed as [-]nan. For 'F' conversions uppercase characters - are used for these special values. The flags '-', '+' and ' ' apply as - usual to these special values, '#' and '0' have no effect. - e,E The argument from the argument stack is assumed to be of type double, - and converted to a decimal floating point in normalized exponential - notation ([?]d.ddd edd). "Normalized" means one nonzero digit before - the decimal point, unless the value is zero. The number of digits after - the decimal point is specified by the precision (default 6), the value - being rounded appropriately. If precision is zero (and the '#' flag is - not given), no decimal point is printed. The exponent has at least two - digits, and not more than necessary to represent the exponent. If the - value is zero, the exponent is zero. The 'e' written to indicate the - exponend is uppercase for 'E' conversions. - Infinity or NaN values are represented as for 'f' and 'F' conversions, - respectively. - g,G The argument from the argument stack is assumed to be of type double, - and converted according to either 'f' or 'e' format for 'g' conversions, - or 'F' or 'E' format for 'G' conversions, respectively, with the actual - conversion chosen depending on the value. 'e' / 'E' conversion is chosen - if the resulting exponent is < -4 or >= the precision (default 1). - Trailing zeroes are removed (unless the '#' flag is given). A decimal - point appears only if followed by a digit. - Infinity or NaN values are represented as for 'f' and 'F' conversions, - respectively. - a,A The argument from the argument stack is assumed to be of type double, - and converted to a floating point hexadecimal notation ([?]0xh.hhhh pd) - with one hexadecimal digit (being nonzero if the value is normalized, - and otherwise unspecified) before the decimal point, and the number of - digits after the decimal point being specified by the precision. If no - precision is given, the default is to print as many digits as nevessary - to give an exact representation of the value (if FLT_RADIX is a power of - 2). If no precision is given and FLT_RADIX is not a power of 2, the - default is to print as many digits to distinguish values of type double - (possibly omitting trailing zeroes). (A precision p is sufficient to - distinguish values of the source type if 16^p-1 > b^n where b is - FLT_RADIX and n is the number of digits in the significand (to base b) - of the source type. A smaller p might suffice depending on the - implementation's scheme for determining the digit to the left of the - decimal point.) The error has the correct sign for the current rounding - direction. - Unless the '#' flag is given, no decimal-point is given for zero - precision. - The 'a' conversion uses lowercase "abcdef", "0x" and 'p', the 'A' - conversion uppercase "ABCDEF", "0X" and 'P'. - The exponent always has at least one digit, and not more than necessary - to represent the decimal exponent of 2. If the value is zero, the - exponent is zero. - Infinity or NaN values are represented as for 'f' and 'F' conversions, - respectively. - Binary implementations are at liberty to chose the hexadecimal digit to - the left of the decimal point so that subsequent digits align to nibble - boundaries. - c The argument from the argument stack is assumed to be of type int, and - converted to a character after the value has been cast to unsigned char. - If the 'l' length modifier is given, the argument is assumed to be of - type wint_t, and converted as by a "%ls" conversion with no precision - and a pointer to a two-element wchar_t array, with the first element - being the wint_t argument and the second a '\0' wide character. - s The argument from the argument stack is assumed to be a char array (i.e. - pointer to char). Characters from that array are printed until a zero - byte is encountered or as many bytes as specified by a given precision - have been written. - If the l length modifier is given, the argument from the argument stack - is assumed to be a wchar_t array (i.e. pointer to wchar_t). Wide - characters from that array are converted to multibyte characters as by - calls to wcrtomb() (using a mbstate_t object initialized to zero prior - to the first conversion), up to and including the terminating null wide - character. The resulting multibyte character sequence is then printed up - to but not including the terminating null character. If a precision is - given, it specifies the maximum number of bytes to be written (including - shift sequences). If the given precision would require access to a wide - character one past the end of the array, the array shall contain a '\0' - wide character. In no case is a partial multibyte character written. - Redundant shift sequences may result if the multibyte characters have a - state-dependent encoding. - TODO: Clarify these statements regarding %ls. - p The argument from the argument stack is assumed to be a void pointer, - and converted to a sequence of printing characters in an implementation- - defined manner. - This implementation casts the pointer to type intptr_t, and prints the - value as if a %#x conversion specifier was given. - n The argument from the argument stack is assumed to be a pointer to a - signed integer, into which the number of characters written so far by - this call to fprintf is stored. The behaviour, should any flags, field - widths, or precisions be given is undefined. - % A verbatim '%' character is written. No argument is taken from the - argument stack. - - Returns the number of characters written if successful, a negative value - otherwise. -*/ -int fprintf( FILE * restrict stream, const char * restrict format, ... ); - -/* TODO: fscanf() documentation */ -/* - Read input from a given stream, as defined by the given format string, and - store converted input in the objects pointed to by 0..n subsequent arguments - (the argument stack). - - The format string contains a sequence of directives that are expected to - match the input. If such a directive fails to match, the function returns - (matching error). It also returns if an input error occurs (input error). - - Directives can be: - - one or more whitespaces, matching any number of whitespaces in the input; - - printing characters, matching the input verbatim; - - conversion specifications, which convert an input sequence into a value as - defined by the individual specifier, and store that value in a memory - location pointed to by the next pointer on the argument stack. Details are - documented below. If there is an insufficient number of pointers on the - argument stack, behaviour is undefined. Additional arguments not required - by any conversion specifications are evaluated, but otherwise ignored. - - (The standard specifies the format string is allowed to contain multibyte - character sequences as long as it starts and ends in initial shift state, - but this is not yet supported by this implementation, which interprets the - format string as sequence of char.) - TODO: Add multibyte support to scanf() functions. - - A conversion specifier consists of: - - Optional assignment-suppressing character ('*') that makes the conversion - read input as usual, but does not assign the conversion result. - - Optional maximum field width as decimal integer. - - Optional length modifier specifying the size of the argument (one of "hh", - "ll", or one of the characters "hljztL"). - - Conversion specifier character specifying the type of conversion to be - applied (and the type of the next argument from the argument stack). One - of the characters "diouxXaAeEfFgGcs[pn%". - - LENGTH MODIFIERS - hh For "diouxXn" conversions, the next pointer from the argument stack is - assumed to point to a variable of of char width. - h For "diouxXn" conversions, the next pointer from the argument stack is - assumed to point to a variable of short int width. - l For "diouxXn" conversions, the next pointer from the argument stack is - assumed to point to a variable of long int width. - For "aAeEfFgG" conversions, it is assumed to point to a variable of type - double. - For "cs[" conversions, it is assumed to point to a variable of type - wchar_t. - ll For "diouxXn" conversions, the next pointer from the argument stack is - assumed to point to a variable of long long int width. - j For "diouxXn" conversions, the next pointer from the argument stack is - assumed to point to a variable of intmax_t width. - z For "diouxXn" conversions, the next pointer from the argument stack is - assumed to point to a variable of size_t width. - t For "diouxXn" conversions, the next pointer from the argument stack is - assumed to point to a variable of ptrdiff_t width. - L For "aAeEfFgG" conversions, the next pointer from the argument stack is - assumed to point to a variable of type long double. - Length modifiers appearing for any conversions not mentioned above will have - undefined behaviour. - If a length modifier appears with any conversion specifier other than as - specified above, the behavior is undefined. - - CONVERSION SPECIFIERS - d Matches an (optionally signed) decimal integer of the format expected - by strtol() with base 10. The next pointer from the argument stack is - assumed to point to a signed integer. - i Matches an (optionally signed) integer of the format expected by - strtol() with base 0. The next pointer from the argument stack is - assumed to point to a signed integer. - o Matches an (optionally signed) octal integer of the format expected by - strtoul() with base 8. The next pointer from the argument stack is - assumed to point to an unsigned integer. - u Matches an (optionally signed) decimal integer of the format expected - by strtoul() with base 10. The next pointer from the argument stack is - assumed to point to an unsigned integer. - x Matches an (optionally signed) hexadecimal integer of the format - expected by strtoul() with base 16. The next pointer from the argument - stack is assumed to point to an unsigned integer. - aefg Matches an (optionally signed) floating point number, infinity, or not- - a-number-value of the format expected by strtod(). The next pointer - from the argument stack is assumed to point to a float. - c Matches a number of characters as specified by the field width (default - 1). The next pointer from the argument stack is assumed to point to a - character array large enough to hold that many characters. - If the 'l' length modifier is given, the input is assumed to match a - sequence of multibyte characters (starting in the initial shift state), - which will be converted to a wide character sequence as by successive - calls to mbrtowc() with a mbstate_t object initialized to zero prior to - the first conversion. The next pointer from the argument stack is - assumed to point to a wchar_t array large enough to hold that many - characters. - In either case, note that no '\0' character is added to terminate the - sequence. - s Matches a sequence of non-white-space characters. The next pointer from - the argument stack is assumed to point to a character array large - enough to hold the sequence including terminating '\0' character. - If the 'l' length modifier is given, the input is assumed to match a - sequence of multibyte characters (starting in the initial shift state), - which will be converted to a wide character sequence as by a call to - mbrtowc() with a mbstate_t object initialized to zero prior to the - first conversion. The next pointer from the argument stack is assumed - to point to a wchar_t array large enough to hold the sequence including - terminating '\0' character. - [ Matches a nonempty sequence consisting of any of those characters - specified between itself and a corresponding closing bracket (']'). - If the first character in the list is a circumflex ('^'), this matches - a nonempty sequence consisting of any characters NOT specified. If the - closing bracket appears as the first character in the scanset ("[]" or - "[^]", it is assumed to belong to the scanset, which then ends with the - NEXT closing bracket. - If there is a '-' character in the scanset which is not the first after - the opening bracket (or the circumflex, see above) or the last in the - scanset, behaviour is implementation-defined. This implementation - handles this character like any other. - - The extend of the input field is determined byte-by-byte for the above - conversions ('c', 's', '['), with no special provisions being made for - multibyte characters. The resulting field is nevertheless a multibyte - sequence begining in intial shift state. - - p Matches a sequence of characters as produced by the printf() "%p" - conversion. The next pointer from the argument stack is assumed to - point to a void pointer, which will be filled with the same location - as the pointer used in the printf() statement. Note that behaviour is - undefined if the input value is not the result of an earlier printf() - call. - n Does not read input. The next pointer from the argument stack is - assumed to point to a signed integer, into which the number of - characters read from input so far by this call to fscanf() is stored. - This does not affect the return value of fscanf(). The behaviour, - should an assignment-supressing character of field width be given, - is undefined. - This can be used to test the success of literal matches and suppressed - assignments. - % Matches a single, verbatim '%' character. - - A, E, F, G and X are valid, and equivalent to their lowercase counterparts. - - All conversions except [, c, or n imply that whitespace characters from the - input stream are consumed until a non-whitespace character is encountered. - Such whitespaces do not count against a maximum field width. - - Conversions push at most one character back into the input stream. That - implies that some character sequences converted by the strtol() and strtod() - function families are not converted identically by the scnaf() function - family. - - Returns the number of input items successfully assigned. This can be zero if - an early mismatch occurs. Returns EOF if an input failure occurs before the - first conversion. -*/ -int fscanf( FILE * restrict stream, const char * restrict format, ... ); - -/* Equivalent to fprintf( stdout, format, ... ). */ -int printf( const char * restrict format, ... ); - -/* Equivalent to fscanf( stdin, format, ... ). */ -int scanf( const char * restrict format, ... ); - -/* Equivalent to fprintf( stdout, format, ... ), except that the result is - written into the buffer pointed to by s, instead of stdout, and that any - characters beyond the (n-1)th are discarded. The (n)th character is - replaced by a '\0' character in this case. - Returns the number of characters that would have been written (not counting - the terminating '\0' character) if n had been sufficiently large, if - successful, and a negative number if an encoding error ocurred. -*/ -int snprintf( char * restrict s, size_t n, const char * restrict format, ... ); - -/* Equivalent to fprintf( stdout, format, ... ), except that the result is - written into the buffer pointed to by s, instead of stdout. -*/ -int sprintf( char * restrict s, const char * restrict format, ... ); - -/* Equivalent to fscanf( stdin, format, ... ), except that the input is read - from the buffer pointed to by s, instead of stdin. -*/ -int sscanf( const char * restrict s, const char * restrict format, ... ); - -/* Equivalent to fprintf( stream, format, ... ), except that the argument stack - is passed as va_list parameter. Note that va_list is not declared by - . -*/ -int vfprintf( FILE * restrict stream, const char * restrict format, _PDCLIB_va_list arg ); - -/* Equivalent to fscanf( stream, format, ... ), except that the argument stack - is passed as va_list parameter. Note that va_list is not declared by - . -*/ -int vfscanf( FILE * restrict stream, const char * restrict format, _PDCLIB_va_list arg ); - -/* Equivalent to fprintf( stdout, format, ... ), except that the argument stack - is passed as va_list parameter. Note that va_list is not declared by - . -*/ -int vprintf( const char * restrict format, _PDCLIB_va_list arg ); - -/* Equivalent to fscanf( stdin, format, ... ), except that the argument stack - is passed as va_list parameter. Note that va_list is not declared by - . -*/ -int vscanf( const char * restrict format, _PDCLIB_va_list arg ); - -/* Equivalent to snprintf( s, n, format, ... ), except that the argument stack - is passed as va_list parameter. Note that va_list is not declared by - . - */ -int vsnprintf( char * restrict s, size_t n, const char * restrict format, _PDCLIB_va_list arg ); - -/* Equivalent to fprintf( stdout, format, ... ), except that the argument stack - is passed as va_list parameter, and the result is written to the buffer - pointed to by s, instead of stdout. Note that va_list is not declared by - . -*/ -int vsprintf( char * restrict s, const char * restrict format, _PDCLIB_va_list arg ); - -/* Equivalent to fscanf( stdin, format, ... ), except that the argument stack - is passed as va_list parameter, and the input is read from the buffer - pointed to by s, instead of stdin. Note that va_list is not declared by - . -*/ -int vsscanf( const char * restrict s, const char * restrict format, _PDCLIB_va_list arg ); - -/* Character input/output functions */ - -/* Retrieve the next character from given stream. - Returns the character, EOF otherwise. - If end-of-file is reached, the EOF indicator of the stream is set. - If a read error occurs, the error indicator of the stream is set. -*/ -int fgetc( FILE * stream ); - -/* Read at most n-1 characters from given stream into the array s, stopping at - \n or EOF. Terminate the read string with \n. If EOF is encountered before - any characters are read, leave the contents of s unchanged. - Returns s if successful, NULL otherwise. - If a read error occurs, the error indicator of the stream is set. In this - case, the contents of s are indeterminate. -*/ -char * fgets( char * restrict s, int n, FILE * restrict stream ); - -/* Write the value c (cast to unsigned char) to the given stream. - Returns c if successful, EOF otherwise. - If a write error occurs, sets the error indicator of the stream is set. -*/ -int fputc( int c, FILE * stream ); - -/* Write the string s (not including the terminating \0) to the given stream. - Returns a value >=0 if successful, EOF otherwise. - This implementation does set the error indicator of the stream if a write - error occurs. -*/ -int fputs( const char * restrict s, FILE * restrict stream ); - -/* Equivalent to fgetc( stream ), but may be overloaded by a macro that - evaluates its parameter more than once. -*/ -int getc( FILE * stream ); - -/* Equivalent to fgetc( stdin ). */ -int getchar( void ); - -/* Equivalent to fputc( c, stream ), but may be overloaded by a macro that - evaluates its parameter more than once. -*/ -int putc( int c, FILE * stream ); - -/* Equivalent to fputc( c, stdout ), but may be overloaded by a macro that - evaluates its parameter more than once. -*/ -int putchar( int c ); - -/* Write the string s (not including the terminating \0) to stdout, and append - a newline to the output. Returns a value >= 0 when successful, EOF if a - write error occurred. -*/ -int puts( const char * s ); - -/* Push the value c (cast to unsigned char) back onto the given (input) stream. - A character pushed back in this way will be delivered by subsequent read - operations (and skipped by subsequent file positioning operations) as if it - has not been read. The external representation of the stream is unaffected - by this pushback (it is a buffer operation). One character of pushback is - guaranteed, further pushbacks may fail. EOF as value for c does not change - the input stream and results in failure of the function. - For text files, the file position indicator is indeterminate until all - pushed-back characters are read. For binary files, the file position - indicator is decremented by each successful call of ungetc(). If the file - position indicator for a binary file was zero before the call of ungetc(), - behaviour is undefined. (Older versions of the library allowed such a call.) - Returns the pushed-back character if successful, EOF if it fails. -*/ -int ungetc( int c, FILE * stream ); - -/* Direct input/output functions */ - -/* Read up to nmemb elements of given size from given stream into the buffer - pointed to by ptr. Returns the number of elements successfully read, which - may be less than nmemb if a read error or EOF is encountered. If a read - error is encountered, the value of the file position indicator is - indeterminate. If a partial element is read, its value is indeterminate. - If size or nmemb are zero, the function does nothing and returns zero. -*/ -size_t fread( void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream ); - -/* Write up to nmemb elements of given size from buffer pointed to by ptr to - the given stream. Returns the number of elements successfully written, which - will be less than nmemb only if a write error is encountered. If a write - error is encountered, the value of the file position indicator is - indeterminate. If size or nmemb are zero, the function does nothing and - returns zero. -*/ -size_t fwrite( const void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream ); - -/* File positioning functions */ - -/* Store the current position indicator (and, where appropriate, the current - mbstate_t status object) for the given stream into the given pos object. The - actual contents of the object are unspecified, but it can be used as second - parameter to fsetpos() to reposition the stream to the exact position and - parse state at the time fgetpos() was called. - Returns zero if successful, nonzero otherwise. - TODO: Implementation-defined errno setting for fgetpos(). -*/ -int fgetpos( FILE * restrict stream, fpos_t * restrict pos ); - -/* Set the position indicator for the given stream to the given offset from: - - the beginning of the file if whence is SEEK_SET, - - the current value of the position indicator if whence is SEEK_CUR, - - end-of-file if whence is SEEK_END. - On text streams, non-zero offsets are only allowed with SEEK_SET, and must - have been returned by ftell() for the same file. - Any characters buffered by ungetc() are dropped, the end-of-file indicator - for the stream is cleared. If the given stream is an update stream, the next - operation after a successful fseek() may be either input or output. - Returns zero if successful, nonzero otherwise. If a read/write error occurs, - the error indicator for the given stream is set. -*/ -int fseek( FILE * stream, long int offset, int whence ); - -/* Set the position indicator (and, where appropriate the mbstate_t status - object) for the given stream to the given pos object (created by an earlier - call to fgetpos() on the same file). - Any characters buffered by ungetc() are dropped, the end-of-file indicator - for the stream is cleared. If the given stream is an update stream, the next - operation after a successful fsetpos() may be either input or output. - Returns zero if successful, nonzero otherwise. If a read/write error occurs, - the error indicator for the given stream is set. - TODO: Implementation-defined errno setting for fsetpos(). -*/ -int fsetpos( FILE * stream, const fpos_t * pos ); - -/* Return the current offset of the given stream from the beginning of the - associated file. For text streams, the exact value returned is unspecified - (and may not be equal to the number of characters), but may be used in - subsequent calls to fseek(). - Returns -1L if unsuccessful. - TODO: Implementation-defined errno setting for ftell(). -*/ -long int ftell( FILE * stream ); - -/* Equivalent to (void)fseek( stream, 0L, SEEK_SET ), except that the error - indicator for the stream is also cleared. -*/ -void rewind( FILE * stream ); - -/* Error-handling functions */ - -/* Clear the end-of-file and error indicators for the given stream. */ -void clearerr( FILE * stream ); - -/* Return zero if the end-of-file indicator for the given stream is not set, - nonzero otherwise. -*/ -int feof( FILE * stream ); - -/* Return zero if the error indicator for the given stream is not set, nonzero - otherwise. -*/ -int ferror( FILE * stream ); - -/* If s is neither a NULL pointer nor an empty string, print the string to - stderr (with appended colon (':') and a space) first. In any case, print an - error message depending on the current value of errno (being the same as if - strerror( errno ) had been called). -*/ -void perror( const char * s ); - -CPP_CHECK_END diff --git a/src/libraries/libc/stdio/clearerr.c b/src/libraries/libc/stdio/clearerr.c deleted file mode 100644 index 0dbf9c1..0000000 --- a/src/libraries/libc/stdio/clearerr.c +++ /dev/null @@ -1,12 +0,0 @@ -/* clearerr( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void clearerr( struct _PDCLIB_file_t * stream ) -{ - stream->status &= ~( _PDCLIB_ERRORFLAG | _PDCLIB_EOFFLAG ); -} diff --git a/src/libraries/libc/stdio/fclose.c b/src/libraries/libc/stdio/fclose.c deleted file mode 100644 index c321f35..0000000 --- a/src/libraries/libc/stdio/fclose.c +++ /dev/null @@ -1,67 +0,0 @@ -/* fclose( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include "j6libc/glue.h" - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -int fclose( struct _PDCLIB_file_t * stream ) -{ - struct _PDCLIB_file_t * current = _PDCLIB_filelist; - struct _PDCLIB_file_t * previous = NULL; - /* Checking that the FILE handle is actually one we had opened before. */ - while ( current != NULL ) - { - if ( stream == current ) - { - /* Flush buffer */ - if ( stream->status & _PDCLIB_FWRITE ) - { - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - /* Flush failed, errno already set */ - return EOF; - } - } - /* Close handle */ - _PDCLIB_close( stream->handle ); - /* Remove stream from list */ - if ( previous != NULL ) - { - previous->next = stream->next; - } - else - { - _PDCLIB_filelist = stream->next; - } - /* Delete tmpfile() */ - if ( stream->status & _PDCLIB_DELONCLOSE ) - { - remove( stream->filename ); - } - /* Free user buffer (SetVBuf allocated) */ - if ( stream->status & _PDCLIB_FREEBUFFER ) - { - free( stream->buffer ); - } - /* Free stream */ - if ( ! ( stream->status & _PDCLIB_STATIC ) ) - { - free( stream ); - } - return 0; - } - previous = current; - current = current->next; - } - /* See the comments on implementation-defined errno values in - . - */ - _PDCLIB_errno = _PDCLIB_ERROR; - return -1; -} diff --git a/src/libraries/libc/stdio/feof.c b/src/libraries/libc/stdio/feof.c deleted file mode 100644 index 56c1115..0000000 --- a/src/libraries/libc/stdio/feof.c +++ /dev/null @@ -1,12 +0,0 @@ -/* feof( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int feof( struct _PDCLIB_file_t * stream ) -{ - return stream->status & _PDCLIB_EOFFLAG; -} diff --git a/src/libraries/libc/stdio/ferror.c b/src/libraries/libc/stdio/ferror.c deleted file mode 100644 index 06baded..0000000 --- a/src/libraries/libc/stdio/ferror.c +++ /dev/null @@ -1,12 +0,0 @@ -/* ferror( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int ferror( struct _PDCLIB_file_t * stream ) -{ - return stream->status & _PDCLIB_ERRORFLAG; -} diff --git a/src/libraries/libc/stdio/fflush.c b/src/libraries/libc/stdio/fflush.c deleted file mode 100644 index 48d8f32..0000000 --- a/src/libraries/libc/stdio/fflush.c +++ /dev/null @@ -1,36 +0,0 @@ -/* fflush( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -int fflush( struct _PDCLIB_file_t * stream ) -{ - if ( stream == NULL ) - { - int rc = 0; - stream = _PDCLIB_filelist; - /* TODO: Check what happens when fflush( NULL ) encounters write errors, in other libs */ - while ( stream != NULL ) - { - if ( stream->status & _PDCLIB_FWRITE ) - { - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - rc = EOF; - } - } - stream = stream->next; - } - return rc; - } - else - { - return _PDCLIB_flushbuffer( stream ); - } -} diff --git a/src/libraries/libc/stdio/fgetc.c b/src/libraries/libc/stdio/fgetc.c deleted file mode 100644 index b71b449..0000000 --- a/src/libraries/libc/stdio/fgetc.c +++ /dev/null @@ -1,21 +0,0 @@ -/* fgetc( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -int fgetc( struct _PDCLIB_file_t * stream ) -{ - if ( _PDCLIB_prepread( stream ) == EOF ) - { - return EOF; - } - if ( stream->ungetidx > 0 ) - { - return (unsigned char)stream->ungetbuf[ --(stream->ungetidx) ]; - } - return (unsigned char)stream->buffer[stream->bufidx++]; -} diff --git a/src/libraries/libc/stdio/fgetpos.c b/src/libraries/libc/stdio/fgetpos.c deleted file mode 100644 index 0076489..0000000 --- a/src/libraries/libc/stdio/fgetpos.c +++ /dev/null @@ -1,15 +0,0 @@ -/* fgetpos( FILE * , fpos_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int fgetpos( struct _PDCLIB_file_t * restrict stream, struct _PDCLIB_fpos_t * restrict pos ) -{ - pos->offset = stream->pos.offset + stream->bufidx - stream->ungetidx; - pos->status = stream->pos.status; - /* TODO: Add mbstate. */ - return 0; -} diff --git a/src/libraries/libc/stdio/fgets.c b/src/libraries/libc/stdio/fgets.c deleted file mode 100644 index 410a6a5..0000000 --- a/src/libraries/libc/stdio/fgets.c +++ /dev/null @@ -1,42 +0,0 @@ -/* fgets( char *, int, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -char * fgets( char * restrict s, int size, struct _PDCLIB_file_t * restrict stream ) -{ - char * dest = s; - if ( size == 0 ) - { - return NULL; - } - if ( size == 1 ) - { - *s = '\0'; - return s; - } - if ( _PDCLIB_prepread( stream ) == EOF ) - { - return NULL; - } - while ( ( ( *dest++ = stream->buffer[stream->bufidx++] ) != '\n' ) && --size > 0 ) - { - if ( stream->bufidx == stream->bufend ) - { - if ( _PDCLIB_fillbuffer( stream ) == EOF ) - { - /* In case of error / EOF before a character is read, this - will lead to a \0 be written anyway. Since the results - are "indeterminate" by definition, this does not hurt. - */ - break; - } - } - } - *dest = '\0'; - return ( dest == s ) ? NULL : s; -} diff --git a/src/libraries/libc/stdio/fopen.c b/src/libraries/libc/stdio/fopen.c deleted file mode 100644 index b3dd147..0000000 --- a/src/libraries/libc/stdio/fopen.c +++ /dev/null @@ -1,70 +0,0 @@ -/* fopen( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include "j6libc/glue.h" - -#include - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -struct _PDCLIB_file_t * fopen( const char * restrict filename, const char * restrict mode ) -{ - struct _PDCLIB_file_t * rc; - size_t filename_len; - if ( mode == NULL || filename == NULL || filename[0] == '\0' ) - { - /* Mode or filename invalid */ - return NULL; - } - /* To reduce the number of malloc calls, all data fields are concatenated: - * the FILE structure itself, - * ungetc buffer, - * filename buffer, - * data buffer. - Data buffer comes last because it might change in size ( setvbuf() ). - */ - filename_len = strlen( filename ) + 1; - if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + filename_len + BUFSIZ ) ) == NULL ) - { - /* no memory */ - return NULL; - } - if ( ( rc->status = _PDCLIB_filemode( mode ) ) == 0 ) - { - /* invalid mode */ - free( rc ); - return NULL; - } - rc->handle = _PDCLIB_open( filename, rc->status ); - if ( rc->handle == _PDCLIB_NOHANDLE ) - { - /* OS open() failed */ - free( rc ); - return NULL; - } - /* Setting pointers into the memory block allocated above */ - rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t ); - rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE; - rc->buffer = rc->filename + filename_len; - /* Copying filename to FILE structure */ - strcpy( rc->filename, filename ); - /* Initializing the rest of the structure */ - rc->bufsize = BUFSIZ; - rc->bufidx = 0; - rc->ungetidx = 0; - /* Setting buffer to _IOLBF because "when opened, a stream is fully - buffered if and only if it can be determined not to refer to an - interactive device." - */ - rc->status |= _IOLBF; - /* TODO: Setting mbstate */ - /* Adding to list of open files */ - rc->next = _PDCLIB_filelist; - _PDCLIB_filelist = rc; - return rc; -} diff --git a/src/libraries/libc/stdio/fprintf.c b/src/libraries/libc/stdio/fprintf.c deleted file mode 100644 index 562ce70..0000000 --- a/src/libraries/libc/stdio/fprintf.c +++ /dev/null @@ -1,18 +0,0 @@ -/* fprintf( FILE *, const char *, ... ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int fprintf( struct _PDCLIB_file_t * restrict stream, const char * restrict format, ... ) -{ - int rc; - va_list ap; - va_start( ap, format ); - rc = vfprintf( stream, format, ap ); - va_end( ap ); - return rc; -} diff --git a/src/libraries/libc/stdio/fputc.c b/src/libraries/libc/stdio/fputc.c deleted file mode 100644 index 8a55f84..0000000 --- a/src/libraries/libc/stdio/fputc.c +++ /dev/null @@ -1,30 +0,0 @@ -/* fputc( int, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -/* Write the value c (cast to unsigned char) to the given stream. - Returns c if successful, EOF otherwise. - If a write error occurs, the error indicator of the stream is set. -*/ -int fputc( int c, struct _PDCLIB_file_t * stream ) -{ - if ( _PDCLIB_prepwrite( stream ) == EOF ) - { - return EOF; - } - stream->buffer[stream->bufidx++] = (char)c; - if ( ( stream->bufidx == stream->bufsize ) /* _IOFBF */ - || ( ( stream->status & _IOLBF ) && ( (char)c == '\n' ) ) /* _IOLBF */ - || ( stream->status & _IONBF ) /* _IONBF */ - ) - { - /* buffer filled, unbuffered stream, or end-of-line. */ - return ( _PDCLIB_flushbuffer( stream ) == 0 ) ? c : EOF; - } - return c; -} diff --git a/src/libraries/libc/stdio/fputs.c b/src/libraries/libc/stdio/fputs.c deleted file mode 100644 index f52d61d..0000000 --- a/src/libraries/libc/stdio/fputs.c +++ /dev/null @@ -1,42 +0,0 @@ -/* fputs( const char *, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -int fputs( const char * restrict s, struct _PDCLIB_file_t * restrict stream ) -{ - if ( _PDCLIB_prepwrite( stream ) == EOF ) - { - return EOF; - } - while ( *s != '\0' ) - { - /* Unbuffered and line buffered streams get flushed when fputs() does - write the terminating end-of-line. All streams get flushed if the - buffer runs full. - */ - stream->buffer[ stream->bufidx++ ] = *s; - if ( ( stream->bufidx == stream->bufsize ) || - ( ( stream->status & _IOLBF ) && *s == '\n' ) - ) - { - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - return EOF; - } - } - ++s; - } - if ( stream->status & _IONBF ) - { - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - return EOF; - } - } - return 0; -} diff --git a/src/libraries/libc/stdio/fread.c b/src/libraries/libc/stdio/fread.c deleted file mode 100644 index 923c8fa..0000000 --- a/src/libraries/libc/stdio/fread.c +++ /dev/null @@ -1,36 +0,0 @@ -/* fwrite( void *, size_t, size_t, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include "j6libc/glue.h" - -size_t fread( void * restrict ptr, size_t size, size_t nmemb, struct _PDCLIB_file_t * restrict stream ) -{ - char * dest = (char *)ptr; - size_t nmemb_i; - if ( _PDCLIB_prepread( stream ) == EOF ) - { - return 0; - } - for ( nmemb_i = 0; nmemb_i < nmemb; ++nmemb_i ) - { - size_t size_i; - for ( size_i = 0; size_i < size; ++size_i ) - { - if ( stream->bufidx == stream->bufend ) - { - if ( _PDCLIB_fillbuffer( stream ) == EOF ) - { - /* Could not read requested data */ - return nmemb_i; - } - } - dest[ nmemb_i * size + size_i ] = stream->buffer[ stream->bufidx++ ]; - } - } - return nmemb_i; -} diff --git a/src/libraries/libc/stdio/freopen.c b/src/libraries/libc/stdio/freopen.c deleted file mode 100644 index 331b60c..0000000 --- a/src/libraries/libc/stdio/freopen.c +++ /dev/null @@ -1,70 +0,0 @@ -/* freopen( const char *, const char *, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include "j6libc/glue.h" - -struct _PDCLIB_file_t * freopen( const char * restrict filename, const char * restrict mode, struct _PDCLIB_file_t * restrict stream ) -{ - unsigned int status = stream->status & ( _IONBF | _IOLBF | _IOFBF | _PDCLIB_FREEBUFFER | _PDCLIB_DELONCLOSE ); - /* TODO: This function can change wide orientation of a stream */ - if ( stream->status & _PDCLIB_FWRITE ) - { - _PDCLIB_flushbuffer( stream ); - } - if ( ( filename == NULL ) && ( stream->filename == NULL ) ) - { - /* TODO: Special handling for mode changes on std-streams */ - return NULL; - } - _PDCLIB_close( stream->handle ); - /* TODO: It is not nice to do this on a stream we just closed. - It does not matter with the current implementation of clearerr(), - but it might start to matter if someone replaced that implementation. - */ - clearerr( stream ); - /* The new filename might not fit the old buffer */ - if ( filename == NULL ) - { - /* Use previous filename */ - filename = stream->filename; - } - else if ( ( stream->filename != NULL ) && ( strlen( stream->filename ) >= strlen( filename ) ) ) - { - /* Copy new filename into existing buffer */ - strcpy( stream->filename, filename ); - } - else - { - /* Allocate new buffer */ - if ( ( stream->filename = (char *)malloc( strlen( filename ) ) ) == NULL ) - { - return NULL; - } - strcpy( stream->filename, filename ); - } - if ( ( mode == NULL ) || ( filename[0] == '\0' ) ) - { - return NULL; - } - if ( ( stream->status = _PDCLIB_filemode( mode ) ) == 0 ) - { - return NULL; - } - /* Re-add the flags we saved above */ - stream->status |= status; - stream->bufidx = 0; - stream->bufend = 0; - stream->ungetidx = 0; - /* TODO: Setting mbstate */ - if ( ( stream->handle = _PDCLIB_open( filename, stream->status ) ) == _PDCLIB_NOHANDLE ) - { - return NULL; - } - return stream; -} diff --git a/src/libraries/libc/stdio/fscanf.c b/src/libraries/libc/stdio/fscanf.c deleted file mode 100644 index 15115b5..0000000 --- a/src/libraries/libc/stdio/fscanf.c +++ /dev/null @@ -1,18 +0,0 @@ -/* fscanf( FILE *, const char *, ... ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int fscanf( FILE * restrict stream, const char * restrict format, ... ) -{ - int rc; - va_list ap; - va_start( ap, format ); - rc = vfscanf( stream, format, ap ); - va_end( ap ); - return rc; -} diff --git a/src/libraries/libc/stdio/fseek.c b/src/libraries/libc/stdio/fseek.c deleted file mode 100644 index 19a8187..0000000 --- a/src/libraries/libc/stdio/fseek.c +++ /dev/null @@ -1,25 +0,0 @@ -/* fseek( FILE *, long, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -int fseek( struct _PDCLIB_file_t * stream, long offset, int whence ) -{ - if ( stream->status & _PDCLIB_FWRITE ) - { - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - return EOF; - } - } - stream->status &= ~ _PDCLIB_EOFFLAG; - if ( stream->status & _PDCLIB_FRW ) - { - stream->status &= ~ ( _PDCLIB_FREAD | _PDCLIB_FWRITE ); - } - return ( _PDCLIB_seek( stream, offset, whence ) != EOF ) ? 0 : EOF; -} diff --git a/src/libraries/libc/stdio/fsetpos.c b/src/libraries/libc/stdio/fsetpos.c deleted file mode 100644 index b0bdeef..0000000 --- a/src/libraries/libc/stdio/fsetpos.c +++ /dev/null @@ -1,26 +0,0 @@ -/* fsetpos( FILE *, const fpos_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -int fsetpos( struct _PDCLIB_file_t * stream, const struct _PDCLIB_fpos_t * pos ) -{ - if ( stream->status & _PDCLIB_FWRITE ) - { - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - return EOF; - } - } - if ( _PDCLIB_seek( stream, pos->offset, SEEK_SET ) == EOF ) - { - return EOF; - } - stream->pos.status = pos->status; - /* TODO: Add mbstate. */ - return 0; -} diff --git a/src/libraries/libc/stdio/ftell.c b/src/libraries/libc/stdio/ftell.c deleted file mode 100644 index 72a3fbc..0000000 --- a/src/libraries/libc/stdio/ftell.c +++ /dev/null @@ -1,38 +0,0 @@ -/* ftell( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -long int ftell( struct _PDCLIB_file_t * stream ) -{ - /* ftell() must take into account: - - the actual *physical* offset of the file, i.e. the offset as recognized - by the operating system (and stored in stream->pos.offset); and - - any buffers held by PDCLib, which - - in case of unwritten buffers, count in *addition* to the offset; or - - in case of unprocessed pre-read buffers, count in *substraction* to - the offset. (Remember to count ungetidx into this number.) - Conveniently, the calculation ( ( bufend - bufidx ) + ungetidx ) results - in just the right number in both cases: - - in case of unwritten buffers, ( ( 0 - unwritten ) + 0 ) - i.e. unwritten bytes as negative number - - in case of unprocessed pre-read, ( ( preread - processed ) + unget ) - i.e. unprocessed bytes as positive number. - That is how the somewhat obscure return-value calculation works. - */ - /* If offset is too large for return type, report error instead of wrong - offset value. - */ - /* TODO: Check what happens when ungetc() is called on a stream at offset 0 */ - if ( ( stream->pos.offset - stream->bufend ) > ( LONG_MAX - ( stream->bufidx - stream->ungetidx ) ) ) - { - /* integer overflow */ - _PDCLIB_errno = _PDCLIB_ERANGE; - return -1; - } - return (long int)( stream->pos.offset - ( ( (int)stream->bufend - (int)stream->bufidx ) + stream->ungetidx ) ); -} diff --git a/src/libraries/libc/stdio/fwrite.c b/src/libraries/libc/stdio/fwrite.c deleted file mode 100644 index 360baf1..0000000 --- a/src/libraries/libc/stdio/fwrite.c +++ /dev/null @@ -1,76 +0,0 @@ -/* fwrite( const void *, size_t, size_t, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include "j6libc/glue.h" - -size_t fwrite( const void * restrict ptr, size_t size, size_t nmemb, struct _PDCLIB_file_t * restrict stream ) -{ - size_t offset = 0; - /* TODO: lineend */ - /* int lineend = 0; */ - size_t nmemb_i; - if ( _PDCLIB_prepwrite( stream ) == EOF ) - { - return 0; - } - for ( nmemb_i = 0; nmemb_i < nmemb; ++nmemb_i ) - { - size_t size_i; - for ( size_i = 0; size_i < size; ++size_i ) - { - if ( ( stream->buffer[ stream->bufidx++ ] = ((char*)ptr)[ nmemb_i * size + size_i ] ) == '\n' ) - { - /* Remember last newline, in case we have to do a partial line-buffered flush */ - offset = stream->bufidx; - /* lineend = true; */ - } - if ( stream->bufidx == stream->bufsize ) - { - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - /* Returning number of objects completely buffered */ - return nmemb_i; - } - /* lineend = false; */ - } - } - } - /* Fully-buffered streams are OK. Non-buffered streams must be flushed, - line-buffered streams only if there's a newline in the buffer. - */ - switch ( stream->status & ( _IONBF | _IOLBF ) ) - { - case _IONBF: - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - /* We are in a pinch here. We have an error, which requires a - return value < nmemb. On the other hand, all objects have - been written to buffer, which means all the caller had to - do was removing the error cause, and re-flush the stream... - Catch 22. We'll return a value one short, to indicate the - error, and can't really do anything about the inconsistency. - */ - return nmemb_i - 1; - } - break; - case _IOLBF: - { - size_t bufidx = stream->bufidx; - stream->bufidx = offset; - if ( _PDCLIB_flushbuffer( stream ) == EOF ) - { - /* See comment above. */ - stream->bufidx = bufidx; - return nmemb_i - 1; - } - stream->bufidx = bufidx - offset; - memmove( stream->buffer, stream->buffer + offset, stream->bufidx ); - } - } - return nmemb_i; -} diff --git a/src/libraries/libc/stdio/getc.c b/src/libraries/libc/stdio/getc.c deleted file mode 100644 index c32609d..0000000 --- a/src/libraries/libc/stdio/getc.c +++ /dev/null @@ -1,12 +0,0 @@ -/* getc( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int getc( struct _PDCLIB_file_t * stream ) -{ - return fgetc( stream ); -} diff --git a/src/libraries/libc/stdio/getchar.c b/src/libraries/libc/stdio/getchar.c deleted file mode 100644 index 5cbcb94..0000000 --- a/src/libraries/libc/stdio/getchar.c +++ /dev/null @@ -1,12 +0,0 @@ -/* getchar( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int getchar( void ) -{ - return fgetc( stdin ); -} diff --git a/src/libraries/libc/stdio/perror.c b/src/libraries/libc/stdio/perror.c deleted file mode 100644 index 9ea8273..0000000 --- a/src/libraries/libc/stdio/perror.c +++ /dev/null @@ -1,27 +0,0 @@ -/* perror( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -/* TODO: Doing this via a static array is not the way to do it. */ -void perror( const char * s ) -{ - if ( ( s != NULL ) && ( s[0] != '\n' ) ) - { - fprintf( stderr, "%s: ", s ); - } - if ( errno >= _PDCLIB_ERRNO_MAX ) - { - fprintf( stderr, "Unknown error\n" ); - } - else - { - fprintf( stderr, "%s\n", _PDCLIB_lc_messages.errno_texts[errno] ); - } - return; -} diff --git a/src/libraries/libc/stdio/printf.c b/src/libraries/libc/stdio/printf.c deleted file mode 100644 index 18d7deb..0000000 --- a/src/libraries/libc/stdio/printf.c +++ /dev/null @@ -1,18 +0,0 @@ -/* printf( const char *, ... ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int printf( const char * restrict format, ... ) -{ - int rc; - va_list ap; - va_start( ap, format ); - rc = vfprintf( stdout, format, ap ); - va_end( ap ); - return rc; -} diff --git a/src/libraries/libc/stdio/putc.c b/src/libraries/libc/stdio/putc.c deleted file mode 100644 index db4931d..0000000 --- a/src/libraries/libc/stdio/putc.c +++ /dev/null @@ -1,12 +0,0 @@ -/* putc( int, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int putc( int c, struct _PDCLIB_file_t * stream ) -{ - return fputc( c, stream ); -} diff --git a/src/libraries/libc/stdio/putchar.c b/src/libraries/libc/stdio/putchar.c deleted file mode 100644 index 01a6fbd..0000000 --- a/src/libraries/libc/stdio/putchar.c +++ /dev/null @@ -1,12 +0,0 @@ -/* putchar( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int putchar( int c ) -{ - return fputc( c, stdout ); -} diff --git a/src/libraries/libc/stdio/puts.c b/src/libraries/libc/stdio/puts.c deleted file mode 100644 index 6923723..0000000 --- a/src/libraries/libc/stdio/puts.c +++ /dev/null @@ -1,39 +0,0 @@ -/* puts( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -extern char * _PDCLIB_eol; - -int puts( const char * s ) -{ - if ( _PDCLIB_prepwrite( stdout ) == EOF ) - { - return EOF; - } - while ( *s != '\0' ) - { - stdout->buffer[ stdout->bufidx++ ] = *s++; - if ( stdout->bufidx == stdout->bufsize ) - { - if ( _PDCLIB_flushbuffer( stdout ) == EOF ) - { - return EOF; - } - } - } - stdout->buffer[ stdout->bufidx++ ] = '\n'; - if ( ( stdout->bufidx == stdout->bufsize ) || - ( stdout->status & ( _IOLBF | _IONBF ) ) ) - { - return _PDCLIB_flushbuffer( stdout ); - } - else - { - return 0; - } -} diff --git a/src/libraries/libc/stdio/remove.c b/src/libraries/libc/stdio/remove.c deleted file mode 100644 index 73f1287..0000000 --- a/src/libraries/libc/stdio/remove.c +++ /dev/null @@ -1,29 +0,0 @@ -/* remove( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of remove() fit for use with POSIX kernels. -*/ - -#include -#include - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -int remove( const char * pathname ) -{ - struct _PDCLIB_file_t * current = _PDCLIB_filelist; - while ( current != NULL ) - { - if ( ( current->filename != NULL ) && ( strcmp( current->filename, pathname ) == 0 ) ) - { - return EOF; - } - current = current->next; - } - - _PDCLIB_errno = _PDCLIB_ERROR; - return -1; -} diff --git a/src/libraries/libc/stdio/rename.c b/src/libraries/libc/stdio/rename.c deleted file mode 100644 index cf2f372..0000000 --- a/src/libraries/libc/stdio/rename.c +++ /dev/null @@ -1,27 +0,0 @@ -/* rename( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -#include - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -int rename( const char * old, const char * new ) -{ - struct _PDCLIB_file_t * current = _PDCLIB_filelist; - while ( current != NULL ) - { - if ( ( current->filename != NULL ) && ( strcmp( current->filename, old ) == 0 ) ) - { - /* File of that name currently open. Do not rename. */ - return EOF; - } - current = current->next; - } - return _PDCLIB_rename( old, new ); -} diff --git a/src/libraries/libc/stdio/rewind.c b/src/libraries/libc/stdio/rewind.c deleted file mode 100644 index 246f68e..0000000 --- a/src/libraries/libc/stdio/rewind.c +++ /dev/null @@ -1,13 +0,0 @@ -/* rewind( FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void rewind( struct _PDCLIB_file_t * stream ) -{ - stream->status &= ~ _PDCLIB_ERRORFLAG; - fseek( stream, 0L, SEEK_SET ); -} diff --git a/src/libraries/libc/stdio/scanf.c b/src/libraries/libc/stdio/scanf.c deleted file mode 100644 index c0176dd..0000000 --- a/src/libraries/libc/stdio/scanf.c +++ /dev/null @@ -1,15 +0,0 @@ -/* scanf( const char *, ... ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int scanf( const char * restrict format, ... ) -{ - va_list ap; - va_start( ap, format ); - return vfscanf( stdin, format, ap ); -} diff --git a/src/libraries/libc/stdio/setbuf.c b/src/libraries/libc/stdio/setbuf.c deleted file mode 100644 index dfca6b3..0000000 --- a/src/libraries/libc/stdio/setbuf.c +++ /dev/null @@ -1,19 +0,0 @@ -/* setbuf( FILE *, char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void setbuf( struct _PDCLIB_file_t * restrict stream, char * restrict buf ) -{ - if ( buf == NULL ) - { - setvbuf( stream, buf, _IONBF, BUFSIZ ); - } - else - { - setvbuf( stream, buf, _IOFBF, BUFSIZ ); - } -} diff --git a/src/libraries/libc/stdio/setvbuf.c b/src/libraries/libc/stdio/setvbuf.c deleted file mode 100644 index 3219538..0000000 --- a/src/libraries/libc/stdio/setvbuf.c +++ /dev/null @@ -1,64 +0,0 @@ -/* setvbuf( FILE *, char *, int, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -int setvbuf( struct _PDCLIB_file_t * restrict stream, char * restrict buf, int mode, size_t size ) -{ - switch ( mode ) - { - case _IONBF: - /* When unbuffered I/O is requested, we keep the buffer anyway, as - we don't want to e.g. flush the stream for every character of a - stream being printed. - */ - break; - case _IOFBF: - case _IOLBF: - if ( size > INT_MAX || size == 0 ) - { - /* PDCLib only supports buffers up to INT_MAX in size. A size - of zero doesn't make sense. - */ - return -1; - } - if ( buf == NULL ) - { - /* User requested buffer size, but leaves it to library to - allocate the buffer. - */ - /* If current buffer is big enough for requested size, but not - over twice as big (and wasting memory space), we use the - current buffer (i.e., do nothing), to save the malloc() / - free() overhead. - */ - if ( ( stream->bufsize < size ) || ( stream->bufsize > ( size << 1 ) ) ) - { - /* Buffer too small, or much too large - allocate. */ - if ( ( buf = (char *) malloc( size ) ) == NULL ) - { - /* Out of memory error. */ - return -1; - } - /* This buffer must be free()d on fclose() */ - stream->status |= _PDCLIB_FREEBUFFER; - } - } - stream->buffer = buf; - stream->bufsize = size; - break; - default: - /* If mode is something else than _IOFBF, _IOLBF or _IONBF -> exit */ - return -1; - } - /* Deleting current buffer mode */ - stream->status &= ~( _IOFBF | _IOLBF | _IONBF ); - /* Set user-defined mode */ - stream->status |= mode; - return 0; -} diff --git a/src/libraries/libc/stdio/snprintf.c b/src/libraries/libc/stdio/snprintf.c deleted file mode 100644 index ee05173..0000000 --- a/src/libraries/libc/stdio/snprintf.c +++ /dev/null @@ -1,18 +0,0 @@ -/* snprintf( char *, size_t, const char *, ... ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int snprintf( char * restrict s, size_t n, const char * restrict format, ...) -{ - int rc; - va_list ap; - va_start( ap, format ); - rc = vsnprintf( s, n, format, ap ); - va_end( ap ); - return rc; -} diff --git a/src/libraries/libc/stdio/sprintf.c b/src/libraries/libc/stdio/sprintf.c deleted file mode 100644 index 8c32b1b..0000000 --- a/src/libraries/libc/stdio/sprintf.c +++ /dev/null @@ -1,19 +0,0 @@ -/* sprintf( char *, const char *, ... ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -int sprintf( char * restrict s, const char * restrict format, ...) -{ - int rc; - va_list ap; - va_start( ap, format ); - rc = vsnprintf( s, SIZE_MAX, format, ap ); /* TODO: replace with non-checking call */ - va_end( ap ); - return rc; -} diff --git a/src/libraries/libc/stdio/sscanf.c b/src/libraries/libc/stdio/sscanf.c deleted file mode 100644 index e3b517b..0000000 --- a/src/libraries/libc/stdio/sscanf.c +++ /dev/null @@ -1,18 +0,0 @@ -/* sscanf( const char *, const char *, ... ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int sscanf( const char * restrict s, const char * restrict format, ... ) -{ - int rc; - va_list ap; - va_start( ap, format ); - rc = vsscanf( s, format, ap ); - va_end( ap ); - return rc; -} diff --git a/src/libraries/libc/stdio/tmpfile.c b/src/libraries/libc/stdio/tmpfile.c deleted file mode 100644 index f00a175..0000000 --- a/src/libraries/libc/stdio/tmpfile.c +++ /dev/null @@ -1,22 +0,0 @@ -/* tmpfile( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -#include -#include -#include - -extern struct _PDCLIB_file_t * _PDCLIB_filelist; - -/* This is an example implementation of tmpfile() fit for use with POSIX - kernels. -*/ -struct _PDCLIB_file_t * tmpfile( void ) -{ - return NULL; -} diff --git a/src/libraries/libc/stdio/tmpnam.c b/src/libraries/libc/stdio/tmpnam.c deleted file mode 100644 index a275293..0000000 --- a/src/libraries/libc/stdio/tmpnam.c +++ /dev/null @@ -1,23 +0,0 @@ -/* tmpnam( char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include "j6libc/glue.h" - -#include - -char * tmpnam( char * s ) -{ - static char filename[ L_tmpnam ]; - FILE * file = tmpfile(); - if ( s == NULL ) - { - s = filename; - } - strcpy( s, file->filename ); - fclose( file ); - return s; -} diff --git a/src/libraries/libc/stdio/ungetc.c b/src/libraries/libc/stdio/ungetc.c deleted file mode 100644 index c62f2ca..0000000 --- a/src/libraries/libc/stdio/ungetc.c +++ /dev/null @@ -1,16 +0,0 @@ -/* ungetc( int, FILE * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int ungetc( int c, struct _PDCLIB_file_t * stream ) -{ - if ( c == EOF || stream->ungetidx == _PDCLIB_UNGETCBUFSIZE ) - { - return -1; - } - return stream->ungetbuf[stream->ungetidx++] = (unsigned char) c; -} diff --git a/src/libraries/libc/stdio/vfprintf.c b/src/libraries/libc/stdio/vfprintf.c deleted file mode 100644 index 1d68dfe..0000000 --- a/src/libraries/libc/stdio/vfprintf.c +++ /dev/null @@ -1,44 +0,0 @@ -/* vfprintf( FILE *, const char *, va_list ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -int vfprintf( struct _PDCLIB_file_t * restrict stream, const char * restrict format, va_list arg ) -{ - /* TODO: This function should interpret format as multibyte characters. */ - struct _PDCLIB_status_t status; - status.base = 0; - status.flags = 0; - status.n = SIZE_MAX; - status.i = 0; - status.current = 0; - status.s = NULL; - status.width = 0; - status.prec = EOF; - status.stream = stream; - va_copy( status.arg, arg ); - - while ( *format != '\0' ) - { - const char * rc; - if ( ( *format != '%' ) || ( ( rc = _PDCLIB_print( format, &status ) ) == format ) ) - { - /* No conversion specifier, print verbatim */ - putc( *(format++), stream ); - status.i++; - } - else - { - /* Continue parsing after conversion specifier */ - format = rc; - } - } - va_end( status.arg ); - return status.i; -} - diff --git a/src/libraries/libc/stdio/vfscanf.c b/src/libraries/libc/stdio/vfscanf.c deleted file mode 100644 index dcf498c..0000000 --- a/src/libraries/libc/stdio/vfscanf.c +++ /dev/null @@ -1,82 +0,0 @@ -/* vfscanf( FILE *, const char *, va_list ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -int vfscanf( FILE * restrict stream, const char * restrict format, va_list arg ) -{ - /* TODO: This function should interpret format as multibyte characters. */ - struct _PDCLIB_status_t status; - status.base = 0; - status.flags = 0; - status.n = 0; - status.i = 0; - status.current = 0; - status.s = NULL; - status.width = 0; - status.prec = EOF; - status.stream = stream; - va_copy( status.arg, arg ); - - while ( *format != '\0' ) - { - const char * rc; - if ( ( *format != '%' ) || ( ( rc = _PDCLIB_scan( format, &status ) ) == format ) ) - { - int c; - /* No conversion specifier, match verbatim */ - if ( isspace( *format ) ) - { - /* Whitespace char in format string: Skip all whitespaces */ - /* No whitespaces in input does not result in matching error */ - while ( isspace( c = getc( stream ) ) ) - { - ++status.i; - } - if ( ! feof( stream ) ) - { - ungetc( c, stream ); - } - } - else - { - /* Non-whitespace char in format string: Match verbatim */ - if ( ( ( c = getc( stream ) ) != *format ) || feof( stream ) ) - { - /* Matching error */ - if ( ! feof( stream ) && ! ferror( stream ) ) - { - ungetc( c, stream ); - } - else if ( status.n == 0 ) - { - return EOF; - } - return status.n; - } - else - { - ++status.i; - } - } - ++format; - } - else - { - /* NULL return code indicates matching error */ - if ( rc == NULL ) - { - break; - } - /* Continue parsing after conversion specifier */ - format = rc; - } - } - va_end( status.arg ); - return status.n; -} diff --git a/src/libraries/libc/stdio/vprintf.c b/src/libraries/libc/stdio/vprintf.c deleted file mode 100644 index 395bec3..0000000 --- a/src/libraries/libc/stdio/vprintf.c +++ /dev/null @@ -1,13 +0,0 @@ -/* vprintf( const char *, va_list ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int vprintf( const char * restrict format, _PDCLIB_va_list arg ) -{ - return vfprintf( stdout, format, arg ); -} diff --git a/src/libraries/libc/stdio/vscanf.c b/src/libraries/libc/stdio/vscanf.c deleted file mode 100644 index cfdb8fe..0000000 --- a/src/libraries/libc/stdio/vscanf.c +++ /dev/null @@ -1,13 +0,0 @@ -/* vscanf( const char *, va_list ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int vscanf( const char * restrict format, _PDCLIB_va_list arg ) -{ - return vfscanf( stdin, format, arg ); -} diff --git a/src/libraries/libc/stdio/vsnprintf.c b/src/libraries/libc/stdio/vsnprintf.c deleted file mode 100644 index e62da66..0000000 --- a/src/libraries/libc/stdio/vsnprintf.c +++ /dev/null @@ -1,50 +0,0 @@ -/* vsnprintf( char *, size_t, const char *, va_list ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int vsnprintf( char * restrict s, size_t n, const char * restrict format, _PDCLIB_va_list arg ) -{ - /* TODO: This function should interpret format as multibyte characters. */ - struct _PDCLIB_status_t status; - status.base = 0; - status.flags = 0; - status.n = n; - status.i = 0; - status.current = 0; - status.s = s; - status.width = 0; - status.prec = EOF; - status.stream = NULL; - va_copy( status.arg, arg ); - - while ( *format != '\0' ) - { - const char * rc; - if ( ( *format != '%' ) || ( ( rc = _PDCLIB_print( format, &status ) ) == format ) ) - { - /* No conversion specifier, print verbatim */ - if ( status.i < n ) - { - s[ status.i ] = *format; - } - status.i++; - format++; - } - else - { - /* Continue parsing after conversion specifier */ - format = rc; - } - } - if ( status.i < n ) - { - s[ status.i ] = '\0'; - } - va_end( status.arg ); - return status.i; -} diff --git a/src/libraries/libc/stdio/vsprintf.c b/src/libraries/libc/stdio/vsprintf.c deleted file mode 100644 index 57fba2e..0000000 --- a/src/libraries/libc/stdio/vsprintf.c +++ /dev/null @@ -1,14 +0,0 @@ -/* vsprintf( char *, const char *, va_list ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -int vsprintf( char * restrict s, const char * restrict format, va_list arg ) -{ - return vsnprintf( s, SIZE_MAX, format, arg ); /* TODO: Replace with a non-checking call */ -} diff --git a/src/libraries/libc/stdio/vsscanf.c b/src/libraries/libc/stdio/vsscanf.c deleted file mode 100644 index 472ad0f..0000000 --- a/src/libraries/libc/stdio/vsscanf.c +++ /dev/null @@ -1,80 +0,0 @@ -/* vsscanf( const char *, const char *, va_list ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -int vsscanf( const char * restrict s, const char * restrict format, va_list arg ) -{ - /* TODO: This function should interpret format as multibyte characters. */ - struct _PDCLIB_status_t status; - status.base = 0; - status.flags = 0; - status.n = 0; - status.i = 0; - status.current = 0; - status.s = (char *) s; - status.width = 0; - status.prec = EOF; - status.stream = NULL; - va_copy( status.arg, arg ); - - while ( *format != '\0' ) - { - const char * rc; - if ( ( *format != '%' ) || ( ( rc = _PDCLIB_scan( format, &status ) ) == format ) ) - { - /* No conversion specifier, match verbatim */ - if ( isspace( *format ) ) - { - /* Whitespace char in format string: Skip all whitespaces */ - /* No whitespaces in input do not result in matching error */ - while ( isspace( *status.s ) ) - { - ++status.s; - ++status.i; - } - } - else - { - /* Non-whitespace char in format string: Match verbatim */ - if ( *status.s != *format ) - { - if ( *status.s == '\0' && status.n == 0 ) - { - /* Early input error */ - return EOF; - } - /* Matching error */ - return status.n; - } - else - { - ++status.s; - ++status.i; - } - } - ++format; - } - else - { - /* NULL return code indicates error */ - if ( rc == NULL ) - { - if ( ( *status.s == '\n' ) && ( status.n == 0 ) ) - { - status.n = EOF; - } - break; - } - /* Continue parsing after conversion specifier */ - format = rc; - } - } - va_end( status.arg ); - return status.n; -} diff --git a/src/libraries/libc/stdlib.h b/src/libraries/libc/stdlib.h deleted file mode 100644 index 781cde5..0000000 --- a/src/libraries/libc/stdlib.h +++ /dev/null @@ -1,234 +0,0 @@ -#pragma once -/* General utilities - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/cpp.h" -#include "j6libc/int.h" -#include "j6libc/null.h" -#include "j6libc/size_t.h" -#include "j6libc/wchar_t.h" - -CPP_CHECK_BEGIN - -/* Numeric conversion functions */ - -/* TODO: atof(), strtof(), strtod(), strtold() */ - -double atof( const char * nptr ); -double strtod( const char * restrict nptr, char * * restrict endptr ); -float strtof( const char * restrict nptr, char * * restrict endptr ); -long double strtold( const char * restrict nptr, char * * restrict endptr ); - -/* Seperate the character array nptr into three parts: A (possibly empty) - sequence of whitespace characters, a character representation of an integer - to the given base, and trailing invalid characters (including the terminating - null character). If base is 0, assume it to be 10, unless the integer - representation starts with 0x / 0X (setting base to 16) or 0 (setting base to - 8). If given, base can be anything from 0 to 36, using the 26 letters of the - base alphabet (both lowercase and uppercase) as digits 10 through 35. - The integer representation is then converted into the return type of the - function. It can start with a '+' or '-' sign. If the sign is '-', the result - of the conversion is negated. - If the conversion is successful, the converted value is returned. If endptr - is not a NULL pointer, a pointer to the first trailing invalid character is - returned in *endptr. - If no conversion could be performed, zero is returned (and nptr in *endptr, - if endptr is not a NULL pointer). If the converted value does not fit into - the return type, the functions return LONG_MIN, LONG_MAX, ULONG_MAX, - LLONG_MIN, LLONG_MAX, or ULLONG_MAX respectively, depending on the sign of - the integer representation and the return type, and errno is set to ERANGE. -*/ -/* There is strtoimax() and strtoumax() in operating on intmax_t / - uintmax_t, if the long long versions do not suit your needs. -*/ -long int strtol( const char * restrict nptr, char * * restrict endptr, int base ); -long long int strtoll( const char * restrict nptr, char * * restrict endptr, int base ); -unsigned long int strtoul( const char * restrict nptr, char * * restrict endptr, int base ); -unsigned long long int strtoull( const char * restrict nptr, char * * restrict endptr, int base ); - -/* These functions are the equivalent of (int)strtol( nptr, NULL, 10 ), - strtol( nptr, NULL, 10 ) and strtoll(nptr, NULL, 10 ) respectively, with the - exception that they do not have to handle overflow situations in any defined - way. - (PDCLib does not simply forward these to their strtox() equivalents, but - provides a simpler atox() function that saves a couple of tests and simply - continues with the conversion in case of overflow.) -*/ -int atoi( const char * nptr ); -long int atol( const char * nptr ); -long long int atoll( const char * nptr ); - -/* Pseudo-random sequence generation functions */ - -extern unsigned long int _PDCLIB_seed; - -#define RAND_MAX 32767 - -/* Returns the next number in a pseudo-random sequence, which is between 0 and - RAND_MAX. - (PDCLib uses the implementation suggested by the standard document, which is - next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % 32768;) -*/ -int rand( void ); - -/* Initialize a new pseudo-random sequence with the starting seed. Same seeds - result in the same pseudo-random sequence. The default seed is 1. -*/ -void srand( unsigned int seed ); - -/* Memory management functions */ - -/* Allocate a chunk of heap memory of given size. If request could not be - satisfied, return NULL. Otherwise, return a pointer to the allocated - memory. Memory contents are undefined. -*/ -void * malloc( size_t size ); - -/* Allocate a chunk of heap memory that is large enough to hold nmemb elements - of the given size, and zero-initialize that memory. If request could not be - satisfied, return NULL. Otherwise, return a pointer to the allocated - memory. -*/ -void * calloc( size_t nmemb, size_t size ); - -/* De-allocate a chunk of heap memory previously allocated using malloc(), - calloc(), or realloc(), and pointed to by ptr. If ptr does not match a - pointer previously returned by the mentioned allocation functions, or - free() has already been called for this ptr, behaviour is undefined. -*/ -void free( void * ptr ); - -/* Resize a chunk of memory previously allocated with malloc() and pointed to - by ptr to the given size (which might be larger or smaller than the original - size). Returns a pointer to the reallocated memory, or NULL if the request - could not be satisfied. Note that the resizing might include a memcpy() - from the original location to a different one, so the return value might or - might not equal ptr. If size is larger than the original size, the value of - memory beyond the original size is undefined. If ptr is NULL, realloc() - behaves like malloc(). -*/ -void * realloc( void * ptr, size_t size ); - -int posix_memalign(void**, size_t, size_t); - -/* Communication with the environment */ - -/* These two can be passed to exit() or _Exit() as status values, to signal - successful and unsuccessful program termination, respectively. EXIT_SUCCESS - can be replaced by 0. How successful or unsuccessful program termination are - signaled to the environment, and what happens if exit() or _Exit() are being - called with a value that is neither of the three, is defined by the hosting - OS and its glue function. -*/ -#define EXIT_SUCCESS _PDCLIB_SUCCESS -#define EXIT_FAILURE _PDCLIB_FAILURE - -/* Initiate abnormal process termination, unless programm catches SIGABRT and - does not return from the signal handler. - This implementantion flushes all streams, closes all files, and removes any - temporary files before exiting with EXIT_FAILURE. - abort() does not return. -*/ -void abort( void ); - -/* Register a function that will be called on exit(), or when main() returns. - At least 32 functions can be registered this way, and will be called in - reverse order of registration (last-in, first-out). - Returns zero if registration is successfull, nonzero if it failed. -*/ -int atexit( void (*func)( void ) ); - -/* Normal process termination. Functions registered by atexit() (see above) are - called, streams flushed, files closed and temporary files removed before the - program is terminated with the given status. (See comment for EXIT_SUCCESS - and EXIT_FAILURE above.) - exit() does not return. -*/ -void exit( int status ); - -/* Normal process termination. Functions registered by atexit() (see above) are - NOT CALLED. This implementation DOES flush streams, close files and removes - temporary files before the program is teminated with the given status. (See - comment for EXIT_SUCCESS and EXIT_FAILURE above.) - _Exit() does not return. -*/ -void _Exit( int status ); - -/* Search an environment-provided key-value map for the given key name, and - return a pointer to the associated value string (or NULL if key name cannot - be found). The value string pointed to might be overwritten by a subsequent - call to getenv(). The library never calls getenv() itself. - Details on the provided keys and how to set / change them are determined by - the hosting OS and its glue function. -*/ -char * getenv( const char * name ); - -/* If string is a NULL pointer, system() returns nonzero if a command processor - is available, and zero otherwise. If string is not a NULL pointer, it is - passed to the command processor. If system() returns, it does so with a - value that is determined by the hosting OS and its glue function. -*/ -int system( const char * string ); - -/* Searching and sorting */ - -/* Do a binary search for a given key in the array with a given base pointer, - which consists of nmemb elements that are of the given size each. To compare - the given key with an element from the array, the given function compar is - called (with key as first parameter and a pointer to the array member as - second parameter); the function should return a value less than, equal to, - or greater than 0 if the key is considered to be less than, equal to, or - greater than the array element, respectively. - The function returns a pointer to the first matching element found, or NULL - if no match is found. -*/ -void * bsearch( const void * key, const void * base, size_t nmemb, size_t size, int (*compar)( const void *, const void * ) ); - -/* Do a quicksort on an array with a given base pointer, which consists of - nmemb elements that are of the given size each. To compare two elements from - the array, the given function compar is called, which should return a value - less than, equal to, or greater than 0 if the first argument is considered - to be less than, equal to, or greater than the second argument, respectively. - If two elements are compared equal, their order in the sorted array is not - specified. -*/ -void qsort( void * base, size_t nmemb, size_t size, int (*compar)( const void *, const void * ) ); - -/* Integer arithmetic functions */ - -/* Return the absolute value of the argument. Note that on machines using two- - complement's notation (most modern CPUs), the largest negative value cannot - be represented as positive value. In this case, behaviour is unspecified. -*/ -int abs( int j ); -long int labs( long int j ); -long long int llabs( long long int j ); - -/* These structures each have a member quot and a member rem, of type int (for - div_t), long int (for ldiv_t) and long long it (for lldiv_t) respectively. - The order of the members is platform-defined to allow the div() functions - below to be implemented efficiently. -*/ -typedef struct _PDCLIB_div_t div_t; -typedef struct _PDCLIB_ldiv_t ldiv_t; -typedef struct _PDCLIB_lldiv_t lldiv_t; - -/* Return quotient (quot) and remainder (rem) of an integer division in one of - the structs above. -*/ -div_t div( int numer, int denom ); -ldiv_t ldiv( long int numer, long int denom ); -lldiv_t lldiv( long long int numer, long long int denom ); - -/* TODO: Multibyte / wide character conversion functions */ -/* TODO: Macro MB_CUR_MAX */ -int mblen( const char * s, size_t n ); -int mbtowc( wchar_t * restrict pwc, const char * restrict s, size_t n ); -int wctomb( char * s, wchar_t wc ); -size_t mbstowcs( wchar_t * restrict pwcs, const char * restrict s, size_t n ); -size_t wcstombs( char * restrict s, const wchar_t * restrict pwcs, size_t n ); - -CPP_CHECK_END diff --git a/src/libraries/libc/stdlib/_Exit.c b/src/libraries/libc/stdlib/_Exit.c deleted file mode 100644 index 2112dab..0000000 --- a/src/libraries/libc/stdlib/_Exit.c +++ /dev/null @@ -1,17 +0,0 @@ -/* _Exit( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include "j6libc/glue.h" - -void _Exit( int status ) -{ - /* TODO: Flush and close open streams. Remove tmpfile() files. Make this - called on process termination automatically. - */ - _PDCLIB_Exit( status ); -} diff --git a/src/libraries/libc/stdlib/abort.c b/src/libraries/libc/stdlib/abort.c deleted file mode 100644 index beebd2f..0000000 --- a/src/libraries/libc/stdlib/abort.c +++ /dev/null @@ -1,14 +0,0 @@ -/* abort( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -void abort( void ) -{ - raise( SIGABRT ); - exit( EXIT_FAILURE ); -} diff --git a/src/libraries/libc/stdlib/abs.c b/src/libraries/libc/stdlib/abs.c deleted file mode 100644 index 6ffdf36..0000000 --- a/src/libraries/libc/stdlib/abs.c +++ /dev/null @@ -1,12 +0,0 @@ -/* abs( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int abs( int j ) -{ - return ( j >= 0 ) ? j : -j; -} diff --git a/src/libraries/libc/stdlib/atexit.c b/src/libraries/libc/stdlib/atexit.c deleted file mode 100644 index 49d1301..0000000 --- a/src/libraries/libc/stdlib/atexit.c +++ /dev/null @@ -1,23 +0,0 @@ -/* atexit( void (*)( void ) ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -extern void (*_PDCLIB_exitstack[])( void ); -extern size_t _PDCLIB_exitptr; - -int atexit( void (*func)( void ) ) -{ - if ( _PDCLIB_exitptr == 0 ) - { - return -1; - } - else - { - _PDCLIB_exitstack[ --_PDCLIB_exitptr ] = func; - return 0; - } -} diff --git a/src/libraries/libc/stdlib/atoi.c b/src/libraries/libc/stdlib/atoi.c deleted file mode 100644 index a3f71ac..0000000 --- a/src/libraries/libc/stdlib/atoi.c +++ /dev/null @@ -1,12 +0,0 @@ -/* atoi( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int atoi( const char * s ) -{ - return (int) _PDCLIB_atomax( s ); -} diff --git a/src/libraries/libc/stdlib/atol.c b/src/libraries/libc/stdlib/atol.c deleted file mode 100644 index 7fb8e2e..0000000 --- a/src/libraries/libc/stdlib/atol.c +++ /dev/null @@ -1,12 +0,0 @@ -/* atol( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -long int atol( const char * s ) -{ - return (long int) _PDCLIB_atomax( s ); -} diff --git a/src/libraries/libc/stdlib/atoll.c b/src/libraries/libc/stdlib/atoll.c deleted file mode 100644 index 874f966..0000000 --- a/src/libraries/libc/stdlib/atoll.c +++ /dev/null @@ -1,12 +0,0 @@ -/* atoll( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -long long int atoll( const char * s ) -{ - return (long long int) _PDCLIB_atomax( s ); -} diff --git a/src/libraries/libc/stdlib/bsearch.c b/src/libraries/libc/stdlib/bsearch.c deleted file mode 100644 index daf66a2..0000000 --- a/src/libraries/libc/stdlib/bsearch.c +++ /dev/null @@ -1,33 +0,0 @@ -/* bsearch( const void *, const void *, size_t, size_t, int(*)( const void *, const void * ) ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void * bsearch( const void * key, const void * base, size_t nmemb, size_t size, int (*compar)( const void *, const void * ) ) -{ - const void * pivot; - int rc; - size_t corr; - while ( nmemb ) - { - /* algorithm needs -1 correction if remaining elements are an even number. */ - corr = nmemb % 2; - nmemb /= 2; - pivot = (const char *)base + (nmemb * size); - rc = compar( key, pivot ); - if ( rc > 0 ) - { - base = (const char *)pivot + size; - /* applying correction */ - nmemb -= ( 1 - corr ); - } - else if ( rc == 0 ) - { - return (void *)pivot; - } - } - return NULL; -} diff --git a/src/libraries/libc/stdlib/div.c b/src/libraries/libc/stdlib/div.c deleted file mode 100644 index 508dc75..0000000 --- a/src/libraries/libc/stdlib/div.c +++ /dev/null @@ -1,16 +0,0 @@ -/* div( int, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -div_t div( int numer, int denom ) -{ - div_t rc; - rc.quot = numer / denom; - rc.rem = numer % denom; - /* TODO: pre-C99 compilers might require modulus corrections */ - return rc; -} diff --git a/src/libraries/libc/stdlib/exit.c b/src/libraries/libc/stdlib/exit.c deleted file mode 100644 index fe8a50c..0000000 --- a/src/libraries/libc/stdlib/exit.c +++ /dev/null @@ -1,28 +0,0 @@ -/* exit( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -/* TODO - "except that a function is called after any previously registered - functions that had already been called at the time it was registered. -*/ - -/* TODO: 32 is guaranteed. This should be dynamic but ATM gives problems - with my malloc. -*/ -#define NUMBER_OF_SLOTS 40 - -void (*_PDCLIB_exitstack[ NUMBER_OF_SLOTS ])( void ) = { _PDCLIB_closeall }; -size_t _PDCLIB_exitptr = NUMBER_OF_SLOTS; - -void exit( int status ) -{ - while ( _PDCLIB_exitptr < NUMBER_OF_SLOTS ) - { - _PDCLIB_exitstack[ _PDCLIB_exitptr++ ](); - } - _Exit( status ); -} diff --git a/src/libraries/libc/stdlib/getenv.c b/src/libraries/libc/stdlib/getenv.c deleted file mode 100644 index c0471d6..0000000 --- a/src/libraries/libc/stdlib/getenv.c +++ /dev/null @@ -1,27 +0,0 @@ -/* getenv( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -char **environ __attribute__ ((weak)); - -extern char **environ; - -char * getenv( const char * name ) -{ - size_t len = strlen( name ); - size_t index = 0; - while ( environ[ index ] != NULL ) - { - if ( strncmp( environ[ index ], name, len ) == 0 ) - { - return environ[ index ] + len + 1; - } - index++; - } - return NULL; -} diff --git a/src/libraries/libc/stdlib/labs.c b/src/libraries/libc/stdlib/labs.c deleted file mode 100644 index 151ed3a..0000000 --- a/src/libraries/libc/stdlib/labs.c +++ /dev/null @@ -1,12 +0,0 @@ -/* labs( long int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -long int labs( long int j ) -{ - return ( j >= 0 ) ? j : -j; -} diff --git a/src/libraries/libc/stdlib/ldiv.c b/src/libraries/libc/stdlib/ldiv.c deleted file mode 100644 index 86c9c0e..0000000 --- a/src/libraries/libc/stdlib/ldiv.c +++ /dev/null @@ -1,16 +0,0 @@ -/* ldiv( long int, long int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -ldiv_t ldiv( long int numer, long int denom ) -{ - ldiv_t rc; - rc.quot = numer / denom; - rc.rem = numer % denom; - /* TODO: pre-C99 compilers might require modulus corrections */ - return rc; -} diff --git a/src/libraries/libc/stdlib/llabs.c b/src/libraries/libc/stdlib/llabs.c deleted file mode 100644 index 4231e91..0000000 --- a/src/libraries/libc/stdlib/llabs.c +++ /dev/null @@ -1,12 +0,0 @@ -/* llabs( long int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -long long int llabs( long long int j ) -{ - return ( j >= 0 ) ? j : -j; -} diff --git a/src/libraries/libc/stdlib/lldiv.c b/src/libraries/libc/stdlib/lldiv.c deleted file mode 100644 index dd1c2b5..0000000 --- a/src/libraries/libc/stdlib/lldiv.c +++ /dev/null @@ -1,16 +0,0 @@ -/* lldiv( long long int, long long int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -lldiv_t lldiv( long long int numer, long long int denom ) -{ - lldiv_t rc; - rc.quot = numer / denom; - rc.rem = numer % denom; - /* TODO: pre-C99 compilers might require modulus corrections */ - return rc; -} diff --git a/src/libraries/libc/stdlib/malloc.c b/src/libraries/libc/stdlib/malloc.c deleted file mode 100644 index 8307634..0000000 --- a/src/libraries/libc/stdlib/malloc.c +++ /dev/null @@ -1,6270 +0,0 @@ -/* - This is a version (aka dlmalloc) of malloc/free/realloc written by - Doug Lea and released to the public domain, as explained at - http://creativecommons.org/publicdomain/zero/1.0/ Send questions, - comments, complaints, performance data, etc to dl@cs.oswego.edu - -* Version 2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee) - - Note: There may be an updated version of this malloc obtainable at - ftp://gee.cs.oswego.edu/pub/misc/malloc.c - Check before installing! - -* Quickstart - - This library is all in one file to simplify the most common usage: - ftp it, compile it (-O3), and link it into another program. All of - the compile-time options default to reasonable values for use on - most platforms. You might later want to step through various - compile-time and dynamic tuning options. - - For convenience, an include file for code using this malloc is at: - ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.5.h - You don't really need this .h file unless you call functions not - defined in your system include files. The .h file contains only the - excerpts from this file needed for using this malloc on ANSI C/C++ - systems, so long as you haven't changed compile-time options about - naming and tuning parameters. If you do, then you can create your - own malloc.h that does include all settings by cutting at the point - indicated below. Note that you may already by default be using a C - library containing a malloc that is based on some version of this - malloc (for example in linux). You might still want to use the one - in this file to customize settings or to avoid overheads associated - with library versions. - -* Vital statistics: - - Supported pointer/size_t representation: 4 or 8 bytes - size_t MUST be an unsigned type of the same width as - pointers. (If you are using an ancient system that declares - size_t as a signed type, or need it to be a different width - than pointers, you can use a previous release of this malloc - (e.g. 2.7.2) supporting these.) - - Alignment: 8 bytes (default) - This suffices for nearly all current machines and C compilers. - However, you can define MALLOC_ALIGNMENT to be wider than this - if necessary (up to 128bytes), at the expense of using more space. - - Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) - 8 or 16 bytes (if 8byte sizes) - Each malloced chunk has a hidden word of overhead holding size - and status information, and additional cross-check word - if FOOTERS is defined. - - Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) - 8-byte ptrs: 32 bytes (including overhead) - - Even a request for zero bytes (i.e., malloc(0)) returns a - pointer to something of the minimum allocatable size. - The maximum overhead wastage (i.e., number of extra bytes - allocated than were requested in malloc) is less than or equal - to the minimum size, except for requests >= mmap_threshold that - are serviced via mmap(), where the worst case wastage is about - 32 bytes plus the remainder from a system page (the minimal - mmap unit); typically 4096 or 8192 bytes. - - Security: static-safe; optionally more or less - The "security" of malloc refers to the ability of malicious - code to accentuate the effects of errors (for example, freeing - space that is not currently malloc'ed or overwriting past the - ends of chunks) in code that calls malloc. This malloc - guarantees not to modify any memory locations below the base of - heap, i.e., static variables, even in the presence of usage - errors. The routines additionally detect most improper frees - and reallocs. All this holds as long as the static bookkeeping - for malloc itself is not corrupted by some other means. This - is only one aspect of security -- these checks do not, and - cannot, detect all possible programming errors. - - If FOOTERS is defined nonzero, then each allocated chunk - carries an additional check word to verify that it was malloced - from its space. These check words are the same within each - execution of a program using malloc, but differ across - executions, so externally crafted fake chunks cannot be - freed. This improves security by rejecting frees/reallocs that - could corrupt heap memory, in addition to the checks preventing - writes to statics that are always on. This may further improve - security at the expense of time and space overhead. (Note that - FOOTERS may also be worth using with MSPACES.) - - By default detected errors cause the program to abort (calling - "abort()"). You can override this to instead proceed past - errors by defining PROCEED_ON_ERROR. In this case, a bad free - has no effect, and a malloc that encounters a bad address - caused by user overwrites will ignore the bad address by - dropping pointers and indices to all known memory. This may - be appropriate for programs that should continue if at all - possible in the face of programming errors, although they may - run out of memory because dropped memory is never reclaimed. - - If you don't like either of these options, you can define - CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has - no errors or vulnerabilities, you can define INSECURE to 1, - which might (or might not) provide a small performance improvement. - - It is also possible to limit the maximum total allocatable - space, using malloc_set_footprint_limit. This is not - designed as a security feature in itself (calls to set limits - are not screened or privileged), but may be useful as one - aspect of a secure implementation. - - Thread-safety: NOT thread-safe unless USE_LOCKS defined non-zero - When USE_LOCKS is defined, each public call to malloc, free, - etc is surrounded with a lock. By default, this uses a plain - pthread mutex, win32 critical section, or a spin-lock if if - available for the platform and not disabled by setting - USE_SPIN_LOCKS=0. However, if USE_RECURSIVE_LOCKS is defined, - recursive versions are used instead (which are not required for - base functionality but may be needed in layered extensions). - Using a global lock is not especially fast, and can be a major - bottleneck. It is designed only to provide minimal protection - in concurrent environments, and to provide a basis for - extensions. If you are using malloc in a concurrent program, - consider instead using nedmalloc - (http://www.nedprod.com/programs/portable/nedmalloc/) or - ptmalloc (See http://www.malloc.de), which are derived from - versions of this malloc. - - System requirements: Any combination of MORECORE and/or MMAP/MUNMAP - This malloc can use unix sbrk or any emulation (invoked using - the CALL_MORECORE macro) and/or mmap/munmap or any emulation - (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system - memory. On most unix systems, it tends to work best if both - MORECORE and MMAP are enabled. On Win32, it uses emulations - based on VirtualAlloc. It also uses common C library functions - like memset. - - Compliance: I believe it is compliant with the Single Unix Specification - (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably - others as well. - -* Overview of algorithms - - This is not the fastest, most space-conserving, most portable, or - most tunable malloc ever written. However it is among the fastest - while also being among the most space-conserving, portable and - tunable. Consistent balance across these factors results in a good - general-purpose allocator for malloc-intensive programs. - - In most ways, this malloc is a best-fit allocator. Generally, it - chooses the best-fitting existing chunk for a request, with ties - broken in approximately least-recently-used order. (This strategy - normally maintains low fragmentation.) However, for requests less - than 256bytes, it deviates from best-fit when there is not an - exactly fitting available chunk by preferring to use space adjacent - to that used for the previous small request, as well as by breaking - ties in approximately most-recently-used order. (These enhance - locality of series of small allocations.) And for very large requests - (>= 256Kb by default), it relies on system memory mapping - facilities, if supported. (This helps avoid carrying around and - possibly fragmenting memory used only for large chunks.) - - All operations (except malloc_stats and mallinfo) have execution - times that are bounded by a constant factor of the number of bits in - a size_t, not counting any clearing in calloc or copying in realloc, - or actions surrounding MORECORE and MMAP that have times - proportional to the number of non-contiguous regions returned by - system allocation routines, which is often just 1. In real-time - applications, you can optionally suppress segment traversals using - NO_SEGMENT_TRAVERSAL, which assures bounded execution even when - system allocators return non-contiguous spaces, at the typical - expense of carrying around more memory and increased fragmentation. - - The implementation is not very modular and seriously overuses - macros. Perhaps someday all C compilers will do as good a job - inlining modular code as can now be done by brute-force expansion, - but now, enough of them seem not to. - - Some compilers issue a lot of warnings about code that is - dead/unreachable only on some platforms, and also about intentional - uses of negation on unsigned types. All known cases of each can be - ignored. - - For a longer but out of date high-level description, see - http://gee.cs.oswego.edu/dl/html/malloc.html - -* MSPACES - If MSPACES is defined, then in addition to malloc, free, etc., - this file also defines mspace_malloc, mspace_free, etc. These - are versions of malloc routines that take an "mspace" argument - obtained using create_mspace, to control all internal bookkeeping. - If ONLY_MSPACES is defined, only these versions are compiled. - So if you would like to use this allocator for only some allocations, - and your system malloc for others, you can compile with - ONLY_MSPACES and then do something like... - static mspace mymspace = create_mspace(0,0); // for example - #define mymalloc(bytes) mspace_malloc(mymspace, bytes) - - (Note: If you only need one instance of an mspace, you can instead - use "USE_DL_PREFIX" to relabel the global malloc.) - - You can similarly create thread-local allocators by storing - mspaces as thread-locals. For example: - static __thread mspace tlms = 0; - void* tlmalloc(size_t bytes) { - if (tlms == 0) tlms = create_mspace(0, 0); - return mspace_malloc(tlms, bytes); - } - void tlfree(void* mem) { mspace_free(tlms, mem); } - - Unless FOOTERS is defined, each mspace is completely independent. - You cannot allocate from one and free to another (although - conformance is only weakly checked, so usage errors are not always - caught). If FOOTERS is defined, then each chunk carries around a tag - indicating its originating mspace, and frees are directed to their - originating spaces. Normally, this requires use of locks. - - ------------------------- Compile-time options --------------------------- - -Be careful in setting #define values for numerical constants of type -size_t. On some systems, literal values are not automatically extended -to size_t precision unless they are explicitly casted. You can also -use the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below. - -WIN32 default: defined if _WIN32 defined - Defining WIN32 sets up defaults for MS environment and compilers. - Otherwise defaults are for unix. Beware that there seem to be some - cases where this malloc might not be a pure drop-in replacement for - Win32 malloc: Random-looking failures from Win32 GDI API's (eg; - SetDIBits()) may be due to bugs in some video driver implementations - when pixel buffers are malloc()ed, and the region spans more than - one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb) - default granularity, pixel buffers may straddle virtual allocation - regions more often than when using the Microsoft allocator. You can - avoid this by using VirtualAlloc() and VirtualFree() for all pixel - buffers rather than using malloc(). If this is not possible, - recompile this malloc with a larger DEFAULT_GRANULARITY. Note: - in cases where MSC and gcc (cygwin) are known to differ on WIN32, - conditions use _MSC_VER to distinguish them. - -DLMALLOC_EXPORT default: extern - Defines how public APIs are declared. If you want to export via a - Windows DLL, you might define this as - #define DLMALLOC_EXPORT extern __declspace(dllexport) - If you want a POSIX ELF shared object, you might use - #define DLMALLOC_EXPORT extern __attribute__((visibility("default"))) - -MALLOC_ALIGNMENT default: (size_t)8 - Controls the minimum alignment for malloc'ed chunks. It must be a - power of two and at least 8, even on machines for which smaller - alignments would suffice. It may be defined as larger than this - though. Note however that code and data structures are optimized for - the case of 8-byte alignment. - -MSPACES default: 0 (false) - If true, compile in support for independent allocation spaces. - This is only supported if HAVE_MMAP is true. - -ONLY_MSPACES default: 0 (false) - If true, only compile in mspace versions, not regular versions. - -USE_LOCKS default: 0 (false) - Causes each call to each public routine to be surrounded with - pthread or WIN32 mutex lock/unlock. (If set true, this can be - overridden on a per-mspace basis for mspace versions.) If set to a - non-zero value other than 1, locks are used, but their - implementation is left out, so lock functions must be supplied manually, - as described below. - -USE_SPIN_LOCKS default: 1 iff USE_LOCKS and spin locks available - If true, uses custom spin locks for locking. This is currently - supported only gcc >= 4.1, older gccs on x86 platforms, and recent - MS compilers. Otherwise, posix locks or win32 critical sections are - used. - -USE_RECURSIVE_LOCKS default: not defined - If defined nonzero, uses recursive (aka reentrant) locks, otherwise - uses plain mutexes. This is not required for malloc proper, but may - be needed for layered allocators such as nedmalloc. - -FOOTERS default: 0 - If true, provide extra checking and dispatching by placing - information in the footers of allocated chunks. This adds - space and time overhead. - -INSECURE default: 0 - If true, omit checks for usage errors and heap space overwrites. - -USE_DL_PREFIX default: NOT defined - Causes compiler to prefix all public routines with the string 'dl'. - This can be useful when you only want to use this malloc in one part - of a program, using your regular system malloc elsewhere. - -MALLOC_INSPECT_ALL default: NOT defined - If defined, compiles malloc_inspect_all and mspace_inspect_all, that - perform traversal of all heap space. Unless access to these - functions is otherwise restricted, you probably do not want to - include them in secure implementations. - -ABORT default: defined as abort() - Defines how to abort on failed checks. On most systems, a failed - check cannot die with an "assert" or even print an informative - message, because the underlying print routines in turn call malloc, - which will fail again. Generally, the best policy is to simply call - abort(). It's not very useful to do more than this because many - errors due to overwriting will show up as address faults (null, odd - addresses etc) rather than malloc-triggered checks, so will also - abort. Also, most compilers know that abort() does not return, so - can better optimize code conditionally calling it. - -PROCEED_ON_ERROR default: defined as 0 (false) - Controls whether detected bad addresses cause them to bypassed - rather than aborting. If set, detected bad arguments to free and - realloc are ignored. And all bookkeeping information is zeroed out - upon a detected overwrite of freed heap space, thus losing the - ability to ever return it from malloc again, but enabling the - application to proceed. If PROCEED_ON_ERROR is defined, the - static variable malloc_corruption_error_count is compiled in - and can be examined to see if errors have occurred. This option - generates slower code than the default abort policy. - -DEBUG default: NOT defined - The DEBUG setting is mainly intended for people trying to modify - this code or diagnose problems when porting to new platforms. - However, it may also be able to better isolate user errors than just - using runtime checks. The assertions in the check routines spell - out in more detail the assumptions and invariants underlying the - algorithms. The checking is fairly extensive, and will slow down - execution noticeably. Calling malloc_stats or mallinfo with DEBUG - set will attempt to check every non-mmapped allocated and free chunk - in the course of computing the summaries. - -ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) - Debugging assertion failures can be nearly impossible if your - version of the assert macro causes malloc to be called, which will - lead to a cascade of further failures, blowing the runtime stack. - ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), - which will usually make debugging easier. - -MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 - The action to take before "return 0" when malloc fails to be able to - return memory because there is none available. - -HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES - True if this system supports sbrk or an emulation of it. - -MORECORE default: sbrk - The name of the sbrk-style system routine to call to obtain more - memory. See below for guidance on writing custom MORECORE - functions. The type of the argument to sbrk/MORECORE varies across - systems. It cannot be size_t, because it supports negative - arguments, so it is normally the signed type of the same width as - size_t (sometimes declared as "intptr_t"). It doesn't much matter - though. Internally, we only call it with arguments less than half - the max value of a size_t, which should work across all reasonable - possibilities, although sometimes generating compiler warnings. - -MORECORE_CONTIGUOUS default: 1 (true) if HAVE_MORECORE - If true, take advantage of fact that consecutive calls to MORECORE - with positive arguments always return contiguous increasing - addresses. This is true of unix sbrk. It does not hurt too much to - set it true anyway, since malloc copes with non-contiguities. - Setting it false when definitely non-contiguous saves time - and possibly wasted space it would take to discover this though. - -MORECORE_CANNOT_TRIM default: NOT defined - True if MORECORE cannot release space back to the system when given - negative arguments. This is generally necessary only if you are - using a hand-crafted MORECORE function that cannot handle negative - arguments. - -NO_SEGMENT_TRAVERSAL default: 0 - If non-zero, suppresses traversals of memory segments - returned by either MORECORE or CALL_MMAP. This disables - merging of segments that are contiguous, and selectively - releasing them to the OS if unused, but bounds execution times. - -HAVE_MMAP default: 1 (true) - True if this system supports mmap or an emulation of it. If so, and - HAVE_MORECORE is not true, MMAP is used for all system - allocation. If set and HAVE_MORECORE is true as well, MMAP is - primarily used to directly allocate very large blocks. It is also - used as a backup strategy in cases where MORECORE fails to provide - space from system. Note: A single call to MUNMAP is assumed to be - able to unmap memory that may have be allocated using multiple calls - to MMAP, so long as they are adjacent. - -HAVE_MREMAP default: 1 on linux, else 0 - If true realloc() uses mremap() to re-allocate large blocks and - extend or shrink allocation spaces. - -MMAP_CLEARS default: 1 except on WINCE. - True if mmap clears memory so calloc doesn't need to. This is true - for standard unix mmap using /dev/zero and on WIN32 except for WINCE. - -USE_BUILTIN_FFS default: 0 (i.e., not used) - Causes malloc to use the builtin ffs() function to compute indices. - Some compilers may recognize and intrinsify ffs to be faster than the - supplied C version. Also, the case of x86 using gcc is special-cased - to an asm instruction, so is already as fast as it can be, and so - this setting has no effect. Similarly for Win32 under recent MS compilers. - (On most x86s, the asm version is only slightly faster than the C version.) - -malloc_getpagesize default: derive from system includes, or 4096. - The system page size. To the extent possible, this malloc manages - memory from the system in page-size units. This may be (and - usually is) a function rather than a constant. This is ignored - if WIN32, where page size is determined using getSystemInfo during - initialization. - -USE_DEV_RANDOM default: 0 (i.e., not used) - Causes malloc to use /dev/random to initialize secure magic seed for - stamping footers. Otherwise, the current time is used. - -NO_MALLINFO default: 0 - If defined, don't compile "mallinfo". This can be a simple way - of dealing with mismatches between system declarations and - those in this file. - -MALLINFO_FIELD_TYPE default: size_t - The type of the fields in the mallinfo struct. This was originally - defined as "int" in SVID etc, but is more usefully defined as - size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set - -NO_MALLOC_STATS default: 0 - If defined, don't compile "malloc_stats". This avoids calls to - fprintf and bringing in stdio dependencies you might not want. - -REALLOC_ZERO_BYTES_FREES default: not defined - This should be set if a call to realloc with zero bytes should - be the same as a call to free. Some people think it should. Otherwise, - since this malloc returns a unique pointer for malloc(0), so does - realloc(p, 0). - -LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H -LACKS_STRINGS_H, LACKS_STRING_H, LACKS_ERRNO_H LACKS_STDLIB_H LACKS_SCHED_H -LACKS_TIME_H default: NOT defined unless on WIN32 - Define these if your system does not have these header files. - You might need to manually insert some of the declarations they provide. - -DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, - system_info.dwAllocationGranularity in WIN32, - otherwise 64K. - Also settable using mallopt(M_GRANULARITY, x) - The unit for allocating and deallocating memory from the system. On - most systems with contiguous MORECORE, there is no reason to - make this more than a page. However, systems with MMAP tend to - either require or encourage larger granularities. You can increase - this value to prevent system allocation functions to be called so - often, especially if they are slow. The value must be at least one - page and must be a power of two. Setting to 0 causes initialization - to either page size or win32 region size. (Note: In previous - versions of malloc, the equivalent of this option was called - "TOP_PAD") - -DEFAULT_TRIM_THRESHOLD default: 2MB - Also settable using mallopt(M_TRIM_THRESHOLD, x) - The maximum amount of unused top-most memory to keep before - releasing via malloc_trim in free(). Automatic trimming is mainly - useful in long-lived programs using contiguous MORECORE. Because - trimming via sbrk can be slow on some systems, and can sometimes be - wasteful (in cases where programs immediately afterward allocate - more large chunks) the value should be high enough so that your - overall system performance would improve by releasing this much - memory. As a rough guide, you might set to a value close to the - average size of a process (program) running on your system. - Releasing this much memory would allow such a process to run in - memory. Generally, it is worth tuning trim thresholds when a - program undergoes phases where several large chunks are allocated - and released in ways that can reuse each other's storage, perhaps - mixed with phases where there are no such chunks at all. The trim - value must be greater than page size to have any useful effect. To - disable trimming completely, you can set to MAX_SIZE_T. Note that the trick - some people use of mallocing a huge space and then freeing it at - program startup, in an attempt to reserve system memory, doesn't - have the intended effect under automatic trimming, since that memory - will immediately be returned to the system. - -DEFAULT_MMAP_THRESHOLD default: 256K - Also settable using mallopt(M_MMAP_THRESHOLD, x) - The request size threshold for using MMAP to directly service a - request. Requests of at least this size that cannot be allocated - using already-existing space will be serviced via mmap. (If enough - normal freed space already exists it is used instead.) Using mmap - segregates relatively large chunks of memory so that they can be - individually obtained and released from the host system. A request - serviced through mmap is never reused by any other request (at least - not directly; the system may just so happen to remap successive - requests to the same locations). Segregating space in this way has - the benefits that: Mmapped space can always be individually released - back to the system, which helps keep the system level memory demands - of a long-lived program low. Also, mapped memory doesn't become - `locked' between other chunks, as can happen with normally allocated - chunks, which means that even trimming via malloc_trim would not - release them. However, it has the disadvantage that the space - cannot be reclaimed, consolidated, and then used to service later - requests, as happens with normal chunks. The advantages of mmap - nearly always outweigh disadvantages for "large" chunks, but the - value of "large" may vary across systems. The default is an - empirically derived value that works well in most systems. You can - disable mmap by setting to MAX_SIZE_T. - -MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP - The number of consolidated frees between checks to release - unused segments when freeing. When using non-contiguous segments, - especially with multiple mspaces, checking only for topmost space - doesn't always suffice to trigger trimming. To compensate for this, - free() will, with a period of MAX_RELEASE_CHECK_RATE (or the - current number of segments, if greater) try to release unused - segments to the OS when freeing chunks that result in - consolidation. The best value for this parameter is a compromise - between slowing down frees with relatively costly checks that - rarely trigger versus holding on to unused memory. To effectively - disable, set to MAX_SIZE_T. This may lead to a very slight speed - improvement at the expense of carrying around more memory. -*/ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wcast-align" - -/* Version identifier to allow people to support multiple versions */ -#ifndef DLMALLOC_VERSION -#define DLMALLOC_VERSION 20805 -#endif /* DLMALLOC_VERSION */ - -#ifndef DLMALLOC_EXPORT -#define DLMALLOC_EXPORT extern -#endif - -#ifndef WIN32 -#ifdef _WIN32 -#define WIN32 1 -#endif /* _WIN32 */ -#ifdef _WIN32_WCE -#define LACKS_FCNTL_H -#define WIN32 1 -#endif /* _WIN32_WCE */ -#endif /* WIN32 */ -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#define HAVE_MMAP 1 -#define HAVE_MORECORE 0 -#define LACKS_UNISTD_H -#define LACKS_SYS_PARAM_H -#define LACKS_SYS_MMAN_H -#define LACKS_STRING_H -#define LACKS_STRINGS_H -#define LACKS_ERRNO_H -#define LACKS_SCHED_H -#ifndef MALLOC_FAILURE_ACTION -#define MALLOC_FAILURE_ACTION -#endif /* MALLOC_FAILURE_ACTION */ -#ifndef MMAP_CLEARS -#ifdef _WIN32_WCE /* WINCE reportedly does not clear */ -#define MMAP_CLEARS 0 -#else -#define MMAP_CLEARS 1 -#endif /* _WIN32_WCE */ -#endif /*MMAP_CLEARS */ -#endif /* WIN32 */ - -#if defined(DARWIN) || defined(_DARWIN) -/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ -#ifndef HAVE_MORECORE -#define HAVE_MORECORE 0 -#define HAVE_MMAP 1 -/* OSX allocators provide 16 byte alignment */ -#ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT ((size_t)16U) -#endif -#endif /* HAVE_MORECORE */ -#endif /* DARWIN */ - -#include /* For size_t */ -#include /* For uintptr_t */ - -/* The maximum possible size_t value has all bits set */ -#define MAX_SIZE_T (~(size_t)0) - -#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ -#if ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ - (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) -#define USE_LOCKS 1 -#else -#define USE_LOCKS 0 -#endif -#endif /* USE_LOCKS */ - -#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ -#if ((defined(__GNUC__) && \ - ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \ - defined(__i386__) || defined(__x86_64__))) || \ - (defined(_MSC_VER) && _MSC_VER>=1310)) -#ifndef USE_SPIN_LOCKS -#define USE_SPIN_LOCKS 1 -#endif /* USE_SPIN_LOCKS */ -#elif USE_SPIN_LOCKS -#error "USE_SPIN_LOCKS defined without implementation" -#endif /* ... locks available... */ -#elif !defined(USE_SPIN_LOCKS) -#define USE_SPIN_LOCKS 0 -#endif /* USE_LOCKS */ - -#ifndef ONLY_MSPACES -#define ONLY_MSPACES 0 -#endif /* ONLY_MSPACES */ -#ifndef MSPACES -#if ONLY_MSPACES -#define MSPACES 1 -#else /* ONLY_MSPACES */ -#define MSPACES 0 -#endif /* ONLY_MSPACES */ -#endif /* MSPACES */ -#ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT ((size_t)8U) -#endif /* MALLOC_ALIGNMENT */ -#ifndef FOOTERS -#define FOOTERS 0 -#endif /* FOOTERS */ -#ifndef ABORT -#define ABORT abort() -#endif /* ABORT */ -#ifndef ABORT_ON_ASSERT_FAILURE -#define ABORT_ON_ASSERT_FAILURE 1 -#endif /* ABORT_ON_ASSERT_FAILURE */ -#ifndef PROCEED_ON_ERROR -#define PROCEED_ON_ERROR 0 -#endif /* PROCEED_ON_ERROR */ - -#ifndef INSECURE -#define INSECURE 0 -#endif /* INSECURE */ -#ifndef MALLOC_INSPECT_ALL -#define MALLOC_INSPECT_ALL 0 -#endif /* MALLOC_INSPECT_ALL */ -#ifndef HAVE_MMAP -#define HAVE_MMAP 1 -#endif /* HAVE_MMAP */ -#ifndef MMAP_CLEARS -#define MMAP_CLEARS 1 -#endif /* MMAP_CLEARS */ -#ifndef HAVE_MREMAP -#ifdef linux -#define HAVE_MREMAP 1 -#define _GNU_SOURCE /* Turns on mremap() definition */ -#else /* linux */ -#define HAVE_MREMAP 0 -#endif /* linux */ -#endif /* HAVE_MREMAP */ -#ifndef MALLOC_FAILURE_ACTION -#define MALLOC_FAILURE_ACTION errno = ENOMEM; -#endif /* MALLOC_FAILURE_ACTION */ -#ifndef HAVE_MORECORE -#if ONLY_MSPACES -#define HAVE_MORECORE 0 -#else /* ONLY_MSPACES */ -#define HAVE_MORECORE 1 -#endif /* ONLY_MSPACES */ -#endif /* HAVE_MORECORE */ -#if !HAVE_MORECORE -#define MORECORE_CONTIGUOUS 0 -#else /* !HAVE_MORECORE */ -#define MORECORE_DEFAULT sbrk -#ifndef MORECORE_CONTIGUOUS -#define MORECORE_CONTIGUOUS 1 -#endif /* MORECORE_CONTIGUOUS */ -#endif /* HAVE_MORECORE */ -#ifndef DEFAULT_GRANULARITY -#if (MORECORE_CONTIGUOUS || defined(WIN32)) -#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ -#else /* MORECORE_CONTIGUOUS */ -#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) -#endif /* MORECORE_CONTIGUOUS */ -#endif /* DEFAULT_GRANULARITY */ -#ifndef DEFAULT_TRIM_THRESHOLD -#ifndef MORECORE_CANNOT_TRIM -#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) -#else /* MORECORE_CANNOT_TRIM */ -#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T -#endif /* MORECORE_CANNOT_TRIM */ -#endif /* DEFAULT_TRIM_THRESHOLD */ -#ifndef DEFAULT_MMAP_THRESHOLD -#if HAVE_MMAP -#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) -#else /* HAVE_MMAP */ -#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T -#endif /* HAVE_MMAP */ -#endif /* DEFAULT_MMAP_THRESHOLD */ -#ifndef MAX_RELEASE_CHECK_RATE -#if HAVE_MMAP -#define MAX_RELEASE_CHECK_RATE 4095 -#else -#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T -#endif /* HAVE_MMAP */ -#endif /* MAX_RELEASE_CHECK_RATE */ -#ifndef USE_BUILTIN_FFS -#define USE_BUILTIN_FFS 0 -#endif /* USE_BUILTIN_FFS */ -#ifndef USE_DEV_RANDOM -#define USE_DEV_RANDOM 0 -#endif /* USE_DEV_RANDOM */ -#ifndef NO_MALLINFO -#define NO_MALLINFO 0 -#endif /* NO_MALLINFO */ -#ifndef MALLINFO_FIELD_TYPE -#define MALLINFO_FIELD_TYPE size_t -#endif /* MALLINFO_FIELD_TYPE */ -#ifndef NO_MALLOC_STATS -#define NO_MALLOC_STATS 0 -#endif /* NO_MALLOC_STATS */ -#ifndef NO_SEGMENT_TRAVERSAL -#define NO_SEGMENT_TRAVERSAL 0 -#endif /* NO_SEGMENT_TRAVERSAL */ - -/* - mallopt tuning options. SVID/XPG defines four standard parameter - numbers for mallopt, normally defined in malloc.h. None of these - are used in this malloc, so setting them has no effect. But this - malloc does support the following options. -*/ - -#define M_TRIM_THRESHOLD (-1) -#define M_GRANULARITY (-2) -#define M_MMAP_THRESHOLD (-3) - -/* ------------------------ Mallinfo declarations ------------------------ */ - -#if !NO_MALLINFO -/* - This version of malloc supports the standard SVID/XPG mallinfo - routine that returns a struct containing usage properties and - statistics. It should work on any system that has a - /usr/include/malloc.h defining struct mallinfo. The main - declaration needed is the mallinfo struct that is returned (by-copy) - by mallinfo(). The malloinfo struct contains a bunch of fields that - are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of - interest. - - HAVE_USR_INCLUDE_MALLOC_H should be set if you have a - /usr/include/malloc.h file that includes a declaration of struct - mallinfo. If so, it is included; else a compliant version is - declared below. These must be precisely the same for mallinfo() to - work. The original SVID version of this struct, defined on most - systems with mallinfo, declares all fields as ints. But some others - define as unsigned long. If your system defines the fields using a - type of different width than listed here, you MUST #include your - system version and #define HAVE_USR_INCLUDE_MALLOC_H. -*/ - -/* #define HAVE_USR_INCLUDE_MALLOC_H */ - -#ifdef HAVE_USR_INCLUDE_MALLOC_H -#include "/usr/include/malloc.h" -#else /* HAVE_USR_INCLUDE_MALLOC_H */ -#ifndef STRUCT_MALLINFO_DECLARED -/* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */ -#define _STRUCT_MALLINFO -#define STRUCT_MALLINFO_DECLARED 1 -struct mallinfo { - MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ - MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ - MALLINFO_FIELD_TYPE smblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ - MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ - MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ - MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ - MALLINFO_FIELD_TYPE fordblks; /* total free space */ - MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ -}; -#endif /* STRUCT_MALLINFO_DECLARED */ -#endif /* HAVE_USR_INCLUDE_MALLOC_H */ -#endif /* NO_MALLINFO */ - -/* - Try to persuade compilers to inline. The most critical functions for - inlining are defined as macros, so these aren't used for them. -*/ - -#ifndef FORCEINLINE - #if defined(__GNUC__) -#define FORCEINLINE __inline __attribute__ ((always_inline)) - #elif defined(_MSC_VER) - #define FORCEINLINE __forceinline - #endif -#endif -#ifndef NOINLINE - #if defined(__GNUC__) - #define NOINLINE __attribute__ ((noinline)) - #elif defined(_MSC_VER) - #define NOINLINE __declspec(noinline) - #else - #define NOINLINE - #endif -#endif - -#ifdef __cplusplus -extern "C" { -#ifndef FORCEINLINE - #define FORCEINLINE inline -#endif -#endif /* __cplusplus */ -#ifndef FORCEINLINE - #define FORCEINLINE -#endif - -#if !ONLY_MSPACES - -/* ------------------- Declarations of public routines ------------------- */ - -#ifndef USE_DL_PREFIX -#define dlcalloc calloc -#define dlfree free -#define dlmalloc malloc -#define dlmemalign memalign -#define dlposix_memalign posix_memalign -#define dlrealloc realloc -#define dlrealloc_in_place realloc_in_place -#define dlvalloc valloc -#define dlpvalloc pvalloc -#define dlmallinfo mallinfo -#define dlmallopt mallopt -#define dlmalloc_trim malloc_trim -#define dlmalloc_stats malloc_stats -#define dlmalloc_usable_size malloc_usable_size -#define dlmalloc_footprint malloc_footprint -#define dlmalloc_max_footprint malloc_max_footprint -#define dlmalloc_footprint_limit malloc_footprint_limit -#define dlmalloc_set_footprint_limit malloc_set_footprint_limit -#define dlmalloc_inspect_all malloc_inspect_all -#define dlindependent_calloc independent_calloc -#define dlindependent_comalloc independent_comalloc -#define dlbulk_free bulk_free -#endif /* USE_DL_PREFIX */ - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or - null if no space is available, in which case errno is set to ENOMEM - on ANSI C systems. - - If n is zero, malloc returns a minimum-sized chunk. (The minimum - size is 16 bytes on most 32bit systems, and 32 bytes on 64bit - systems.) Note that size_t is an unsigned type, so calls with - arguments that would be negative if signed are interpreted as - requests for huge amounts of space, which will often fail. The - maximum supported value of n differs across systems, but is in all - cases less than the maximum representable value of a size_t. -*/ -DLMALLOC_EXPORT void* dlmalloc(size_t); - -/* - free(void* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. If p was not malloced or already - freed, free(p) will by default cause the current program to abort. -*/ -DLMALLOC_EXPORT void dlfree(void*); - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -DLMALLOC_EXPORT void* dlcalloc(size_t, size_t); - -/* - realloc(void* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p in most cases when possible, otherwise it - employs the equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. realloc with a size - argument of zero (re)allocates a minimum-sized chunk. - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ -DLMALLOC_EXPORT void* dlrealloc(void*, size_t); - -/* - realloc_in_place(void* p, size_t n) - Resizes the space allocated for p to size n, only if this can be - done without moving p (i.e., only if there is adjacent space - available if n is greater than p's current allocated size, or n is - less than or equal to p's size). This may be used instead of plain - realloc if an alternative allocation strategy is needed upon failure - to expand space; for example, reallocation of a buffer that must be - memory-aligned or cleared. You can use realloc_in_place to trigger - these alternatives only when needed. - - Returns p if successful; otherwise null. -*/ -DLMALLOC_EXPORT void* dlrealloc_in_place(void*, size_t); - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ -DLMALLOC_EXPORT void* dlmemalign(size_t, size_t); - -/* - int posix_memalign(void** pp, size_t alignment, size_t n); - Allocates a chunk of n bytes, aligned in accord with the alignment - argument. Differs from memalign only in that it (1) assigns the - allocated memory to *pp rather than returning it, (2) fails and - returns EINVAL if the alignment is not a power of two (3) fails and - returns ENOMEM if memory cannot be allocated. -*/ -DLMALLOC_EXPORT int dlposix_memalign(void**, size_t, size_t); - -/* - valloc(size_t n); - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ -DLMALLOC_EXPORT void* dlvalloc(size_t); - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. To workaround the fact that mallopt is specified to use int, - not size_t parameters, the value -1 is specially treated as the - maximum unsigned size_t value. - - SVID/XPG/ANSI defines four standard param numbers for mallopt, - normally defined in malloc.h. None of these are use in this malloc, - so setting them has no effect. But this malloc also supports other - options in mallopt. See below for details. Briefly, supported - parameters are as follows (listed defaults are for "typical" - configurations). - - Symbol param # default allowed param values - M_TRIM_THRESHOLD -1 2*1024*1024 any (-1 disables) - M_GRANULARITY -2 page size any power of 2 >= page size - M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) -*/ -DLMALLOC_EXPORT int dlmallopt(int, int); - -/* - malloc_footprint(); - Returns the number of bytes obtained from the system. The total - number of bytes allocated by malloc, realloc etc., is less than this - value. Unlike mallinfo, this function returns only a precomputed - result, so can be called frequently to monitor memory consumption. - Even if locks are otherwise defined, this function does not use them, - so results might not be up to date. -*/ -DLMALLOC_EXPORT size_t dlmalloc_footprint(void); - -/* - malloc_max_footprint(); - Returns the maximum number of bytes obtained from the system. This - value will be greater than current footprint if deallocated space - has been reclaimed by the system. The peak number of bytes allocated - by malloc, realloc etc., is less than this value. Unlike mallinfo, - this function returns only a precomputed result, so can be called - frequently to monitor memory consumption. Even if locks are - otherwise defined, this function does not use them, so results might - not be up to date. -*/ -DLMALLOC_EXPORT size_t dlmalloc_max_footprint(void); - -/* - malloc_footprint_limit(); - Returns the number of bytes that the heap is allowed to obtain from - the system, returning the last value returned by - malloc_set_footprint_limit, or the maximum size_t value if - never set. The returned value reflects a permission. There is no - guarantee that this number of bytes can actually be obtained from - the system. -*/ -DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(void); - -/* - malloc_set_footprint_limit(); - Sets the maximum number of bytes to obtain from the system, causing - failure returns from malloc and related functions upon attempts to - exceed this value. The argument value may be subject to page - rounding to an enforceable limit; this actual value is returned. - Using an argument of the maximum possible size_t effectively - disables checks. If the argument is less than or equal to the - current malloc_footprint, then all future allocations that require - additional system memory will fail. However, invocation cannot - retroactively deallocate existing used memory. -*/ -DLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes); - -#if MALLOC_INSPECT_ALL -/* - malloc_inspect_all(void(*handler)(void *start, - void *end, - size_t used_bytes, - void* callback_arg), - void* arg); - Traverses the heap and calls the given handler for each managed - region, skipping all bytes that are (or may be) used for bookkeeping - purposes. Traversal does not include include chunks that have been - directly memory mapped. Each reported region begins at the start - address, and continues up to but not including the end address. The - first used_bytes of the region contain allocated data. If - used_bytes is zero, the region is unallocated. The handler is - invoked with the given callback argument. If locks are defined, they - are held during the entire traversal. It is a bad idea to invoke - other malloc functions from within the handler. - - For example, to count the number of in-use chunks with size greater - than 1000, you could write: - static int count = 0; - void count_chunks(void* start, void* end, size_t used, void* arg) { - if (used >= 1000) ++count; - } - then: - malloc_inspect_all(count_chunks, NULL); - - malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined. -*/ -DLMALLOC_EXPORT void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), - void* arg); - -#endif /* MALLOC_INSPECT_ALL */ - -#if !NO_MALLINFO -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: always zero. - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: always zero - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - Because these fields are ints, but internal bookkeeping may - be kept as longs, the reported values may wrap around zero and - thus be inaccurate. -*/ -DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); -#endif /* NO_MALLINFO */ - -/* - independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements that can hold contents of size elem_size, each - of which starts out cleared, and can be independently freed, - realloc'ed etc. The elements are guaranteed to be adjacently - allocated (this is not guaranteed to occur with multiple callocs or - mallocs), which may also improve cache locality in some - applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be freed when it is no longer needed. This can be - done all at once using bulk_free. - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) die(); - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ -DLMALLOC_EXPORT void** dlindependent_calloc(size_t, size_t, void**); - -/* - independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be freed when it is no longer needed. This can be - done all at once using bulk_free. - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ -DLMALLOC_EXPORT void** dlindependent_comalloc(size_t, size_t*, void**); - -/* - bulk_free(void* array[], size_t n_elements) - Frees and clears (sets to null) each non-null pointer in the given - array. This is likely to be faster than freeing them one-by-one. - If footers are used, pointers that have been allocated in different - mspaces are not freed or cleared, and the count of all such pointers - is returned. For large arrays of pointers with poor locality, it - may be worthwhile to sort this array before calling bulk_free. -*/ -DLMALLOC_EXPORT size_t dlbulk_free(void**, size_t n_elements); - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ -DLMALLOC_EXPORT void* dlpvalloc(size_t); - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative arguments - to sbrk) if there is unused memory at the `high' end of the malloc - pool or in unused MMAP segments. You can call this after freeing - large blocks of memory to potentially reduce the system-level memory - requirements of a program. However, it cannot guarantee to reduce - memory. Under some allocation patterns, some large free blocks of - memory will be locked between two used chunks, so they cannot be - given back to the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, only - the minimum amount of memory to maintain internal data structures - will be left. Non-zero arguments can be supplied to maintain enough - trailing space to service future expected allocations without having - to re-obtain memory from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. -*/ -DLMALLOC_EXPORT int dlmalloc_trim(size_t); - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. -*/ -DLMALLOC_EXPORT void dlmalloc_stats(void); - -#endif /* ONLY_MSPACES */ - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ -size_t dlmalloc_usable_size(void*); - -#if MSPACES - -/* - mspace is an opaque type representing an independent - region of space that supports mspace_malloc, etc. -*/ -typedef void* mspace; - -/* - create_mspace creates and returns a new independent space with the - given initial capacity, or, if 0, the default granularity size. It - returns null if there is no system memory available to create the - space. If argument locked is non-zero, the space uses a separate - lock to control access. The capacity of the space will grow - dynamically as needed to service mspace_malloc requests. You can - control the sizes of incremental increases of this space by - compiling with a different DEFAULT_GRANULARITY or dynamically - setting with mallopt(M_GRANULARITY, value). -*/ -DLMALLOC_EXPORT mspace create_mspace(size_t capacity, int locked); - -/* - destroy_mspace destroys the given space, and attempts to return all - of its memory back to the system, returning the total number of - bytes freed. After destruction, the results of access to all memory - used by the space become undefined. -*/ -DLMALLOC_EXPORT size_t destroy_mspace(mspace msp); - -/* - create_mspace_with_base uses the memory supplied as the initial base - of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this - space is used for bookkeeping, so the capacity must be at least this - large. (Otherwise 0 is returned.) When this initial space is - exhausted, additional memory will be obtained from the system. - Destroying this space will deallocate all additionally allocated - space (if possible) but not the initial base. -*/ -DLMALLOC_EXPORT mspace create_mspace_with_base(void* base, size_t capacity, int locked); - -/* - mspace_track_large_chunks controls whether requests for large chunks - are allocated in their own untracked mmapped regions, separate from - others in this mspace. By default large chunks are not tracked, - which reduces fragmentation. However, such chunks are not - necessarily released to the system upon destroy_mspace. Enabling - tracking by setting to true may increase fragmentation, but avoids - leakage when relying on destroy_mspace to release all memory - allocated using this space. The function returns the previous - setting. -*/ -DLMALLOC_EXPORT int mspace_track_large_chunks(mspace msp, int enable); - - -/* - mspace_malloc behaves as malloc, but operates within - the given space. -*/ -DLMALLOC_EXPORT void* mspace_malloc(mspace msp, size_t bytes); - -/* - mspace_free behaves as free, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_free is not actually needed. - free may be called instead of mspace_free because freed chunks from - any space are handled by their originating spaces. -*/ -DLMALLOC_EXPORT void mspace_free(mspace msp, void* mem); - -/* - mspace_realloc behaves as realloc, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_realloc is not actually - needed. realloc may be called instead of mspace_realloc because - realloced chunks from any space are handled by their originating - spaces. -*/ -DLMALLOC_EXPORT void* mspace_realloc(mspace msp, void* mem, size_t newsize); - -/* - mspace_calloc behaves as calloc, but operates within - the given space. -*/ -DLMALLOC_EXPORT void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); - -/* - mspace_memalign behaves as memalign, but operates within - the given space. -*/ -DLMALLOC_EXPORT void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); - -/* - mspace_independent_calloc behaves as independent_calloc, but - operates within the given space. -*/ -DLMALLOC_EXPORT void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]); - -/* - mspace_independent_comalloc behaves as independent_comalloc, but - operates within the given space. -*/ -DLMALLOC_EXPORT void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]); - -/* - mspace_footprint() returns the number of bytes obtained from the - system for this space. -*/ -DLMALLOC_EXPORT size_t mspace_footprint(mspace msp); - -/* - mspace_max_footprint() returns the peak number of bytes obtained from the - system for this space. -*/ -DLMALLOC_EXPORT size_t mspace_max_footprint(mspace msp); - - -#if !NO_MALLINFO -/* - mspace_mallinfo behaves as mallinfo, but reports properties of - the given space. -*/ -DLMALLOC_EXPORT struct mallinfo mspace_mallinfo(mspace msp); -#endif /* NO_MALLINFO */ - -/* - malloc_usable_size(void* p) behaves the same as malloc_usable_size; -*/ -DLMALLOC_EXPORT size_t mspace_usable_size(void* mem); - -/* - mspace_malloc_stats behaves as malloc_stats, but reports - properties of the given space. -*/ -DLMALLOC_EXPORT void mspace_malloc_stats(mspace msp); - -/* - mspace_trim behaves as malloc_trim, but - operates within the given space. -*/ -DLMALLOC_EXPORT int mspace_trim(mspace msp, size_t pad); - -/* - An alias for mallopt. -*/ -DLMALLOC_EXPORT int mspace_mallopt(int, int); - -#endif /* MSPACES */ - -#ifdef __cplusplus -} /* end of extern "C" */ -#endif /* __cplusplus */ - -/* - ======================================================================== - To make a fully customizable malloc.h header file, cut everything - above this line, put into file malloc.h, edit to suit, and #include it - on the next line, as well as in programs that use this malloc. - ======================================================================== -*/ - -/* #include "malloc.h" */ - -/*------------------------------ internal #includes ---------------------- */ - -#ifdef _MSC_VER -#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ -#endif /* _MSC_VER */ - -#if !NO_MALLOC_STATS -#include /* for printing in malloc_stats */ -#endif /* NO_MALLOC_STATS */ - -#ifndef LACKS_ERRNO_H -#include /* for MALLOC_FAILURE_ACTION */ -#endif /* LACKS_ERRNO_H */ - -#ifdef DEBUG -#if ABORT_ON_ASSERT_FAILURE -#undef assert -#define assert(x) if(!(x)) ABORT -#else /* ABORT_ON_ASSERT_FAILURE */ -#include -#endif /* ABORT_ON_ASSERT_FAILURE */ -#else /* DEBUG */ -#ifndef assert -#define assert(x) -#endif -#define DEBUG 0 -#endif /* DEBUG */ - -#if !defined(WIN32) && !defined(LACKS_TIME_H) -#include /* for magic initialization */ -#endif /* WIN32 */ - -#ifndef LACKS_STDLIB_H -#include /* for abort() */ -#endif /* LACKS_STDLIB_H */ - -#ifndef LACKS_STRING_H -#include /* for memset etc */ -#endif /* LACKS_STRING_H */ - -#if USE_BUILTIN_FFS -#ifndef LACKS_STRINGS_H -#include /* for ffs */ -#endif /* LACKS_STRINGS_H */ -#endif /* USE_BUILTIN_FFS */ - -#if HAVE_MMAP -#ifndef LACKS_SYS_MMAN_H -/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ -#if (defined(linux) && !defined(__USE_GNU)) -#define __USE_GNU 1 -#include /* for mmap */ -#undef __USE_GNU -#else -#include /* for mmap */ -#endif /* linux */ -#endif /* LACKS_SYS_MMAN_H */ -#ifndef LACKS_FCNTL_H -#include -#endif /* LACKS_FCNTL_H */ -#endif /* HAVE_MMAP */ - -#ifndef LACKS_UNISTD_H -#include /* for sbrk, sysconf */ -#else /* LACKS_UNISTD_H */ -#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -extern void* sbrk(ptrdiff_t); -#endif /* FreeBSD etc */ -#endif /* LACKS_UNISTD_H */ - -/* Declarations for locking */ -#if USE_LOCKS -#ifndef WIN32 -#if defined (__SVR4) && defined (__sun) /* solaris */ -#include -#elif !defined(LACKS_SCHED_H) -#include -#endif /* solaris or LACKS_SCHED_H */ -#if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS -#include -#endif /* USE_RECURSIVE_LOCKS ... */ -#elif defined(_MSC_VER) -#ifndef _M_AMD64 -/* These are already defined on AMD64 builds */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp); -LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value); -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* _M_AMD64 */ -#pragma intrinsic (_InterlockedCompareExchange) -#pragma intrinsic (_InterlockedExchange) -#define interlockedcompareexchange _InterlockedCompareExchange -#define interlockedexchange _InterlockedExchange -#elif defined(WIN32) && defined(__GNUC__) -#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b) -#define interlockedexchange __sync_lock_test_and_set -#endif /* Win32 */ -#endif /* USE_LOCKS */ - -/* Declarations for bit scanning on win32 */ -#if defined(_MSC_VER) && _MSC_VER>=1300 -#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -unsigned char _BitScanForward(unsigned long *index, unsigned long mask); -unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#define BitScanForward _BitScanForward -#define BitScanReverse _BitScanReverse -#pragma intrinsic(_BitScanForward) -#pragma intrinsic(_BitScanReverse) -#endif /* BitScanForward */ -#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ - -#ifndef WIN32 -#ifndef malloc_getpagesize -# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ -# ifndef _SC_PAGE_SIZE -# define _SC_PAGE_SIZE _SC_PAGESIZE -# endif -# endif -# ifdef _SC_PAGE_SIZE -# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) -# else -# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) - extern size_t getpagesize(); -# define malloc_getpagesize getpagesize() -# else -# ifdef WIN32 /* use supplied emulation of getpagesize */ -# define malloc_getpagesize getpagesize() -# else -# ifndef LACKS_SYS_PARAM_H -# include -# endif -# ifdef EXEC_PAGESIZE -# define malloc_getpagesize EXEC_PAGESIZE -# else -# ifdef NBPG -# ifndef CLSIZE -# define malloc_getpagesize NBPG -# else -# define malloc_getpagesize (NBPG * CLSIZE) -# endif -# else -# ifdef NBPC -# define malloc_getpagesize NBPC -# else -# ifdef PAGESIZE -# define malloc_getpagesize PAGESIZE -# else /* just guess */ -# define malloc_getpagesize ((size_t)4096U) -# endif -# endif -# endif -# endif -# endif -# endif -# endif -#endif -#endif - -/* ------------------- size_t and alignment properties -------------------- */ - -/* The byte and bit size of a size_t */ -#define SIZE_T_SIZE (sizeof(size_t)) -#define SIZE_T_BITSIZE (sizeof(size_t) << 3) - -/* Some constants coerced to size_t */ -/* Annoying but necessary to avoid errors on some platforms */ -#define SIZE_T_ZERO ((size_t)0) -#define SIZE_T_ONE ((size_t)1) -#define SIZE_T_TWO ((size_t)2) -#define SIZE_T_FOUR ((size_t)4) -#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) -#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) -#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) -#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) - -/* The bit mask value corresponding to MALLOC_ALIGNMENT */ -#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) - -/* True if address a has acceptable alignment */ -#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) - -/* the number of bytes to offset an address to align it */ -#define align_offset(A)\ - ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ - ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) - -/* -------------------------- MMAP preliminaries ------------------------- */ - -/* - If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and - checks to fail so compiler optimizer can delete code rather than - using so many "#if"s. -*/ - - -/* MORECORE and MMAP must return MFAIL on failure */ -#define MFAIL ((void*)(MAX_SIZE_T)) -#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ - -#if HAVE_MMAP - -#ifndef WIN32 -#define MUNMAP_DEFAULT(a, s) munmap((a), (s)) -#define MMAP_PROT (PROT_READ|PROT_WRITE) -#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -#define MAP_ANONYMOUS MAP_ANON -#endif /* MAP_ANON */ -#ifdef MAP_ANONYMOUS -#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) -#define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) -#else /* MAP_ANONYMOUS */ -/* - Nearly all versions of mmap support MAP_ANONYMOUS, so the following - is unlikely to be needed, but is supplied just in case. -*/ -#define MMAP_FLAGS (MAP_PRIVATE) -static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ -#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \ - (dev_zero_fd = open("/dev/zero", O_RDWR), \ - mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ - mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) -#endif /* MAP_ANONYMOUS */ - -#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) - -#else /* WIN32 */ - -/* Win32 MMAP via VirtualAlloc */ -static FORCEINLINE void* win32mmap(size_t size) { - void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - return (ptr != 0)? ptr: MFAIL; -} - -/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ -static FORCEINLINE void* win32direct_mmap(size_t size) { - void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, - PAGE_READWRITE); - return (ptr != 0)? ptr: MFAIL; -} - -/* This function supports releasing coalesed segments */ -static FORCEINLINE int win32munmap(void* ptr, size_t size) { - MEMORY_BASIC_INFORMATION minfo; - char* cptr = (char*)ptr; - while (size) { - if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) - return -1; - if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || - minfo.State != MEM_COMMIT || minfo.RegionSize > size) - return -1; - if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) - return -1; - cptr += minfo.RegionSize; - size -= minfo.RegionSize; - } - return 0; -} - -#define MMAP_DEFAULT(s) win32mmap(s) -#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) -#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) -#endif /* WIN32 */ -#endif /* HAVE_MMAP */ - -#if HAVE_MREMAP -#ifndef WIN32 -#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) -#endif /* WIN32 */ -#endif /* HAVE_MREMAP */ - -/** - * Define CALL_MORECORE - */ -#if HAVE_MORECORE - #ifdef MORECORE - #define CALL_MORECORE(S) MORECORE(S) - #else /* MORECORE */ - #define CALL_MORECORE(S) MORECORE_DEFAULT(S) - #endif /* MORECORE */ -#else /* HAVE_MORECORE */ - #define CALL_MORECORE(S) MFAIL -#endif /* HAVE_MORECORE */ - -/** - * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP - */ -#if HAVE_MMAP - #define USE_MMAP_BIT (SIZE_T_ONE) - - #ifdef MMAP - #define CALL_MMAP(s) MMAP(s) - #else /* MMAP */ - #define CALL_MMAP(s) MMAP_DEFAULT(s) - #endif /* MMAP */ - #ifdef MUNMAP - #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) - #else /* MUNMAP */ - #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) - #endif /* MUNMAP */ - #ifdef DIRECT_MMAP - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) - #else /* DIRECT_MMAP */ - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) - #endif /* DIRECT_MMAP */ -#else /* HAVE_MMAP */ - #define USE_MMAP_BIT (SIZE_T_ZERO) - - #define MMAP(s) MFAIL - #define MUNMAP(a, s) (-1) - #define DIRECT_MMAP(s) MFAIL - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) - #define CALL_MMAP(s) MMAP(s) - #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) -#endif /* HAVE_MMAP */ - -/** - * Define CALL_MREMAP - */ -#if HAVE_MMAP && HAVE_MREMAP - #ifdef MREMAP - #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) - #else /* MREMAP */ - #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) - #endif /* MREMAP */ -#else /* HAVE_MMAP && HAVE_MREMAP */ - #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL -#endif /* HAVE_MMAP && HAVE_MREMAP */ - -/* mstate bit set if continguous morecore disabled or failed */ -#define USE_NONCONTIGUOUS_BIT (4U) - -/* segment bit set in create_mspace_with_base */ -#define EXTERN_BIT (8U) - - -/* --------------------------- Lock preliminaries ------------------------ */ - -/* - When locks are defined, there is one global lock, plus - one per-mspace lock. - - The global lock_ensures that mparams.magic and other unique - mparams values are initialized only once. It also protects - sequences of calls to MORECORE. In many cases sys_alloc requires - two calls, that should not be interleaved with calls by other - threads. This does not protect against direct calls to MORECORE - by other threads not using this lock, so there is still code to - cope the best we can on interference. - - Per-mspace locks surround calls to malloc, free, etc. - By default, locks are simple non-reentrant mutexes. - - Because lock-protected regions generally have bounded times, it is - OK to use the supplied simple spinlocks. Spinlocks are likely to - improve performance for lightly contended applications, but worsen - performance under heavy contention. - - If USE_LOCKS is > 1, the definitions of lock routines here are - bypassed, in which case you will need to define the type MLOCK_T, - and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK - and TRY_LOCK. You must also declare a - static MLOCK_T malloc_global_mutex = { initialization values };. - -*/ - -#if !USE_LOCKS -#define USE_LOCK_BIT (0U) -#define INITIAL_LOCK(l) (0) -#define DESTROY_LOCK(l) (0) -#define ACQUIRE_MALLOC_GLOBAL_LOCK() -#define RELEASE_MALLOC_GLOBAL_LOCK() - -#else -#if USE_LOCKS > 1 -/* ----------------------- User-defined locks ------------------------ */ -/* Define your own lock implementation here */ -/* #define INITIAL_LOCK(lk) ... */ -/* #define DESTROY_LOCK(lk) ... */ -/* #define ACQUIRE_LOCK(lk) ... */ -/* #define RELEASE_LOCK(lk) ... */ -/* #define TRY_LOCK(lk) ... */ -/* static MLOCK_T malloc_global_mutex = ... */ - -#elif USE_SPIN_LOCKS - -/* First, define CAS_LOCK and CLEAR_LOCK on ints */ -/* Note CAS_LOCK defined to return 0 on success */ - -#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) -#define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1) -#define CLEAR_LOCK(sl) __sync_lock_release(sl) - -#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) -/* Custom spin locks for older gcc on x86 */ -static FORCEINLINE int x86_cas_lock(int *sl) { - int ret; - int val = 1; - int cmp = 0; - __asm__ __volatile__ ("lock; cmpxchgl %1, %2" - : "=a" (ret) - : "r" (val), "m" (*(sl)), "0"(cmp) - : "memory", "cc"); - return ret; -} - -static FORCEINLINE void x86_clear_lock(int* sl) { - assert(*sl != 0); - int prev = 0; - int ret; - __asm__ __volatile__ ("lock; xchgl %0, %1" - : "=r" (ret) - : "m" (*(sl)), "0"(prev) - : "memory"); -} - -#define CAS_LOCK(sl) x86_cas_lock(sl) -#define CLEAR_LOCK(sl) x86_clear_lock(sl) - -#else /* Win32 MSC */ -#define CAS_LOCK(sl) interlockedexchange(sl, 1) -#define CLEAR_LOCK(sl) interlockedexchange (sl, 0) - -#endif /* ... gcc spins locks ... */ - -/* How to yield for a spin lock */ -#define SPINS_PER_YIELD 63 -#if defined(_MSC_VER) -#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ -#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE) -#elif defined (__SVR4) && defined (__sun) /* solaris */ -#define SPIN_LOCK_YIELD thr_yield(); -#elif !defined(LACKS_SCHED_H) -#define SPIN_LOCK_YIELD sched_yield(); -#else -#define SPIN_LOCK_YIELD -#endif /* ... yield ... */ - -#if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0 -/* Plain spin locks use single word (embedded in malloc_states) */ -static int spin_acquire_lock(int *sl) { - int spins = 0; - while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) { - if ((++spins & SPINS_PER_YIELD) == 0) { - SPIN_LOCK_YIELD; - } - } - return 0; -} - -#define MLOCK_T int -#define TRY_LOCK(sl) !CAS_LOCK(sl) -#define RELEASE_LOCK(sl) CLEAR_LOCK(sl) -#define ACQUIRE_LOCK(sl) (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0) -#define INITIAL_LOCK(sl) (*sl = 0) -#define DESTROY_LOCK(sl) (0) -static MLOCK_T malloc_global_mutex = 0; - -#else /* USE_RECURSIVE_LOCKS */ -/* types for lock owners */ -#ifdef WIN32 -#define THREAD_ID_T DWORD -#define CURRENT_THREAD GetCurrentThreadId() -#define EQ_OWNER(X,Y) ((X) == (Y)) -#else -/* - Note: the following assume that pthread_t is a type that can be - initialized to (casted) zero. If this is not the case, you will need to - somehow redefine these or not use spin locks. -*/ -#define THREAD_ID_T pthread_t -#define CURRENT_THREAD pthread_self() -#define EQ_OWNER(X,Y) pthread_equal(X, Y) -#endif - -struct malloc_recursive_lock { - int sl; - unsigned int c; - THREAD_ID_T threadid; -}; - -#define MLOCK_T struct malloc_recursive_lock -static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0}; - -static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) { - assert(lk->sl != 0); - if (--lk->c == 0) { - CLEAR_LOCK(&lk->sl); - } -} - -static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) { - THREAD_ID_T mythreadid = CURRENT_THREAD; - int spins = 0; - for (;;) { - if (*((volatile int *)(&lk->sl)) == 0) { - if (!CAS_LOCK(&lk->sl)) { - lk->threadid = mythreadid; - lk->c = 1; - return 0; - } - } - else if (EQ_OWNER(lk->threadid, mythreadid)) { - ++lk->c; - return 0; - } - if ((++spins & SPINS_PER_YIELD) == 0) { - SPIN_LOCK_YIELD; - } - } -} - -static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) { - THREAD_ID_T mythreadid = CURRENT_THREAD; - if (*((volatile int *)(&lk->sl)) == 0) { - if (!CAS_LOCK(&lk->sl)) { - lk->threadid = mythreadid; - lk->c = 1; - return 1; - } - } - else if (EQ_OWNER(lk->threadid, mythreadid)) { - ++lk->c; - return 1; - } - return 0; -} - -#define RELEASE_LOCK(lk) recursive_release_lock(lk) -#define TRY_LOCK(lk) recursive_try_lock(lk) -#define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk) -#define INITIAL_LOCK(lk) ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0) -#define DESTROY_LOCK(lk) (0) -#endif /* USE_RECURSIVE_LOCKS */ - -#elif defined(WIN32) /* Win32 critical sections */ -#define MLOCK_T CRITICAL_SECTION -#define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0) -#define RELEASE_LOCK(lk) LeaveCriticalSection(lk) -#define TRY_LOCK(lk) TryEnterCriticalSection(lk) -#define INITIAL_LOCK(lk) (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000)) -#define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0) -#define NEED_GLOBAL_LOCK_INIT - -static MLOCK_T malloc_global_mutex; -static volatile long malloc_global_mutex_status; - -/* Use spin loop to initialize global lock */ -static void init_malloc_global_mutex() { - for (;;) { - long stat = malloc_global_mutex_status; - if (stat > 0) - return; - /* transition to < 0 while initializing, then to > 0) */ - if (stat == 0 && - interlockedcompareexchange(&malloc_global_mutex_status, -1, 0) == 0) { - InitializeCriticalSection(&malloc_global_mutex); - interlockedexchange(&malloc_global_mutex_status,1); - return; - } - SleepEx(0, FALSE); - } -} - -#else /* pthreads-based locks */ -#define MLOCK_T pthread_mutex_t -#define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk) -#define RELEASE_LOCK(lk) pthread_mutex_unlock(lk) -#define TRY_LOCK(lk) (!pthread_mutex_trylock(lk)) -#define INITIAL_LOCK(lk) pthread_init_lock(lk) -#define DESTROY_LOCK(lk) pthread_mutex_destroy(lk) - -#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE) -/* Cope with old-style linux recursive lock initialization by adding */ -/* skipped internal declaration from pthread.h */ -extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr, - int __kind)); -#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP -#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y) -#endif /* USE_RECURSIVE_LOCKS ... */ - -static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER; - -static int pthread_init_lock (MLOCK_T *lk) { - pthread_mutexattr_t attr; - if (pthread_mutexattr_init(&attr)) return 1; -#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1; -#endif - if (pthread_mutex_init(lk, &attr)) return 1; - if (pthread_mutexattr_destroy(&attr)) return 1; - return 0; -} - -#endif /* ... lock types ... */ - -/* Common code for all lock types */ -#define USE_LOCK_BIT (2U) - -#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK -#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); -#endif - -#ifndef RELEASE_MALLOC_GLOBAL_LOCK -#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); -#endif - -#endif /* USE_LOCKS */ - -/* ----------------------- Chunk representations ------------------------ */ - -/* - (The following includes lightly edited explanations by Colin Plumb.) - - The malloc_chunk declaration below is misleading (but accurate and - necessary). It declares a "view" into memory allowing access to - necessary fields at known offsets from a given base. - - Chunks of memory are maintained using a `boundary tag' method as - originally described by Knuth. (See the paper by Paul Wilson - ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such - techniques.) Sizes of free chunks are stored both in the front of - each chunk and at the end. This makes consolidating fragmented - chunks into bigger chunks fast. The head fields also hold bits - representing whether chunks are free or in use. - - Here are some pictures to make it clearer. They are "exploded" to - show that the state of a chunk can be thought of as extending from - the high 31 bits of the head field of its header through the - prev_foot and PINUSE_BIT bit of the following chunk header. - - A chunk that's in use looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk (if P = 0) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 1| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - +- -+ - | | - +- -+ - | : - +- size - sizeof(size_t) available payload bytes -+ - : | - chunk-> +- -+ - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| - | Size of next chunk (may or may not be in use) | +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - And if it's free, it looks like this: - - chunk-> +- -+ - | User payload (must be in use, or we would have merged!) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 0| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Next pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prev pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- size - sizeof(struct chunk) unused bytes -+ - : | - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| - | Size of next chunk (must be in use, or we would have merged)| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- User payload -+ - : | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |0| - +-+ - Note that since we always merge adjacent free chunks, the chunks - adjacent to a free chunk must be in use. - - Given a pointer to a chunk (which can be derived trivially from the - payload pointer) we can, in O(1) time, find out whether the adjacent - chunks are free, and if so, unlink them from the lists that they - are on and merge them with the current chunk. - - Chunks always begin on even word boundaries, so the mem portion - (which is returned to the user) is also on an even word boundary, and - thus at least double-word aligned. - - The P (PINUSE_BIT) bit, stored in the unused low-order bit of the - chunk size (which is always a multiple of two words), is an in-use - bit for the *previous* chunk. If that bit is *clear*, then the - word before the current chunk size contains the previous chunk - size, and can be used to find the front of the previous chunk. - The very first chunk allocated always has this bit set, preventing - access to non-existent (or non-owned) memory. If pinuse is set for - any given chunk, then you CANNOT determine the size of the - previous chunk, and might even get a memory addressing fault when - trying to do so. - - The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of - the chunk size redundantly records whether the current chunk is - inuse (unless the chunk is mmapped). This redundancy enables usage - checks within free and realloc, and reduces indirection when freeing - and consolidating chunks. - - Each freshly allocated chunk must have both cinuse and pinuse set. - That is, each allocated chunk borders either a previously allocated - and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the `lowest' part of any - found chunk. Further, no free chunk physically borders another one, - so each free chunk is known to be preceded and followed by either - inuse chunks or the ends of memory. - - Note that the `foot' of the current chunk is actually represented - as the prev_foot of the NEXT chunk. This makes it easier to - deal with alignments etc but can be very confusing when trying - to extend or adapt this code. - - The exceptions to all this are - - 1. The special chunk `top' is the top-most available chunk (i.e., - the one bordering the end of available memory). It is treated - specially. Top is never included in any bin, is used only if - no other chunk is available, and is released back to the - system if it is very large (see M_TRIM_THRESHOLD). In effect, - the top chunk is treated as larger (and thus less well - fitting) than any other available chunk. The top chunk - doesn't update its trailing size field since there is no next - contiguous chunk that would have to index off it. However, - space is still allocated for it (TOP_FOOT_SIZE) to enable - separation or merging when space is extended. - - 3. Chunks allocated via mmap, have both cinuse and pinuse bits - cleared in their head fields. Because they are allocated - one-by-one, each must carry its own prev_foot field, which is - also used to hold the offset this chunk has within its mmapped - region, which is needed to preserve alignment. Each mmapped - chunk is trailed by the first two fields of a fake next-chunk - for sake of usage checks. - -*/ - -struct malloc_chunk { - size_t prev_foot; /* Size of previous chunk (if free). */ - size_t head; /* Size and inuse bits. */ - struct malloc_chunk* fd; /* double links -- used only if free. */ - struct malloc_chunk* bk; -}; - -typedef struct malloc_chunk mchunk; -typedef struct malloc_chunk* mchunkptr; -typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ -typedef unsigned int bindex_t; /* Described below */ -typedef unsigned int binmap_t; /* Described below */ -typedef unsigned int flag_t; /* The type of various bit flag sets */ - -/* ------------------- Chunks sizes and alignments ----------------------- */ - -#define MCHUNK_SIZE (sizeof(mchunk)) - -#if FOOTERS -#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -#else /* FOOTERS */ -#define CHUNK_OVERHEAD (SIZE_T_SIZE) -#endif /* FOOTERS */ - -/* MMapped chunks need a second word of overhead ... */ -#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -/* ... and additional padding for fake next-chunk at foot */ -#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) - -/* The smallest size we can malloc is an aligned minimal chunk */ -#define MIN_CHUNK_SIZE\ - ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* conversion from malloc headers to user pointers, and back */ -#define chunk2mem(p) ((void*)((uintptr_t)(p) + TWO_SIZE_T_SIZES)) -#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) -/* chunk associated with aligned address A */ -#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) - -/* Bounds on request (not chunk) sizes. */ -#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) -#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) - -/* pad request bytes into a usable size */ -#define pad_request(req) \ - (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* pad request, checking for minimum (but not maximum) */ -#define request2size(req) \ - (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) - - -/* ------------------ Operations on head and foot fields ----------------- */ - -/* - The head field of a chunk is or'ed with PINUSE_BIT when previous - adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in - use, unless mmapped, in which case both bits are cleared. - - FLAG4_BIT is not used by this malloc, but might be useful in extensions. -*/ - -#define PINUSE_BIT (SIZE_T_ONE) -#define CINUSE_BIT (SIZE_T_TWO) -#define FLAG4_BIT (SIZE_T_FOUR) -#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) -#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) - -/* Head value for fenceposts */ -#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) - -/* extraction of fields from head words */ -#define cinuse(p) ((p)->head & CINUSE_BIT) -#define pinuse(p) ((p)->head & PINUSE_BIT) -#define flag4inuse(p) ((p)->head & FLAG4_BIT) -#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) -#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) - -#define chunksize(p) ((p)->head & ~(FLAG_BITS)) - -#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) -#define set_flag4(p) ((p)->head |= FLAG4_BIT) -#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT) - -/* Treat space at ptr +/- offset as a chunk */ -#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) -#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) - -/* Ptr to next or previous physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) -#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) - -/* extract next chunk's pinuse bit */ -#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) - -/* Get/set size at footer */ -#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) -#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) - -/* Set size, pinuse bit, and foot */ -#define set_size_and_pinuse_of_free_chunk(p, s)\ - ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) - -/* Set size, pinuse bit, foot, and clear next pinuse */ -#define set_free_with_pinuse(p, s, n)\ - (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) - -/* Get the internal overhead associated with chunk p */ -#define overhead_for(p)\ - (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) - -/* Return true if malloced space is not necessarily cleared */ -#if MMAP_CLEARS -#define calloc_must_clear(p) (!is_mmapped(p)) -#else /* MMAP_CLEARS */ -#define calloc_must_clear(p) (1) -#endif /* MMAP_CLEARS */ - -/* ---------------------- Overlaid data structures ----------------------- */ - -/* - When chunks are not in use, they are treated as nodes of either - lists or trees. - - "Small" chunks are stored in circular doubly-linked lists, and look - like this: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space (may be 0 bytes long) . - . . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Larger chunks are kept in a form of bitwise digital trees (aka - tries) keyed on chunksizes. Because malloc_tree_chunks are only for - free chunks greater than 256 bytes, their size doesn't impose any - constraints on user chunk sizes. Each node looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to left child (child[0]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to right child (child[1]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to parent | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | bin index of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Each tree holding treenodes is a tree of unique chunk sizes. Chunks - of the same size are arranged in a circularly-linked list, with only - the oldest chunk (the next to be used, in our FIFO ordering) - actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node - is inserted, it is linked off the existing node using pointers that - work in the same way as fd/bk pointers of small chunks. - - Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each - tree level, with the chunks in the smaller half of the range (0x100 - <= x < 0x140 for the top nose) in the left subtree and the larger - half (0x140 <= x < 0x180) in the right subtree. This is, of course, - done by inspecting individual bits. - - Using these rules, each node's left subtree contains all smaller - sizes than its right subtree. However, the node at the root of each - subtree has no particular ordering relationship to either. (The - dividing line between the subtree sizes is based on trie relation.) - If we remove the last chunk of a given size from the interior of the - tree, we need to replace it with a leaf node. The tree ordering - rules permit a node to be replaced by any leaf below it. - - The smallest chunk in a tree (a common operation in a best-fit - allocator) can be found by walking a path to the leftmost leaf in - the tree. Unlike a usual binary tree, where we follow left child - pointers until we reach a null, here we follow the right child - pointer any time the left one is null, until we reach a leaf with - both child pointers null. The smallest chunk in the tree will be - somewhere along that path. - - The worst case number of steps to add, find, or remove a node is - bounded by the number of bits differentiating chunks within - bins. Under current bin calculations, this ranges from 6 up to 21 - (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case - is of course much better. -*/ - -struct malloc_tree_chunk { - /* The first four fields must be compatible with malloc_chunk */ - size_t prev_foot; - size_t head; - struct malloc_tree_chunk* fd; - struct malloc_tree_chunk* bk; - - struct malloc_tree_chunk* child[2]; - struct malloc_tree_chunk* parent; - bindex_t index; -}; - -typedef struct malloc_tree_chunk tchunk; -typedef struct malloc_tree_chunk* tchunkptr; -typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ - -/* A little helper macro for trees */ -#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) - -/* ----------------------------- Segments -------------------------------- */ - -/* - Each malloc space may include non-contiguous segments, held in a - list headed by an embedded malloc_segment record representing the - top-most space. Segments also include flags holding properties of - the space. Large chunks that are directly allocated by mmap are not - included in this list. They are instead independently created and - destroyed without otherwise keeping track of them. - - Segment management mainly comes into play for spaces allocated by - MMAP. Any call to MMAP might or might not return memory that is - adjacent to an existing segment. MORECORE normally contiguously - extends the current space, so this space is almost always adjacent, - which is simpler and faster to deal with. (This is why MORECORE is - used preferentially to MMAP when both are available -- see - sys_alloc.) When allocating using MMAP, we don't use any of the - hinting mechanisms (inconsistently) supported in various - implementations of unix mmap, or distinguish reserving from - committing memory. Instead, we just ask for space, and exploit - contiguity when we get it. It is probably possible to do - better than this on some systems, but no general scheme seems - to be significantly better. - - Management entails a simpler variant of the consolidation scheme - used for chunks to reduce fragmentation -- new adjacent memory is - normally prepended or appended to an existing segment. However, - there are limitations compared to chunk consolidation that mostly - reflect the fact that segment processing is relatively infrequent - (occurring only when getting memory from system) and that we - don't expect to have huge numbers of segments: - - * Segments are not indexed, so traversal requires linear scans. (It - would be possible to index these, but is not worth the extra - overhead and complexity for most programs on most platforms.) - * New segments are only appended to old ones when holding top-most - memory; if they cannot be prepended to others, they are held in - different segments. - - Except for the top-most segment of an mstate, each segment record - is kept at the tail of its segment. Segments are added by pushing - segment records onto the list headed by &mstate.seg for the - containing mstate. - - Segment flags control allocation/merge/deallocation policies: - * If EXTERN_BIT set, then we did not allocate this segment, - and so should not try to deallocate or merge with others. - (This currently holds only for the initial segment passed - into create_mspace_with_base.) - * If USE_MMAP_BIT set, the segment may be merged with - other surrounding mmapped segments and trimmed/de-allocated - using munmap. - * If neither bit is set, then the segment was obtained using - MORECORE so can be merged with surrounding MORECORE'd segments - and deallocated/trimmed using MORECORE with negative arguments. -*/ - -struct malloc_segment { - char* base; /* base address */ - size_t size; /* allocated size */ - struct malloc_segment* next; /* ptr to next segment */ - flag_t sflags; /* mmap and extern flag */ -}; - -#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) -#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) - -typedef struct malloc_segment msegment; -typedef struct malloc_segment* msegmentptr; - -/* ---------------------------- malloc_state ----------------------------- */ - -/* - A malloc_state holds all of the bookkeeping for a space. - The main fields are: - - Top - The topmost chunk of the currently active segment. Its size is - cached in topsize. The actual size of topmost space is - topsize+TOP_FOOT_SIZE, which includes space reserved for adding - fenceposts and segment records if necessary when getting more - space from the system. The size at which to autotrim top is - cached from mparams in trim_check, except that it is disabled if - an autotrim fails. - - Designated victim (dv) - This is the preferred chunk for servicing small requests that - don't have exact fits. It is normally the chunk split off most - recently to service another small request. Its size is cached in - dvsize. The link fields of this chunk are not maintained since it - is not kept in a bin. - - SmallBins - An array of bin headers for free chunks. These bins hold chunks - with sizes less than MIN_LARGE_SIZE bytes. Each bin contains - chunks of all the same size, spaced 8 bytes apart. To simplify - use in double-linked lists, each bin header acts as a malloc_chunk - pointing to the real first node, if it exists (else pointing to - itself). This avoids special-casing for headers. But to avoid - waste, we allocate only the fd/bk pointers of bins, and then use - repositioning tricks to treat these as the fields of a chunk. - - TreeBins - Treebins are pointers to the roots of trees holding a range of - sizes. There are 2 equally spaced treebins for each power of two - from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything - larger. - - Bin maps - There is one bit map for small bins ("smallmap") and one for - treebins ("treemap). Each bin sets its bit when non-empty, and - clears the bit when empty. Bit operations are then used to avoid - bin-by-bin searching -- nearly all "search" is done without ever - looking at bins that won't be selected. The bit maps - conservatively use 32 bits per map word, even if on 64bit system. - For a good description of some of the bit-based techniques used - here, see Henry S. Warren Jr's book "Hacker's Delight" (and - supplement at http://hackersdelight.org/). Many of these are - intended to reduce the branchiness of paths through malloc etc, as - well as to reduce the number of memory locations read or written. - - Segments - A list of segments headed by an embedded malloc_segment record - representing the initial space. - - Address check support - The least_addr field is the least address ever obtained from - MORECORE or MMAP. Attempted frees and reallocs of any address less - than this are trapped (unless INSECURE is defined). - - Magic tag - A cross-check field that should always hold same value as mparams.magic. - - Max allowed footprint - The maximum allowed bytes to allocate from system (zero means no limit) - - Flags - Bits recording whether to use MMAP, locks, or contiguous MORECORE - - Statistics - Each space keeps track of current and maximum system memory - obtained via MORECORE or MMAP. - - Trim support - Fields holding the amount of unused topmost memory that should trigger - trimming, and a counter to force periodic scanning to release unused - non-topmost segments. - - Locking - If USE_LOCKS is defined, the "mutex" lock is acquired and released - around every public call using this mspace. - - Extension support - A void* pointer and a size_t field that can be used to help implement - extensions to this malloc. -*/ - -/* Bin types, widths and sizes */ -#define NSMALLBINS (32U) -#define NTREEBINS (32U) -#define SMALLBIN_SHIFT (3U) -#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) -#define TREEBIN_SHIFT (8U) -#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) -#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) -#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) - -struct malloc_state { - binmap_t smallmap; - binmap_t treemap; - size_t dvsize; - size_t topsize; - char* least_addr; - mchunkptr dv; - mchunkptr top; - size_t trim_check; - size_t release_checks; - size_t magic; - mchunkptr smallbins[(NSMALLBINS+1)*2]; - tbinptr treebins[NTREEBINS]; - size_t footprint; - size_t max_footprint; - size_t footprint_limit; /* zero means no limit */ - flag_t mflags; -#if USE_LOCKS - MLOCK_T mutex; /* locate lock among fields that rarely change */ -#endif /* USE_LOCKS */ - msegment seg; - void* extp; /* Unused but available for extensions */ - size_t exts; -}; - -typedef struct malloc_state* mstate; - -/* ------------- Global malloc_state and malloc_params ------------------- */ - -/* - malloc_params holds global properties, including those that can be - dynamically set using mallopt. There is a single instance, mparams, - initialized in init_mparams. Note that the non-zeroness of "magic" - also serves as an initialization flag. -*/ - -struct malloc_params { - size_t magic; - size_t page_size; - size_t granularity; - size_t mmap_threshold; - size_t trim_threshold; - flag_t default_mflags; -}; - -static struct malloc_params mparams; - -/* Ensure mparams initialized */ -#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams()) - -#if !ONLY_MSPACES - -/* The global malloc_state used for all non-"mspace" calls */ -static struct malloc_state _gm_; -#define gm (&_gm_) -#define is_global(M) ((M) == &_gm_) - -#endif /* !ONLY_MSPACES */ - -#define is_initialized(M) ((M)->top != 0) - -/* -------------------------- system alloc setup ------------------------- */ - -/* Operations on mflags */ - -#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) -#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) -#if USE_LOCKS -#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) -#else -#define disable_lock(M) -#endif - -#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) -#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) -#if HAVE_MMAP -#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) -#else -#define disable_mmap(M) -#endif - -#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) -#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) - -#define set_lock(M,L)\ - ((M)->mflags = (L)?\ - ((M)->mflags | USE_LOCK_BIT) :\ - ((M)->mflags & ~USE_LOCK_BIT)) - -/* page-align a size */ -#define page_align(S)\ - (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) - -/* granularity-align a size */ -#define granularity_align(S)\ - (((S) + (mparams.granularity - SIZE_T_ONE))\ - & ~(mparams.granularity - SIZE_T_ONE)) - - -/* For mmap, use granularity alignment on windows, else page-align */ -#ifdef WIN32 -#define mmap_align(S) granularity_align(S) -#else -#define mmap_align(S) page_align(S) -#endif - -/* For sys_alloc, enough padding to ensure can malloc request on success */ -#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) - -#define is_page_aligned(S)\ - (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) -#define is_granularity_aligned(S)\ - (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) - -/* True if segment S holds address A */ -#define segment_holds(S, A)\ - ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) - -/* Return segment holding given address */ -static msegmentptr segment_holding(mstate m, char* addr) { - msegmentptr sp = &m->seg; - for (;;) { - if (addr >= sp->base && addr < sp->base + sp->size) - return sp; - if ((sp = sp->next) == 0) - return 0; - } -} - -/* Return true if segment contains a segment link */ -static int has_segment_link(mstate m, msegmentptr ss) { - msegmentptr sp = &m->seg; - for (;;) { - if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) - return 1; - if ((sp = sp->next) == 0) - return 0; - } -} - -#ifndef MORECORE_CANNOT_TRIM -#define should_trim(M,s) ((s) > (M)->trim_check) -#else /* MORECORE_CANNOT_TRIM */ -#define should_trim(M,s) (0) -#endif /* MORECORE_CANNOT_TRIM */ - -/* - TOP_FOOT_SIZE is padding at the end of a segment, including space - that may be needed to place segment records and fenceposts when new - noncontiguous segments are added. -*/ -#define TOP_FOOT_SIZE\ - (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) - - -/* ------------------------------- Hooks -------------------------------- */ - -/* - PREACTION should be defined to return 0 on success, and nonzero on - failure. If you are not using locking, you can redefine these to do - anything you like. -*/ - -#if USE_LOCKS -#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) -#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } -#else /* USE_LOCKS */ - -#ifndef PREACTION -#define PREACTION(M) (0) -#endif /* PREACTION */ - -#ifndef POSTACTION -#define POSTACTION(M) -#endif /* POSTACTION */ - -#endif /* USE_LOCKS */ - -/* - CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. - USAGE_ERROR_ACTION is triggered on detected bad frees and - reallocs. The argument p is an address that might have triggered the - fault. It is ignored by the two predefined actions, but might be - useful in custom actions that try to help diagnose errors. -*/ - -#if PROCEED_ON_ERROR - -/* A count of the number of corruption errors causing resets */ -int malloc_corruption_error_count; - -/* default corruption action */ -static void reset_on_error(mstate m); - -#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) -#define USAGE_ERROR_ACTION(m, p) - -#else /* PROCEED_ON_ERROR */ - -#ifndef CORRUPTION_ERROR_ACTION -#define CORRUPTION_ERROR_ACTION(m) ABORT -#endif /* CORRUPTION_ERROR_ACTION */ - -#ifndef USAGE_ERROR_ACTION -#define USAGE_ERROR_ACTION(m,p) ABORT -#endif /* USAGE_ERROR_ACTION */ - -#endif /* PROCEED_ON_ERROR */ - - -/* -------------------------- Debugging setup ---------------------------- */ - -#if ! DEBUG - -#define check_free_chunk(M,P) -#define check_inuse_chunk(M,P) -#define check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) -#define check_malloc_state(M) -#define check_top_chunk(M,P) - -#else /* DEBUG */ -#define check_free_chunk(M,P) do_check_free_chunk(M,P) -#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) -#define check_top_chunk(M,P) do_check_top_chunk(M,P) -#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) -#define check_malloc_state(M) do_check_malloc_state(M) - -static void do_check_any_chunk(mstate m, mchunkptr p); -static void do_check_top_chunk(mstate m, mchunkptr p); -static void do_check_mmapped_chunk(mstate m, mchunkptr p); -static void do_check_inuse_chunk(mstate m, mchunkptr p); -static void do_check_free_chunk(mstate m, mchunkptr p); -static void do_check_malloced_chunk(mstate m, void* mem, size_t s); -static void do_check_tree(mstate m, tchunkptr t); -static void do_check_treebin(mstate m, bindex_t i); -static void do_check_smallbin(mstate m, bindex_t i); -static void do_check_malloc_state(mstate m); -static int bin_find(mstate m, mchunkptr x); -static size_t traverse_and_check(mstate m); -#endif /* DEBUG */ - -/* ---------------------------- Indexing Bins ---------------------------- */ - -#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) -#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) -#define small_index2size(i) ((i) << SMALLBIN_SHIFT) -#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) - -/* addressing by index. See above about smallbin repositioning */ -#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) -#define treebin_at(M,i) (&((M)->treebins[i])) - -/* assign tree index for size S to variable I. Use x86 asm if possible */ -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -#define compute_tree_index(S, I)\ -{\ - unsigned int X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} - -#elif defined (__INTEL_COMPILER) -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K = _bit_scan_reverse (X); \ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} - -#elif defined(_MSC_VER) && _MSC_VER>=1300 -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K;\ - _BitScanReverse((DWORD *) &K, (DWORD) X);\ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} - -#else /* GNUC */ -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int Y = (unsigned int)X;\ - unsigned int N = ((Y - 0x100) >> 16) & 8;\ - unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ - N += K;\ - N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ - K = 14 - N + ((Y <<= K) >> 15);\ - I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ - }\ -} -#endif /* GNUC */ - -/* Bit representing maximum resolved size in a treebin at i */ -#define bit_for_tree_index(i) \ - (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) - -/* Shift placing maximum resolved bit in a treebin at i as sign bit */ -#define leftshift_for_tree_index(i) \ - ((i == NTREEBINS-1)? 0 : \ - ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) - -/* The size of the smallest chunk held in bin with index i */ -#define minsize_for_tree_index(i) \ - ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ - (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) - - -/* ------------------------ Operations on bin maps ----------------------- */ - -/* bit corresponding to given index */ -#define idx2bit(i) ((binmap_t)(1) << (i)) - -/* Mark/Clear bits with given index */ -#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) -#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) -#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) - -#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) -#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) -#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) - -/* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & -(x)) - -/* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x<<1) | -(x<<1)) - -/* mask with all bits to left of or equal to least bit of x on */ -#define same_or_left_bits(x) ((x) | -(x)) - -/* index corresponding to given bit. Use x86 asm if possible */ - -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - J = __builtin_ctz(X); \ - I = (bindex_t)J;\ -} - -#elif defined (__INTEL_COMPILER) -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - J = _bit_scan_forward (X); \ - I = (bindex_t)J;\ -} - -#elif defined(_MSC_VER) && _MSC_VER>=1300 -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - _BitScanForward((DWORD *) &J, X);\ - I = (bindex_t)J;\ -} - -#elif USE_BUILTIN_FFS -#define compute_bit2idx(X, I) I = ffs(X)-1 - -#else -#define compute_bit2idx(X, I)\ -{\ - unsigned int Y = X - 1;\ - unsigned int K = Y >> (16-4) & 16;\ - unsigned int N = K; Y >>= K;\ - N += K = Y >> (8-3) & 8; Y >>= K;\ - N += K = Y >> (4-2) & 4; Y >>= K;\ - N += K = Y >> (2-1) & 2; Y >>= K;\ - N += K = Y >> (1-0) & 1; Y >>= K;\ - I = (bindex_t)(N + Y);\ -} -#endif /* GNUC */ - - -/* ----------------------- Runtime Check Support ------------------------- */ - -/* - For security, the main invariant is that malloc/free/etc never - writes to a static address other than malloc_state, unless static - malloc_state itself has been corrupted, which cannot occur via - malloc (because of these checks). In essence this means that we - believe all pointers, sizes, maps etc held in malloc_state, but - check all of those linked or offsetted from other embedded data - structures. These checks are interspersed with main code in a way - that tends to minimize their run-time cost. - - When FOOTERS is defined, in addition to range checking, we also - verify footer fields of inuse chunks, which can be used guarantee - that the mstate controlling malloc/free is intact. This is a - streamlined version of the approach described by William Robertson - et al in "Run-time Detection of Heap-based Overflows" LISA'03 - http://www.usenix.org/events/lisa03/tech/robertson.html The footer - of an inuse chunk holds the xor of its mstate and a random seed, - that is checked upon calls to free() and realloc(). This is - (probabalistically) unguessable from outside the program, but can be - computed by any code successfully malloc'ing any chunk, so does not - itself provide protection against code that has already broken - security through some other means. Unlike Robertson et al, we - always dynamically check addresses of all offset chunks (previous, - next, etc). This turns out to be cheaper than relying on hashes. -*/ - -#if !INSECURE -/* Check if address a is at least as high as any from MORECORE or MMAP */ -#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) -/* Check if address of next chunk n is higher than base chunk p */ -#define ok_next(p, n) ((char*)(p) < (char*)(n)) -/* Check if p has inuse status */ -#define ok_inuse(p) is_inuse(p) -/* Check if p has its pinuse bit on */ -#define ok_pinuse(p) pinuse(p) - -#else /* !INSECURE */ -#define ok_address(M, a) (1) -#define ok_next(b, n) (1) -#define ok_inuse(p) (1) -#define ok_pinuse(p) (1) -#endif /* !INSECURE */ - -#if (FOOTERS && !INSECURE) -/* Check if (alleged) mstate m has expected magic field */ -#define ok_magic(M) ((M)->magic == mparams.magic) -#else /* (FOOTERS && !INSECURE) */ -#define ok_magic(M) (1) -#endif /* (FOOTERS && !INSECURE) */ - -/* In gcc, use __builtin_expect to minimize impact of checks */ -#if !INSECURE -#if defined(__GNUC__) && __GNUC__ >= 3 -#define RTCHECK(e) __builtin_expect(e, 1) -#else /* GNUC */ -#define RTCHECK(e) (e) -#endif /* GNUC */ -#else /* !INSECURE */ -#define RTCHECK(e) (1) -#endif /* !INSECURE */ - -/* macros to set up inuse chunks with or without footers */ - -#if !FOOTERS - -#define mark_inuse_foot(M,p,s) - -/* Macros for setting head/foot of non-mmapped chunks */ - -/* Set cinuse bit and pinuse bit of next chunk */ -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set size, cinuse and pinuse bit of this chunk */ -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) - -#else /* FOOTERS */ - -/* Set foot of inuse chunk to be xor of mstate and seed */ -#define mark_inuse_foot(M,p,s)\ - (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) - -#define get_mstate_for(p)\ - ((mstate)(((mchunkptr)((char*)(p) +\ - (chunksize(p))))->prev_foot ^ mparams.magic)) - -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ - mark_inuse_foot(M,p,s)) - -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ - mark_inuse_foot(M,p,s)) - -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - mark_inuse_foot(M, p, s)) - -#endif /* !FOOTERS */ - -/* ---------------------------- setting mparams -------------------------- */ - -/* Initialize mparams */ -static int init_mparams(void) { -#ifdef NEED_GLOBAL_LOCK_INIT - if (malloc_global_mutex_status <= 0) - init_malloc_global_mutex(); -#endif - - ACQUIRE_MALLOC_GLOBAL_LOCK(); - if (mparams.magic == 0) { - size_t magic; - size_t psize; - size_t gsize; - -#ifndef WIN32 - psize = malloc_getpagesize; - gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize); -#else /* WIN32 */ - { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - psize = system_info.dwPageSize; - gsize = ((DEFAULT_GRANULARITY != 0)? - DEFAULT_GRANULARITY : system_info.dwAllocationGranularity); - } -#endif /* WIN32 */ - - /* Sanity-check configuration: - size_t must be unsigned and as wide as pointer type. - ints must be at least 4 bytes. - alignment must be at least 8. - Alignment, min chunk size, and page size must all be powers of 2. - */ - if ((sizeof(size_t) != sizeof(char*)) || - (MAX_SIZE_T < MIN_CHUNK_SIZE) || - (sizeof(int) < 4) || - (MALLOC_ALIGNMENT < (size_t)8U) || - ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || - ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || - ((gsize & (gsize-SIZE_T_ONE)) != 0) || - ((psize & (psize-SIZE_T_ONE)) != 0)) - ABORT; - - mparams.granularity = gsize; - mparams.page_size = psize; - mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; - mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; -#if MORECORE_CONTIGUOUS - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; -#else /* MORECORE_CONTIGUOUS */ - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; -#endif /* MORECORE_CONTIGUOUS */ - -#if !ONLY_MSPACES - /* Set up lock for main malloc area */ - gm->mflags = mparams.default_mflags; - (void)INITIAL_LOCK(&gm->mutex); -#endif - - { -#if USE_DEV_RANDOM - int fd; - unsigned char buf[sizeof(size_t)]; - /* Try to use /dev/urandom, else fall back on using time */ - if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && - read(fd, buf, sizeof(buf)) == sizeof(buf)) { - magic = *((size_t *) buf); - close(fd); - } - else -#endif /* USE_DEV_RANDOM */ -#ifdef WIN32 - magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); -#elif defined(LACKS_TIME_H) - magic = (size_t)&magic ^ (size_t)0x55555555U; -#else - magic = (size_t)(time(0) ^ (size_t)0x55555555U); -#endif - magic |= (size_t)8U; /* ensure nonzero */ - magic &= ~(size_t)7U; /* improve chances of fault for bad values */ - /* Until memory modes commonly available, use volatile-write */ - (*(volatile size_t *)(&(mparams.magic))) = magic; - } - } - - RELEASE_MALLOC_GLOBAL_LOCK(); - return 1; -} - -/* support for mallopt */ -static int change_mparam(int param_number, int value) { - size_t val; - ensure_initialization(); - val = (value == -1)? MAX_SIZE_T : (size_t)value; - switch(param_number) { - case M_TRIM_THRESHOLD: - mparams.trim_threshold = val; - return 1; - case M_GRANULARITY: - if (val >= mparams.page_size && ((val & (val-1)) == 0)) { - mparams.granularity = val; - return 1; - } - else - return 0; - case M_MMAP_THRESHOLD: - mparams.mmap_threshold = val; - return 1; - default: - return 0; - } -} - -#if DEBUG -/* ------------------------- Debugging Support --------------------------- */ - -/* Check properties of any chunk, whether free, inuse, mmapped etc */ -static void do_check_any_chunk(mstate m, mchunkptr p) { - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); -} - -/* Check properties of top chunk */ -static void do_check_top_chunk(mstate m, mchunkptr p) { - msegmentptr sp = segment_holding(m, (char*)p); - size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ - assert(sp != 0); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(sz == m->topsize); - assert(sz > 0); - assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); - assert(pinuse(p)); - assert(!pinuse(chunk_plus_offset(p, sz))); -} - -/* Check properties of (inuse) mmapped chunks */ -static void do_check_mmapped_chunk(mstate m, mchunkptr p) { - size_t sz = chunksize(p); - size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD); - assert(is_mmapped(p)); - assert(use_mmap(m)); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(!is_small(sz)); - assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); - assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); - assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); -} - -/* Check properties of inuse chunks */ -static void do_check_inuse_chunk(mstate m, mchunkptr p) { - do_check_any_chunk(m, p); - assert(is_inuse(p)); - assert(next_pinuse(p)); - /* If not pinuse and not mmapped, previous chunk has OK offset */ - assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); - if (is_mmapped(p)) - do_check_mmapped_chunk(m, p); -} - -/* Check properties of free chunks */ -static void do_check_free_chunk(mstate m, mchunkptr p) { - size_t sz = chunksize(p); - mchunkptr next = chunk_plus_offset(p, sz); - do_check_any_chunk(m, p); - assert(!is_inuse(p)); - assert(!next_pinuse(p)); - assert (!is_mmapped(p)); - if (p != m->dv && p != m->top) { - if (sz >= MIN_CHUNK_SIZE) { - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(is_aligned(chunk2mem(p))); - assert(next->prev_foot == sz); - assert(pinuse(p)); - assert (next == m->top || is_inuse(next)); - assert(p->fd->bk == p); - assert(p->bk->fd == p); - } - else /* markers are always of size SIZE_T_SIZE */ - assert(sz == SIZE_T_SIZE); - } -} - -/* Check properties of malloced chunks at the point they are malloced */ -static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - size_t sz = p->head & ~INUSE_BITS; - do_check_inuse_chunk(m, p); - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(sz >= MIN_CHUNK_SIZE); - assert(sz >= s); - /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ - assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); - } -} - -/* Check a tree and its subtrees. */ -static void do_check_tree(mstate m, tchunkptr t) { - tchunkptr head = 0; - tchunkptr u = t; - bindex_t tindex = t->index; - size_t tsize = chunksize(t); - bindex_t idx; - compute_tree_index(tsize, idx); - assert(tindex == idx); - assert(tsize >= MIN_LARGE_SIZE); - assert(tsize >= minsize_for_tree_index(idx)); - assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); - - do { /* traverse through chain of same-sized nodes */ - do_check_any_chunk(m, ((mchunkptr)u)); - assert(u->index == tindex); - assert(chunksize(u) == tsize); - assert(!is_inuse(u)); - assert(!next_pinuse(u)); - assert(u->fd->bk == u); - assert(u->bk->fd == u); - if (u->parent == 0) { - assert(u->child[0] == 0); - assert(u->child[1] == 0); - } - else { - assert(head == 0); /* only one node on chain has parent */ - head = u; - assert(u->parent != u); - assert (u->parent->child[0] == u || - u->parent->child[1] == u || - *((tbinptr*)(u->parent)) == u); - if (u->child[0] != 0) { - assert(u->child[0]->parent == u); - assert(u->child[0] != u); - do_check_tree(m, u->child[0]); - } - if (u->child[1] != 0) { - assert(u->child[1]->parent == u); - assert(u->child[1] != u); - do_check_tree(m, u->child[1]); - } - if (u->child[0] != 0 && u->child[1] != 0) { - assert(chunksize(u->child[0]) < chunksize(u->child[1])); - } - } - u = u->fd; - } while (u != t); - assert(head != 0); -} - -/* Check all the chunks in a treebin. */ -static void do_check_treebin(mstate m, bindex_t i) { - tbinptr* tb = treebin_at(m, i); - tchunkptr t = *tb; - int empty = (m->treemap & (1U << i)) == 0; - if (t == 0) - assert(empty); - if (!empty) - do_check_tree(m, t); -} - -/* Check all the chunks in a smallbin. */ -static void do_check_smallbin(mstate m, bindex_t i) { - sbinptr b = smallbin_at(m, i); - mchunkptr p = b->bk; - unsigned int empty = (m->smallmap & (1U << i)) == 0; - if (p == b) - assert(empty); - if (!empty) { - for (; p != b; p = p->bk) { - size_t size = chunksize(p); - mchunkptr q; - /* each chunk claims to be free */ - do_check_free_chunk(m, p); - /* chunk belongs in bin */ - assert(small_index(size) == i); - assert(p->bk == b || chunksize(p->bk) == chunksize(p)); - /* chunk is followed by an inuse chunk */ - q = next_chunk(p); - if (q->head != FENCEPOST_HEAD) - do_check_inuse_chunk(m, q); - } - } -} - -/* Find x in a bin. Used in other check functions. */ -static int bin_find(mstate m, mchunkptr x) { - size_t size = chunksize(x); - if (is_small(size)) { - bindex_t sidx = small_index(size); - sbinptr b = smallbin_at(m, sidx); - if (smallmap_is_marked(m, sidx)) { - mchunkptr p = b; - do { - if (p == x) - return 1; - } while ((p = p->fd) != b); - } - } - else { - bindex_t tidx; - compute_tree_index(size, tidx); - if (treemap_is_marked(m, tidx)) { - tchunkptr t = *treebin_at(m, tidx); - size_t sizebits = size << leftshift_for_tree_index(tidx); - while (t != 0 && chunksize(t) != size) { - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - sizebits <<= 1; - } - if (t != 0) { - tchunkptr u = t; - do { - if (u == (tchunkptr)x) - return 1; - } while ((u = u->fd) != t); - } - } - } - return 0; -} - -/* Traverse each chunk and check it; return total */ -static size_t traverse_and_check(mstate m) { - size_t sum = 0; - if (is_initialized(m)) { - msegmentptr s = &m->seg; - sum += m->topsize + TOP_FOOT_SIZE; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - mchunkptr lastq = 0; - assert(pinuse(q)); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - sum += chunksize(q); - if (is_inuse(q)) { - assert(!bin_find(m, q)); - do_check_inuse_chunk(m, q); - } - else { - assert(q == m->dv || bin_find(m, q)); - assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ - do_check_free_chunk(m, q); - } - lastq = q; - q = next_chunk(q); - } - s = s->next; - } - } - return sum; -} - - -/* Check all properties of malloc_state. */ -static void do_check_malloc_state(mstate m) { - bindex_t i; - size_t total; - /* check bins */ - for (i = 0; i < NSMALLBINS; ++i) - do_check_smallbin(m, i); - for (i = 0; i < NTREEBINS; ++i) - do_check_treebin(m, i); - - if (m->dvsize != 0) { /* check dv chunk */ - do_check_any_chunk(m, m->dv); - assert(m->dvsize == chunksize(m->dv)); - assert(m->dvsize >= MIN_CHUNK_SIZE); - assert(bin_find(m, m->dv) == 0); - } - - if (m->top != 0) { /* check top chunk */ - do_check_top_chunk(m, m->top); - /*assert(m->topsize == chunksize(m->top)); redundant */ - assert(m->topsize > 0); - assert(bin_find(m, m->top) == 0); - } - - total = traverse_and_check(m); - assert(total <= m->footprint); - assert(m->footprint <= m->max_footprint); -} -#endif /* DEBUG */ - -/* ----------------------------- statistics ------------------------------ */ - -#if !NO_MALLINFO -static struct mallinfo internal_mallinfo(mstate m) { - struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - ensure_initialization(); - if (!PREACTION(m)) { - check_malloc_state(m); - if (is_initialized(m)) { - size_t nfree = SIZE_T_ONE; /* top always free */ - size_t mfree = m->topsize + TOP_FOOT_SIZE; - size_t sum = mfree; - msegmentptr s = &m->seg; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - size_t sz = chunksize(q); - sum += sz; - if (!is_inuse(q)) { - mfree += sz; - ++nfree; - } - q = next_chunk(q); - } - s = s->next; - } - - nm.arena = sum; - nm.ordblks = nfree; - nm.hblkhd = m->footprint - sum; - nm.usmblks = m->max_footprint; - nm.uordblks = m->footprint - mfree; - nm.fordblks = mfree; - nm.keepcost = m->topsize; - } - - POSTACTION(m); - } - return nm; -} -#endif /* !NO_MALLINFO */ - -#if !NO_MALLOC_STATS -static void internal_malloc_stats(mstate m) { - ensure_initialization(); - if (!PREACTION(m)) { - size_t maxfp = 0; - size_t fp = 0; - size_t used = 0; - check_malloc_state(m); - if (is_initialized(m)) { - msegmentptr s = &m->seg; - maxfp = m->max_footprint; - fp = m->footprint; - used = fp - (m->topsize + TOP_FOOT_SIZE); - - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - if (!is_inuse(q)) - used -= chunksize(q); - q = next_chunk(q); - } - s = s->next; - } - } - POSTACTION(m); /* drop lock */ - fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); - fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); - fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); - } -} -#endif /* NO_MALLOC_STATS */ - -/* ----------------------- Operations on smallbins ----------------------- */ - -/* - Various forms of linking and unlinking are defined as macros. Even - the ones for trees, which are very long but have very short typical - paths. This is ugly but reduces reliance on inlining support of - compilers. -*/ - -/* Link a free chunk into a smallbin */ -#define insert_small_chunk(M, P, S) {\ - bindex_t I = small_index(S);\ - mchunkptr B = smallbin_at(M, I);\ - mchunkptr F = B;\ - assert(S >= MIN_CHUNK_SIZE);\ - if (!smallmap_is_marked(M, I))\ - mark_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, B->fd)))\ - F = B->fd;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - B->fd = P;\ - F->bk = P;\ - P->fd = F;\ - P->bk = B;\ -} - -/* Unlink a chunk from a smallbin */ -#define unlink_small_chunk(M, P, S) {\ - mchunkptr F = P->fd;\ - mchunkptr B = P->bk;\ - bindex_t I = small_index(S);\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \ - if (B == F) {\ - clear_smallmap(M, I);\ - }\ - else if (RTCHECK(B == smallbin_at(M,I) ||\ - (ok_address(M, B) && B->fd == P))) {\ - F->bk = B;\ - B->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Unlink the first chunk from a smallbin */ -#define unlink_first_small_chunk(M, B, P, I) {\ - mchunkptr F = P->fd;\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (B == F) {\ - clear_smallmap(M, I);\ - }\ - else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\ - F->bk = B;\ - B->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Replace dv node, binning the old one */ -/* Used only when dvsize known to be small */ -#define replace_dv(M, P, S) {\ - size_t DVS = M->dvsize;\ - assert(is_small(DVS));\ - if (DVS != 0) {\ - mchunkptr DV = M->dv;\ - insert_small_chunk(M, DV, DVS);\ - }\ - M->dvsize = S;\ - M->dv = P;\ -} - -/* ------------------------- Operations on trees ------------------------- */ - -/* Insert chunk into tree */ -#define insert_large_chunk(M, X, S) {\ - tbinptr* H;\ - bindex_t I;\ - compute_tree_index(S, I);\ - H = treebin_at(M, I);\ - X->index = I;\ - X->child[0] = X->child[1] = 0;\ - if (!treemap_is_marked(M, I)) {\ - mark_treemap(M, I);\ - *H = X;\ - X->parent = (tchunkptr)H;\ - X->fd = X->bk = X;\ - }\ - else {\ - tchunkptr T = *H;\ - size_t K = S << leftshift_for_tree_index(I);\ - for (;;) {\ - if (chunksize(T) != S) {\ - tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ - K <<= 1;\ - if (*C != 0)\ - T = *C;\ - else if (RTCHECK(ok_address(M, C))) {\ - *C = X;\ - X->parent = T;\ - X->fd = X->bk = X;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - else {\ - tchunkptr F = T->fd;\ - if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ - T->fd = F->bk = X;\ - X->fd = F;\ - X->bk = T;\ - X->parent = 0;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - }\ - }\ -} - -/* - Unlink steps: - - 1. If x is a chained node, unlink it from its same-sized fd/bk links - and choose its bk node as its replacement. - 2. If x was the last node of its size, but not a leaf node, it must - be replaced with a leaf node (not merely one with an open left or - right), to make sure that lefts and rights of descendents - correspond properly to bit masks. We use the rightmost descendent - of x. We could use any other leaf, but this is easy to locate and - tends to counteract removal of leftmosts elsewhere, and so keeps - paths shorter than minimally guaranteed. This doesn't loop much - because on average a node in a tree is near the bottom. - 3. If x is the base of a chain (i.e., has parent links) relink - x's parent and children to x's replacement (or null if none). -*/ - -#define unlink_large_chunk(M, X) {\ - tchunkptr XP = X->parent;\ - tchunkptr R;\ - if (X->bk != X) {\ - tchunkptr F = X->fd;\ - R = X->bk;\ - if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\ - F->bk = R;\ - R->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else {\ - tchunkptr* RP;\ - if (((R = *(RP = &(X->child[1]))) != 0) ||\ - ((R = *(RP = &(X->child[0]))) != 0)) {\ - tchunkptr* CP;\ - while ((*(CP = &(R->child[1])) != 0) ||\ - (*(CP = &(R->child[0])) != 0)) {\ - R = *(RP = CP);\ - }\ - if (RTCHECK(ok_address(M, RP)))\ - *RP = 0;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - }\ - if (XP != 0) {\ - tbinptr* H = treebin_at(M, X->index);\ - if (X == *H) {\ - if ((*H = R) == 0) \ - clear_treemap(M, X->index);\ - }\ - else if (RTCHECK(ok_address(M, XP))) {\ - if (XP->child[0] == X) \ - XP->child[0] = R;\ - else \ - XP->child[1] = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - if (R != 0) {\ - if (RTCHECK(ok_address(M, R))) {\ - tchunkptr C0, C1;\ - R->parent = XP;\ - if ((C0 = X->child[0]) != 0) {\ - if (RTCHECK(ok_address(M, C0))) {\ - R->child[0] = C0;\ - C0->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - if ((C1 = X->child[1]) != 0) {\ - if (RTCHECK(ok_address(M, C1))) {\ - R->child[1] = C1;\ - C1->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ -} - -/* Relays to large vs small bin operations */ - -#define insert_chunk(M, P, S)\ - if (is_small(S)) insert_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } - -#define unlink_chunk(M, P, S)\ - if (is_small(S)) unlink_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } - - -/* Relays to internal calls to malloc/free from realloc, memalign etc */ - -#if ONLY_MSPACES -#define internal_malloc(m, b) mspace_malloc(m, b) -#define internal_free(m, mem) mspace_free(m,mem); -#else /* ONLY_MSPACES */ -#if MSPACES -#define internal_malloc(m, b)\ - ((m == gm)? dlmalloc(b) : mspace_malloc(m, b)) -#define internal_free(m, mem)\ - if (m == gm) dlfree(mem); else mspace_free(m,mem); -#else /* MSPACES */ -#define internal_malloc(m, b) dlmalloc(b) -#define internal_free(m, mem) dlfree(mem) -#endif /* MSPACES */ -#endif /* ONLY_MSPACES */ - -/* ----------------------- Direct-mmapping chunks ----------------------- */ - -/* - Directly mmapped chunks are set up with an offset to the start of - the mmapped region stored in the prev_foot field of the chunk. This - allows reconstruction of the required argument to MUNMAP when freed, - and also allows adjustment of the returned chunk to meet alignment - requirements (especially in memalign). -*/ - -/* Malloc using mmap */ -static void* mmap_alloc(mstate m, size_t nb) { - size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - if (m->footprint_limit != 0) { - size_t fp = m->footprint + mmsize; - if (fp <= m->footprint || fp > m->footprint_limit) - return 0; - } - if (mmsize > nb) { /* Check for wrap around 0 */ - char* mm = (char*)(CALL_DIRECT_MMAP(mmsize)); - if (mm != CMFAIL) { - size_t offset = align_offset(chunk2mem(mm)); - size_t psize = mmsize - offset - MMAP_FOOT_PAD; - mchunkptr p = (mchunkptr)(mm + offset); - p->prev_foot = offset; - p->head = psize; - mark_inuse_foot(m, p, psize); - chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; - - if (m->least_addr == 0 || mm < m->least_addr) - m->least_addr = mm; - if ((m->footprint += mmsize) > m->max_footprint) - m->max_footprint = m->footprint; - assert(is_aligned(chunk2mem(p))); - check_mmapped_chunk(m, p); - return chunk2mem(p); - } - } - return 0; -} - -/* Realloc using mmap */ -static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) { - size_t oldsize = chunksize(oldp); - if (is_small(nb)) /* Can't shrink mmap regions below small size */ - return 0; - /* Keep old chunk if big enough but not too big */ - if (oldsize >= nb + SIZE_T_SIZE && - (oldsize - nb) <= (mparams.granularity << 1)) - return oldp; - else { - size_t offset = oldp->prev_foot; - size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; - size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - char* cp = (char*)CALL_MREMAP((char*)oldp - offset, - oldmmsize, newmmsize, flags); - if (cp != CMFAIL) { - mchunkptr newp = (mchunkptr)(cp + offset); - size_t psize = newmmsize - offset - MMAP_FOOT_PAD; - newp->head = psize; - mark_inuse_foot(m, newp, psize); - chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; - - if (cp < m->least_addr) - m->least_addr = cp; - if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) - m->max_footprint = m->footprint; - check_mmapped_chunk(m, newp); - return newp; - } - } - return 0; -} - - -/* -------------------------- mspace management -------------------------- */ - -/* Initialize top chunk and its size */ -static void init_top(mstate m, mchunkptr p, size_t psize) { - /* Ensure alignment */ - size_t offset = align_offset(chunk2mem(p)); - p = (mchunkptr)((char*)p + offset); - psize -= offset; - - m->top = p; - m->topsize = psize; - p->head = psize | PINUSE_BIT; - /* set size of fake trailing chunk holding overhead space only once */ - chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; - m->trim_check = mparams.trim_threshold; /* reset on each update */ -} - -/* Initialize bins for a new mstate that is otherwise zeroed out */ -static void init_bins(mstate m) { - /* Establish circular links for smallbins */ - bindex_t i; - for (i = 0; i < NSMALLBINS; ++i) { - sbinptr bin = smallbin_at(m,i); - bin->fd = bin->bk = bin; - } -} - -#if PROCEED_ON_ERROR - -/* default corruption action */ -static void reset_on_error(mstate m) { - int i; - ++malloc_corruption_error_count; - /* Reinitialize fields to forget about all memory */ - m->smallmap = m->treemap = 0; - m->dvsize = m->topsize = 0; - m->seg.base = 0; - m->seg.size = 0; - m->seg.next = 0; - m->top = m->dv = 0; - for (i = 0; i < NTREEBINS; ++i) - *treebin_at(m, i) = 0; - init_bins(m); -} -#endif /* PROCEED_ON_ERROR */ - -/* Allocate chunk and prepend remainder with chunk in successor base. */ -static void* prepend_alloc(mstate m, char* newbase, char* oldbase, - size_t nb) { - mchunkptr p = align_as_chunk(newbase); - mchunkptr oldfirst = align_as_chunk(oldbase); - size_t psize = (char*)oldfirst - (char*)p; - mchunkptr q = chunk_plus_offset(p, nb); - size_t qsize = psize - nb; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - - assert((char*)oldfirst > (char*)q); - assert(pinuse(oldfirst)); - assert(qsize >= MIN_CHUNK_SIZE); - - /* consolidate remainder with first chunk of old base */ - if (oldfirst == m->top) { - size_t tsize = m->topsize += qsize; - m->top = q; - q->head = tsize | PINUSE_BIT; - check_top_chunk(m, q); - } - else if (oldfirst == m->dv) { - size_t dsize = m->dvsize += qsize; - m->dv = q; - set_size_and_pinuse_of_free_chunk(q, dsize); - } - else { - if (!is_inuse(oldfirst)) { - size_t nsize = chunksize(oldfirst); - unlink_chunk(m, oldfirst, nsize); - oldfirst = chunk_plus_offset(oldfirst, nsize); - qsize += nsize; - } - set_free_with_pinuse(q, qsize, oldfirst); - insert_chunk(m, q, qsize); - check_free_chunk(m, q); - } - - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); -} - -/* Add a segment to hold a new noncontiguous region */ -static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { - /* Determine locations and sizes of segment, fenceposts, old top */ - char* old_top = (char*)m->top; - msegmentptr oldsp = segment_holding(m, old_top); - char* old_end = oldsp->base + oldsp->size; - size_t ssize = pad_request(sizeof(struct malloc_segment)); - char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - size_t offset = align_offset(chunk2mem(rawsp)); - char* asp = rawsp + offset; - char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; - mchunkptr sp = (mchunkptr)csp; - msegmentptr ss = (msegmentptr)(chunk2mem(sp)); - mchunkptr tnext = chunk_plus_offset(sp, ssize); - mchunkptr p = tnext; - int nfences = 0; - - /* reset top to new space */ - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - - /* Set up segment record */ - assert(is_aligned(ss)); - set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); - *ss = m->seg; /* Push current record */ - m->seg.base = tbase; - m->seg.size = tsize; - m->seg.sflags = mmapped; - m->seg.next = ss; - - /* Insert trailing fenceposts */ - for (;;) { - mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); - p->head = FENCEPOST_HEAD; - ++nfences; - if ((char*)(&(nextp->head)) < old_end) - p = nextp; - else - break; - } - assert(nfences >= 2); - - /* Insert the rest of old top into a bin as an ordinary free chunk */ - if (csp != old_top) { - mchunkptr q = (mchunkptr)old_top; - size_t psize = csp - old_top; - mchunkptr tn = chunk_plus_offset(q, psize); - set_free_with_pinuse(q, psize, tn); - insert_chunk(m, q, psize); - } - - check_top_chunk(m, m->top); -} - -/* -------------------------- System allocation -------------------------- */ - -/* Get memory from system using MORECORE or MMAP */ -static void* sys_alloc(mstate m, size_t nb) { - char* tbase = CMFAIL; - size_t tsize = 0; - flag_t mmap_flag = 0; - size_t asize; /* allocation size */ - - ensure_initialization(); - - /* Directly map large chunks, but only if already initialized */ - if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) { - void* mem = mmap_alloc(m, nb); - if (mem != 0) - return mem; - } - - asize = granularity_align(nb + SYS_ALLOC_PADDING); - if (asize <= nb) - return 0; /* wraparound */ - if (m->footprint_limit != 0) { - size_t fp = m->footprint + asize; - if (fp <= m->footprint || fp > m->footprint_limit) - return 0; - } - - /* - Try getting memory in any of three ways (in most-preferred to - least-preferred order): - 1. A call to MORECORE that can normally contiguously extend memory. - (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) - 2. A call to MMAP new space (disabled if not HAVE_MMAP). - Note that under the default settings, if MORECORE is unable to - fulfill a request, and HAVE_MMAP is true, then mmap is - used as a noncontiguous system allocator. This is a useful backup - strategy for systems with holes in address spaces -- in this case - sbrk cannot contiguously expand the heap, but mmap may be able to - find space. - 3. A call to MORECORE that cannot usually contiguously extend memory. - (disabled if not HAVE_MORECORE) - - In all cases, we need to request enough bytes from system to ensure - we can malloc nb bytes upon success, so pad with enough space for - top_foot, plus alignment-pad to make sure we don't lose bytes if - not on boundary, and round this up to a granularity unit. - */ - - if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { - char* br = CMFAIL; - msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); - ACQUIRE_MALLOC_GLOBAL_LOCK(); - - if (ss == 0) { /* First time through or recovery */ - char* base = (char*)CALL_MORECORE(0); - if (base != CMFAIL) { - size_t fp; - /* Adjust to end on a page boundary */ - if (!is_page_aligned(base)) - asize += (page_align((size_t)base) - (size_t)base); - fp = m->footprint + asize; /* recheck limits */ - if (asize > nb && asize < HALF_MAX_SIZE_T && - (m->footprint_limit == 0 || - (fp > m->footprint && fp <= m->footprint_limit)) && - (br = (char*)(CALL_MORECORE(asize))) == base) { - tbase = base; - tsize = asize; - } - } - } - else { - /* Subtract out existing available top space from MORECORE request. */ - asize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); - /* Use mem here only if it did continuously extend old space */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { - tbase = br; - tsize = asize; - } - } - - if (tbase == CMFAIL) { /* Cope with partial failure */ - if (br != CMFAIL) { /* Try to use/extend the space we did get */ - if (asize < HALF_MAX_SIZE_T && - asize < nb + SYS_ALLOC_PADDING) { - size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - asize); - if (esize < HALF_MAX_SIZE_T) { - char* end = (char*)CALL_MORECORE(esize); - if (end != CMFAIL) - asize += esize; - else { /* Can't use; try to release */ - (void) CALL_MORECORE(-asize); - br = CMFAIL; - } - } - } - } - if (br != CMFAIL) { /* Use the space we did get */ - tbase = br; - tsize = asize; - } - else - disable_contiguous(m); /* Don't try contiguous path in the future */ - } - - RELEASE_MALLOC_GLOBAL_LOCK(); - } - - if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ - char* mp = (char*)(CALL_MMAP(asize)); - if (mp != CMFAIL) { - tbase = mp; - tsize = asize; - mmap_flag = USE_MMAP_BIT; - } - } - - if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ - if (asize < HALF_MAX_SIZE_T) { - char* br = CMFAIL; - char* end = CMFAIL; - ACQUIRE_MALLOC_GLOBAL_LOCK(); - br = (char*)(CALL_MORECORE(asize)); - end = (char*)(CALL_MORECORE(0)); - RELEASE_MALLOC_GLOBAL_LOCK(); - if (br != CMFAIL && end != CMFAIL && br < end) { - size_t ssize = end - br; - if (ssize > nb + TOP_FOOT_SIZE) { - tbase = br; - tsize = ssize; - } - } - } - } - - if (tbase != CMFAIL) { - - if ((m->footprint += tsize) > m->max_footprint) - m->max_footprint = m->footprint; - - if (!is_initialized(m)) { /* first-time initialization */ - if (m->least_addr == 0 || tbase < m->least_addr) - m->least_addr = tbase; - m->seg.base = tbase; - m->seg.size = tsize; - m->seg.sflags = mmap_flag; - m->magic = mparams.magic; - m->release_checks = MAX_RELEASE_CHECK_RATE; - init_bins(m); -#if !ONLY_MSPACES - if (is_global(m)) - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - else -#endif - { - /* Offset top by embedded malloc_state */ - mchunkptr mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); - } - } - - else { - /* Try to merge with an existing segment */ - msegmentptr sp = &m->seg; - /* Only consider most recent segment if traversal suppressed */ - while (sp != 0 && tbase != sp->base + sp->size) - sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - (sp->sflags & USE_MMAP_BIT) == mmap_flag && - segment_holds(sp, m->top)) { /* append */ - sp->size += tsize; - init_top(m, m->top, m->topsize + tsize); - } - else { - if (tbase < m->least_addr) - m->least_addr = tbase; - sp = &m->seg; - while (sp != 0 && sp->base != tbase + tsize) - sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - (sp->sflags & USE_MMAP_BIT) == mmap_flag) { - char* oldbase = sp->base; - sp->base = tbase; - sp->size += tsize; - return prepend_alloc(m, tbase, oldbase, nb); - } - else - add_segment(m, tbase, tsize, mmap_flag); - } - } - - if (nb < m->topsize) { /* Allocate from new or extended top space */ - size_t rsize = m->topsize -= nb; - mchunkptr p = m->top; - mchunkptr r = m->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - check_top_chunk(m, m->top); - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); - } - } - - MALLOC_FAILURE_ACTION; - return 0; -} - -/* ----------------------- system deallocation -------------------------- */ - -/* Unmap and unlink any mmapped segments that don't contain used chunks */ -static size_t release_unused_segments(mstate m) { - size_t released = 0; - size_t nsegs = 0; - msegmentptr pred = &m->seg; - msegmentptr sp = pred->next; - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - msegmentptr next = sp->next; - ++nsegs; - if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { - mchunkptr p = align_as_chunk(base); - size_t psize = chunksize(p); - /* Can unmap if first chunk holds entire segment and not pinned */ - if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { - tchunkptr tp = (tchunkptr)p; - assert(segment_holds(sp, (char*)sp)); - if (p == m->dv) { - m->dv = 0; - m->dvsize = 0; - } - else { - unlink_large_chunk(m, tp); - } - if (CALL_MUNMAP(base, size) == 0) { - released += size; - m->footprint -= size; - /* unlink obsoleted record */ - sp = pred; - sp->next = next; - } - else { /* back out if cannot unmap */ - insert_large_chunk(m, tp, psize); - } - } - } - if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ - break; - pred = sp; - sp = next; - } - /* Reset check counter */ - m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)? - nsegs : MAX_RELEASE_CHECK_RATE); - return released; -} - -static int sys_trim(mstate m, size_t pad) { - size_t released = 0; - ensure_initialization(); - if (pad < MAX_REQUEST && is_initialized(m)) { - pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ - - if (m->topsize > pad) { - /* Shrink top space in granularity-size units, keeping at least one */ - size_t unit = mparams.granularity; - size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - - SIZE_T_ONE) * unit; - msegmentptr sp = segment_holding(m, (char*)m->top); - - if (!is_extern_segment(sp)) { - if (is_mmapped_segment(sp)) { - if (HAVE_MMAP && - sp->size >= extra && - !has_segment_link(m, sp)) { /* can't shrink if pinned */ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-variable" - size_t newsize = sp->size - extra; -#pragma clang diagnostic pop - /* Prefer mremap, fall back to munmap */ - if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || - (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { - released = extra; - } - } - } - else if (HAVE_MORECORE) { - if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ - extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; - ACQUIRE_MALLOC_GLOBAL_LOCK(); - { - /* Make sure end of memory is where we last set it. */ - char* old_br = (char*)(CALL_MORECORE(0)); - if (old_br == sp->base + sp->size) { - char* rel_br = (char*)(CALL_MORECORE(-extra)); - char* new_br = (char*)(CALL_MORECORE(0)); - if (rel_br != CMFAIL && new_br < old_br) - released = old_br - new_br; - } - } - RELEASE_MALLOC_GLOBAL_LOCK(); - } - } - - if (released != 0) { - sp->size -= released; - m->footprint -= released; - init_top(m, m->top, m->topsize - released); - check_top_chunk(m, m->top); - } - } - - /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) - released += release_unused_segments(m); - - /* On failure, disable autotrim to avoid repeated failed future calls */ - if (released == 0 && m->topsize > m->trim_check) - m->trim_check = MAX_SIZE_T; - } - - return (released != 0)? 1 : 0; -} - -/* Consolidate and bin a chunk. Differs from exported versions - of free mainly in that the chunk need not be marked as inuse. -*/ -static void dispose_chunk(mstate m, mchunkptr p, size_t psize) { - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - mchunkptr prev; - size_t prevsize = p->prev_foot; - if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - m->footprint -= psize; - return; - } - prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */ - if (p != m->dv) { - unlink_chunk(m, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - m->dvsize = psize; - set_free_with_pinuse(p, psize, next); - return; - } - } - else { - CORRUPTION_ERROR_ACTION(m); - return; - } - } - if (RTCHECK(ok_address(m, next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == m->top) { - size_t tsize = m->topsize += psize; - m->top = p; - p->head = tsize | PINUSE_BIT; - if (p == m->dv) { - m->dv = 0; - m->dvsize = 0; - } - return; - } - else if (next == m->dv) { - size_t dsize = m->dvsize += psize; - m->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - return; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(m, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == m->dv) { - m->dvsize = psize; - return; - } - } - } - else { - set_free_with_pinuse(p, psize, next); - } - insert_chunk(m, p, psize); - } - else { - CORRUPTION_ERROR_ACTION(m); - } -} - -/* ---------------------------- malloc --------------------------- */ - -/* allocate a large request from the best fitting chunk in a treebin */ -static void* tmalloc_large(mstate m, size_t nb) { - tchunkptr v = 0; - size_t rsize = -nb; /* Unsigned negation */ - tchunkptr t; - bindex_t idx; - compute_tree_index(nb, idx); - if ((t = *treebin_at(m, idx)) != 0) { - /* Traverse tree for this bin looking for node with size == nb */ - size_t sizebits = nb << leftshift_for_tree_index(idx); - tchunkptr rst = 0; /* The deepest untaken right subtree */ - for (;;) { - tchunkptr rt; - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - v = t; - if ((rsize = trem) == 0) - break; - } - rt = t->child[1]; - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - if (rt != 0 && rt != t) - rst = rt; - if (t == 0) { - t = rst; /* set t to least subtree holding sizes > nb */ - break; - } - sizebits <<= 1; - } - } - if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ - binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; - if (leftbits != 0) { - bindex_t i; - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - t = *treebin_at(m, i); - } - } - - while (t != 0) { /* find smallest of tree or subtree */ - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - t = leftmost_child(t); - } - - /* If dv is a better fit, return 0 so malloc will use it */ - if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { - if (RTCHECK(ok_address(m, v))) { /* split */ - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - insert_chunk(m, r, rsize); - } - return chunk2mem(v); - } - } - CORRUPTION_ERROR_ACTION(m); - } - return 0; -} - -/* allocate a small request from the best fitting chunk in a treebin */ -static void* tmalloc_small(mstate m, size_t nb) { - tchunkptr t, v; - size_t rsize; - bindex_t i; - binmap_t leastbit = least_bit(m->treemap); - compute_bit2idx(leastbit, i); - v = t = *treebin_at(m, i); - rsize = chunksize(t) - nb; - - while ((t = leftmost_child(t)) != 0) { - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - } - - if (RTCHECK(ok_address(m, v))) { - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(m, r, rsize); - } - return chunk2mem(v); - } - } - - CORRUPTION_ERROR_ACTION(m); - return 0; -} - -#if !ONLY_MSPACES - -void* dlmalloc(size_t bytes) { - /* - Basic algorithm: - If a small request (< 256 bytes minus per-chunk overhead): - 1. If one exists, use a remainderless chunk in associated smallbin. - (Remainderless means that there are too few excess bytes to - represent as a chunk.) - 2. If it is big enough, use the dv chunk, which is normally the - chunk adjacent to the one used for the most recent small request. - 3. If one exists, split the smallest available chunk in a bin, - saving remainder in dv. - 4. If it is big enough, use the top chunk. - 5. If available, get memory from system and use it - Otherwise, for a large request: - 1. Find the smallest available binned chunk that fits, and use it - if it is better fitting than dv chunk, splitting if necessary. - 2. If better fitting than any binned chunk, use the dv chunk. - 3. If it is big enough, use the top chunk. - 4. If request size >= mmap threshold, try to directly mmap this chunk. - 5. If available, get memory from system and use it - - The ugly goto's here ensure that postaction occurs along all paths. - */ - -#if USE_LOCKS - ensure_initialization(); /* initialize in sys_alloc if not using locks */ -#endif - - if (!PREACTION(gm)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = gm->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(gm, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(gm, b, p, idx); - set_inuse_and_pinuse(gm, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb > gm->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(gm, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(gm, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(gm, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(gm, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - - if (nb <= gm->dvsize) { - size_t rsize = gm->dvsize - nb; - mchunkptr p = gm->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = gm->dv = chunk_plus_offset(p, nb); - gm->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - } - else { /* exhaust dv */ - size_t dvs = gm->dvsize; - gm->dvsize = 0; - gm->dv = 0; - set_inuse_and_pinuse(gm, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb < gm->topsize) { /* Split top */ - size_t rsize = gm->topsize -= nb; - mchunkptr p = gm->top; - mchunkptr r = gm->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - mem = chunk2mem(p); - check_top_chunk(gm, gm->top); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - mem = sys_alloc(gm, nb); - - postaction: - POSTACTION(gm); - return mem; - } - - return 0; -} - -/* ---------------------------- free --------------------------- */ - -void dlfree(void* mem) { - /* - Consolidate freed chunks with preceeding or succeeding bordering - free chunks, if they exist, and then place in a bin. Intermixed - with special cases for top, dv, mmapped chunks, and usage errors. - */ - - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } -#else /* FOOTERS */ -#define fm gm -#endif /* FOOTERS */ - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - - if (is_small(psize)) { - insert_small_chunk(fm, p, psize); - check_free_chunk(fm, p); - } - else { - tchunkptr tp = (tchunkptr)p; - insert_large_chunk(fm, tp, psize); - check_free_chunk(fm, p); - if (--fm->release_checks == 0) - release_unused_segments(fm); - } - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -#if !FOOTERS -#undef fm -#endif /* FOOTERS */ -} - -void* dlcalloc(size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = dlmalloc(req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -#endif /* !ONLY_MSPACES */ - -/* ------------ Internal support for realloc, memalign, etc -------------- */ - -/* Try to realloc; only in-place unless can_move true */ -static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, - int can_move) { - mchunkptr newp = 0; - size_t oldsize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, oldsize); - if (RTCHECK(ok_address(m, p) && ok_inuse(p) && - ok_next(p, next) && ok_pinuse(next))) { - if (is_mmapped(p)) { - newp = mmap_resize(m, p, nb, can_move); - } - else if (oldsize >= nb) { /* already big enough */ - size_t rsize = oldsize - nb; - if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */ - mchunkptr r = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, r, rsize); - dispose_chunk(m, r, rsize); - } - newp = p; - } - else if (next == m->top) { /* extend into top */ - if (oldsize + m->topsize > nb) { - size_t newsize = oldsize + m->topsize; - size_t newtopsize = newsize - nb; - mchunkptr newtop = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - newtop->head = newtopsize |PINUSE_BIT; - m->top = newtop; - m->topsize = newtopsize; - newp = p; - } - } - else if (next == m->dv) { /* extend into dv */ - size_t dvs = m->dvsize; - if (oldsize + dvs >= nb) { - size_t dsize = oldsize + dvs - nb; - if (dsize >= MIN_CHUNK_SIZE) { - mchunkptr r = chunk_plus_offset(p, nb); - mchunkptr n = chunk_plus_offset(r, dsize); - set_inuse(m, p, nb); - set_size_and_pinuse_of_free_chunk(r, dsize); - clear_pinuse(n); - m->dvsize = dsize; - m->dv = r; - } - else { /* exhaust dv */ - size_t newsize = oldsize + dvs; - set_inuse(m, p, newsize); - m->dvsize = 0; - m->dv = 0; - } - newp = p; - } - } - else if (!cinuse(next)) { /* extend into next free chunk */ - size_t nextsize = chunksize(next); - if (oldsize + nextsize >= nb) { - size_t rsize = oldsize + nextsize - nb; - unlink_chunk(m, next, nextsize); - if (rsize < MIN_CHUNK_SIZE) { - size_t newsize = oldsize + nextsize; - set_inuse(m, p, newsize); - } - else { - mchunkptr r = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, r, rsize); - dispose_chunk(m, r, rsize); - } - newp = p; - } - } - } - else { - USAGE_ERROR_ACTION(m, oldmem); - } - return newp; -} - -static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { - void* mem = 0; - if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ - alignment = MIN_CHUNK_SIZE; - if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ - size_t a = MALLOC_ALIGNMENT << 1; - while (a < alignment) a <<= 1; - alignment = a; - } - if (bytes >= MAX_REQUEST - alignment) { - if (m != 0) { /* Test isn't needed but avoids compiler warning */ - MALLOC_FAILURE_ACTION; - } - } - else { - size_t nb = request2size(bytes); - size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; - mem = internal_malloc(m, req); - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (PREACTION(m)) - return 0; - if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ - /* - Find an aligned spot inside chunk. Since we need to give - back leading space in a chunk of at least MIN_CHUNK_SIZE, if - the first calculation places us at a spot with less than - MIN_CHUNK_SIZE leader, we can move to the next aligned spot. - We've allocated enough total room so that this is always - possible. - */ - char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment - - SIZE_T_ONE)) & - -alignment)); - char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? - br : br+alignment; - mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char*)(p); - size_t newsize = chunksize(p) - leadsize; - - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ - newp->prev_foot = p->prev_foot + leadsize; - newp->head = newsize; - } - else { /* Otherwise, give back leader, use the rest */ - set_inuse(m, newp, newsize); - set_inuse(m, p, leadsize); - dispose_chunk(m, p, leadsize); - } - p = newp; - } - - /* Give back spare room at the end */ - if (!is_mmapped(p)) { - size_t size = chunksize(p); - if (size > nb + MIN_CHUNK_SIZE) { - size_t remainder_size = size - nb; - mchunkptr remainder = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, remainder, remainder_size); - dispose_chunk(m, remainder, remainder_size); - } - } - - mem = chunk2mem(p); - assert (chunksize(p) >= nb); - assert(((size_t)mem & (alignment - 1)) == 0); - check_inuse_chunk(m, p); - POSTACTION(m); - } - } - return mem; -} - -/* - Common support for independent_X routines, handling - all of the combinations that can result. - The opts arg has: - bit 0 set if all elements are same size (using sizes[0]) - bit 1 set if elements should be zeroed -*/ -static void** ialloc(mstate m, - size_t n_elements, - size_t* sizes, - int opts, - void* chunks[]) { - - size_t element_size; /* chunksize of each element, if all same */ - size_t contents_size; /* total size of elements */ - size_t array_size; /* request size of pointer array */ - void* mem; /* malloced aggregate space */ - mchunkptr p; /* corresponding chunk */ - size_t remainder_size; /* remaining bytes while splitting */ - void** marray; /* either "chunks" or malloced ptr array */ - mchunkptr array_chunk; /* chunk for malloced ptr array */ - flag_t was_enabled; /* to disable mmap */ - size_t size; - size_t i; - - ensure_initialization(); - /* compute array length, if needed */ - if (chunks != 0) { - if (n_elements == 0) - return chunks; /* nothing to do */ - marray = chunks; - array_size = 0; - } - else { - /* if empty req, must still return chunk representing empty array */ - if (n_elements == 0) - return (void**)internal_malloc(m, 0); - marray = 0; - array_size = request2size(n_elements * (sizeof(void*))); - } - - /* compute total element size */ - if (opts & 0x1) { /* all-same-size */ - element_size = request2size(*sizes); - contents_size = n_elements * element_size; - } - else { /* add up all the sizes */ - element_size = 0; - contents_size = 0; - for (i = 0; i != n_elements; ++i) - contents_size += request2size(sizes[i]); - } - - size = contents_size + array_size; - - /* - Allocate the aggregate chunk. First disable direct-mmapping so - malloc won't use it, since we would not be able to later - free/realloc space internal to a segregated mmap region. - */ - was_enabled = use_mmap(m); - disable_mmap(m); - mem = internal_malloc(m, size - CHUNK_OVERHEAD); - if (was_enabled) - enable_mmap(m); - if (mem == 0) - return 0; - - if (PREACTION(m)) return 0; - p = mem2chunk(mem); - remainder_size = chunksize(p); - - assert(!is_mmapped(p)); - - if (opts & 0x2) { /* optionally clear the elements */ - memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); - } - - /* If not provided, allocate the pointer array as final part of chunk */ - if (marray == 0) { - size_t array_chunk_size; - array_chunk = chunk_plus_offset(p, contents_size); - array_chunk_size = remainder_size - contents_size; - marray = (void**) (chunk2mem(array_chunk)); - set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); - remainder_size = contents_size; - } - - /* split out elements */ - for (i = 0; ; ++i) { - marray[i] = chunk2mem(p); - if (i != n_elements-1) { - if (element_size != 0) - size = element_size; - else - size = request2size(sizes[i]); - remainder_size -= size; - set_size_and_pinuse_of_inuse_chunk(m, p, size); - p = chunk_plus_offset(p, size); - } - else { /* the final element absorbs any overallocation slop */ - set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); - break; - } - } - -#if DEBUG - if (marray != chunks) { - /* final element must have exactly exhausted chunk */ - if (element_size != 0) { - assert(remainder_size == element_size); - } - else { - assert(remainder_size == request2size(sizes[i])); - } - check_inuse_chunk(m, mem2chunk(marray)); - } - for (i = 0; i != n_elements; ++i) - check_inuse_chunk(m, mem2chunk(marray[i])); - -#endif /* DEBUG */ - - POSTACTION(m); - return marray; -} - -/* Try to free all pointers in the given array. - Note: this could be made faster, by delaying consolidation, - at the price of disabling some user integrity checks, We - still optimize some consolidations by combining adjacent - chunks before freeing, which will occur often if allocated - with ialloc or the array is sorted. -*/ -static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) { - size_t unfreed = 0; - if (!PREACTION(m)) { - void** a; - void** fence = &(array[nelem]); - for (a = array; a != fence; ++a) { - void* mem = *a; - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - size_t psize = chunksize(p); -#if FOOTERS - if (get_mstate_for(p) != m) { - ++unfreed; - continue; - } -#endif - check_inuse_chunk(m, p); - *a = 0; - if (RTCHECK(ok_address(m, p) && ok_inuse(p))) { - void ** b = a + 1; /* try to merge with next chunk */ - mchunkptr next = next_chunk(p); - if (b != fence && *b == chunk2mem(next)) { - size_t newsize = chunksize(next) + psize; - set_inuse(m, p, newsize); - *b = chunk2mem(p); - } - else - dispose_chunk(m, p, psize); - } - else { - CORRUPTION_ERROR_ACTION(m); - break; - } - } - } - if (should_trim(m, m->topsize)) - sys_trim(m, 0); - POSTACTION(m); - } - return unfreed; -} - -/* Traversal */ -#if MALLOC_INSPECT_ALL -static void internal_inspect_all(mstate m, - void(*handler)(void *start, - void *end, - size_t used_bytes, - void* callback_arg), - void* arg) { - if (is_initialized(m)) { - mchunkptr top = m->top; - msegmentptr s; - for (s = &m->seg; s != 0; s = s->next) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) { - mchunkptr next = next_chunk(q); - size_t sz = chunksize(q); - size_t used; - void* start; - if (is_inuse(q)) { - used = sz - CHUNK_OVERHEAD; /* must not be mmapped */ - start = chunk2mem(q); - } - else { - used = 0; - if (is_small(sz)) { /* offset by possible bookkeeping */ - start = (void*)((char*)q + sizeof(malloc_chunk)); - } - else { - start = (void*)((char*)q + sizeof(malloc_tree_chunk)); - } - } - if (start < (void*)next) /* skip if all space is bookkeeping */ - handler(start, next, used, arg); - if (q == top) - break; - q = next; - } - } - } -} -#endif /* MALLOC_INSPECT_ALL */ - -/* ------------------ Exported realloc, memalign, etc -------------------- */ - -#if !ONLY_MSPACES - -void* dlrealloc(void* oldmem, size_t bytes) { - void* mem = 0; - if (oldmem == 0) { - mem = dlmalloc(bytes); - } - else if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - } -#ifdef REALLOC_ZERO_BYTES_FREES - else if (bytes == 0) { - dlfree(oldmem); - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { - size_t nb = request2size(bytes); - mchunkptr oldp = mem2chunk(oldmem); -#if ! FOOTERS - mstate m = gm; -#else /* FOOTERS */ - mstate m = get_mstate_for(oldp); - if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); - return 0; - } -#endif /* FOOTERS */ - if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); - POSTACTION(m); - if (newp != 0) { - check_inuse_chunk(m, newp); - mem = chunk2mem(newp); - } - else { - mem = internal_malloc(m, bytes); - if (mem != 0) { - size_t oc = chunksize(oldp) - overhead_for(oldp); - memcpy(mem, oldmem, (oc < bytes)? oc : bytes); - internal_free(m, oldmem); - } - } - } - } - return mem; -} - -void* dlrealloc_in_place(void* oldmem, size_t bytes) { - void* mem = 0; - if (oldmem != 0) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - } - else { - size_t nb = request2size(bytes); - mchunkptr oldp = mem2chunk(oldmem); -#if ! FOOTERS - mstate m = gm; -#else /* FOOTERS */ - mstate m = get_mstate_for(oldp); - if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); - return 0; - } -#endif /* FOOTERS */ - if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); - POSTACTION(m); - if (newp == oldp) { - check_inuse_chunk(m, newp); - mem = oldmem; - } - } - } - } - return mem; -} - -void* dlmemalign(size_t alignment, size_t bytes) { - if (alignment <= MALLOC_ALIGNMENT) { - return dlmalloc(bytes); - } - return internal_memalign(gm, alignment, bytes); -} - -int dlposix_memalign(void** pp, size_t alignment, size_t bytes) { - void* mem = 0; - if (alignment == MALLOC_ALIGNMENT) - mem = dlmalloc(bytes); - else { - size_t d = alignment / sizeof(void*); - size_t r = alignment % sizeof(void*); - if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0) - return EINVAL; - else if (bytes >= MAX_REQUEST - alignment) { - if (alignment < MIN_CHUNK_SIZE) - alignment = MIN_CHUNK_SIZE; - mem = internal_memalign(gm, alignment, bytes); - } - } - if (mem == 0) - return ENOMEM; - else { - *pp = mem; - return 0; - } -} - -void* dlvalloc(size_t bytes) { - size_t pagesz; - ensure_initialization(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, bytes); -} - -void* dlpvalloc(size_t bytes) { - size_t pagesz; - ensure_initialization(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); -} - -void** dlindependent_calloc(size_t n_elements, size_t elem_size, - void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - return ialloc(gm, n_elements, &sz, 3, chunks); -} - -void** dlindependent_comalloc(size_t n_elements, size_t sizes[], - void* chunks[]) { - return ialloc(gm, n_elements, sizes, 0, chunks); -} - -size_t dlbulk_free(void* array[], size_t nelem) { - return internal_bulk_free(gm, array, nelem); -} - -#if MALLOC_INSPECT_ALL -void dlmalloc_inspect_all(void(*handler)(void *start, - void *end, - size_t used_bytes, - void* callback_arg), - void* arg) { - ensure_initialization(); - if (!PREACTION(gm)) { - internal_inspect_all(gm, handler, arg); - POSTACTION(gm); - } -} -#endif /* MALLOC_INSPECT_ALL */ - -int dlmalloc_trim(size_t pad) { - int result = 0; - ensure_initialization(); - if (!PREACTION(gm)) { - result = sys_trim(gm, pad); - POSTACTION(gm); - } - return result; -} - -size_t dlmalloc_footprint(void) { - return gm->footprint; -} - -size_t dlmalloc_max_footprint(void) { - return gm->max_footprint; -} - -size_t dlmalloc_footprint_limit(void) { - size_t maf = gm->footprint_limit; - return maf == 0 ? MAX_SIZE_T : maf; -} - -size_t dlmalloc_set_footprint_limit(size_t bytes) { - size_t result; /* invert sense of 0 */ - if (bytes == 0) - result = granularity_align(1); /* Use minimal size */ - if (bytes == MAX_SIZE_T) - result = 0; /* disable */ - else - result = granularity_align(bytes); - return gm->footprint_limit = result; -} - -#if !NO_MALLINFO -struct mallinfo dlmallinfo(void) { - return internal_mallinfo(gm); -} -#endif /* NO_MALLINFO */ - -#if !NO_MALLOC_STATS -void dlmalloc_stats() { - internal_malloc_stats(gm); -} -#endif /* NO_MALLOC_STATS */ - -int dlmallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -size_t dlmalloc_usable_size(void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (is_inuse(p)) - return chunksize(p) - overhead_for(p); - } - return 0; -} - -#endif /* !ONLY_MSPACES */ - -/* ----------------------------- user mspaces ---------------------------- */ - -#if MSPACES - -static mstate init_user_mstate(char* tbase, size_t tsize) { - size_t msize = pad_request(sizeof(struct malloc_state)); - mchunkptr mn; - mchunkptr msp = align_as_chunk(tbase); - mstate m = (mstate)(chunk2mem(msp)); - memset(m, 0, msize); - (void)INITIAL_LOCK(&m->mutex); - msp->head = (msize|INUSE_BITS); - m->seg.base = m->least_addr = tbase; - m->seg.size = m->footprint = m->max_footprint = tsize; - m->magic = mparams.magic; - m->release_checks = MAX_RELEASE_CHECK_RATE; - m->mflags = mparams.default_mflags; - m->extp = 0; - m->exts = 0; - disable_contiguous(m); - init_bins(m); - mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); - check_top_chunk(m, m->top); - return m; -} - -mspace create_mspace(size_t capacity, int locked) { - mstate m = 0; - size_t msize; - ensure_initialization(); - msize = pad_request(sizeof(struct malloc_state)); - if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - size_t rs = ((capacity == 0)? mparams.granularity : - (capacity + TOP_FOOT_SIZE + msize)); - size_t tsize = granularity_align(rs); - char* tbase = (char*)(CALL_MMAP(tsize)); - if (tbase != CMFAIL) { - m = init_user_mstate(tbase, tsize); - m->seg.sflags = USE_MMAP_BIT; - set_lock(m, locked); - } - } - return (mspace)m; -} - -mspace create_mspace_with_base(void* base, size_t capacity, int locked) { - mstate m = 0; - size_t msize; - ensure_initialization(); - msize = pad_request(sizeof(struct malloc_state)); - if (capacity > msize + TOP_FOOT_SIZE && - capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - m = init_user_mstate((char*)base, capacity); - m->seg.sflags = EXTERN_BIT; - set_lock(m, locked); - } - return (mspace)m; -} - -int mspace_track_large_chunks(mspace msp, int enable) { - int ret = 0; - mstate ms = (mstate)msp; - if (!PREACTION(ms)) { - if (!use_mmap(ms)) - ret = 1; - if (!enable) - enable_mmap(ms); - else - disable_mmap(ms); - POSTACTION(ms); - } - return ret; -} - -size_t destroy_mspace(mspace msp) { - size_t freed = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - msegmentptr sp = &ms->seg; - (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */ - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - flag_t flag = sp->sflags; - sp = sp->next; - if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) && - CALL_MUNMAP(base, size) == 0) - freed += size; - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return freed; -} - -/* - mspace versions of routines are near-clones of the global - versions. This is not so nice but better than the alternatives. -*/ - -void* mspace_malloc(mspace msp, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (!PREACTION(ms)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = ms->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(ms, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(ms, b, p, idx); - set_inuse_and_pinuse(ms, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb > ms->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(ms, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(ms, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(ms, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(ms, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - - if (nb <= ms->dvsize) { - size_t rsize = ms->dvsize - nb; - mchunkptr p = ms->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = ms->dv = chunk_plus_offset(p, nb); - ms->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - } - else { /* exhaust dv */ - size_t dvs = ms->dvsize; - ms->dvsize = 0; - ms->dv = 0; - set_inuse_and_pinuse(ms, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb < ms->topsize) { /* Split top */ - size_t rsize = ms->topsize -= nb; - mchunkptr p = ms->top; - mchunkptr r = ms->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - mem = chunk2mem(p); - check_top_chunk(ms, ms->top); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - mem = sys_alloc(ms, nb); - - postaction: - POSTACTION(ms); - return mem; - } - - return 0; -} - -void mspace_free(mspace msp, void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); - msp = msp; /* placate people compiling -Wunused */ -#else /* FOOTERS */ - mstate fm = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - - if (is_small(psize)) { - insert_small_chunk(fm, p, psize); - check_free_chunk(fm, p); - } - else { - tchunkptr tp = (tchunkptr)p; - insert_large_chunk(fm, tp, psize); - check_free_chunk(fm, p); - if (--fm->release_checks == 0) - release_unused_segments(fm); - } - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -} - -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = internal_malloc(ms, req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { - void* mem = 0; - if (oldmem == 0) { - mem = mspace_malloc(msp, bytes); - } - else if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - } -#ifdef REALLOC_ZERO_BYTES_FREES - else if (bytes == 0) { - mspace_free(msp, oldmem); - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { - size_t nb = request2size(bytes); - mchunkptr oldp = mem2chunk(oldmem); -#if ! FOOTERS - mstate m = (mstate)msp; -#else /* FOOTERS */ - mstate m = get_mstate_for(oldp); - if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); - return 0; - } -#endif /* FOOTERS */ - if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); - POSTACTION(m); - if (newp != 0) { - check_inuse_chunk(m, newp); - mem = chunk2mem(newp); - } - else { - mem = mspace_malloc(m, bytes); - if (mem != 0) { - size_t oc = chunksize(oldp) - overhead_for(oldp); - memcpy(mem, oldmem, (oc < bytes)? oc : bytes); - mspace_free(m, oldmem); - } - } - } - } - return mem; -} - -void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) { - void* mem = 0; - if (oldmem != 0) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - } - else { - size_t nb = request2size(bytes); - mchunkptr oldp = mem2chunk(oldmem); -#if ! FOOTERS - mstate m = (mstate)msp; -#else /* FOOTERS */ - mstate m = get_mstate_for(oldp); - msp = msp; /* placate people compiling -Wunused */ - if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); - return 0; - } -#endif /* FOOTERS */ - if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); - POSTACTION(m); - if (newp == oldp) { - check_inuse_chunk(m, newp); - mem = oldmem; - } - } - } - } - return mem; -} - -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (alignment <= MALLOC_ALIGNMENT) - return mspace_malloc(msp, bytes); - return internal_memalign(ms, alignment, bytes); -} - -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, &sz, 3, chunks); -} - -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, sizes, 0, chunks); -} - -size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) { - return internal_bulk_free((mstate)msp, array, nelem); -} - -#if MALLOC_INSPECT_ALL -void mspace_inspect_all(mspace msp, - void(*handler)(void *start, - void *end, - size_t used_bytes, - void* callback_arg), - void* arg) { - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - if (!PREACTION(ms)) { - internal_inspect_all(ms, handler, arg); - POSTACTION(ms); - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } -} -#endif /* MALLOC_INSPECT_ALL */ - -int mspace_trim(mspace msp, size_t pad) { - int result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - if (!PREACTION(ms)) { - result = sys_trim(ms, pad); - POSTACTION(ms); - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -#if !NO_MALLOC_STATS -void mspace_malloc_stats(mspace msp) { - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - internal_malloc_stats(ms); - } - else { - USAGE_ERROR_ACTION(ms,ms); - } -} -#endif /* NO_MALLOC_STATS */ - -size_t mspace_footprint(mspace msp) { - size_t result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->footprint; - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -size_t mspace_max_footprint(mspace msp) { - size_t result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->max_footprint; - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -size_t mspace_footprint_limit(mspace msp) { - size_t result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - size_t maf = ms->footprint_limit; - result = (maf == 0) ? MAX_SIZE_T : maf; - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -size_t mspace_set_footprint_limit(mspace msp, size_t bytes) { - size_t result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - if (bytes == 0) - result = granularity_align(1); /* Use minimal size */ - if (bytes == MAX_SIZE_T) - result = 0; /* disable */ - else - result = granularity_align(bytes); - ms->footprint_limit = result; - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -#if !NO_MALLINFO -struct mallinfo mspace_mallinfo(mspace msp) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - } - return internal_mallinfo(ms); -} -#endif /* NO_MALLINFO */ - -size_t mspace_usable_size(void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (is_inuse(p)) - return chunksize(p) - overhead_for(p); - } - return 0; -} - -int mspace_mallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -#endif /* MSPACES */ - -#pragma clang diagnostic pop // ignored -Wcast-align - -/* -------------------- Alternative MORECORE functions ------------------- */ - -/* - Guidelines for creating a custom version of MORECORE: - - * For best performance, MORECORE should allocate in multiples of pagesize. - * MORECORE may allocate more memory than requested. (Or even less, - but this will usually result in a malloc failure.) - * MORECORE must not allocate memory when given argument zero, but - instead return one past the end address of memory from previous - nonzero call. - * For best performance, consecutive calls to MORECORE with positive - arguments should return increasing addresses, indicating that - space has been contiguously extended. - * Even though consecutive calls to MORECORE need not return contiguous - addresses, it must be OK for malloc'ed chunks to span multiple - regions in those cases where they do happen to be contiguous. - * MORECORE need not handle negative arguments -- it may instead - just return MFAIL when given negative arguments. - Negative arguments are always multiples of pagesize. MORECORE - must not misinterpret negative args as large positive unsigned - args. You can suppress all such calls from even occurring by defining - MORECORE_CANNOT_TRIM, - - As an example alternative MORECORE, here is a custom allocator - kindly contributed for pre-OSX macOS. It uses virtually but not - necessarily physically contiguous non-paged memory (locked in, - present and won't get swapped out). You can use it by uncommenting - this section, adding some #includes, and setting up the appropriate - defines above: - - #define MORECORE osMoreCore - - There is also a shutdown routine that should somehow be called for - cleanup upon program exit. - - #define MAX_POOL_ENTRIES 100 - #define MINIMUM_MORECORE_SIZE (64 * 1024U) - static int next_os_pool; - void *our_os_pools[MAX_POOL_ENTRIES]; - - void *osMoreCore(int size) - { - void *ptr = 0; - static void *sbrk_top = 0; - - if (size > 0) - { - if (size < MINIMUM_MORECORE_SIZE) - size = MINIMUM_MORECORE_SIZE; - if (CurrentExecutionLevel() == kTaskLevel) - ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); - if (ptr == 0) - { - return (void *) MFAIL; - } - // save ptrs so they can be freed during cleanup - our_os_pools[next_os_pool] = ptr; - next_os_pool++; - ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); - sbrk_top = (char *) ptr + size; - return ptr; - } - else if (size < 0) - { - // we don't currently support shrink behavior - return (void *) MFAIL; - } - else - { - return sbrk_top; - } - } - - // cleanup any allocated memory pools - // called as last thing before shutting down driver - - void osCleanupMem(void) - { - void **ptr; - - for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) - if (*ptr) - { - PoolDeallocate(*ptr); - *ptr = 0; - } - } - -*/ - - -/* ----------------------------------------------------------------------- -History: - v2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee) - * Always perform unlink checks unless INSECURE - * Add posix_memalign. - * Improve realloc to expand in more cases; expose realloc_in_place. - Thanks to Peter Buhr for the suggestion. - * Add footprint_limit, inspect_all, bulk_free. Thanks - to Barry Hayes and others for the suggestions. - * Internal refactorings to avoid calls while holding locks - * Use non-reentrant locks by default. Thanks to Roland McGrath - for the suggestion. - * Small fixes to mspace_destroy, reset_on_error. - * Various configuration extensions/changes. Thanks - to all who contributed these. - - V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu) - * Update Creative Commons URL - - V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) - * Use zeros instead of prev foot for is_mmapped - * Add mspace_track_large_chunks; thanks to Jean Brouwers - * Fix set_inuse in internal_realloc; thanks to Jean Brouwers - * Fix insufficient sys_alloc padding when using 16byte alignment - * Fix bad error check in mspace_footprint - * Adaptations for ptmalloc; thanks to Wolfram Gloger. - * Reentrant spin locks; thanks to Earl Chew and others - * Win32 improvements; thanks to Niall Douglas and Earl Chew - * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options - * Extension hook in malloc_state - * Various small adjustments to reduce warnings on some compilers - * Various configuration extensions/changes for more platforms. Thanks - to all who contributed these. - - V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) - * Add max_footprint functions - * Ensure all appropriate literals are size_t - * Fix conditional compilation problem for some #define settings - * Avoid concatenating segments with the one provided - in create_mspace_with_base - * Rename some variables to avoid compiler shadowing warnings - * Use explicit lock initialization. - * Better handling of sbrk interference. - * Simplify and fix segment insertion, trimming and mspace_destroy - * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x - * Thanks especially to Dennis Flanagan for help on these. - - V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) - * Fix memalign brace error. - - V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) - * Fix improper #endif nesting in C++ - * Add explicit casts needed for C++ - - V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) - * Use trees for large bins - * Support mspaces - * Use segments to unify sbrk-based and mmap-based system allocation, - removing need for emulation on most platforms without sbrk. - * Default safety checks - * Optional footer checks. Thanks to William Robertson for the idea. - * Internal code refactoring - * Incorporate suggestions and platform-specific changes. - Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, - Aaron Bachmann, Emery Berger, and others. - * Speed up non-fastbin processing enough to remove fastbins. - * Remove useless cfree() to avoid conflicts with other apps. - * Remove internal memcpy, memset. Compilers handle builtins better. - * Remove some options that no one ever used and rename others. - - V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) - * Fix malloc_state bitmap array misdeclaration - - V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) - * Allow tuning of FIRST_SORTED_BIN_SIZE - * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. - * Better detection and support for non-contiguousness of MORECORE. - Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger - * Bypass most of malloc if no frees. Thanks To Emery Berger. - * Fix freeing of old top non-contiguous chunk im sysmalloc. - * Raised default trim and map thresholds to 256K. - * Fix mmap-related #defines. Thanks to Lubos Lunak. - * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. - * Branch-free bin calculation - * Default trim and mmap thresholds now 256K. - - V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) - * Introduce independent_comalloc and independent_calloc. - Thanks to Michael Pachos for motivation and help. - * Make optional .h file available - * Allow > 2GB requests on 32bit systems. - * new WIN32 sbrk, mmap, munmap, lock code from . - Thanks also to Andreas Mueller , - and Anonymous. - * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for - helping test this.) - * memalign: check alignment arg - * realloc: don't try to shift chunks backwards, since this - leads to more fragmentation in some programs and doesn't - seem to help in any others. - * Collect all cases in malloc requiring system memory into sysmalloc - * Use mmap as backup to sbrk - * Place all internal state in malloc_state - * Introduce fastbins (although similar to 2.5.1) - * Many minor tunings and cosmetic improvements - * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK - * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS - Thanks to Tony E. Bennett and others. - * Include errno.h to support default failure action. - - V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) - * return null for negative arguments - * Added Several WIN32 cleanups from Martin C. Fong - * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' - (e.g. WIN32 platforms) - * Cleanup header file inclusion for WIN32 platforms - * Cleanup code to avoid Microsoft Visual C++ compiler complaints - * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing - memory allocation routines - * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) - * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to - usage of 'assert' in non-WIN32 code - * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to - avoid infinite loop - * Always call 'fREe()' rather than 'free()' - - V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) - * Fixed ordering problem with boundary-stamping - - V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) - * Added pvalloc, as recommended by H.J. Liu - * Added 64bit pointer support mainly from Wolfram Gloger - * Added anonymously donated WIN32 sbrk emulation - * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen - * malloc_extend_top: fix mask error that caused wastage after - foreign sbrks - * Add linux mremap support code from HJ Liu - - V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) - * Integrated most documentation with the code. - * Add support for mmap, with help from - Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Use last_remainder in more cases. - * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshhold - * Eliminate block-local decls to simplify tracing and debugging. - * Support another case of realloc via move into top - * Fix error occuring when initial sbrk_base not word-aligned. - * Rely on page size for units instead of SBRK_UNIT to - avoid surprises about sbrk alignment conventions. - * Add mallinfo, mallopt. Thanks to Raymond Nijssen - (raymond@es.ele.tue.nl) for the suggestion. - * Add `pad' argument to malloc_trim and top_pad mallopt parameter. - * More precautions for cases where other routines call sbrk, - courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Added macros etc., allowing use in linux libc from - H.J. Lu (hjl@gnu.ai.mit.edu) - * Inverted this history list - - V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) - * Re-tuned and fixed to behave more nicely with V2.6.0 changes. - * Removed all preallocation code since under current scheme - the work required to undo bad preallocations exceeds - the work saved in good cases for most test programs. - * No longer use return list or unconsolidated bins since - no scheme using them consistently outperforms those that don't - given above changes. - * Use best fit for very large chunks to prevent some worst-cases. - * Added some support for debugging - - V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) - * Removed footers when chunks are in use. Thanks to - Paul Wilson (wilson@cs.texas.edu) for the suggestion. - - V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) - * Added malloc_trim, with help from Wolfram Gloger - (wmglo@Dent.MED.Uni-Muenchen.DE). - - V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) - - V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) - * realloc: try to expand in both directions - * malloc: swap order of clean-bin strategy; - * realloc: only conditionally expand backwards - * Try not to scavenge used bins - * Use bin counts as a guide to preallocation - * Occasionally bin return list chunks in first scan - * Add a few optimizations from colin@nyx10.cs.du.edu - - V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) - * faster bin computation & slightly different binning - * merged all consolidations to one part of malloc proper - (eliminating old malloc_find_space & malloc_clean_bin) - * Scan 2 returns chunks (not just 1) - * Propagate failure in realloc if malloc returns 0 - * Add stuff to allow compilation on non-ANSI compilers - from kpv@research.att.com - - V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) - * removed potential for odd address access in prev_chunk - * removed dependency on getpagesize.h - * misc cosmetics and a bit more internal documentation - * anticosmetics: mangled names in macros to evade debugger strangeness - * tested on sparc, hp-700, dec-mips, rs6000 - with gcc & native cc (hp, dec only) allowing - Detlefs & Zorn comparison study (in SIGPLAN Notices.) - - Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) - * Based loosely on libg++-1.2X malloc. (It retains some of the overall - structure of old version, but most details differ.) - -*/ - diff --git a/src/libraries/libc/stdlib/qsort.c b/src/libraries/libc/stdlib/qsort.c deleted file mode 100644 index c908407..0000000 --- a/src/libraries/libc/stdlib/qsort.c +++ /dev/null @@ -1,124 +0,0 @@ -/* qsort( void *, size_t, size_t, int(*)( const void *, const void * ) ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -/* This implementation is taken from Paul Edward's PDPCLIB. - - Original code is credited to Raymond Gardner, Englewood CO. - Minor mods are credited to Paul Edwards. - Some reformatting and simplification done by Martin Baute. - All code is still Public Domain. -*/ - -/* Wrapper for _PDCLIB_memswp protects against multiple argument evaluation. */ -static inline void memswp( char * i, char * j, size_t size ) -{ - _PDCLIB_memswp( i, j, size ); -} - -/* For small sets, insertion sort is faster than quicksort. - T is the threshold below which insertion sort will be used. - Must be 3 or larger. -*/ -#define T 7 - -/* Macros for handling the QSort stack */ -#define PREPARE_STACK char * stack[STACKSIZE]; char * * stackptr = stack -#define PUSH( base, limit ) stackptr[0] = base; stackptr[1] = limit; stackptr += 2 -#define POP( base, limit ) stackptr -= 2; base = stackptr[0]; limit = stackptr[1] -/* TODO: Stack usage is log2( nmemb ) (minus what T shaves off the worst case). - Worst-case nmemb is platform dependent and should probably be - configured through config.h. -*/ -#define STACKSIZE 64 - -void qsort( void * base, size_t nmemb, size_t size, int (*compar)( const void *, const void * ) ) -{ - char * i; - char * j; - size_t thresh = T * size; - char * base_ = (char *)base; - char * limit = base_ + nmemb * size; - PREPARE_STACK; - - for ( ;; ) - { - if ( (size_t)( limit - base_ ) > thresh ) /* QSort for more than T elements. */ - { - /* We work from second to last - first will be pivot element. */ - i = base_ + size; - j = limit - size; - /* We swap first with middle element, then sort that with second - and last element so that eventually first element is the median - of the three - avoiding pathological pivots. - TODO: Instead of middle element, chose one randomly. - */ - memswp( ( ( ( (size_t)( limit - base_ ) ) / size ) / 2 ) * size + base_, base_, size ); - if ( compar( i, j ) > 0 ) memswp( i, j, size ); - if ( compar( base_, j ) > 0 ) memswp( base_, j, size ); - if ( compar( i, base_ ) > 0 ) memswp( i, base_, size ); - /* Now we have the median for pivot element, entering main Quicksort. */ - for ( ;; ) - { - do - { - /* move i right until *i >= pivot */ - i += size; - } while ( compar( i, base_ ) < 0 ); - do - { - /* move j left until *j <= pivot */ - j -= size; - } while ( compar( j, base_ ) > 0 ); - if ( i > j ) - { - /* break loop if pointers crossed */ - break; - } - /* else swap elements, keep scanning */ - memswp( i, j, size ); - } - /* move pivot into correct place */ - memswp( base_, j, size ); - /* larger subfile base / limit to stack, sort smaller */ - if ( j - base_ > limit - i ) - { - /* left is larger */ - PUSH( base_, j ); - base_ = i; - } - else - { - /* right is larger */ - PUSH( i, limit ); - limit = j; - } - } - else /* insertion sort for less than T elements */ - { - for ( j = base_, i = j + size; i < limit; j = i, i += size ) - { - for ( ; compar( j, j + size ) > 0; j -= size ) - { - memswp( j, j + size, size ); - if ( j == base_ ) - { - break; - } - } - } - if ( stackptr != stack ) /* if any entries on stack */ - { - POP( base_, limit ); - } - else /* else stack empty, done */ - { - break; - } - } - } -} diff --git a/src/libraries/libc/stdlib/rand.c b/src/libraries/libc/stdlib/rand.c deleted file mode 100644 index 165e026..0000000 --- a/src/libraries/libc/stdlib/rand.c +++ /dev/null @@ -1,13 +0,0 @@ -/* rand( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int rand( void ) -{ - _PDCLIB_seed = _PDCLIB_seed * 1103515245 + 12345; - return (int)( _PDCLIB_seed / 65536 ) % 32768; -} diff --git a/src/libraries/libc/stdlib/srand.c b/src/libraries/libc/stdlib/srand.c deleted file mode 100644 index 6dcf28c..0000000 --- a/src/libraries/libc/stdlib/srand.c +++ /dev/null @@ -1,12 +0,0 @@ -/* srand( unsigned int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void srand( unsigned int seed ) -{ - _PDCLIB_seed = seed; -} diff --git a/src/libraries/libc/stdlib/strtol.c b/src/libraries/libc/stdlib/strtol.c deleted file mode 100644 index 162a1e1..0000000 --- a/src/libraries/libc/stdlib/strtol.c +++ /dev/null @@ -1,27 +0,0 @@ -/* strtol( const char *, char * *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -long int strtol( const char * s, char ** endptr, int base ) -{ - long int rc; - char sign = '+'; - const char * p = _PDCLIB_strtox_prelim( s, &sign, &base ); - if ( base < 2 || base > 36 ) return 0; - if ( sign == '+' ) - { - rc = (long int)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LONG_MAX, (uintmax_t)( LONG_MAX / base ), (int)( LONG_MAX % base ), &sign ); - } - else - { - rc = (long int)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LONG_MIN, (uintmax_t)( LONG_MIN / -base ), (int)( -( LONG_MIN % base ) ), &sign ); - } - if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s; - return ( sign == '+' ) ? rc : -rc; -} diff --git a/src/libraries/libc/stdlib/strtoll.c b/src/libraries/libc/stdlib/strtoll.c deleted file mode 100644 index 64ae4c8..0000000 --- a/src/libraries/libc/stdlib/strtoll.c +++ /dev/null @@ -1,27 +0,0 @@ -/* strtoll( const char *, char * *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -long long int strtoll( const char * s, char ** endptr, int base ) -{ - long long int rc; - char sign = '+'; - const char * p = _PDCLIB_strtox_prelim( s, &sign, &base ); - if ( base < 2 || base > 36 ) return 0; - if ( sign == '+' ) - { - rc = (long long int)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LLONG_MAX, (uintmax_t)( LLONG_MAX / base ), (int)( LLONG_MAX % base ), &sign ); - } - else - { - rc = (long long int)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LLONG_MIN, (uintmax_t)( LLONG_MIN / -base ), (int)( -( LLONG_MIN % base ) ), &sign ); - } - if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s; - return ( sign == '+' ) ? rc : -rc; -} diff --git a/src/libraries/libc/stdlib/strtoul.c b/src/libraries/libc/stdlib/strtoul.c deleted file mode 100644 index 73f887d..0000000 --- a/src/libraries/libc/stdlib/strtoul.c +++ /dev/null @@ -1,20 +0,0 @@ -/* strtoul( const char *, char * *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -unsigned long int strtoul( const char * s, char ** endptr, int base ) -{ - unsigned long int rc; - char sign = '+'; - const char * p = _PDCLIB_strtox_prelim( s, &sign, &base ); - if ( base < 2 || base > 36 ) return 0; - rc = (unsigned long int)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)ULONG_MAX, (uintmax_t)( ULONG_MAX / base ), (int)( ULONG_MAX % base ), &sign ); - if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s; - return ( sign == '+' ) ? rc : -rc; -} diff --git a/src/libraries/libc/stdlib/strtoull.c b/src/libraries/libc/stdlib/strtoull.c deleted file mode 100644 index 258f886..0000000 --- a/src/libraries/libc/stdlib/strtoull.c +++ /dev/null @@ -1,20 +0,0 @@ -/* strtoull( const char *, char * *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include - -unsigned long long int strtoull( const char * s, char ** endptr, int base ) -{ - unsigned long long int rc; - char sign = '+'; - const char * p = _PDCLIB_strtox_prelim( s, &sign, &base ); - if ( base < 2 || base > 36 ) return 0; - rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)ULLONG_MAX, (uintmax_t)( ULLONG_MAX / base ), (int)( ULLONG_MAX % base ), &sign ); - if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s; - return ( sign == '+' ) ? rc : -rc; -} diff --git a/src/libraries/libc/stdlib/system.c b/src/libraries/libc/stdlib/system.c deleted file mode 100644 index 8102c47..0000000 --- a/src/libraries/libc/stdlib/system.c +++ /dev/null @@ -1,34 +0,0 @@ -/* system( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -/* This is an example implementation of system() fit for use with POSIX kernels. -*/ - -extern int fork( void ); -extern int execve( const char * filename, char * const argv[], char * const envp[] ); -extern int wait( int * status ); - -int system( const char * string ) -{ - const char * argv[] = { "sh", "-c", NULL, NULL }; - argv[2] = string; - if ( string != NULL ) - { - int pid = fork(); - if ( pid == 0 ) - { - execve( "/bin/sh", (char * * const)argv, NULL ); - } - else if ( pid > 0 ) - { - while( wait( NULL ) != pid ); - } - } - return -1; -} - diff --git a/src/libraries/libc/stdnoreturn.h b/src/libraries/libc/stdnoreturn.h deleted file mode 100644 index c18059b..0000000 --- a/src/libraries/libc/stdnoreturn.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -/* _Noreturn - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#define noreturn _Noreturn diff --git a/src/libraries/libc/string.h b/src/libraries/libc/string.h deleted file mode 100644 index ac7dd4a..0000000 --- a/src/libraries/libc/string.h +++ /dev/null @@ -1,178 +0,0 @@ -#pragma once -/* String handling - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/cpp.h" -#include "j6libc/int.h" -#include "j6libc/null.h" -#include "j6libc/size_t.h" - -CPP_CHECK_BEGIN - -/* String function conventions */ - -/* - In any of the following functions taking a size_t n to specify the length of - an array or size of a memory region, n may be 0, but the pointer arguments to - the call shall still be valid unless otherwise stated. -*/ - -/* Copying functions */ - -/* Copy a number of n characters from the memory area pointed to by s2 to the - area pointed to by s1. If the two areas overlap, behaviour is undefined. - Returns the value of s1. -*/ -void * memcpy( void * restrict s1, const void * restrict s2, size_t n ); - -/* Copy a number of n characters from the memory area pointed to by s2 to the - area pointed to by s1. The two areas may overlap. - Returns the value of s1. -*/ -void * memmove( void * restrict s1, const void * restrict s2, size_t n ); - -/* Copy the character array s2 (including terminating '\0' byte) into the - character array s1. - Returns the value of s1. -*/ -char * strcpy( char * restrict s1, const char * restrict s2 ); - -/* Copy a maximum of n characters from the character array s2 into the character - array s1. If s2 is shorter than n characters, '\0' bytes will be appended to - the copy in s1 until n characters have been written. If s2 is longer than n - characters, NO terminating '\0' will be written to s1. If the arrays overlap, - behaviour is undefined. - Returns the value of s1. -*/ -char * strncpy( char * restrict s1, const char * restrict s2, size_t n ); - -/* Concatenation functions */ - -/* Append the contents of the character array s2 (including terminating '\0') to - the character array s1 (first character of s2 overwriting the '\0' of s1). If - the arrays overlap, behaviour is undefined. - Returns the value of s1. -*/ -char * strcat( char * restrict s1, const char * restrict s2 ); - -/* Append a maximum of n characters from the character array s1 to the character - array s1 (first character of s2 overwriting the '\0' of s1). A terminating - '\0' is ALWAYS appended, even if the full n characters have already been - written. If the arrays overlap, behaviour is undefined. - Returns the value of s1. -*/ -char * strncat( char * restrict s1, const char * restrict s2, size_t n ); - -/* Comparison functions */ - -/* Compare the first n characters of the memory areas pointed to by s1 and s2. - Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if - s1 > s2. -*/ -int memcmp( const void * s1, const void * s2, size_t n ); - -/* Compare the character arrays s1 and s2. - Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if - s1 > s2. -*/ -int strcmp( const char * s1, const char * s2 ); - -/* Compare the character arrays s1 and s2, interpreted as specified by the - LC_COLLATE category of the current locale. - Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if - s1 > s2. - TODO: Currently a dummy wrapper for strcmp() as PDCLib does not yet support - locales. -*/ -int strcoll( const char * s1, const char * s2 ); - -/* Compare no more than the first n characters of the character arrays s1 and - s2. - Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if - s1 > s2. -*/ -int strncmp( const char * s1, const char * s2, size_t n ); - -/* Transform the character array s2 as appropriate for the LC_COLLATE setting of - the current locale. If length of resulting string is less than n, store it in - the character array pointed to by s1. Return the length of the resulting - string. -*/ -size_t strxfrm( char * restrict s1, const char * restrict s2, size_t n ); - -/* Search functions */ - -/* Search the first n characters in the memory area pointed to by s for the - character c (interpreted as unsigned char). - Returns a pointer to the first instance found, or NULL. -*/ -void * memchr( const void * s, int c, size_t n ); - -/* Search the character array s (including terminating '\0') for the character c - (interpreted as char). - Returns a pointer to the first instance found, or NULL. -*/ -char * strchr( const char * s, int c ); - -/* Determine the length of the initial substring of character array s1 which - consists only of characters not from the character array s2. - Returns the length of that substring. -*/ -size_t strcspn( const char * s1, const char * s2 ); - -/* Search the character array s1 for any character from the character array s2. - Returns a pointer to the first occurrence, or NULL. -*/ -char * strpbrk( const char * s1, const char * s2 ); - -/* Search the character array s (including terminating '\0') for the character c - (interpreted as char). - Returns a pointer to the last instance found, or NULL. -*/ -char * strrchr( const char * s, int c ); - -/* Determine the length of the initial substring of character array s1 which - consists only of characters from the character array s2. - Returns the length of that substring. -*/ -size_t strspn( const char * s1, const char * s2 ); - -/* Search the character array s1 for the substring in character array s2. - Returns a pointer to that sbstring, or NULL. If s2 is of length zero, - returns s1. -*/ -char * strstr( const char * s1, const char * s2 ); - -/* In a series of subsequent calls, parse a C string into tokens. - On the first call to strtok(), the first argument is a pointer to the to-be- - parsed C string. On subsequent calls, the first argument is NULL unless you - want to start parsing a new string. s2 holds an array of seperator characters - which can differ from call to call. Leading seperators are skipped, the first - trailing seperator overwritten with '\0'. - Returns a pointer to the next token. - WARNING: This function uses static storage, and as such is not reentrant. -*/ -char * strtok( char * restrict s1, const char * restrict s2 ); - -/* Miscellaneous functions */ - -/* Write the character c (interpreted as unsigned char) to the first n - characters of the memory area pointed to by s. - Returns s. -*/ -void * memset( void * s, int c, size_t n ); - -/* Map an error number to a (locale-specific) error message string. Error - numbers are typically errno values, but any number is mapped to a message. - TODO: PDCLib does not yet support locales. -*/ -char * strerror( int errnum ); - -/* Returns the length of the string s (excluding terminating '\0'). -*/ -size_t strlen( const char * s ); - -CPP_CHECK_END diff --git a/src/libraries/libc/string/memchr.c b/src/libraries/libc/string/memchr.c deleted file mode 100644 index efb84fb..0000000 --- a/src/libraries/libc/string/memchr.c +++ /dev/null @@ -1,21 +0,0 @@ -/* memchr( const void *, int, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void * memchr( const void * s, int c, size_t n ) -{ - const unsigned char * p = (const unsigned char *) s; - while ( n-- ) - { - if ( *p == (unsigned char) c ) - { - return (void *) p; - } - ++p; - } - return NULL; -} diff --git a/src/libraries/libc/string/memcmp.c b/src/libraries/libc/string/memcmp.c deleted file mode 100644 index 4076140..0000000 --- a/src/libraries/libc/string/memcmp.c +++ /dev/null @@ -1,23 +0,0 @@ -/* memcmp( const void *, const void *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int memcmp( const void * s1, const void * s2, size_t n ) -{ - const unsigned char * p1 = (const unsigned char *) s1; - const unsigned char * p2 = (const unsigned char *) s2; - while ( n-- ) - { - if ( *p1 != *p2 ) - { - return *p1 - *p2; - } - ++p1; - ++p2; - } - return 0; -} diff --git a/src/libraries/libc/string/memcpy.c b/src/libraries/libc/string/memcpy.c deleted file mode 100644 index ed1cda9..0000000 --- a/src/libraries/libc/string/memcpy.c +++ /dev/null @@ -1,33 +0,0 @@ -/* memcpy( void *, const void *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void * memcpy( void * restrict s1, const void * restrict s2, size_t n ) -{ - char * dest = (char *) s1; - const char * src = (const char *) s2; - - if (((uintptr_t)src & 7) == ((uintptr_t)dest & 7)) { - while (((uintptr_t)src & 7) && n--) - *dest++ = *src++; - - const uint64_t *srcq = (const uint64_t*)src; - uint64_t *destq = (uint64_t*)dest; - while (n >= 8) { - *destq++ = *srcq++; - n -= 8; - } - - src = (const char*)srcq; - dest = (char*)destq; - } - - while (n--) - *dest++ = *src++; - - return s1; -} diff --git a/src/libraries/libc/string/memmove.c b/src/libraries/libc/string/memmove.c deleted file mode 100644 index ffe1aa8..0000000 --- a/src/libraries/libc/string/memmove.c +++ /dev/null @@ -1,30 +0,0 @@ -/* memmove( void *, const void *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void * memmove( void * s1, const void * s2, size_t n ) -{ - char * dest = (char *) s1; - const char * src = (const char *) s2; - if ( dest <= src ) - { - while ( n-- ) - { - *dest++ = *src++; - } - } - else - { - src += n; - dest += n; - while ( n-- ) - { - *--dest = *--src; - } - } - return s1; -} diff --git a/src/libraries/libc/string/memset.c b/src/libraries/libc/string/memset.c deleted file mode 100644 index 9a03985..0000000 --- a/src/libraries/libc/string/memset.c +++ /dev/null @@ -1,17 +0,0 @@ -/* memset( void *, int, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -void * memset( void * s, int c, size_t n ) -{ - unsigned char * p = (unsigned char *) s; - while ( n-- ) - { - *p++ = (unsigned char) c; - } - return s; -} diff --git a/src/libraries/libc/string/strcat.c b/src/libraries/libc/string/strcat.c deleted file mode 100644 index b5b3c30..0000000 --- a/src/libraries/libc/string/strcat.c +++ /dev/null @@ -1,18 +0,0 @@ -/* strcat( char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strcat( char * restrict s1, const char * restrict s2 ) -{ - char * rc = s1; - if ( *s1 ) - { - while ( *++s1 ); - } - while ( (*s1++ = *s2++) ); - return rc; -} diff --git a/src/libraries/libc/string/strchr.c b/src/libraries/libc/string/strchr.c deleted file mode 100644 index 115d970..0000000 --- a/src/libraries/libc/string/strchr.c +++ /dev/null @@ -1,19 +0,0 @@ -/* strchr( const char *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strchr( const char * s, int c ) -{ - do - { - if ( *s == (char) c ) - { - return (char *) s; - } - } while ( *s++ ); - return NULL; -} diff --git a/src/libraries/libc/string/strcmp.c b/src/libraries/libc/string/strcmp.c deleted file mode 100644 index bd7b3fc..0000000 --- a/src/libraries/libc/string/strcmp.c +++ /dev/null @@ -1,17 +0,0 @@ -/* strcmp( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int strcmp( const char * s1, const char * s2 ) -{ - while ( ( *s1 ) && ( *s1 == *s2 ) ) - { - ++s1; - ++s2; - } - return ( *(unsigned char *)s1 - *(unsigned char *)s2 ); -} diff --git a/src/libraries/libc/string/strcoll.c b/src/libraries/libc/string/strcoll.c deleted file mode 100644 index 2b8ec4f..0000000 --- a/src/libraries/libc/string/strcoll.c +++ /dev/null @@ -1,23 +0,0 @@ -/* strcoll( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -int strcoll( const char * s1, const char * s2 ) -{ - return strcmp( s1, s2 ); - - /* FIXME: This code became invalid when we started doing *real* locales... */ - /* - while ( ( *s1 ) && ( _PDCLIB_lc_ctype[(unsigned char)*s1].collation == _PDCLIB_lc_ctype[(unsigned char)*s2].collation ) ) - { - ++s1; - ++s2; - } - return ( _PDCLIB_lc_ctype[(unsigned char)*s1].collation == _PDCLIB_lc_ctype[(unsigned char)*s2].collation ); - */ -} diff --git a/src/libraries/libc/string/strcpy.c b/src/libraries/libc/string/strcpy.c deleted file mode 100644 index 40428fb..0000000 --- a/src/libraries/libc/string/strcpy.c +++ /dev/null @@ -1,14 +0,0 @@ -/* strcpy( char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strcpy( char * restrict s1, const char * restrict s2 ) -{ - char * rc = s1; - while ( ( *s1++ = *s2++ ) ); - return rc; -} diff --git a/src/libraries/libc/string/strcspn.c b/src/libraries/libc/string/strcspn.c deleted file mode 100644 index 2f067da..0000000 --- a/src/libraries/libc/string/strcspn.c +++ /dev/null @@ -1,26 +0,0 @@ -/* strcspn( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -size_t strcspn( const char * s1, const char * s2 ) -{ - size_t len = 0; - const char * p; - while ( s1[len] ) - { - p = s2; - while ( *p ) - { - if ( s1[len] == *p++ ) - { - return len; - } - } - ++len; - } - return len; -} diff --git a/src/libraries/libc/string/strerror.c b/src/libraries/libc/string/strerror.c deleted file mode 100644 index 2c4a617..0000000 --- a/src/libraries/libc/string/strerror.c +++ /dev/null @@ -1,21 +0,0 @@ -/* strerror( int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -/* TODO: Doing this via a static array is not the way to do it. */ -char * strerror( int errnum ) -{ - if ( errnum >= _PDCLIB_ERRNO_MAX ) - { - return (char *)"Unknown error"; - } - else - { - return _PDCLIB_lc_messages.errno_texts[errnum]; - } -} diff --git a/src/libraries/libc/string/strlen.c b/src/libraries/libc/string/strlen.c deleted file mode 100644 index f21877b..0000000 --- a/src/libraries/libc/string/strlen.c +++ /dev/null @@ -1,17 +0,0 @@ -/* strlen( const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -size_t strlen( const char * s ) -{ - size_t rc = 0; - while ( s[rc] ) - { - ++rc; - } - return rc; -} diff --git a/src/libraries/libc/string/strncat.c b/src/libraries/libc/string/strncat.c deleted file mode 100644 index 5c7c3d5..0000000 --- a/src/libraries/libc/string/strncat.c +++ /dev/null @@ -1,25 +0,0 @@ -/* strncat( char *, const char *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strncat( char * restrict s1, const char * restrict s2, size_t n ) -{ - char * rc = s1; - while ( *s1 ) - { - ++s1; - } - while ( n && ( *s1++ = *s2++ ) ) - { - --n; - } - if ( n == 0 ) - { - *s1 = '\0'; - } - return rc; -} diff --git a/src/libraries/libc/string/strncmp.c b/src/libraries/libc/string/strncmp.c deleted file mode 100644 index 99fe338..0000000 --- a/src/libraries/libc/string/strncmp.c +++ /dev/null @@ -1,25 +0,0 @@ -/* strncmp( const char *, const char *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int strncmp( const char * s1, const char * s2, size_t n ) -{ - while ( n && *s1 && ( *s1 == *s2 ) ) - { - ++s1; - ++s2; - --n; - } - if ( n == 0 ) - { - return 0; - } - else - { - return ( *(unsigned char *)s1 - *(unsigned char *)s2 ); - } -} diff --git a/src/libraries/libc/string/strncpy.c b/src/libraries/libc/string/strncpy.c deleted file mode 100644 index 8b6350c..0000000 --- a/src/libraries/libc/string/strncpy.c +++ /dev/null @@ -1,26 +0,0 @@ -/* strncpy( char *, const char *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strncpy( char * restrict s1, const char * restrict s2, size_t n ) -{ - char * rc = s1; - while ( n && ( *s1++ = *s2++ ) ) - { - /* Cannot do "n--" in the conditional as size_t is unsigned and we have - to check it again for >0 in the next loop below, so we must not risk - underflow. - */ - --n; - } - /* Checking against 1 as we missed the last --n in the loop above. */ - while ( n-- > 1 ) - { - *s1++ = '\0'; - } - return rc; -} diff --git a/src/libraries/libc/string/strpbrk.c b/src/libraries/libc/string/strpbrk.c deleted file mode 100644 index 853f398..0000000 --- a/src/libraries/libc/string/strpbrk.c +++ /dev/null @@ -1,26 +0,0 @@ -/* strpbrk( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strpbrk( const char * s1, const char * s2 ) -{ - const char * p1 = s1; - const char * p2; - while ( *p1 ) - { - p2 = s2; - while ( *p2 ) - { - if ( *p1 == *p2++ ) - { - return (char *) p1; - } - } - ++p1; - } - return NULL; -} diff --git a/src/libraries/libc/string/strrchr.c b/src/libraries/libc/string/strrchr.c deleted file mode 100644 index 5bc5183..0000000 --- a/src/libraries/libc/string/strrchr.c +++ /dev/null @@ -1,21 +0,0 @@ -/* strrchr( const char *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strrchr( const char * s, int c ) -{ - size_t i = 0; - while ( s[i++] ); - do - { - if ( s[--i] == (char) c ) - { - return (char *) s + i; - } - } while ( i ); - return NULL; -} diff --git a/src/libraries/libc/string/strspn.c b/src/libraries/libc/string/strspn.c deleted file mode 100644 index 37a2eb2..0000000 --- a/src/libraries/libc/string/strspn.c +++ /dev/null @@ -1,31 +0,0 @@ -/* strspn( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -size_t strspn( const char * s1, const char * s2 ) -{ - size_t len = 0; - const char * p; - while ( s1[ len ] ) - { - p = s2; - while ( *p ) - { - if ( s1[len] == *p ) - { - break; - } - ++p; - } - if ( ! *p ) - { - return len; - } - ++len; - } - return len; -} diff --git a/src/libraries/libc/string/strstr.c b/src/libraries/libc/string/strstr.c deleted file mode 100644 index 78f0e5f..0000000 --- a/src/libraries/libc/string/strstr.c +++ /dev/null @@ -1,29 +0,0 @@ -/* strstr( const char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strstr( const char * s1, const char * s2 ) -{ - const char * p1 = s1; - const char * p2; - while ( *s1 ) - { - p2 = s2; - while ( *p2 && ( *p1 == *p2 ) ) - { - ++p1; - ++p2; - } - if ( ! *p2 ) - { - return (char *) s1; - } - ++s1; - p1 = s1; - } - return NULL; -} diff --git a/src/libraries/libc/string/strtok.c b/src/libraries/libc/string/strtok.c deleted file mode 100644 index d8864c4..0000000 --- a/src/libraries/libc/string/strtok.c +++ /dev/null @@ -1,69 +0,0 @@ -/* strtok( char *, const char * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * strtok( char * restrict s1, const char * restrict s2 ) -{ - static char * tmp = NULL; - const char * p = s2; - - if ( s1 != NULL ) - { - /* new string */ - tmp = s1; - } - else - { - /* old string continued */ - if ( tmp == NULL ) - { - /* No old string, no new string, nothing to do */ - return NULL; - } - s1 = tmp; - } - - /* skipping leading s2 characters */ - while ( *p && *s1 ) - { - if ( *s1 == *p ) - { - /* found seperator; skip and start over */ - ++s1; - p = s2; - continue; - } - ++p; - } - - if ( ! *s1 ) - { - /* no more to parse */ - return ( tmp = NULL ); - } - - /* skipping non-s2 characters */ - tmp = s1; - while ( *tmp ) - { - p = s2; - while ( *p ) - { - if ( *tmp == *p++ ) - { - /* found seperator; overwrite with '\0', position tmp, return */ - *tmp++ = '\0'; - return s1; - } - } - ++tmp; - } - - /* parsed to end of string */ - tmp = NULL; - return s1; -} diff --git a/src/libraries/libc/string/strxfrm.c b/src/libraries/libc/string/strxfrm.c deleted file mode 100644 index 83821f1..0000000 --- a/src/libraries/libc/string/strxfrm.c +++ /dev/null @@ -1,23 +0,0 @@ -/* strxfrm( char *, const char *, size_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include - -size_t strxfrm( char * restrict s1, const char * restrict s2, size_t n ) -{ - size_t len = strlen( s2 ); - if ( len < n ) - { - /* Cannot use strncpy() here as the filling of s1 with '\0' is not part - of the spec. - */ - /* FIXME: The code below became invalid when we started doing *real* locales... */ - /*while ( n-- && ( *s1++ = _PDCLIB_lc_collate[(unsigned char)*s2++].collation ) );*/ - while ( n-- && ( *s1++ = (unsigned char)*s2++ ) ); - } - return len; -} diff --git a/src/libraries/libc/time.h b/src/libraries/libc/time.h deleted file mode 100644 index 9680a64..0000000 --- a/src/libraries/libc/time.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once -/* Date and time - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/cpp.h" -#include "j6libc/int.h" -#include "j6libc/null.h" -#include "j6libc/size_t.h" - -CPP_CHECK_BEGIN - -/* These are defined to be "real types capable of representing types", with - "range and precision of times representable in [them being] implementation- - defined". - As part of struct timespec (see below), time_t is further defined as "a - linear count of seconds", with potentially different semantics from a - "normal" time_t. - For sake of simplicity, we used just that (common) definition of "seconds - since epoch" as integer. -*/ -typedef _PDCLIB_time_t time_t; -typedef _PDCLIB_clock_t clock_t; - -#define CLOCKS_PER_SEC _PDCLIB_CLOCKS_PER_SEC -#define TIME_UTC _PDCLIB_TIME_UTC - -struct timespec -{ - time_t tv_sec; - long tv_nsec; -}; - -struct tm -{ - int tm_sec; /* 0-60 */ - int tm_min; /* 0-59 */ - int tm_hour; /* 0-23 */ - int tm_mday; /* 1-31 */ - int tm_mon; /* 0-11 */ - int tm_year; /* years since 1900 */ - int tm_wday; /* 0-6 */ - int tm_yday; /* 0-365 */ - int tm_isdst; /* >0 DST, 0 no DST, <0 information unavailable */ -}; - -/* Returns the number of "clocks" in processor time since the invocation - of the program. Divide by CLOCKS_PER_SEC to get the value in seconds. - Returns -1 if the value cannot be represented in the return type or is - not available. -*/ -clock_t clock( void ); - -/* Returns the difference between two calendar times in seconds. */ -double difftime( time_t time1, time_t time0 ); - -/* Normalizes the values in the broken-down time pointed to by timeptr. - Returns the calender time specified by the broken-down time. -*/ -time_t mktime( struct tm * timeptr ); - -/* Returns the current calender time. If timer is not a NULL pointer, stores - the current calender time at that address as well. -*/ -time_t time( time_t * timer ); - -/* Sets the interval pointed to by ts to the current calender time, based - on the specified base. - Returns base, if successful, otherwise zero. -*/ -int timespec_get( struct timespec * ts, int base ); - -/* Converts the broken-down time pointed to by timeptr into a string in the - form "Sun Sep 16 01:03:52 1973\n\0". -*/ -char * asctime( const struct tm * timeptr ); - -/* Equivalent to asctime( localtime( timer ) ). */ -char * ctime( const time_t * timer ); - -/* Converts the calender time pointed to by timer into a broken-down time - expressed as UTC. - Returns a pointer to the broken-down time, or a NULL pointer if it - cannot be represented. -*/ -struct tm * gmtime( const time_t * timer ); - -/* Converts the calender time pointed to by timer into a broken-down time - expressed as local time. - Returns a pointer to the broken-down time, or a NULL pointer if if - cannot be represented. -*/ -struct tm * localtime( const time_t * timer ); - -/* Writes the broken-down time pointed to by timeptr into the character - array pointed to by s. The string pointed to by format controls the - exact output. No more than maxsize charactrs will be written. - Returns the number of characters written (excluding the terminating - null character), or zero on failure. -*/ -size_t strftime( char * restrict s, size_t maxsize, const char * restrict format, const struct tm * restrict timeptr ); - -CPP_CHECK_END diff --git a/src/libraries/libc/time/asctime.c b/src/libraries/libc/time/asctime.c deleted file mode 100644 index 382f6ff..0000000 --- a/src/libraries/libc/time/asctime.c +++ /dev/null @@ -1,12 +0,0 @@ -/* asctime( const struct tm * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * asctime( const struct tm * timeptr ) -{ - return NULL; -} diff --git a/src/libraries/libc/time/clock.c b/src/libraries/libc/time/clock.c deleted file mode 100644 index c911aa5..0000000 --- a/src/libraries/libc/time/clock.c +++ /dev/null @@ -1,12 +0,0 @@ -/* clock( void ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -clock_t clock( void ) -{ - return -1; -} diff --git a/src/libraries/libc/time/ctime.c b/src/libraries/libc/time/ctime.c deleted file mode 100644 index cd47230..0000000 --- a/src/libraries/libc/time/ctime.c +++ /dev/null @@ -1,12 +0,0 @@ -/* ctime( const time_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -char * ctime( const time_t * timer ) -{ - return NULL; -} diff --git a/src/libraries/libc/time/difftime.c b/src/libraries/libc/time/difftime.c deleted file mode 100644 index 21149ab..0000000 --- a/src/libraries/libc/time/difftime.c +++ /dev/null @@ -1,56 +0,0 @@ -/* difftime( time_t, time_t ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef DISABLE_SSE -double difftime( time_t time1, time_t time0 ) -{ - /* If we want to avoid rounding errors and overflows, we need to be - careful with the exact type of time_t being unknown to us. - The code below is based on tzcode's difftime.c, which is in the - public domain, so clarified as of 1996-06-05 by Arthur David Olson. - */ - - /* If double is large enough, simply covert and substract - (assuming that the larger type has more precision). - */ - if ( sizeof( time_t ) < sizeof( double ) ) - { - return (double)time1 - (double)time0; - } - - /* The difference of two unsigned values cannot overflow if the - minuend is greater or equal to the subtrahend. - */ - if ( ! _PDCLIB_TYPE_SIGNED( time_t ) ) - { - return ( time1 >= time0 ) ? (double)( time1 - time0 ) : -(double)( time0 - time1 ); - } - - /* Use uintmax_t if wide enough. */ - if ( sizeof( time_t ) <= sizeof( uintmax_t ) ) - { - uintmax_t t1 = time1, t0 = time0; - return ( time1 >= time0 ) ? t1 - t0 : -(double)( t0 - t1 ); - } - - /* If both times have the same sign, their difference cannot overflow. */ - if ( ( time1 < 0 ) == ( time0 < 0 ) ) - { - return time1 - time0; - } - - /* The times have opposite signs, and uintmax_t is too narrow. - This suffers from double rounding; attempt to lessen that - by using long double temporaries. - */ - { - long double t1 = time1, t0 = time0; - return t1 - t0; - } -} -#endif diff --git a/src/libraries/libc/time/gmtime.c b/src/libraries/libc/time/gmtime.c deleted file mode 100644 index 34a831a..0000000 --- a/src/libraries/libc/time/gmtime.c +++ /dev/null @@ -1,12 +0,0 @@ -/* gmtime( const time_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -struct tm * gmtime( const time_t * timer ) -{ - return NULL; -} diff --git a/src/libraries/libc/time/localtime.c b/src/libraries/libc/time/localtime.c deleted file mode 100644 index f405621..0000000 --- a/src/libraries/libc/time/localtime.c +++ /dev/null @@ -1,12 +0,0 @@ -/* localtime( const time_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -struct tm * localtime( const time_t * timer ) -{ - return NULL; -} diff --git a/src/libraries/libc/time/mktime.c b/src/libraries/libc/time/mktime.c deleted file mode 100644 index bfaef40..0000000 --- a/src/libraries/libc/time/mktime.c +++ /dev/null @@ -1,12 +0,0 @@ -/* mktime( struct tm * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -time_t mktime( struct tm * timeptr ) -{ - return -1; -} diff --git a/src/libraries/libc/time/strftime.c b/src/libraries/libc/time/strftime.c deleted file mode 100644 index b96be49..0000000 --- a/src/libraries/libc/time/strftime.c +++ /dev/null @@ -1,582 +0,0 @@ -/* strftime( char * restrict, size_t, const char * restrict, const struct tm * restrict ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#include -#include -#include - -/* TODO: Alternative representations / numerals not supported. Multibyte support missing. */ - -/* This implementation's code is highly repetitive, but I did not really - care for putting it into a number of macros / helper functions. -*/ - -enum wstart_t -{ - E_SUNDAY = 0, - E_MONDAY = 1, - E_ISO_WEEK, - E_ISO_YEAR -}; - -#include - -static int week_calc( const struct tm * timeptr, int wtype ) -{ - int wday; - int bias; - int week; - - if ( wtype <= E_MONDAY ) - { - /* Simple -- first week starting with E_SUNDAY / E_MONDAY, - days before that are week 0. - */ - div_t weeks = div( timeptr->tm_yday, 7 ); - wday = ( timeptr->tm_wday + 7 - wtype ) % 7; - if ( weeks.rem >= wday ) - { - ++weeks.quot; - } - return weeks.quot; - } - - /* calculating ISO week; relies on Sunday == 7 */ - wday = timeptr->tm_wday; - if ( wday == 0 ) - { - wday = 7; - } - /* https://en.wikipedia.org/wiki/ISO_week_date */ - week = ( timeptr->tm_yday - wday + 11 ) / 7; - if ( week == 53 ) - { - /* date *may* belong to the *next* year, if: - * it is 31.12. and Monday - Wednesday - * it is 30.12. and Monday - Tuesday - * it is 29.12. and Monday - We can safely assume December... - */ - if ( ( timeptr->tm_yday - wday - _PDCLIB_is_leap( timeptr->tm_year ) ) > 360 ) - { - week = 1; - } - } - else if ( week == 0 ) - { - /* date *does* belong to *previous* year, - i.e. has week 52 *unless*... - * current year started on a Friday, or - * previous year is leap and this year - started on a Saturday. - */ - int firstday = timeptr->tm_wday - ( timeptr->tm_yday % 7 ); - if ( firstday < 0 ) - { - firstday += 7; - } - if ( ( firstday == 5 ) || ( _PDCLIB_is_leap( timeptr->tm_year - 1 ) && firstday == 6 ) ) - { - week = 53; - } - else - { - week = 52; - } - } - if ( wtype == E_ISO_WEEK ) - { - return week; - } - - /* E_ISO_YEAR -- determine the "week-based year" */ - bias = 0; - if ( week >= 52 && timeptr->tm_mon == 0 ) - { - --bias; - } - else if ( week == 1 && timeptr->tm_mon == 11 ) - { - ++bias; - } - return timeptr->tm_year + 1900 + bias; -} - -/* Assuming presence of s, rc, maxsize. - Checks index for valid range, target buffer for sufficient remaining - capacity, and copies the locale-specific string (or "?" if index out - of range). Returns with zero if buffer capacity insufficient. -*/ -#define SPRINTSTR( array, index, max ) \ - { \ - int ind = (index); \ - const char * str = "?"; \ - size_t len; \ - if ( ind >= 0 && ind <= max ) \ - { \ - str = array[ ind ]; \ - } \ - len = strlen( str ); \ - if ( rc < ( maxsize - len ) ) \ - { \ - strcpy( s + rc, str ); \ - rc += len; \ - } \ - else \ - { \ - return 0; \ - } \ - } - -#define SPRINTREC( format ) \ - { \ - size_t count = strftime( s + rc, maxsize - rc, format, timeptr ); \ - if ( count == 0 ) \ - { \ - return 0; \ - } \ - else \ - { \ - rc += count; \ - } \ - } - -size_t strftime( char * restrict s, size_t maxsize, const char * restrict format, const struct tm * restrict timeptr ) -{ - size_t rc = 0; - - while ( rc < maxsize ) - { - if ( *format != '%' ) - { - if ( ( s[rc] = *format++ ) == '\0' ) - { - return rc; - } - else - { - ++rc; - } - } - else - { - /* char flag = 0; */ - switch ( *++format ) - { - case 'E': - case 'O': - /* flag = *format++; */ - break; - default: - /* EMPTY */ - break; - } - switch( *format++ ) - { - case 'a': - { - /* tm_wday abbreviated */ - SPRINTSTR( _PDCLIB_lc_time.day_name_abbr, timeptr->tm_wday, 6 ); - break; - } - case 'A': - { - /* tm_wday full */ - SPRINTSTR( _PDCLIB_lc_time.day_name_full, timeptr->tm_wday, 6 ); - break; - } - case 'b': - case 'h': - { - /* tm_mon abbreviated */ - SPRINTSTR( _PDCLIB_lc_time.month_name_abbr, timeptr->tm_mon, 11 ); - break; - } - case 'B': - { - /* tm_mon full */ - SPRINTSTR( _PDCLIB_lc_time.month_name_full, timeptr->tm_mon, 11 ); - break; - } - case 'c': - { - /* locale's date / time representation, %a %b %e %T %Y for C locale */ - /* 'E' for locale's alternative representation */ - SPRINTREC( _PDCLIB_lc_time.date_time_format ); - break; - } - case 'C': - { - /* tm_year divided by 100, truncated to decimal (00-99) */ - /* 'E' for base year (period) in locale's alternative representation */ - if ( rc < ( maxsize - 2 ) ) - { - div_t period = div( ( ( timeptr->tm_year + 1900 ) / 100 ), 10 ); - s[rc++] = '0' + period.quot; - s[rc++] = '0' + period.rem; - } - else - { - return 0; - } - break; - } - case 'd': - { - /* tm_mday as decimal (01-31) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t day = div( timeptr->tm_mday, 10 ); - s[rc++] = '0' + day.quot; - s[rc++] = '0' + day.rem; - } - else - { - return 0; - } - break; - } - case 'D': - { - /* %m/%d/%y */ - SPRINTREC( "%m/%d/%y" ); - break; - } - case 'e': - { - /* tm_mday as decimal ( 1-31) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t day = div( timeptr->tm_mday, 10 ); - s[rc++] = ( day.quot > 0 ) ? '0' + day.quot : ' '; - s[rc++] = '0' + day.rem; - } - else - { - return 0; - } - break; - } - case 'F': - { - /* %Y-%m-%d */ - SPRINTREC( "%Y-%m-%d" ); - break; - } - case 'g': - { - /* last 2 digits of the week-based year as decimal (00-99) */ - if ( rc < ( maxsize - 2 ) ) - { - div_t year = div( week_calc( timeptr, E_ISO_YEAR ) % 100, 10 ); - s[rc++] = '0' + year.quot; - s[rc++] = '0' + year.rem; - } - else - { - return 0; - } - break; - } - case 'G': - { - /* week-based year as decimal (e.g. 1997) */ - if ( rc < ( maxsize - 4 ) ) - { - int year = week_calc( timeptr, E_ISO_YEAR ); - int i; - for ( i = 3; i >= 0; --i ) - { - div_t digit = div( year, 10 ); - s[ rc + i ] = '0' + digit.rem; - year = digit.quot; - } - - rc += 4; - } - else - { - return 0; - } - break; - } - case 'H': - { - /* tm_hour as 24h decimal (00-23) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t hour = div( timeptr->tm_hour, 10 ); - s[rc++] = '0' + hour.quot; - s[rc++] = '0' + hour.rem; - } - else - { - return 0; - } - break; - } - case 'I': - { - /* tm_hour as 12h decimal (01-12) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t hour = div( ( timeptr->tm_hour + 11 ) % 12 + 1, 10 ); - s[rc++] = '0' + hour.quot; - s[rc++] = '0' + hour.rem; - } - else - { - return 0; - } - break; - } - case 'j': - { - /* tm_yday as decimal (001-366) */ - if ( rc < ( maxsize - 3 ) ) - { - div_t yday = div( timeptr->tm_yday + 1, 100 ); - s[rc++] = '0' + yday.quot; - s[rc++] = '0' + yday.rem / 10; - s[rc++] = '0' + yday.rem % 10; - } - else - { - return 0; - } - break; - } - case 'm': - { - /* tm_mon as decimal (01-12) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t mon = div( timeptr->tm_mon + 1, 10 ); - s[rc++] = '0' + mon.quot; - s[rc++] = '0' + mon.rem; - } - else - { - return 0; - } - break; - } - case 'M': - { - /* tm_min as decimal (00-59) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t min = div( timeptr->tm_min, 10 ); - s[rc++] = '0' + min.quot; - s[rc++] = '0' + min.rem; - } - else - { - return 0; - } - break; - } - case 'n': - { - /* newline */ - s[rc++] = '\n'; - break; - } - case 'p': - { - /* tm_hour locale's AM/PM designations */ - SPRINTSTR( _PDCLIB_lc_time.am_pm, timeptr->tm_hour > 11, 1 ); - break; - } - case 'r': - { - /* tm_hour / tm_min / tm_sec as locale's 12-hour clock time, %I:%M:%S %p for C locale */ - SPRINTREC( _PDCLIB_lc_time.time_format_12h ); - break; - } - case 'R': - { - /* %H:%M */ - SPRINTREC( "%H:%M" ); - break; - } - case 'S': - { - /* tm_sec as decimal (00-60) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t sec = div( timeptr->tm_sec, 10 ); - s[rc++] = '0' + sec.quot; - s[rc++] = '0' + sec.rem; - } - else - { - return 0; - } - break; - } - case 't': - { - /* tabulator */ - s[rc++] = '\t'; - break; - } - case 'T': - { - /* %H:%M:%S */ - SPRINTREC( "%H:%M:%S" ); - break; - } - case 'u': - { - /* tm_wday as decimal (1-7) with Monday == 1 */ - /* 'O' for locale's alternative numeric symbols */ - s[rc++] = ( timeptr->tm_wday == 0 ) ? '7' : '0' + timeptr->tm_wday; - break; - } - case 'U': - { - /* week number of the year (first Sunday as the first day of week 1) as decimal (00-53) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t week = div( week_calc( timeptr, E_SUNDAY ), 10 ); - s[rc++] = '0' + week.quot; - s[rc++] = '0' + week.rem; - } - else - { - return 0; - } - break; - } - case 'V': - { - /* ISO week number as decimal (01-53) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t week = div( week_calc( timeptr, E_ISO_WEEK ), 10 ); - s[rc++] = '0' + week.quot; - s[rc++] = '0' + week.rem; - } - else - { - return 0; - } - break; - } - case 'w': - { - /* tm_wday as decimal number (0-6) with Sunday == 0 */ - /* 'O' for locale's alternative numeric symbols */ - s[rc++] = '0' + timeptr->tm_wday; - break; - } - case 'W': - { - /* week number of the year (first Monday as the first day of week 1) as decimal (00-53) */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t week = div( week_calc( timeptr, E_MONDAY ), 10 ); - s[rc++] = '0' + week.quot; - s[rc++] = '0' + week.rem; - } - else - { - return 0; - } - break; - } - case 'x': - { - /* locale's date representation, %m/%d/%y for C locale */ - /* 'E' for locale's alternative representation */ - SPRINTREC( _PDCLIB_lc_time.date_format ); - break; - } - case 'X': - { - /* locale's time representation, %T for C locale */ - /* 'E' for locale's alternative representation */ - SPRINTREC( _PDCLIB_lc_time.time_format ); - break; - } - case 'y': - { - /* last 2 digits of tm_year as decimal (00-99) */ - /* 'E' for offset from %EC (year only) in locale's alternative representation */ - /* 'O' for locale's alternative numeric symbols */ - if ( rc < ( maxsize - 2 ) ) - { - div_t year = div( ( timeptr->tm_year % 100 ), 10 ); - s[rc++] = '0' + year.quot; - s[rc++] = '0' + year.rem; - } - else - { - return 0; - } - break; - } - case 'Y': - { - /* tm_year as decimal (e.g. 1997) */ - /* 'E' for locale's alternative representation */ - if ( rc < ( maxsize - 4 ) ) - { - int year = timeptr->tm_year + 1900; - int i; - - for ( i = 3; i >= 0; --i ) - { - div_t digit = div( year, 10 ); - s[ rc + i ] = '0' + digit.rem; - year = digit.quot; - } - - rc += 4; - } - else - { - return 0; - } - break; - } - case 'z': - { - /* tm_isdst / UTC offset in ISO8601 format (e.g. -0430 meaning 4 hours 30 minutes behind Greenwich), or no characters */ - /* TODO: 'z' */ - break; - } - case 'Z': - { - /* tm_isdst / locale's time zone name or abbreviation, or no characters */ - /* TODO: 'Z' */ - break; - } - case '%': - { - /* '%' character */ - s[rc++] = '%'; - break; - } - } - } - } - - return 0; -} diff --git a/src/libraries/libc/time/time.c b/src/libraries/libc/time/time.c deleted file mode 100644 index ae6f7ed..0000000 --- a/src/libraries/libc/time/time.c +++ /dev/null @@ -1,13 +0,0 @@ -/* time( time_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -/* See comments in time.h on the semantics of time_t. */ - -time_t time( time_t * timer ) -{ - return -1; -} diff --git a/src/libraries/libc/time/timespec_get.c b/src/libraries/libc/time/timespec_get.c deleted file mode 100644 index 1af674c..0000000 --- a/src/libraries/libc/time/timespec_get.c +++ /dev/null @@ -1,12 +0,0 @@ -/* timespec_get( struct timespec *, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -int timespec_get( struct timespec * ts, int base ) -{ - return 0; -} diff --git a/src/libraries/libc/wchar.h b/src/libraries/libc/wchar.h deleted file mode 100644 index 8d2d57e..0000000 --- a/src/libraries/libc/wchar.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once -/* Wide character functions -*/ - -#include "j6libc/cpp.h" -#include "j6libc/int.h" -#include "j6libc/null.h" -#include "j6libc/size_t.h" -#include "j6libc/wchar_t.h" -#include "j6libc/wctype_t.h" -#include "j6libc/wint_t.h" - -#include -#include - -CPP_CHECK_BEGIN - -typedef unsigned long mbstate_t; - -wint_t btowc(int); -int fwprintf(FILE *, const wchar_t *, ...); -int fwscanf(FILE *, const wchar_t *, ...); -int iswalnum(wint_t); -int iswalpha(wint_t); -int iswcntrl(wint_t); -int iswdigit(wint_t); -int iswgraph(wint_t); -int iswlower(wint_t); -int iswprint(wint_t); -int iswpunct(wint_t); -int iswspace(wint_t); -int iswupper(wint_t); -int iswxdigit(wint_t); -int iswctype(wint_t, wctype_t); -wint_t fgetwc(FILE *); -wchar_t *fgetws(wchar_t *, int, FILE *); -wint_t fputwc(wchar_t, FILE *); -int fputws(const wchar_t *, FILE *); -int fwide(FILE *, int); -wint_t getwc(FILE *); -wint_t getwchar(void); -int mbsinit(const mbstate_t *); -size_t mbrlen(const char *, size_t, mbstate_t *); -size_t mbrtowc(wchar_t *, const char *, size_t, mbstate_t *); -size_t mbsrtowcs(wchar_t *, const char **, size_t, mbstate_t *); -wint_t putwc(wchar_t, FILE *); -wint_t putwchar(wchar_t); -int swprintf(wchar_t *, size_t, const wchar_t *, ...); -int swscanf(const wchar_t *, const wchar_t *, ...); -wint_t towlower(wint_t); -wint_t towupper(wint_t); -wint_t ungetwc(wint_t, FILE *); -int vfwprintf(FILE *, const wchar_t *, va_list); -int vwprintf(const wchar_t *, va_list); -int vswprintf(wchar_t *, size_t, const wchar_t *, va_list); -size_t wcrtomb(char *, wchar_t, mbstate_t *); -wchar_t *wcscat(wchar_t *, const wchar_t *); -wchar_t *wcschr(const wchar_t *, wchar_t); -int wcscmp(const wchar_t *, const wchar_t *); -int wcscoll(const wchar_t *, const wchar_t *); -wchar_t *wcscpy(wchar_t *, const wchar_t *); -size_t wcscspn(const wchar_t *, const wchar_t *); -size_t wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *); -size_t wcslen(const wchar_t *); -wchar_t *wcsncat(wchar_t *, const wchar_t *, size_t); -int wcsncmp(const wchar_t *, const wchar_t *, size_t); -wchar_t *wcsncpy(wchar_t *, const wchar_t *, size_t); -wchar_t *wcspbrk(const wchar_t *, const wchar_t *); -wchar_t *wcsrchr(const wchar_t *, wchar_t); -size_t wcsrtombs(char *, const wchar_t **, size_t, mbstate_t *); -size_t wcsspn(const wchar_t *, const wchar_t *); -wchar_t *wcsstr(const wchar_t *, const wchar_t *); -double wcstod(const wchar_t *, wchar_t **); -wchar_t *wcstok(wchar_t *, const wchar_t *, wchar_t **); -long int wcstol(const wchar_t *, wchar_t **, int); -unsigned long int wcstoul(const wchar_t *, wchar_t **, int); -wchar_t *wcswcs(const wchar_t *, const wchar_t *); -int wcswidth(const wchar_t *, size_t); -size_t wcsxfrm(wchar_t *, const wchar_t *, size_t); -int wctob(wint_t); -wctype_t wctype(const char *); -int wcwidth(wchar_t); -wchar_t *wmemchr(const wchar_t *, wchar_t, size_t); -int wmemcmp(const wchar_t *, const wchar_t *, size_t); -wchar_t *wmemcpy(wchar_t *, const wchar_t *, size_t); -wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t); -wchar_t *wmemset(wchar_t *, wchar_t, size_t); -int wprintf(const wchar_t *, ...); -int wscanf(const wchar_t *, ...); - -CPP_CHECK_END diff --git a/src/libraries/libc/wctype.h b/src/libraries/libc/wctype.h deleted file mode 100644 index 89364fc..0000000 --- a/src/libraries/libc/wctype.h +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once -/* Wide character classification and mapping utilities - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include "j6libc/cpp.h" -#include "j6libc/int.h" -#include "j6libc/wint_t.h" - -CPP_CHECK_BEGIN - -// wctrans_t -// wctype_t - -#ifndef _PDCLIB_WEOF_DEFINED -#define _PDCLIB_WEOF_DEFINED _PDCLIB_WEOF_DEFINED -#define WEOF (wint_t)-1 -#endif - -/* Wide character classification functions */ - -/* Returns iswalpha( wc ) || iswdigit( wc ) */ -int iswalnum( wint_t wc ); - -/* Returns true for wide characters for which either isupper( wc ) or - islower( wc ) is true, as well as a set of locale-specific wide - characters which are neither control characters, digits, punctuation, - or whitespace. -*/ -int iswalpha( wint_t wc ); - -/* Returns true if the character iswspace() and used for separating words - within a line of text. In the "C" locale, only L' ' and L'\t' are - considered blanks. -*/ -int iswblank( wint_t wc ); - -/* Returns true if the wide character is a control character. */ -int iswcntrl( wint_t wc ); - -/* Returns true if the wide character is a decimal digit. Locale- - independent. */ -int iswdigit( wint_t wc ); - -/* Returns iswprint( wc ) && ! iswspace( wc ). - NOTE: This definition differs from that of isgraph() in , - which considers only ' ', not all isspace() characters. -*/ -int iswgraph( wint_t wc ); - -/* Returns true for lowerspace wide characters, as well as a set of - locale-specific wide characters which are neither control charcters, - digits, punctuation, or whitespace. -*/ -int iswlower( wint_t wc ); - -/* Returns true for every printing wide character. */ -int iswprint( wint_t wc ); - -/* Returns true for a locale-specific set of punctuation characters that - are neither whitespace nor alphanumeric. -*/ -int iswpunct( wint_t wc ); - -/* Returns true for a locale-specific set of whitespace characters that - are neither alphanumeric, graphic, or punctuation. -*/ -int iswspace( wint_t wc ); - -/* Returns true for upperspace wide characters, as well as a set of - locale-specific wide characters which are neither control charcters, - digits, punctuation, or whitespace. -*/ -int iswupper( wint_t wc ); - -/* Returns true if the wide character is a hexadecimal digit. Locale- - independent. */ -int iswxdigit( wint_t wc ); - -/* Extensible wide character classification functions */ - -/* Returns true if the wide character wc has the property described by - desc (which was retrieved by a previous call to wctype() without - changing the LC_CTYPE locale setting between the two calls). -*/ -int iswctype( wint_t wc, wctype_t desc ); - -/* Returns a description object for a named character property, to be - used as parameter to the iswctype() function. Supported property - names are: - "alnum" -- alphanumeric, as per iswalnum() - "alpha" -- alphabetic, as per iswalpha() - "blank" -- blank, as per iswblank() - "cntrl" -- control, as per iswcntrl() - "digit" -- decimal digit, as per iswdigit() - "graph" -- graphic, as per iswgraph() - "lower" -- lowercase, as per iswlower() - "print" -- printing, as per iswprint() - "punct" -- punctuation, as per iswprint() - "space" -- whitespace, as per iswspace() - "upper" -- uppercase, as per iswupper() - "xdigit" -- hexadecimal digit, as per iswxdigit() - For unsupported properties, the function returns zero. -*/ -wctype_t wctype( const char * property ); - -/* Wide character case mapping utilities */ - -/* Converts an uppercase letter to a corresponding lowercase letter. Input for - which no corresponding lowercase letter exists remains unchanged. -*/ -wint_t towlower( wint_t wc ); - -/* Converts a lowercase letter to a corresponding uppercase letter. Input for - which no corresponding uppercase letter exists remains unchanged. -*/ -wint_t towupper( wint_t wc ); - -/* Extensible wide character case mapping utilities */ - -/* Converts the wide character wc according to the transition described - by desc (which was retrieved by a previous call to wctrans() without - changing the LC_CTYPE locale setting between the two calls). -*/ -wint_t towctrans( wint_t wc, wctrans_t desc ); - -/* Returns a description object for a named character transformation, to - be used as parameter to the towctrans() function. Supported transformation - properties are: - "tolower" -- lowercase mapping, as per towlower() - "toupper" -- uppercase mapping, as per towupper() - For unsupported properties, the function returns zero. -*/ -wctrans_t wctrans( const char * property ); - -CPP_CHECK_END