mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[libc] Bring libc in-tree
Moving libc from its separate repo into this one, minor resulting build fixes, and a hacky way to add -I for libc headers in builds.
This commit is contained in:
57
src/libraries/libc/include/j6libc/aux.h
Normal file
57
src/libraries/libc/include/j6libc/aux.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
/* Auxiliary PDCLib code <aux.h>
|
||||
|
||||
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 )
|
||||
336
src/libraries/libc/include/j6libc/config.h
Normal file
336
src/libraries/libc/include/j6libc/config.h
Normal file
@@ -0,0 +1,336 @@
|
||||
#pragma once
|
||||
/* Internal PDCLib configuration <config.h>
|
||||
(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 <j6libc/int_widths.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 <stdlib.h> 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
|
||||
|
||||
/* <stdlib.h> 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;
|
||||
};
|
||||
|
||||
/* <inttypes.h> 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 <time.h> 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 (<stdarg.h>)
|
||||
The macros defined by <stdarg.h> 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 <stdarg.h>. */
|
||||
#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 <errno.h> will "see" EPERM instead of EISDIR (the _PDCLIB_*
|
||||
prefix removed by <errno.h> 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 <errno.h> 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
|
||||
|
||||
9
src/libraries/libc/include/j6libc/cpp.h
Normal file
9
src/libraries/libc/include/j6libc/cpp.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define CPP_CHECK_BEGIN extern "C" {
|
||||
#define CPP_CHECK_END }
|
||||
#else
|
||||
#define CPP_CHECK_BEGIN
|
||||
#define CPP_CHECK_END
|
||||
#endif
|
||||
67
src/libraries/libc/include/j6libc/glue.h
Normal file
67
src/libraries/libc/include/j6libc/glue.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
/* OS glue functions declaration <glue.h>
|
||||
|
||||
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 );
|
||||
347
src/libraries/libc/include/j6libc/int.h
Normal file
347
src/libraries/libc/include/j6libc/int.h
Normal file
@@ -0,0 +1,347 @@
|
||||
#pragma once
|
||||
/* PDCLib internal integer logic <int.h>
|
||||
|
||||
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 <stdbool.h>
|
||||
|
||||
#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 <stdio.h> internals */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Flags for representing mode (see fopen()). Note these must fit the same
|
||||
status field as the _IO?BF flags in <stdio.h> 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 <time.h> 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 <errno.h>.
|
||||
*/
|
||||
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 );
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* <locale.h> 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
|
||||
57
src/libraries/libc/include/j6libc/int_widths.h
Normal file
57
src/libraries/libc/include/j6libc/int_widths.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#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;
|
||||
|
||||
14
src/libraries/libc/include/j6libc/max_align_t.h
Normal file
14
src/libraries/libc/include/j6libc/max_align_t.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#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
|
||||
|
||||
6
src/libraries/libc/include/j6libc/null.h
Normal file
6
src/libraries/libc/include/j6libc/null.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
/* Constant definition: NULL */
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
14
src/libraries/libc/include/j6libc/sig_atomic_t.h
Normal file
14
src/libraries/libc/include/j6libc/sig_atomic_t.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#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
|
||||
6
src/libraries/libc/include/j6libc/size_t.h
Normal file
6
src/libraries/libc/include/j6libc/size_t.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
/* Type definition: size_t */
|
||||
|
||||
#if __is_identifier(size_t)
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
#endif
|
||||
6
src/libraries/libc/include/j6libc/wchar_t.h
Normal file
6
src/libraries/libc/include/j6libc/wchar_t.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
/* Type definition: wchar_t */
|
||||
|
||||
#if __is_identifier(wchar_t)
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
#endif
|
||||
6
src/libraries/libc/include/j6libc/wctype_t.h
Normal file
6
src/libraries/libc/include/j6libc/wctype_t.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
/* Type definitions: wctype_t wctrans_t */
|
||||
|
||||
typedef uint32_t wctrans_t;
|
||||
typedef uint32_t wctype_t ;
|
||||
|
||||
5
src/libraries/libc/include/j6libc/wint_t.h
Normal file
5
src/libraries/libc/include/j6libc/wint_t.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
/* Type definition: wint_t */
|
||||
|
||||
typedef __WINT_TYPE__ wint_t;
|
||||
|
||||
Reference in New Issue
Block a user