3 /* PDCLib internal integer logic <_PDCLIB_int.h>
5 This file is part of the Public Domain C Library (PDCLib).
6 Permission is granted to use, modify, and / or redistribute at will.
10 #define _PDCLIB_INT_H _PDCLIB_INT_H
12 /* -------------------------------------------------------------------------- */
13 /* You should not have to edit anything in this file; if you DO have to, it */
14 /* would be considered a bug / missing feature: notify the author(s). */
15 /* -------------------------------------------------------------------------- */
17 #include <_PDCLIB_config.h>
18 #include <_PDCLIB_aux.h>
20 /* null pointer constant */
21 #define _PDCLIB_NULL 0
23 /* -------------------------------------------------------------------------- */
24 /* Limits of native datatypes */
25 /* -------------------------------------------------------------------------- */
26 /* The definition of minimum limits for unsigned datatypes is done because */
27 /* later on we will "construct" limits for other abstract types: */
28 /* USHRT -> _PDCLIB_ + USHRT + _MIN -> _PDCLIB_USHRT_MIN -> 0 */
29 /* INT -> _PDCLIB_ + INT + _MIN -> _PDCLIB_INT_MIN -> ... you get the idea. */
30 /* -------------------------------------------------------------------------- */
32 /* Setting 'char' limits */
33 #define _PDCLIB_CHAR_BIT 8
34 #define _PDCLIB_UCHAR_MIN 0
35 #define _PDCLIB_UCHAR_MAX 0xff
36 #define _PDCLIB_SCHAR_MIN (-0x7f - 1)
37 #define _PDCLIB_SCHAR_MAX 0x7f
38 #ifdef _PDCLIB_CHAR_SIGNED
39 #define _PDCLIB_CHAR_MIN _PDCLIB_SCHAR_MIN
40 #define _PDCLIB_CHAR_MAX _PDCLIB_SCHAR_MAX
42 #define _PDCLIB_CHAR_MIN 0
43 #define _PDCLIB_CHAR_MAX _PDCLIB_UCHAR_MAX
46 /* Setting 'short' limits */
47 #if _PDCLIB_SHRT_BYTES == 2
48 #define _PDCLIB_SHRT_MAX 0x7fff
49 #define _PDCLIB_SHRT_MIN (-0x7fff - 1)
50 #define _PDCLIB_USHRT_MAX 0xffff
52 #error Unsupported width of 'short' (not 16 bit).
54 #define _PDCLIB_USHRT_MIN 0
56 #if _PDCLIB_INT_BYTES < _PDCLIB_SHRT_BYTES
57 #error Bogus setting: short > int? Check _PDCLIB_config.h.
60 /* Setting 'int' limits */
61 #if _PDCLIB_INT_BYTES == 2
62 #define _PDCLIB_INT_MAX 0x7fff
63 #define _PDCLIB_INT_MIN (-0x7fff - 1)
64 #define _PDCLIB_UINT_MAX 0xffffU
65 #elif _PDCLIB_INT_BYTES == 4
66 #define _PDCLIB_INT_MAX 0x7fffffff
67 #define _PDCLIB_INT_MIN (-0x7fffffff - 1)
68 #define _PDCLIB_UINT_MAX 0xffffffffU
69 #elif _PDCLIB_INT_BYTES == 8
70 #define _PDCLIB_INT_MAX 0x7fffffffffffffff
71 #define _PDCLIB_INT_MIN (-0x7fffffffffffffff - 1)
72 #define _PDCLIB_UINT_MAX 0xffffffffffffffff
74 #error Unsupported width of 'int' (neither 16, 32, nor 64 bit).
76 #define _PDCLIB_UINT_MIN 0
78 /* Setting 'long' limits */
79 #if _PDCLIB_LONG_BYTES == 4
80 #define _PDCLIB_LONG_MAX 0x7fffffffL
81 #define _PDCLIB_LONG_MIN (-0x7fffffffL - 1L)
82 #define _PDCLIB_ULONG_MAX 0xffffffffUL
83 #elif _PDCLIB_LONG_BYTES == 8
84 #define _PDCLIB_LONG_MAX 0x7fffffffffffffffL
85 #define _PDCLIB_LONG_MIN (-0x7fffffffffffffffL - 1L)
86 #define _PDCLIB_ULONG_MAX 0xffffffffffffffffUL
88 #error Unsupported width of 'long' (neither 32 nor 64 bit).
90 #define _PDCLIB_ULONG_MIN 0
92 /* Setting 'long long' limits */
93 #if _PDCLIB_LLONG_BYTES == 8
94 #define _PDCLIB_LLONG_MAX 0x7fffffffffffffffLL
95 #define _PDCLIB_LLONG_MIN (-0x7fffffffffffffffLL - 1LL)
96 #define _PDCLIB_ULLONG_MAX 0xffffffffffffffffULL
97 #elif _PDCLIB_LLONG_BYTES == 16
98 #define _PDCLIB_LLONG_MAX 0x7fffffffffffffffffffffffffffffffLL
99 #define _PDCLIB_LLONG_MIN (-0x7fffffffffffffffffffffffffffffffLL - 1LL)
100 #define _PDCLIB_ULLONG_MAX 0xffffffffffffffffffffffffffffffffULL
102 #error Unsupported width of 'long long' (neither 64 nor 128 bit).
104 #define _PDCLIB_ULLONG_MIN 0
106 /* -------------------------------------------------------------------------- */
107 /* <stdint.h> exact-width types and their limits */
108 /* -------------------------------------------------------------------------- */
109 /* Note that, for the "standard" widths of 8, 16, 32 and 64 bit, the "LEAST" */
110 /* types are identical to the "exact-width" types, by definition. */
112 /* Setting 'int8_t', its limits, its literal, and conversion macros. */
113 #if _PDCLIB_CHAR_BIT == 8
114 typedef signed char _PDCLIB_int8_t;
115 typedef unsigned char _PDCLIB_uint8_t;
116 #define _PDCLIB_INT8_MAX _PDCLIB_CHAR_MAX
117 #define _PDCLIB_INT8_MIN _PDCLIB_CHAR_MIN
118 #define _PDCLIB_UINT8_MAX _PDCLIB_UCHAR_MAX
119 #define _PDCLIB_8_CONV hh
121 #error Unsupported width of char (not 8 bits).
124 /* Setting 'int16_t', its limits, its literal, and conversion macros. */
125 #if _PDCLIB_INT_BYTES == 2
126 typedef signed int _PDCLIB_int16_t;
127 typedef unsigned int _PDCLIB_uint16_t;
128 #define _PDCLIB_INT16_MAX _PDCLIB_INT_MAX
129 #define _PDCLIB_INT16_MIN _PDCLIB_INT_MIN
130 #define _PDCLIB_UINT16_MAX _PDCLIB_UINT_MAX
131 #define _PDCLIB_16_CONV
132 #elif _PDCLIB_SHRT_BYTES == 2
133 typedef signed short _PDCLIB_int16_t;
134 typedef unsigned short _PDCLIB_uint16_t;
135 #define _PDCLIB_INT16_MAX _PDCLIB_SHRT_MAX
136 #define _PDCLIB_INT16_MIN _PDCLIB_SHRT_MIN
137 #define _PDCLIB_UINT16_MAX _PDCLIB_USHRT_MAX
138 #define _PDCLIB_16_CONV h
140 #error Neither 'short' nor 'int' are 16-bit.
143 /* Setting 'int32_t', its limits, its literal, and conversion macros. */
144 #if _PDCLIB_INT_BYTES == 4
145 typedef signed int _PDCLIB_int32_t;
146 typedef unsigned int _PDCLIB_uint32_t;
147 #define _PDCLIB_INT32_MAX _PDCLIB_INT_MAX
148 #define _PDCLIB_INT32_MIN _PDCLIB_INT_MIN
149 #define _PDCLIB_UINT32_MAX _PDCLIB_UINT_MAX
150 #define _PDCLIB_INT32_LITERAL
151 #define _PDCLIB_UINT32_LITERAL
152 #define _PDCLIB_32_CONV
153 #elif _PDCLIB_LONG_BYTES == 4
154 typedef signed long _PDCLIB_int32_t;
155 typedef unsigned long _PDCLIB_uint32_t;
156 #define _PDCLIB_INT32_MAX _PDCLIB_LONG_MAX
157 #define _PDCLIB_INT32_MIN _PDCLIB_LONG_MIN
158 #define _PDCLIB_UINT32_MAX _PDCLIB_LONG_MAX
159 #define _PDCLIB_INT32_LITERAL l
160 #define _PDCLIB_UINT32_LITERAL ul
161 #define _PDCLIB_32_CONV l
163 #error Neither 'int' nor 'long' are 32-bit.
166 /* Setting 'int64_t', its limits, its literal, and conversion macros. */
167 #if _PDCLIB_LONG_BYTES == 8
168 typedef signed long _PDCLIB_int64_t;
169 typedef unsigned long _PDCLIB_uint64_t;
170 #define _PDCLIB_INT64_MAX _PDCLIB_LONG_MAX
171 #define _PDCLIB_INT64_MIN _PDCLIB_LONG_MIN
172 #define _PDCLIB_UINT64_MAX _PDCLIB_ULONG_MAX
173 #define _PDCLIB_INT64_LITERAL l
174 #define _PDCLIB_UINT64_LITERAL ul
175 #define _PDCLIB_64_CONV l
176 #elif _PDCLIB_LLONG_BYTES == 8
177 typedef signed long long _PDCLIB_int64_t;
178 typedef unsigned long long _PDCLIB_uint64_t;
179 #define _PDCLIB_INT64_MAX _PDCLIB_LLONG_MAX
180 #define _PDCLIB_INT64_MIN _PDCLIB_LLONG_MIN
181 #define _PDCLIB_UINT64_MAX _PDCLIB_ULLONG_MAX
182 #define _PDCLIB_INT64_LITERAL ll
183 #define _PDCLIB_UINT64_LITERAL ull
184 #define _PDCLIB_64_CONV ll
186 #error Neither 'long' nor 'long long' are 64-bit.
189 /* -------------------------------------------------------------------------- */
190 /* <stdint.h> "fastest" types and their limits */
191 /* -------------------------------------------------------------------------- */
192 /* This is, admittedly, butt-ugly. But at least it's ugly where the average */
193 /* user of PDCLib will never see it, and makes <_PDCLIB_config.h> much */
195 /* -------------------------------------------------------------------------- */
197 typedef _PDCLIB_fast8 _PDCLIB_int_fast8_t;
198 typedef unsigned _PDCLIB_fast8 _PDCLIB_uint_fast8_t;
199 #define _PDCLIB_INT_FAST8_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST8 ), _MIN )
200 #define _PDCLIB_INT_FAST8_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST8 ), _MAX )
201 #define _PDCLIB_UINT_FAST8_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_U, _PDCLIB_FAST8 ), _MAX )
203 typedef _PDCLIB_fast16 _PDCLIB_int_fast16_t;
204 typedef unsigned _PDCLIB_fast16 _PDCLIB_uint_fast16_t;
205 #define _PDCLIB_INT_FAST16_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST16 ), _MIN )
206 #define _PDCLIB_INT_FAST16_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST16 ), _MAX )
207 #define _PDCLIB_UINT_FAST16_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_U, _PDCLIB_FAST16 ), _MAX )
209 typedef _PDCLIB_fast32 _PDCLIB_int_fast32_t;
210 typedef unsigned _PDCLIB_fast32 _PDCLIB_uint_fast32_t;
211 #define _PDCLIB_INT_FAST32_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST32 ), _MIN )
212 #define _PDCLIB_INT_FAST32_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST32 ), _MAX )
213 #define _PDCLIB_UINT_FAST32_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_U, _PDCLIB_FAST32 ), _MAX )
215 typedef _PDCLIB_fast64 _PDCLIB_int_fast64_t;
216 typedef unsigned _PDCLIB_fast64 _PDCLIB_uint_fast64_t;
217 #define _PDCLIB_INT_FAST64_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST64 ), _MIN )
218 #define _PDCLIB_INT_FAST64_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_FAST64 ), _MAX )
219 #define _PDCLIB_UINT_FAST64_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_U, _PDCLIB_FAST64 ), _MAX )
221 /* -------------------------------------------------------------------------- */
222 /* Various <stddef.h> typedefs and limits */
223 /* -------------------------------------------------------------------------- */
225 typedef _PDCLIB_ptrdiff _PDCLIB_ptrdiff_t;
226 #define _PDCLIB_PTRDIFF_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_PTRDIFF ), _MIN )
227 #define _PDCLIB_PTRDIFF_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_PTRDIFF ), _MAX )
229 #define _PDCLIB_SIG_ATOMIC_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_SIG_ATOMIC ), _MIN )
230 #define _PDCLIB_SIG_ATOMIC_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_SIG_ATOMIC ), _MAX )
232 typedef _PDCLIB_size _PDCLIB_size_t;
233 #define _PDCLIB_SIZE_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_SIZE ), _MAX )
235 typedef _PDCLIB_wchar _PDCLIB_wchar_t;
236 #define _PDCLIB_WCHAR_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_WCHAR ), _MIN )
237 #define _PDCLIB_WCHAR_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_WCHAR ), _MAX )
239 typedef _PDCLIB_intptr _PDCLIB_intptr_t;
240 typedef unsigned _PDCLIB_intptr _PDCLIB_uintptr_t;
241 #define _PDCLIB_INTPTR_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_INTPTR ), _MIN )
242 #define _PDCLIB_INTPTR_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_INTPTR ), _MAX )
243 #define _PDCLIB_UINTPTR_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_U, _PDCLIB_INTPTR ), _MAX )
245 typedef _PDCLIB_intmax _PDCLIB_intmax_t;
246 typedef unsigned _PDCLIB_intmax _PDCLIB_uintmax_t;
247 #define _PDCLIB_INTMAX_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_INTMAX ), _MIN )
248 #define _PDCLIB_INTMAX_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_INTMAX ), _MAX )
249 #define _PDCLIB_UINTMAX_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_U, _PDCLIB_INTMAX ), _MAX )
250 #define _PDCLIB_INTMAX_C( value ) _PDCLIB_concat( value, _PDCLIB_INTMAX_LITERAL )
251 #define _PDCLIB_UINTMAX_C( value ) _PDCLIB_concat( value, _PDCLIB_concat( u, _PDCLIB_INTMAX_LITERAL ) )
253 /* -------------------------------------------------------------------------- */
254 /* Various <stdio.h> internals */
255 /* -------------------------------------------------------------------------- */
257 /* Flags for representing mode (see fopen()). Note these must fit the same
258 status field as the _IO?BF flags in <stdio.h> and the internal flags below.
260 #define _PDCLIB_FREAD 8u
261 #define _PDCLIB_FWRITE 16u
262 #define _PDCLIB_FAPPEND 32u
263 #define _PDCLIB_FRW 64u
264 #define _PDCLIB_FBIN 128u
266 /* Internal flags, made to fit the same status field as the flags above. */
267 /* -------------------------------------------------------------------------- */
268 /* free() the buffer memory on closing (false for user-supplied buffer) */
269 #define _PDCLIB_FREEBUFFER 512u
270 /* stream has encountered error / EOF */
271 #define _PDCLIB_ERRORFLAG 1024u
272 #define _PDCLIB_EOFFLAG 2048u
273 /* stream is wide-oriented */
274 #define _PDCLIB_WIDESTREAM 4096u
275 /* stream is byte-oriented */
276 #define _PDCLIB_BYTESTREAM 8192u
277 /* file associated with stream should be remove()d on closing (tmpfile()) */
278 #define _PDCLIB_DELONCLOSE 16384u
279 /* stream handle should not be free()d on close (stdin, stdout, stderr) */
280 #define _PDCLIB_STATIC 32768u
282 /* Position / status structure for getpos() / fsetpos(). */
283 struct _PDCLIB_fpos_t
285 _PDCLIB_uint64_t offset; /* File position offset */
286 int status; /* Multibyte parsing state (unused, reserved) */
290 struct _PDCLIB_file_t
292 _PDCLIB_fd_t handle; /* OS file handle */
293 char * buffer; /* Pointer to buffer memory */
294 _PDCLIB_size_t bufsize; /* Size of buffer */
295 _PDCLIB_size_t bufidx; /* Index of current position in buffer */
296 _PDCLIB_size_t bufend; /* Index of last pre-read character in buffer */
297 struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */
298 _PDCLIB_size_t ungetidx; /* Number of ungetc()'ed characters */
299 unsigned char * ungetbuf; /* ungetc() buffer */
300 unsigned int status; /* Status flags; see above */
301 /* multibyte parsing status to be added later */
302 char * filename; /* Name the current stream has been opened with */
303 struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */
306 /* -------------------------------------------------------------------------- */
307 /* Internal data types */
308 /* -------------------------------------------------------------------------- */
310 /* Structure required by both atexit() and exit() for handling atexit functions */
311 struct _PDCLIB_exitfunc_t
313 struct _PDCLIB_exitfunc_t * next;
314 void (*func)( void );
317 /* Structures required by malloc(), realloc(), and free(). */
318 struct _PDCLIB_headnode_t
320 struct _PDCLIB_memnode_t * first;
321 struct _PDCLIB_memnode_t * last;
324 struct _PDCLIB_memnode_t
327 struct _PDCLIB_memnode_t * next;
330 /* Status structure required by _PDCLIB_print(). */
331 struct _PDCLIB_status_t
333 int base; /* base to which the value shall be converted */
334 _PDCLIB_int_fast32_t flags; /* flags and length modifiers */
335 _PDCLIB_size_t n; /* print: maximum characters to be written */
336 /* scan: number matched conversion specifiers */
337 _PDCLIB_size_t i; /* number of characters read/written */
338 _PDCLIB_size_t current;/* chars read/written in the CURRENT conversion */
339 char * s; /* *sprintf(): target buffer */
340 /* *sscanf(): source string */
341 _PDCLIB_size_t width; /* specified field width */
342 _PDCLIB_size_t prec; /* specified field precision */
343 struct _PDCLIB_file_t * stream; /* *fprintf() / *fscanf() stream */
344 _PDCLIB_va_list arg; /* argument stack */
347 /* -------------------------------------------------------------------------- */
348 /* Declaration of helper functions (implemented in functions/_PDCLIB). */
349 /* -------------------------------------------------------------------------- */
351 /* This is the main function called by atoi(), atol() and atoll(). */
352 _PDCLIB_intmax_t _PDCLIB_atomax( const char * s );
354 /* Two helper functions used by strtol(), strtoul() and long long variants. */
355 const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base );
356 _PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, _PDCLIB_uintmax_t error, _PDCLIB_uintmax_t limval, int limdigit, char * sign );
358 /* Digits arrays used by various integer conversion functions */
359 extern char _PDCLIB_digits[];
360 extern char _PDCLIB_Xdigits[];
362 /* The worker for all printf() type of functions. The pointer spec should point
363 to the introducing '%' of a conversion specifier. The status structure is to
364 be that of the current printf() function, of which the members n, s, stream
365 and arg will be preserved; i will be updated; and all others will be trashed
367 Returns a pointer to the first character not parsed as conversion specifier.
369 const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status );
371 /* The worker for all scanf() type of functions. The pointer spec should point
372 to the introducing '%' of a conversion specifier. The status structure is to
373 be that of the current scanf() function, of which the member stream will be
374 preserved; n, i, and s will be updated; and all others will be trashed by
376 Returns a pointer to the first character not parsed as conversion specifier,
377 or NULL in case of error.
378 FIXME: Should distinguish between matching and input error
380 const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status );
382 /* Parsing any fopen() style filemode string into a number of flags. */
383 unsigned int _PDCLIB_filemode( const char * mode );
385 /* Sanity checking and preparing of read buffer, should be called first thing
386 by any stdio read-data function.
387 Returns 0 on success, EOF on error.
388 On error, EOF / error flags and errno are set appropriately.
390 int _PDCLIB_prepread( struct _PDCLIB_file_t * stream );
392 /* Sanity checking, should be called first thing by any stdio write-data
394 Returns 0 on success, EOF on error.
395 On error, error flags and errno are set appropriately.
397 int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream );
399 /* Closing all streams on program exit */
400 void _PDCLIB_closeall( void );
402 /* -------------------------------------------------------------------------- */
404 /* -------------------------------------------------------------------------- */
406 /* If PDCLib would call its error number "errno" directly, there would be no way
407 to catch its value from underlying system calls that also use it (i.e., POSIX
408 operating systems). That is why we use an internal name, providing a means to
409 access it through <errno.h>.
411 extern int _PDCLIB_errno;
413 /* A mechanism for delayed evaluation. (Not sure if this is really necessary, so
414 no detailed documentation on the "why".)
416 int * _PDCLIB_errno_func( void );
418 /* -------------------------------------------------------------------------- */
419 /* <ctype.h> lookup tables */
420 /* -------------------------------------------------------------------------- */
422 #define _PDCLIB_CTYPE_ALPHA 1
423 #define _PDCLIB_CTYPE_BLANK 2
424 #define _PDCLIB_CTYPE_CNTRL 4
425 #define _PDCLIB_CTYPE_GRAPH 8
426 #define _PDCLIB_CTYPE_PUNCT 16
427 #define _PDCLIB_CTYPE_SPACE 32
428 #define _PDCLIB_CTYPE_LOWER 64
429 #define _PDCLIB_CTYPE_UPPER 128
430 #define _PDCLIB_CTYPE_DIGIT 256
431 #define _PDCLIB_CTYPE_XDIGT 512
433 struct _PDCLIB_ctype_t
435 _PDCLIB_uint16_t flags;
438 unsigned char collation;