From 97357f3170d59a64f9ac72eb1d06ec93172a9252 Mon Sep 17 00:00:00 2001 From: slinky55 Date: Sun, 28 Jun 2026 17:58:58 -0500 Subject: [PATCH] compiled newlib, need to hook up the system calls --- compile_commands.json | 425 ++ kernel/boot/boot.S | 1 + kernel/common.h | 10 + kernel/drivers/pit/pit.S | 2 +- kernel/gdt.c | 2 + kernel/interrupts.S | 10 +- kernel/interrupts.c | 7 +- kernel/kmain.c | 28 +- kernel/process.h | 2 + kernel/scheduler.S | 41 +- kernel/scheduler.c | 61 +- kernel/scheduler.h | 3 +- kernel/syscall.c | 30 +- libc/arch/i686/crt0.S | 0 libc/include/rock.h | 17 - libc/include/string.h | 11 - libc/makefile | 0 programs/crt0.S | 24 + programs/crt0.s | 28 + programs/linker.ld | 31 + programs/main.c | 8 + programs/makefile | 23 +- programs/origin.S | 16 - rocklibc/.gitignore | 1 + rocklibc/compile_commands.json | 4937 +++++++++++++ rocklibc/include/assert.h | 50 + rocklibc/include/ctype.h | 110 + rocklibc/include/errno.h | 202 + rocklibc/include/fcntl.h | 19 + rocklibc/include/float.h | 82 + rocklibc/include/inttypes.h | 368 + rocklibc/include/iso646.h | 31 + rocklibc/include/limits.h | 50 + rocklibc/include/locale.h | 114 + rocklibc/include/math.h | 467 ++ rocklibc/include/pdclib/_PDCLIB_config.h | 915 +++ rocklibc/include/pdclib/_PDCLIB_defguard.h | 29 + rocklibc/include/pdclib/_PDCLIB_glue.h | 93 + rocklibc/include/pdclib/_PDCLIB_internal.h | 686 ++ rocklibc/include/pdclib/_PDCLIB_lib_ext1.h | 32 + .../include/pdclib/_PDCLIB_platform_errno.h | 6 + .../include/pdclib/_PDCLIB_platform_fcntl.h | 6 + rocklibc/include/pdclib/_PDCLIB_print.h | 145 + rocklibc/include/pdclib/_PDCLIB_tzcode.h | 153 + rocklibc/include/signal.h | 91 + rocklibc/include/stdalign.h | 30 + rocklibc/include/stdarg.h | 34 + rocklibc/include/stdbool.h | 24 + rocklibc/include/stddef.h | 55 + rocklibc/include/stdint.h | 236 + rocklibc/include/stdio.h | 935 +++ rocklibc/include/stdlib.h | 379 + rocklibc/include/stdnoreturn.h | 26 + rocklibc/include/string.h | 394 + rocklibc/include/sys/stat.h | 50 + rocklibc/include/sys/time.h | 21 + rocklibc/include/sys/times.h | 17 + rocklibc/include/sys/types.h | 29 + rocklibc/include/time.h | 191 + rocklibc/include/unistd.h | 28 + rocklibc/include/wctype.h | 152 + rocklibc/makefile | 20 + rocklibc/src/_PDCLIB/Readme.txt | 10 + rocklibc/src/_PDCLIB/_PDCLIB_Exit.c | 48 + rocklibc/src/_PDCLIB/_PDCLIB_atomax.c | 59 + rocklibc/src/_PDCLIB/_PDCLIB_bigint_add.c | 83 + rocklibc/src/_PDCLIB/_PDCLIB_bigint_cmp.c | 74 + .../src/_PDCLIB/_PDCLIB_bigint_digit_log2.c | 83 + rocklibc/src/_PDCLIB/_PDCLIB_bigint_div.c | 135 + .../src/_PDCLIB/_PDCLIB_bigint_from_bigint.c | 54 + .../src/_PDCLIB/_PDCLIB_bigint_from_digit.c | 43 + .../src/_PDCLIB/_PDCLIB_bigint_from_pow10.c | 131 + .../src/_PDCLIB/_PDCLIB_bigint_from_pow2.c | 54 + rocklibc/src/_PDCLIB/_PDCLIB_bigint_log2.c | 64 + rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul.c | 121 + rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul10.c | 58 + .../src/_PDCLIB/_PDCLIB_bigint_mul_pow10.c | 30 + rocklibc/src/_PDCLIB/_PDCLIB_bigint_shl.c | 83 + rocklibc/src/_PDCLIB/_PDCLIB_changemode.c | 73 + rocklibc/src/_PDCLIB/_PDCLIB_close.c | 44 + rocklibc/src/_PDCLIB/_PDCLIB_closeall.c | 38 + rocklibc/src/_PDCLIB/_PDCLIB_digits.c | 33 + rocklibc/src/_PDCLIB/_PDCLIB_filemode.c | 114 + rocklibc/src/_PDCLIB/_PDCLIB_fillbuffer.c | 77 + rocklibc/src/_PDCLIB/_PDCLIB_flushbuffer.c | 103 + rocklibc/src/_PDCLIB/_PDCLIB_fp_from_dbl.c | 106 + rocklibc/src/_PDCLIB/_PDCLIB_fp_from_ldbl.c | 106 + rocklibc/src/_PDCLIB/_PDCLIB_getstream.c | 49 + rocklibc/src/_PDCLIB/_PDCLIB_init_file_t.c | 82 + rocklibc/src/_PDCLIB/_PDCLIB_is_leap.c | 39 + rocklibc/src/_PDCLIB/_PDCLIB_isstream.c | 49 + .../src/_PDCLIB/_PDCLIB_load_lc_collate.c | 63 + rocklibc/src/_PDCLIB/_PDCLIB_load_lc_ctype.c | 365 + .../src/_PDCLIB/_PDCLIB_load_lc_messages.c | 88 + .../src/_PDCLIB/_PDCLIB_load_lc_monetary.c | 158 + .../src/_PDCLIB/_PDCLIB_load_lc_numeric.c | 84 + rocklibc/src/_PDCLIB/_PDCLIB_load_lc_time.c | 165 + rocklibc/src/_PDCLIB/_PDCLIB_load_lines.c | 81 + rocklibc/src/_PDCLIB/_PDCLIB_naive_etod.c | 96 + rocklibc/src/_PDCLIB/_PDCLIB_naive_ptod.c | 97 + rocklibc/src/_PDCLIB/_PDCLIB_prepread.c | 42 + rocklibc/src/_PDCLIB/_PDCLIB_prepwrite.c | 39 + rocklibc/src/_PDCLIB/_PDCLIB_print.c | 493 ++ rocklibc/src/_PDCLIB/_PDCLIB_print_fp.c | 390 + rocklibc/src/_PDCLIB/_PDCLIB_print_fp_deci.c | 211 + rocklibc/src/_PDCLIB/_PDCLIB_print_fp_hexa.c | 268 + rocklibc/src/_PDCLIB/_PDCLIB_print_integer.c | 175 + rocklibc/src/_PDCLIB/_PDCLIB_print_string.c | 85 + rocklibc/src/_PDCLIB/_PDCLIB_realpath.c | 61 + rocklibc/src/_PDCLIB/_PDCLIB_remove.c | 42 + rocklibc/src/_PDCLIB/_PDCLIB_rename.c | 117 + rocklibc/src/_PDCLIB/_PDCLIB_scan.c | 781 ++ rocklibc/src/_PDCLIB/_PDCLIB_seed.c | 19 + rocklibc/src/_PDCLIB/_PDCLIB_seek.c | 81 + rocklibc/src/_PDCLIB/_PDCLIB_stdinit.c | 598 ++ rocklibc/src/_PDCLIB/_PDCLIB_strtod_prelim.c | 135 + rocklibc/src/_PDCLIB/_PDCLIB_strtok.c | 186 + rocklibc/src/_PDCLIB/_PDCLIB_strtox_main.c | 99 + rocklibc/src/_PDCLIB/_PDCLIB_strtox_prelim.c | 113 + rocklibc/src/_PDCLIB/assert.c | 73 + rocklibc/src/_PDCLIB/errno.c | 71 + rocklibc/src/_PDCLIB/stdarg.c | 120 + rocklibc/src/_dlmalloc/malloc-2.8.6.patch | 154 + rocklibc/src/_dlmalloc/malloc.c | 6348 +++++++++++++++++ rocklibc/src/_tzcode/Readme.txt | 10 + rocklibc/src/_tzcode/_PDCLIB_gmtcheck.c | 53 + rocklibc/src/_tzcode/_PDCLIB_gmtsub.c | 43 + .../src/_tzcode/_PDCLIB_increment_overflow.c | 45 + rocklibc/src/_tzcode/_PDCLIB_init_ttinfo.c | 35 + rocklibc/src/_tzcode/_PDCLIB_localsub.c | 164 + .../src/_tzcode/_PDCLIB_localtime_tzset.c | 46 + rocklibc/src/_tzcode/_PDCLIB_mktime_tzname.c | 528 ++ rocklibc/src/_tzcode/_PDCLIB_timesub.c | 190 + rocklibc/src/_tzcode/_PDCLIB_tzload.c | 683 ++ rocklibc/src/_tzcode/_PDCLIB_tzparse.c | 775 ++ rocklibc/src/_tzcode/_PDCLIB_tzset_unlocked.c | 185 + .../src/_tzcode/_PDCLIB_update_tzname_etc.c | 44 + rocklibc/src/ctype/isalnum.c | 38 + rocklibc/src/ctype/isalpha.c | 34 + rocklibc/src/ctype/isblank.c | 35 + rocklibc/src/ctype/iscntrl.c | 33 + rocklibc/src/ctype/isdigit.c | 34 + rocklibc/src/ctype/isgraph.c | 37 + rocklibc/src/ctype/islower.c | 35 + rocklibc/src/ctype/isprint.c | 38 + rocklibc/src/ctype/ispunct.c | 38 + rocklibc/src/ctype/isspace.c | 36 + rocklibc/src/ctype/isupper.c | 35 + rocklibc/src/ctype/isxdigit.c | 42 + rocklibc/src/ctype/tolower.c | 35 + rocklibc/src/ctype/toupper.c | 35 + rocklibc/src/inttypes/imaxabs.c | 32 + rocklibc/src/inttypes/imaxdiv.c | 39 + rocklibc/src/inttypes/strtoimax.c | 158 + rocklibc/src/inttypes/strtoumax.c | 122 + rocklibc/src/locale/localeconv.c | 32 + rocklibc/src/locale/setlocale.c | 269 + rocklibc/src/math/fabs.c | 114 + rocklibc/src/math/fdim.c | 74 + rocklibc/src/math/fmax.c | 105 + rocklibc/src/math/fmin.c | 105 + rocklibc/src/math/fpclassify.c | 161 + rocklibc/src/math/isfinite.c | 92 + rocklibc/src/math/isinf.c | 123 + rocklibc/src/math/isnan.c | 123 + rocklibc/src/math/isnormal.c | 110 + rocklibc/src/math/signbit.c | 69 + rocklibc/src/rockos/syscall.c | 97 + rocklibc/src/rockos/time.c | 10 + rocklibc/src/rockos/times.c | 12 + rocklibc/src/signal/raise.c | 135 + rocklibc/src/signal/signal.c | 84 + rocklibc/src/stdio/clearerr.c | 54 + rocklibc/src/stdio/fclose.c | 117 + rocklibc/src/stdio/feof.c | 28 + rocklibc/src/stdio/ferror.c | 28 + rocklibc/src/stdio/fflush.c | 71 + rocklibc/src/stdio/fgetc.c | 48 + rocklibc/src/stdio/fgetpos.c | 49 + rocklibc/src/stdio/fgets.c | 98 + rocklibc/src/stdio/fopen.c | 104 + rocklibc/src/stdio/fopen_s.c | 79 + rocklibc/src/stdio/fprintf.c | 46 + rocklibc/src/stdio/fputc.c | 55 + rocklibc/src/stdio/fputs.c | 87 + rocklibc/src/stdio/fread.c | 93 + rocklibc/src/stdio/freopen.c | 242 + rocklibc/src/stdio/freopen_s.c | 88 + rocklibc/src/stdio/fscanf.c | 41 + rocklibc/src/stdio/fseek.c | 103 + rocklibc/src/stdio/fsetpos.c | 56 + rocklibc/src/stdio/ftell.c | 113 + rocklibc/src/stdio/fwrite.c | 117 + rocklibc/src/stdio/getc.c | 28 + rocklibc/src/stdio/getchar.c | 28 + rocklibc/src/stdio/perror.c | 67 + rocklibc/src/stdio/printf.c | 47 + rocklibc/src/stdio/putc.c | 28 + rocklibc/src/stdio/putchar.c | 29 + rocklibc/src/stdio/puts.c | 80 + rocklibc/src/stdio/remove.c | 66 + rocklibc/src/stdio/rename.c | 103 + rocklibc/src/stdio/rewind.c | 29 + rocklibc/src/stdio/scanf.c | 42 + rocklibc/src/stdio/setbuf.c | 55 + rocklibc/src/stdio/setvbuf.c | 141 + rocklibc/src/stdio/snprintf.c | 46 + rocklibc/src/stdio/sprintf.c | 44 + rocklibc/src/stdio/sscanf.c | 39 + rocklibc/src/stdio/tmpfile.c | 133 + rocklibc/src/stdio/tmpfile_s.c | 79 + rocklibc/src/stdio/tmpnam.c | 47 + rocklibc/src/stdio/ungetc.c | 93 + rocklibc/src/stdio/vfprintf.c | 110 + rocklibc/src/stdio/vfscanf.c | 138 + rocklibc/src/stdio/vprintf.c | 50 + rocklibc/src/stdio/vscanf.c | 45 + rocklibc/src/stdio/vsnprintf.c | 88 + rocklibc/src/stdio/vsprintf.c | 47 + rocklibc/src/stdio/vsscanf.c | 115 + rocklibc/src/stdlib/_Exit.c | 34 + rocklibc/src/stdlib/abort.c | 40 + rocklibc/src/stdlib/abort_handler_s.c | 32 + rocklibc/src/stdlib/abs.c | 32 + rocklibc/src/stdlib/at_quick_exit.c | 73 + rocklibc/src/stdlib/atexit.c | 67 + rocklibc/src/stdlib/atoi.c | 28 + rocklibc/src/stdlib/atol.c | 28 + rocklibc/src/stdlib/atoll.c | 28 + rocklibc/src/stdlib/bsearch.c | 64 + rocklibc/src/stdlib/bsearch_s.c | 78 + rocklibc/src/stdlib/div.c | 40 + rocklibc/src/stdlib/exit.c | 40 + rocklibc/src/stdlib/getenv.c | 56 + rocklibc/src/stdlib/getenv_s.c | 110 + rocklibc/src/stdlib/ignore_handler_s.c | 31 + rocklibc/src/stdlib/labs.c | 32 + rocklibc/src/stdlib/ldiv.c | 40 + rocklibc/src/stdlib/llabs.c | 32 + rocklibc/src/stdlib/lldiv.c | 40 + rocklibc/src/stdlib/qsort.c | 188 + rocklibc/src/stdlib/qsort_s.c | 202 + rocklibc/src/stdlib/quick_exit.c | 40 + rocklibc/src/stdlib/rand.c | 34 + .../src/stdlib/set_constraint_handler_s.c | 48 + rocklibc/src/stdlib/srand.c | 28 + rocklibc/src/stdlib/strtod.c | 171 + rocklibc/src/stdlib/strtof.c | 169 + rocklibc/src/stdlib/strtol.c | 144 + rocklibc/src/stdlib/strtold.c | 169 + rocklibc/src/stdlib/strtoll.c | 138 + rocklibc/src/stdlib/strtoul.c | 124 + rocklibc/src/stdlib/strtoull.c | 119 + rocklibc/src/stdlib/system.c | 71 + rocklibc/src/string/memchr.c | 44 + rocklibc/src/string/memcmp.c | 46 + rocklibc/src/string/memcpy.c | 42 + rocklibc/src/string/memcpy_s.c | 92 + rocklibc/src/string/memmove.c | 55 + rocklibc/src/string/memmove_s.c | 87 + rocklibc/src/string/memset.c | 42 + rocklibc/src/string/memset_s.c | 73 + rocklibc/src/string/strcat.c | 55 + rocklibc/src/string/strcat_s.c | 103 + rocklibc/src/string/strchr.c | 41 + rocklibc/src/string/strcmp.c | 42 + rocklibc/src/string/strcoll.c | 37 + rocklibc/src/string/strcpy.c | 42 + rocklibc/src/string/strcpy_s.c | 89 + rocklibc/src/string/strcspn.c | 54 + rocklibc/src/string/strerror.c | 41 + rocklibc/src/string/strerror_s.c | 69 + rocklibc/src/string/strerrorlen_s.c | 29 + rocklibc/src/string/strlen.c | 36 + rocklibc/src/string/strncat.c | 64 + rocklibc/src/string/strncat_s.c | 118 + rocklibc/src/string/strncmp.c | 55 + rocklibc/src/string/strncpy.c | 59 + rocklibc/src/string/strncpy_s.c | 95 + rocklibc/src/string/strpbrk.c | 53 + rocklibc/src/string/strrchr.c | 47 + rocklibc/src/string/strspn.c | 55 + rocklibc/src/string/strstr.c | 56 + rocklibc/src/string/strtok.c | 64 + rocklibc/src/string/strtok_s.c | 72 + rocklibc/src/string/strxfrm.c | 54 + rocklibc/src/time/asctime.c | 47 + rocklibc/src/time/asctime_s.c | 63 + rocklibc/src/time/clock.c | 37 + rocklibc/src/time/ctime.c | 44 + rocklibc/src/time/ctime_s.c | 61 + rocklibc/src/time/difftime.c | 70 + rocklibc/src/time/gmtime.c | 55 + rocklibc/src/time/gmtime_s.c | 68 + rocklibc/src/time/localtime.c | 56 + rocklibc/src/time/localtime_s.c | 67 + rocklibc/src/time/mktime.c | 53 + rocklibc/src/time/strftime.c | 1788 +++++ rocklibc/src/time/time.c | 48 + rocklibc/src/time/timespec_get.c | 46 + sysroot/usr/include/assert.h | 50 + sysroot/usr/include/ctype.h | 110 + sysroot/usr/include/errno.h | 202 + sysroot/usr/include/fcntl.h | 19 + sysroot/usr/include/float.h | 82 + sysroot/usr/include/inttypes.h | 368 + sysroot/usr/include/iso646.h | 31 + sysroot/usr/include/limits.h | 50 + sysroot/usr/include/locale.h | 114 + sysroot/usr/include/math.h | 467 ++ sysroot/usr/include/pdclib/_PDCLIB_config.h | 915 +++ sysroot/usr/include/pdclib/_PDCLIB_defguard.h | 29 + sysroot/usr/include/pdclib/_PDCLIB_glue.h | 93 + sysroot/usr/include/pdclib/_PDCLIB_internal.h | 686 ++ sysroot/usr/include/pdclib/_PDCLIB_lib_ext1.h | 32 + .../include/pdclib/_PDCLIB_platform_errno.h | 6 + .../include/pdclib/_PDCLIB_platform_fcntl.h | 6 + sysroot/usr/include/pdclib/_PDCLIB_print.h | 145 + sysroot/usr/include/pdclib/_PDCLIB_tzcode.h | 153 + sysroot/usr/include/signal.h | 91 + sysroot/usr/include/stdalign.h | 30 + sysroot/usr/include/stdarg.h | 34 + sysroot/usr/include/stdbool.h | 24 + sysroot/usr/include/stddef.h | 55 + sysroot/usr/include/stdint.h | 236 + sysroot/usr/include/stdio.h | 935 +++ sysroot/usr/include/stdlib.h | 379 + sysroot/usr/include/stdnoreturn.h | 26 + sysroot/usr/include/string.h | 394 + sysroot/usr/include/sys/stat.h | 50 + sysroot/usr/include/sys/time.h | 21 + sysroot/usr/include/sys/times.h | 17 + sysroot/usr/include/sys/types.h | 29 + sysroot/usr/include/time.h | 191 + sysroot/usr/include/unistd.h | 28 + sysroot/usr/include/wctype.h | 152 + sysroot/usr/lib/rlibc.a | Bin 0 -> 271538 bytes 337 files changed, 47955 insertions(+), 114 deletions(-) create mode 100644 kernel/common.h delete mode 100644 libc/arch/i686/crt0.S delete mode 100644 libc/include/rock.h delete mode 100644 libc/include/string.h delete mode 100644 libc/makefile create mode 100644 programs/crt0.S create mode 100644 programs/crt0.s create mode 100644 programs/linker.ld create mode 100644 programs/main.c delete mode 100644 programs/origin.S create mode 100644 rocklibc/.gitignore create mode 100644 rocklibc/compile_commands.json create mode 100644 rocklibc/include/assert.h create mode 100644 rocklibc/include/ctype.h create mode 100644 rocklibc/include/errno.h create mode 100644 rocklibc/include/fcntl.h create mode 100644 rocklibc/include/float.h create mode 100644 rocklibc/include/inttypes.h create mode 100644 rocklibc/include/iso646.h create mode 100644 rocklibc/include/limits.h create mode 100644 rocklibc/include/locale.h create mode 100644 rocklibc/include/math.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_config.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_defguard.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_glue.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_internal.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_lib_ext1.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_platform_errno.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_platform_fcntl.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_print.h create mode 100644 rocklibc/include/pdclib/_PDCLIB_tzcode.h create mode 100644 rocklibc/include/signal.h create mode 100644 rocklibc/include/stdalign.h create mode 100644 rocklibc/include/stdarg.h create mode 100644 rocklibc/include/stdbool.h create mode 100644 rocklibc/include/stddef.h create mode 100644 rocklibc/include/stdint.h create mode 100644 rocklibc/include/stdio.h create mode 100644 rocklibc/include/stdlib.h create mode 100644 rocklibc/include/stdnoreturn.h create mode 100644 rocklibc/include/string.h create mode 100644 rocklibc/include/sys/stat.h create mode 100644 rocklibc/include/sys/time.h create mode 100644 rocklibc/include/sys/times.h create mode 100644 rocklibc/include/sys/types.h create mode 100644 rocklibc/include/time.h create mode 100644 rocklibc/include/unistd.h create mode 100644 rocklibc/include/wctype.h create mode 100644 rocklibc/makefile create mode 100644 rocklibc/src/_PDCLIB/Readme.txt create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_Exit.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_atomax.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_add.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_cmp.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_digit_log2.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_div.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_bigint.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_digit.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow10.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow2.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_log2.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul10.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul_pow10.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_bigint_shl.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_changemode.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_close.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_closeall.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_digits.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_filemode.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_fillbuffer.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_flushbuffer.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_fp_from_dbl.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_fp_from_ldbl.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_getstream.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_init_file_t.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_is_leap.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_isstream.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_load_lc_collate.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_load_lc_ctype.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_load_lc_messages.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_load_lc_monetary.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_load_lc_numeric.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_load_lc_time.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_load_lines.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_naive_etod.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_naive_ptod.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_prepread.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_prepwrite.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_print.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_print_fp.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_print_fp_deci.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_print_fp_hexa.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_print_integer.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_print_string.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_realpath.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_remove.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_rename.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_scan.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_seed.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_seek.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_stdinit.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_strtod_prelim.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_strtok.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_strtox_main.c create mode 100644 rocklibc/src/_PDCLIB/_PDCLIB_strtox_prelim.c create mode 100644 rocklibc/src/_PDCLIB/assert.c create mode 100644 rocklibc/src/_PDCLIB/errno.c create mode 100644 rocklibc/src/_PDCLIB/stdarg.c create mode 100644 rocklibc/src/_dlmalloc/malloc-2.8.6.patch create mode 100644 rocklibc/src/_dlmalloc/malloc.c create mode 100644 rocklibc/src/_tzcode/Readme.txt create mode 100644 rocklibc/src/_tzcode/_PDCLIB_gmtcheck.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_gmtsub.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_increment_overflow.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_init_ttinfo.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_localsub.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_localtime_tzset.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_mktime_tzname.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_timesub.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_tzload.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_tzparse.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_tzset_unlocked.c create mode 100644 rocklibc/src/_tzcode/_PDCLIB_update_tzname_etc.c create mode 100644 rocklibc/src/ctype/isalnum.c create mode 100644 rocklibc/src/ctype/isalpha.c create mode 100644 rocklibc/src/ctype/isblank.c create mode 100644 rocklibc/src/ctype/iscntrl.c create mode 100644 rocklibc/src/ctype/isdigit.c create mode 100644 rocklibc/src/ctype/isgraph.c create mode 100644 rocklibc/src/ctype/islower.c create mode 100644 rocklibc/src/ctype/isprint.c create mode 100644 rocklibc/src/ctype/ispunct.c create mode 100644 rocklibc/src/ctype/isspace.c create mode 100644 rocklibc/src/ctype/isupper.c create mode 100644 rocklibc/src/ctype/isxdigit.c create mode 100644 rocklibc/src/ctype/tolower.c create mode 100644 rocklibc/src/ctype/toupper.c create mode 100644 rocklibc/src/inttypes/imaxabs.c create mode 100644 rocklibc/src/inttypes/imaxdiv.c create mode 100644 rocklibc/src/inttypes/strtoimax.c create mode 100644 rocklibc/src/inttypes/strtoumax.c create mode 100644 rocklibc/src/locale/localeconv.c create mode 100644 rocklibc/src/locale/setlocale.c create mode 100644 rocklibc/src/math/fabs.c create mode 100644 rocklibc/src/math/fdim.c create mode 100644 rocklibc/src/math/fmax.c create mode 100644 rocklibc/src/math/fmin.c create mode 100644 rocklibc/src/math/fpclassify.c create mode 100644 rocklibc/src/math/isfinite.c create mode 100644 rocklibc/src/math/isinf.c create mode 100644 rocklibc/src/math/isnan.c create mode 100644 rocklibc/src/math/isnormal.c create mode 100644 rocklibc/src/math/signbit.c create mode 100644 rocklibc/src/rockos/syscall.c create mode 100644 rocklibc/src/rockos/time.c create mode 100644 rocklibc/src/rockos/times.c create mode 100644 rocklibc/src/signal/raise.c create mode 100644 rocklibc/src/signal/signal.c create mode 100644 rocklibc/src/stdio/clearerr.c create mode 100644 rocklibc/src/stdio/fclose.c create mode 100644 rocklibc/src/stdio/feof.c create mode 100644 rocklibc/src/stdio/ferror.c create mode 100644 rocklibc/src/stdio/fflush.c create mode 100644 rocklibc/src/stdio/fgetc.c create mode 100644 rocklibc/src/stdio/fgetpos.c create mode 100644 rocklibc/src/stdio/fgets.c create mode 100644 rocklibc/src/stdio/fopen.c create mode 100644 rocklibc/src/stdio/fopen_s.c create mode 100644 rocklibc/src/stdio/fprintf.c create mode 100644 rocklibc/src/stdio/fputc.c create mode 100644 rocklibc/src/stdio/fputs.c create mode 100644 rocklibc/src/stdio/fread.c create mode 100644 rocklibc/src/stdio/freopen.c create mode 100644 rocklibc/src/stdio/freopen_s.c create mode 100644 rocklibc/src/stdio/fscanf.c create mode 100644 rocklibc/src/stdio/fseek.c create mode 100644 rocklibc/src/stdio/fsetpos.c create mode 100644 rocklibc/src/stdio/ftell.c create mode 100644 rocklibc/src/stdio/fwrite.c create mode 100644 rocklibc/src/stdio/getc.c create mode 100644 rocklibc/src/stdio/getchar.c create mode 100644 rocklibc/src/stdio/perror.c create mode 100644 rocklibc/src/stdio/printf.c create mode 100644 rocklibc/src/stdio/putc.c create mode 100644 rocklibc/src/stdio/putchar.c create mode 100644 rocklibc/src/stdio/puts.c create mode 100644 rocklibc/src/stdio/remove.c create mode 100644 rocklibc/src/stdio/rename.c create mode 100644 rocklibc/src/stdio/rewind.c create mode 100644 rocklibc/src/stdio/scanf.c create mode 100644 rocklibc/src/stdio/setbuf.c create mode 100644 rocklibc/src/stdio/setvbuf.c create mode 100644 rocklibc/src/stdio/snprintf.c create mode 100644 rocklibc/src/stdio/sprintf.c create mode 100644 rocklibc/src/stdio/sscanf.c create mode 100644 rocklibc/src/stdio/tmpfile.c create mode 100644 rocklibc/src/stdio/tmpfile_s.c create mode 100644 rocklibc/src/stdio/tmpnam.c create mode 100644 rocklibc/src/stdio/ungetc.c create mode 100644 rocklibc/src/stdio/vfprintf.c create mode 100644 rocklibc/src/stdio/vfscanf.c create mode 100644 rocklibc/src/stdio/vprintf.c create mode 100644 rocklibc/src/stdio/vscanf.c create mode 100644 rocklibc/src/stdio/vsnprintf.c create mode 100644 rocklibc/src/stdio/vsprintf.c create mode 100644 rocklibc/src/stdio/vsscanf.c create mode 100644 rocklibc/src/stdlib/_Exit.c create mode 100644 rocklibc/src/stdlib/abort.c create mode 100644 rocklibc/src/stdlib/abort_handler_s.c create mode 100644 rocklibc/src/stdlib/abs.c create mode 100644 rocklibc/src/stdlib/at_quick_exit.c create mode 100644 rocklibc/src/stdlib/atexit.c create mode 100644 rocklibc/src/stdlib/atoi.c create mode 100644 rocklibc/src/stdlib/atol.c create mode 100644 rocklibc/src/stdlib/atoll.c create mode 100644 rocklibc/src/stdlib/bsearch.c create mode 100644 rocklibc/src/stdlib/bsearch_s.c create mode 100644 rocklibc/src/stdlib/div.c create mode 100644 rocklibc/src/stdlib/exit.c create mode 100644 rocklibc/src/stdlib/getenv.c create mode 100644 rocklibc/src/stdlib/getenv_s.c create mode 100644 rocklibc/src/stdlib/ignore_handler_s.c create mode 100644 rocklibc/src/stdlib/labs.c create mode 100644 rocklibc/src/stdlib/ldiv.c create mode 100644 rocklibc/src/stdlib/llabs.c create mode 100644 rocklibc/src/stdlib/lldiv.c create mode 100644 rocklibc/src/stdlib/qsort.c create mode 100644 rocklibc/src/stdlib/qsort_s.c create mode 100644 rocklibc/src/stdlib/quick_exit.c create mode 100644 rocklibc/src/stdlib/rand.c create mode 100644 rocklibc/src/stdlib/set_constraint_handler_s.c create mode 100644 rocklibc/src/stdlib/srand.c create mode 100644 rocklibc/src/stdlib/strtod.c create mode 100644 rocklibc/src/stdlib/strtof.c create mode 100644 rocklibc/src/stdlib/strtol.c create mode 100644 rocklibc/src/stdlib/strtold.c create mode 100644 rocklibc/src/stdlib/strtoll.c create mode 100644 rocklibc/src/stdlib/strtoul.c create mode 100644 rocklibc/src/stdlib/strtoull.c create mode 100644 rocklibc/src/stdlib/system.c create mode 100644 rocklibc/src/string/memchr.c create mode 100644 rocklibc/src/string/memcmp.c create mode 100644 rocklibc/src/string/memcpy.c create mode 100644 rocklibc/src/string/memcpy_s.c create mode 100644 rocklibc/src/string/memmove.c create mode 100644 rocklibc/src/string/memmove_s.c create mode 100644 rocklibc/src/string/memset.c create mode 100644 rocklibc/src/string/memset_s.c create mode 100644 rocklibc/src/string/strcat.c create mode 100644 rocklibc/src/string/strcat_s.c create mode 100644 rocklibc/src/string/strchr.c create mode 100644 rocklibc/src/string/strcmp.c create mode 100644 rocklibc/src/string/strcoll.c create mode 100644 rocklibc/src/string/strcpy.c create mode 100644 rocklibc/src/string/strcpy_s.c create mode 100644 rocklibc/src/string/strcspn.c create mode 100644 rocklibc/src/string/strerror.c create mode 100644 rocklibc/src/string/strerror_s.c create mode 100644 rocklibc/src/string/strerrorlen_s.c create mode 100644 rocklibc/src/string/strlen.c create mode 100644 rocklibc/src/string/strncat.c create mode 100644 rocklibc/src/string/strncat_s.c create mode 100644 rocklibc/src/string/strncmp.c create mode 100644 rocklibc/src/string/strncpy.c create mode 100644 rocklibc/src/string/strncpy_s.c create mode 100644 rocklibc/src/string/strpbrk.c create mode 100644 rocklibc/src/string/strrchr.c create mode 100644 rocklibc/src/string/strspn.c create mode 100644 rocklibc/src/string/strstr.c create mode 100644 rocklibc/src/string/strtok.c create mode 100644 rocklibc/src/string/strtok_s.c create mode 100644 rocklibc/src/string/strxfrm.c create mode 100644 rocklibc/src/time/asctime.c create mode 100644 rocklibc/src/time/asctime_s.c create mode 100644 rocklibc/src/time/clock.c create mode 100644 rocklibc/src/time/ctime.c create mode 100644 rocklibc/src/time/ctime_s.c create mode 100644 rocklibc/src/time/difftime.c create mode 100644 rocklibc/src/time/gmtime.c create mode 100644 rocklibc/src/time/gmtime_s.c create mode 100644 rocklibc/src/time/localtime.c create mode 100644 rocklibc/src/time/localtime_s.c create mode 100644 rocklibc/src/time/mktime.c create mode 100644 rocklibc/src/time/strftime.c create mode 100644 rocklibc/src/time/time.c create mode 100644 rocklibc/src/time/timespec_get.c create mode 100644 sysroot/usr/include/assert.h create mode 100644 sysroot/usr/include/ctype.h create mode 100644 sysroot/usr/include/errno.h create mode 100644 sysroot/usr/include/fcntl.h create mode 100644 sysroot/usr/include/float.h create mode 100644 sysroot/usr/include/inttypes.h create mode 100644 sysroot/usr/include/iso646.h create mode 100644 sysroot/usr/include/limits.h create mode 100644 sysroot/usr/include/locale.h create mode 100644 sysroot/usr/include/math.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_config.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_defguard.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_glue.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_internal.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_lib_ext1.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_platform_errno.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_platform_fcntl.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_print.h create mode 100644 sysroot/usr/include/pdclib/_PDCLIB_tzcode.h create mode 100644 sysroot/usr/include/signal.h create mode 100644 sysroot/usr/include/stdalign.h create mode 100644 sysroot/usr/include/stdarg.h create mode 100644 sysroot/usr/include/stdbool.h create mode 100644 sysroot/usr/include/stddef.h create mode 100644 sysroot/usr/include/stdint.h create mode 100644 sysroot/usr/include/stdio.h create mode 100644 sysroot/usr/include/stdlib.h create mode 100644 sysroot/usr/include/stdnoreturn.h create mode 100644 sysroot/usr/include/string.h create mode 100644 sysroot/usr/include/sys/stat.h create mode 100644 sysroot/usr/include/sys/time.h create mode 100644 sysroot/usr/include/sys/times.h create mode 100644 sysroot/usr/include/sys/types.h create mode 100644 sysroot/usr/include/time.h create mode 100644 sysroot/usr/include/unistd.h create mode 100644 sysroot/usr/include/wctype.h create mode 100644 sysroot/usr/lib/rlibc.a diff --git a/compile_commands.json b/compile_commands.json index c07e8d7..c2308ae 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -1,4 +1,327 @@ [ + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/globals.c.o", + "kernel/globals.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/globals.c", + "output": "/home/slinky/source/RockOS/obj/kernel/globals.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/kmain.c.o", + "kernel/kmain.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/kmain.c", + "output": "/home/slinky/source/RockOS/obj/kernel/kmain.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/pic/pic.c.o", + "kernel/drivers/pic/pic.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/pic/pic.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/pic/pic.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/vga/vga.c.o", + "kernel/drivers/vga/vga.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/vga/vga.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/vga/vga.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/ide/ide.c.o", + "kernel/drivers/ide/ide.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/ide/ide.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/ide/ide.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/ps2/ps2.c.o", + "kernel/drivers/ps2/ps2.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/ps2/ps2.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/ps2/ps2.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/iso/iso.c.o", + "kernel/drivers/iso/iso.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/iso/iso.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/iso/iso.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/gdt.c.o", + "kernel/gdt.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/gdt.c", + "output": "/home/slinky/source/RockOS/obj/kernel/gdt.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/memory/mm.c.o", + "kernel/memory/mm.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/memory/mm.c", + "output": "/home/slinky/source/RockOS/obj/kernel/memory/mm.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/interrupts.c.o", + "kernel/interrupts.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/interrupts.c", + "output": "/home/slinky/source/RockOS/obj/kernel/interrupts.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/syscall.c.o", + "kernel/syscall.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/syscall.c", + "output": "/home/slinky/source/RockOS/obj/kernel/syscall.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/lib/stream.c.o", + "kernel/lib/stream.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/lib/stream.c", + "output": "/home/slinky/source/RockOS/obj/kernel/lib/stream.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/lib/memory.c.o", + "kernel/lib/memory.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/lib/memory.c", + "output": "/home/slinky/source/RockOS/obj/kernel/lib/memory.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/lib/print.c.o", + "kernel/lib/print.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/lib/print.c", + "output": "/home/slinky/source/RockOS/obj/kernel/lib/print.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/lib/tasks.c.o", + "kernel/lib/tasks.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/lib/tasks.c", + "output": "/home/slinky/source/RockOS/obj/kernel/lib/tasks.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/scheduler.c.o", + "kernel/scheduler.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/scheduler.c", + "output": "/home/slinky/source/RockOS/obj/kernel/scheduler.c.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/syscall.S.o", + "kernel/syscall.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/syscall.S", + "output": "/home/slinky/source/RockOS/obj/kernel/syscall.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/common.S.o", + "kernel/common.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/common.S", + "output": "/home/slinky/source/RockOS/obj/kernel/common.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/pic/pic.S.o", + "kernel/drivers/pic/pic.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/pic/pic.S", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/pic/pic.S.o" + }, { "arguments": [ "/home/slinky/opt/cross/bin/i686-elf-gcc", @@ -15,5 +338,107 @@ "directory": "/home/slinky/source/RockOS", "file": "/home/slinky/source/RockOS/kernel/drivers/pit/pit.S", "output": "/home/slinky/source/RockOS/obj/kernel/drivers/pit/pit.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/ps2/ps2.S.o", + "kernel/drivers/ps2/ps2.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/ps2/ps2.S", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/ps2/ps2.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/memory/mm_stubs.S.o", + "kernel/memory/mm_stubs.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/memory/mm_stubs.S", + "output": "/home/slinky/source/RockOS/obj/kernel/memory/mm_stubs.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/boot/boot.S.o", + "kernel/boot/boot.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/boot/boot.S", + "output": "/home/slinky/source/RockOS/obj/kernel/boot/boot.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/scheduler.S.o", + "kernel/scheduler.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/scheduler.S", + "output": "/home/slinky/source/RockOS/obj/kernel/scheduler.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/gdt.S.o", + "kernel/gdt.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/gdt.S", + "output": "/home/slinky/source/RockOS/obj/kernel/gdt.S.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/interrupts.S.o", + "kernel/interrupts.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/interrupts.S", + "output": "/home/slinky/source/RockOS/obj/kernel/interrupts.S.o" } ] diff --git a/kernel/boot/boot.S b/kernel/boot/boot.S index 0e41fab..73f7ada 100644 --- a/kernel/boot/boot.S +++ b/kernel/boot/boot.S @@ -37,6 +37,7 @@ higher: push %eax call kmain loop: + hlt jmp loop .section .bss diff --git a/kernel/common.h b/kernel/common.h new file mode 100644 index 0000000..b7c189a --- /dev/null +++ b/kernel/common.h @@ -0,0 +1,10 @@ +#ifndef KCOMMON_H +#define KCOMMON_H + +#include + +void enable_interrupts(); +void disable_interrupts(); +uint32_t fetch_cr3(); + +#endif \ No newline at end of file diff --git a/kernel/drivers/pit/pit.S b/kernel/drivers/pit/pit.S index c16c64d..0271c60 100644 --- a/kernel/drivers/pit/pit.S +++ b/kernel/drivers/pit/pit.S @@ -1,6 +1,6 @@ .code32 .global init_pit -init_pit: # tickrate: 1193182/1000 = 0x04A9 (1000hz) (1ms) +init_pit: movb $0x36, %al outb %al, $0x43 diff --git a/kernel/gdt.c b/kernel/gdt.c index c4bf167..c6bff54 100644 --- a/kernel/gdt.c +++ b/kernel/gdt.c @@ -129,6 +129,7 @@ void init_gdt() { for (uint32_t i = 0; i < sizeof(tss_entry); i++) { ((char*)&tss)[i] = 0; } + tss.ss0 = 0x10; tss.iomap_base = sizeof(tss_entry); @@ -136,6 +137,7 @@ void init_gdt() { gdtr.limit = 6 * sizeof(uint64_t) - 1; gdtr.base = (uint32_t)&gdt; + load_gdt(); tss_flush(); } diff --git a/kernel/interrupts.S b/kernel/interrupts.S index d2765cd..00e6d47 100644 --- a/kernel/interrupts.S +++ b/kernel/interrupts.S @@ -14,7 +14,7 @@ isr\num: jmp isr_common_stub .endm -.extern common_interrupt_handler +.extern common_interrupt_handler # interrupts.c isr_common_stub: pushal @@ -40,18 +40,20 @@ ISR_ERRCODE 14 # Page Fault (Has Error Code!) // This is a special case so we need to handle it for task switching .global isr32 +.extern switch_context # scheduler.c +.extern send_eoi_master # drivers/pic/pic.c isr32: cli + pushal - + pushl %esp - call schedule_next_task + call switch_context movl %eax, %esp call send_eoi_master popal - sti iret diff --git a/kernel/interrupts.c b/kernel/interrupts.c index faecda2..f9838c1 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -34,9 +34,8 @@ typedef struct __attribute__((packed)) { uint32_t eip, cs, eflags, useresp, ss; } registers; +// (interrupts.S) extern void load_idt(void); - -// isr stubs extern void isr0(); extern void isr1(); extern void isr8(); @@ -127,10 +126,6 @@ void common_interrupt_handler(registers *args) { while(1); break; } - case 32: - // wake the PIT timer driver - send_eoi_master(); - break; case 33: { uint8_t data = ps2_read_data(); send_eoi_master(); diff --git a/kernel/kmain.c b/kernel/kmain.c index bbd9177..500f377 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -1,8 +1,8 @@ #include "multiboot.h" #include "interrupts.h" -#include "elf.h" #include "gdt.h" #include "scheduler.h" +#include "common.h" #include #include @@ -20,21 +20,22 @@ #include #include -extern void enable_interrupts(); -extern void disable_interrupts(); -extern uint32_t fetch_cr3(); - extern char __kernel_start; extern char __kernel_end; -void kernel_test_task() { - while (1) { - kprintf("task sleeping...\n"); - sleep(10000000); +void first_task() { + kprintf("task started\n"); + int i = 5; + while (i--) { + sleep(1000); + kprintf("task awake [%d]\n", i); } + kprintf("exiting\n"); + exit(); } void kmain(uint32_t magic, multiboot_info* mbi) { + disable_interrupts(); if (!(mbi->flags & (1 << 6))) { return; } @@ -54,9 +55,14 @@ void kmain(uint32_t magic, multiboot_info* mbi) { kprintf("basic initializations complete\n"); - disable_interrupts(); + disable_interrupts(); // just paranoid... do it again init_scheduler(); enable_interrupts(); - while(1) yield(); + create_task((uint32_t)first_task, fetch_cr3()); + + while(1) { + sleep(5000); + kprintf("kernel awake\n"); + } } diff --git a/kernel/process.h b/kernel/process.h index 11f7f2d..410fb50 100644 --- a/kernel/process.h +++ b/kernel/process.h @@ -6,6 +6,7 @@ typedef enum { STATE_READY, STATE_SLEEPING, + STATE_BLOCKED, STATE_DEAD } process_state_t; @@ -15,6 +16,7 @@ typedef struct { uint32_t cr3; process_state_t state; uint32_t sleep; + void* next; } __attribute__((packed)) process_t; #endif \ No newline at end of file diff --git a/kernel/scheduler.S b/kernel/scheduler.S index 8f1d91e..fa526e0 100644 --- a/kernel/scheduler.S +++ b/kernel/scheduler.S @@ -1,12 +1,31 @@ -.code32 -.extern schedule_next_task + + +.code32 .global yield -yield: - cli - pushal - push %esp - call schedule_next_task - movl %eax, %esp - popal - sti - ret \ No newline at end of file +.extern schedule_next_task +yield: # void yield() + cli + + pushfl + pushl %cs + + movl 8(%esp), %eax + pushl %eax + + movl 4(%esp), %ebx # Get CS + movl %ebx, 8(%esp) # Move CS over Old EIP + movl 0(%esp), %ebx # Get Return EIP + movl %ebx, 4(%esp) # Move Return EIP over CS + addl $4, %esp # Adjust stack pointer up. + + # the stack now looks like a hardware interrupt just happened, even though we never called one. + + pushal + + pushl %esp + call switch_context + movl %eax, %esp + + popal + sti + iret \ No newline at end of file diff --git a/kernel/scheduler.c b/kernel/scheduler.c index ab80e57..0a9ae5d 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -5,24 +5,30 @@ #include +#include "common.h" #include "process.h" #include "scheduler.h" static process_t* process_table; -static spinlock_t process_table_lock = {0}; static int current_process = 0; static int total_processes = 0; -extern uint32_t fetch_cr3(); - #define IDLE_TASK_PID 1 static void idle_task() { while (1) asm volatile("hlt"); } -uint32_t schedule_next_task(uint32_t current_esp) { - spin_lock(&process_table_lock); +static void lock_scheduler() { + disable_interrupts(); +} + +static void unlock_scheduler() { + enable_interrupts(); +} + +// called from isr and yield, interrupts are already disabled and re enabled in the isr/yield func +uint32_t switch_context(uint32_t current_esp) { process_table[current_process].esp = current_esp; for (int i = 0; i < total_processes; i++) { @@ -39,6 +45,7 @@ uint32_t schedule_next_task(uint32_t current_esp) { int next_process = current_process; int found_ready = 0; + while (1) { next_process = (next_process + 1) % total_processes; if (next_process != IDLE_TASK_PID && process_table[next_process].state == STATE_READY) { @@ -66,10 +73,7 @@ uint32_t schedule_next_task(uint32_t current_esp) { load_pd(process_table[current_process].cr3); } - uint32_t rtn = process_table[current_process].esp; - spin_unlock(&process_table_lock); - - return rtn; + return process_table[current_process].esp; } void init_scheduler() { @@ -94,9 +98,19 @@ int create_task(uint32_t entry_point, uint32_t cr3) { return 0; } - spin_lock(&process_table_lock); + lock_scheduler(); + + // default to a new task, but if we find a dead one, re use it process_t* process = &process_table[total_processes]; - process->pid = total_processes; + uint32_t pid = total_processes; + for (uint32_t i = 0; i < total_processes; i++) { + if (process_table[i].state == STATE_DEAD) { + process = &process_table[i]; + pid = i; + } + } + + process->pid = pid; process->cr3 = cr3; process->state = STATE_READY; process->sleep = 0; @@ -118,19 +132,24 @@ int create_task(uint32_t entry_point, uint32_t cr3) { *(--esp) = 0; // EDI process->esp = (uint32_t)esp; - spin_unlock(&process_table_lock); - total_processes++; + unlock_scheduler(); return 1; } -void sleep(uint32_t ticks) { - if (ticks == 0) return; - - spin_lock(&process_table_lock); - process_table[current_process].sleep = ticks; +void sleep(uint32_t ms) { + if (ms == 0) return; + lock_scheduler(); + process_table[current_process].sleep = ms; process_table[current_process].state = STATE_SLEEPING; - spin_unlock(&process_table_lock); - yield(); -} \ No newline at end of file + unlock_scheduler(); +} + +void exit() { + lock_scheduler(); + process_table[current_process].state = STATE_DEAD; + yield(); // yield forever + unlock_scheduler(); +} + diff --git a/kernel/scheduler.h b/kernel/scheduler.h index a0d825e..a02ceb8 100644 --- a/kernel/scheduler.h +++ b/kernel/scheduler.h @@ -7,7 +7,8 @@ void init_scheduler(); int create_task(uint32_t entry_point, uint32_t cr3); -void sleep(uint32_t ticks); +void sleep(uint32_t ms); void yield(); +void exit(); #endif \ No newline at end of file diff --git a/kernel/syscall.c b/kernel/syscall.c index ef4e60e..bbe6993 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1,6 +1,6 @@ #include -#include "lib/print.h" +#include "scheduler.h" typedef struct registers { uint32_t gs, fs, es, ds; // Pushed manually @@ -9,19 +9,35 @@ typedef struct registers { uint32_t eip, cs, eflags, useresp, ss; // Pushed automatically by CPU } registers_t; -int32_t sys_vga_text_write(char* buf); +int32_t sys_exit(); +int32_t sys_read(); +int32_t sys_write(); +int32_t sys_open(); +int32_t sys_close(); +int32_t sys_brk(); int32_t syscall(registers_t* regs) { switch(regs->eax) { - case 1: { - return sys_vga_text_write((char*)regs->ebx); - } + case 1: return sys_exit(); + case 3: return sys_read(); + case 4: return sys_write(); + case 5: return sys_open(); + case 6: return sys_close(); + case 12: return sys_brk(); default: return -1; } } -int32_t sys_vga_text_write(char* buf) { - kprintf(buf); +int32_t sys_exit() { + exit(); + return 0; +} + +int32_t sys_read() { + return 0; +} + +int32_t sys_write() { return 0; } \ No newline at end of file diff --git a/libc/arch/i686/crt0.S b/libc/arch/i686/crt0.S deleted file mode 100644 index e69de29..0000000 diff --git a/libc/include/rock.h b/libc/include/rock.h deleted file mode 100644 index 59f6303..0000000 --- a/libc/include/rock.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef LIBC_ROCK_H -#define LIBC_ROCK_H - -#include - -static inline int32_t syscall(int num, uint32_t arg1, uint32_t arg2, uint32_t arg3) { - int32_t ret; - __asm__ __volatile__ ( - "int $0x80" - : "=a" (ret) - : "0" (num), "b" (arg1), "c" (arg2), "d" (arg3) - : "memory" - ); - return ret; -} - -#endif \ No newline at end of file diff --git a/libc/include/string.h b/libc/include/string.h deleted file mode 100644 index ed43a62..0000000 --- a/libc/include/string.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef LIBC_STRING_H -#define LIBC_STRING_H - -#include - -void* memcpy(void* dst, const void* src, size_t n); -void* memset(void* dst, int c, size_t n); -void* memmove(void* dst, const void* src, size_t n); -int memcmp(const void* s1, const void* s2, size_t n); - -#endif \ No newline at end of file diff --git a/libc/makefile b/libc/makefile deleted file mode 100644 index e69de29..0000000 diff --git a/programs/crt0.S b/programs/crt0.S new file mode 100644 index 0000000..5521689 --- /dev/null +++ b/programs/crt0.S @@ -0,0 +1,24 @@ +.global _start +.intel_syntax noprefix + +.section .text +_start: + xor ebp, ebp + push ebp + mov ebp, esp + + mov eax, [esp + 4] + lea ebx, [esp + 8] + lea ecx, [esp + 12] + + push ecx + push ebx + push eax + + call main + + push eax + call exit + +1: hlt + jmp 1b \ No newline at end of file diff --git a/programs/crt0.s b/programs/crt0.s new file mode 100644 index 0000000..8c72caa --- /dev/null +++ b/programs/crt0.s @@ -0,0 +1,28 @@ +# 0 "crt0.S" +# 0 "" +# 0 "" +# 1 "crt0.S" +.global _start +.intel_syntax noprefix + +.section .text +_start: + xor ebp, ebp + push ebp + mov ebp, esp + + mov eax, [esp + 4] + lea ebx, [esp + 8] + lea ecx, [esp + 12] + + push ecx + push ebx + push eax + + call main + + push eax + call exit + +1: hlt + jmp 1b diff --git a/programs/linker.ld b/programs/linker.ld new file mode 100644 index 0000000..03d6e3c --- /dev/null +++ b/programs/linker.ld @@ -0,0 +1,31 @@ +ENTRY(_start) + +SECTIONS +{ + . = 0x40000000; + + .text ALIGN(4K) : + { + /* Force the crt0.o entry code to be placed FIRST in memory */ + KEEP(*crt0.o(.text)) + *(.text .text.*) + } + + .rodata ALIGN(4K) : + { + *(.rodata .rodata.*) + } + + .data ALIGN(4K) : + { + *(.data .data.*) + } + + .bss ALIGN(4K) : + { + _bss_start = .; + *(.bss .bss.*) + *(COMMON) + _bss_end = .; + } +} \ No newline at end of file diff --git a/programs/main.c b/programs/main.c new file mode 100644 index 0000000..69d8084 --- /dev/null +++ b/programs/main.c @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char** argv) { + printf("Hello, World from RockOS!\n"); + + return 0; +} \ No newline at end of file diff --git a/programs/makefile b/programs/makefile index f84e57b..c88a74f 100644 --- a/programs/makefile +++ b/programs/makefile @@ -1,16 +1,23 @@ CC = i686-elf-gcc LD = i686-elf-ld -CFLAGS := -ffreestanding -O2 -Wall -Wextra +CFLAGS = -ffreestanding -O2 -Wall -Wextra -I../rocklibc/include +LDFLAGS = -m elf_i386 -nostdlib -all: origin.elf +TARGET = origin.elf -origin.o: origin.S - $(CC) -c origin.S -o origin.o $(CFLAGS) +all: $(TARGET) -origin.elf: origin.o - $(LD) -Ttext 0x40000000 origin.o -o origin.elf - mv origin.elf ../isodir/boot +crt0.o: crt0.s + $(CC) $(CFLAGS) -c crt0.s -o crt0.o + +main.o: main.c + $(CC) $(CFLAGS) -c main.c -o main.o + +$(TARGET): crt0.o main.o ../rocklibc/rlibc.a + $(LD) $(LDFLAGS) -T linker.ld crt0.o main.o ../rocklibc/rlibc.a $(shell $(CC) -print-libgcc-file-name) -o $(TARGET) clean: - rm -f origin.o origin.elf \ No newline at end of file + rm -f *.o $(TARGET) + +.PHONY: all clean \ No newline at end of file diff --git a/programs/origin.S b/programs/origin.S deleted file mode 100644 index 049de3c..0000000 --- a/programs/origin.S +++ /dev/null @@ -1,16 +0,0 @@ -.code32 - -.section .text -.global _start -_start: - mov $1, %eax - mov $(message), %ebx - mov $0, %ecx - mov $0, %edx - int $0x80 -loop: - jmp loop - -.section .data -message: - .asciz "Hello, Userland!\n"; \ No newline at end of file diff --git a/rocklibc/.gitignore b/rocklibc/.gitignore new file mode 100644 index 0000000..aa00c4e --- /dev/null +++ b/rocklibc/.gitignore @@ -0,0 +1 @@ +*.a \ No newline at end of file diff --git a/rocklibc/compile_commands.json b/rocklibc/compile_commands.json new file mode 100644 index 0000000..0dbbd48 --- /dev/null +++ b/rocklibc/compile_commands.json @@ -0,0 +1,4937 @@ +[ + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_closeall.o", + "src/_PDCLIB/_PDCLIB_closeall.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_closeall.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_closeall.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_getstream.o", + "src/_PDCLIB/_PDCLIB_getstream.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_getstream.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_getstream.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_from_pow2.o", + "src/_PDCLIB/_PDCLIB_bigint_from_pow2.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow2.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow2.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_seek.o", + "src/_PDCLIB/_PDCLIB_seek.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_seek.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_seek.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_filemode.o", + "src/_PDCLIB/_PDCLIB_filemode.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_filemode.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_filemode.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_realpath.o", + "src/_PDCLIB/_PDCLIB_realpath.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_realpath.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_realpath.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_mul_pow10.o", + "src/_PDCLIB/_PDCLIB_bigint_mul_pow10.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul_pow10.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul_pow10.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_remove.o", + "src/_PDCLIB/_PDCLIB_remove.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_remove.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_remove.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_seed.o", + "src/_PDCLIB/_PDCLIB_seed.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_seed.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_seed.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_mul.o", + "src/_PDCLIB/_PDCLIB_bigint_mul.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_print_fp_hexa.o", + "src/_PDCLIB/_PDCLIB_print_fp_hexa.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_hexa.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_hexa.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_log2.o", + "src/_PDCLIB/_PDCLIB_bigint_log2.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_log2.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_log2.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_prepwrite.o", + "src/_PDCLIB/_PDCLIB_prepwrite.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_prepwrite.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_prepwrite.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/assert.o", + "src/_PDCLIB/assert.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/assert.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/assert.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_load_lc_ctype.o", + "src/_PDCLIB/_PDCLIB_load_lc_ctype.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_ctype.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_ctype.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_div.o", + "src/_PDCLIB/_PDCLIB_bigint_div.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_div.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_div.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_naive_ptod.o", + "src/_PDCLIB/_PDCLIB_naive_ptod.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_naive_ptod.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_naive_ptod.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_cmp.o", + "src/_PDCLIB/_PDCLIB_bigint_cmp.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_cmp.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_cmp.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_digits.o", + "src/_PDCLIB/_PDCLIB_digits.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_digits.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_digits.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_naive_etod.o", + "src/_PDCLIB/_PDCLIB_naive_etod.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_naive_etod.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_naive_etod.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_prepread.o", + "src/_PDCLIB/_PDCLIB_prepread.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_prepread.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_prepread.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_print.o", + "src/_PDCLIB/_PDCLIB_print.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_stdinit.o", + "src/_PDCLIB/_PDCLIB_stdinit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_stdinit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_stdinit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_strtox_prelim.o", + "src/_PDCLIB/_PDCLIB_strtox_prelim.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtox_prelim.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtox_prelim.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_print_integer.o", + "src/_PDCLIB/_PDCLIB_print_integer.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_integer.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_integer.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_load_lc_monetary.o", + "src/_PDCLIB/_PDCLIB_load_lc_monetary.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_monetary.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_monetary.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_load_lc_messages.o", + "src/_PDCLIB/_PDCLIB_load_lc_messages.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_messages.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_messages.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_rename.o", + "src/_PDCLIB/_PDCLIB_rename.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_rename.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_rename.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/errno.o", + "src/_PDCLIB/errno.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/errno.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/errno.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_fillbuffer.o", + "src/_PDCLIB/_PDCLIB_fillbuffer.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_fillbuffer.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_fillbuffer.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_fp_from_dbl.o", + "src/_PDCLIB/_PDCLIB_fp_from_dbl.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_dbl.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_dbl.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_init_file_t.o", + "src/_PDCLIB/_PDCLIB_init_file_t.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_init_file_t.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_init_file_t.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_is_leap.o", + "src/_PDCLIB/_PDCLIB_is_leap.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_is_leap.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_is_leap.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_strtok.o", + "src/_PDCLIB/_PDCLIB_strtok.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtok.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtok.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_fp_from_ldbl.o", + "src/_PDCLIB/_PDCLIB_fp_from_ldbl.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_ldbl.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_ldbl.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_strtod_prelim.o", + "src/_PDCLIB/_PDCLIB_strtod_prelim.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtod_prelim.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtod_prelim.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_load_lc_numeric.o", + "src/_PDCLIB/_PDCLIB_load_lc_numeric.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_numeric.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_numeric.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_strtox_main.o", + "src/_PDCLIB/_PDCLIB_strtox_main.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtox_main.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_strtox_main.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_load_lc_collate.o", + "src/_PDCLIB/_PDCLIB_load_lc_collate.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_collate.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_collate.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_close.o", + "src/_PDCLIB/_PDCLIB_close.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_close.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_close.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_load_lc_time.o", + "src/_PDCLIB/_PDCLIB_load_lc_time.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_time.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_time.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_scan.o", + "src/_PDCLIB/_PDCLIB_scan.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_scan.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_scan.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_digit_log2.o", + "src/_PDCLIB/_PDCLIB_bigint_digit_log2.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_digit_log2.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_digit_log2.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_load_lines.o", + "src/_PDCLIB/_PDCLIB_load_lines.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lines.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_load_lines.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_atomax.o", + "src/_PDCLIB/_PDCLIB_atomax.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_atomax.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_atomax.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/stdarg.o", + "src/_PDCLIB/stdarg.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/stdarg.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/stdarg.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_flushbuffer.o", + "src/_PDCLIB/_PDCLIB_flushbuffer.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_flushbuffer.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_flushbuffer.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_Exit.o", + "src/_PDCLIB/_PDCLIB_Exit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_Exit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_Exit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_print_fp.o", + "src/_PDCLIB/_PDCLIB_print_fp.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_fp.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_fp.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_print_string.o", + "src/_PDCLIB/_PDCLIB_print_string.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_string.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_string.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_isstream.o", + "src/_PDCLIB/_PDCLIB_isstream.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_isstream.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_isstream.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_from_pow10.o", + "src/_PDCLIB/_PDCLIB_bigint_from_pow10.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow10.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow10.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_print_fp_deci.o", + "src/_PDCLIB/_PDCLIB_print_fp_deci.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_deci.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_deci.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_from_digit.o", + "src/_PDCLIB/_PDCLIB_bigint_from_digit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_digit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_digit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_from_bigint.o", + "src/_PDCLIB/_PDCLIB_bigint_from_bigint.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_bigint.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_bigint.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_shl.o", + "src/_PDCLIB/_PDCLIB_bigint_shl.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_shl.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_shl.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_add.o", + "src/_PDCLIB/_PDCLIB_bigint_add.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_add.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_add.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_changemode.o", + "src/_PDCLIB/_PDCLIB_changemode.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_changemode.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_changemode.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_PDCLIB/_PDCLIB_bigint_mul10.o", + "src/_PDCLIB/_PDCLIB_bigint_mul10.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul10.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul10.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_dlmalloc/malloc.o", + "src/_dlmalloc/malloc.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_dlmalloc/malloc.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_dlmalloc/malloc.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/isnormal.o", + "src/math/isnormal.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/isnormal.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/isnormal.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/isfinite.o", + "src/math/isfinite.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/isfinite.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/isfinite.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/isnan.o", + "src/math/isnan.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/isnan.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/isnan.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/fdim.o", + "src/math/fdim.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/fdim.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/fdim.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/fabs.o", + "src/math/fabs.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/fabs.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/fabs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/isinf.o", + "src/math/isinf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/isinf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/isinf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/fpclassify.o", + "src/math/fpclassify.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/fpclassify.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/fpclassify.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/signbit.o", + "src/math/signbit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/signbit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/signbit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/fmax.o", + "src/math/fmax.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/fmax.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/fmax.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/math/fmin.o", + "src/math/fmin.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/math/fmin.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/math/fmin.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_tzset_unlocked.o", + "src/_tzcode/_PDCLIB_tzset_unlocked.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_tzset_unlocked.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_tzset_unlocked.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_tzload.o", + "src/_tzcode/_PDCLIB_tzload.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_tzload.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_tzload.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_gmtcheck.o", + "src/_tzcode/_PDCLIB_gmtcheck.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_gmtcheck.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_gmtcheck.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_timesub.o", + "src/_tzcode/_PDCLIB_timesub.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_timesub.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_timesub.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_localsub.o", + "src/_tzcode/_PDCLIB_localsub.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_localsub.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_localsub.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_localtime_tzset.o", + "src/_tzcode/_PDCLIB_localtime_tzset.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_localtime_tzset.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_localtime_tzset.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_update_tzname_etc.o", + "src/_tzcode/_PDCLIB_update_tzname_etc.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_update_tzname_etc.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_update_tzname_etc.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_mktime_tzname.o", + "src/_tzcode/_PDCLIB_mktime_tzname.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_mktime_tzname.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_mktime_tzname.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_increment_overflow.o", + "src/_tzcode/_PDCLIB_increment_overflow.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_increment_overflow.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_increment_overflow.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_gmtsub.o", + "src/_tzcode/_PDCLIB_gmtsub.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_gmtsub.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_gmtsub.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_tzparse.o", + "src/_tzcode/_PDCLIB_tzparse.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_tzparse.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_tzparse.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/_tzcode/_PDCLIB_init_ttinfo.o", + "src/_tzcode/_PDCLIB_init_ttinfo.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_init_ttinfo.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/_tzcode/_PDCLIB_init_ttinfo.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isupper.o", + "src/ctype/isupper.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isupper.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isupper.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/iscntrl.o", + "src/ctype/iscntrl.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/iscntrl.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/iscntrl.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/toupper.o", + "src/ctype/toupper.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/toupper.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/toupper.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/ispunct.o", + "src/ctype/ispunct.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/ispunct.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/ispunct.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isalnum.o", + "src/ctype/isalnum.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isalnum.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isalnum.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/islower.o", + "src/ctype/islower.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/islower.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/islower.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isgraph.o", + "src/ctype/isgraph.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isgraph.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isgraph.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isprint.o", + "src/ctype/isprint.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isprint.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isprint.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/tolower.o", + "src/ctype/tolower.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/tolower.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/tolower.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isspace.o", + "src/ctype/isspace.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isspace.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isspace.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isdigit.o", + "src/ctype/isdigit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isdigit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isdigit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isxdigit.o", + "src/ctype/isxdigit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isxdigit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isxdigit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isblank.o", + "src/ctype/isblank.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isblank.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isblank.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/ctype/isalpha.o", + "src/ctype/isalpha.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/ctype/isalpha.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/ctype/isalpha.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/signal/raise.o", + "src/signal/raise.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/signal/raise.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/signal/raise.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/signal/signal.o", + "src/signal/signal.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/signal/signal.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/signal/signal.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/ferror.o", + "src/stdio/ferror.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/ferror.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/ferror.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fopen.o", + "src/stdio/fopen.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fopen.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fopen.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/puts.o", + "src/stdio/puts.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/puts.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/puts.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fgets.o", + "src/stdio/fgets.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fgets.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fgets.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/snprintf.o", + "src/stdio/snprintf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/snprintf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/snprintf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fgetpos.o", + "src/stdio/fgetpos.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fgetpos.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fgetpos.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/getchar.o", + "src/stdio/getchar.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/getchar.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/getchar.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/rename.o", + "src/stdio/rename.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/rename.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/rename.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fscanf.o", + "src/stdio/fscanf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fscanf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fscanf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fseek.o", + "src/stdio/fseek.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fseek.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fseek.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/perror.o", + "src/stdio/perror.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/perror.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/perror.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/scanf.o", + "src/stdio/scanf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/scanf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/scanf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/tmpfile_s.o", + "src/stdio/tmpfile_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/tmpfile_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/tmpfile_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fgetc.o", + "src/stdio/fgetc.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fgetc.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fgetc.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/vsnprintf.o", + "src/stdio/vsnprintf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/vsnprintf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/vsnprintf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/sprintf.o", + "src/stdio/sprintf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/sprintf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/sprintf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fclose.o", + "src/stdio/fclose.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fclose.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fclose.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/sscanf.o", + "src/stdio/sscanf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/sscanf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/sscanf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/rewind.o", + "src/stdio/rewind.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/rewind.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/rewind.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/freopen_s.o", + "src/stdio/freopen_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/freopen_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/freopen_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/getc.o", + "src/stdio/getc.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/getc.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/getc.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fsetpos.o", + "src/stdio/fsetpos.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fsetpos.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fsetpos.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/vprintf.o", + "src/stdio/vprintf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/vprintf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/vprintf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/printf.o", + "src/stdio/printf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/printf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/printf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/setbuf.o", + "src/stdio/setbuf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/setbuf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/setbuf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/feof.o", + "src/stdio/feof.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/feof.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/feof.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fprintf.o", + "src/stdio/fprintf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fprintf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fprintf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/vsscanf.o", + "src/stdio/vsscanf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/vsscanf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/vsscanf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/clearerr.o", + "src/stdio/clearerr.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/clearerr.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/clearerr.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/tmpfile.o", + "src/stdio/tmpfile.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/tmpfile.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/tmpfile.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/vsprintf.o", + "src/stdio/vsprintf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/vsprintf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/vsprintf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/setvbuf.o", + "src/stdio/setvbuf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/setvbuf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/setvbuf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fopen_s.o", + "src/stdio/fopen_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fopen_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fopen_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/remove.o", + "src/stdio/remove.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/remove.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/remove.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/vfscanf.o", + "src/stdio/vfscanf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/vfscanf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/vfscanf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fputs.o", + "src/stdio/fputs.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fputs.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fputs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fwrite.o", + "src/stdio/fwrite.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fwrite.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fwrite.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/ungetc.o", + "src/stdio/ungetc.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/ungetc.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/ungetc.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fread.o", + "src/stdio/fread.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fread.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fread.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/putchar.o", + "src/stdio/putchar.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/putchar.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/putchar.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/freopen.o", + "src/stdio/freopen.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/freopen.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/freopen.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/ftell.o", + "src/stdio/ftell.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/ftell.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/ftell.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/putc.o", + "src/stdio/putc.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/putc.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/putc.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/vscanf.o", + "src/stdio/vscanf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/vscanf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/vscanf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/tmpnam.o", + "src/stdio/tmpnam.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/tmpnam.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/tmpnam.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fputc.o", + "src/stdio/fputc.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fputc.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fputc.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/vfprintf.o", + "src/stdio/vfprintf.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/vfprintf.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/vfprintf.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdio/fflush.o", + "src/stdio/fflush.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdio/fflush.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdio/fflush.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/rockos/times.o", + "src/rockos/times.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/rockos/times.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/rockos/times.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/rockos/time.o", + "src/rockos/time.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/rockos/time.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/rockos/time.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/rockos/syscall.o", + "src/rockos/syscall.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/rockos/syscall.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/rockos/syscall.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/locale/localeconv.o", + "src/locale/localeconv.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/locale/localeconv.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/locale/localeconv.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/locale/setlocale.o", + "src/locale/setlocale.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/locale/setlocale.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/locale/setlocale.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/localtime.o", + "src/time/localtime.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/localtime.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/localtime.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/clock.o", + "src/time/clock.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/clock.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/clock.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/ctime.o", + "src/time/ctime.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/ctime.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/ctime.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/gmtime_s.o", + "src/time/gmtime_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/gmtime_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/gmtime_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/strftime.o", + "src/time/strftime.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/strftime.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/strftime.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/gmtime.o", + "src/time/gmtime.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/gmtime.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/gmtime.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/ctime_s.o", + "src/time/ctime_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/ctime_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/ctime_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/localtime_s.o", + "src/time/localtime_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/localtime_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/localtime_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/time.o", + "src/time/time.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/time.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/time.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/mktime.o", + "src/time/mktime.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/mktime.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/mktime.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/difftime.o", + "src/time/difftime.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/difftime.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/difftime.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/asctime_s.o", + "src/time/asctime_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/asctime_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/asctime_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/asctime.o", + "src/time/asctime.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/asctime.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/asctime.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/time/timespec_get.o", + "src/time/timespec_get.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/time/timespec_get.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/time/timespec_get.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/inttypes/strtoumax.o", + "src/inttypes/strtoumax.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/inttypes/strtoumax.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/inttypes/strtoumax.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/inttypes/imaxdiv.o", + "src/inttypes/imaxdiv.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/inttypes/imaxdiv.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/inttypes/imaxdiv.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/inttypes/imaxabs.o", + "src/inttypes/imaxabs.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/inttypes/imaxabs.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/inttypes/imaxabs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/inttypes/strtoimax.o", + "src/inttypes/strtoimax.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/inttypes/strtoimax.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/inttypes/strtoimax.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/qsort.o", + "src/stdlib/qsort.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/qsort.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/qsort.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/at_quick_exit.o", + "src/stdlib/at_quick_exit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/at_quick_exit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/at_quick_exit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/div.o", + "src/stdlib/div.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/div.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/div.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/strtoull.o", + "src/stdlib/strtoull.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtoull.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtoull.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/getenv.o", + "src/stdlib/getenv.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/getenv.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/getenv.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/strtof.o", + "src/stdlib/strtof.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtof.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtof.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/abs.o", + "src/stdlib/abs.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/abs.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/abs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/atoi.o", + "src/stdlib/atoi.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atoi.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atoi.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/system.o", + "src/stdlib/system.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/system.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/system.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/srand.o", + "src/stdlib/srand.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/srand.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/srand.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/ignore_handler_s.o", + "src/stdlib/ignore_handler_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/ignore_handler_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/ignore_handler_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/strtoul.o", + "src/stdlib/strtoul.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtoul.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtoul.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/rand.o", + "src/stdlib/rand.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/rand.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/rand.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/strtol.o", + "src/stdlib/strtol.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtol.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtol.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/labs.o", + "src/stdlib/labs.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/labs.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/labs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/bsearch.o", + "src/stdlib/bsearch.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/bsearch.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/bsearch.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/qsort_s.o", + "src/stdlib/qsort_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/qsort_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/qsort_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/lldiv.o", + "src/stdlib/lldiv.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/lldiv.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/lldiv.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/atexit.o", + "src/stdlib/atexit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atexit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atexit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/llabs.o", + "src/stdlib/llabs.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/llabs.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/llabs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/abort.o", + "src/stdlib/abort.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/abort.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/abort.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/atol.o", + "src/stdlib/atol.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atol.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atol.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/strtod.o", + "src/stdlib/strtod.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtod.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtod.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/atoll.o", + "src/stdlib/atoll.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atoll.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/atoll.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/quick_exit.o", + "src/stdlib/quick_exit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/quick_exit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/quick_exit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/abort_handler_s.o", + "src/stdlib/abort_handler_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/abort_handler_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/abort_handler_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/_Exit.o", + "src/stdlib/_Exit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/_Exit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/_Exit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/exit.o", + "src/stdlib/exit.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/exit.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/exit.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/ldiv.o", + "src/stdlib/ldiv.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/ldiv.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/ldiv.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/set_constraint_handler_s.o", + "src/stdlib/set_constraint_handler_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/set_constraint_handler_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/set_constraint_handler_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/strtold.o", + "src/stdlib/strtold.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtold.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtold.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/getenv_s.o", + "src/stdlib/getenv_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/getenv_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/getenv_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/bsearch_s.o", + "src/stdlib/bsearch_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/bsearch_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/bsearch_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/stdlib/strtoll.o", + "src/stdlib/strtoll.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtoll.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/stdlib/strtoll.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memcpy.o", + "src/string/memcpy.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memcpy.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memcpy.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strerror_s.o", + "src/string/strerror_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strerror_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strerror_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strrchr.o", + "src/string/strrchr.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strrchr.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strrchr.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strchr.o", + "src/string/strchr.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strchr.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strchr.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strerror.o", + "src/string/strerror.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strerror.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strerror.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strcpy_s.o", + "src/string/strcpy_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strcpy_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strcpy_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memset.o", + "src/string/memset.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memset.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memset.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strtok_s.o", + "src/string/strtok_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strtok_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strtok_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strpbrk.o", + "src/string/strpbrk.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strpbrk.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strpbrk.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strncat_s.o", + "src/string/strncat_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strncat_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strncat_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strncat.o", + "src/string/strncat.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strncat.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strncat.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strcoll.o", + "src/string/strcoll.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strcoll.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strcoll.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strncpy.o", + "src/string/strncpy.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strncpy.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strncpy.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strspn.o", + "src/string/strspn.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strspn.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strspn.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memmove.o", + "src/string/memmove.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memmove.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memmove.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strcat.o", + "src/string/strcat.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strcat.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strcat.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strncpy_s.o", + "src/string/strncpy_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strncpy_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strncpy_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strcmp.o", + "src/string/strcmp.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strcmp.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strcmp.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strcspn.o", + "src/string/strcspn.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strcspn.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strcspn.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strxfrm.o", + "src/string/strxfrm.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strxfrm.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strxfrm.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memmove_s.o", + "src/string/memmove_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memmove_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memmove_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strlen.o", + "src/string/strlen.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strlen.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strlen.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strcpy.o", + "src/string/strcpy.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strcpy.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strcpy.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strcat_s.o", + "src/string/strcat_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strcat_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strcat_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memcpy_s.o", + "src/string/memcpy_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memcpy_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memcpy_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strncmp.o", + "src/string/strncmp.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strncmp.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strncmp.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memset_s.o", + "src/string/memset_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memset_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memset_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strerrorlen_s.o", + "src/string/strerrorlen_s.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strerrorlen_s.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strerrorlen_s.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memchr.o", + "src/string/memchr.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memchr.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memchr.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/memcmp.o", + "src/string/memcmp.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/memcmp.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/memcmp.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strstr.o", + "src/string/strstr.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strstr.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strstr.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Iinclude", + "-DHAVE_MMAP=0", + "-DLACKS_SYS_MMAN_H=1", + "-DUSE_LOCKS=0", + "-DLACKS_SYS_PARAM_H=1", + "-c", + "-o", + "src/string/strtok.o", + "src/string/strtok.c" + ], + "directory": "/home/slinky/source/RockOS/rocklibc", + "file": "/home/slinky/source/RockOS/rocklibc/src/string/strtok.c", + "output": "/home/slinky/source/RockOS/rocklibc/src/string/strtok.o" + } +] diff --git a/rocklibc/include/assert.h b/rocklibc/include/assert.h new file mode 100644 index 0000000..34bea52 --- /dev/null +++ b/rocklibc/include/assert.h @@ -0,0 +1,50 @@ +/* Diagnostics + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_ASSERT_H +#define _PDCLIB_ASSERT_H _PDCLIB_ASSERT_H +_PDCLIB_PUBLIC void _PDCLIB_assert99( const char * const, const char * const, const char * const ); +_PDCLIB_PUBLIC void _PDCLIB_assert89( const char * const ); +#endif + +/* If NDEBUG is set, assert() is a null operation. */ +#undef assert + +#ifdef NDEBUG +#define assert( ignore ) ( (void) 0 ) +#else +#if __STDC_VERSION__ >= 199901L +#define assert( expression ) ( ( expression ) ? (void) 0 \ + : _PDCLIB_assert99( "Assertion failed: " #expression \ + ", function ", __func__, \ + ", file " __FILE__ \ + ", line " _PDCLIB_value2string( __LINE__ ) \ + ".\n" ) ) +#else +#define assert( expression ) ( ( expression ) ? (void) 0 \ + : _PDCLIB_assert89( "Assertion failed: " #expression \ + ", file " __FILE__ \ + ", line " _PDCLIB_value2string( __LINE__ ) \ + ".\n" ) ) +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_ASSERT_H +#include _PDCLIB_EXTEND_ASSERT_H +#endif + +#ifdef __cplusplus +} +#endif diff --git a/rocklibc/include/ctype.h b/rocklibc/include/ctype.h new file mode 100644 index 0000000..551667a --- /dev/null +++ b/rocklibc/include/ctype.h @@ -0,0 +1,110 @@ +/* Character handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_CTYPE_H +#define _PDCLIB_CTYPE_H _PDCLIB_CTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +/* 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 ) */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int isalpha( int c ); + +/* Returns true if the character isspace() and used for separating words within + a line of text. In the "C" locale, only ' ' and '\t' are considered blanks. +*/ +_PDCLIB_PUBLIC int isblank( int c ); + +/* Returns true if the character is a control character. */ +_PDCLIB_PUBLIC int iscntrl( int c ); + +/* Returns true if the character is a decimal digit. Locale-independent. */ +_PDCLIB_PUBLIC 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 ' '. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC int islower( int c ); + +/* Returns true for every printing character including space (' '). */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC int isupper( int c ); + +/* Returns true for any hexadecimal-digit character. Locale-independent. */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int tolower( int c ); + +/* Converts a lowercase letter to a corresponding uppercase letter. Input that + is not a lowercase letter remains unchanged. +*/ +_PDCLIB_PUBLIC int toupper( int c ); + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_CTYPE_H +#include _PDCLIB_EXTEND_CTYPE_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/errno.h b/rocklibc/include/errno.h new file mode 100644 index 0000000..28eaf5b --- /dev/null +++ b/rocklibc/include/errno.h @@ -0,0 +1,202 @@ +/* Errors + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_ERRNO_H +#define _PDCLIB_ERRNO_H _PDCLIB_ERRNO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +/* FIXME: With , this needs to be in thread-specific storage. */ +#define errno (*_PDCLIB_errno_func()) + +/* C only requires the following three */ + +/* Result too large */ +#define ERANGE _PDCLIB_ERANGE +/* Mathematics argument out of domain of function */ +#define EDOM _PDCLIB_EDOM +/* Illegal byte sequence */ +#define EILSEQ _PDCLIB_EILSEQ + +/* C++ additionally requires the folloing */ + +/* Argument list too long */ +#define E2BIG _PDCLIB_E2BIG +/* Permission denied */ +#define EACCES _PDCLIB_EACCES +/* Address in use */ +#define EADDRINUSE _PDCLIB_EADDRINUSE +/* Address not available */ +#define EADDRNOTAVAIL _PDCLIB_EADDRNOTAVAIL +/* Address family not supported */ +#define EAFNOSUPPORT _PDCLIB_EAFNOSUPPORT +/* Resource unavailable, try again */ +#define EAGAIN _PDCLIB_EAGAIN +/* Connection already in progress */ +#define EALREADY _PDCLIB_EALREADY +/* Bad file descriptor */ +#define EBADF _PDCLIB_EBADF +/* Bad message */ +#define EBADMSG _PDCLIB_EBADMSG +/* Device or resource busy */ +#define EBUSY _PDCLIB_EBUSY +/* Operation canceled */ +#define ECANCELED _PDCLIB_ECANCELED +/* No child processes */ +#define ECHILD _PDCLIB_ECHILD +/* Connection aborted */ +#define ECONNABORTED _PDCLIB_ECONNABORTED +/* Connection refused */ +#define ECONNREFUSED _PDCLIB_ECONNREFUSED +/* Connection reset */ +#define ECONNRESET _PDCLIB_ECONNRESET +/* Resource deadlock would occur */ +#define EDEADLK _PDCLIB_EDEADLK +/* Destination address required */ +#define EDESTADDRREQ _PDCLIB_EDESTADDRREQ +/* File exists */ +#define EEXIST _PDCLIB_EEXIST +/* Bad address */ +#define EFAULT _PDCLIB_EFAULT +/* File too large */ +#define EFBIG _PDCLIB_EFBIG +/* Host is unreachable */ +#define EHOSTUNREACH _PDCLIB_EHOSTUNREACH +/* Identifier removed */ +#define EIDRM _PDCLIB_EIDRM +/* Operation in progress */ +#define EINPROGRESS _PDCLIB_EINPROGRESS +/* Interrupted function */ +#define EINTR _PDCLIB_EINTR +/* Invalid argument */ +#define EINVAL _PDCLIB_EINVAL +/* I/O error */ +#define EIO _PDCLIB_EIO +/* Socket is connected */ +#define EISCONN _PDCLIB_EISCONN +/* Is a directory */ +#define EISDIR _PDCLIB_EISDIR +/* Too many levels of symbolic links */ +#define ELOOP _PDCLIB_ELOOP +/* File descriptor value too large */ +#define EMFILE _PDCLIB_EMFILE +/* Too many links */ +#define EMLINK _PDCLIB_EMLINK +/* Message too large */ +#define EMSGSIZE _PDCLIB_EMSGSIZE +/* Filename too long */ +#define ENAMETOOLONG _PDCLIB_ENAMETOOLONG +/* Network is down */ +#define ENETDOWN _PDCLIB_ENETDOWN +/* Connection aborted by network */ +#define ENETRESET _PDCLIB_ENETRESET +/* Network unreachable */ +#define ENETUNREACH _PDCLIB_ENETUNREACH +/* Too many files open in system */ +#define ENFILE _PDCLIB_ENFILE +/* No buffer space available */ +#define ENOBUFS _PDCLIB_ENOBUFS +/* No message is available on the STREAM head read queue */ +#define ENODATA _PDCLIB_ENODATA +/* No such device */ +#define ENODEV _PDCLIB_ENODEV +/* No such file or directory */ +#define ENOENT _PDCLIB_ENOENT +/* Executable file format error */ +#define ENOEXEC _PDCLIB_ENOEXEC +/* No locks available */ +#define ENOLCK _PDCLIB_ENOLCK +/* Link has been severed */ +#define ENOLINK _PDCLIB_ENOLINK +/* Not enough space */ +#define ENOMEM _PDCLIB_ENOMEM +/* No message of the desired type */ +#define ENOMSG _PDCLIB_ENOMSG +/* Protocol not available */ +#define ENOPROTOOPT _PDCLIB_ENOPROTOOPT +/* No space left on device */ +#define ENOSPC _PDCLIB_ENOSPC +/* No STREAM resources */ +#define ENOSR _PDCLIB_ENOSR +/* Not a STREAM */ +#define ENOSTR _PDCLIB_ENOSTR +/* Function not supported */ +#define ENOSYS _PDCLIB_ENOSYS +/* The socket is not connected */ +#define ENOTCONN _PDCLIB_ENOTCONN +/* Not a directory */ +#define ENOTDIR _PDCLIB_ENOTDIR +/* Directory not empty */ +#define ENOTEMPTY _PDCLIB_ENOTEMPTY +/* State not recoverable */ +#define ENOTRECOVERABLE _PDCLIB_ENOTRECOVERABLE +/* Not a socket */ +#define ENOTSOCK _PDCLIB_ENOTSOCK +/* Not supported */ +#define ENOTSUP _PDCLIB_ENOTSUP +/* Inappropriate I/O control operation */ +#define ENOTTY _PDCLIB_ENOTTY +/* No such device or address */ +#define ENXIO _PDCLIB_ENXIO +/* Operation not supported on socket */ +#define EOPNOTSUPP _PDCLIB_EOPNOTSUPP +/* Value too large to be stored in data type */ +#define EOVERFLOW _PDCLIB_EOVERFLOW +/* Previous owner died */ +#define EOWNERDEAD _PDCLIB_EOWNERDEAD +/* Operation not permitted */ +#define EPERM _PDCLIB_EPERM +/* Broken pipe */ +#define EPIPE _PDCLIB_EPIPE +/* Protocol error */ +#define EPROTO _PDCLIB_EPROTO +/* Protocol not supported */ +#define EPROTONOSUPPORT _PDCLIB_EPROTONOSUPPORT +/* Protocol wrong type for socket */ +#define EPROTOTYPE _PDCLIB_EPROTOTYPE +/* Read-only file system */ +#define EROFS _PDCLIB_EROFS +/* Invalid seek */ +#define ESPIPE _PDCLIB_ESPIPE +/* No such process */ +#define ESRCH _PDCLIB_ESRCH +/* Stream ioctl() timeout */ +#define ETIME _PDCLIB_ETIME +/* Connection timed out */ +#define ETIMEDOUT _PDCLIB_ETIMEDOUT +/* Text file busy */ +#define ETXTBSY _PDCLIB_ETXTBSY +/* Operation would block */ +#define EWOULDBLOCK _PDCLIB_EWOULDBLOCK +/* Cross-device link */ +#define EXDEV _PDCLIB_EXDEV + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_ERRNO_H +#include _PDCLIB_EXTEND_ERRNO_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/fcntl.h b/rocklibc/include/fcntl.h new file mode 100644 index 0000000..99d530f --- /dev/null +++ b/rocklibc/include/fcntl.h @@ -0,0 +1,19 @@ +#ifndef _FCNTL_H +#define _FCNTL_H + +/* File access modes for open() */ +#define O_RDONLY 00000000 +#define O_WRONLY 00000001 +#define O_RDWR 00000002 + +/* File creation flags */ +#define O_CREAT 00000100 +#define O_EXCL 00000200 +#define O_NOCTTY 00000400 +#define O_TRUNC 00001000 +#define O_APPEND 00002000 +#define O_NONBLOCK 00004000 + +#define AT_FDCWD (-100) + +#endif /* _FCNTL_H */ \ No newline at end of file diff --git a/rocklibc/include/float.h b/rocklibc/include/float.h new file mode 100644 index 0000000..49d5d2e --- /dev/null +++ b/rocklibc/include/float.h @@ -0,0 +1,82 @@ +/* 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. +*/ + +#ifndef _PDCLIB_FLOAT_H +#define _PDCLIB_FLOAT_H _PDCLIB_FLOAT_H + +#include "pdclib/_PDCLIB_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__ + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_FLOAT_H +#include _PDCLIB_EXTEND_FLOAT_H +#endif + +#endif diff --git a/rocklibc/include/inttypes.h b/rocklibc/include/inttypes.h new file mode 100644 index 0000000..0be401d --- /dev/null +++ b/rocklibc/include/inttypes.h @@ -0,0 +1,368 @@ +/* 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. +*/ + +#ifndef _PDCLIB_INTTYPES_H +#define _PDCLIB_INTTYPES_H _PDCLIB_INTTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct _PDCLIB_imaxdiv_t imaxdiv_t; + +/* 7.8.1 Macros for format specifiers */ + +/* The various leastN_t, fastN_t, intmax_t, and intptr_t types are typedefs + to native types. But the user does not know which ones, which gives some + problems when trying to *printf() / *scanf() those types. The various + macros defined below allow to give the correct conversion specifiers + without knowing the actual native type they represent. +*/ + +#if _PDCLIB_INT_LEAST8_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define PRIiLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define PRIoLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define PRIuLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define PRIxLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) +#define PRIXLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, X ) ) +#else +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#endif + +#if _PDCLIB_INT_FAST8_MAX > _PDCLIB_INT_MAX +#define PRIdFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, d ) ) +#define PRIiFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, i ) ) +#define PRIoFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, o ) ) +#define PRIuFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, u ) ) +#define PRIxFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, x ) ) +#define PRIXFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, X ) ) +#else +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" +#endif + +#if _PDCLIB_INT_LEAST16_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define PRIiLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define PRIoLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define PRIuLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define PRIxLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) +#define PRIXLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, X ) ) +#else +#define PRIdLEAST16 "d" +#define PRIiLEAST16 "i" +#define PRIoLEAST16 "o" +#define PRIuLEAST16 "u" +#define PRIxLEAST16 "x" +#define PRIXLEAST16 "X" +#endif + +#if _PDCLIB_INT_FAST16_MAX > _PDCLIB_INT_MAX +#define PRIdFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, d ) ) +#define PRIiFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, i ) ) +#define PRIoFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, o ) ) +#define PRIuFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, u ) ) +#define PRIxFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, x ) ) +#define PRIXFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, X ) ) +#else +#define PRIdFAST16 "d" +#define PRIiFAST16 "i" +#define PRIoFAST16 "o" +#define PRIuFAST16 "u" +#define PRIxFAST16 "x" +#define PRIXFAST16 "X" +#endif + +#if _PDCLIB_INT_LEAST32_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define PRIiLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define PRIoLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define PRIuLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define PRIxLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) +#define PRIXLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, X ) ) +#else +#define PRIdLEAST32 "d" +#define PRIiLEAST32 "i" +#define PRIoLEAST32 "o" +#define PRIuLEAST32 "u" +#define PRIxLEAST32 "x" +#define PRIXLEAST32 "X" +#endif + +#if _PDCLIB_INT_FAST32_MAX > _PDCLIB_INT_MAX +#define PRIdFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, d ) ) +#define PRIiFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, i ) ) +#define PRIoFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, o ) ) +#define PRIuFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, u ) ) +#define PRIxFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, x ) ) +#define PRIXFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, X ) ) +#else +#define PRIdFAST32 "d" +#define PRIiFAST32 "i" +#define PRIoFAST32 "o" +#define PRIuFAST32 "u" +#define PRIxFAST32 "x" +#define PRIXFAST32 "X" +#endif + +#if _PDCLIB_INT_LEAST64_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define PRIiLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define PRIoLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define PRIuLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define PRIxLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) +#define PRIXLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, X ) ) +#else +#define PRIdLEAST64 "d" +#define PRIiLEAST64 "i" +#define PRIoLEAST64 "o" +#define PRIuLEAST64 "u" +#define PRIxLEAST64 "x" +#define PRIXLEAST64 "X" +#endif + +#if _PDCLIB_INT_FAST64_MAX > _PDCLIB_INT_MAX +#define PRIdFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, d ) ) +#define PRIiFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, i ) ) +#define PRIoFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, o ) ) +#define PRIuFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, u ) ) +#define PRIxFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, x ) ) +#define PRIXFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, X ) ) +#else +#define PRIdFAST64 "d" +#define PRIiFAST64 "i" +#define PRIoFAST64 "o" +#define PRIuFAST64 "u" +#define PRIxFAST64 "x" +#define PRIXFAST64 "X" +#endif + +#if _PDCLIB_INTMAX_MAX > _PDCLIB_INT_MAX +#define PRIdMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, d ) ) +#define PRIiMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, i ) ) +#define PRIoMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, o ) ) +#define PRIuMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, u ) ) +#define PRIxMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, x ) ) +#define PRIXMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, X ) ) +#else +#define PRIdMAX "d" +#define PRIiMAX "i" +#define PRIoMAX "o" +#define PRIuMAX "u" +#define PRIxMAX "x" +#define PRIXMAX "X" +#endif + +#if _PDCLIB_INTPTR_MAX > _PDCLIB_INT_MAX +#define PRIdPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, d ) ) +#define PRIiPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, i ) ) +#define PRIoPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, o ) ) +#define PRIuPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, u ) ) +#define PRIxPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, x ) ) +#define PRIXPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, X ) ) +#else +#define PRIdPTR "d" +#define PRIiPTR "i" +#define PRIoPTR "o" +#define PRIuPTR "u" +#define PRIxPTR "x" +#define PRIXPTR "X" +#endif + +#define SCNdLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define SCNiLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define SCNoLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define SCNuLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define SCNxLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) + +#define SCNdFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, d ) ) +#define SCNiFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, i ) ) +#define SCNoFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, o ) ) +#define SCNuFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, u ) ) +#define SCNxFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, x ) ) + +#define SCNdLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define SCNiLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define SCNoLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define SCNuLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define SCNxLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) + +#define SCNdFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, d ) ) +#define SCNiFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, i ) ) +#define SCNoFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, o ) ) +#define SCNuFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, u ) ) +#define SCNxFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, x ) ) + +#define SCNdLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define SCNiLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define SCNoLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define SCNuLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define SCNxLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) + +#define SCNdFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, d ) ) +#define SCNiFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, i ) ) +#define SCNoFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, o ) ) +#define SCNuFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, u ) ) +#define SCNxFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, x ) ) + +#define SCNdLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define SCNiLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define SCNoLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define SCNuLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define SCNxLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) + +#define SCNdFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, d ) ) +#define SCNiFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, i ) ) +#define SCNoFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, o ) ) +#define SCNuFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, u ) ) +#define SCNxFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, x ) ) + +#define SCNdMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, d ) ) +#define SCNiMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, i ) ) +#define SCNoMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, o ) ) +#define SCNuMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, u ) ) +#define SCNxMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, x ) ) + +#define SCNdPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, d ) ) +#define SCNiPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, i ) ) +#define SCNoPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, o ) ) +#define SCNuPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, u ) ) +#define SCNxPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, x ) ) + +/* The exact-width types (int8_t, int16_t, ...) are *optional*, as not all + architectures support the necessary 8-bits-per-byte two's complement + native types. +*/ + +#if _PDCLIB_TWOS_COMPLEMENT == 1 + +#if _PDCLIB_INT_LEAST8_MAX == 0x7f +#if _PDCLIB_INT_LEAST8_MAX > _PDCLIB_INT_MAX +#define PRId8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define PRIi8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define PRIo8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define PRIu8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define PRIx8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) +#define PRIX8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, X ) ) +#endif +#define SCNd8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define SCNi8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define SCNo8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define SCNu8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define SCNx8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) +#endif + +#if _PDCLIB_INT_LEAST16_MAX == 0x7fff +#if _PDCLIB_INT_LEAST16_MAX > _PDCLIB_INT_MAX +#define PRId16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define PRIi16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define PRIo16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define PRIu16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define PRIx16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) +#define PRIX16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, X ) ) +#endif +#define SCNd16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define SCNi16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define SCNo16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define SCNu16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define SCNx16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) +#endif + +#if _PDCLIB_INT_LEAST32_MAX == 0x7fffffffl +#if _PDCLIB_INT_LEAST32_MAX > _PDCLIB_INT_MAX +#define PRId32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define PRIi32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define PRIo32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define PRIu32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define PRIx32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) +#define PRIX32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, X ) ) +#endif +#define SCNd32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define SCNi32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define SCNo32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define SCNu32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define SCNx32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) +#endif + +#if _PDCLIB_INT_LEAST64_MAX == 0x7fffffffffffffffll +#if _PDCLIB_INT_LEAST64_MAX > _PDCLIB_INT_MAX +#define PRId64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define PRIi64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define PRIo64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define PRIu64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define PRIx64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) +#define PRIX64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, X ) ) +#endif +#define SCNd64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define SCNi64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define SCNo64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define SCNu64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define SCNx64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) +#endif + +#endif + +/* 7.8.2 Functions for greatest-width integer types */ + +/* Calculate the absolute value of j */ +_PDCLIB_PUBLIC intmax_t imaxabs( intmax_t j ); + +/* Return quotient (quot) and remainder (rem) of an integer division in the + imaxdiv_t struct. +*/ +_PDCLIB_PUBLIC imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom ); + +/* Separate 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. +*/ +_PDCLIB_PUBLIC intmax_t strtoimax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC uintmax_t strtoumax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); + +/* TODO: wcstoimax(), wcstoumax() */ + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_INTTYPES_H +#include _PDCLIB_EXTEND_INTTYPES_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/iso646.h b/rocklibc/include/iso646.h new file mode 100644 index 0000000..88e521c --- /dev/null +++ b/rocklibc/include/iso646.h @@ -0,0 +1,31 @@ +/* Alternative spellings + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_ISO646_H +#define _PDCLIB_ISO646_H _PDCLIB_ISO646_H + +#ifndef __cplusplus +#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 ^= +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_ISO646_H +#include _PDCLIB_EXTEND_ISO646_H +#endif + +#endif diff --git a/rocklibc/include/limits.h b/rocklibc/include/limits.h new file mode 100644 index 0000000..72268a4 --- /dev/null +++ b/rocklibc/include/limits.h @@ -0,0 +1,50 @@ +/* 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. +*/ + +#ifndef _PDCLIB_LIMITS_H +#define _PDCLIB_LIMITS_H _PDCLIB_LIMITS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +/* TODO: Defined to 1 as multibyte characters are not supported yet. */ +#define MB_LEN_MAX 1 + +#define LLONG_MIN _PDCLIB_LLONG_MIN +#define LLONG_MAX _PDCLIB_LLONG_MAX +#define ULLONG_MAX _PDCLIB_ULLONG_MAX + +#define CHAR_BIT _PDCLIB_CHAR_BIT +#define CHAR_MAX _PDCLIB_CHAR_MAX +#define CHAR_MIN _PDCLIB_CHAR_MIN +#define SCHAR_MAX _PDCLIB_SCHAR_MAX +#define SCHAR_MIN _PDCLIB_SCHAR_MIN +#define UCHAR_MAX _PDCLIB_UCHAR_MAX +#define SHRT_MAX _PDCLIB_SHRT_MAX +#define SHRT_MIN _PDCLIB_SHRT_MIN +#define INT_MAX _PDCLIB_INT_MAX +#define INT_MIN _PDCLIB_INT_MIN +#define LONG_MAX _PDCLIB_LONG_MAX +#define LONG_MIN _PDCLIB_LONG_MIN +#define USHRT_MAX _PDCLIB_USHRT_MAX +#define UINT_MAX _PDCLIB_UINT_MAX +#define ULONG_MAX _PDCLIB_ULONG_MAX + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_LIMITS_H +#include _PDCLIB_EXTEND_LIMITS_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/locale.h b/rocklibc/include/locale.h new file mode 100644 index 0000000..0c18446 --- /dev/null +++ b/rocklibc/include/locale.h @@ -0,0 +1,114 @@ +/* Localization + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_LOCALE_H +#define _PDCLIB_LOCALE_H _PDCLIB_LOCALE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* The structure returned by localeconv(). + + The values for *_sep_by_space: + 0 - no space + 1 - if symbol and sign are adjacent, a space separates them from the value; + otherwise a space separates the symbol from the value + 2 - if symbol and sign are adjacent, a space separates them; otherwise a + space separates 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 separating 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 separated by space from pos. qty. */ /* LC_MONETARY */ + char n_sep_by_space; /* if it is separated 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. +*/ +_PDCLIB_PUBLIC char * setlocale( int category, const char * locale ); + +/* Returns a struct lconv initialized to the values appropriate for the current + locale setting. +*/ +_PDCLIB_PUBLIC struct lconv * localeconv( void ); + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_LOCALE_H +#include _PDCLIB_EXTEND_LOCALE_H +#endif + +#endif diff --git a/rocklibc/include/math.h b/rocklibc/include/math.h new file mode 100644 index 0000000..88b6619 --- /dev/null +++ b/rocklibc/include/math.h @@ -0,0 +1,467 @@ +/* Mathematics + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_MATH_H +#define _PDCLIB_MATH_H _PDCLIB_MATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +typedef float float_t; +typedef double double_t; + +#define HUGE_VALF _PDCLIB_HUGE_VALF; +#define HUGE_VAL _PDCLIB_HUGE_VAL; +#define HUGE_VALL _PDCLIB_HUGE_VALL; + +#define INFINITY (_PDCLIB_FLT_MAX * 2) +#define NAN ( -(0.0f / 0.0f) ) + +#define FP_FAST_FMAF +#define FP_FAST_FMA +#define FP_FAST_FMAL + +#define FP_ILOGB0 INT_MIN +#define FP_ILOGBNAN INT_MAX + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 + +#define math_errhandling + +/* Classification */ + +/* FP_ZERO, FP_SUBNORMAL, FP_NORMAL */ +#define isfinite( x ) _PDCLIB_GENERIC( isfinite, x ) + +/* FP_INFINITE */ +#define isinf( x ) _PDCLIB_GENERIC( isinf, x ) + +/* FP_NAN */ +#define isnan( x ) _PDCLIB_GENERIC( isnan, x ) + +/* FP_NORMAL */ +#define isnormal( x ) _PDCLIB_GENERIC( isnormal, x ) + +/* Negative */ +#define signbit( x ) _PDCLIB_GENERIC( signbit, x ) + +/* See FP_* classes */ +#define fpclassify( x ) _PDCLIB_GENERIC( fpclassify, x ) + +#define FP_INFINITE 1 +#define FP_NAN 2 +#define FP_NORMAL 3 +#define FP_SUBNORMAL 4 +#define FP_ZERO 5 + +/* Trigonometric functions */ + +/* The principal value of the arc cosine of x. + Domain error for arguments not in the interval -1..+1. + Returns the interval 0..Pi radians. +*/ +double acos( double x ); +float acosf( float x ); +long double acosl( long double x ); + +/* The principal value of the arc sine of x. + Domain error for arguments not in the interval -1..+1. + Returns the interval -Pi/2..Pi/2 radians. +*/ +double asin( double x ); +float asinf( float x ); +long double asinl( long double x ); + +/* The principal value of the arc tangent of x. + Returns the interval -Pi/2..Pi/2 radians. +*/ +double atan( double x ); +float atanf( float x ); +long double atanl( long double x ); + +/* The value of the arc tangent of y/x, using the signs of both + arguments to determine the quadrant of the return value. + Domain error if both arguments are zero. + Returns the interval -Pi..Pi radians. +*/ +double atan2( double y, double x ); +float atan2f( float y, float x ); +long double atan2l( long double y, long double x ); + +/* Cosine of x in radians. */ +double cos( double x ); +float cosf( float x ); +long double cosl( long double x ); + +/* Sine of x in radians. */ +double sin( double x ); +float sinf( float x ); +long double sinl( long double x ); + +/* Tangent of x in radians. */ +double tan( double x ); +float tanf( float x ); +long double tanl( long double x ); + +/* Hyperbolic functions */ + +/* The (nonnegative) arc hyberbolic cosine of x. + Domain error for arguments less than 1. + Returns the interval 0..INF. +*/ +double acosh( double x ); +float acoshf( float x ); +long double acoshl( long double x ); + +/* The arc hyberbolic sine of x. +*/ +double asinh( double x ); +float asinhf( float x ); +long double asinhl( long double x ); + +/* The arc hyberbolic tangent of x. + Domain error for arguments not in -1..1. + Range error if -1 or +1. +*/ +double atanh( double x ); +float atanhf( float x ); +long double atanhl( long double x ); + +/* The hyberbolic cosine of x. + Range error if magnitude of x is too large. +*/ +double cosh( double x ); +float coshf( float x ); +long double coshl( long double x ); + +/* The hyberbolic sine of x. + Range error if magnitude of x is too large. +*/ +double sinh( double x ); +float sinhf( float x ); +long double sinhl( long double x ); + +/* The hyberbolic tangent of x. + Range error if magnitude of x is too large. +*/ +double tanh( double x ); +float tanhf( float x ); +long double tanhl( long double x ); + +/* Exponential and logarithmic functions */ + +/* The base-e exponential of x. + Range error if magnitude of x is too large. +*/ +double exp( double x ); +float expf( float x ); +long double expl( long double x ); + +/* The base-2 exponential of x. + Range error if magnitude of x is too large. +*/ +double exp2( double x ); +float exp2f( float x ); +long double exp2l( long double x ); + +/* The base-e exponential of x, minus 1. + Range error if magnitude of x is too large. + Returns e^x - 1. +*/ +double expm1( double x ); +float expm1f( float x ); +long double expm1l( long double x ); + +/* Breaks a floating-point number into a normalized fraction + and an integral power of 2 (stored in the object pointed + to by exp). +*/ +double frexp( double value, int * exp ); +float frexpf( float value, int * exp ); +long double frexpl( long double value, int * exp ); + +/* Extract the exponent of x as a signed int. + * Returns FP_ILOGB0 if x is zero, INT_MAX if x is infinite, + * FP_ILOGBNAN if x is a NaN. Range error may occur if x is 0. +*/ +double ilogb( double x ); +float ilogbf( float x ); +long double ilogbl( long double x ); + +/* Multiply x by 2^exp. Range error may occur. */ +double ldexp( double x, int exp ); +float ldexpf( float x, int exp ); +long double ldexpl( long double x, int exp ); + +/* Compute the base-e logarithm of x. + Domain error if argument is negative. + Range error if argument is zero. +*/ +double log( double x ); +float logf( float x ); +long double logl( long double x ); + +/* Compute the base-10 logarithm of x. + Domain error if argument is negative. + Range error if argument is zero. +*/ +double log10( double x ); +float log10f( float x ); +long double log10l( long double x ); + +/* Compute the base-e logarithm of 1 plus x. + Domain error if argument is less than -1. + Range error if argument is -1. +*/ +double log1p( double x ); +float log1pf( float x ); +long double log1pl( long double x ); + +/* Compute the base-2 logarithm of x. + Domain error if argument is negative. + Range error if argument is zero. +*/ +double log2( double x ); +float log2f( float x ); +long double log2l( long double x ); + +/* Extract exponent of x, as signed integer in floating-point format. + Subnormal is treated as though normalized. + Domain error if argument is zero. +*/ +double logb( double x ); +float logbf( float x ); +long double logbl( long double x ); + +/* Breaks value into integral and fractional parts, each having + the same type and sign as the argument. The integral part is + stored in the object pointed to by iptr. +*/ +double modf( double value, double * exp ); +float modff( float value, float * exp ); +long double modfl( long double value, long double * exp ); + +/* Compute x * FLT_RADIX^n efficiently. Range error may occur. */ +double scalbn( double x, int n ); +float scalbnf( float x, int n ); +long double scalbnl( long double x, int n ); + +double scalbln( double x, long int * n ); +float scalblnf( float x, long int * n ); +long double scalblnl( long double x, long int * n ); + +/* Power and absolute-value functions */ + +/* Returns x^1/3. */ +double cbrt( double x ); +float cbrtf( float x ); +long double cbrtl( long double x ); + +/* Returns absolute value of x. */ +double fabs( double x ); +float fabsf( float x ); +long double fabsl( long double x ); + +/* Returns square root of the sum of squares of x and y. + Range error may occur. +*/ +double hypot( double x, double y ); +float hypotf( float x, float y ); +long double hypotl( long double x, long double y ); + +/* Returns x^y. + Domain error if x is finite and negative and y is finite and not + an integer value. + Domain error if x is zero and y is less or equal zero. + Range error may occur. +*/ +double pow( double x, double y ); +float powf( float x, float y ); +long double powl( long double x, long double y ); + +/* Returns x^1/2. */ +double sqrt( double x ); +float sqrtf( float x ); +long double sqrtl( long double x ); + +/* Error and gamma functions */ + +/* Compute the error function of x. */ +double erf( double x ); +float erff( float x ); +long double erfl( long double x ); + +/* Compute the complementary error function of x. + Range error if x is too large. +*/ +double erfc( double x ); +float erfcf( float x ); +long double erfcl( long double x ); + +/* Compute the natural logarithm of the absolute value of gamma(x). + Range error if x is too lange, x is negative, or zero. +*/ +double lgamma( double x ); +float lgammaf( float x ); +long double lgammal( long double x ); + +/* Compute the gamma function of x. + Range error if x is negative, or zero, too large or too small. +*/ +double tgamma( double x ); +float tgammaf( float x ); +long double tgammal( long double x ); + +/* Nearest integer functions */ + +/* The smallest integer no less than x. */ +double ceil( double x ); +float ceilf( float x ); +long double ceill( long double x ); + +/* The largest integer no greater than x. */ +double floor( double x ); +float floorf( float x ); +long double floorl( long double x ); + +/* Round in current rounding direction. No "inexact" exception. */ +double nearbyint( double x ); +float nearbyintf( float x ); +long double nearbyintl( long double x ); + +/* Round in current rounding direction. Raises "inexact" exception. */ +double rint( double x ); +float rintf( float x ); +long double rintl( long double x ); + +/* Round in current rounding direction. + Range error if magnitude is too large. +*/ +long int lrint( double x ); +long int lrintf( float x ); +long int lrintl( long double x ); +long long int llrint( double x ); +long long int llrintf( float x ); +long long int llrintl( long double x ); + +/* Round to nearest, breaking ties away from zero. */ +double round( double x ); +float roundf( float x ); +long double roundl( long double x ); + +/* Round to nearest, breaking ties away from zero. + Range error if magnitude is too large. +*/ +long int lround( double x ); +long int lroundf( float x ); +long int lroundl( long double x ); +long long int llround( double x ); +long long int llroundf( float x ); +long long int llroundl( long double x ); + +/* Round toward zero. */ +double trunc( double x ); +float truncf( float x ); +long double truncl( long double x ); + +/* Remainder functions */ + +/* Compute the remainder of x / y. */ +double fmod( double x, double y ); +float fmodf( float x, float y ); +long double fmodl( long double x, long double y ); + +/* Compute the remainder of x REM y. */ +double remainder( double x, double y ); +float remainderf( float x, float y ); +long double remainderl( long double x, long double y ); + +/* Compute the remainder of x REM y. In quo store a value with + the sign of the quotient and magnitude congruent mod 2^n to + the magnitude of the integral quotient of x / y, with n + an implementation-defined integer greater than or equal to 3. +*/ +double rmquo( double x, double y ); +float rmquof( float x, float y ); +long double rmquol( long double x, long double y ); + +/* Manipulation functions */ + +/* Returns a value with magnitude of x and sign of y. */ +double copysign( double x, double y ); +float copysignf( float x, float y ); +long double copysignl( long double x, long double y ); + +/* Returns a NaN value with the given n-char sequence. */ +double nan( const char * tagp ); +float nanf( const char * tagp ); +long double nanl( const char * tagp ); + +/* Determine the next representable value after x in direction y. + Range error if result is not representable. +*/ +double nextafter( double x, double y ); +float nextafterf( float x, float y ); +long double nextafterl( long double x, long double y ); + +/* As nextafter but with long double as second parameter. */ +double nexttoward( double x, double y ); +float nexttowardf( float x, float y ); +long double nexttowardl( long double x, long double y ); + +/* Maximum, minimum, and positive difference functions */ + +/* Positive difference. */ +double fdim( double x, double y ); +float fdimf( float x, float y ); +long double fdiml( long double x, long double y ); + +/* Maximum. */ +double fmax( double x, double y ); +float fmaxf( float x, float y ); +long double fmaxl( long double x, long double y ); + +/* Minimum. */ +double fmin( double x, double y ); +float fminf( float x, float y ); +long double fminl( long double x, long double y ); + +/* Multiply-add. */ +double fma( double x, double y, double z ); +float fmaf( float x, float y, float z ); +long double fmal( long double x, long double y, long double z ); + +/* Comparison macros (without "invalid" FP exception) */ + +#define isgreater( x, y ) + +#define isgreaterequal( x, y ) + +#define isless( x, y ) + +#define islessequal( x, y ) + +#define islessgreater( x, y ) + +#define isunordered( x, y ) + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_MATH_H +#include _PDCLIB_EXTEND_MATH_H +#endif + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_config.h b/rocklibc/include/pdclib/_PDCLIB_config.h new file mode 100644 index 0000000..653f89e --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_config.h @@ -0,0 +1,915 @@ +/* Internal PDCLib configuration <_PDCLIB_config.h> + ("Example" platform target, for PDCLib development) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_CONFIG_H +#define _PDCLIB_CONFIG_H _PDCLIB_CONFIG_H + +/* -------------------------------------------------------------------------- */ +/* Misc */ +/* -------------------------------------------------------------------------- */ + +/* Helper macros also documented in _PDCLIB_internal.h, but defined here as */ +/* they are needed in this file already. */ +/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending. */ +/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */ +#define _PDCLIB_cc( x, y ) x ## y +#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y ) + +/* 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 ); + +/* Define this to some compiler directive that can be written after the */ +/* parameter list of a function declaration to indicate the function does */ +/* never return. If your compiler does not support such a directive, define */ +/* to nothing. (This is to avoid warnings with the exit functions under GCC */ +/* when compiling with C99/C++ settings, where C11 _Noreturn is unavailable.) */ +#define _PDCLIB_NORETURN __attribute__(( noreturn )) + +/* -------------------------------------------------------------------------- */ +/* Symbol Visibility */ +/* -------------------------------------------------------------------------- */ + +/* This defines _PDCLIB_PUBLIC to indicate external linkage, and _PDCLIB_LOCAL + to indicate local linkage. +*/ + +#ifdef _PDCLIB_STATIC_DEFINE + #define _PDCLIB_PUBLIC + #define _PDCLIB_LOCAL +#else + #if defined _WIN32 || defined __CYGWIN__ + #ifdef _PDCLIB_BUILD + #ifdef __GNUC__ + #define _PDCLIB_PUBLIC __attribute__ ((dllexport)) + #else + #define _PDCLIB_PUBLIC __declspec(dllexport) + #endif + #else + #ifdef __GNUC__ + #define _PDCLIB_PUBLIC __attribute__ ((dllimport)) + #else + #define _PDCLIB_PUBLIC __declspec(dllimport) + #endif + #endif + #define _PDCLIB_LOCAL + #else + #if __GNUC__ >= 4 + #define _PDCLIB_PUBLIC __attribute__ ((visibility ("default"))) + #define _PDCLIB_LOCAL __attribute__ ((visibility ("hidden"))) + #else + #define _PDCLIB_PUBLIC + #define _PDCLIB_LOCAL + #endif + #endif +#endif + +/* -------------------------------------------------------------------------- */ +/* Integers */ +/* -------------------------------------------------------------------------- */ +/* The defines below make use of predefines offered by GCC and clang. If you */ +/* adapt PDCLib for a different compiler family, you will have to use what */ +/* that compiler provides, or enter actual values. */ +/* -------------------------------------------------------------------------- */ + +/* At the point of writing, PDCLib makes no provisions for, nor has it been */ +/* tested, on a platform that uses signed magnitude or one's complement to */ +/* encode its integers. Most importantly, there are no guarantees that the */ +/* negative zero of those encodings is in any form handled gracefully. */ +#define _PDCLIB_TWOS_COMPLEMENT 1 + +/* 1234 for little endian, 4321 for big endian; other types not supported. */ +#define _PDCLIB_ENDIANESS __BYTE_ORDER__ + +/* Calculation of a minimum value from a given maximum for two's complement. */ +/* (For convenience only, used only in this header file below.) */ +#define _PDCLIB_MIN_CALC( max ) ( ( - max ) - 1 ) + +/* Now, introducting the various predefines to the _PDCLIB_* namespace, so */ +/* the rest of PDCLib can work with that and adapting to a different compiler */ +/* will require changes only in this one file. */ + +/* Bits in a char */ +#define _PDCLIB_CHAR_BIT __CHAR_BIT__ + +/* Maximum and minimum values of signed / unsigned char */ +#define _PDCLIB_SCHAR_MAX __SCHAR_MAX__ +#define _PDCLIB_SCHAR_MIN _PDCLIB_MIN_CALC( __SCHAR_MAX__ ) +#define _PDCLIB_UCHAR_MAX ( __SCHAR_MAX__ * 2 + 1 ) + +/* Whether the 'char' type is unsigned */ +#ifdef __CHAR_UNSIGNED__ +#define _PDCLIB_CHAR_MAX _PDCLIB_UCHAR_MAX +#define _PDCLIB_CHAR_MIN 0 +#else +#define _PDCLIB_CHAR_MAX _PDCLIB_SCHAR_MAX +#define _PDCLIB_CHAR_MIN _PDCLIB_SCHAR_MIN +#endif + +/* Maximum and minimum values of signed / unsigned short */ +#define _PDCLIB_SHRT_MAX __SHRT_MAX__ +#define _PDCLIB_SHRT_MIN _PDCLIB_MIN_CALC( __SHRT_MAX__ ) +#define _PDCLIB_USHRT_MAX ( __SHRT_MAX__ * 2u + 1 ) + +/* Maximum and minimum values of signed / unsigned int */ +#define _PDCLIB_INT_MAX __INT_MAX__ +#define _PDCLIB_INT_MIN _PDCLIB_MIN_CALC( __INT_MAX__ ) +#define _PDCLIB_UINT_MAX ( __INT_MAX__ * 2u + 1 ) + +/* Maximum and minimum values of signed / unsigned long */ +#define _PDCLIB_LONG_MAX __LONG_MAX__ +#define _PDCLIB_LONG_MIN _PDCLIB_MIN_CALC( __LONG_MAX__ ) +#define _PDCLIB_ULONG_MAX ( __LONG_MAX__ * 2ul + 1 ) + +/* Maximum and minimum values of signed / unsigned long long */ +#define _PDCLIB_LLONG_MAX __LONG_LONG_MAX__ +#define _PDCLIB_LLONG_MIN _PDCLIB_MIN_CALC( __LONG_LONG_MAX__ ) +#define _PDCLIB_ULLONG_MAX ( __LONG_LONG_MAX__ * 2ull + 1 ) + +/* -------------------------------------------------------------------------- */ +/* defines a set of integer types that are of a minimum width, and */ +/* "usually fastest" on the system. (If, for example, accessing a single char */ +/* requires the CPU to access a complete int and then mask out the char, the */ +/* "usually fastest" type of at least 8 bits would be int, not char.) */ +/* If you do not have information on the relative performance of the types, */ +/* the standard allows you to define any type that meets minimum width and */ +/* signedness requirements. */ +/* The first define is the appropriate basic type (e.g. "long int"), second */ +/* its max value, the third its min value (both expressed in the given type). */ +/* The same follows for the unsigned type (for which the minimum value is */ +/* obviously zero and need not be defined). */ +/* There *are* predefines provided for the printf()/scanf() length specifiers */ +/* but tunneling them through here would have added many lines of repetitive */ +/* and mostly redundant defines. They are determined in <_PDCLIB_internal.h>. */ +/* -------------------------------------------------------------------------- */ + +/* int_fast8_t / uint_fast8_t */ +#define _PDCLIB_int_fast8_t __INT_FAST8_TYPE__ +#define _PDCLIB_INT_FAST8_MAX __INT_FAST8_MAX__ +#define _PDCLIB_INT_FAST8_MIN _PDCLIB_MIN_CALC( __INT_FAST8_MAX__ ) +#define _PDCLIB_uint_fast8_t __UINT_FAST8_TYPE__ +#define _PDCLIB_UINT_FAST8_MAX __UINT_FAST8_MAX__ + +/* int_least8_t / uint_least8_t */ +#define _PDCLIB_int_least8_t __INT_LEAST8_TYPE__ +#define _PDCLIB_INT_LEAST8_MAX __INT_LEAST8_MAX__ +#define _PDCLIB_INT_LEAST8_MIN _PDCLIB_MIN_CALC( __INT_LEAST8_MAX__ ) +#define _PDCLIB_uint_least8_t __UINT_LEAST8_TYPE__ +#define _PDCLIB_UINT_LEAST8_MAX __UINT_LEAST8_MAX__ + +/* int_fast16_t / uint_fast16_t */ +#define _PDCLIB_int_fast16_t __INT_FAST16_TYPE__ +#define _PDCLIB_INT_FAST16_MAX __INT_FAST16_MAX__ +#define _PDCLIB_INT_FAST16_MIN _PDCLIB_MIN_CALC( __INT_FAST16_MAX__ ) +#define _PDCLIB_uint_fast16_t __UINT_FAST16_TYPE__ +#define _PDCLIB_UINT_FAST16_MAX __UINT_FAST16_MAX__ + +/* int_least16_t / uint_least16_t */ +#define _PDCLIB_int_least16_t __INT_LEAST16_TYPE__ +#define _PDCLIB_INT_LEAST16_MAX __INT_LEAST16_MAX__ +#define _PDCLIB_INT_LEAST16_MIN _PDCLIB_MIN_CALC( __INT_LEAST16_MAX__ ) +#define _PDCLIB_uint_least16_t __UINT_LEAST16_TYPE__ +#define _PDCLIB_UINT_LEAST16_MAX __UINT_LEAST16_MAX__ + +/* int_fast32_t / uint_fast32_t */ +#define _PDCLIB_int_fast32_t __INT_FAST32_TYPE__ +#define _PDCLIB_INT_FAST32_MAX __INT_FAST32_MAX__ +#define _PDCLIB_INT_FAST32_MIN _PDCLIB_MIN_CALC( __INT_FAST32_MAX__ ) +#define _PDCLIB_uint_fast32_t __UINT_FAST32_TYPE__ +#define _PDCLIB_UINT_FAST32_MAX __UINT_FAST32_MAX__ + +/* int_least32_t / uint_least32_t */ +#define _PDCLIB_int_least32_t __INT_LEAST32_TYPE__ +#define _PDCLIB_INT_LEAST32_MAX __INT_LEAST32_MAX__ +#define _PDCLIB_INT_LEAST32_MIN _PDCLIB_MIN_CALC( __INT_LEAST32_MAX__ ) +#define _PDCLIB_uint_least32_t __UINT_LEAST32_TYPE__ +#define _PDCLIB_UINT_LEAST32_MAX __UINT_LEAST32_MAX__ + +/* int_fast64_t / uint_fast64_t */ +#define _PDCLIB_int_fast64_t __INT_FAST64_TYPE__ +#define _PDCLIB_INT_FAST64_MAX __INT_FAST64_MAX__ +#define _PDCLIB_INT_FAST64_MIN _PDCLIB_MIN_CALC( __INT_FAST64_MAX__ ) +#define _PDCLIB_uint_fast64_t __UINT_FAST64_TYPE__ +#define _PDCLIB_UINT_FAST64_MAX __UINT_FAST64_MAX__ + +/* int_least64_t / uint_least64_t */ +#define _PDCLIB_int_least64_t __INT_LEAST64_TYPE__ +#define _PDCLIB_INT_LEAST64_MAX __INT_LEAST64_MAX__ +#define _PDCLIB_INT_LEAST64_MIN _PDCLIB_MIN_CALC( __INT_LEAST64_MAX__ ) +#define _PDCLIB_uint_least64_t __UINT_LEAST64_TYPE__ +#define _PDCLIB_UINT_LEAST64_MAX __UINT_LEAST64_MAX__ + +/* Exact-width integer types. These are *optional*. If your platform does not */ +/* support types of these exact widths in two's complement encoding, just */ +/* leave them undefined. */ +#define _PDCLIB_int8_t __INT8_TYPE__ +#define _PDCLIB_int16_t __INT16_TYPE__ +#define _PDCLIB_int32_t __INT32_TYPE__ +#define _PDCLIB_int64_t __INT64_TYPE__ +#define _PDCLIB_uint8_t __UINT8_TYPE__ +#define _PDCLIB_uint16_t __UINT16_TYPE__ +#define _PDCLIB_uint32_t __UINT32_TYPE__ +#define _PDCLIB_uint64_t __UINT64_TYPE__ + +/* INTn_C / UINTn_C macros to define int_leastN_t / uint_leastN_t literals. */ +#if defined( __INT8_C ) +/* GCC */ +#define _PDCLIB_INT_LEAST8_C __INT8_C +#define _PDCLIB_UINT_LEAST8_C __UINT8_C +#define _PDCLIB_INT_LEAST16_C __INT16_C +#define _PDCLIB_UINT_LEAST16_C __UINT16_C +#define _PDCLIB_INT_LEAST32_C __INT32_C +#define _PDCLIB_UINT_LEAST32_C __UINT32_C +#define _PDCLIB_INT_LEAST64_C __INT64_C +#define _PDCLIB_UINT_LEAST64_C __UINT64_C +#elif defined( __INT8_C_SUFFIX__ ) +/* Clang */ +#define _PDCLIB_INT_LEAST8_C(c) _PDCLIB_concat( c, __INT8_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST8_C(c) _PDCLIB_concat( c, __UINT8_C_SUFFIX__ ) +#define _PDCLIB_INT_LEAST16_C(c) _PDCLIB_concat( c, __INT16_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST16_C(c) _PDCLIB_concat( c, __UINT16_C_SUFFIX__ ) +#define _PDCLIB_INT_LEAST32_C(c) _PDCLIB_concat( c, __INT32_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST32_C(c) _PDCLIB_concat( c, __UINT32_C_SUFFIX__ ) +#define _PDCLIB_INT_LEAST64_C(c) _PDCLIB_concat( c, __INT64_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST64_C(c) _PDCLIB_concat( c, __UINT64_C_SUFFIX__ ) +#else +#error Please create your own _PDCLIB_config.h. Using the existing one as-is will not work. (Unsupported *INTn_C macros.) +#endif + +/* 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; +}; + +/* -------------------------------------------------------------------------- */ +/* What follows are a couple of "special" typedefs and their limits. */ +/* -------------------------------------------------------------------------- */ + +/* The result type of substracting two pointers */ +#define _PDCLIB_ptrdiff_t __PTRDIFF_TYPE__ +#define _PDCLIB_PTRDIFF_MAX __PTRDIFF_MAX__ +#define _PDCLIB_PTRDIFF_MIN _PDCLIB_MIN_CALC( __PTRDIFF_MAX__ ) + +/* An integer type that can be accessed as atomic entity (think asynchronous */ +/* interrupts). In a freestanding environment, the type itself need not be */ +/* defined, but its limits must. (Don't ask.) GCC is so kind to predefine it, */ +/* but clang is only giving us its MAX value, so we use that to identify the */ +/* type in _PDCLIB_int.h if the type definition is unavailable. */ +#ifdef __SIG_ATOMIC_TYPE__ +#define _PDCLIB_sig_atomic_t __SIG_ATOMIC_TYPE__ +#endif +#define _PDCLIB_SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ +#define _PDCLIB_SIG_ATOMIC_MIN _PDCLIB_MIN_CALC( __SIG_ATOMIC_MAX__ ) + +/* Result type of the 'sizeof' operator (must be unsigned). */ +/* Note: In , this is taken as the base for RSIZE_MAX, the limit */ +/* for the bounds-checking interfaces of Annex K. The recommendation by the */ +/* standard is to use ( SIZE_MAX >> 1 ) when "targeting machines with large */ +/* addess spaces", whereas small address spaces should use SIZE_MAX directly. */ +#define _PDCLIB_size_t __SIZE_TYPE__ +#define _PDCLIB_SIZE_MAX __SIZE_MAX__ + +/* Large enough an integer to hold all character codes of the widest */ +/* supported locale. */ +#define _PDCLIB_wchar_t __WCHAR_TYPE__ +#define _PDCLIB_WCHAR_MAX __WCHAR_MAX__ +#define _PDCLIB_WCHAR_MIN __WCHAR_MIN__ + +/* Large enough an integer to hold all character codes of the widest */ +/* supported locale plus WEOF (which needs not to be equal to EOF, nor needs */ +/* to be of negative value). */ +#define _PDCLIB_wint_t __WINT_TYPE__ +#define _PDCLIB_WINT_MAX __WINT_MAX__ +#define _PDCLIB_WINT_MIN __WINT_MIN__ + +/* Integer types capable of taking the (cast) value of a void *, and having */ +/* the value cast back to void *, comparing equal to the original. */ +#define _PDCLIB_intptr_t __INTPTR_TYPE__ +#define _PDCLIB_INTPTR_MAX __INTPTR_MAX__ +#define _PDCLIB_INTPTR_MIN _PDCLIB_MIN_CALC( __INTPTR_MAX__ ) +#define _PDCLIB_uintptr_t __UINTPTR_TYPE__ +#define _PDCLIB_UINTPTR_MAX __UINTPTR_MAX__ + +/* Largest supported integer type. Implementation note: see _PDCLIB_atomax(). */ +#define _PDCLIB_intmax_t __INTMAX_TYPE__ +#define _PDCLIB_INTMAX_MAX __INTMAX_MAX__ +#define _PDCLIB_INTMAX_MIN _PDCLIB_MIN_CALC( __INTMAX_MAX__ ) +#define _PDCLIB_INTMAX_C __INTMAX_C +#define _PDCLIB_uintmax_t __UINTMAX_TYPE__ +#define _PDCLIB_UINTMAX_MAX __UINTMAX_MAX__ +#define _PDCLIB_UINTMAX_C __UINTMAX_C + +/* defines imaxdiv(), which is equivalent to the div() function */ +/* family (see further above) with intmax_t as basis. */ +struct _PDCLIB_imaxdiv_t +{ + _PDCLIB_intmax_t quot; + _PDCLIB_intmax_t rem; +}; + +/* -------------------------------------------------------------------------- */ +/* Time types, limits, constants, and paths */ +/* -------------------------------------------------------------------------- */ + +/* _PDCLIB_time is the type for type_t; _PDCLIB_clock for clock_t. Both types */ +/* are defined as "real types capable of representing times". The "range and */ +/* precision of times representable" is implementation-defined. */ + +/* For clock_t, the standard defines that dividing the result of clock() by */ +/* CLOCKS_PER_SEC gives the seconds elapsed. */ +#ifdef __CYGWIN__ +#define _PDCLIB_clock_t unsigned long +#else +#define _PDCLIB_clock_t long +#endif +#define _PDCLIB_CLOCKS_PER_SEC 1000000 + +/* For time_t, no such divider exists. Most implementations use a count of */ +/* seconds since a specified epoch. While PDCLib really should support other */ +/* encodings as well, for now "count of seconds" is the only supported one. */ +/* MIN / MAX values for time_t are not required by the standard (and they are */ +/* not "exported" from the _PDCLIB namespace), but they are useful in support */ +/* of the _tzcode implementation. */ +#ifdef __MINGW64__ +#define _PDCLIB_time_t long long +#define _PDCLIB_TIME_MAX __LONG_LONG_MAX__ +#define _PDCLIB_TIME_MIN _PDCLIB_MIN_CALC( __LONG_LONG_MAX__ ) +#else +#define _PDCLIB_time_t long +#define _PDCLIB_TIME_MAX __LONG_MAX__ +#define _PDCLIB_TIME_MIN _PDCLIB_MIN_CALC( __LONG_MAX__ ) +#endif + +/* "Unix time" uses 1970-01-01T00:00:00 as "epoch". If your system uses a */ +/* different "zero point" for its timestamps, set this to the offset between */ +/* your epoch and Unix epoch. (For example, NTP uses 1900-01-01T00:00:00 as */ +/* epoch, giving an offset of (70 * 365 + 17) * 86400 = 220898800 seconds.) */ +#define _PDCLIB_EPOCH_BIAS INT64_C( 0 ) + +/* Leave this alone for now. */ +#define _PDCLIB_TIME_UTC 1 + +/* Path to TZ data. */ +/* IMPORTANT: *Must* end with separator character! */ +/* It does make it much easier for the time data handling code if this detail */ +/* can be relied upon and need not be handled in code. */ +#define _PDCLIB_TZDIR "/usr/share/zoneinfo/" + +/* Path to default (local) timezone */ +#define _PDCLIB_TZDEFAULT "/etc/localtime" + +/* -------------------------------------------------------------------------- */ +/* 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 + +/* Check for explanations on each of these values. */ +#define _PDCLIB_FLT_EVAL_METHOD __FLT_EVAL_METHOD__ + +#define _PDCLIB_FLT_HAS_SUBNORM __FLT_HAS_DENORM__ +#define _PDCLIB_DBL_HAS_SUBNORM __DBL_HAS_DENORM__ +#define _PDCLIB_LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__ + +#define _PDCLIB_FLT_RADIX __FLT_RADIX__ + +#define _PDCLIB_FLT_MANT_DIG __FLT_MANT_DIG__ +#define _PDCLIB_DBL_MANT_DIG __DBL_MANT_DIG__ +#define _PDCLIB_LDBL_MANT_DIG __LDBL_MANT_DIG__ + +#define _PDCLIB_FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__ +#define _PDCLIB_DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ +#define _PDCLIB_LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__ + +#define _PDCLIB_DECIMAL_DIG __DECIMAL_DIG__ + +#define _PDCLIB_FLT_DIG __FLT_DIG__ +#define _PDCLIB_DBL_DIG __DBL_DIG__ +#define _PDCLIB_LDBL_DIG __LDBL_DIG__ + +#define _PDCLIB_FLT_MIN_EXP __FLT_MIN_EXP__ +#define _PDCLIB_DBL_MIN_EXP __DBL_MIN_EXP__ +#define _PDCLIB_LDBL_MIN_EXP __LDBL_MIN_EXP__ + +#define _PDCLIB_FLT_MIN_10_EXP __FLT_MIN_10_EXP__ +#define _PDCLIB_DBL_MIN_10_EXP __DBL_MIN_10_EXP__ +#define _PDCLIB_LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ + +#define _PDCLIB_FLT_MAX_EXP __FLT_MAX_EXP__ +#define _PDCLIB_DBL_MAX_EXP __DBL_MAX_EXP__ +#define _PDCLIB_LDBL_MAX_EXP __LDBL_MAX_EXP__ + +#define _PDCLIB_FLT_MAX_10_EXP __FLT_MAX_10_EXP__ +#define _PDCLIB_DBL_MAX_10_EXP __DBL_MAX_10_EXP__ +#define _PDCLIB_LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ + +#define _PDCLIB_FLT_MAX __FLT_MAX__ +#define _PDCLIB_DBL_MAX __DBL_MAX__ +#define _PDCLIB_LDBL_MAX __LDBL_MAX__ + +#define _PDCLIB_FLT_EPSILON __FLT_EPSILON__ +#define _PDCLIB_DBL_EPSILON __DBL_EPSILON__ +#define _PDCLIB_LDBL_EPSILON __LDBL_EPSILON__ + +#define _PDCLIB_FLT_MIN __FLT_MIN__ +#define _PDCLIB_DBL_MIN __DBL_MIN__ +#define _PDCLIB_LDBL_MIN __LDBL_MIN__ + +#define _PDCLIB_FLT_TRUE_MIN __FLT_DENORM_MIN__ +#define _PDCLIB_DBL_TRUE_MIN __DBL_DENORM_MIN__ +#define _PDCLIB_LDBL_TRUE_MIN __LDBL_DENORM_MIN__ + +/* Macros for deconstructing floating point values */ +/* This assumes that the floating point value has been memcpy'd into an array */ +/* of _PDCLIB_bigint_digit_t (see _PDCLIB_bigint_from_*dbl.c with the array */ +/* passed to the macro as parameter. */ +#define _PDCLIB_FLT_SIGN( data ) ( ( data[1] & 0x8000 ) >> 15 ) +#define _PDCLIB_FLT_EXP( data ) ( ( data[1] & 0x7f80 ) >> 7 ) +#define _PDCLIB_FLT_SIZE( data ) ( data[1] &= 0x007f, 2 ) + +#define _PDCLIB_DBL_SIGN( data ) ( ( data[3] & 0x8000 ) >> 15 ) +#define _PDCLIB_DBL_EXP( data ) ( ( data[3] & 0x7ff0u ) >> 4 ) +#define _PDCLIB_DBL_SIZE( data ) ( data[3] &= 0x000fu, 4 ) + +/* Most platforms today use IEEE 754 single precision for 'float', and double */ +/* precision for 'double'. But type 'long double' varies. We use what the */ +/* compiler states about LDBL_MANT_DIG to determine the type. */ +#if _PDCLIB_LDBL_MANT_DIG == 64 + +/* Intel "Extended Precision" format, using 80 bits (64bit mantissa) */ +#define _PDCLIB_LDBL_SIGN( data ) ( ( data[4] & 0x8000u ) >> 15 ) +#define _PDCLIB_LDBL_EXP( data ) ( data[4] & 0x7fffu ) +#define _PDCLIB_LDBL_SIZE( data ) ( data[3] &= 0x7fffu, 4 ) + +#elif _PDCLIB_LDBL_MANT_DIG == 113 + +/* IEEE "Quadruple Precision" format, using 128 bits (113bit mantissa) */ +#define _PDCLIB_LDBL_SIGN( data ) ( ( data[7] & 0x8000u ) >> 15 ) +#define _PDCLIB_LDBL_EXP( data ) ( data[7] & 0x7fffu ) +#define _PDCLIB_LDBL_SIZE( data ) 7 + +#else + +/* IEEE "Double Precision" format, using 64 bits (53bit mantissa) */ +/* (Same as DBL above) */ +#define _PDCLIB_LDBL_SIGN( data ) ( ( data[3] & 0x8000 ) >> 15 ) +#define _PDCLIB_LDBL_EXP( data ) ( ( data[3] & 0x7ff0u ) >> 4 ) +#define _PDCLIB_LDBL_SIZE( data ) ( data[3] &= 0x000fu, 4 ) + +#endif + +/* Given the definitions for *_MANT_START above, which resolve to "pointer + to most dignificant byte of mantissa", the operand to use to get at the + less significant bytes. (That would be - for i386, x86_64, and ARM.) +*/ +#define _PDCLIB_FLT_OP - + +/* -------------------------------------------------------------------------- */ +/* Big Integer Arithmetic */ +/* -------------------------------------------------------------------------- */ +/* In support of the floating point converstions required by printf() etc., */ +/* PDCLib provides rudimentary big integer arithmetics. The _PDCLIB_bigint_t */ +/* type stores values in a sequence of integer "digits", which may be of any */ +/* uint_leastN_t type with N being 32 or 16. Note that multiplication and */ +/* division require the help of the next larger type. So set the define to */ +/* 32 if efficient 64bit integer arithmetics are available on your platform, */ +/* and to 16 otherwise. */ +/* (The value range of _PDCLIB_bigint_t is not affected by this setting.) */ + +#define _PDCLIB_BIGINT_DIGIT_BITS 16 + +/* -------------------------------------------------------------------------- */ +/* 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__ ) || defined( __ARM_NEON ) + +/* 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 _PDCLIB_config.h. Using the existing one as-is will not work. (Unsupported varargs.) + +#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 _PDCLIB_glue.h. */ +/* -------------------------------------------------------------------------- */ + +/* I/O ---------------------------------------------------------------------- */ + +/* The type of the file descriptor returned by _PDCLIB_open(), i.e. whatever */ +/* the underlying kernel uses for stream identification. */ +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 guarantees can opened */ +/* simultaneously. Must be at least 8. Depends largely on how the platform */ +/* does the bookkeeping in whatever is called by _PDCLIB_open(). PDCLib puts */ +/* no further limits on the number of open files other than 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 52 + +/* 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, you should 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); PDCLib supports larger values, but applications */ +/* relying on this would rely on implementation-defined behaviour (not good). */ +#define _PDCLIB_UNGETCBUFSIZE 1 + +/* The number of functions that can be registered with atexit(). Needs to be */ +/* at least 33 (32 guaranteed by the standard, plus _PDCLIB_closeall() which */ +/* is used internally by PDCLib to close all open streams). */ +/* TODO: Should expand dynamically. */ +#define _PDCLIB_ATEXIT_SLOTS 40 + +/* 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 of "translating" between errno values used by the hosting OS 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 'errno == EISDIR', and set '*_PDCLIB_errno_func() */ +/* = _PDCLIB_EPERM'. Anyone using PDCLib's will "see" EPERM instead */ +/* of EISDIR. */ +/* */ +/* 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, to avoid confusion. */ +/* auxiliary/errno/errno_readout.c provides a convenience program to read */ +/* those errno values mandated by the standard from a platform's , */ +/* giving output that can readily be pasted here. */ +/* Either way, note that the list below, the list in PDCLib's , and */ +/* the list in _PDCLIB_stdinit.h, need to be kept in sync. */ +/* */ +/* The values below are read from a Linux system. */ + +/* Argument list too long */ +#define _PDCLIB_E2BIG 7 +/* Permission denied */ +#define _PDCLIB_EACCES 13 +/* Address in use */ +#define _PDCLIB_EADDRINUSE 98 +/* Address not available */ +#define _PDCLIB_EADDRNOTAVAIL 99 +/* Address family not supported */ +#define _PDCLIB_EAFNOSUPPORT 97 +/* Resource unavailable, try again */ +#define _PDCLIB_EAGAIN 11 +/* Connection already in progress */ +#define _PDCLIB_EALREADY 114 +/* Bad file descriptor */ +#define _PDCLIB_EBADF 9 +/* Bad message */ +#define _PDCLIB_EBADMSG 74 +/* Device or resource busy */ +#define _PDCLIB_EBUSY 16 +/* Operation canceled */ +#define _PDCLIB_ECANCELED 125 +/* No child processes */ +#define _PDCLIB_ECHILD 10 +/* Connection aborted */ +#define _PDCLIB_ECONNABORTED 103 +/* Connection refused */ +#define _PDCLIB_ECONNREFUSED 111 +/* Connection reset */ +#define _PDCLIB_ECONNRESET 104 +/* Resource deadlock would occur */ +#define _PDCLIB_EDEADLK 35 +/* Destination address required */ +#define _PDCLIB_EDESTADDRREQ 89 +/* Mathematics argument out of domain of function */ +#define _PDCLIB_EDOM 33 +/* File exists */ +#define _PDCLIB_EEXIST 17 +/* Bad address */ +#define _PDCLIB_EFAULT 14 +/* File too large */ +#define _PDCLIB_EFBIG 27 +/* Host is unreachable */ +#define _PDCLIB_EHOSTUNREACH 113 +/* Identifier removed */ +#define _PDCLIB_EIDRM 43 +/* Illegal byte sequence */ +#define _PDCLIB_EILSEQ 84 +/* Operation in progress */ +#define _PDCLIB_EINPROGRESS 115 +/* Interrupted function */ +#define _PDCLIB_EINTR 4 +/* Invalid argument */ +#define _PDCLIB_EINVAL 22 +/* I/O error */ +#define _PDCLIB_EIO 5 +/* Socket is connected */ +#define _PDCLIB_EISCONN 106 +/* Is a directory */ +#define _PDCLIB_EISDIR 21 +/* Too many levels of symbolic links */ +#define _PDCLIB_ELOOP 40 +/* File descriptor value too large */ +#define _PDCLIB_EMFILE 24 +/* Too many links */ +#define _PDCLIB_EMLINK 31 +/* Message too large */ +#define _PDCLIB_EMSGSIZE 90 +/* Filename too long */ +#define _PDCLIB_ENAMETOOLONG 36 +/* Network is down */ +#define _PDCLIB_ENETDOWN 100 +/* Connection aborted by network */ +#define _PDCLIB_ENETRESET 102 +/* Network unreachable */ +#define _PDCLIB_ENETUNREACH 101 +/* Too many files open in system */ +#define _PDCLIB_ENFILE 23 +/* No buffer space available */ +#define _PDCLIB_ENOBUFS 105 +/* No message is available on the STREAM head read queue */ +#define _PDCLIB_ENODATA 61 +/* No such device */ +#define _PDCLIB_ENODEV 19 +/* No such file or directory */ +#define _PDCLIB_ENOENT 2 +/* Executable file format error */ +#define _PDCLIB_ENOEXEC 8 +/* No locks available */ +#define _PDCLIB_ENOLCK 37 +/* Link has been severed */ +#define _PDCLIB_ENOLINK 67 +/* Not enough space */ +#define _PDCLIB_ENOMEM 12 +/* No message of the desired type */ +#define _PDCLIB_ENOMSG 42 +/* Protocol not available */ +#define _PDCLIB_ENOPROTOOPT 92 +/* No space left on device */ +#define _PDCLIB_ENOSPC 28 +/* No STREAM resources */ +#define _PDCLIB_ENOSR 63 +/* Not a STREAM */ +#define _PDCLIB_ENOSTR 60 +/* Function not supported */ +#define _PDCLIB_ENOSYS 38 +/* The socket is not connected */ +#define _PDCLIB_ENOTCONN 107 +/* Not a directory */ +#define _PDCLIB_ENOTDIR 20 +/* Directory not empty */ +#define _PDCLIB_ENOTEMPTY 39 +/* State not recoverable */ +#define _PDCLIB_ENOTRECOVERABLE 131 +/* Not a socket */ +#define _PDCLIB_ENOTSOCK 88 +/* Not supported */ +#define _PDCLIB_ENOTSUP 95 +/* Inappropriate I/O control operation */ +#define _PDCLIB_ENOTTY 25 +/* No such device or address */ +#define _PDCLIB_ENXIO 6 +/* Operation not supported on socket */ +#define _PDCLIB_EOPNOTSUPP 95 +/* Value too large to be stored in data type */ +#define _PDCLIB_EOVERFLOW 75 +/* Previous owner died */ +#define _PDCLIB_EOWNERDEAD 130 +/* Operation not permitted */ +#define _PDCLIB_EPERM 1 +/* Broken pipe */ +#define _PDCLIB_EPIPE 32 +/* Protocol error */ +#define _PDCLIB_EPROTO 71 +/* Protocol not supported */ +#define _PDCLIB_EPROTONOSUPPORT 93 +/* Protocol wrong type for socket */ +#define _PDCLIB_EPROTOTYPE 91 +/* Result too large */ +#define _PDCLIB_ERANGE 34 +/* Read-only file system */ +#define _PDCLIB_EROFS 30 +/* Invalid seek */ +#define _PDCLIB_ESPIPE 29 +/* No such process */ +#define _PDCLIB_ESRCH 3 +/* Stream ioctl() timeout */ +#define _PDCLIB_ETIME 62 +/* Connection timed out */ +#define _PDCLIB_ETIMEDOUT 110 +/* Text file busy */ +#define _PDCLIB_ETXTBSY 26 +/* Operation would block */ +#define _PDCLIB_EWOULDBLOCK 11 +/* Cross-device link */ +#define _PDCLIB_EXDEV 18 + +/* The highest defined errno value, plus one. 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.) */ +#define _PDCLIB_ERRNO_MAX 132 + +/* The error message used for unknown error codes (generated by errno_readout */ +/* for consistency between the 'holes' in the list of defined error messages */ +/* and the text generated by e.g. strerror() for out-of-range error values.) */ +#define _PDCLIB_EUNKNOWN_TEXT (char*)"unknown error" + +/* 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 + +/* threads ------------------------------------------------------------------ */ + +/* This is relying on underlying implementation to provide thread */ +/* support. */ +/* The problem here is we cannot just #include and access the */ +/* original definitions. The standard library must not drag identifiers into */ +/* the user's namespace, so we have to set our own definitions in the _PDCLIB */ +/* namespace. Which are, obviously, platform-specific. */ +/* If you do NOT want to provide threads support, define __STDC_NO_THREADS__ */ +/* to 1 and simply delete the threads.h header and the corresponding files in */ +/* functions/threads/. This makes PDCLib non-thread-safe (obviously), as the */ +/* safeguards against race conditions (e.g. in ) will be omitted. */ + +/* auxiliary/pthread/pthread_readout.c provides a convenience program to read */ +/* appropriate definitions from a platform's , giving output that */ +/* can be copy & pasted here. */ + +#define __STDC_NO_THREADS__ + +#ifndef __STDC_NO_THREADS__ + +typedef unsigned long int _PDCLIB_thrd_t; +typedef union { unsigned char _PDCLIB_cnd_t_data[ 48 ]; long long int _PDCLIB_cnd_t_align; } _PDCLIB_cnd_t; +#if defined( __arm__ ) || defined( __ARM_NEON ) +typedef union { unsigned char _PDCLIB_mtx_t_data[ 24 ]; long int _PDCLIB_mtx_t_align; } _PDCLIB_mtx_t; +#else +typedef union { unsigned char _PDCLIB_mtx_t_data[ 40 ]; long int _PDCLIB_mtx_t_align; } _PDCLIB_mtx_t; +#endif +typedef unsigned int _PDCLIB_tss_t; +typedef int _PDCLIB_once_flag; +#define _PDCLIB_ONCE_FLAG_INIT 0 +#define _PDCLIB_RECURSIVE_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +/* This one is actually hidden in , and only if __USE_POSIX is */ +/* defined prior to #include (PTHREAD_DESTRUCTOR_ITERATIONS). */ +#define _PDCLIB_TSS_DTOR_ITERATIONS 4 +/* The following are not made public in any header, but used internally for */ +/* interfacing with the pthread API. */ +typedef union { unsigned char _PDCLIB_cnd_attr_t_data[ 4 ]; int _PDCLIB_cnd_attr_t_align; } _PDCLIB_cnd_attr_t; +typedef union { unsigned char _PDCLIB_mtx_attr_t_data[ 4 ]; int _PDCLIB_mtx_attr_t_align; } _PDCLIB_mtx_attr_t; +#if defined( __arm__ ) || defined( __ARM_NEON ) +typedef union { unsigned char _PDCLIB_thrd_attr_t_data[ 36 ]; long int _PDCLIB_thrd_attr_t_align; } _PDCLIB_thrd_attr_t; +#else +typedef union { unsigned char _PDCLIB_thrd_attr_t_data[ 56 ]; long int _PDCLIB_thrd_attr_t_align; } _PDCLIB_thrd_attr_t; +#endif +/* Static initialization of recursive mutex. */ +#if defined( __arm__ ) || defined( __ARM_NEON ) +#define _PDCLIB_MTX_RECURSIVE_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +/* Static initialization of plain / timeout mutex (identical with pthread). */ +#define _PDCLIB_MTX_PLAIN_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +#else +#define _PDCLIB_MTX_RECURSIVE_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +/* Static initialization of plain / timeout mutex (identical with pthread). */ +#define _PDCLIB_MTX_PLAIN_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +#endif + +#endif + +/* Termux defines atexit in crtbegin_so.o leading to a multiple definition */ +/* error from the linker. This is a crude workaround, which does NOT fix */ +/* various run-time issues on Termux likely also related to crt linkage. But */ +/* at least things compile OK, and SOME tests can be run. */ +#if defined( __ARM_NEON ) +#define atexit _PDCLIB_atexit +#endif + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_defguard.h b/rocklibc/include/pdclib/_PDCLIB_defguard.h new file mode 100644 index 0000000..cd51abe --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_defguard.h @@ -0,0 +1,29 @@ +/* Definition guard <_PDCLIB_defguard.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_DEFGUARD_H +#define _PDCLIB_DEFGUARD_H _PDCLIB_DEFGUARD_H + +#if defined( __ANDROID__ ) +/* typedef sigset_t */ +#include "bits/signal_types.h" +#endif + +/* Linux defines its own version of struct timespec (from ) in + some internal header (depending on clib implementation), which leads + to problems when accessing e.g. sys/time.h (type redefinition). + The solution is to set the Linux header's include guard (to avoid + Linux' definition), and to include PDCLib's to define the + type unambiguously. +*/ + +#define _TIMESPEC_DEFINED +#define _SYS__TIMESPEC_H_ +#define _STRUCT_TIMESPEC + +#include + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_glue.h b/rocklibc/include/pdclib/_PDCLIB_glue.h new file mode 100644 index 0000000..3e59302 --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_glue.h @@ -0,0 +1,93 @@ +/* OS glue functions declaration <_PDCLIB_glue.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_GLUE_H +#define _PDCLIB_GLUE_H _PDCLIB_GLUE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.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 _PDCLIB_config.h. */ +/* -------------------------------------------------------------------------- */ + +/* stdlib.h */ + +/* A system call that terminates the calling process, returning a given status + to the environment. +*/ +_PDCLIB_LOCAL _PDCLIB_Noreturn void _PDCLIB_Exit( int status ) _PDCLIB_NORETURN; + + +/* 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_LOCAL _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. +*/ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL _PDCLIB_int_least64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int_least64_t offset, int whence ); + +/* A system call that closes a file identified by given file descriptor. Return + zero on success, non-zero otherwise. +*/ +_PDCLIB_LOCAL int _PDCLIB_close( _PDCLIB_fd_t fd ); + +/* A system call that changes the mode of a given stream to that passed as + argument (the argument being the value returned by _PDCLIB_filemode()), + *without* closing the stream. See comments in example implementation + for details. Return zero if the requested mode change is not supported + for this stream and freopen() should try to close and reopen the stream; + return INT_MIN if the change is not supported and freopen() should close + and NOT try to close / reopen (i.e., fail). Return any other value on + success. +*/ +_PDCLIB_LOCAL int _PDCLIB_changemode( struct _PDCLIB_file_t * stream, unsigned int mode ); + +/* A system call that returns a canonicalized absolute filename in + dynamically allocated memory, or NULL if the file does not exist. +*/ +_PDCLIB_LOCAL char * _PDCLIB_realpath( const char * path ); + +/* A system call that removes a file. Return zero on success, non-zero + otherwise. +*/ +_PDCLIB_LOCAL int _PDCLIB_remove( const char * pathname ); + +/* 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. +*/ +_PDCLIB_LOCAL int _PDCLIB_rename( const char * oldpath, const char * newpath ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_internal.h b/rocklibc/include/pdclib/_PDCLIB_internal.h new file mode 100644 index 0000000..1ad3c66 --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_internal.h @@ -0,0 +1,686 @@ +/* PDCLib internal logic <_PDCLIB_internal.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_INTERNAL_H +#define _PDCLIB_INTERNAL_H _PDCLIB_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------------------------------------------------------- */ +/* 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 "pdclib/_PDCLIB_config.h" + +/* -------------------------------------------------------------------------- */ +/* 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 + +#ifndef __STDC_HOSTED__ +#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)! +#elif __STDC_HOSTED__ != 0 && __STDC_HOSTED__ != 1 +#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)! +#endif + +/* null pointer constant -- ((void *)0) in C, 0 in C++98, nullptr since C++11 */ +#ifdef __cplusplus +#if __cplusplus >= 201103L +#define _PDCLIB_NULL nullptr +#else +#define _PDCLIB_NULL 0 +#endif +#else +#define _PDCLIB_NULL ((void *)0) +#endif + +/* restrict / inline enabled for C99 onward only */ +#if defined( __cplusplus ) || ! defined( __STDC_VERSION ) || __STDC_VERSION__ < 199901L +#define _PDCLIB_restrict +#define _PDCLIB_inline +#else +#define _PDCLIB_restrict restrict +#define _PDCLIB_inline inline +#endif + +/* noreturn enabled for C11 onward only */ +#if defined( __cplusplus ) && __cplusplus >= 201103L +#define _PDCLIB_Noreturn [[noreturn]] +#else +#if defined( __STDC_VERSION__ ) >= 201112L +#define _PDCLIB_Noreturn _Noreturn +#else +#define _PDCLIB_Noreturn +#endif +#endif + +/* -------------------------------------------------------------------------- */ +/* Helper macros: */ +/* */ +/* (defined in _PDCLIB_config.h) */ +/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending. */ +/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */ +/* */ +/* (defined below) */ +/* _PDCLIB_static_assert( e, m ) does a compile-time assertion of expression */ +/* e, with m as the failure message. */ +/* _PDCLIB_symbol2string( x ) turn symbol into string literal (by adding ""). */ +/* _PDCLIB_value2string( x ) expands a preprocessor token and turns it into a */ +/* string literal (by adding ""). */ +/* _PDCLIB_TYPE_SIGNED( type ) resolves to true if type is signed. */ +/* _PDCLIB_LOCK( mtx ) lock a mutex if library has threads support. */ +/* _PDCLIB_UNLOCK( mtx ) unlock a mutex if library has threads support. */ +/* _PDCLIB_CONSTRAINT_VIOLATION( e ) expand errno number e to parameter list */ +/* fit for Annex K constraint violation */ +/* handler. */ +/* _PDCLIB_Generic( f, fp ) expand to _PDCLIB_f, _PDCLIB_ff, _PDCLIB_fl */ +/* depending on fp being sizeof double, float, or */ +/* long double. */ +/* -------------------------------------------------------------------------- */ + +#define _PDCLIB_static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) } + +#define _PDCLIB_TYPE_SIGNED( type ) (((type) -1) < 0) + +#define _PDCLIB_symbol2string( x ) #x +#define _PDCLIB_value2string( x ) _PDCLIB_symbol2string( x ) + +#ifndef __STDC_NO_THREADS__ +#define _PDCLIB_LOCK( mtx ) mtx_lock( &mtx ) +#define _PDCLIB_UNLOCK( mtx ) mtx_unlock( &mtx ) +#else +#define _PDCLIB_LOCK( mtx ) +#define _PDCLIB_UNLOCK( mtx ) +#endif + +#define _PDCLIB_CONSTRAINT_VIOLATION( e ) _PDCLIB_lc_messages->errno_texts[e], NULL, e + +#define _PDCLIB_GETC( fh ) ( ( fh->ungetidx == 0 ) ? ( unsigned char )fh->buffer[ fh->bufidx++ ] : ( unsigned char )fh->ungetbuf[ --fh->ungetidx ] ) + +#define _PDCLIB_CHECKBUFFER( fh ) ( ( ( fh->bufidx == fh->bufend ) && ( fh->ungetidx == 0 ) ) ? _PDCLIB_fillbuffer( fh ) : 0 ) + +#define _PDCLIB_GENERIC( func, x ) ( ( sizeof( x ) == sizeof( double ) ) ? _PDCLIB_ ## func ## d( x ) : \ + ( sizeof( x ) == sizeof( float ) ) ? _PDCLIB_ ## func ## f( x ) : \ + ( _PDCLIB_ ## func ## l( x ) ) ) + +/* -------------------------------------------------------------------------- */ +/* Preparing the length modifiers used in . */ +/* -------------------------------------------------------------------------- */ + +/* We use the _MAX value as a proxy for the actual type here. That is crude + but the best we can do, cross-platform wise. + Identifying which type the leastN_t / fastN_t / intmax_t / intptr_t are + and providing the appropriate printf()/scanf() length modifier. +*/ + +#if _PDCLIB_INT_FAST8_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST8_PREFIX hh +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST8_PREFIX h +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST8_PREFIX +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST8_PREFIX l +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST8_PREFIX ll +#else +#error No matching native type for int_fast8_t. Please check your setup. +#endif + +#if _PDCLIB_INT_FAST16_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST16_PREFIX hh +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST16_PREFIX h +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST16_PREFIX +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST16_PREFIX l +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST16_PREFIX ll +#else +#error No matching native type for int_fast16_t. Please check your setup. +#endif + +#if _PDCLIB_INT_FAST32_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST32_PREFIX hh +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST32_PREFIX h +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST32_PREFIX +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST32_PREFIX l +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST32_PREFIX ll +#else +#error No matching native type for int_fast32_t. Please check your setup. +#endif + +#if _PDCLIB_INT_FAST64_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST64_PREFIX hh +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST64_PREFIX h +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST64_PREFIX +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST64_PREFIX l +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST64_PREFIX ll +#else +#error No matching native type for int_fast64_t. Please check your setup. +#endif + +/* Many of the combinations below can very likely be ruled out logically. + All combinations are still listed for simplicity's sake (and to not fall + into the trap of false assumptions). +*/ + +#if _PDCLIB_INT_LEAST8_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST8_PREFIX hh +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST8_PREFIX h +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST8_PREFIX +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST8_PREFIX l +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST8_PREFIX ll +#else +#error No matching native type for int_least8_t. Please check your setup. +#endif + +#if _PDCLIB_INT_LEAST16_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST16_PREFIX hh +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST16_PREFIX h +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST16_PREFIX +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST16_PREFIX l +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST16_PREFIX ll +#else +#error No matching native type for int_least16_t. Please check your setup. +#endif + +#if _PDCLIB_INT_LEAST32_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST32_PREFIX hh +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST32_PREFIX h +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST32_PREFIX +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST32_PREFIX l +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST32_PREFIX ll +#else +#error No matching native type for int_least32_t. Please check your setup. +#endif + +#if _PDCLIB_INT_LEAST64_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST64_PREFIX hh +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST64_PREFIX h +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST64_PREFIX +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST64_PREFIX l +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST64_PREFIX ll +#else +#error No matching native type for int_least64_t. Please check your setup. +#endif + +#if _PDCLIB_INTMAX_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INTMAX_PREFIX hh +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INTMAX_PREFIX h +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INTMAX_PREFIX +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INTMAX_PREFIX l +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INTMAX_PREFIX ll +#else +#error No matching native type for intmax_t. Please check your setup. +#endif + +#if _PDCLIB_INTPTR_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INTPTR_PREFIX hh +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INTPTR_PREFIX h +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INTPTR_PREFIX +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INTPTR_PREFIX l +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INTPTR_PREFIX ll +#else +#error No matching native type for intptr_t. Please check your setup. +#endif + +/* We might not have a type definition for sig_atomic_t at this point. The */ +/* clang compiler does not provide an appropriate predefine for it. So if we */ +/* do not have _PDCLIB_sig_atomic_t, identify the type trough its MAX value. */ + +#ifndef _PDCLIB_sig_atomic_t + +#if _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_sig_atomic_t char +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_sig_atomic_t short +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_sig_atomic_t int +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_sig_atomic_t long +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_sig_atomic_t long long +#else +#error No matching native type for sig_atomic_t. Please check your setup. +#endif + +#endif + +/* -------------------------------------------------------------------------- */ +/* 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 (1u<<3) +#define _PDCLIB_FWRITE (1u<<4) +#define _PDCLIB_FAPPEND (1u<<5) +#define _PDCLIB_FRW (1u<<6) +#define _PDCLIB_FBIN (1u<<7) + +/* Internal flags, made to fit the same status field as the flags above. */ +/* -------------------------------------------------------------------------- */ +/* free() the buffer memory on closing (setvbuf()) */ +#define _PDCLIB_FREEBUFFER (1u<<8) +/* stream has encountered error / EOF */ +#define _PDCLIB_ERRORFLAG (1u<<9) +#define _PDCLIB_EOFFLAG (1u<<10) +/* stream is wide-oriented */ +#define _PDCLIB_WIDESTREAM (1u<<11) +/* stream is byte-oriented */ +#define _PDCLIB_BYTESTREAM (1u<<12) +/* file associated with stream should be remove()d on closing (tmpfile()) */ +#define _PDCLIB_DELONCLOSE (1u<<13) + +/* Position / status structure for getpos() / fsetpos(). */ +struct _PDCLIB_fpos_t +{ + _PDCLIB_uint_least64_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 */ + _PDCLIB_size_t bufsize; /* Size of buffer */ + _PDCLIB_size_t bufidx; /* Index of current position in buffer */ + _PDCLIB_size_t bufend; /* Index of last pre-read character in buffer */ + struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */ + _PDCLIB_size_t ungetidx; /* Number of ungetc()'ed characters */ + unsigned char ungetbuf[_PDCLIB_UNGETCBUFSIZE]; /* ungetc() buffer */ + unsigned int status; /* Status flags; see above */ + /* multibyte parsing status to be added later */ +#ifndef __STDC_NO_THREADS__ + _PDCLIB_mtx_t mtx; /* Multithreading safety */ +#endif + char * filename; /* Name the current stream has been opened with */ + struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */ +}; + +/* -------------------------------------------------------------------------- */ +/* 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 ); +}; + +/* Status structure required by _PDCLIB_print(). */ +struct _PDCLIB_status_t +{ + int base; /* base to which the value shall be converted */ + _PDCLIB_int_fast32_t flags; /* flags and length modifiers */ + _PDCLIB_size_t n; /* print: maximum characters to be written */ + /* scan: number matched conversion specifiers */ + _PDCLIB_size_t i; /* number of characters read/written */ + _PDCLIB_size_t current;/* chars read/written in the CURRENT conversion */ + char * s; /* *sprintf(): target buffer */ + /* *sscanf(): source string */ + _PDCLIB_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(). */ +_PDCLIB_LOCAL _PDCLIB_intmax_t _PDCLIB_atomax( const char * s ); + +/* Two helper functions used by strtol(), strtoul() and long long variants. */ +_PDCLIB_LOCAL const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base ); +_PDCLIB_LOCAL _PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, _PDCLIB_uintmax_t error, _PDCLIB_uintmax_t limit, char * sign ); + +/* Helper function used by strtof(), strtod(), and strtold(). */ +_PDCLIB_LOCAL int _PDCLIB_strtod_prelim( const char * p, char * sign, char ** endptr ); + +/* 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. +*/ +_PDCLIB_LOCAL 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 +*/ +_PDCLIB_LOCAL const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ); + +/* Parsing any fopen() style filemode string into a number of flags. */ +_PDCLIB_LOCAL unsigned int _PDCLIB_filemode( const char * mode ); + +/* Initialize a FILE structure. If the parameter is NULL, a new FILE structure + is malloc'ed. Returns a pointer to the stream if successful, NULL otherwise. +*/ +_PDCLIB_LOCAL struct _PDCLIB_file_t * _PDCLIB_init_file_t( struct _PDCLIB_file_t * stream ); + +/* 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. +*/ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream ); + +/* Closing all streams on program exit */ +_PDCLIB_LOCAL void _PDCLIB_closeall( void ); + +/* Check if a given year is a leap year. Parameter is offset to 1900. */ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL char * _PDCLIB_load_lines( struct _PDCLIB_file_t * stream, _PDCLIB_size_t lines ); + +/* Returns the (locale dependent) error message associated with the argument + errno value. +*/ +_PDCLIB_LOCAL char * _PDCLIB_geterrtext( int errnum ); + +/* Returns non-zero if the given stream is on the internal list of open files, + zero otherwise. Sets the second paramenter (if not NULL) to the previous + stream on the list (or NULL if the given stream is the first on the list). + This function does not lock _PDCLIB_filelist_mtx, this needs to be done by + the calling function (_PDCLIB_getstream() or freopen()). +*/ +_PDCLIB_LOCAL int _PDCLIB_isstream( struct _PDCLIB_file_t * stream, struct _PDCLIB_file_t ** previous ); + +/* Removes the given stream from the internal list of open files. Returns zero + if successful, non-zero otherwise. In case of error, sets errno to EBADF. + This function does not lock _PDCLIB_filelist_mtx, this needs to be done by + the calling function (fclose()). +*/ +_PDCLIB_LOCAL int _PDCLIB_getstream( struct _PDCLIB_file_t * stream ); + +/* Backend for strtok and strtok_s (plus potential extensions like strtok_r). */ +_PDCLIB_LOCAL char * _PDCLIB_strtok( char * _PDCLIB_restrict s1, _PDCLIB_size_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr ); + +/* Conversion of exponent notation to floating point */ +_PDCLIB_LOCAL long double _PDCLIB_naive_etod( const char * s, char ** endptr ); + +/* Conversion of hexadecimal notation to floating point */ +_PDCLIB_LOCAL long double _PDCLIB_naive_ptod( const char * s, char ** endptr ); + +/* -------------------------------------------------------------------------- */ +/* Declaration of math helper functions (implemented in functions/math). */ +/* -------------------------------------------------------------------------- */ + +int _PDCLIB_isnand( double x ); +int _PDCLIB_isnanf( float x ); +int _PDCLIB_isnanl( long double x ); + +int _PDCLIB_isinfd( double x ); +int _PDCLIB_isinff( float x ); +int _PDCLIB_isinfl( long double x ); + +int _PDCLIB_signbitd( double x ); +int _PDCLIB_signbitf( float x ); +int _PDCLIB_signbitl( long double x ); + +int _PDCLIB_isfinited( double x ); +int _PDCLIB_isfinitef( float x ); +int _PDCLIB_isfinitel( long double x ); + +int _PDCLIB_isnormald( double x ); +int _PDCLIB_isnormalf( float x ); +int _PDCLIB_isnormall( long double x ); + +int _PDCLIB_fpclassifyd( double x ); +int _PDCLIB_fpclassifyf( float x ); +int _PDCLIB_fpclassifyl( long double x ); + +/* -------------------------------------------------------------------------- */ +/* errno */ +/* -------------------------------------------------------------------------- */ + +/* A mechanism for delayed evaluation. + 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 . +*/ +_PDCLIB_PUBLIC 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 << _PDCLIB_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_C; +extern struct _PDCLIB_lc_collate_t * _PDCLIB_lc_collate; + +/* One entry to the _PDCLIB_lc_ctype_t.entry data table */ +struct _PDCLIB_lc_ctype_entry_t +{ + _PDCLIB_uint_least16_t flags; /* Whether a character is of a given CTYPE */ + unsigned char upper; /* Result for toupper() */ + unsigned char lower; /* Result for tolower() */ +}; + +struct _PDCLIB_lc_ctype_t +{ + int alloced; /* .entry dynamically allocated? */ + int digits_low; /* Where decimal digits start */ + int digits_high; /* Where decimal digits end */ + int Xdigits_low; /* Where A..F start */ + int Xdigits_high; /* Where A..F end */ + int xdigits_low; /* Where a..f start */ + int xdigits_high; /* Where a..f end */ + struct _PDCLIB_lc_ctype_entry_t * entry; /* The data table */ +}; + +extern struct _PDCLIB_lc_ctype_t _PDCLIB_lc_ctype_C; +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_C; +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_C; +extern struct _PDCLIB_lc_time_t * _PDCLIB_lc_time; + +_PDCLIB_LOCAL struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale ); + +/* -------------------------------------------------------------------------- */ +/* Sanity checks */ +/* -------------------------------------------------------------------------- */ + +/* signed-ness of char */ +_PDCLIB_static_assert( _PDCLIB_CHAR_MIN == ((((char) -1) < 0) ? _PDCLIB_SCHAR_MIN : 0), "Compiler disagrees on signed-ness of 'char'." ); + +/* two's complement */ +#if _PDCLIB_TWOS_COMPLEMENT == 1 +#if _PDCLIB_CHAR_MIN < 0 +_PDCLIB_static_assert( ((char) ~ (char) 0 < 0), "Not two's complement on 'char'." ); +#endif +_PDCLIB_static_assert( ((short) ~ (short) 0 < 0), "Not two's complement on 'short'." ); +_PDCLIB_static_assert( ((int) ~ (int) 0 < 0), "Not two's complement on 'int'." ); +_PDCLIB_static_assert( ((long) ~ (long) 0 < 0), "Not two's complement on 'long'." ); +_PDCLIB_static_assert( ((long long) ~ (long long) 0 < 0), "Not two's complement on 'long long'." ); +#endif + +/* size_t as the result of sizeof */ +_PDCLIB_static_assert( sizeof( sizeof( int ) ) == sizeof( _PDCLIB_size_t ), "Compiler disagrees on size_t." ); + +/* wchar_t as the type of wide character literals */ +_PDCLIB_static_assert( sizeof( _PDCLIB_wchar_t ) == sizeof( L'x' ), "Compiler disagrees on wchar_t." ); +#ifdef __cplusplus +_PDCLIB_static_assert( sizeof( _PDCLIB_wchar_t ) == sizeof( wchar_t ), "Compiler disagrees on wchar_t (C++)." ); +#endif + +/* intptr_t/uintptr_t being wide enough to store the value of a pointer */ +_PDCLIB_static_assert( sizeof( void * ) == sizeof( _PDCLIB_intptr_t ), "Compiler disagrees on intptr_t." ); +_PDCLIB_static_assert( sizeof( void * ) == sizeof( _PDCLIB_uintptr_t ), "Compiler disagrees on uintptr_t." ); + +/* ptrdiff_t as the result of pointer arithmetic */ +_PDCLIB_static_assert( sizeof( &_PDCLIB_digits[1] - &_PDCLIB_digits[0] ) == sizeof( _PDCLIB_ptrdiff_t ), "Compiler disagrees on ptrdiff_t." ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_lib_ext1.h b/rocklibc/include/pdclib/_PDCLIB_lib_ext1.h new file mode 100644 index 0000000..fe96bca --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_lib_ext1.h @@ -0,0 +1,32 @@ +/* __STDC_WANT_LIB_EXT1__ redefinition guard + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef __STDC_WANT_LIB_EXT1__ + #ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__ + #if __STDC_WANT_LIB_EXT1_PREVIOUS__ != -1 + #error __STDC_WANT_LIB_EXT1__ undefined when it was defined earlier. + #endif + #else + #define __STDC_WANT_LIB_EXT1_PREVIOUS__ -1 + #endif +#else + #if ( __STDC_WANT_LIB_EXT1__ + 0 ) == 0 && ( 0 - __STDC_WANT_LIB_EXT1__ - 1 ) == 1 + #error __STDC_WANT_LIB_EXT1__ defined but empty. Should be an integer value. + #endif + #ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__ + #if ( __STDC_WANT_LIB_EXT1__ + 0 ) != __STDC_WANT_LIB_EXT1_PREVIOUS__ + #error __STDC_WANT_LIB_EXT1__ redefined from previous value. + #endif + #else + #if ( __STDC_WANT_LIB_EXT1__ + 0 ) == 0 + #define __STDC_WANT_LIB_EXT1_PREVIOUS__ 0 + #elif ( __STDC_WANT_LIB_EXT1__ + 0 ) == 1 + #define __STDC_WANT_LIB_EXT1_PREVIOUS__ 1 + #else + #error __STDC_WANT_LIB_EXT1__ set to value other than 0,1 -- undefined behavior + #endif + #endif +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_platform_errno.h b/rocklibc/include/pdclib/_PDCLIB_platform_errno.h new file mode 100644 index 0000000..04e4f3d --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_platform_errno.h @@ -0,0 +1,6 @@ +#ifndef _PDCLIB_PLATFORM_ERRNO +#define _PDCLIB_PLATFORM_ERRNO + +#include "errno.h" + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_platform_fcntl.h b/rocklibc/include/pdclib/_PDCLIB_platform_fcntl.h new file mode 100644 index 0000000..8c7c026 --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_platform_fcntl.h @@ -0,0 +1,6 @@ +#ifndef _PDCLIB_PLATFORM_FCNTL +#define _PDCLIB_PLATFORM_FCNTL + +#include "fcntl.h" + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_print.h b/rocklibc/include/pdclib/_PDCLIB_print.h new file mode 100644 index 0000000..015b0ff --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_print.h @@ -0,0 +1,145 @@ +/* PDCLib printf logic <_PDCLIB_print.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_PRINT_H +#define _PDCLIB_PRINT_H _PDCLIB_PRINT_H + +#include "pdclib/_PDCLIB_internal.h" + +#include +#include +#include + +/* 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 ) + + +/* Using an integer's bits as flags for both the conversion flags and length + modifiers. +*/ +#define E_minus (INT32_C(1)<<0) +#define E_plus (INT32_C(1)<<1) +#define E_alt (INT32_C(1)<<2) +#define E_space (INT32_C(1)<<3) + +#define E_zero (INT32_C(1)<<4) +#define E_done (INT32_C(1)<<5) +#define E_char (INT32_C(1)<<6) +#define E_short (INT32_C(1)<<7) + +#define E_long (INT32_C(1)<<8) +#define E_llong (INT32_C(1)<<9) +#define E_intmax (INT32_C(1)<<10) +#define E_size (INT32_C(1)<<11) + +#define E_ptrdiff (INT32_C(1)<<12) +#define E_pointer (INT32_C(1)<<13) +#define E_double (INT32_C(1)<<14) +#define E_ldouble (INT32_C(1)<<15) + +#define E_lower (INT32_C(1)<<16) +#define E_unsigned (INT32_C(1)<<17) +#define E_decimal (INT32_C(1)<<18) +#define E_exponent (INT32_C(1)<<19) + +#define E_generic (INT32_C(1)<<20) +#define E_hexa (INT32_C(1)<<21) + +/* -------------------------------------------------------------------------- */ +/* _PDCLIB_bigint_t support (required for floating point conversions) */ +/* -------------------------------------------------------------------------- */ + +/* Must be divisible by 32. */ +/* 1120 is enough for 64bit floats. A 128 float takes 16544 bits. */ +#define _PDCLIB_BIGINT_BITS 1120 + +#if _PDCLIB_BIGINT_DIGIT_BITS == 32 +#define _PDCLIB_BIGINT_DIGIT_MAX _PDCLIB_UINT_LEAST32_C( 0xFFFFFFFF ) +typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_digit_t; +typedef _PDCLIB_int_least32_t _PDCLIB_bigint_sdigit_t; +typedef _PDCLIB_uint_least64_t _PDCLIB_bigint_arith_t; +#elif _PDCLIB_BIGINT_DIGIT_BITS == 16 +#define _PDCLIB_BIGINT_DIGIT_MAX _PDCLIB_UINT_LEAST16_C( 0xFFFF ) +typedef _PDCLIB_uint_least16_t _PDCLIB_bigint_digit_t; +typedef _PDCLIB_int_least16_t _PDCLIB_bigint_sdigit_t; +typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_arith_t; +#else +#error _PDCLIB_BIGINT_DIGIT_BITS.needs to be 16 or 32. +#endif + +/* How many "digits" a _PDCLIB_bigint_t holds. */ +#define _PDCLIB_BIGINT_DIGITS _PDCLIB_BIGINT_BITS / _PDCLIB_BIGINT_DIGIT_BITS + +/* Maximum number of characters needed for _PDCLIB_bigint_tostring() */ +#define _PDCLIB_BIGINT_CHARS ( _PDCLIB_BIGINT_BITS / 4 + _PDCLIB_BIGINT_DIGITS + 2 ) + +/* Type */ +/* ---- */ + +typedef struct +{ + /* Number of digits used; zero value == zero size */ + _PDCLIB_size_t size; + /* Least significant digit first */ + _PDCLIB_bigint_digit_t data[ _PDCLIB_BIGINT_DIGITS ]; +} _PDCLIB_bigint_t; + +typedef struct +{ + _PDCLIB_bigint_t mantissa; + _PDCLIB_int_least16_t exponent; + _PDCLIB_int_least16_t scale; + enum + { + _PDCLIB_FP_NORMAL, + _PDCLIB_FP_SUBNORMAL, + _PDCLIB_FP_INF, + _PDCLIB_FP_NAN + } state; + char sign; +} _PDCLIB_fp_t; + +void _PDCLIB_fp_from_dbl( _PDCLIB_fp_t * fp, double value ); +void _PDCLIB_fp_from_ldbl( _PDCLIB_fp_t * fp, long double value ); + +void _PDCLIB_bigint_from_digit( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_digit_t digit ); +void _PDCLIB_bigint_from_pow2( _PDCLIB_bigint_t * bigint, unsigned pow ); +void _PDCLIB_bigint_from_pow10( _PDCLIB_bigint_t * bigint, unsigned pow ); +void _PDCLIB_bigint_from_bigint( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); +void _PDCLIB_bigint_add( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); +void _PDCLIB_bigint_mul( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); +void _PDCLIB_bigint_mul_pow10( _PDCLIB_bigint_t * bigint, int pow10 ); +int _PDCLIB_bigint_cmp( _PDCLIB_bigint_t const * lhs, _PDCLIB_bigint_t const * rhs ); +void _PDCLIB_bigint_shl( _PDCLIB_bigint_t * bigint, _PDCLIB_size_t bits ); +void _PDCLIB_bigint_mul10( _PDCLIB_bigint_t * bigint ); +int _PDCLIB_bigint_digit_log2( _PDCLIB_bigint_digit_t digit ); +int _PDCLIB_bigint_log2( _PDCLIB_bigint_t const * bigint ); +unsigned _PDCLIB_bigint_div( _PDCLIB_bigint_t * dividend, _PDCLIB_bigint_t const * divisor ); + +void _PDCLIB_print_integer( struct _PDCLIB_imaxdiv_t div, struct _PDCLIB_status_t * status ); +void _PDCLIB_print_string( const char * s, struct _PDCLIB_status_t * status ); +void _PDCLIB_print_fp( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status ); +int _PDCLIB_print_fp_deci( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer ); +void _PDCLIB_print_fp_hexa( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer ); +void _PDCLIB_print_fp_dragon4( _PDCLIB_bigint_t * fp, struct _PDCLIB_status_t * status ); + +#endif diff --git a/rocklibc/include/pdclib/_PDCLIB_tzcode.h b/rocklibc/include/pdclib/_PDCLIB_tzcode.h new file mode 100644 index 0000000..d12c4a7 --- /dev/null +++ b/rocklibc/include/pdclib/_PDCLIB_tzcode.h @@ -0,0 +1,153 @@ +/* TZ Code declarations and definitions <_PDCLIB_tzcode.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_TZCODE_H +#define _PDCLIB_TZCODE_H _PDCLIB_TZCODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include + +/* Handy macros that are independent of tzfile implementation. */ +#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define AVGSECSPERYEAR 31556952L +#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR) +#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +extern struct tm _PDCLIB_tm; +extern int lcl_is_set; + +static const char gmt[] = "GMT"; + +static const int mon_lengths[ 2 ][ MONSPERYEAR ] = +{ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static const int year_lengths[2] = +{ + DAYSPERNYEAR, DAYSPERLYEAR +}; + +/* time type information */ +struct ttinfo +{ + int_fast32_t utoff; /* UT offset in seconds */ + bool isdst; /* used to set tm_isdst */ + int desigidx; /* abbreviation list index */ + bool ttisstd; /* transition is std time */ + bool ttisut; /* transition is UT */ +}; + +/* leap second information */ +struct lsinfo +{ + time_t trans; /* transition time */ + int_fast64_t corr; /* correction to apply */ +}; + +#define BIGGEST( a, b ) (((a) > (b)) ? (a) : (b)) + +#ifndef TZ_MAX_TIMES +#define TZ_MAX_TIMES 2000 +#endif + +#ifndef TZ_MAX_TYPES +/* This must be at least 17 for Europe/Vilnius. */ +/* Limited by what (unsigned char)s can hold */ +#define TZ_MAX_TYPES 256 +#endif + +#ifndef TZ_MAX_CHARS +/* Maximum number of abbreviation characters */ +/* Limited by what (unsigned char)s can hold */ +#define TZ_MAX_CHARS 50 +#endif + +#ifndef TZ_MAX_LEAPS +/* Maximum number of leap second corrections */ +#define TZ_MAX_LEAPS 50 +#endif + +#ifdef TZNAME_MAX +#define MY_TZNAME_MAX TZNAME_MAX +#else +#define MY_TZNAME_MAX 255 +#endif + +struct state +{ + int leapcnt; + int timecnt; + int typecnt; + int charcnt; + bool goback; + bool goahead; + time_t ats[ TZ_MAX_TIMES ]; + unsigned char types[ TZ_MAX_TIMES ]; + struct ttinfo ttis[ TZ_MAX_TYPES ]; + char chars[ BIGGEST( BIGGEST( TZ_MAX_CHARS + 1, sizeof gmt ), ( 2 * ( MY_TZNAME_MAX + 1 ) ) ) ]; + struct lsinfo lsis[ TZ_MAX_LEAPS ]; + + /* The time type to use for early times or if no transitions. + It is always zero for recent tzdb releases. + It might be nonzero for data from tzdb 2018e or earlier. + */ + int defaulttype; +}; + +extern struct state _PDCLIB_lclmem; +extern struct state _PDCLIB_gmtmem; + +void _PDCLIB_gmtcheck(void); +struct tm * _PDCLIB_gmtsub( struct state const * sp, time_t const * timep, int_fast32_t offset, struct tm * tmp ); +bool _PDCLIB_increment_overflow( int * ip, int j ); +void _PDCLIB_init_ttinfo( struct ttinfo * s, int_fast32_t utoff, bool isdst, int desigidx ); +struct tm * _PDCLIB_localsub( struct state const * sp, time_t const * timep, int_fast32_t setname, struct tm * const tmp ); +struct tm * _PDCLIB_localtime_tzset( time_t const * timep, struct tm * tmp, bool setname ); +time_t _PDCLIB_mktime_tzname( struct state * sp, struct tm * tmp, bool setname ); +struct tm * _PDCLIB_timesub( const time_t * timep, int_fast32_t offset, const struct state * sp, struct tm * tmp ); +int _PDCLIB_tzload( char const * name, struct state * sp, bool doextend ); +bool _PDCLIB_tzparse(char const *, struct state *, bool); +void _PDCLIB_tzset_unlocked( void ); +void _PDCLIB_update_tzname_etc( struct state const * sp, struct ttinfo const * ttisp ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/signal.h b/rocklibc/include/signal.h new file mode 100644 index 0000000..1f679ec --- /dev/null +++ b/rocklibc/include/signal.h @@ -0,0 +1,91 @@ +/* Signal handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_SIGNAL_H +#define _PDCLIB_SIGNAL_H _PDCLIB_SIGNAL_H + +#include "pdclib/_PDCLIB_internal.h" + +/* 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 + +/* 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 (void (*)( int ))0 +#define SIG_ERR (void (*)( int ))-1 +#define SIG_IGN (void (*)( int ))1 + +typedef _PDCLIB_sig_atomic_t sig_atomic_t; + +/* 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. +*/ +_PDCLIB_PUBLIC void ( *signal( int sig, void ( *func )( int ) ) )( int ); + +/* 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. */ +_PDCLIB_PUBLIC int raise( int sig ); + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_SIGNAL_H +#include _PDCLIB_EXTEND_SIGNAL_H +#endif + +#endif diff --git a/rocklibc/include/stdalign.h b/rocklibc/include/stdalign.h new file mode 100644 index 0000000..b302601 --- /dev/null +++ b/rocklibc/include/stdalign.h @@ -0,0 +1,30 @@ +/* Alignment + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDALIGN_H +#define _PDCLIB_STDALIGN_H _PDCLIB_STDALIGN_H + +#ifndef __cplusplus +#define __alignas_is_defined 1 +#define __alignof_is_defined 1 + +#if ! defined( __STDC_VERSION__ ) || ( __STDC_VERSION__ < 202311L ) +#define alignas _Alignas +#define alignof _Alignof +#elif __STDC_VERSION__ >= 202311L +#warning has been deprecated as of C23. +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDALIGN_H +#include _PDCLIB_EXTEND_STDALIGN_H +#endif + +#endif + diff --git a/rocklibc/include/stdarg.h b/rocklibc/include/stdarg.h new file mode 100644 index 0000000..7741b70 --- /dev/null +++ b/rocklibc/include/stdarg.h @@ -0,0 +1,34 @@ +/* Variable arguments + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDARG_H +#define _PDCLIB_STDARG_H _PDCLIB_STDARG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_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 ) + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDARG_H +#include _PDCLIB_EXTEND_STDARG_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/stdbool.h b/rocklibc/include/stdbool.h new file mode 100644 index 0000000..e901f63 --- /dev/null +++ b/rocklibc/include/stdbool.h @@ -0,0 +1,24 @@ +/* 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 _PDCLIB_STDBOOL_H +#define _PDCLIB_STDBOOL_H _PDCLIB_STDBOOL_H + +#ifndef __cplusplus +#define bool _Bool +#define true 1 +#define false 0 +#endif +#define __bool_true_false_are_defined 1 + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDBOOL_H +#include _PDCLIB_EXTEND_STDBOOL_H +#endif + +#endif diff --git a/rocklibc/include/stddef.h b/rocklibc/include/stddef.h new file mode 100644 index 0000000..7d03d07 --- /dev/null +++ b/rocklibc/include/stddef.h @@ -0,0 +1,55 @@ +/* Common definitions + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDDEF_H +#define _PDCLIB_STDDEF_H _PDCLIB_STDDEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +typedef _PDCLIB_ptrdiff_t ptrdiff_t; + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef __cplusplus +typedef _PDCLIB_wchar_t wchar_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +#define offsetof( type, member ) _PDCLIB_offsetof( type, member ) + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef size_t rsize_t; +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDDEF_H +#include _PDCLIB_EXTEND_STDDEF_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/stdint.h b/rocklibc/include/stdint.h new file mode 100644 index 0000000..04af6b0 --- /dev/null +++ b/rocklibc/include/stdint.h @@ -0,0 +1,236 @@ +/* Integer types + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDINT_H +#define _PDCLIB_STDINT_H _PDCLIB_STDINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +/* 7.18.1.1 Exact-width integer types. */ + +#ifdef _PDCLIB_int8_t +typedef _PDCLIB_int8_t int8_t; +typedef _PDCLIB_uint8_t uint8_t; +#endif + +#ifdef _PDCLIB_int16_t +typedef _PDCLIB_int16_t int16_t; +typedef _PDCLIB_uint16_t uint16_t; +#endif + +#ifdef _PDCLIB_int32_t +typedef _PDCLIB_int32_t int32_t; +typedef _PDCLIB_uint32_t uint32_t; +#endif + +#ifdef _PDCLIB_int64_t +typedef _PDCLIB_int64_t int64_t; +typedef _PDCLIB_uint64_t uint64_t; +#endif + +/* 7.18.1.2 Minimum-width integer types */ + +/* You are allowed to add more types here, e.g. int_least24_t. */ + +typedef _PDCLIB_int_least8_t int_least8_t; +typedef _PDCLIB_int_least16_t int_least16_t; +typedef _PDCLIB_int_least32_t int_least32_t; +typedef _PDCLIB_int_least64_t int_least64_t; + +typedef _PDCLIB_uint_least8_t uint_least8_t; +typedef _PDCLIB_uint_least16_t uint_least16_t; +typedef _PDCLIB_uint_least32_t uint_least32_t; +typedef _PDCLIB_uint_least64_t 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 _PDCLIB_int_fast8_t int_fast8_t; +typedef _PDCLIB_int_fast16_t int_fast16_t; +typedef _PDCLIB_int_fast32_t int_fast32_t; +typedef _PDCLIB_int_fast64_t int_fast64_t; + +typedef _PDCLIB_uint_fast8_t uint_fast8_t; +typedef _PDCLIB_uint_fast16_t uint_fast16_t; +typedef _PDCLIB_uint_fast32_t uint_fast32_t; +typedef _PDCLIB_uint_fast64_t uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +typedef _PDCLIB_intptr_t intptr_t; +typedef _PDCLIB_uintptr_t uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ + +typedef _PDCLIB_intmax_t intmax_t; +typedef _PDCLIB_uintmax_t uintmax_t; + +/* 7.18.2 Limits of specified-width integer types */ + +#if defined( __cplusplus ) && __cplusplus < 201103L +#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 */ + +#if _PDCLIB_TWOS_COMPLEMENT == 1 + +#if _PDCLIB_INT_LEAST8_MAX == 0x7f +#define INT8_MAX _PDCLIB_INT_LEAST8_MAX +#define INT8_MIN _PDCLIB_INT_LEAST8_MIN +#define UINT8_MAX _PDCLIB_UINT_LEAST8_MAX +#endif + +#if _PDCLIB_INT_LEAST16_MAX == 0x7fff +#define INT16_MAX _PDCLIB_INT_LEAST16_MAX +#define INT16_MIN _PDCLIB_INT_LEAST16_MIN +#define UINT16_MAX _PDCLIB_UINT_LEAST16_MAX +#endif + +#if _PDCLIB_INT_LEAST32_MAX == 0x7fffffffl +#define INT32_MAX _PDCLIB_INT_LEAST32_MAX +#define INT32_MIN _PDCLIB_INT_LEAST32_MIN +#define UINT32_MAX _PDCLIB_UINT_LEAST32_MAX +#endif + +#if _PDCLIB_INT_LEAST64_MAX == 0x7fffffffffffffffll +#define INT64_MAX _PDCLIB_INT_LEAST64_MAX +#define INT64_MIN _PDCLIB_INT_LEAST64_MIN +#define UINT64_MAX _PDCLIB_UINT_LEAST64_MAX +#endif + +#endif + +/* 7.18.2.2 Limits of minimum-width integer types */ + +#define INT_LEAST8_MIN _PDCLIB_INT_LEAST8_MIN +#define INT_LEAST8_MAX _PDCLIB_INT_LEAST8_MAX +#define UINT_LEAST8_MAX _PDCLIB_UINT_LEAST8_MAX + +#define INT_LEAST16_MIN _PDCLIB_INT_LEAST16_MIN +#define INT_LEAST16_MAX _PDCLIB_INT_LEAST16_MAX +#define UINT_LEAST16_MAX _PDCLIB_UINT_LEAST16_MAX + +#define INT_LEAST32_MIN _PDCLIB_INT_LEAST32_MIN +#define INT_LEAST32_MAX _PDCLIB_INT_LEAST32_MAX +#define UINT_LEAST32_MAX _PDCLIB_UINT_LEAST32_MAX + +#define INT_LEAST64_MIN _PDCLIB_INT_LEAST64_MIN +#define INT_LEAST64_MAX _PDCLIB_INT_LEAST64_MAX +#define UINT_LEAST64_MAX _PDCLIB_UINT_LEAST64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ + +#define INT_FAST8_MIN _PDCLIB_INT_FAST8_MIN +#define INT_FAST8_MAX _PDCLIB_INT_FAST8_MAX +#define UINT_FAST8_MAX _PDCLIB_UINT_FAST8_MAX + +#define INT_FAST16_MIN _PDCLIB_INT_FAST16_MIN +#define INT_FAST16_MAX _PDCLIB_INT_FAST16_MAX +#define UINT_FAST16_MAX _PDCLIB_UINT_FAST16_MAX + +#define INT_FAST32_MIN _PDCLIB_INT_FAST32_MIN +#define INT_FAST32_MAX _PDCLIB_INT_FAST32_MAX +#define UINT_FAST32_MAX _PDCLIB_UINT_FAST32_MAX + +#define INT_FAST64_MIN _PDCLIB_INT_FAST64_MIN +#define INT_FAST64_MAX _PDCLIB_INT_FAST64_MAX +#define UINT_FAST64_MAX _PDCLIB_UINT_FAST64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ + +#define INTPTR_MIN _PDCLIB_INTPTR_MIN +#define INTPTR_MAX _PDCLIB_INTPTR_MAX +#define UINTPTR_MAX _PDCLIB_UINTPTR_MAX + +/* 7.18.2.5 Limits of greatest-width integer types */ + +#define INTMAX_MIN _PDCLIB_INTMAX_MIN +#define INTMAX_MAX _PDCLIB_INTMAX_MAX +#define UINTMAX_MAX _PDCLIB_UINTMAX_MAX + +/* 7.18.3 Limits of other integer types */ + +#define PTRDIFF_MIN _PDCLIB_PTRDIFF_MIN +#define PTRDIFF_MAX _PDCLIB_PTRDIFF_MAX + +#define SIG_ATOMIC_MIN _PDCLIB_SIG_ATOMIC_MIN +#define SIG_ATOMIC_MAX _PDCLIB_SIG_ATOMIC_MAX + +#define SIZE_MAX _PDCLIB_SIZE_MAX + +#define WCHAR_MIN _PDCLIB_WCHAR_MIN +#define WCHAR_MAX _PDCLIB_WCHAR_MAX + +#define WINT_MIN _PDCLIB_WINT_MIN +#define WINT_MAX _PDCLIB_WINT_MAX + +#endif + +/* 7.18.4 Macros for integer constants */ + +#if defined( __cplusplus ) && __cplusplus < 201103L +#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 */ + +/* Expand to an integer constant of specified value and type int_leastN_t */ + +#define INT8_C _PDCLIB_INT_LEAST8_C +#define INT16_C _PDCLIB_INT_LEAST16_C +#define INT32_C _PDCLIB_INT_LEAST32_C +#define INT64_C _PDCLIB_INT_LEAST64_C + +/* Expand to an integer constant of specified value and type uint_leastN_t */ + +#define UINT8_C _PDCLIB_UINT_LEAST8_C +#define UINT16_C _PDCLIB_UINT_LEAST16_C +#define UINT32_C _PDCLIB_UINT_LEAST32_C +#define UINT64_C _PDCLIB_UINT_LEAST64_C + +/* 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_INTMAX_C( value ) + +/* Expand to an integer constant of specified value and type uintmax_t */ +#define UINTMAX_C( value ) _PDCLIB_UINTMAX_C( value ) + +#endif + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 +#define RSIZE_MAX ( _PDCLIB_SIZE_MAX >> 1 ) +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDINT_H +#include _PDCLIB_EXTEND_STDINT_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/stdio.h b/rocklibc/include/stdio.h new file mode 100644 index 0000000..4ee538f --- /dev/null +++ b/rocklibc/include/stdio.h @@ -0,0 +1,935 @@ +/* Input/output + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDIO_H +#define _PDCLIB_STDIO_H _PDCLIB_STDIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* See setvbuf(), third argument */ +#define _IOFBF (1u<<0) +#define _IOLBF (1u<<1) +#define _IONBF (1u<<2) + +/* The following are platform-dependent, and defined in _PDCLIB_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"). +*/ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC int rename( const char * oldpath, const char * newpath ); + +/* 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()). +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC FILE * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_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.) + + Returns a pointer to the stream handle if successfull, NULL otherwise. +*/ +_PDCLIB_PUBLIC FILE * freopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, FILE * _PDCLIB_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 ). +*/ +_PDCLIB_PUBLIC void setbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int setvbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int fprintf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int fscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fprintf( stdout, format, ... ). */ +_PDCLIB_PUBLIC int printf( const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fscanf( stdin, format, ... ). */ +_PDCLIB_PUBLIC int scanf( const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int snprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fprintf( stdout, format, ... ), except that the result is + written into the buffer pointed to by s, instead of stdout. +*/ +_PDCLIB_PUBLIC int sprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fscanf( stdin, format, ... ), except that the input is read + from the buffer pointed to by s, instead of stdin. +*/ +_PDCLIB_PUBLIC int sscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vfprintf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vprintf( const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vscanf( const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vsnprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vsprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC char * fgets( char * _PDCLIB_restrict s, int n, FILE * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int fputs( const char * _PDCLIB_restrict s, FILE * _PDCLIB_restrict stream ); + +/* Equivalent to fgetc( stream ), but may be overloaded by a macro that + evaluates its parameter more than once. +*/ +_PDCLIB_PUBLIC int getc( FILE * stream ); + +/* Equivalent to fgetc( stdin ). */ +_PDCLIB_PUBLIC int getchar( void ); + +/* Equivalent to fputc( c, stream ), but may be overloaded by a macro that + evaluates its parameter more than once. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC size_t fread( void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_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(). +*/ +_PDCLIB_PUBLIC int fgetpos( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC long int ftell( FILE * stream ); + +/* Equivalent to (void)fseek( stream, 0L, SEEK_SET ), except that the error + indicator for the stream is also cleared. +*/ +_PDCLIB_PUBLIC void rewind( FILE * stream ); + +/* Error-handling functions */ + +/* Clear the end-of-file and error indicators for the given stream. */ +_PDCLIB_PUBLIC void clearerr( FILE * stream ); + +/* Return zero if the end-of-file indicator for the given stream is not set, + nonzero otherwise. +*/ +_PDCLIB_PUBLIC int feof( FILE * stream ); + +/* Return zero if the error indicator for the given stream is not set, nonzero + otherwise. +*/ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC void perror( const char * s ); + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#define L_tmpnam_s _PDCLIB_L_tmpnam +#define TMP_MAX_S _PDCLIB_TMP_MAX + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef _PDCLIB_size_t rsize_t; +#endif + +/* 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()). + If successful, the FILE * pointed to by streamptr will be set to point at + the opened file handle, and the function returns zero. If unsuccessful, + the FILE * pointed to by streamptr will be set to NULL and a non-zero + value is returned. + The following conditions will be considered runtime constraint violations: + - streamptr being NULL. + In case of a constraint violation, no file is being created. + This implementation does not remove temporary files if the process aborts + abnormally (e.g. abort()). +*/ +_PDCLIB_PUBLIC errno_t tmpfile_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr ); + +/* Open the file with the given filename in the given mode, and sets the given + streamptr to point at the file handle for that file, 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. + + The following conditions will be considered runtime constraint violations: + - streamptr being NULL. + - filename being NULL. + - mode being NULL. + In case of a constraint violation, no file is opened. If streamptr is not + NULL, *streamptr is set to NULL. + + Returns zero if successful, non-zero otherwise. +*/ +_PDCLIB_PUBLIC errno_t fopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_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.) + + The following conditions will be considered runtime constraint violations: + - newstreamptr being NULL. + - mode being NULL. + - stream being NULL. + In case of a constraint violation, no attempt is made to close or open any + file. If newstreamptr is not NULL, *newstreamptr is set to NULL. + + Returns zero if successfull, non-zero otherwise. +*/ +_PDCLIB_PUBLIC errno_t freopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict newstreamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, FILE * _PDCLIB_restrict stream ); + +/* None of these are implemented yet. Placeholder declarations. */ +_PDCLIB_PUBLIC errno_t tmpnam_s( char * s, rsize_t maxsize ); +_PDCLIB_PUBLIC int fprintf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int fscanf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int printf_s( const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int scanf_s( const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int snprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int sprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int sscanf_s( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int vfprintf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vfscanf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vprintf_s( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vscanf_s( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vsnprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vsprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vsscanf_s( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC char * gets_s( char * s, rsize_t n ); + +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDIO_H +#include _PDCLIB_EXTEND_STDIO_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/stdlib.h b/rocklibc/include/stdlib.h new file mode 100644 index 0000000..9dc8b33 --- /dev/null +++ b/rocklibc/include/stdlib.h @@ -0,0 +1,379 @@ +/* General utilities + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDLIB_H +#define _PDCLIB_STDLIB_H _PDCLIB_STDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* Numeric conversion functions */ + +/* TODO: atof(), strtof(), strtod(), strtold() */ + +_PDCLIB_PUBLIC double atof( const char * nptr ); +_PDCLIB_PUBLIC double strtod( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr ); +_PDCLIB_PUBLIC float strtof( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr ); +_PDCLIB_PUBLIC long double strtold( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr ); + +/* Separate 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. +*/ +_PDCLIB_PUBLIC long int strtol( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC long long int strtoll( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC unsigned long int strtoul( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC unsigned long long int strtoull( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_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.) +*/ +_PDCLIB_PUBLIC int atoi( const char * nptr ); +_PDCLIB_PUBLIC long int atol( const char * nptr ); +_PDCLIB_PUBLIC 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;) +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC void * realloc( void * ptr, size_t size ); + +/* 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. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void abort( void ) _PDCLIB_NORETURN; + +/* Register a function that will be called on quick_exit(). + 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. +*/ +_PDCLIB_PUBLIC int at_quick_exit( void ( *func )( 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void exit( int status ) _PDCLIB_NORETURN; + +/* Normal process termination. Functions registered by at_quick_exit() (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.) + quick_exit() does not return. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void quick_exit( int status ) _PDCLIB_NORETURN; + +/* Normal process termination. Functions registered by atexit()/at_quick_exit() + (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. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void _Exit( int status ) _PDCLIB_NORETURN; + +/* 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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 a matching element found, or NULL if no + match is found. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int abs( int j ); +_PDCLIB_PUBLIC long int labs( long int j ); +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC div_t div( int numer, int denom ); +_PDCLIB_PUBLIC ldiv_t ldiv( long int numer, long int denom ); +_PDCLIB_PUBLIC lldiv_t lldiv( long long int numer, long long int denom ); + +/* TODO: Multibyte / wide character conversion functions */ + +/* TODO: Macro MB_CUR_MAX */ + +/* +_PDCLIB_PUBLIC int mblen( const char * s, size_t n ); +_PDCLIB_PUBLIC int mbtowc( wchar_t * _PDCLIB_restrict pwc, const char * _PDCLIB_restrict s, size_t n ); +_PDCLIB_PUBLIC int wctomb( char * s, wchar_t wc ); +_PDCLIB_PUBLIC size_t mbstowcs( wchar_t * _PDCLIB_restrict pwcs, const char * _PDCLIB_restrict s, size_t n ); +_PDCLIB_PUBLIC size_t wcstombs( char * _PDCLIB_restrict s, const wchar_t * _PDCLIB_restrict pwcs, size_t n ); +*/ + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef size_t rsize_t; +#endif + +/* A function type that can serve as a constraint handler (see below). The + first parameter is an error message on the constraint violation, the + second parameter a pointer to an implementation-defined object, the + third an error code related to the constraint violation. + If the function calling the constraint handler is defined to return + errno_t, the third parameter will be identical to the return value of + that function. + This implementation sets the second parameter of the constraint handler + call to NULL. +*/ +typedef void ( *constraint_handler_t )( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ); + +/* The currently active constraint violation handler. This implementation + sets abort_handler_s as the default constraint violation handler. +*/ +extern constraint_handler_t _PDCLIB_constraint_handler; + +/* Set the given function as the new constraint violation handler. */ +_PDCLIB_PUBLIC constraint_handler_t set_constraint_handler_s( constraint_handler_t handler ); + +/* One of two predefined constraint violation handlers. When called, it will + print an error message (including the message passed as the first + parameter to the handler function) and call abort(). +*/ +_PDCLIB_PUBLIC void abort_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ); + +/* One of two predefined constraint violation handlers. Simply returns, + ignoring the constraint violation. +*/ +_PDCLIB_PUBLIC void ignore_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ); + +/* Search an environment-provided key-value map for the given key name. + If the name is found, + - if len is not NULL, the length of the associated value string is stored + in that location. + - if len < maxsize, the value string is copied to the indicated location. + If the name is not found, + - if len is not NULL, a zero is stored in that location. + - if maxsize > 0, value[0] is set to the null character. + Details on the provided keys and how to set / change them are determined by + the hosting OS and its glue function. + The following conditions will be considered runtime constraint violations: + - value being a NULL pointer. + - maxsize == 0 or maxsize > RSIZE_MAX. + In case of a constraint violation, if len is not NULL a zero will be + stored at that location, and the environment key-value map not searched. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t getenv_s( size_t * _PDCLIB_restrict len, char * _PDCLIB_restrict value, rsize_t maxsize, const char * _PDCLIB_restrict name ); + +/* 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, a pointer to the array member as + second parameter, and the context parameter passed to bsearch_s() as third + 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 a matching element found, or NULL if no + match is found. + The following conditions will be considered runtime constraint violations: + - nmemb or size > RSIZE_MAX. + - nmemb > 0 and either of key, base, or compar being a null pointer. + In case of a constraint violation, the array will not be searched. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC void * bsearch_s( const void * key, const void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void * k, const void * y, void * context ), void * context ); + +/* 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, with the first two arguments + being pointers to the two objects to be compared, and the third argument + being the context parameter passed to qsort_s. The compar function 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. + The following conditions will be considered runtime constraint violations: + - nmemb or size > RSIZE_MAX. + - nmemb > 0 and either of base or compar being a null pointer. + In case of a constraint violation, the array will not be sorted. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t qsort_s( void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void * x, const void * y, void * context ), void * context ); + +/* TODO: Multibyte / wide character functions */ + +#endif + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDLIB_H +#include _PDCLIB_EXTEND_STDLIB_H +#endif + +#endif diff --git a/rocklibc/include/stdnoreturn.h b/rocklibc/include/stdnoreturn.h new file mode 100644 index 0000000..ab4ddb4 --- /dev/null +++ b/rocklibc/include/stdnoreturn.h @@ -0,0 +1,26 @@ +/* _Noreturn + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDNORETURN_H +#define _PDCLIB_STDNORETURN_H _PDCLIB_STDNORETURN_H + +#include "pdclib/_PDCLIB_internal.h" + +/* This basically breaks the letter of the standard (which states that + noreturn be defined to _Noreturn). This defines noreturn -> _Noreturn + on C11 compliant compilers only (as older compilers do not know about + _Noreturn). +*/ +#define noreturn _PDCLIB_Noreturn + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDNORETURN_H +#include _PDCLIB_EXTEND_STDNORETURN_H +#endif + +#endif diff --git a/rocklibc/include/string.h b/rocklibc/include/string.h new file mode 100644 index 0000000..05062fd --- /dev/null +++ b/rocklibc/include/string.h @@ -0,0 +1,394 @@ +/* String handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STRING_H +#define _PDCLIB_STRING_H _PDCLIB_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* 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. +*/ +_PDCLIB_PUBLIC void * memcpy( void * _PDCLIB_restrict s1, const void * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC void * memmove( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n ); + +/* Copy the character array s2 (including terminating '\0' byte) into the + character array s1. + Returns the value of s1. +*/ +_PDCLIB_PUBLIC char * strcpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC char * strncpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC char * strcat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ); + +/* Append a maximum of n characters from the character array s2 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. +*/ +_PDCLIB_PUBLIC char * strncat( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC size_t strxfrm( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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 separator characters + which can differ from call to call. Leading separators are skipped, the first + trailing separator overwritten with '\0'. + Returns a pointer to the next token. + WARNING: This function uses static storage, and as such is not reentrant. +*/ +_PDCLIB_PUBLIC char * strtok( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC char * strerror( int errnum ); + +/* Returns the length of the string s (excluding terminating '\0'). +*/ +_PDCLIB_PUBLIC size_t strlen( const char * s ); + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef _PDCLIB_size_t rsize_t; +#endif + +/* Copy a number of n characters from the memory area pointed to by s2 to the + area pointed to by s1 of size s1max. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - n > s1max (not enough space in s1). + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX + then the first s1max characters of s1 will be set to zero. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t memcpy_s( void * _PDCLIB_restrict s1, rsize_t s1max, const void * _PDCLIB_restrict s2, rsize_t n ); + +/* Copy a number of n characters from the memory area pointed to by s2 to the + area pointed to by s1 of size s1max. The two areas may overlap. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - n > s1max (not enough space in s1). + In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX + then the first s1max characters of s1 will be set to zero. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t memmove_s( void * _PDCLIB_restrict s1, rsize_t s1max, const void * _PDCLIB_restrict s2, rsize_t n ); + +/* Copy the character array s2 (including terminating '\0' byte) into the + character array s1. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max being zero or > RSIZE_MAX. + - s1max not greater than strnlen_s( s2, s1max ) (not enough space in s1). + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX + then s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strcpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 ); + +/* Copy a maximum of n characters from the character array s2 into the character + array s1. If s2 is longer than n, s1[n] will be set to '\0'. + Returns zero if successful, non-zero otherwise. + + ATTENTION ATTENTION ATTENTION + + This function differs in two fundamental ways from strncpy(): + - remaining space in s1 will NOT be zeroed. Their value is unspecified. + - s1 WILL be zero-terminated even if there is not enough space to hold + all n characters from s2. + + THANK YOU FOR YOUR ATTENTION. + + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - s1max being zero. + - n >= s1max and s1max <= strnlen_s( s2, s1max ) (not enough space in s1). + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strncpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n ); + +/* 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). + Elements following the terminating null character (if any) take unspecified + values. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max being > RSIZE_MAX. + - s1max being zero. + - not enough space in s1 for both s1 and the characters copied from s2. + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strcat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 ); + +/* Append a maximum of n characters from the character array s2 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. + Elements following the terminating null character (if any) take unspecified + values. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - s1max being zero. + - not enough space in s1 for both s1 and the characters copied from s2. + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strncat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n ); + +/* 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 of size *s1max. On subsequent calls, the first argument is + NULL unless you want to start parsing a new string. s2 holds an array of + separator characters which can differ from call to call. Leading separators + are skipped, the first trailing separator overwritten with '\0'. + Returns a pointer to the next token. + The following conditions will be considered runtime constraint violations: + - s1max, s2, or ptr being NULL. + - s1max or n being > RSIZE_MAX. + - s1max being zero. + - not enough space in s1 for both s1 and the characters copied from s2. + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC char * strtok_s( char * _PDCLIB_restrict s1, rsize_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr ); + +/* Write the character c (interpreted as unsigned char) to the first n + characters of the memory area pointed to by s of size smax. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s being NULL. + - smax or n being > RSIZE_MAX. + - n being > smax. + In case of a constraint violation, if s is not NULL and smax is <= RSIZE_MAX + the value of c (interpreted as unsigned char) is written to the first smax + characters of s. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t memset_s( void * s, rsize_t smax, int c, rsize_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. + If the length of the mapped string is < maxsize, the string is copied to s. + Otherwise, if maxsize is greater than zero, as much of the string as does + fit is copied, and s[maxsize-1] set to '\0'. If maxsize is greater than 3, + the partial string is made to end in "...". + Returns zero if the string was copied successfully in full, non-zero + otherwise. + The following conditions will be considered runtime constraint violations: + - s being NULL. + - maxsize being zero or > RSIZE_MAX. + In case of a constraint violation, s is not modified. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strerror_s( char * s, rsize_t maxsize, errno_t errnum ); + +/* Map an error number to a (locale-specific) error message string, the same + way as strerror_s() would do. Error numbers are typically errno values, + but any number is mapped to a message. + TODO: PDCLib does not yet support locales. + Returns the length of the mapped string. +*/ +_PDCLIB_PUBLIC size_t strerrorlen_s( errno_t errnum ); + +/* Returns the length of the string s (excluding terminating '\0'). + If there is no null character in the first maxsize characters of s, + rerturns maxsize. If s is NULL, returns zero. + At most the first maxsize characters of s shall be accessed by the + function. +*/ +_PDCLIB_PUBLIC size_t strnlen_s( const char * s, size_t maxsize ); + +#endif + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STRING_H +#include _PDCLIB_EXTEND_STRING_H +#endif + +#endif diff --git a/rocklibc/include/sys/stat.h b/rocklibc/include/sys/stat.h new file mode 100644 index 0000000..7225b36 --- /dev/null +++ b/rocklibc/include/sys/stat.h @@ -0,0 +1,50 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include + +// Basic POSIX types for i686 execution +typedef uint32_t dev_t; +typedef uint32_t ino_t; +typedef uint32_t mode_t; +typedef uint32_t nlink_t; +typedef uint32_t uid_t; +typedef uint32_t gid_t; +typedef int32_t off_t; +typedef int32_t time_t; + +// The stat layout expected by standard C files +struct stat { + dev_t st_dev; /* ID of device containing file */ + ino_t st_ino; /* Inode number */ + mode_t st_mode; /* File type and mode flags */ + nlink_t st_nlink; /* Number of hard links */ + uid_t st_uid; /* User ID of owner */ + gid_t st_gid; /* Group ID of owner */ + dev_t st_rdev; /* Device ID (if special file) */ + off_t st_size; /* Total size, in bytes */ + time_t st_atime; /* Time of last access */ + time_t st_mtime; /* Time of last modification */ + time_t st_ctime; /* Time of last status change */ +}; + +// Traditional POSIX file permission/type bitmasks +#define S_IFMT 0170000 /* Bitmask for the file type bit fields */ +#define S_IFSOCK 0140000 /* Socket */ +#define S_IFLNK 0120000 /* Symbolic link */ +#define S_IFREG 0100000 /* Regular file */ +#define S_IFBLK 0060000 /* Block device */ +#define S_IFDIR 0040000 /* Directory */ +#define S_IFCHR 0020000 /* Character device */ +#define S_IFIFO 0010000 /* FIFO */ + +#define S_IRUSR 00400 /* Owner has read permission */ +#define S_IWUSR 00200 /* Owner has write permission */ +#define S_IXUSR 00100 /* Owner has execute permission */ +#define S_IRWXU 00700 /* Owner has read, write, and execute permission */ + +// Helper check macros commonly used in PDCLib +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) + +#endif /* _SYS_STAT_H */ \ No newline at end of file diff --git a/rocklibc/include/sys/time.h b/rocklibc/include/sys/time.h new file mode 100644 index 0000000..de1d7ce --- /dev/null +++ b/rocklibc/include/sys/time.h @@ -0,0 +1,21 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#include + +// Represents an exact elapsed time signature +struct timeval { + time_t tv_sec; /* Seconds since Unix Epoch */ + int32_t tv_usec; /* Microseconds component */ +}; + +// Represents traditional timezone offsets (largely obsolete but required) +struct timezone { + int tz_minuteswest; /* Minutes west of Greenwich */ + int tz_dsttime; /* Type of DST correction */ +}; + +/* Prototype for time fetching system operation */ +int gettimeofday(struct timeval *restrict tv, void *restrict tz); + +#endif /* _SYS_TIME_H */ \ No newline at end of file diff --git a/rocklibc/include/sys/times.h b/rocklibc/include/sys/times.h new file mode 100644 index 0000000..0ca899e --- /dev/null +++ b/rocklibc/include/sys/times.h @@ -0,0 +1,17 @@ +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#include + +/* Structure describing CPU time used by a process and its children */ +struct tms { + clock_t tms_utime; /* User CPU time */ + clock_t tms_stime; /* System CPU time */ + clock_t tms_cutime; /* User CPU time of dead children */ + clock_t tms_cstime; /* System CPU time of dead children */ +}; + +/* Function prototype for timing system call */ +clock_t times(struct tms *buffer); + +#endif /* _SYS_TIMES_H */ \ No newline at end of file diff --git a/rocklibc/include/sys/types.h b/rocklibc/include/sys/types.h new file mode 100644 index 0000000..be32cab --- /dev/null +++ b/rocklibc/include/sys/types.h @@ -0,0 +1,29 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include + +// Standard signed and unsigned size primitives +typedef int32_t ssize_t; +typedef uint32_t size_t; + +// Process and Thread IDs +typedef int32_t pid_t; +typedef int32_t id_t; + +// File system block and reference markers +typedef int32_t blkcnt_t; +typedef int32_t blksize_t; +typedef uint32_t dev_t; +typedef uint32_t gid_t; +typedef uint32_t ino_t; +typedef uint32_t mode_t; +typedef uint32_t nlink_t; +typedef int32_t off_t; +typedef uint32_t uid_t; + +// Clock and Timing fields +typedef int32_t time_t; +typedef int32_t clock_t; + +#endif /* _SYS_TYPES_H */ \ No newline at end of file diff --git a/rocklibc/include/time.h b/rocklibc/include/time.h new file mode 100644 index 0000000..17ae34f --- /dev/null +++ b/rocklibc/include/time.h @@ -0,0 +1,191 @@ +/* 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. +*/ + +#ifndef _PDCLIB_TIME_H +#define _PDCLIB_TIME_H _PDCLIB_TIMEH + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* See comments in _PDCLIB_config.h on the semantics of time_t and clock_t. */ + +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 + +/* Implementor's note: If you change this structure, and are using Pthread + threading support, check auxiliary/pthread/pthread_readout.c for its + twin. It is imperative that Pthread and PDCLib use identical layouts for + struct timespec, as they are implicitly cast from one to the other. This + cannot be checked for in this header (as we may not include host system + headers here), so the assert()s are in pthread_readout.c (which, in turn, + cannot include *this* header, which is why this admonishment to keep the + definitions in sync exists...). +*/ +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. +*/ +_PDCLIB_PUBLIC clock_t clock( void ); + +/* Returns the difference between two calendar times in seconds. */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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". +*/ +_PDCLIB_PUBLIC char * asctime( const struct tm * timeptr ); + +/* Equivalent to asctime( localtime( timer ) ). */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC size_t strftime( char * _PDCLIB_restrict s, size_t maxsize, const char * _PDCLIB_restrict format, const struct tm * _PDCLIB_restrict timeptr ); + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef _PDCLIB_size_t rsize_t; +#endif + +/* Converts the broken-down time pointed to by timeptr into a string in the + form "Sun Sep 16 01:03:52 1973\n\0", which is stored in buffer s of maxsize. + Returns zero if the time was successfully converted and stored, non-zero + otherwise. + The following conditions will be considered runtime constraint violations: + - s or timeptr being NULL. + - maxsize being < 26 or > RSIZE_MAX. + - the broken-down time pointed to by timeptr not being normalized. + - the year represented by the broken-down time pointed to by timeptr + being < 0 or > 9999. + In case of a constraint violation, the time will not be converted. If + s is not NULL and maxsize is neither zero nor > RSIZE_MAX, s[0] will be + set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t asctime_s( char * s, rsize_t maxsize, const struct tm * timeptr ); + +/* Equivalent to asctime_s( s, maxsize, localtime( timer ) ). */ +_PDCLIB_PUBLIC errno_t ctime_s( char * s, rsize_t maxsize, const time_t * timer ); + +/* Converts the calender time pointed to by timer into a broken-down time + expressed as UTC, which gets stored in the result struct. + Returns a pointer to the broken-down time, or a NULL pointer if if + cannot be represented or stored. + The following conditions will be considered runtime constraint violations: + - timer or result being NULL. + In case of a constraint violation, the time will not be converted. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC struct tm * gmtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result ); + +/* Converts the calender time pointed to by timer into a broken-down time + expressed as local time, which gets stored in the result struct. + Returns a pointer to the broken-down time, or a NULL pointer if if + cannot be represented or stored. + The following conditions will be considered runtime constraint violations: + - timer or result being NULL. + In case of a constraint violation, the time will not be converted. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC struct tm * localtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result ); + +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_TIME_H +#include _PDCLIB_EXTEND_TIME_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/include/unistd.h b/rocklibc/include/unistd.h new file mode 100644 index 0000000..35ce2bb --- /dev/null +++ b/rocklibc/include/unistd.h @@ -0,0 +1,28 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +/* Standard file descriptors used by streams */ +#define STDIN_FILENO 0 /* Standard input */ +#define STDOUT_FILENO 1 /* Standard output */ +#define STDERR_FILENO 2 /* Standard error output */ + +/* Seek constants for lseek() / _PDCLIB_lseek() */ +#ifndef SEEK_SET +#define SEEK_SET 0 /* Seek from beginning of file */ +#define SEEK_CUR 1 /* Seek from current position */ +#define SEEK_END 2 /* Seek from end of file */ +#endif + +/* Null pointer declaration constant */ +#ifndef NULL +#define NULL ((void *)0) +#endif + +int open(const char *pathname, int flags, ...); +int read(int fd, void *buf, size_t count); +int close(int fd); + + +#endif /* _UNISTD_H */ \ No newline at end of file diff --git a/rocklibc/include/wctype.h b/rocklibc/include/wctype.h new file mode 100644 index 0000000..3776b7a --- /dev/null +++ b/rocklibc/include/wctype.h @@ -0,0 +1,152 @@ +/* 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. +*/ + +#ifndef _PDCLIB_WCTYPE_H +#define _PDCLIB_WCTYPE_H _PDCLIB_WCTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +typedef _PDCLIB_wint_t wint_t; +typedef int wctrans_t; +typedef int 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 ) */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int iswblank( wint_t wc ); + +/* Returns true if the wide character is a control character. */ +_PDCLIB_PUBLIC int iswcntrl( wint_t wc ); + +/* Returns true if the wide character is a decimal digit. Locale- + independent. */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int iswlower( wint_t wc ); + +/* Returns true for every printing wide character. */ +_PDCLIB_PUBLIC int iswprint( wint_t wc ); + +/* Returns true for a locale-specific set of punctuation characters that + are neither whitespace nor alphanumeric. +*/ +_PDCLIB_PUBLIC int iswpunct( wint_t wc ); + +/* Returns true for a locale-specific set of whitespace characters that + are neither alphanumeric, graphic, or punctuation. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int iswupper( wint_t wc ); + +/* Returns true if the wide character is a hexadecimal digit. Locale- + independent. */ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC wctrans_t wctrans( const char * property ); + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_WCTYPE_H +#include _PDCLIB_EXTEND_WCTYPE_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rocklibc/makefile b/rocklibc/makefile new file mode 100644 index 0000000..efc4608 --- /dev/null +++ b/rocklibc/makefile @@ -0,0 +1,20 @@ +CC = i686-elf-gcc +AR = i686-elf-ar +CFLAGS = -ffreestanding -O2 -Wall -Wextra -Iinclude -DHAVE_MMAP=0 -DLACKS_SYS_MMAN_H=1 -DUSE_LOCKS=0 -DLACKS_SYS_PARAM_H=1 +TARGET = rlibc.a + +SRCS = $(shell find src -name "*.c") +OBJS = $(SRCS:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) rcs $@ $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) $(TARGET) + +.PHONY: all clean \ No newline at end of file diff --git a/rocklibc/src/_PDCLIB/Readme.txt b/rocklibc/src/_PDCLIB/Readme.txt new file mode 100644 index 0000000..13ad05c --- /dev/null +++ b/rocklibc/src/_PDCLIB/Readme.txt @@ -0,0 +1,10 @@ +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/rocklibc/src/_PDCLIB/_PDCLIB_Exit.c b/rocklibc/src/_PDCLIB/_PDCLIB_Exit.c new file mode 100644 index 0000000..b5c5fd2 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_Exit.c @@ -0,0 +1,48 @@ +/* _PDCLIB_Exit( 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_Exit() fit for use with POSIX + kernels. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern _PDCLIB_Noreturn void _exit( int status ) _PDCLIB_NORETURN; + +#ifdef __cplusplus +} +#endif + +void _PDCLIB_Exit( int status ) +{ + _exit( status ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + int UNEXPECTED_RETURN = 0; + _PDCLIB_Exit( 0 ); + TESTCASE( UNEXPECTED_RETURN ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_atomax.c b/rocklibc/src/_PDCLIB/_PDCLIB_atomax.c new file mode 100644 index 0000000..c8fe665 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_atomax.c @@ -0,0 +1,59 @@ +/* _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 + +#ifndef REGTEST + +_PDCLIB_intmax_t _PDCLIB_atomax( const char * s ) +{ + _PDCLIB_intmax_t rc = 0; + char sign = '+'; + const char * x; + + /* TODO: In other than "C" locale, additional patterns may be defined */ + while ( isspace( (unsigned char)*s ) ) + { + ++s; + } + + if ( *s == '+' ) + { + ++s; + } + else if ( *s == '-' ) + { + sign = *( s++ ); + } + + /* TODO: Earlier version was missing tolower() but was not caught by tests */ + while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)*( s++ ) ), 10 ) ) != NULL ) + { + rc = rc * 10 + ( x - _PDCLIB_digits ); + } + + return ( sign == '+' ) ? rc : -rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + /* basic functionality */ + TESTCASE( _PDCLIB_atomax( "123" ) == 123 ); + /* testing skipping of leading whitespace and trailing garbage */ + TESTCASE( _PDCLIB_atomax( " \n\v\t\f123xyz" ) == 123 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_add.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_add.c new file mode 100644 index 0000000..caf029e --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_add.c @@ -0,0 +1,83 @@ +/* _PDCLIB_bigint_add( bigint_t *, bigint_t const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +void _PDCLIB_bigint_add( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ) +{ + unsigned i = 0; + _PDCLIB_bigint_arith_t arith = 0; + + for ( i = bigint->size; i < other->size; ++i ) + { + bigint->data[i] = 0; + } + + bigint->size = i; + + for ( i = 0; i < bigint->size; ++i ) + { + arith += bigint->data[i] + other->data[i]; + bigint->data[i] = arith & ( ( (_PDCLIB_bigint_arith_t)1 << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 ); + arith >>= _PDCLIB_BIGINT_DIGIT_BITS; + } + + if ( arith > 0 ) + { + bigint->data[i] = arith; + --(bigint->size); + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + _PDCLIB_bigint_t testdata[] = + { + { 1, { 0x0001u } }, + { 2, { (_PDCLIB_bigint_digit_t)( ( (_PDCLIB_bigint_arith_t)1 << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 ), 0x0001u } }, + { 1, { 0x0002u } }, + { 2, { 0x0001u, 0x0002u } }, + { 2, { 0x0000u, 0x0002u } } + }; + + /* 1 + 1 */ + _PDCLIB_bigint_from_digit( &bigint, 1 ); + _PDCLIB_bigint_add( &bigint, &bigint ); + _PDCLIB_bigint_cmp( &bigint, &testdata[2] ); + + /* 1 + 0x0001 0xFFFF -- carry */ + _PDCLIB_bigint_add( &bigint, &testdata[1] ); + _PDCLIB_bigint_cmp( &bigint, &testdata[3] ); + + /* 0x0001 0xFFFF + 1 -- carry */ + _PDCLIB_bigint_from_bigint( &bigint, &testdata[1] ); + _PDCLIB_bigint_add( &bigint, &testdata[0] ); + _PDCLIB_bigint_cmp( &bigint, &testdata[4] ); + + /* 0 + 0 */ + _PDCLIB_bigint_from_digit( &bigint, 0 ); + _PDCLIB_bigint_add( &bigint, &bigint ); + TESTCASE( bigint.size == 0 ); + + /* 0 + 1 */ + _PDCLIB_bigint_add( &bigint, &testdata[0] ); + _PDCLIB_bigint_cmp( &bigint, &testdata[0] ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_cmp.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_cmp.c new file mode 100644 index 0000000..664cdc3 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_cmp.c @@ -0,0 +1,74 @@ +/* _PDCLIB_bigint_cmp( bigint_t const *, bigint_t const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +int _PDCLIB_bigint_cmp( _PDCLIB_bigint_t const * lhs, _PDCLIB_bigint_t const * rhs ) +{ + _PDCLIB_size_t i = lhs->size; + + if ( i != rhs->size ) + { + return i > rhs->size ? 1 : -1; + } + + while ( i-- > 0 ) + { + if ( lhs->data[i] != rhs->data[i] ) + { + return lhs->data[i] > rhs->data[i] ? 1 : -1; + } + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t lhs, rhs; + _PDCLIB_bigint_t testdata[] = + { + { 2, { 0, 0x0001u } }, + { 1, { 1 } } + }; + + _PDCLIB_bigint_from_digit( &lhs, 0 ); + _PDCLIB_bigint_from_digit( &rhs, 0 ); + + TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) == 0 ); + + _PDCLIB_bigint_add( &lhs, &testdata[1] ); + TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) > 0 ); + + _PDCLIB_bigint_add( &rhs, &testdata[1] ); + TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) == 0 ); + + _PDCLIB_bigint_add( &rhs, &testdata[1] ); + TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) < 0 ); + + _PDCLIB_bigint_from_bigint( &lhs, &testdata[0] ); + TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) > 0 ); + + _PDCLIB_bigint_from_bigint( &rhs, &testdata[0] ); + TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) == 0 ); + + _PDCLIB_bigint_add( &rhs, &testdata[1] ); + TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) < 0 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_digit_log2.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_digit_log2.c new file mode 100644 index 0000000..06946d0 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_digit_log2.c @@ -0,0 +1,83 @@ +/* _PDCLIB_bigint_digit_log2( bigint_t const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +int _PDCLIB_bigint_digit_log2( _PDCLIB_bigint_digit_t digit ) +{ + unsigned char log2_lookup[] = + { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + }; + _PDCLIB_bigint_digit_t t; + +#if _PDCLIB_BIGINT_DIGIT_BITS > 16 + if ( ( t = ( digit >> 24 ) ) ) + { + return log2_lookup[ t ] + 24; + } + else if ( ( t = ( digit >> 16 ) ) ) + { + return log2_lookup[ t ] + 16; + } + else +#endif + if ( ( t = ( digit >> 8 ) ) ) + { + return log2_lookup[ t ] + 8; + } + else if ( digit > 0 ) + { + return log2_lookup[ digit ]; + } + else + { + return -1; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ +#ifndef REGTEST + unsigned i; + + for ( i = 1; i < (1 << _PDCLIB_BIGINT_DIGIT_BITS); ++i ) + { + //TESTCASE( _PDCLIB_bigint_digit_log2( i ) == (int)log2( i ) ); + } +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_div.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_div.c new file mode 100644 index 0000000..56a5a0b --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_div.c @@ -0,0 +1,135 @@ +/* _PDCLIB_bigint_div( bigint_t *, bigint_t const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +unsigned _PDCLIB_bigint_div( _PDCLIB_bigint_t * dividend, _PDCLIB_bigint_t const * divisor ) +{ + _PDCLIB_bigint_digit_t quotient; + _PDCLIB_size_t s = dividend->size; + _PDCLIB_size_t i; + + assert( divisor->size > 0 ); + assert( s <= divisor->size ); + assert( divisor->data[ divisor->size - 1 ] < _PDCLIB_BIGINT_DIGIT_MAX ); + + if ( s < divisor->size || dividend->data[ s - 1 ] < divisor->data[ s - 1 ]) + { + return 0; + } + + /* With dividend truncated, and divisor + 1, + this quotient might be one short of correct. + */ + quotient = dividend->data[ s - 1 ] / ( divisor->data[ s - 1 ] + 1 ); + + if ( quotient > 0 ) + { + /* dividend = dividend - (divisor * quotient) */ + _PDCLIB_bigint_arith_t t = 0; + _PDCLIB_bigint_arith_t d = 0; + + for ( i = 0; i < s; ++i ) + { + t += (_PDCLIB_bigint_arith_t)divisor->data[i] * quotient; + d = (_PDCLIB_bigint_arith_t)dividend->data[i] - ( t & _PDCLIB_BIGINT_DIGIT_MAX ) - d; + + dividend->data[i] = d & _PDCLIB_BIGINT_DIGIT_MAX; + t >>= _PDCLIB_BIGINT_DIGIT_BITS; + d >>= _PDCLIB_BIGINT_DIGIT_BITS; + d &= 1; + } + } + + /* dividend might have leading zero digits here, + but that does not matter for the compare or + the subsequent substraction. + */ + if ( _PDCLIB_bigint_cmp( dividend, divisor ) >= 0 ) + { + /* quotient was too small, substract divisor once more. */ + _PDCLIB_bigint_arith_t d = 0; + ++quotient; + + for ( i = 0; i < s; ++i ) + { + d = (_PDCLIB_bigint_arith_t)dividend->data[i] - divisor->data[i] - d; + dividend->data[i] = d & _PDCLIB_BIGINT_DIGIT_MAX; + d >>= _PDCLIB_BIGINT_DIGIT_BITS; + d &= 1; + } + } + + /* size down dividend if it has leading zero digits. */ + while ( dividend->size > 0 && dividend->data[ dividend->size - 1 ] == 0 ) + { + --dividend->size; + } + + return quotient; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t dividend; + _PDCLIB_bigint_t divisor; + _PDCLIB_bigint_t testdata[] = + { + { 1, { 0x1234 } }, + { 2, { 0x2345, 0x0001 } }, + { 1, { 0x4000 } }, + { 1, { 0x3FFF } }, + { 1, { 0x0001 } }, + { 1, { _PDCLIB_BIGINT_DIGIT_MAX } }, + { 1, { 0xFFF9 } }, + { 1, { 0x1C71 } } + }; + + /* dividend < divisor */ + _PDCLIB_bigint_from_bigint( ÷nd, &testdata[0] ); + _PDCLIB_bigint_from_bigint( &divisor, &testdata[1] ); + TESTCASE( _PDCLIB_bigint_div( ÷nd, &divisor ) == 0 ); + TESTCASE( _PDCLIB_bigint_cmp( ÷nd, &testdata[0] ) == 0 ); + + _PDCLIB_bigint_from_bigint( ÷nd, &testdata[3] ); + _PDCLIB_bigint_from_bigint( &divisor, &testdata[2] ); + TESTCASE( _PDCLIB_bigint_div( ÷nd, &divisor ) == 0 ); + TESTCASE( _PDCLIB_bigint_cmp( ÷nd, &testdata[3] ) == 0 ); + + /* dividend = divisor + 1 */ + _PDCLIB_bigint_from_bigint( ÷nd, &testdata[2] ); + _PDCLIB_bigint_from_bigint( &divisor, &testdata[3] ); + TESTCASE( _PDCLIB_bigint_div( ÷nd, &divisor ) == 1 ); + TESTCASE( _PDCLIB_bigint_cmp( ÷nd, &testdata[4] ) == 0 ); + + /* dividend = divisor * 9 */ + _PDCLIB_bigint_from_bigint( ÷nd, &testdata[6] ); + _PDCLIB_bigint_from_bigint( &divisor, &testdata[7] ); + TESTCASE( _PDCLIB_bigint_div( ÷nd, &divisor ) == 9 ); + TESTCASE( dividend.size == 0 ); + + /* dividend = divisor * 9 + rem */ + _PDCLIB_bigint_from_bigint( ÷nd, &testdata[5] ); + _PDCLIB_bigint_from_digit( &divisor, testdata[5].data[0] / 9 ); + TESTCASE( _PDCLIB_bigint_div( ÷nd, &divisor ) == 9 ); + TESTCASE( dividend.data[0] == ( testdata[5].data[0] % 9 ) ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_bigint.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_bigint.c new file mode 100644 index 0000000..2046e8c --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_bigint.c @@ -0,0 +1,54 @@ +/* _PDCLIB_bigint_from_bigint( bigint_t *, bigint_t const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +void _PDCLIB_bigint_from_bigint( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ) +{ + _PDCLIB_size_t i; + + for ( i = 0; i < other->size; ++i ) + { + bigint->data[i] = other->data[i]; + } + + bigint->size = other->size; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + _PDCLIB_bigint_t testdata[] = + { + /* Only 16bit, works with 32bit digits as well. */ + { 0, { 0u } }, + { 1, { 0xFFFFu } }, + { 2, { 0xAAAAu, 0xFFFFu } } + }; + + _PDCLIB_bigint_from_bigint( &bigint, &testdata[0] ); + TESTCASE( bigint.size == 0 ); + + _PDCLIB_bigint_from_bigint( &bigint, &testdata[1] ); + _PDCLIB_bigint_cmp( &bigint, &testdata[1] ); + + _PDCLIB_bigint_from_bigint( &bigint, &testdata[2] ); + _PDCLIB_bigint_cmp( &bigint, &testdata[2] ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_digit.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_digit.c new file mode 100644 index 0000000..5714aea --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_digit.c @@ -0,0 +1,43 @@ +/* _PDCLIB_bigint_from_digit( bigint_t *, digit_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +void _PDCLIB_bigint_from_digit( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_digit_t digit ) +{ + bigint->size = ( digit > 0 ); + bigint->data[0] = digit; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + + _PDCLIB_bigint_from_digit( &bigint, 0 ); + TESTCASE( bigint.size == 0 ); + + _PDCLIB_bigint_from_digit( &bigint, 1 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 1 ); + + _PDCLIB_bigint_from_digit( &bigint, _PDCLIB_BIGINT_DIGIT_MAX ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == _PDCLIB_BIGINT_DIGIT_MAX ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow10.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow10.c new file mode 100644 index 0000000..49b7a25 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow10.c @@ -0,0 +1,131 @@ +/* _PDCLIB_bigint_from_pow10( bigint_t *, unsigned ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +void _PDCLIB_bigint_from_pow10( _PDCLIB_bigint_t * bigint, unsigned pow ) +{ + _PDCLIB_bigint_t powers_of_10[] = + { + { 1, { 0x0001u } }, + { 1, { 0x000au } }, + { 1, { 0x0064u } }, + { 1, { 0x03e8u } }, + { 1, { 0x2710u } }, + { 2, { 0x86a0u, 0x0001u } }, + { 2, { 0x4240u, 0x000fu } }, + { 2, { 0x9680u, 0x0098u } }, + { 2, { 0xe100u, 0x05f5u } }, + { 4, { 0x0000u, 0x6fc1u, 0x86f2u, 0x0023u } }, + { 7, { 0x0000u, 0x0000u, 0xef81u, 0x85acu, + 0x415bu, 0x2d6du, 0x04eeu } }, + { 14, { 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x1f01u, 0xbf6au, 0xed64u, 0x6e38u, + 0x97edu, 0xdaa7u, 0xf9f4u, 0xe93fu, + 0x4f03u, 0x0018u } }, + { 27, { 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x3e01u, 0x2e95u, 0x9909u, 0x03dfu, + 0x38fdu, 0x0f15u, 0xe42fu, 0x2374u, + 0xf5ecu, 0xd3cfu, 0xdc08u, 0xc404u, + 0xb0dau, 0xbccdu, 0x7f19u, 0xa633u, + 0x2603u, 0xe91fu, 0x024eu } }, + { 54, { 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x7c01u, 0x982eu, 0x875bu, 0xbed3u, + 0x9f72u, 0xd8d9u, 0x2f87u, 0x1215u, + 0x50c6u, 0x6bdeu, 0x6e70u, 0xcf4au, + 0xd80fu, 0xd595u, 0x716eu, 0x26b2u, + 0x66b0u, 0xadc6u, 0x3624u, 0x1d15u, + 0xd35au, 0x3c42u, 0x540eu, 0x63ffu, + 0x73c0u, 0xcc55u, 0xef17u, 0x65f9u, + 0x28f2u, 0x55bcu, 0xc7f7u, 0x80dcu, + 0xeddcu, 0xf46eu, 0xefceu, 0x5fdcu, + 0x53f7u, 0x0005u } } + }; + + _PDCLIB_size_t index = 8; + + _PDCLIB_bigint_from_bigint( bigint, &powers_of_10[ pow & 7 ] ); + pow >>= 3; + + while ( pow > 0 ) + { + if ( pow & 1 ) + { + _PDCLIB_bigint_mul( bigint, &powers_of_10[ index ] ); + } + + pow >>= 1; + ++index; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + + _PDCLIB_bigint_from_pow10( &bigint, 0 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 1 ); + + _PDCLIB_bigint_from_pow10( &bigint, 1 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 10 ); + + _PDCLIB_bigint_from_pow10( &bigint, 2 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 100 ); + + _PDCLIB_bigint_from_pow10( &bigint, 3 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 1000 ); + + _PDCLIB_bigint_from_pow10( &bigint, 4 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 10000 ); + + _PDCLIB_bigint_from_pow10( &bigint, 5 ); + TESTCASE( bigint.size == 2 ); + TESTCASE( bigint.data[1] == 1 ); + TESTCASE( bigint.data[0] == 34464 ); + + _PDCLIB_bigint_from_pow10( &bigint, 6 ); + TESTCASE( bigint.size == 2 ); + TESTCASE( bigint.data[1] == 15 ); + TESTCASE( bigint.data[0] == 16960 ); + + _PDCLIB_bigint_from_pow10( &bigint, 7 ); + TESTCASE( bigint.size == 2 ); + TESTCASE( bigint.data[1] == 152 ); + TESTCASE( bigint.data[0] == 38528 ); + + _PDCLIB_bigint_from_pow10( &bigint, 8 ); + TESTCASE( bigint.size == 2 ); + TESTCASE( bigint.data[1] == 1525 ); + TESTCASE( bigint.data[0] == 57600 ); + + _PDCLIB_bigint_from_pow10( &bigint, 9 ); + TESTCASE( bigint.size == 2 ); + TESTCASE( bigint.data[1] == 15258 ); + TESTCASE( bigint.data[0] == 51712 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow2.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow2.c new file mode 100644 index 0000000..fbb6cad --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_from_pow2.c @@ -0,0 +1,54 @@ +/* _PDCLIB_bigint_from_pow2( bigint_t *, unsigned ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +void _PDCLIB_bigint_from_pow2( _PDCLIB_bigint_t * bigint, unsigned pow ) +{ + ldiv_t dv = ldiv( pow, _PDCLIB_BIGINT_DIGIT_BITS ); + long i; + + for ( i = 0; i < dv.quot; ++i ) + { + bigint->data[i] = 0; + } + + bigint->data[i] = 1u << dv.rem; + bigint->size = i + 1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + + _PDCLIB_bigint_from_pow2( &bigint, 0 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 1 ); + + _PDCLIB_bigint_from_pow2( &bigint, 1 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 2 ); + + _PDCLIB_bigint_from_pow2( &bigint, 2 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 4 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_log2.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_log2.c new file mode 100644 index 0000000..ed1cf51 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_log2.c @@ -0,0 +1,64 @@ +/* _PDCLIB_bigint_log2( bigint_t const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +int _PDCLIB_bigint_log2( _PDCLIB_bigint_t const * bigint ) +{ + _PDCLIB_size_t s = bigint->size; + + if ( s == 0 ) + { + return -1; + } + + --s; + + return _PDCLIB_bigint_digit_log2( bigint->data[ s ] ) + s * _PDCLIB_BIGINT_DIGIT_BITS; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + _PDCLIB_bigint_t one; + _PDCLIB_bigint_from_digit( &bigint, 0 ); + _PDCLIB_bigint_from_digit( &one, 1 ); + + TESTCASE( _PDCLIB_bigint_log2( &bigint ) == -1 ); + TESTCASE( _PDCLIB_bigint_log2( &one ) == 0 ); + + _PDCLIB_bigint_mul10( &one ); + TESTCASE( _PDCLIB_bigint_log2( &one ) == 3 ); + + _PDCLIB_bigint_mul10( &one ); + TESTCASE( _PDCLIB_bigint_log2( &one ) == 6 ); + + _PDCLIB_bigint_mul10( &one ); + TESTCASE( _PDCLIB_bigint_log2( &one ) == 9 ); + + _PDCLIB_bigint_mul10( &one ); + TESTCASE( _PDCLIB_bigint_log2( &one ) == 13 ); + + _PDCLIB_bigint_mul10( &one ); + TESTCASE( _PDCLIB_bigint_log2( &one ) == 16 ); + + _PDCLIB_bigint_mul10( &one ); + TESTCASE( _PDCLIB_bigint_log2( &one ) == 19 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul.c new file mode 100644 index 0000000..812cdef --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul.c @@ -0,0 +1,121 @@ +/* _PDCLIB_bigint_mul( bigint_t *, bigint_t const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +void _PDCLIB_bigint_mul( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ) +{ + _PDCLIB_size_t s = other->size; + _PDCLIB_size_t b = bigint->size; + + if ( s == 0 || b == 0 ) + { + _PDCLIB_bigint_from_digit( bigint, 0 ); + return; + } + + { + _PDCLIB_bigint_t result = { s + b, { 0 } }; + _PDCLIB_bigint_t const * small; + _PDCLIB_bigint_t const * big; + + if ( s <= b ) + { + small = other; + big = bigint; + } + else + { + small = bigint; + big = other; + } + + for ( s = 0; s < small->size; ++s ) + { + _PDCLIB_bigint_arith_t t = 0; + + for ( b = 0; b < big->size; ++b ) + { + t += result.data[ s + b ] + + (_PDCLIB_bigint_arith_t)small->data[ s ] + * (_PDCLIB_bigint_arith_t)big->data[ b ]; + result.data[ s + b ] = t & ( ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 ); + t >>= _PDCLIB_BIGINT_DIGIT_BITS; + } + + result.data[ s + b ] = t & ( ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 ); + } + + while ( result.data[ result.size - 1 ] == 0 ) + { + --result.size; + } + + _PDCLIB_bigint_from_bigint( bigint, &result ); + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + _PDCLIB_bigint_t testdata[] = + { + { 1, { 0x0001u } }, + { 1, { 0x0002u } }, + { 1, { ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 1 } }, + { 2, { ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 1, 1u } } + }; + + _PDCLIB_bigint_from_bigint( &bigint, &testdata[0] ); + _PDCLIB_bigint_mul( &bigint, &testdata[0] ); + + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 1u ); + + _PDCLIB_bigint_mul( &bigint, &testdata[1] ); + + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 2u ); + + _PDCLIB_bigint_mul( &bigint, &testdata[2] ); + + TESTCASE( bigint.size == 2 ); + TESTCASE( bigint.data[0] == ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 2 ); + TESTCASE( bigint.data[1] == 1u ); + + _PDCLIB_bigint_mul( &bigint, &testdata[1] ); + + TESTCASE( bigint.size == 2 ); + TESTCASE( bigint.data[0] == ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 4 ); + TESTCASE( bigint.data[1] == 3u ); + + _PDCLIB_bigint_from_bigint( &bigint, &testdata[3] ); + _PDCLIB_bigint_mul( &bigint, &bigint ); + + TESTCASE( bigint.data[0] == 1 ); + TESTCASE( bigint.data[1] == ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 4 ); + +#if _PDCLIB_BIGINT_DIGIT_BITS == 16 + TESTCASE( bigint.size == 3 ); + TESTCASE( bigint.data[2] == 3 ); +#else + TESTCASE( bigint.size == 2 ); +#endif +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul10.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul10.c new file mode 100644 index 0000000..76767fc --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul10.c @@ -0,0 +1,58 @@ +/* _PDCLIB_bigint_mul10( bigint_t * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +void _PDCLIB_bigint_mul10( _PDCLIB_bigint_t * bigint ) +{ + _PDCLIB_bigint_arith_t t = 0; + _PDCLIB_size_t i; + + for ( i = 0; i < bigint->size; ++i ) + { + t = (_PDCLIB_bigint_arith_t)bigint->data[ i ] * 10 + t; + bigint->data[ i ] = t & _PDCLIB_BIGINT_DIGIT_MAX; + t >>= _PDCLIB_BIGINT_DIGIT_BITS; + } + + if ( t > 0 ) + { + bigint->data[ bigint->size++ ] = t; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + _PDCLIB_bigint_t testdata[] = + { + { 2, { 0x8080u, 0x0101u } }, + { 2, { 0x0500u, 0x0a0fu } }, + { 1, { 0x000au } } + }; + + _PDCLIB_bigint_from_digit( &bigint, 1 ); + _PDCLIB_bigint_mul10( &bigint ); + TESTCASE( _PDCLIB_bigint_cmp( &bigint, &testdata[2] ) == 0 ); + + _PDCLIB_bigint_from_bigint( &bigint, &testdata[0] ); + _PDCLIB_bigint_mul10( &bigint ); + TESTCASE( _PDCLIB_bigint_cmp( &bigint, &testdata[1] ) == 0 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul_pow10.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul_pow10.c new file mode 100644 index 0000000..2924fe2 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_mul_pow10.c @@ -0,0 +1,30 @@ +/* _PDCLIB_bigint_mul_pow10( bigint_t *, int pow10 ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +void _PDCLIB_bigint_mul_pow10( _PDCLIB_bigint_t * bigint, int pow10 ) +{ + _PDCLIB_bigint_t multiplier; + _PDCLIB_bigint_from_pow10( &multiplier, pow10 ); + _PDCLIB_bigint_mul( bigint, &multiplier ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_bigint_shl.c b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_shl.c new file mode 100644 index 0000000..a04e752 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_bigint_shl.c @@ -0,0 +1,83 @@ +/* _PDCLIB_bigint_shl( bigint_t *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +void _PDCLIB_bigint_shl( _PDCLIB_bigint_t * bigint, _PDCLIB_size_t bits ) +{ + ldiv_t dv = ldiv( bits, _PDCLIB_BIGINT_DIGIT_BITS ); + _PDCLIB_bigint_arith_t t = 0; + size_t i; + + if ( dv.quot > 0 ) + { + i = bigint->size; + + /* shifting whole digits */ + while ( i-- > 0 ) + { + bigint->data[ i + dv.quot ] = bigint->data[ i ]; + } + + bigint->size += dv.quot; + + /* zero out shifted low digits */ + while ( (long)i < dv.quot ) + { + bigint->data[ i++ ] = 0; + } + } + + for ( i = dv.quot; i < bigint->size; ++i ) + { + t = ( (_PDCLIB_bigint_arith_t)bigint->data[ i ] << dv.rem ) + t; + bigint->data[ i ] = t & _PDCLIB_BIGINT_DIGIT_MAX; + t >>= _PDCLIB_BIGINT_DIGIT_BITS; + } + + if ( t > 0 ) + { + bigint->data[ bigint->size++ ] = t; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_bigint_t bigint; + _PDCLIB_bigint_t testdata[] = + { + { 2, { 0x8080u, 0x0101u } }, + { 3, { 0x0000u, 0x0100u, 0x0203u } } + }; + + _PDCLIB_bigint_from_digit( &bigint, 1 ); + _PDCLIB_bigint_shl( &bigint, 2 ); + TESTCASE( bigint.size == 1 ); + TESTCASE( bigint.data[0] == 4 ); + + _PDCLIB_bigint_from_bigint( &bigint, &testdata[0] ); + _PDCLIB_bigint_shl( &bigint, _PDCLIB_BIGINT_DIGIT_BITS + 1 ); + TESTCASE( bigint.size == 3 ); + TESTCASE( bigint.data[0] == 0 ); + TESTCASE( bigint.data[1] == 0x0100 ); + TESTCASE( bigint.data[2] == 0x0203 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_changemode.c b/rocklibc/src/_PDCLIB/_PDCLIB_changemode.c new file mode 100644 index 0000000..0a0cf58 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_changemode.c @@ -0,0 +1,73 @@ +/* _PDCLIB_changemode( FILE * stream, int mode ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +/* This is a utility function used by freopen, to allow for a rather + specific bit of trickery. + ISO/IEC 9899:2011 (i.e., the ISO C standard) is ambiguous in the case + of the filename argument being NULL. It states that the mode of the + open stream could be _changed_ in implementation-defined circumstances. + While it goes on to state that freopen will "first attempt to close any + file that is associated with the specified stream", it is not quite + clear if the "implementation-defined circumstances" mentioned earlier + would include changing the mode without actually closing the file. + IEEE Std 1003.1, 2004 Edition (POSIX) on the other hand is less + ambiguous, as it states that "the file descriptor associated with the + stream need not be closed if the call to freopen() succeeds" for the + same case (filename being NULL). + This function gets called by PDCLib's freopen() in just that case, + allowing you to perform whatever mode changes YOUR implementation + decides to support. Return zero if the change requested is not + supported and freopen() should attempt the close-and-open-again way. + Return INT_MIN if the change request is not supported and freopen() + should fail. Return any other value if the requested mode change was + supported and successful. +*/ + +/* This is a dummy implementation of _PDCLIB_open() not supporting any + mode changes. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#include +#include + +int _PDCLIB_changemode( struct _PDCLIB_file_t * stream, unsigned int mode ) +{ + if ( mode == 0 ) + { + return INT_MIN; + } + + /* Attempt mode change without closing the stream */ + + if ( stream->filename == NULL ) + { + /* Standard stream, no filename for reopen */ + return INT_MIN; + } + else + { + /* Stream with file associated, attempt reopen */ + return 0; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* No test drivers. */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_close.c b/rocklibc/src/_PDCLIB/_PDCLIB_close.c new file mode 100644 index 0000000..55439d6 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_close.c @@ -0,0 +1,44 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int close( int fd ); + +#ifdef __cplusplus +} +#endif + +int _PDCLIB_close( int fd ) +{ + return close( fd ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* No testdriver; tested in driver for _PDCLIB_open(). */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_closeall.c b/rocklibc/src/_PDCLIB/_PDCLIB_closeall.c new file mode 100644 index 0000000..eb42cda --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_closeall.c @@ -0,0 +1,38 @@ +/* _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 + +#ifndef REGTEST + +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; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* No testdriver */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_digits.c b/rocklibc/src/_PDCLIB/_PDCLIB_digits.c new file mode 100644 index 0000000..c35702a --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_digits.c @@ -0,0 +1,33 @@ +/* _PDCLIB_digits + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +const char _PDCLIB_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +/* For _PDCLIB/print.c only; obsolete with ctype.h */ +const char _PDCLIB_Xdigits[] = "0123456789ABCDEF"; + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ +#ifndef REGTEST + TESTCASE( strcmp( _PDCLIB_digits, "0123456789abcdefghijklmnopqrstuvwxyz" ) == 0 ); + TESTCASE( strcmp( _PDCLIB_Xdigits, "0123456789ABCDEF" ) == 0 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_filemode.c b/rocklibc/src/_PDCLIB/_PDCLIB_filemode.c new file mode 100644 index 0000000..c34da1d --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_filemode.c @@ -0,0 +1,114 @@ +/* _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 + +#ifndef REGTEST + +/* 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; + + if ( mode == NULL ) + { + return 0; + } + + 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 ) + { + /* Duplicates are invalid */ + return 0; + } + + rc |= _PDCLIB_FRW; + break; + + case 'b': + if ( rc & _PDCLIB_FBIN ) + { + /* Duplicates are invalid */ + return 0; + } + + 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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + TESTCASE( _PDCLIB_filemode( "r" ) == _PDCLIB_FREAD ); + TESTCASE( _PDCLIB_filemode( "w" ) == _PDCLIB_FWRITE ); + TESTCASE( _PDCLIB_filemode( "a" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE ) ); + TESTCASE( _PDCLIB_filemode( "r+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW ) ); + TESTCASE( _PDCLIB_filemode( "w+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW ) ); + TESTCASE( _PDCLIB_filemode( "a+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FRW ) ); + TESTCASE( _PDCLIB_filemode( "rb" ) == ( _PDCLIB_FREAD | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "wb" ) == ( _PDCLIB_FWRITE | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "ab" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "r+b" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "w+b" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "a+b" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "rb+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "wb+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "ab+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) ); + TESTCASE( _PDCLIB_filemode( "x" ) == 0 ); + TESTCASE( _PDCLIB_filemode( "r++" ) == 0 ); + TESTCASE( _PDCLIB_filemode( "wbb" ) == 0 ); + TESTCASE( _PDCLIB_filemode( "a+bx" ) == 0 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_fillbuffer.c b/rocklibc/src/_PDCLIB/_PDCLIB_fillbuffer.c new file mode 100644 index 0000000..f96c7b7 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_fillbuffer.c @@ -0,0 +1,77 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#include "pdclib/_PDCLIB_platform_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef long ssize_t; +extern ssize_t read( int fd, void * buf, size_t count ); + +#ifdef __cplusplus +} +#endif + +int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) +{ + /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */ + ssize_t rc = read( stream->handle, stream->buffer, stream->bufsize ); + + if ( rc > 0 ) + { + /* Reading successful. */ + if ( !( stream->status & _PDCLIB_FBIN ) ) + { + /* TODO: Text stream conversion here */ + } + + stream->pos.offset += rc; + stream->bufend = rc; + stream->bufidx = 0; + return 0; + } + + if ( rc < 0 ) + { + /* The 1:1 mapping done in _PDCLIB_config.h ensures + this works. + */ + *_PDCLIB_errno_func() = errno; + /* Flag the stream */ + stream->status |= _PDCLIB_ERRORFLAG; + return EOF; + } + + /* End-of-File */ + stream->status |= _PDCLIB_EOFFLAG; + return EOF; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_flushbuffer.c b/rocklibc/src/_PDCLIB/_PDCLIB_flushbuffer.c new file mode 100644 index 0000000..764c38e --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_flushbuffer.c @@ -0,0 +1,103 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#include "pdclib/_PDCLIB_platform_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef long ssize_t; +extern ssize_t write( int fd, const void * buf, size_t count ); + +#ifdef __cplusplus +} +#endif + +/* The number of attempts of output buffer flushing before giving up. */ +#define _PDCLIB_IO_RETRIES 1 + +/* What the system should do after an I/O operation did not succeed, before */ +/* trying again. (Empty by default.) */ +#define _PDCLIB_IO_RETRY_OP( stream ) + +int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ) +{ + /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */ + _PDCLIB_size_t written = 0; + int rc; + unsigned int retries; + + if ( !( stream->status & _PDCLIB_FBIN ) ) + { + /* TODO: Text stream conversion here */ + } + + /* Keep trying to write data until everything is written, an error + occurs, or the configured number of retries is exceeded. + */ + for ( retries = _PDCLIB_IO_RETRIES; retries > 0; --retries ) + { + rc = ( int )write( stream->handle, stream->buffer + written, stream->bufidx - written ); + + if ( rc < 0 ) + { + /* The 1:1 mapping done in _PDCLIB_config.h ensures + this works. + */ + *_PDCLIB_errno_func() = errno; + /* Flag the stream */ + stream->status |= _PDCLIB_ERRORFLAG; + /* Move unwritten remains to begin of buffer. */ + stream->bufidx -= written; + memmove( stream->buffer, stream->buffer + written, stream->bufidx ); + return EOF; + } + + written += ( _PDCLIB_size_t )rc; + stream->pos.offset += rc; + + if ( written == stream->bufidx ) + { + /* Buffer written completely. */ + stream->bufidx = 0; + return 0; + } + } + + /* Number of retries exceeded. */ + *_PDCLIB_errno_func() = _PDCLIB_EAGAIN; + stream->status |= _PDCLIB_ERRORFLAG; + /* Move unwritten remains to begin of buffer. */ + stream->bufidx -= written; + memmove( stream->buffer, stream->buffer + written, stream->bufidx ); + return EOF; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_dbl.c b/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_dbl.c new file mode 100644 index 0000000..1a1e6a4 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_dbl.c @@ -0,0 +1,106 @@ +/* _PDCLIB_fp_from_dbl( _PDCLIB_fp_t *, double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include +#include + +void _PDCLIB_fp_from_dbl( _PDCLIB_fp_t * fp, double d ) +{ + memcpy( fp->mantissa.data, &d, sizeof( double ) ); + + fp->sign = _PDCLIB_DBL_SIGN( fp->mantissa.data ); + fp->exponent = _PDCLIB_DBL_EXP( fp->mantissa.data ); + fp->mantissa.size = _PDCLIB_DBL_SIZE( fp->mantissa.data ); + + switch ( fp->exponent ) + { + case 0: + fp->state = _PDCLIB_FP_SUBNORMAL; + fp->exponent = 1 - ( _PDCLIB_DBL_MAX_EXP - 1 ); + fp->scale = _PDCLIB_DBL_MANT_DIG - 1; + break; + case ( _PDCLIB_DBL_MAX_EXP - 1 ) + _PDCLIB_DBL_MAX_EXP: + fp->state = _PDCLIB_FP_NAN; + break; + default: + { + div_t dv = div( _PDCLIB_DBL_MANT_DIG - 1, _PDCLIB_BIGINT_DIGIT_BITS ); + fp->state = _PDCLIB_FP_NORMAL; + + if ( dv.rem == 0 ) + { + fp->mantissa.data[ fp->mantissa.size++ ] = 1u; + } + else + { + fp->mantissa.data[ dv.quot ] |= ( 1u << dv.rem ); + } + + fp->exponent -= ( _PDCLIB_DBL_MAX_EXP - 1 ); + fp->scale = _PDCLIB_DBL_MANT_DIG - 1; + break; + } + } + + while ( fp->mantissa.size > 0 && fp->mantissa.data[ fp->mantissa.size - 1 ] == 0 ) + { + --fp->mantissa.size; + } + + if ( ( fp->state == _PDCLIB_FP_NAN ) && ( fp->mantissa.size == 0 ) ) + { + fp->state = _PDCLIB_FP_INF; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_fp_t fp; + _PDCLIB_bigint_t t; + + /* Normal */ + _PDCLIB_fp_from_dbl( &fp, -1.0 ); + _PDCLIB_bigint_from_pow2( &t, _PDCLIB_DBL_MANT_DIG - 1 ); + TESTCASE( fp.state == _PDCLIB_FP_NORMAL ); + TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 ); + TESTCASE( fp.scale == ( _PDCLIB_DBL_MANT_DIG - 1 ) ); + TESTCASE( fp.exponent == 0 ); + + /* Inf */ + _PDCLIB_fp_from_dbl( &fp, 1e500 ); + TESTCASE( fp.state == _PDCLIB_FP_INF ); + TESTCASE( fp.mantissa.size == 0 ); + + /* NaN */ + _PDCLIB_fp_from_dbl( &fp, -0.0/0.0 ); + _PDCLIB_bigint_from_pow2( &t, _PDCLIB_DBL_MANT_DIG - 2 ); + TESTCASE( fp.state == _PDCLIB_FP_NAN ); + TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 ); + + /* Subnormal */ + _PDCLIB_fp_from_dbl( &fp, _PDCLIB_DBL_MIN / 2 ); + _PDCLIB_bigint_from_pow2( &t, _PDCLIB_DBL_MANT_DIG - 2 ); + TESTCASE( fp.state == _PDCLIB_FP_SUBNORMAL ); + TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 ); + TESTCASE( fp.scale == ( _PDCLIB_DBL_MANT_DIG - 1 ) ); + TESTCASE( fp.exponent == (_PDCLIB_int_least16_t)(1 - ( _PDCLIB_DBL_MAX_EXP - 1 ) ) ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_ldbl.c b/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_ldbl.c new file mode 100644 index 0000000..f759523 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_fp_from_ldbl.c @@ -0,0 +1,106 @@ +/* _PDCLIB_fp_from_ldbl( _PDCLIB_fp_t *, long double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include +#include + +void _PDCLIB_fp_from_ldbl( _PDCLIB_fp_t * fp, long double ld ) +{ + memcpy( fp->mantissa.data, &ld, sizeof( long double ) ); + + fp->sign = _PDCLIB_LDBL_SIGN( fp->mantissa.data ); + fp->exponent = _PDCLIB_LDBL_EXP( fp->mantissa.data ); + fp->mantissa.size = _PDCLIB_LDBL_SIZE( fp->mantissa.data ); + + switch ( fp->exponent ) + { + case 0: + fp->state = _PDCLIB_FP_SUBNORMAL; + fp->exponent = 1 - ( _PDCLIB_LDBL_MAX_EXP - 1 ); + fp->scale = _PDCLIB_LDBL_MANT_DIG - 1; + break; + case ( _PDCLIB_LDBL_MAX_EXP - 1 ) + _PDCLIB_LDBL_MAX_EXP: + fp->state = _PDCLIB_FP_NAN; + break; + default: + { + div_t dv = div( _PDCLIB_LDBL_MANT_DIG - 1, _PDCLIB_BIGINT_DIGIT_BITS ); + fp->state = _PDCLIB_FP_NORMAL; + + if ( dv.rem == 0 ) + { + fp->mantissa.data[ fp->mantissa.size++ ] = 1u; + } + else + { + fp->mantissa.data[ dv.quot ] |= ( 1u << dv.rem ); + } + + fp->exponent -= ( _PDCLIB_LDBL_MAX_EXP - 1 ); + fp->scale = _PDCLIB_LDBL_MANT_DIG - 1; + break; + } + } + + while ( fp->mantissa.size > 0 && fp->mantissa.data[ fp->mantissa.size - 1 ] == 0 ) + { + --fp->mantissa.size; + } + + if ( ( fp->state == _PDCLIB_FP_NAN ) && ( fp->mantissa.size == 0 ) ) + { + fp->state = _PDCLIB_FP_INF; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + _PDCLIB_fp_t fp; + _PDCLIB_bigint_t t; + + /* Normal */ + _PDCLIB_fp_from_ldbl( &fp, -1.0L ); + _PDCLIB_bigint_from_pow2( &t, _PDCLIB_LDBL_MANT_DIG - 1 ); + TESTCASE( fp.state == _PDCLIB_FP_NORMAL ); + TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 ); + TESTCASE( fp.scale == ( _PDCLIB_LDBL_MANT_DIG - 1 ) ); + TESTCASE( fp.exponent == 0 ); + + /* Inf */ + _PDCLIB_fp_from_ldbl( &fp, 1e5000L ); + TESTCASE( fp.state == _PDCLIB_FP_INF ); + TESTCASE( fp.mantissa.size == 0 ); + + /* NaN */ + _PDCLIB_fp_from_ldbl( &fp, -0.0L/0.0L ); + _PDCLIB_bigint_from_pow2( &t, _PDCLIB_LDBL_MANT_DIG - 2 ); + TESTCASE( fp.state == _PDCLIB_FP_NAN ); + TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 ); + + /* Subnormal */ + _PDCLIB_fp_from_ldbl( &fp, _PDCLIB_LDBL_MIN / 2L ); + _PDCLIB_bigint_from_pow2( &t, _PDCLIB_LDBL_MANT_DIG - 2 ); + TESTCASE( fp.state == _PDCLIB_FP_SUBNORMAL ); + TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 ); + TESTCASE( fp.scale == ( _PDCLIB_LDBL_MANT_DIG - 1 ) ); + TESTCASE( fp.exponent == (_PDCLIB_int_least16_t)(1 - ( _PDCLIB_LDBL_MAX_EXP - 1 ) ) ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_getstream.c b/rocklibc/src/_PDCLIB/_PDCLIB_getstream.c new file mode 100644 index 0000000..610cbf8 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_getstream.c @@ -0,0 +1,49 @@ +/* _PDCLIB_getstream( FILE * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +int _PDCLIB_getstream( struct _PDCLIB_file_t * stream ) +{ + struct _PDCLIB_file_t * previous; + + if ( ! _PDCLIB_isstream( stream, &previous ) ) + { + *_PDCLIB_errno_func() = _PDCLIB_EBADF; + return EOF; + } + + if ( previous != NULL ) + { + previous->next = stream->next; + } + else + { + _PDCLIB_filelist = stream->next; + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* No testdriver */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_init_file_t.c b/rocklibc/src/_PDCLIB/_PDCLIB_init_file_t.c new file mode 100644 index 0000000..4021774 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_init_file_t.c @@ -0,0 +1,82 @@ +/* _PDCLIB_init_file_t( _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. +*/ + +#ifndef REGTEST + +#include +#include +#include + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +struct _PDCLIB_file_t * _PDCLIB_init_file_t( struct _PDCLIB_file_t * stream ) +{ + struct _PDCLIB_file_t * rc = stream; + + if ( rc == NULL ) + { + if ( ( rc = (struct _PDCLIB_file_t *)malloc( sizeof( struct _PDCLIB_file_t ) ) ) == NULL ) + { + /* No memory */ + return NULL; + } + } + + if ( ( rc->buffer = (char *)malloc( BUFSIZ ) ) == NULL ) + { + /* No memory */ + free( rc ); + return NULL; + } + + rc->bufsize = BUFSIZ; + rc->bufidx = 0; + rc->bufend = 0; + rc->pos.offset = 0; + rc->pos.status = 0; + rc->ungetidx = 0; + rc->status = _PDCLIB_FREEBUFFER; + +#ifndef __STDC_NO_THREADS__ + + if ( stream == NULL ) + { + /* If called by freopen() (stream not NULL), mutex is already + initialized. + */ + if ( mtx_init( &rc->mtx, mtx_plain | mtx_recursive ) != thrd_success ) + { + /* could not initialize stream mutex */ + free( rc->buffer ); + free( rc ); + return NULL; + } + } + +#endif + + /* TODO: Setting mbstate */ + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + TESTCASE( NO_TESTDRIVER ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_is_leap.c b/rocklibc/src/_PDCLIB/_PDCLIB_is_leap.c new file mode 100644 index 0000000..da05f7f --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_is_leap.c @@ -0,0 +1,39 @@ +/* _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. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.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 ) ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + /* 1901 not leap */ + TESTCASE( ! _PDCLIB_is_leap( 1 ) ); + /* 1904 leap */ + TESTCASE( _PDCLIB_is_leap( 4 ) ); + /* 1900 not leap */ + TESTCASE( ! _PDCLIB_is_leap( 0 ) ); + /* 2000 leap */ + TESTCASE( _PDCLIB_is_leap( 100 ) ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_isstream.c b/rocklibc/src/_PDCLIB/_PDCLIB_isstream.c new file mode 100644 index 0000000..69f28ce --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_isstream.c @@ -0,0 +1,49 @@ +/* _PDCLIB_isstream( FILE *, FILE ** ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +int _PDCLIB_isstream( struct _PDCLIB_file_t * stream, struct _PDCLIB_file_t ** previous ) +{ + struct _PDCLIB_file_t * current = _PDCLIB_filelist; + + if ( previous != NULL ) + { + *previous = NULL; + } + + while ( ( current != NULL ) && ( current != stream ) ) + { + if ( previous != NULL ) + { + *previous = current; + } + + current = current->next; + } + + return current != NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* No testdriver */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_collate.c b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_collate.c new file mode 100644 index 0000000..7bfa711 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_collate.c @@ -0,0 +1,63 @@ +/* _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. +*/ + +#ifndef REGTEST + +#include +#include +#include +#include + +#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_collate_t *)malloc( sizeof( struct _PDCLIB_lc_collate_t ) ) ) != NULL ) + { + /* TODO: Collation data */ + + rc->alloced = 1; + } + + fclose( fh ); + } + + free( file ); + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + TESTCASE( NO_TESTDRIVER ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_ctype.c b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_ctype.c new file mode 100644 index 0000000..9b3226d --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_ctype.c @@ -0,0 +1,365 @@ +/* _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. +*/ + +#ifndef REGTEST + +#include +#include +#include +#include +#include +#include +#include + +#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_ctype_t *)malloc( sizeof( struct _PDCLIB_lc_ctype_t ) ) ) != NULL ) + { + struct _PDCLIB_lc_ctype_entry_t * entry; + + if ( ( entry = (struct _PDCLIB_lc_ctype_entry_t *)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, "%" SCNx16 " %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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ +#ifndef REGTEST + FILE * fh = fopen( "test_ctype.dat", "wb" ); + TESTCASE( fh != NULL ); + /* For test purposes, let's set up a charset that only has the hex digits */ + /* 0x00..0x09 - digits */ + /* 0x11..0x16 - Xdigits */ + /* 0x21..0x26 - xdigits */ + TESTCASE( fprintf( fh, "%x %x\n", 0x00, 0x09 ) ); + TESTCASE( fprintf( fh, "%x %x %x %x\n", 0x11, 0x16, 0x21, 0x26 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x00, 0x00 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x01, 0x01 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x02, 0x02 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x03, 0x03 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x04, 0x04 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x05, 0x05 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x06, 0x06 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x07, 0x07 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x08, 0x08 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x09, 0x09 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0A, 0x0A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0B, 0x0B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0C, 0x0C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0D, 0x0D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0E, 0x0E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0F, 0x0F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x10, 0x10 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x11, 0x11 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x12, 0x12 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x13, 0x13 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x14, 0x14 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x15, 0x15 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x16, 0x16 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x17, 0x17 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x18, 0x18 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x19, 0x19 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1A, 0x1A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1B, 0x1B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1C, 0x1C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1D, 0x1D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1E, 0x1E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1F, 0x1F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x20, 0x20 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x21, 0x21 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x22, 0x22 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x23, 0x23 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x24, 0x24 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x25, 0x25 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x26, 0x26 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x27, 0x27 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x28, 0x28 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x29, 0x29 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2A, 0x2A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2B, 0x2B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2C, 0x2C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2D, 0x2D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2E, 0x2E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2F, 0x2F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x30, 0x30 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x31, 0x31 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x32, 0x32 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x33, 0x33 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x34, 0x34 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x35, 0x35 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x36, 0x36 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x37, 0x37 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x38, 0x38 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x39, 0x39 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3A, 0x3A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3B, 0x3B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3C, 0x3C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3D, 0x3D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3E, 0x3E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3F, 0x3F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x40, 0x40 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x41, 0x41 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x42, 0x42 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x43, 0x43 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x44, 0x44 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x45, 0x45 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x46, 0x46 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x47, 0x47 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x48, 0x48 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x49, 0x49 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4A, 0x4A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4B, 0x4B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4C, 0x4C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4D, 0x4D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4E, 0x4E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4F, 0x4F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x50, 0x50 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x51, 0x51 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x52, 0x52 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x53, 0x53 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x54, 0x54 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x55, 0x55 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x56, 0x56 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x57, 0x57 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x58, 0x58 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x59, 0x59 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5A, 0x5A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5B, 0x5B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5C, 0x5C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5D, 0x5D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5E, 0x5E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5F, 0x5F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x60, 0x60 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x61, 0x61 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x62, 0x62 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x63, 0x63 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x64, 0x64 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x65, 0x65 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x66, 0x66 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x67, 0x67 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x68, 0x68 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x69, 0x69 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6A, 0x6A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6B, 0x6B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6C, 0x6C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6D, 0x6D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6E, 0x6E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6F, 0x6F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x70, 0x70 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x71, 0x71 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x72, 0x72 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x73, 0x73 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x74, 0x74 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x75, 0x75 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x76, 0x76 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x77, 0x77 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x78, 0x78 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x79, 0x79 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7A, 0x7A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7B, 0x7B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7C, 0x7C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7D, 0x7D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7E, 0x7E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7F, 0x7F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x80, 0x80 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x81, 0x81 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x82, 0x82 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x83, 0x83 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x84, 0x84 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x85, 0x85 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x86, 0x86 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x87, 0x87 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x88, 0x88 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x89, 0x89 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8A, 0x8A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8B, 0x8B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8C, 0x8C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8D, 0x8D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8E, 0x8E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8F, 0x8F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x90, 0x90 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x91, 0x91 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x92, 0x92 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x93, 0x93 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x94, 0x94 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x95, 0x95 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x96, 0x96 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x97, 0x97 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x98, 0x98 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x99, 0x99 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9A, 0x9A ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9B, 0x9B ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9C, 0x9C ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9D, 0x9D ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9E, 0x9E ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9F, 0x9F ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA0, 0xA0 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA1, 0xA1 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA2, 0xA2 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA3, 0xA3 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA4, 0xA4 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA5, 0xA5 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA6, 0xA6 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA7, 0xA7 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA8, 0xA8 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA9, 0xA9 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAA, 0xAA ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAB, 0xAB ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAC, 0xAC ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAD, 0xAD ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAE, 0xAE ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAF, 0xAF ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB0, 0xB0 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB1, 0xB1 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB2, 0xB2 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB3, 0xB3 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB4, 0xB4 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB5, 0xB5 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB6, 0xB6 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB7, 0xB7 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB8, 0xB8 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB9, 0xB9 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBA, 0xBA ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBB, 0xBB ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBC, 0xBC ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBD, 0xBD ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBE, 0xBE ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBF, 0xBF ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC0, 0xC0 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC1, 0xC1 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC2, 0xC2 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC3, 0xC3 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC4, 0xC4 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC5, 0xC5 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC6, 0xC6 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC7, 0xC7 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC8, 0xC8 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC9, 0xC9 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCA, 0xCA ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCB, 0xCB ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCC, 0xCC ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCD, 0xCD ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCE, 0xCE ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCF, 0xCF ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD0, 0xD0 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD1, 0xD1 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD2, 0xD2 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD3, 0xD3 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD4, 0xD4 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD5, 0xD5 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD6, 0xD6 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD7, 0xD7 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD8, 0xD8 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD9, 0xD9 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDA, 0xDA ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDB, 0xDB ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDC, 0xDC ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDD, 0xDD ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDE, 0xDE ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDF, 0xDF ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE0, 0xE0 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE1, 0xE1 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE2, 0xE2 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE3, 0xE3 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE4, 0xE4 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE5, 0xE5 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE6, 0xE6 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE7, 0xE7 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE8, 0xE8 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE9, 0xE9 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEA, 0xEA ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEB, 0xEB ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEC, 0xEC ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xED, 0xED ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEE, 0xEE ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEF, 0xEF ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF0, 0xF0 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF1, 0xF1 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF2, 0xF2 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF3, 0xF3 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF4, 0xF4 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF5, 0xF5 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF6, 0xF6 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF7, 0xF7 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF8, 0xF8 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF9, 0xF9 ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFA, 0xFA ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFB, 0xFB ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFC, 0xFC ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFD, 0xFD ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFE, 0xFE ) ); + TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFF, 0xFF ) ); + fclose( fh ); + TESTCASE( _PDCLIB_load_lc_ctype( "./", "test" ) != NULL ); + remove( "test_ctype.dat" ); + /* + TESTCASE( isdigit( 0x00 ) && ! isxdigit( 0x00 ) && ! isalpha( 0x00 ) ); + TESTCASE( ! isdigit( 0x11 ) && isxdigit( 0x11 ) && isalpha( 0x11 ) && isupper( 0x11 ) && ! islower( 0x11 ) ); + TESTCASE( ! isdigit( 0x21 ) && isxdigit( 0x21 ) && isalpha( 0x21 ) && ! isupper( 0x11 ) && islower( 0x11 ) ); + */ +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_messages.c b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_messages.c new file mode 100644 index 0000000..507303d --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_messages.c @@ -0,0 +1,88 @@ +/* _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. +*/ + +#ifndef REGTEST + +#include +#include +#include +#include + +#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_messages_t *)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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + FILE * fh = fopen( "test_numeric.dat", "wb" ); + struct _PDCLIB_lc_lconv_numeric_t * lc; + TESTCASE( fh != NULL ); + TESTCASE( fputs( ",\n.\n\n", fh ) != EOF ); + fclose( fh ); + TESTCASE( ( lc = _PDCLIB_load_lc_numeric( "./", "test" ) ) ); + remove( "test_numeric.dat" ); + TESTCASE( strcmp( lc->decimal_point, "," ) == 0 ); + TESTCASE( strcmp( lc->thousands_sep, "." ) == 0 ); + TESTCASE( strcmp( lc->grouping, "" ) == 0 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_monetary.c b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_monetary.c new file mode 100644 index 0000000..1180bb0 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_monetary.c @@ -0,0 +1,158 @@ +/* _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. +*/ + +#ifndef REGTEST + +#include +#include +#include +#include +#include + +#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_lconv_monetary_t *)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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + FILE * fh = fopen( "test_monetary.dat", "wb" ); + struct _PDCLIB_lc_lconv_monetary_t * lc; + TESTCASE( fh != NULL ); + fprintf( fh, "%s\n", "," ); /* mon_decimal_point */ + fprintf( fh, "%s\n", "." ); /* mon_thousands_sep */ + fprintf( fh, "%s\n", "3" ); /* mon_grouping */ + fprintf( fh, "%s\n", "" ); /* positive_sign */ + fprintf( fh, "%s\n", "-" ); /* negative_sign */ + fprintf( fh, "%s\n", "\xa4" ); /* currency_symbol */ + fprintf( fh, "%s\n", "EUR" ); /* int_curr_symbol */ + fputc( 2, fh ); /* frac_digits */ + fputc( 0, fh ); /* p_cs_precedes */ + fputc( 0, fh ); /* n_cs_precedes */ + fputc( 1, fh ); /* p_sep_by_space */ + fputc( 1, fh ); /* n_sep_by_space */ + fputc( 1, fh ); /* p_sign_posn */ + fputc( 1, fh ); /* n_sign_posn */ + fputc( 2, fh ); /* int_frac_digits */ + fputc( 0, fh ); /* int_p_cs_precedes */ + fputc( 0, fh ); /* int_n_cs_precedes */ + fputc( 1, fh ); /* int_p_sep_by_space */ + fputc( 1, fh ); /* int_n_sep_by_space */ + fputc( 1, fh ); /* int_p_sign_posn */ + fputc( 1, fh ); /* int_n_sign_posn */ + fprintf( fh, "\n" ); + fclose( fh ); + TESTCASE( ( lc = _PDCLIB_load_lc_monetary( "./", "test" ) ) ); + remove( "test_monetary.dat" ); + TESTCASE( strcmp( lc->mon_decimal_point, "," ) == 0 ); + TESTCASE( strcmp( lc->mon_thousands_sep, "." ) == 0 ); + TESTCASE( strcmp( lc->mon_grouping, "3" ) == 0 ); + TESTCASE( strcmp( lc->positive_sign, "" ) == 0 ); + TESTCASE( strcmp( lc->negative_sign, "-" ) == 0 ); + TESTCASE( strcmp( lc->currency_symbol, "\xa4" ) == 0 ); + TESTCASE( strcmp( lc->int_curr_symbol, "EUR" ) == 0 ); + + TESTCASE( lc->frac_digits == 2 ); + TESTCASE( lc->p_cs_precedes == 0 ); + TESTCASE( lc->n_cs_precedes == 0 ); + TESTCASE( lc->p_sep_by_space == 1 ); + TESTCASE( lc->n_sep_by_space == 1 ); + TESTCASE( lc->p_sign_posn == 1 ); + TESTCASE( lc->n_sign_posn == 1 ); + TESTCASE( lc->int_frac_digits == 2 ); + TESTCASE( lc->int_p_cs_precedes == 0 ); + TESTCASE( lc->int_n_cs_precedes == 0 ); + TESTCASE( lc->int_p_sep_by_space == 1 ); + TESTCASE( lc->int_n_sep_by_space == 1 ); + TESTCASE( lc->int_p_sign_posn == 1 ); + TESTCASE( lc->int_n_sign_posn == 1 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_numeric.c b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_numeric.c new file mode 100644 index 0000000..16caedb --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_numeric.c @@ -0,0 +1,84 @@ +/* _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. +*/ + +#ifndef REGTEST + +#include +#include +#include +#include + +#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_lconv_numeric_t *)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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + FILE * fh = fopen( "test_numeric.dat", "wb" ); + struct _PDCLIB_lc_lconv_numeric_t * lc; + TESTCASE( fh != NULL ); + TESTCASE( fputs( ",\n.\n\n", fh ) != EOF ); + fclose( fh ); + TESTCASE( ( lc = _PDCLIB_load_lc_numeric( "./", "test" ) ) ); + remove( "test_numeric.dat" ); + TESTCASE( strcmp( lc->decimal_point, "," ) == 0 ); + TESTCASE( strcmp( lc->thousands_sep, "." ) == 0 ); + TESTCASE( strcmp( lc->grouping, "" ) == 0 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_time.c b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_time.c new file mode 100644 index 0000000..99be781 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_load_lc_time.c @@ -0,0 +1,165 @@ +/* _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. +*/ + +#ifndef REGTEST + +#include +#include +#include +#include +#include + +#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_time_t *)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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + FILE * fh = fopen( "test_time.dat", "wb" ); + struct _PDCLIB_lc_time_t * lc; + + TESTCASE( fh != NULL ); + + /* month name abbreviation */ + TESTCASE( fprintf( fh, "%s\n", "Jan" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Feb" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "M\xe4r" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Apr" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Mai" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Jun" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Jul" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Aug" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Sep" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Okt" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Nov" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Dez" ) == 4 ); + /* month name full */ + TESTCASE( fprintf( fh, "%s\n", "Januar" ) == 7 ); + TESTCASE( fprintf( fh, "%s\n", "Februar" ) == 8 ); + TESTCASE( fprintf( fh, "%s\n", "M\xe4rz" ) == 5 ); + TESTCASE( fprintf( fh, "%s\n", "April" ) == 6 ); + TESTCASE( fprintf( fh, "%s\n", "Mai" ) == 4 ); + TESTCASE( fprintf( fh, "%s\n", "Juni" ) == 5 ); + TESTCASE( fprintf( fh, "%s\n", "Juli" ) == 5 ); + TESTCASE( fprintf( fh, "%s\n", "August" ) == 7 ); + TESTCASE( fprintf( fh, "%s\n", "September" ) == 10 ); + TESTCASE( fprintf( fh, "%s\n", "Oktober" ) == 8 ); + TESTCASE( fprintf( fh, "%s\n", "November" ) == 9 ); + TESTCASE( fprintf( fh, "%s\n", "Dezember" ) == 9 ); + /* day name abbreviation */ + TESTCASE( fprintf( fh, "%s\n", "So" ) == 3 ); + TESTCASE( fprintf( fh, "%s\n", "Mo" ) == 3 ); + TESTCASE( fprintf( fh, "%s\n", "Di" ) == 3 ); + TESTCASE( fprintf( fh, "%s\n", "Mi" ) == 3 ); + TESTCASE( fprintf( fh, "%s\n", "Do" ) == 3 ); + TESTCASE( fprintf( fh, "%s\n", "Fr" ) == 3 ); + TESTCASE( fprintf( fh, "%s\n", "Sa" ) == 3 ); + /* day name full */ + TESTCASE( fprintf( fh, "%s\n", "Sonntag" ) == 8 ); + TESTCASE( fprintf( fh, "%s\n", "Montag" ) == 7 ); + TESTCASE( fprintf( fh, "%s\n", "Dienstag" ) == 9 ); + TESTCASE( fprintf( fh, "%s\n", "Mittwoch" ) == 9 ); + TESTCASE( fprintf( fh, "%s\n", "Donnerstag" ) == 11 ); + TESTCASE( fprintf( fh, "%s\n", "Freitag" ) == 8 ); + TESTCASE( fprintf( fh, "%s\n", "Samstag" ) == 8 ); + + TESTCASE( fprintf( fh, "%s\n", "%a %d %b %Y %T %Z" ) == 18 ); /* date time format (%c) */ + TESTCASE( fprintf( fh, "%s\n", "%I:%M:%S" ) == 9 ); /* 12-hour time format (%r) */ + TESTCASE( fprintf( fh, "%s\n", "%d.%m.%Y" ) == 9 ); /* date format (%x) */ + TESTCASE( fprintf( fh, "%s\n", "%H:%M:%S" ) == 9 ); /* time format (%X) */ + + TESTCASE( fprintf( fh, "%s\n", "" ) == 1 ); /* AM */ + TESTCASE( fprintf( fh, "%s\n", "" ) == 1 ); /* PM */ + fclose( fh ); + TESTCASE( ( lc = _PDCLIB_load_lc_time( "./", "test" ) ) ); + remove( "test_time.dat" ); + + TESTCASE( strcmp( lc->month_name_abbr[ 0 ], "Jan" ) == 0 ); + TESTCASE( strcmp( lc->month_name_abbr[ 11 ], "Dez" ) == 0 ); + TESTCASE( strcmp( lc->month_name_full[ 0 ], "Januar" ) == 0 ); + TESTCASE( strcmp( lc->month_name_full[ 11 ], "Dezember" ) == 0 ); + TESTCASE( strcmp( lc->day_name_abbr[ 0 ], "So" ) == 0 ); + TESTCASE( strcmp( lc->day_name_abbr[ 6 ], "Sa" ) == 0 ); + TESTCASE( strcmp( lc->day_name_full[ 0 ], "Sonntag" ) == 0 ); + TESTCASE( strcmp( lc->day_name_full[ 6 ], "Samstag" ) == 0 ); + +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_load_lines.c b/rocklibc/src/_PDCLIB/_PDCLIB_load_lines.c new file mode 100644 index 0000000..7529545 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_load_lines.c @@ -0,0 +1,81 @@ +/* _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 + +#ifndef REGTEST + +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 = (char *)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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + FILE * fh = fopen( "test_lines.txt", "w+" ); + char * rc; + + TESTCASE( fh != NULL ); + TESTCASE( fputs( "Foo\n\nBar\n", fh ) != EOF ); + + rewind( fh ); + rc = _PDCLIB_load_lines( fh, 3 ); + fclose( fh ); + remove( "test_lines.txt" ); + + TESTCASE( rc != NULL ); + TESTCASE( strcmp( rc, "Foo" ) == 0 ); + TESTCASE( strcmp( rc + 4, "" ) == 0 ); + TESTCASE( strcmp( rc + 5, "Bar" ) == 0 ); + +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_naive_etod.c b/rocklibc/src/_PDCLIB/_PDCLIB_naive_etod.c new file mode 100644 index 0000000..24ba71e --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_naive_etod.c @@ -0,0 +1,96 @@ +/* _PDCLIB_naive_ptod( const char *, char ** endptr ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +#include +#include + +long double _PDCLIB_naive_etod( const char * s, char ** endptr ) +{ + /* This is nowhere good enough, just a quick approximation */ + long double rc = 0.0; + + while ( isdigit( (unsigned char)*s ) ) + { + rc = rc * 10 + ( *s++ - '0' ); + } + + if ( *s == '.' ) + { + long double fraction = 0.0; + long double scale = 1.0; + ++s; + + while ( isdigit( (unsigned char)*s ) ) + { + fraction = fraction * 10 + ( *s++ - '0' ); + scale *= 10; + } + + rc += ( fraction / scale ); + } + + if ( tolower( (unsigned char)*s ) == 'e' ) + { + char sign = '+'; + long double exp = 0.0; + long double scale = 1.0; + ++s; + + if ( *s == '-' ) + { + sign = *s++; + } + else if ( *s == '+' ) + { + ++s; + } + + while ( isdigit( (unsigned char)*s ) ) + { + exp = ( exp * 10 ) + ( *s++ - '0' ); + } + + while ( exp > 0 ) + { + scale *= 10; + --exp; + } + + if ( sign == '+' ) + { + rc *= scale; + } + else + { + rc /= scale; + } + } + + if ( endptr != NULL ) + { + *endptr = (char *)s; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Tested by strtof / strtol / strtold */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_naive_ptod.c b/rocklibc/src/_PDCLIB/_PDCLIB_naive_ptod.c new file mode 100644 index 0000000..27e6ed9 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_naive_ptod.c @@ -0,0 +1,97 @@ +/* _PDCLIB_naive_ptod( const char *, char ** endptr ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +#include +#include + +long double _PDCLIB_naive_ptod( const char * s, char ** endptr ) +{ + /* This is nowhere good enough, just a quick approximation */ + long double rc = 0.0; + const char * x; + + while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)*s ), 16 ) ) != NULL ) + { + rc = rc * 16 + ( x - _PDCLIB_digits ); + } + + if ( *s == '.' ) + { + long double fraction = 0.0; + long double scale = 1.0; + ++s; + + while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)*s ), 16 ) ) != NULL ) + { + fraction = fraction * 16 + ( x - _PDCLIB_digits ); + scale *= 16; + } + + rc += ( fraction / scale ); + } + + if ( tolower( (unsigned char)*s ) == 'p' ) + { + char sign = '+'; + long double exp = 0.0; + long double scale = 1.0; + ++s; + + if ( *s == '-' ) + { + sign = *s++; + } + else if ( *s == '+' ) + { + ++s; + } + + while ( isdigit( (unsigned char)*s ) ) + { + exp = ( exp * 10 ) + ( *s++ - '0' ); + } + + while ( exp > 0 ) + { + scale *= 2; + --exp; + } + + if ( sign == '+' ) + { + rc *= scale; + } + else + { + rc /= scale; + } + } + + if ( endptr != NULL ) + { + *endptr = (char *)s; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Tested by strtof / strtol / strtold */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_prepread.c b/rocklibc/src/_PDCLIB/_PDCLIB_prepread.c new file mode 100644 index 0000000..8f50964 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_prepread.c @@ -0,0 +1,42 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_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. */ + *_PDCLIB_errno_func() = _PDCLIB_EBADF; + stream->status |= _PDCLIB_ERRORFLAG; + return EOF; + } + + stream->status |= _PDCLIB_FREAD | _PDCLIB_BYTESTREAM; + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_prepwrite.c b/rocklibc/src/_PDCLIB/_PDCLIB_prepwrite.c new file mode 100644 index 0000000..607d61e --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_prepwrite.c @@ -0,0 +1,39 @@ +/* _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 + +#ifndef REGTEST + +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. */ + *_PDCLIB_errno_func() = _PDCLIB_EBADF; + stream->status |= _PDCLIB_ERRORFLAG; + return EOF; + } + + stream->status |= _PDCLIB_FWRITE | _PDCLIB_BYTESTREAM; + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_print.c b/rocklibc/src/_PDCLIB/_PDCLIB_print.c new file mode 100644 index 0000000..1cd8759 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_print.c @@ -0,0 +1,493 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +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, + forced decimal point for floats, trailing zeroes not + removed for %g/%G + */ + 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; + } + } + + /* 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': + status->base = 2; + status->flags |= ( E_decimal | E_double | E_lower ); + break; + + case 'F': + status->base = 2; + status->flags |= ( E_decimal | E_double ); + break; + + case 'e': + status->base = 2; + status->flags |= ( E_exponent | E_double | E_lower ); + break; + + case 'E': + status->base = 2; + status->flags |= ( E_exponent | E_double ); + break; + + case 'g': + status->base = 2; + status->flags |= ( E_generic | E_double | E_lower ); + break; + + case 'G': + status->base = 2; + status->flags |= ( E_generic | E_double ); + break; + + case 'a': + status->base = 2; + status->flags |= ( E_hexa | E_double | E_lower ); + break; + + case 'A': + status->base = 2; + status->flags |= ( E_hexa | E_double ); + break; + + case 'c': + /* TODO: wide chars. */ + { + char c[1]; + c[0] = ( char )va_arg( status->arg, int ); + status->flags |= E_char; + _PDCLIB_print_string( c, status ); + return ++spec; + } + + case 's': + /* TODO: wide chars. */ + _PDCLIB_print_string( 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 ) + { + /* TODO: Check for invalid flag combinations. */ + if ( status->flags & E_double ) + { + /* Floating Point conversions */ + if ( status->flags & E_ldouble ) + { + long double value = va_arg( status->arg, long double ); + _PDCLIB_fp_t fp; + _PDCLIB_fp_from_ldbl( &fp, value ); + _PDCLIB_print_fp( &fp, status ); + } + else + { + double value = va_arg( status->arg, double ); + _PDCLIB_fp_t fp; + _PDCLIB_fp_from_dbl( &fp, value ); + _PDCLIB_print_fp( &fp, status ); + } + } + else + { + /* Having a precision cancels out any zero flag. */ + if ( status->prec != EOF ) + { + status->flags &= ~E_zero; + } + + if ( status->flags & E_unsigned ) + { + /* Integer conversions (unsigned) */ + uintmax_t value; + imaxdiv_t div; + + 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; + } + + div.quot = value / status->base; + div.rem = value % status->base; + _PDCLIB_print_integer( div, status ); + } + else + { + /* Integer conversions (signed) */ + 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; + } + + _PDCLIB_print_integer( imaxdiv( value, status->base ), status ); + } + } + + if ( status->flags & E_minus ) + { + /* Left-aligned filling */ + while ( status->current < status->width ) + { + PUT( ' ' ); + ++( status->current ); + } + } + + if ( status->i >= status->n && status->n > 0 ) + { + status->s[status->n - 1] = '\0'; + } + } + + return ++spec; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "_PDCLIB/print.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +#ifndef REGTEST + +static int testprintf( char * buffer, const char * format, ... ) +{ + /* Members: base, flags, n, i, current, s, width, prec, stream, arg */ + struct _PDCLIB_status_t status; + status.base = 0; + status.flags = 0; + status.n = 100; + status.i = 0; + status.current = 0; + status.s = buffer; + status.width = 0; + status.prec = EOF; + status.stream = NULL; + va_start( status.arg, format ); + memset( buffer, '\0', 100 ); + + if ( *( _PDCLIB_print( format, &status ) ) != '\0' ) + { + printf( "_PDCLIB_print() did not return end-of-specifier on '%s'.\n", format ); + ++TEST_RESULTS; + } + + va_end( status.arg ); + return status.i; +} + +#endif + +#define TEST_CONVERSION_ONLY + +#include + +int main( void ) +{ +#ifndef REGTEST + char target[100]; +#include "printf_testcases.h" +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_print_fp.c b/rocklibc/src/_PDCLIB/_PDCLIB_print_fp.c new file mode 100644 index 0000000..0a4b7d4 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_print_fp.c @@ -0,0 +1,390 @@ +/* _PDCLIB_print_fp( _PDCLIB_fp_t *, 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. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include +#include + +#define MIN( x, y ) ( ( x < y ) ? x : y ) + +static char * exp_to_buffer( int exponent, char * buffer ) +{ + div_t dv = div( exponent, 10 ); + + if ( dv.quot > 0 ) + { + buffer = exp_to_buffer( dv.quot, buffer ); + } + + *buffer++ = _PDCLIB_digits[ dv.rem ]; + return buffer; +} + +static void _PDCLIB_format_e( struct _PDCLIB_status_t * status, char * buffer, int exp10, char sign ) +{ + size_t len = strlen( buffer ); + int exponent = ( len + exp10 ) - 1; + int i; + char exp_buffer[8]; + char * current; + + /* Print exponent to exp_buffer */ + current = exp_buffer; + *current++ = ( status->flags & E_lower ) ? 'e' : 'E'; + + if ( exponent < 0 ) + { + *current++ = '-'; + exponent *= -1; + } + else + { + *current++ = '+'; + } + + if ( exponent > -10 && exponent < 10 ) + { + *current++ = '0'; + } + + current = exp_to_buffer( exponent, current ); + *current = '\0'; + + /* Left padding, if applicable */ + if ( ! ( status->flags & E_minus ) ) + { + i = ( sign != '\0' ) + + 1 + + ( status->prec > 0 || status->flags & E_alt ) + + ( ( status->prec > 0 ) ? status->prec : 0 ) + + ( current - exp_buffer ); + + if ( ( sign != '\0' ) && ( status->flags & E_zero ) ) + { + PUT( sign ); + status->current++; + } + + for ( ; (size_t)i < status->width; ++i ) + { + PUT( ( status->flags & E_zero ) ? '0' : ' ' ); + status->current++; + } + + if ( ( sign != '\0' ) && ! ( status->flags & E_zero ) ) + { + PUT( sign ); + status->current++; + } + } + else if ( sign != '\0' ) + { + PUT( sign ); + status->current++; + } + + /* Print buffer */ + current = buffer; + PUT( _PDCLIB_digits[ (size_t)*current++ ] ); + status->current++; + + if ( status->prec > 0 || status->flags & E_alt ) + { + PUT( '.' ); + status->current++; + } + + for ( i = 0; i < status->prec; ++i ) + { + if ( *current != '\0' ) + { + PUT( _PDCLIB_digits[ (size_t)*current++ ] ); + status->current++; + } + else if ( ! ( status->flags & E_generic ) ) + { + PUT( '0' ); + status->current++; + } + } + + /* Print exponent */ + for ( current = exp_buffer; *current != '\0'; ++current ) + { + PUT( *current ); + status->current++; + } +} + +static void _PDCLIB_format_f( struct _PDCLIB_status_t * status, char * buffer, int exp10, char sign ) +{ + size_t len = strlen( buffer ); + + /* Left padding, if applicable */ + if ( ! ( status->flags & E_minus ) ) + { + size_t i = ( sign != '\0' ) + + ( ( (int)len + exp10 > 0 ) ? ( len + exp10 ) : 1 ) + + ( status->prec > 0 || status->flags & E_alt ) + + ( ( status->prec > 0 ) ? status->prec : 0 ); + + if ( ( sign != '\0' ) && ( status->flags & E_zero ) ) + { + PUT( sign ); + status->current++; + } + + for ( ; i < status->width; ++i ) + { + PUT( ( status->flags & E_zero ) ? '0' : ' ' ); + status->current++; + } + + if ( ( sign != '\0' ) && ! ( status->flags & E_zero ) ) + { + PUT( sign ); + status->current++; + } + } + else if ( sign != '\0' ) + { + PUT( sign ); + status->current++; + } + + if ( exp10 >= 0 ) + { + /* Print buffer, period, zeroes to precision */ + /* len + exp10 + [period + [prec]] */ + int i; + + for ( i = 0; (size_t)i < len; ++i ) + { + PUT( _PDCLIB_digits[ (size_t)buffer[i] ] ); + status->current++; + } + + for ( i = 0; i < exp10; ++i ) + { + PUT( _PDCLIB_digits[0] ); + status->current++; + } + + if ( ( ( ! ( status->flags & E_generic ) ) && status->prec > 0 ) || status->flags & E_alt ) + { + PUT( '.' ); + status->current++; + } + + len = status->prec; + } + else + { + int n = len + exp10; + int i; + + if ( n > 0 ) + { + /* Print n from buffer, period, rest from buffer, zeroes to precision */ + for ( i = 0; i < n; ++i ) + { + PUT( _PDCLIB_digits[ (size_t)buffer[i] ] ); + status->current++; + } + + if ( status->prec > 0 || status->flags & E_alt ) + { + PUT( '.' ); + status->current++; + } + + for ( i = 0; buffer[ i + n ] != '\0'; ++i ) + { + PUT( _PDCLIB_digits[ (size_t)buffer[ i + n ] ] ); + status->current++; + } + + len = status->prec - i; + } + else + { + /* Print zero, period, -n zeroes, buffer, zeroes to precision */ + PUT( _PDCLIB_digits[0] ); + status->current++; + + if ( status->prec > 0 || status->flags & E_alt ) + { + PUT( '.' ); + status->current++; + } + + for ( i = 0; i < -n; ++i ) + { + PUT( _PDCLIB_digits[0] ); + status->current++; + } + + for ( i = 0; buffer[i] != '\0'; ++i ) + { + PUT( _PDCLIB_digits[ (size_t)buffer[i] ] ); + status->current++; + } + + n = -n + i; + len = status->prec - n; + } + } + + if ( ! ( status->flags & E_generic ) ) + { + for ( ; len > 0; --len ) + { + PUT( _PDCLIB_digits[0] ); + status->current++; + } + } +} + +static void _PDCLIB_format_infnan( struct _PDCLIB_status_t * status, int state, char sign ) +{ + size_t i; + char const * s = ( state == _PDCLIB_FP_INF ) + ? ( ( status->flags & E_lower ) ? "inf" : "INF" ) + : ( ( status->flags & E_lower ) ? "nan" : "NAN" ); + + /* Left padding, if applicable */ + if ( ! ( status->flags & E_minus ) ) + { + i = ( sign != '\0' ) ? 4 : 3; + for ( i = ( sign != '\0' ) ? 4 : 3; i < status->width; ++i ) + { + PUT( ' ' ); + status->current++; + } + } + + if ( sign != '\0' ) + { + PUT( sign ); + status->current++; + } + + for ( i = 0; i < 3; ++i ) + { + PUT( s[i] ); + } + + status->current += 3; +} + +void _PDCLIB_print_fp( _PDCLIB_fp_t * fp, + struct _PDCLIB_status_t * status ) +{ + char buffer[ _PDCLIB_LDBL_MANT_DIG + 10 ]; + + /* Turning sign bit into sign character. */ + if ( fp->sign == 1 ) + { + fp->sign = '-'; + } + else if ( status->flags & E_plus ) + { + fp->sign = '+'; + } + else if ( status->flags & E_space ) + { + fp->sign = ' '; + } + else + { + fp->sign = '\0'; + } + + if ( fp->state == _PDCLIB_FP_INF || fp->state == _PDCLIB_FP_NAN ) + { + _PDCLIB_format_infnan( status, fp->state, fp->sign ); + return; + } + + if ( status->flags & E_hexa ) + { + _PDCLIB_print_fp_hexa( fp, status, buffer ); + return; + } + else + { + int exp10; + + if ( status->prec < 0 ) + { + status->prec = 6; + } + + switch ( status->flags & ( E_decimal | E_exponent | E_generic ) ) + { + case E_decimal: + { + exp10 = _PDCLIB_print_fp_deci( fp, status, buffer ); + _PDCLIB_format_f( status, buffer, exp10, fp->sign ); + break; + } + case E_exponent: + { + exp10 = _PDCLIB_print_fp_deci( fp, status, buffer ); + _PDCLIB_format_e( status, buffer, exp10, fp->sign ); + break; + } + case E_generic: + { + _PDCLIB_bigint_t mant; + int exponent; + _PDCLIB_bigint_from_bigint( &mant, &fp->mantissa ); + + if ( status->prec == 0 ) + { + status->prec = 1; + } + + exp10 = _PDCLIB_print_fp_deci( fp, status, buffer ); + exponent = ( strlen( buffer ) + exp10 ) - 1; + + if ( exponent >= -4 && exponent < status->prec ) + { + _PDCLIB_bigint_from_bigint( &fp->mantissa, &mant ); + status->flags &= ~E_generic; + status->flags |= E_decimal; + status->prec -= exponent + 1; + exp10 = _PDCLIB_print_fp_deci( fp, status, buffer ); + status->flags |= E_generic; + _PDCLIB_format_f( status, buffer, exp10, fp->sign ); + } + else + { + status->prec -= 1; + _PDCLIB_format_e( status, buffer, exp10, fp->sign ); + } + break; + } + } + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( int argc, char * argv[] ) +{ + /* Tested by _PDCLIB_print testdriver */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_deci.c b/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_deci.c new file mode 100644 index 0000000..890328f --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_deci.c @@ -0,0 +1,211 @@ +/* _PDCLIB_print_fp_deci( _PDCLIB_fp_t *, struct _PDCLIB_status_t *, char ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +static int prep( _PDCLIB_bigint_t * mantissa, int exponent ) +{ + /* log10(2) to 128bit precision */ + const long double log_10_2 = 0.30102999566398119521373889472449302l; + + /* Get an approximation of the base 10 exponent we are looking at + and make it fall one short in most cases as correction is easier + that way. + */ + double guess = (double)( _PDCLIB_bigint_log2( mantissa ) + exponent ) * log_10_2 - 0.69; + int exp10 = ( (int)guess < guess ) ? (int)guess + 1 : (int)guess; + + return exp10; +} + +int _PDCLIB_print_fp_deci( _PDCLIB_fp_t * fp, + struct _PDCLIB_status_t * status, + char * buffer ) +{ + char * current = buffer; + _PDCLIB_bigint_t divisor; + _PDCLIB_bigint_digit_t msd; + int digit; + int cutoff; + + /* No decimal point in the mantissa, so we adjust the exponent. */ + int exponent = fp->exponent - fp->scale; + + int exp10 = prep( &fp->mantissa, exponent ); + + if ( ( status->flags & E_decimal ) && ( status->prec >= 0 ) && ( exp10 <= -status->prec ) ) + { + exp10 = -status->prec + 1; + } + + /* Set up the fraction. */ + if ( exponent > 0 ) + { + _PDCLIB_bigint_shl( &fp->mantissa, exponent ); + _PDCLIB_bigint_from_digit( &divisor, 1 ); + } + else + { + _PDCLIB_bigint_from_pow2( &divisor, -exponent ); + } + + /* Using the approx. exp10, scale the fraction close to where + we could start dividing. + */ + if ( exp10 > 0 ) + { + _PDCLIB_bigint_mul_pow10( &divisor, exp10 ); + } + else if ( exp10 < 0 ) + { + _PDCLIB_bigint_mul_pow10( &fp->mantissa, -exp10 ); + } + + /* Now we know if our approximation was good or needs correction. + This is why we substracted as much as we could in prep(), as + correctiong for one short is the cheaper operation. + */ + if ( _PDCLIB_bigint_cmp( &fp->mantissa, &divisor ) >= 0 ) + { + ++exp10; + } + else + { + _PDCLIB_bigint_mul10( &fp->mantissa ); + } + + /* We make sure the fraction is scaled properly. + The previous operations already ensured that + the mantissa is no more than divisor * 10. + Now we make sure that the divisor has enough + bits in the most significant digit to give a + proper result, and that both mantissa and the + divisor are scaled to the same bigint length. + */ + msd = divisor.data[ divisor.size - 1 ]; + + if ( ( msd < 8 ) || ( msd > ( _PDCLIB_BIGINT_DIGIT_MAX / 10 ) ) ) + { + int shift = ( ( _PDCLIB_BIGINT_DIGIT_BITS * 2 - 5 ) - _PDCLIB_bigint_digit_log2( msd ) ) % 32; + _PDCLIB_bigint_shl( &fp->mantissa, shift ); + _PDCLIB_bigint_shl( &divisor, shift ); + } + + /* Main loop - divide, generate digits, multiply with 10, repeat */ + switch ( status->flags & ( E_decimal | E_exponent | E_generic ) ) + { + case E_decimal: + cutoff = -status->prec; + break; + case E_exponent: + case E_generic: + cutoff = exp10 - status->prec - 1; + break; + } + + for (;;) + { + digit = _PDCLIB_bigint_div( &fp->mantissa, &divisor ); + --exp10; + + if ( fp->mantissa.size == 0 || exp10 == cutoff ) + { + break; + } + + *current++ = _PDCLIB_digits[ digit ]; + _PDCLIB_bigint_mul10( &fp->mantissa ); + } + + /* rounding */ + { + int roundup = 0; + + switch ( FLT_ROUNDS ) + { + case 3: /*FE_DOWNWARD*/ + roundup = ( fp->sign == '-' ); + break; + case 2: /*FE_UPWARD*/ + roundup = ( fp->sign != '-' ); + break; + case 0: /*FE_TOWARDZERO*/ + roundup = 0; + break; + default: + case 1: /*FE_TONEAREST*/ + { + int compare; + _PDCLIB_bigint_shl( &fp->mantissa, 1 ); + compare = _PDCLIB_bigint_cmp( &fp->mantissa, &divisor ); + if ( ( compare > 0 ) /* Over 0.5 */ + || ( ( compare == 0 ) && ( digit & 1 ) ) ) /* Break tie to even */ + { + roundup = 1; + } + } + + if ( roundup ) + { + if ( digit < 9 ) + { + *current++ = _PDCLIB_digits[ ++digit ]; + } + else + { + for (;;) + { + ++exp10; + + if ( current == buffer ) + { + *current++ = _PDCLIB_digits[1]; + ++exp10; + break; + } + + if ( *--current != _PDCLIB_digits[9] ) + { + ++*current++; + break; + } + } + } + } + else + { + *current++ = _PDCLIB_digits[ digit ]; + } + } + + while ( *(current - 1) == '0' ) + { + --current; + ++exp10; + } + } + + *current = '\0'; + return exp10; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( int argc, char * argv[] ) +{ + /* Tested by _PDCLIB_print testdriver */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_hexa.c b/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_hexa.c new file mode 100644 index 0000000..d2b56e5 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_print_fp_hexa.c @@ -0,0 +1,268 @@ +/* _PDCLIB_print_fp_hexa( _PDCLIB_bigint_t *, struct _PDCLIB_status_t *, char ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include +#include +#include + +static inline void round_up( char * buffer, size_t index ) +{ + if ( buffer[ index ] < '\017' ) + { + ++buffer[ index ]; + } + else + { + buffer[ index ] = '\0'; + round_up( buffer, index - 1 ); + } +} + +static inline void round( char * buffer, size_t last_non_zero, size_t prec, char sign ) +{ + switch ( FLT_ROUNDS ) + { + case 0: /*FE_TOWARDZERO*/ + break; + default: /*FE_TONEAREST*/ + case 1: + if ( buffer[ prec + 1 ] > '\005' ) + { + round_up( buffer, prec ); + } + else if ( buffer[ prec + 1 ] == '\005' ) + { + if ( last_non_zero > ( prec + 1 ) || ( buffer[ prec ] % 2 ) ) + { + round_up( buffer, prec ); + } + } + break; + case 2: /*FE_UPWARD*/ + if ( sign != '-' ) + { + round_up( buffer, prec ); + } + break; + case 3: /*FE_DOWNWARD*/ + if ( sign == '-' ) + { + round_up( buffer, prec ); + } + break; + } +} + +static char * print_exp( char * buffer, int exp ) +{ + div_t dv = div( exp, 10 ); + + if ( dv.quot > 0 ) + { + buffer = print_exp( buffer, dv.quot ); + } + + *buffer = _PDCLIB_digits[ dv.rem ]; + return ++buffer; +} + +static size_t print_mant( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer ) +{ + size_t i; + int last_non_zero; + size_t mant_dig = ( ( status->flags & E_ldouble ) ? _PDCLIB_LDBL_MANT_DIG : _PDCLIB_DBL_MANT_DIG ) - 1; + size_t log2 = _PDCLIB_bigint_log2( &fp->mantissa ); + char * bufend = buffer; + + if ( ( mant_dig % 4 ) > 0 ) + { + /* alignment */ + int shift = 4 - ( mant_dig % 4 ); + _PDCLIB_bigint_shl( &fp->mantissa, shift ); + mant_dig += shift; + log2 += shift; + } + + if ( mant_dig > log2 ) + { + /* subnormal, leading zeroes */ + for ( i = 0; i <= ( mant_dig - log2 - 1 ) / 4; ++i ) + { + *bufend++ = '\0'; + } + } + + for ( i = log2 / 4 + 1; i > 0; --i, ++bufend ) + { + /* data nibbles */ + div_t dv = div( i - 1, _PDCLIB_BIGINT_DIGIT_BITS / 4 ); + + if ( ( *bufend = ( fp->mantissa.data[ dv.quot ] >> ( dv.rem * 4 ) ) & 0xfu ) > 0 ) + { + last_non_zero = bufend - buffer; + } + } + + if ( status->prec >= 0 ) + { + /* check rounding */ + if ( last_non_zero > ( status->prec + 1 ) ) + { + round( buffer, last_non_zero, status->prec, fp->sign ); + } + + return status->prec + 1; + } + else + { + /* no precision given */ + return last_non_zero + 1; + } +} + +void _PDCLIB_print_fp_hexa( _PDCLIB_fp_t * fp, + struct _PDCLIB_status_t * status, + char * buffer ) +{ + _PDCLIB_static_assert( _PDCLIB_FLT_RADIX == 2, "Assuming 2-based Floating Point" ); + + char const * digits = ( status->flags & E_lower ) ? _PDCLIB_digits : _PDCLIB_Xdigits; + int exp = (_PDCLIB_bigint_sdigit_t)fp->exponent; + /* sign + "0x" + dec + "." + ( LDBL_MANT_DIG / 4 ) + + 'p' + sign + exp[5] + '\0' <= 41 + ...but how could I do THAT? :-) + */ + char * current = buffer; + size_t count; + size_t i; + + /* significant */ + if ( fp->mantissa.size == 0 ) + { + *current++ = '0'; + exp = 0; + } + else + { + count = print_mant( fp, status, current ); + + *current = digits[ (size_t)*current ]; + ++current; + + if ( ( count > 1 && status->prec != 0 ) || status->flags & E_alt ) + { + for ( i = count; i > 1; --i ) + { + current[ i ] = current[ i - 1 ]; + } + + *current++ = '.'; /* TODO: decimal point */ + } + + for ( i = 1; i < count; ++i ) + { + *current = digits[ (size_t)*current ]; + ++current; + } + } + + /* exponent */ + *current++ = ( status->flags & E_lower ) ? 'p' : 'P'; + + if ( exp < 0 ) + { + *current++ = '-'; + exp *= -1; + } + else + { + *current++ = '+'; + } + + current = print_exp( current, exp ); + *current = '\0'; + + /* output */ + count = ( current - buffer ) + ( ( fp->sign == '\0' ) ? 2 : 3 ); + count = ( status->width > count ) ? ( status->width - count ) : 0; + + if ( ( count > 0 ) && ! ( status->flags & E_minus ) && ! ( status->flags & E_zero ) ) + { + for ( i = 0; i < count; ++i ) + { + PUT( ' ' ); + status->current++; + } + } + + if ( fp->sign != '\0' ) + { + PUT( fp->sign ); + status->current++; + } + + PUT( '0' ); + PUT( ( status->flags & E_lower ) ? 'x' : 'X' ); + status->current += 2; + + if ( ( count > 0 ) && ! ( status->flags & E_minus ) && ( status->flags & E_zero ) ) + { + for ( i = 0; i < count; ++i ) + { + PUT( '0' ); + status->current++; + } + } + + current = buffer; + + while ( *current != '\0' ) + { + PUT( *current++ ); + status->current++; + } + + if ( ( count > 0 ) && ( status->flags & E_minus ) ) + { + for ( i = 0; i < count; ++i ) + { + PUT( ' ' ); + status->current++; + } + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( int argc, char * argv[] ) +{ + /* Tested by _PDCLIB_print testdriver */ +#ifndef REGTEST + char buffer[100]; + *(print_exp( buffer, 0 )) = '\0'; + TESTCASE( strcmp( buffer, "0" ) == 0 ); + + *(print_exp( buffer, 9 )) = '\0'; + TESTCASE( strcmp( buffer, "9" ) == 0 ); + + *(print_exp( buffer, 10 )) = '\0'; + TESTCASE( strcmp( buffer, "10" ) == 0 ); + + *(print_exp( buffer, 100 )) = '\0'; + TESTCASE( strcmp( buffer, "100" ) == 0 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_print_integer.c b/rocklibc/src/_PDCLIB/_PDCLIB_print_integer.c new file mode 100644 index 0000000..bca0ce4 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_print_integer.c @@ -0,0 +1,175 @@ +/* _PDCLIB_print_integer + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include +#include + +#include "pdclib/_PDCLIB_print.h" + +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 signed 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 = ( ( _PDCLIB_size_t )status->prec > status->current ) ? ( ( _PDCLIB_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 > ( _PDCLIB_size_t )status->prec ) ? status->current : ( _PDCLIB_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 ); + } + } + } +} + +/* 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. +*/ +void _PDCLIB_print_integer( imaxdiv_t div, struct _PDCLIB_status_t * status ) +{ + if ( status->current == 0 && div.quot == 0 && div.rem == 0 && status->prec == 0 ) + { + intformat( 0, status ); + } + else + { + ++(status->current); + + if ( div.quot != 0 ) + { + _PDCLIB_print_integer( imaxdiv( div.quot, status->base ), status ); + } + else + { + intformat( div.rem, status ); + } + + if ( div.rem < 0 ) + { + div.rem *= -1; + } + + if ( status->flags & E_lower ) + { + PUT( _PDCLIB_digits[ div.rem ] ); + } + else + { + PUT( _PDCLIB_Xdigits[ div.rem ] ); + } + } +} + +#endif + +#ifdef TEST + +#include + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Tested by the various *printf() drivers. */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_print_string.c b/rocklibc/src/_PDCLIB/_PDCLIB_print_string.c new file mode 100644 index 0000000..ab253a8 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_print_string.c @@ -0,0 +1,85 @@ +/* _PDCLIB_print_string + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include +#include +#include + +#include "pdclib/_PDCLIB_print.h" + +/* Print a "string" (%c, %s) under control of a given status struct. See + INT2BASE(). +*/ +void _PDCLIB_print_string( 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 > ( _PDCLIB_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 ); + } + } +} + +#endif + +#ifdef TEST + +#include + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Tested by _PDCLIB_print testdriver */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_realpath.c b/rocklibc/src/_PDCLIB/_PDCLIB_realpath.c new file mode 100644 index 0000000..8711c36 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_realpath.c @@ -0,0 +1,61 @@ +/* _PDCLIB_realpath( const char * path ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern char * realpath( const char * file_name, char * resolved_name ); + +#ifdef __cplusplus +} +#endif + +char * _PDCLIB_realpath( const char * path ) +{ + /* TODO: PATH_MAX but that seems difficult to come by */ + char buffer[ 4096 ]; + char * resolved_name; + + if ( realpath( path, buffer ) == NULL ) + { + return NULL; + } + + /* Need to do our own alloc-and-copy here, as realpath() + would be linked to the system malloc(), and if our + fclose() would run our free() on someone else's memory, + results are more interesting than we would like to see. + */ + if ( ( resolved_name = malloc( strlen( buffer + 1 ) ) ) == NULL ) + { + return NULL; + } + + return strcpy( resolved_name, buffer ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* No test drivers. */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_remove.c b/rocklibc/src/_PDCLIB/_PDCLIB_remove.c new file mode 100644 index 0000000..aaad673 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_remove.c @@ -0,0 +1,42 @@ +/* _PDCLIB_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 _PDCLIB_remove() fit for use with + POSIX kernels. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int unlink( const char * ); + +#ifdef __cplusplus +} +#endif + +int _PDCLIB_remove( const char * pathname ) +{ + return unlink( pathname ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c (and several others) */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_rename.c b/rocklibc/src/_PDCLIB/_PDCLIB_rename.c new file mode 100644 index 0000000..2ff1cea --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_rename.c @@ -0,0 +1,117 @@ +/* _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 + +#ifndef REGTEST + +/* Having to jump through some hoops here so including fcntl.h does + work. Linux struggles with redefinitions of SEEK_SET et al. if + we set _GNU_SOURCE, but Cygwin needs that to actually get to the + AT_FDCWD definition. +*/ +#ifdef __linux__ +#define _ATFILE_SOURCE 1 +#else +#define _GNU_SOURCE 1 +#endif + +#include "pdclib/_PDCLIB_glue.h" +#include "pdclib/_PDCLIB_defguard.h" + +#include "pdclib/_PDCLIB_platform_errno.h" + +/* The system calls provided for renaming are rename(), renameat() + and renameat2(). Using rename() is not possible, since we have + that symbol in our library and would end up with a recursive + call. But we *can* use renameat() with default parameters! + AT_FDCWD is declared in fcntl.h. We need to manually declare + renameat() here as it is declared in system's . +*/ +#include "pdclib/_PDCLIB_platform_fcntl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int renameat( int, const char *, int, const char * ); + +#ifdef __cplusplus +} +#endif + +int _PDCLIB_rename( const char * oldpath, const char * newpath ) +{ + /* Whether existing newpath is overwritten is implementation- + defined. This system call *does* overwrite. + */ + if ( renameat( AT_FDCWD, oldpath, AT_FDCWD, newpath ) != 0 ) + { + /* The 1:1 mapping in _PDCLIB_config.h ensures this works. */ + *_PDCLIB_errno_func() = errno; + return -1; + } + else + { + return 0; + } +} + +#endif + +#ifdef TEST +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ +#ifndef REGTEST + FILE * file; + remove( testfile1 ); + remove( testfile2 ); + /* check that neither file exists */ + TESTCASE( fopen( testfile1, "r" ) == NULL ); + TESTCASE( fopen( testfile2, "r" ) == NULL ); + /* rename file 1 to file 2 - expected to fail */ + TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == -1 ); + /* create file 1 */ + TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL ); + TESTCASE( fputc( 'x', file ) == 'x' ); + TESTCASE( fclose( file ) == 0 ); + /* check that file 1 exists */ + TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL ); + TESTCASE( fclose( file ) == 0 ); + /* rename file 1 to file 2 */ + TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == 0 ); + /* check that file 2 exists, file 1 does not */ + TESTCASE( fopen( testfile1, "r" ) == NULL ); + TESTCASE( ( file = fopen( testfile2, "r" ) ) != NULL ); + TESTCASE( fclose( file ) == 0 ); + /* create another file 1 */ + TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL ); + TESTCASE( fputc( 'x', file ) == 'x' ); + TESTCASE( fclose( file ) == 0 ); + /* check that file 1 exists */ + TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL ); + TESTCASE( fclose( file ) == 0 ); + /* Whether existing destination files are overwritten or not + is implementation-defined. + This implementation *does* overwrite. + */ + TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == 0 ); + /* remove both files */ + remove( testfile1 ); + remove( testfile2 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_scan.c b/rocklibc/src/_PDCLIB/_PDCLIB_scan.c new file mode 100644 index 0000000..1bc23d0 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_scan.c @@ -0,0 +1,781 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +/* 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 ) + { + if ( _PDCLIB_CHECKBUFFER( status->stream ) != EOF ) + { + rc = _PDCLIB_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 = NULL; + + if ( !( status->flags & E_suppressed ) ) + { + 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 ) ) + { + if ( c != NULL ) + { + *( c++ ) = rc; + } + + value_parsed = 1; + } + + /* width or input exhausted */ + if ( value_parsed ) + { + if ( c != NULL ) + { + ++status->n; + } + + return ++spec; + } + else + { + /* input error, no character read */ + if ( status->n == 0 ) + { + status->n = -1; + } + + return NULL; + } + } + + case 's': + { + char * c = NULL; + + if ( !( status->flags & E_suppressed ) ) + { + c = va_arg( status->arg, char * ); + } + + while ( ( status->current < status->width ) && + ( ( rc = GET( status ) ) != EOF ) ) + { + if ( isspace( (unsigned char)rc ) ) + { + UNGET( rc, status ); + + if ( value_parsed ) + { + /* matching sequence terminated by whitespace */ + if ( c != NULL ) + { + *c = '\0'; + ++status->n; + } + + return ++spec; + } + else + { + /* matching error */ + return NULL; + } + } + else + { + /* match */ + if ( c != NULL ) + { + *( c++ ) = rc; + } + + value_parsed = 1; + } + } + + /* width or input exhausted */ + if ( value_parsed ) + { + if ( c != NULL ) + { + *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 = NULL; + + if ( !( status->flags & E_suppressed ) ) + { + c = va_arg( status->arg, char * ); + } + + 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 */ + 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; + } + } + + if ( c != NULL ) + { + *( c++ ) = rc; + } + + value_parsed = 1; + } + + /* width or input exhausted */ + if ( value_parsed ) + { + if ( c != NULL ) + { + *c = '\0'; + ++status->n; + } + + return ++endspec; + } + else + { + if ( status->n == 0 ) + { + status->n = -1; + } + + return NULL; + } + } + + case 'p': + status->base = 16; + status->flags |= E_pointer; + break; + + case 'n': + { + if ( !( status->flags & E_suppressed ) ) + { + 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( (unsigned char)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( (unsigned char)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 = (char *)memchr( _PDCLIB_digits, tolower( (unsigned char)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: + fputs( "UNSUPPORTED SCANF FLAG COMBINATIONi\n", stdout ); + return NULL; /* behaviour unspecified */ + } + + ++( status->n ); + } + + return ++spec; + } + + /* TODO: Floats. */ + return NULL; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "_PDCLIB/scan.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +#ifndef REGTEST + +static int testscanf( const char * s, const char * format, ... ) +{ + struct _PDCLIB_status_t status; + char const * rc; + + status.n = 0; + status.i = 0; + status.s = ( char * )s; + status.stream = NULL; + va_start( status.arg, format ); + + rc = _PDCLIB_scan( format, &status ); + + if ( rc != NULL && rc[0] != '\0' ) + { + printf( "_PDCLIB_scan() did not return end-of-specifier on '%s'.\n", format ); + ++TEST_RESULTS; + } + + if ( rc == NULL && s[0] != '\0' ) + { + printf( "_PDCLIB_scan() returned NULL on '%s' input.", s ); + ++TEST_RESULTS; + } + + va_end( status.arg ); + return status.n; +} + +#endif + +#define TEST_CONVERSION_ONLY + +int main( void ) +{ +#ifndef REGTEST + char source[100]; +#include "scanf_testcases.h" +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_seed.c b/rocklibc/src/_PDCLIB/_PDCLIB_seed.c new file mode 100644 index 0000000..ce7c31c --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_seed.c @@ -0,0 +1,19 @@ +/* _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; + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* no tests for raw data */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_seek.c b/rocklibc/src/_PDCLIB/_PDCLIB_seek.c new file mode 100644 index 0000000..dea648c --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_seek.c @@ -0,0 +1,81 @@ +/* int_least64_t _PDCLIB_seek( FILE *, int_least64_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. + */ + +#ifndef REGTEST + +#include +#include + +#include "pdclib/_PDCLIB_glue.h" + +#include "pdclib/_PDCLIB_platform_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int64_t lseek64( int fd, _PDCLIB_int_least64_t offset, int whence ); +extern long lseek( int fd, long offset, int whence ); + +#ifdef __cplusplus +} +#endif + +_PDCLIB_int_least64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int_least64_t offset, int whence ) +{ + _PDCLIB_int_least64_t rc; + + switch ( whence ) + { + case SEEK_SET: + case SEEK_CUR: + case SEEK_END: + /* EMPTY - OK */ + break; + + default: + *_PDCLIB_errno_func() = _PDCLIB_EINVAL; + return EOF; + break; + } + +#ifdef __CYGWIN__ + rc = lseek( stream->handle, offset, whence ); +#else + rc = lseek64( stream->handle, offset, whence ); +#endif + + if ( rc != EOF ) + { + stream->ungetidx = 0; + stream->bufidx = 0; + stream->bufend = 0; + stream->pos.offset = rc; + return rc; + } + + /* The 1:1 mapping in _PDCLIB_config.h ensures that this works. */ + *_PDCLIB_errno_func() = errno; + return EOF; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_stdinit.c b/rocklibc/src/_PDCLIB/_PDCLIB_stdinit.c new file mode 100644 index 0000000..10d8a8b --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_stdinit.c @@ -0,0 +1,598 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +/* 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 struct _PDCLIB_file_t _PDCLIB_serr = { 2, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, { 0 }, _IONBF | _PDCLIB_FWRITE, +#ifndef __STDC_NO_THREADS__ + _PDCLIB_MTX_RECURSIVE_INIT, +#endif + NULL, NULL +}; +static struct _PDCLIB_file_t _PDCLIB_sout = { 1, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, { 0 }, _IOLBF | _PDCLIB_FWRITE, +#ifndef __STDC_NO_THREADS__ + _PDCLIB_MTX_RECURSIVE_INIT, +#endif + NULL, &_PDCLIB_serr +}; +static struct _PDCLIB_file_t _PDCLIB_sin = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, { 0 }, _IOLBF | _PDCLIB_FREAD, +#ifndef __STDC_NO_THREADS__ + _PDCLIB_MTX_RECURSIVE_INIT, +#endif + 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; + +#ifndef __STDC_NO_THREADS__ +_PDCLIB_mtx_t _PDCLIB_filelist_mtx = _PDCLIB_MTX_PLAIN_INIT; +_PDCLIB_mtx_t _PDCLIB_time_mtx = _PDCLIB_MTX_PLAIN_INIT; +#endif + +/* "C" locale - defaulting to ASCII-7. + 1 kByte (+ 4 byte) of data. + Each line: flags, lowercase, uppercase. +*/ +static struct _PDCLIB_lc_ctype_entry_t _ctype_entries_C[ _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_C = { 0, 0x30, 0x39, 0x41, 0x46, 0x61, 0x66, &_ctype_entries_C[1] }; +struct _PDCLIB_lc_ctype_t * _PDCLIB_lc_ctype = &_PDCLIB_lc_ctype_C; + +struct _PDCLIB_lc_collate_t _PDCLIB_lc_collate_C = { 0 }; +struct _PDCLIB_lc_collate_t * _PDCLIB_lc_collate = &_PDCLIB_lc_collate_C; + +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_C = +{ + 0, + /* _PDCLIB_errno_texts */ + { + /* unknown error */ ( char * )"unknown error", + /* EPERM */ ( char * )"EPERM (Operation not permitted)", + /* ENOENT */ ( char * )"ENOENT (No such file or directory)", + /* ESRCH */ ( char * )"ESRCH (No such process)", + /* EINTR */ ( char * )"EINTR (Interrupted function)", + /* EIO */ ( char * )"EIO (I/O error)", + /* ENXIO */ ( char * )"ENXIO (No such device or address)", + /* E2BIG */ ( char * )"E2BIG (Argument list too long)", + /* ENOEXEC */ ( char * )"ENOEXEC (Executable file format error)", + /* EBADF */ ( char * )"EBADF (Bad file descriptor)", + /* ECHILD */ ( char * )"ECHILD (No child processes)", + /* EAGAIN */ ( char * )"EAGAIN (Resource unavailable, try again)", + /* ENOMEM */ ( char * )"ENOMEM (Not enough space)", + /* EACCES */ ( char * )"EACCES (Permission denied)", + /* EFAULT */ ( char * )"EFAULT (Bad address)", + /* unknown error */ ( char * )"unknown error", + /* EBUSY */ ( char * )"EBUSY (Device or resource busy)", + /* EEXIST */ ( char * )"EEXIST (File exists)", + /* EXDEV */ ( char * )"EXDEV (Cross-device link)", + /* ENODEV */ ( char * )"ENODEV (No such device)", + /* ENOTDIR */ ( char * )"ENOTDIR (Not a directory)", + /* EISDIR */ ( char * )"EISDIR (Is a directory)", + /* EINVAL */ ( char * )"EINVAL (Invalid argument)", + /* ENFILE */ ( char * )"ENFILE (Too many files open in system)", + /* EMFILE */ ( char * )"EMFILE (File descriptor value too large)", + /* ENOTTY */ ( char * )"ENOTTY (Inappropriate I/O control operation)", + /* ETXTBSY */ ( char * )"ETXTBSY (Text file busy)", + /* EFBIG */ ( char * )"EFBIG (File too large)", + /* ENOSPC */ ( char * )"ENOSPC (No space left on device)", + /* ESPIPE */ ( char * )"ESPIPE (Invalid seek)", + /* EROFS */ ( char * )"EROFS (Read-only file system)", + /* EMLINK */ ( char * )"EMLINK (Too many links)", + /* EPIPE */ ( char * )"EPIPE (Broken pipe)", + /* EDOM */ ( char * )"EDOM (Mathematics argument out of domain of function)", + /* ERANGE */ ( char * )"ERANGE (Result too large)", + /* EDEADLK */ ( char * )"EDEADLK (Resource deadlock would occur)", + /* ENAMETOOLONG */ ( char * )"ENAMETOOLONG (Filename too long)", + /* ENOLCK */ ( char * )"ENOLCK (No locks available)", + /* ENOSYS */ ( char * )"ENOSYS (Function not supported)", + /* ENOTEMPTY */ ( char * )"ENOTEMPTY (Directory not empty)", + /* ELOOP */ ( char * )"ELOOP (Too many levels of symbolic links)", + /* unknown error */ ( char * )"unknown error", + /* ENOMSG */ ( char * )"ENOMSG (No message of the desired type)", + /* EIDRM */ ( char * )"EIDRM (Identifier removed)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* ENOSTR */ ( char * )"ENOSTR (Not a STREAM)", + /* ENODATA */ ( char * )"ENODATA (No message is available on the STREAM head read queue)", + /* ETIME */ ( char * )"ETIME (Stream ioctl() timeout)", + /* ENOSR */ ( char * )"ENOSR (No STREAM resources)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* ENOLINK */ ( char * )"ENOLINK (Link has been severed)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* EPROTO */ ( char * )"EPROTO (Protocol error)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* EBADMSG */ ( char * )"EBADMSG (Bad message)", + /* EOVERFLOW */ ( char * )"EOVERFLOW (Value too large to be stored in data type)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* EILSEQ */ ( char * )"EILSEQ (Illegal byte sequence)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* ENOTSOCK */ ( char * )"ENOTSOCK (Not a socket)", + /* EDESTADDRREQ */ ( char * )"EDESTADDRREQ (Destination address required)", + /* EMSGSIZE */ ( char * )"EMSGSIZE (Message too large)", + /* EPROTOTYPE */ ( char * )"EPROTOTYPE (Protocol wrong type for socket)", + /* ENOPROTOOPT */ ( char * )"ENOPROTOOPT (Protocol not available)", + /* EPROTONOSUPPORT */ ( char * )"EPROTONOSUPPORT (Protocol not supported)", + /* unknown error */ ( char * )"unknown error", + /* ENOTSUP */ ( char * )"ENOTSUP (Not supported)", + /* unknown error */ ( char * )"unknown error", + /* EAFNOSUPPORT */ ( char * )"EAFNOSUPPORT (Address family not supported)", + /* EADDRINUSE */ ( char * )"EADDRINUSE (Address in use)", + /* EADDRNOTAVAIL */ ( char * )"EADDRNOTAVAIL (Address not available)", + /* ENETDOWN */ ( char * )"ENETDOWN (Network is down)", + /* ENETUNREACH */ ( char * )"ENETUNREACH (Network unreachable)", + /* ENETRESET */ ( char * )"ENETRESET (Connection aborted by network)", + /* ECONNABORTED */ ( char * )"ECONNABORTED (Connection aborted)", + /* ECONNRESET */ ( char * )"ECONNRESET (Connection reset)", + /* ENOBUFS */ ( char * )"ENOBUFS (No buffer space available)", + /* EISCONN */ ( char * )"EISCONN (Socket is connected)", + /* ENOTCONN */ ( char * )"ENOTCONN (The socket is not connected)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* ETIMEDOUT */ ( char * )"ETIMEDOUT (Connection timed out)", + /* ECONNREFUSED */ ( char * )"ECONNREFUSED (Connection refused)", + /* unknown error */ ( char * )"unknown error", + /* EHOSTUNREACH */ ( char * )"EHOSTUNREACH (Host is unreachable)", + /* EALREADY */ ( char * )"EALREADY (Connection already in progress)", + /* EINPROGRESS */ ( char * )"EINPROGRESS (Operation in progress)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* ECANCELED */ ( char * )"ECANCELED (Operation canceled)", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* unknown error */ ( char * )"unknown error", + /* EOWNERDEAD */ ( char * )"EOWNERDEAD (Previous owner died)", + /* ENOTRECOVERABLE */ ( char * )"ENOTRECOVERABLE (State not recoverable)", + } +}; + +struct _PDCLIB_lc_messages_t * _PDCLIB_lc_messages = &_PDCLIB_lc_messages_C; + +struct _PDCLIB_lc_time_t _PDCLIB_lc_time_C = +{ + 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 * )"Nov", + ( 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" + } +}; + +struct _PDCLIB_lc_time_t * _PDCLIB_lc_time = &_PDCLIB_lc_time_C; + +struct state _PDCLIB_lclmem; +struct state _PDCLIB_gmtmem; + +/* Section 4.12.3 of X3.159-1989 requires that + Except for the strftime function, these functions [asctime, + ctime, gmtime, localtime] return values in one of two static + objects: a broken-down time structure and an array of char. + Thanks to Paul Eggert for noting this. +*/ +struct tm _PDCLIB_tm; + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by several other testdrivers using stdin / stdout / + stderr. + */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_strtod_prelim.c b/rocklibc/src/_PDCLIB/_PDCLIB_strtod_prelim.c new file mode 100644 index 0000000..0e5bc83 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_strtod_prelim.c @@ -0,0 +1,135 @@ +/* _PDCLIB_strtod_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 + +#ifndef REGTEST + +int _PDCLIB_strtod_prelim( const char * p, char * sign, char ** endptr ) +{ + int base = 10; + + /* skipping leading whitespace */ + while ( isspace( (unsigned char)*p ) ) + { + ++p; + } + + /* determining / skipping sign */ + if ( *p != '+' && *p != '-' ) + { + *sign = '+'; + } + else + { + *sign = *( p++ ); + } + + /* determining base */ + if ( *p == '0' ) + { + ++p; + + if ( *p == 'x' || *p == 'X' ) + { + int period = 0; + base = 16; + ++p; + + if ( *p == '.' ) + { + ++p; + period = 1; + } + + /* catching a border case here: "0x" followed by a non-digit should + be parsed as the unprefixed zero. + We have to "rewind" the parsing. + */ + if ( memchr( _PDCLIB_digits, tolower( (unsigned char)*p ), base ) == NULL ) + { + p -= ( 2 + period ); + } + } + else + { + --p; + } + } + else + { + /* inf / nan(...) */ + /* Repurposing base: 0 for no match, -1 for inf, -2 for nan */ + if ( tolower( (unsigned char)p[0] ) == 'i' && tolower( (unsigned char)p[1] ) == 'n' && tolower( (unsigned char)p[2] ) == 'f' ) + { + p += 3; + base = -1; + } + else if ( tolower( (unsigned char)p[0] ) == 'n' && tolower( (unsigned char)p[1] ) == 'a' && tolower( (unsigned char)p[2] ) == 'n' ) + { + const char * n = p + 3; + p = n; + base = -2; + + if ( *n == '(' ) + { + while ( *++n && *n != ')' ); + + if ( *n == ')' ) + { + p = n + 1; + } + } + } + } + + *endptr = (char *)p; + return base; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + int base = 0; + char sign = '\0'; + char test1[] = " 123"; + char test2[] = "\t+0123"; + char test3[] = "\v-0x123"; + TESTCASE( _PDCLIB_strtox_prelim( test1, &sign, &base ) == &test1[2] ); + TESTCASE( sign == '+' ); + TESTCASE( base == 10 ); + base = 0; + sign = '\0'; + TESTCASE( _PDCLIB_strtox_prelim( test2, &sign, &base ) == &test2[2] ); + TESTCASE( sign == '+' ); + TESTCASE( base == 8 ); + base = 0; + sign = '\0'; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[4] ); + TESTCASE( sign == '-' ); + TESTCASE( base == 16 ); + base = 10; + sign = '\0'; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[2] ); + TESTCASE( sign == '-' ); + TESTCASE( base == 10 ); + base = 1; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL ); + base = 37; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_strtok.c b/rocklibc/src/_PDCLIB/_PDCLIB_strtok.c new file mode 100644 index 0000000..e99e719 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_strtok.c @@ -0,0 +1,186 @@ +/* _PDCLIB_strtok( char *, rsize_t *, const char *, char ** ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +char * _PDCLIB_strtok( char * _PDCLIB_restrict s1, rsize_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr ) +{ + const char * p = s2; + + if ( s1max == NULL || s2 == NULL || ptr == NULL || ( s1 == NULL && *ptr == NULL ) || *s1max > RSIZE_MAX ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return NULL; + } + + if ( s1 != NULL ) + { + /* new string */ + *ptr = s1; + } + else + { + /* old string continued */ + if ( *ptr == NULL ) + { + /* No old string, no new string, nothing to do */ + return NULL; + } + + s1 = *ptr; + } + + /* skip leading s2 characters */ + while ( *p && *s1 ) + { + if ( *s1 == *p ) + { + /* found separator; skip and start over */ + if ( *s1max == 0 ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return NULL; + } + + ++s1; + --( *s1max ); + p = s2; + continue; + } + + ++p; + } + + if ( ! *s1 ) + { + /* no more to parse */ + *ptr = s1; + return NULL; + } + + /* skipping non-s2 characters */ + *ptr = s1; + + while ( **ptr ) + { + p = s2; + + while ( *p ) + { + if ( **ptr == *p++ ) + { + /* found separator; overwrite with '\0', position *ptr, return */ + if ( *s1max == 0 ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return NULL; + } + + --( *s1max ); + *( ( *ptr )++ ) = '\0'; + return s1; + } + } + + if ( *s1max == 0 ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return NULL; + } + + --( *s1max ); + ++( *ptr ); + } + + /* parsed to end of string */ + return s1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#ifndef REGTEST + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#ifndef REGTEST + /* The original PDCLib strtok() test */ + char s[] = "_a_bc__d_"; + rsize_t max = strlen( s ); + char * p; + + TESTCASE( _PDCLIB_strtok( s, &max, "_", &p ) == &s[1] ); + TESTCASE( max == 6 ); + TESTCASE( s[1] == 'a' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[3] ); + TESTCASE( max == 3 ); + TESTCASE( s[3] == 'b' ); + TESTCASE( s[4] == 'c' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[7] ); + TESTCASE( max == 0 ); + TESTCASE( s[6] == '_' ); + TESTCASE( s[7] == 'd' ); + TESTCASE( s[8] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == NULL ); + TESTCASE( max == 0 ); + strcpy( s, "ab_cd" ); + max = strlen( s ); + TESTCASE( _PDCLIB_strtok( s, &max, "_", &p ) == &s[0] ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[1] == 'b' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[3] ); + TESTCASE( s[3] == 'c' ); + TESTCASE( s[4] == 'd' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == NULL ); + + /* Testing the constraint handling */ + strcpy( s, "ab.cd" ); + max = 2; + TESTCASE( set_constraint_handler_s( test_handler ) == abort_handler_s ); + TESTCASE( _PDCLIB_strtok( s, &max, ".", &p ) == NULL ); + TESTCASE( HANDLER_CALLS == 1 ); + + { + /* The strtok_s() example code from the standard */ + char str1[] = "?a???b,,,#c"; + char str2[] = "\t \t"; + rsize_t max1 = strlen( str1 ); + rsize_t max2 = strlen( str2 ); + char * ptr1; + char * ptr2; + + TESTCASE( _PDCLIB_strtok( str1, &max1, "?", &ptr1 ) == &str1[1] ); + TESTCASE( _PDCLIB_strtok( NULL, &max1, ",", &ptr1 ) == &str1[3] ); + TESTCASE( _PDCLIB_strtok( str2, &max2, " \t", &ptr2 ) == NULL ); + TESTCASE( _PDCLIB_strtok( NULL, &max1, "#,", &ptr1 ) == &str1[10] ); + TESTCASE( _PDCLIB_strtok( NULL, &max1, "?", &ptr1 ) == NULL ); + } +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_strtox_main.c b/rocklibc/src/_PDCLIB/_PDCLIB_strtox_main.c new file mode 100644 index 0000000..cf50e23 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_strtox_main.c @@ -0,0 +1,99 @@ +/* _PDCLIB_strtox_main( const char **, int, _PDCLIB_uintmax_t, _PDCLIB_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 + +#ifndef REGTEST + +_PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limit, char * sign ) +{ + _PDCLIB_uintmax_t rc = 0; + int digit = -1; + const char * x; + _PDCLIB_uintmax_t limval = limit / base; + int limdigit = limit % base; + + while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)**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( (unsigned char)**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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ +#ifndef REGTEST + const char * p; + char test[] = "123_"; + char fail[] = "xxx"; + char sign = '-'; + /* basic functionality */ + p = test; + errno = 0; + TESTCASE( _PDCLIB_strtox_main( &p, 10u, ( uintmax_t )999, ( uintmax_t )999, &sign ) == 123 ); + TESTCASE( errno == 0 ); + TESTCASE( p == &test[3] ); + /* proper functioning to smaller base */ + p = test; + TESTCASE( _PDCLIB_strtox_main( &p, 8u, ( uintmax_t )999, ( uintmax_t )999, &sign ) == 0123 ); + TESTCASE( errno == 0 ); + TESTCASE( p == &test[3] ); + /* overflowing subject sequence must still return proper endptr */ + p = test; + TESTCASE( _PDCLIB_strtox_main( &p, 4u, ( uintmax_t )999, ( uintmax_t )6, &sign ) == 999 ); + TESTCASE( errno == ERANGE ); + TESTCASE( p == &test[3] ); + TESTCASE( sign == '+' ); + /* testing conversion failure */ + errno = 0; + p = fail; + sign = '-'; + TESTCASE( _PDCLIB_strtox_main( &p, 10u, ( uintmax_t )999, ( uintmax_t )999, &sign ) == 0 ); + TESTCASE( p == NULL ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/_PDCLIB_strtox_prelim.c b/rocklibc/src/_PDCLIB/_PDCLIB_strtox_prelim.c new file mode 100644 index 0000000..1bbddc1 --- /dev/null +++ b/rocklibc/src/_PDCLIB/_PDCLIB_strtox_prelim.c @@ -0,0 +1,113 @@ +/* _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 + +#ifndef REGTEST + +const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base ) +{ + /* skipping leading whitespace */ + while ( isspace( (unsigned char)*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( (unsigned char)*p ), *base ) == NULL ) + { + p -= 2; + } + } + else if ( *base == 0 ) + { + *base = 8; + /* back up one digit, so that a plain zero is decoded correctly + (and endptr is set correctly as well). + (2019-01-15, Giovanni Mascellani) + */ + --p; + } + else + { + --p; + } + } + else if ( ! *base ) + { + *base = 10; + } + + return ( ( *base >= 2 ) && ( *base <= 36 ) ) ? p : NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + int base = 0; + char sign = '\0'; + char test1[] = " 123"; + char test2[] = "\t+0123"; + char test3[] = "\v-0x123"; + TESTCASE( _PDCLIB_strtox_prelim( test1, &sign, &base ) == &test1[2] ); + TESTCASE( sign == '+' ); + TESTCASE( base == 10 ); + base = 0; + sign = '\0'; + TESTCASE( _PDCLIB_strtox_prelim( test2, &sign, &base ) == &test2[2] ); + TESTCASE( sign == '+' ); + TESTCASE( base == 8 ); + base = 0; + sign = '\0'; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[4] ); + TESTCASE( sign == '-' ); + TESTCASE( base == 16 ); + base = 10; + sign = '\0'; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[2] ); + TESTCASE( sign == '-' ); + TESTCASE( base == 10 ); + base = 1; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL ); + base = 37; + TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/assert.c b/rocklibc/src/_PDCLIB/assert.c new file mode 100644 index 0000000..4c08716 --- /dev/null +++ b/rocklibc/src/_PDCLIB/assert.c @@ -0,0 +1,73 @@ +/* _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 + +#ifndef REGTEST + +void _PDCLIB_assert99( const char * const message1, const char * const function, const char * const message2 ) +{ + fputs( message1, stderr ); + fputs( function, stderr ); + fputs( message2, stderr ); + abort(); +} + +void _PDCLIB_assert89( const char * const message ) +{ + fputs( message, stderr ); + abort(); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +static int EXPECTED_ABORT = 0; +static int UNEXPECTED_ABORT = 1; + +static void aborthandler( int sig ) +{ + TESTCASE( ! EXPECTED_ABORT ); + exit( ( signed int )TEST_RESULTS ); +} + +#ifdef NDEBUG +#error Compiling test drivers with NDEBUG set is a questionable choice... +#endif + +#define NDEBUG + +#include + +static int disabled_test( void ) +{ + int i = 0; + assert( i == 0 ); /* NDEBUG set, condition met */ + assert( i == 1 ); /* NDEBUG set, condition fails */ + return i; +} + +#undef NDEBUG + +#include + +int main( void ) +{ + TESTCASE( signal( SIGABRT, &aborthandler ) != SIG_ERR ); + TESTCASE( disabled_test() == 0 ); + assert( UNEXPECTED_ABORT ); /* NDEBUG not set, condition met */ + assert( EXPECTED_ABORT ); /* NDEBUG not set, condition fails - should abort */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/errno.c b/rocklibc/src/_PDCLIB/errno.c new file mode 100644 index 0000000..f503b39 --- /dev/null +++ b/rocklibc/src/_PDCLIB/errno.c @@ -0,0 +1,71 @@ +/* _PDCLIB_errno + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +#if __STDC_VERSION__ >= 201112L && ! defined( __STDC_NO_THREADS__ ) +_Thread_local int _PDCLIB_errno = 0; +#else +static int _PDCLIB_errno = 0; +#endif + +int * _PDCLIB_errno_func() +{ + return &_PDCLIB_errno; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +#if ! defined( REGTEST ) && __STDC_VERSION__ >= 201112L && ! defined( __STDC_NO_THREADS__ ) + +#include + +static int thread_func( void * arg ) +{ + TESTCASE( errno == 0 ); + *_PDCLIB_errno_func() = 1; + TESTCASE( errno == 1 ); + thrd_exit( 0 ); +} + +#endif + +int main( void ) +{ + errno = 0; + TESTCASE( errno == 0 ); + errno = EDOM; + TESTCASE( errno == EDOM ); + errno = ERANGE; + TESTCASE( errno == ERANGE ); + +#if ! defined( REGTEST ) && __STDC_VERSION__ >= 201112L && ! defined( __STDC_NO_THREADS__ ) + { + thrd_t t; + struct timespec spec = { 1, 0 }; + int rc; + + TESTCASE( thrd_create( &t, thread_func, NULL ) == thrd_success ); + + TESTCASE( thrd_sleep( &spec, NULL ) == 0 ); + TESTCASE( errno == ERANGE ); + TESTCASE( thrd_join( t, &rc ) == thrd_success ); + TESTCASE( rc == 0 ); + } +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_PDCLIB/stdarg.c b/rocklibc/src/_PDCLIB/stdarg.c new file mode 100644 index 0000000..0de8320 --- /dev/null +++ b/rocklibc/src/_PDCLIB/stdarg.c @@ -0,0 +1,120 @@ +/* stdarg + + 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 + +#ifdef TEST + +#include "_PDCLIB_test.h" + +typedef int ( *intfunc_t )( void ); + +#define TAG_END 0 +#define TAG_INT 1 +#define TAG_LONG 2 +#define TAG_LLONG 3 +#define TAG_DBL 4 +#define TAG_LDBL 5 +#define TAG_INTPTR 6 +#define TAG_LDBLPTR 7 +#define TAG_FUNCPTR 8 + +static int dummy( void ) +{ + return INT_MAX; +} + +static int test( int s, ... ) +{ + va_list ap; + va_start( ap, s ); + + for ( ;; ) + { + switch ( s ) + { + case TAG_INT: + { + TESTCASE( va_arg( ap, int ) == INT_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_LONG: + { + TESTCASE( va_arg( ap, long ) == LONG_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_LLONG: + { + TESTCASE( va_arg( ap, long long ) == LLONG_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_DBL: + { + TESTCASE( va_arg( ap, double ) == DBL_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_LDBL: + { + TESTCASE( va_arg( ap, long double ) == LDBL_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_INTPTR: + { + TESTCASE( *( va_arg( ap, int * ) ) == INT_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_LDBLPTR: + { + TESTCASE( *( va_arg( ap, long double * ) ) == LDBL_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_FUNCPTR: + { + intfunc_t function; + TESTCASE( ( function = va_arg( ap, intfunc_t ) ) == dummy ); + TESTCASE( function() == INT_MAX ); + s = va_arg( ap, int ); + break; + } + + case TAG_END: + { + va_end( ap ); + return 0; + } + } + } +} + +int main( void ) +{ + int x = INT_MAX; + long double d = LDBL_MAX; + test( TAG_END ); + test( TAG_INT, INT_MAX, TAG_END ); + test( TAG_LONG, LONG_MAX, TAG_LLONG, LLONG_MAX, TAG_END ); + test( TAG_DBL, DBL_MAX, TAG_LDBL, LDBL_MAX, TAG_END ); + test( TAG_INTPTR, &x, TAG_LDBLPTR, &d, TAG_FUNCPTR, dummy, TAG_END ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_dlmalloc/malloc-2.8.6.patch b/rocklibc/src/_dlmalloc/malloc-2.8.6.patch new file mode 100644 index 0000000..834d81d --- /dev/null +++ b/rocklibc/src/_dlmalloc/malloc-2.8.6.patch @@ -0,0 +1,154 @@ +--- malloc-2.8.6.c 2024-05-01 19:50:19.477383272 +0200 ++++ malloc.c 2024-05-02 21:47:51.377419724 +0200 +@@ -1,3 +1,63 @@ ++/* malloc( size_t ) ++ calloc( size_t, size_t ) ++ realloc( void *, size_t ) ++ aligned_alloc( size_t, size_t ) ++ free( void * ) ++ ++ This file is part of the Public Domain C Library (PDCLib). ++ Permission is granted to use, modify, and / or redistribute at will. ++ ++ It is a slightly modified copy of Doug Lea's malloc(), retrieved from ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ at version 2.8.6, which is released under CC0 license just as PDCLib. ++*/ ++ ++/* Declared implicitly by dlmalloc. This declaration avoids the warning. */ ++#include ++void * sbrk( intptr_t ); ++ ++#ifndef REGTEST ++ ++#include "pdclib/_PDCLIB_config.h" ++#include "pdclib/_PDCLIB_defguard.h" ++ ++/* Have all functions herein use the dl* prefix */ ++#define USE_DL_PREFIX 1 ++ ++/* Thread safety */ ++#define USE_LOCKS 1 ++ ++/* Hide all functions herein as internal to the library */ ++#define DLMALLOC_EXPORT _PDCLIB_LOCAL ++ ++/* Unhide the standard functions. (Their declarations with the ++ DLMALLOC_EXPORT modifier below has been commented out; they ++ are declared _PDCLIB_PUBLIC in , marking them ++ exported from the library.) ++*/ ++#define dlmalloc malloc ++#define dlcalloc calloc ++#define dlrealloc realloc ++#define dlfree free ++#if __STDC_VERSION__ >= 201112L ++#define dlmemalign aligned_alloc ++#endif ++ ++#endif ++ ++#ifdef TEST ++ ++#include "_PDCLIB_test.h" ++ ++int main( void ) ++{ ++ TESTCASE( NO_TESTDRIVER ); ++ return TEST_RESULTS; ++} ++ ++#endif ++ ++/* ------------------------------------------------------------------- */ + /* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain, as explained at +@@ -585,8 +645,15 @@ + #define MAX_SIZE_T (~(size_t)0) + + #ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ +-#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ +- (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) ++/* defined() in the expansion of a macro is non-portable behavior ++ and runs afoul of -Wextra. ++*/ ++#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 */ +@@ -851,7 +918,7 @@ + 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); ++/*DLMALLOC_EXPORT void* dlmalloc(size_t);*/ + + /* + free(void* p) +@@ -860,14 +927,14 @@ + 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*); ++/*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); ++/*DLMALLOC_EXPORT void* dlcalloc(size_t, size_t);*/ + + /* + realloc(void* p, size_t n) +@@ -891,7 +958,7 @@ + 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); ++/*DLMALLOC_EXPORT void* dlrealloc(void*, size_t);*/ + + /* + realloc_in_place(void* p, size_t n) +@@ -996,7 +1063,7 @@ + guarantee that this number of bytes can actually be obtained from + the system. + */ +-DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(); ++DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(void); + + /* + malloc_set_footprint_limit(); +@@ -1256,8 +1323,8 @@ + + p = malloc(n); + assert(malloc_usable_size(p) >= 256); +-*/ + size_t dlmalloc_usable_size(void*); ++*/ + + #endif /* ONLY_MSPACES */ + +@@ -5376,6 +5443,7 @@ + return change_mparam(param_number, value); + } + ++/* + size_t dlmalloc_usable_size(void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +@@ -5384,6 +5452,7 @@ + } + return 0; + } ++*/ + + #endif /* !ONLY_MSPACES */ + diff --git a/rocklibc/src/_dlmalloc/malloc.c b/rocklibc/src/_dlmalloc/malloc.c new file mode 100644 index 0000000..ce47b08 --- /dev/null +++ b/rocklibc/src/_dlmalloc/malloc.c @@ -0,0 +1,6348 @@ +/* malloc( size_t ) + calloc( size_t, size_t ) + realloc( void *, size_t ) + aligned_alloc( size_t, size_t ) + free( void * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. + + It is a slightly modified copy of Doug Lea's malloc(), retrieved from + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + at version 2.8.6, which is released under CC0 license just as PDCLib. +*/ + +/* Declared implicitly by dlmalloc. This declaration avoids the warning. */ +#include +void * sbrk( intptr_t ); + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_config.h" +#include "pdclib/_PDCLIB_defguard.h" + +/* Have all functions herein use the dl* prefix */ +#define USE_DL_PREFIX 1 + +/* Thread safety */ + +/* Hide all functions herein as internal to the library */ +#define DLMALLOC_EXPORT _PDCLIB_LOCAL + +/* Unhide the standard functions. (Their declarations with the + DLMALLOC_EXPORT modifier below has been commented out; they + are declared _PDCLIB_PUBLIC in , marking them + exported from the library.) +*/ +#define dlmalloc malloc +#define dlcalloc calloc +#define dlrealloc realloc +#define dlfree free +#if __STDC_VERSION__ >= 201112L +#define dlmemalign aligned_alloc +#endif + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif + +/* ------------------------------------------------------------------- */ +/* + 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.6 Wed Aug 29 06:57:58 2012 Doug Lea + 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.6.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 (minimum) + 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 __declspec(dllexport) + If you want a POSIX ELF shared object, you might use + #define DLMALLOC_EXPORT extern __attribute__((visibility("default"))) + +MALLOC_ALIGNMENT default: (size_t)(2 * sizeof(void *)) + 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. + +LOCK_AT_FORK default: not defined + If defined nonzero, performs pthread_atfork upon initialization + to initialize child lock while holding parent lock. The implementation + assumes that pthread locks (not custom locks) are being used. In other + cases, you may need to customize the implementation. + +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_SYS_TYPES_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. +*/ + +/* Version identifier to allow people to support multiple versions */ +#ifndef DLMALLOC_VERSION +#define DLMALLOC_VERSION 20806 +#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_SYS_TYPES_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 */ + +#ifndef LACKS_SYS_TYPES_H +#include /* For size_t */ +#endif /* LACKS_SYS_TYPES_H */ + +/* 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 */ +/* defined() in the expansion of a macro is non-portable behavior + and runs afoul of -Wextra. +*/ +#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)(2 * sizeof(void *))) +#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); + +/* + 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*); +*/ + +#endif /* ONLY_MSPACES */ + +#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(const 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 */ +#else /* USE_LOCKS */ +#endif /* USE_LOCKS */ + +#ifndef LOCK_AT_FORK +#define LOCK_AT_FORK 0 +#endif + +/* 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, (LONG)1) +#define CLEAR_LOCK(sl) interlockedexchange (sl, (LONG)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, (LONG)-1, (LONG)0) == 0) { + InitializeCriticalSection(&malloc_global_mutex); + interlockedexchange(&malloc_global_mutex_status, (LONG)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*)((char*)(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 -------------------------- */ + +#if LOCK_AT_FORK +static void pre_fork(void) { ACQUIRE_LOCK(&(gm)->mutex); } +static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); } +static void post_fork_child(void) { INITIAL_LOCK(&(gm)->mutex); } +#endif /* LOCK_AT_FORK */ + +/* 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 LOCK_AT_FORK + pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child); +#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); + (void)flags; /* placate people compiling -Wunused */ + 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; + size_t ssize = asize; /* sbrk call size */ + 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)) + ssize += (page_align((size_t)base) - (size_t)base); + fp = m->footprint + ssize; /* recheck limits */ + if (ssize > nb && ssize < HALF_MAX_SIZE_T && + (m->footprint_limit == 0 || + (fp > m->footprint && fp <= m->footprint_limit)) && + (br = (char*)(CALL_MORECORE(ssize))) == base) { + tbase = base; + tsize = ssize; + } + } + } + else { + /* Subtract out existing available top space from MORECORE request. */ + ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); + /* Use mem here only if it did continuously extend old space */ + if (ssize < HALF_MAX_SIZE_T && + (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) { + tbase = br; + tsize = ssize; + } + } + + if (tbase == CMFAIL) { /* Cope with partial failure */ + if (br != CMFAIL) { /* Try to use/extend the space we did get */ + if (ssize < HALF_MAX_SIZE_T && + ssize < nb + SYS_ALLOC_PADDING) { + size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize); + if (esize < HALF_MAX_SIZE_T) { + char* end = (char*)CALL_MORECORE(esize); + if (end != CMFAIL) + ssize += esize; + else { /* Can't use; try to release */ + (void) CALL_MORECORE(-ssize); + br = CMFAIL; + } + } + } + } + if (br != CMFAIL) { /* Use the space we did get */ + tbase = br; + tsize = ssize; + } + 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; + int 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 = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)? + (size_t) nsegs : (size_t) 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 */ + size_t newsize = sp->size - extra; + (void)newsize; /* placate people compiling -Wunused-variable */ + /* 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, chunk2mem(p)); + } + 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(struct malloc_chunk)); + } + else { + start = (void*)((char*)q + sizeof(struct 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; + (void)base; /* placate people compiling -Wunused-variable */ + 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); + (void)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); + (void)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(const 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 */ + + +/* -------------------- 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.6 Wed Aug 29 06:57:58 2012 Doug Lea + * fix bad comparison in dlposix_memalign + * don't reuse adjusted asize in sys_alloc + * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion + * reduce compiler warnings -- thanks to all who reported/suggested these + + 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/rocklibc/src/_tzcode/Readme.txt b/rocklibc/src/_tzcode/Readme.txt new file mode 100644 index 0000000..8eaa30b --- /dev/null +++ b/rocklibc/src/_tzcode/Readme.txt @@ -0,0 +1,10 @@ +Major parts of PDCLib's implementation are based on IANA's reference +implementation, tzcode. + + https://data.iana.org/time-zones/tz-link.html + +The latest version of tzcode can be downloaded at: + + https://www.iana.org/time-zones/repository/tzcode-latest.tar.gz + +At the time of this writing, the latest tzcode version used as basis is 2020a. diff --git a/rocklibc/src/_tzcode/_PDCLIB_gmtcheck.c b/rocklibc/src/_tzcode/_PDCLIB_gmtcheck.c new file mode 100644 index 0000000..713af2b --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_gmtcheck.c @@ -0,0 +1,53 @@ +/* _PDCLIB_gmtcheck( void ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_time_mtx; +#endif + +static void gmtload( struct state * sp ) +{ + if ( _PDCLIB_tzload( gmt, sp, true ) != 0 ) + { + _PDCLIB_tzparse( gmt, sp, true ); + } +} + +void _PDCLIB_gmtcheck( void ) +{ + static bool gmt_is_set; + + _PDCLIB_LOCK( _PDCLIB_time_mtx ); + + if ( ! gmt_is_set ) + { + gmtload( &_PDCLIB_gmtmem ); + gmt_is_set = true; + } + + _PDCLIB_UNLOCK( _PDCLIB_time_mtx ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_gmtsub.c b/rocklibc/src/_tzcode/_PDCLIB_gmtsub.c new file mode 100644 index 0000000..59d7b8f --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_gmtsub.c @@ -0,0 +1,43 @@ +/* _PDCLIB_gmtsub( struct state const *, time_t const *, int_fast32_t, struct tm * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +/* gmtsub is to gmtime as localsub is to localtime. */ +struct tm * _PDCLIB_gmtsub( struct state const * sp, time_t const * timep, int_fast32_t offset, struct tm * tmp ) +{ + struct tm * result; + + result = _PDCLIB_timesub( timep, offset, &_PDCLIB_gmtmem, tmp ); + +#ifdef TM_ZONE + /* Could get fancy here and deliver something such as + "+xx" or "-xx" if offset is non-zero, + but this is no time for a treasure hunt. + */ + tmp->TM_ZONE = ( (char *)( offset ? wildabbr : &_PDCLIB_gmtmem ? _PDCLIB_gmtptr.chars : gmt ) ); +#endif + + return result; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_increment_overflow.c b/rocklibc/src/_tzcode/_PDCLIB_increment_overflow.c new file mode 100644 index 0000000..4734e0e --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_increment_overflow.c @@ -0,0 +1,45 @@ +/* _PDCLIB_increment_overflow( int *, int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +/* Normalize logic courtesy Paul Eggert. */ + +bool _PDCLIB_increment_overflow( int * ip, int j ) +{ + int const i = *ip; + + /* If i >= 0 there can only be overflow if i + j > INT_MAX + or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow. + If i < 0 there can only be overflow if i + j < INT_MIN + or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow. + */ + if ( ( i >= 0 ) ? ( j > _PDCLIB_INT_MAX - i ) : ( j < _PDCLIB_INT_MIN - i ) ) + { + return true; + } + + *ip += j; + return false; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_init_ttinfo.c b/rocklibc/src/_tzcode/_PDCLIB_init_ttinfo.c new file mode 100644 index 0000000..da18c7c --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_init_ttinfo.c @@ -0,0 +1,35 @@ +/* _PDCLIB_init_ttinfo( struct ttinfo *, int_fast32_t, bool, int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */ +void _PDCLIB_init_ttinfo( struct ttinfo * s, int_fast32_t utoff, bool isdst, int desigidx ) +{ + s->utoff = utoff; + s->isdst = isdst; + s->desigidx = desigidx; + s->ttisstd = false; + s->ttisut = false; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_localsub.c b/rocklibc/src/_tzcode/_PDCLIB_localsub.c new file mode 100644 index 0000000..fbdc186 --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_localsub.c @@ -0,0 +1,164 @@ +/* _PDCLIB_localsub( struct state const *, time_t const *, int_fast32_t, struct tm * const ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +/* The easy way to behave "as if no library function calls" localtime + is to not call it, so we drop its guts into "localsub", which can be + freely called. (And no, the PANS doesn't require the above behavior, + but it *is* desirable.) + + If successful and SETNAME is nonzero, + set the applicable parts of tzname, timezone and altzone; + however, it's OK to omit this step if the timezone is POSIX-compatible, + since in that case tzset should have already done this step correctly. + SETNAME's type is intfast32_t for compatibility with gmtsub, + but it is actually a boolean and its value should be 0 or 1. +*/ + +/*ARGSUSED*/ +struct tm * _PDCLIB_localsub( struct state const * sp, time_t const * timep, int_fast32_t setname, struct tm * const tmp ) +{ + const struct ttinfo * ttisp; + int i; + struct tm * result; + const time_t t = *timep; + + if ( sp == NULL ) + { + /* Don't bother to set tzname etc.; tzset has already done it. */ + return _PDCLIB_gmtsub( &_PDCLIB_gmtmem, timep, 0, tmp ); + } + + if ( ( sp->goback && t < sp->ats[ 0 ] ) || ( sp->goahead && t > sp->ats[ sp->timecnt - 1 ] ) ) + { + time_t newt = t; + time_t seconds; + time_t years; + + if ( t < sp->ats[ 0 ] ) + { + seconds = sp->ats[ 0 ] - t; + } + else + { + seconds = t - sp->ats[ sp->timecnt - 1 ]; + } + + --seconds; + years = ( seconds / SECSPERREPEAT + 1 ) * YEARSPERREPEAT; + seconds = years * AVGSECSPERYEAR; + + if ( t < sp->ats[ 0 ] ) + { + newt += seconds; + } + else + { + newt -= seconds; + } + + if ( newt < sp->ats[ 0 ] || newt > sp->ats[ sp->timecnt - 1 ] ) + { + return NULL; /* "cannot happen" */ + } + + result = _PDCLIB_localsub( sp, &newt, setname, tmp ); + + if ( result ) + { + int_fast64_t newy; + + newy = result->tm_year; + + if ( t < sp->ats[ 0 ] ) + { + newy -= years; + } + else + { + newy += years; + } + + if ( ! ( _PDCLIB_INT_MIN <= newy && newy <= _PDCLIB_INT_MAX ) ) + { + return NULL; + } + + result->tm_year = newy; + } + + return result; + } + + if ( sp->timecnt == 0 || t < sp->ats[ 0 ] ) + { + i = sp->defaulttype; + } + else + { + int lo = 1; + int hi = sp->timecnt; + + while ( lo < hi ) + { + int mid = ( lo + hi ) >> 1; + + if ( t < sp->ats[ mid ] ) + { + hi = mid; + } + else + { + lo = mid + 1; + } + } + + i = (int) sp->types[ lo - 1 ]; + } + + ttisp = &sp->ttis[ i ]; + + /* To get (wrong) behavior that's compatible with System V Release 2.0 + you'd replace the statement below with + t += ttisp->utoff; + timesub( &t, 0L, sp, tmp ); + */ + result = _PDCLIB_timesub( &t, ttisp->utoff, sp, tmp ); + + if ( result ) + { + result->tm_isdst = ttisp->isdst; +#ifdef TM_ZONE + result->TM_ZONE = (char *) &sp->chars[ ttisp->desigidx ]; +#endif /* defined TM_ZONE */ + + if ( setname ) + { + _PDCLIB_update_tzname_etc( sp, ttisp ); + } + } + + return result; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_localtime_tzset.c b/rocklibc/src/_tzcode/_PDCLIB_localtime_tzset.c new file mode 100644 index 0000000..988a042 --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_localtime_tzset.c @@ -0,0 +1,46 @@ +/* _PDCLIB_localtime_tzset( time_t const *, struct tm *, bool ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_time_mtx; +#endif + +#include + +struct tm * _PDCLIB_localtime_tzset( time_t const * timep, struct tm * tmp, bool setname ) +{ + _PDCLIB_LOCK( _PDCLIB_time_mtx ); + + if ( setname || ! lcl_is_set ) + { + _PDCLIB_tzset_unlocked(); + } + + tmp = _PDCLIB_localsub( &_PDCLIB_lclmem, timep, setname, tmp ); + _PDCLIB_UNLOCK( _PDCLIB_time_mtx ); + return tmp; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_mktime_tzname.c b/rocklibc/src/_tzcode/_PDCLIB_mktime_tzname.c new file mode 100644 index 0000000..2881370 --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_mktime_tzname.c @@ -0,0 +1,528 @@ +/* _PDCLIB_mktime_tzname( struct state *, struct tm *, bool ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +/* Adapted from code provided by Robert Elz, who writes: + The "best" way to do mktime I think is based on an idea of Bob + Kridle's (so its said...) from a long time ago. + It does a binary search of the time_t space. Since time_t's are + just 32 bits, its a max of 32 iterations (even at 64 bits it + would still be very reasonable). +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif + +/* Normalize logic courtesy Paul Eggert. */ + +static bool increment_overflow32( int_fast32_t * lp, int m ) +{ + int_fast32_t const l = *lp; + + if ( ( l >= 0 ) ? ( m > _PDCLIB_INT_FAST32_MAX - l ) : ( m < _PDCLIB_INT_FAST32_MIN - l ) ) + { + return true; + } + + *lp += m; + return false; +} + +static bool normalize_overflow( int * tensptr, int * unitsptr, int base ) +{ + int tensdelta; + + tensdelta = ( *unitsptr >= 0 ) ? + ( *unitsptr / base ) : + ( -1 - ( -1 - *unitsptr ) / base ); + *unitsptr -= tensdelta * base; + return _PDCLIB_increment_overflow( tensptr, tensdelta ); +} + +static bool normalize_overflow32( int_fast32_t * tensptr, int * unitsptr, int base ) +{ + int tensdelta; + + tensdelta = ( *unitsptr >= 0 ) ? + ( *unitsptr / base ) : + ( -1 - ( -1 - *unitsptr ) / base ); + *unitsptr -= tensdelta * base; + return increment_overflow32( tensptr, tensdelta ); +} + +static int tmcomp( const struct tm * atmp, const struct tm * btmp ) +{ + int result; + + if ( atmp->tm_year != btmp->tm_year ) + { + return atmp->tm_year < btmp->tm_year ? -1 : 1; + } + + if ( ( result = ( atmp->tm_mon - btmp->tm_mon ) ) == 0 && + ( result = ( atmp->tm_mday - btmp->tm_mday ) ) == 0 && + ( result = ( atmp->tm_hour - btmp->tm_hour ) ) == 0 && + ( result = ( atmp->tm_min - btmp->tm_min ) ) == 0 ) + { + result = atmp->tm_sec - btmp->tm_sec; + } + + return result; +} + +static time_t time2sub( struct tm * tmp, struct tm *(*funcp)( struct state const *, time_t const *, int_fast32_t, struct tm * ), struct state const * sp, const int_fast32_t offset, bool * okayp, bool do_norm_secs ) +{ + int dir; + int i, j; + int saved_seconds; + int_fast32_t li; + time_t lo; + time_t hi; + int_fast32_t y; + time_t newt; + time_t t; + struct tm yourtm, mytm; + + *okayp = false; + yourtm = *tmp; + + if ( do_norm_secs ) + { + if ( normalize_overflow( &yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN ) ) + { + return WRONG; + } + } + + if ( normalize_overflow( &yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR ) ) + { + return WRONG; + } + + if ( normalize_overflow( &yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY ) ) + { + return WRONG; + } + + y = yourtm.tm_year; + + if ( normalize_overflow32( &y, &yourtm.tm_mon, MONSPERYEAR ) ) + { + return WRONG; + } + + /* Turn y into an actual year number for now. + It is converted back to an offset from TM_YEAR_BASE later. + */ + if ( increment_overflow32( &y, TM_YEAR_BASE ) ) + { + return WRONG; + } + + while ( yourtm.tm_mday <= 0 ) + { + if ( increment_overflow32( &y, -1 ) ) + { + return WRONG; + } + + li = y + ( 1 < yourtm.tm_mon ); + yourtm.tm_mday += year_lengths[ _PDCLIB_is_leap( li ) ]; + } + while ( yourtm.tm_mday > DAYSPERLYEAR ) + { + li = y + ( 1 < yourtm.tm_mon ); + yourtm.tm_mday -= year_lengths[ _PDCLIB_is_leap( li ) ]; + + if ( increment_overflow32( &y, 1 ) ) + { + return WRONG; + } + } + + for ( ; ; ) + { + i = mon_lengths[ _PDCLIB_is_leap( y ) ][ yourtm.tm_mon ]; + + if ( yourtm.tm_mday <= i ) + { + break; + } + + yourtm.tm_mday -= i; + + if ( ++yourtm.tm_mon >= MONSPERYEAR ) + { + yourtm.tm_mon = 0; + + if ( increment_overflow32( &y, 1 ) ) + { + return WRONG; + } + } + } + + if ( increment_overflow32( &y, -TM_YEAR_BASE ) ) + { + return WRONG; + } + + if ( ! ( _PDCLIB_INT_MIN <= y && y <= _PDCLIB_INT_MAX ) ) + { + return WRONG; + } + + yourtm.tm_year = y; + + if ( yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN ) + { + saved_seconds = 0; + } + else if ( y + TM_YEAR_BASE < EPOCH_YEAR ) + { + /* We can't set tm_sec to 0, because that might push the + time below the minimum representable time. + Set tm_sec to 59 instead. + This assumes that the minimum representable time is + not in the same minute that a leap second was deleted from, + which is a safer assumption than using 58 would be. + */ + if ( _PDCLIB_increment_overflow( &yourtm.tm_sec, 1 - SECSPERMIN ) ) + { + return WRONG; + } + + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = SECSPERMIN - 1; + } + else + { + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + } + + /* Do a binary search (this works whatever time_t's type is). */ + lo = _PDCLIB_TIME_MIN; + hi = _PDCLIB_TIME_MAX; + + for ( ; ; ) + { + t = lo / 2 + hi / 2; + + if ( t < lo ) + { + t = lo; + } + else if ( t > hi ) + { + t = hi; + } + + if ( ! funcp( sp, &t, offset, &mytm ) ) + { + /* Assume that t is too extreme to be represented in + a struct tm; arrange things so that it is less + extreme on the next pass. + */ + dir = ( t > 0 ) ? 1 : -1; + } + else + { + dir = tmcomp( &mytm, &yourtm ); + } + + if ( dir != 0 ) + { + if ( t == lo ) + { + if ( t == _PDCLIB_TIME_MAX ) + { + return WRONG; + } + + ++t; + ++lo; + } + else if ( t == hi ) + { + if ( t == _PDCLIB_TIME_MIN ) + { + return WRONG; + } + + --t; + --hi; + } + + if ( lo > hi ) + { + return WRONG; + } + + if ( dir > 0 ) + { + hi = t; + } + else + { + lo = t; + } + + continue; + } + +#if defined TM_GMTOFF && ! UNINIT_TRAP + if ( mytm.TM_GMTOFF != yourtm.TM_GMTOFF + && ( yourtm.TM_GMTOFF < 0 + ? ( -SECSPERDAY <= yourtm.TM_GMTOFF + && ( mytm.TM_GMTOFF <= + ( SMALLEST ( _PDCLIB_INT_FAST32_MAX, _PDCLIB_LONG_MAX ) + + yourtm.TM_GMTOFF ) ) ) + : ( yourtm.TM_GMTOFF <= SECSPERDAY + && ( ( BIGGEST ( _PDCLIB_INT_FAST32_MIN, _PDCLIB_LONG_MIN ) + + yourtm.TM_GMTOFF ) + <= mytm.TM_GMTOFF ) ) ) ) + { + /* MYTM matches YOURTM except with the wrong UT offset. + YOURTM.TM_GMTOFF is plausible, so try it instead. + It's OK if YOURTM.TM_GMTOFF contains uninitialized data, + since the guess gets checked. + */ + time_t altt = t; + int_fast32_t diff = mytm.TM_GMTOFF - yourtm.TM_GMTOFF; + + if ( ! increment_overflow_time( &altt, diff ) ) + { + struct tm alttm; + if ( funcp( sp, &altt, offset, &alttm ) + && alttm.tm_isdst == mytm.tm_isdst + && alttm.TM_GMTOFF == yourtm.TM_GMTOFF + && tmcomp( &alttm, &yourtm ) == 0 ) + { + t = altt; + mytm = alttm; + } + } + } +#endif + + if ( yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst ) + { + break; + } + + /* Right time, wrong type. + Hunt for right time, right type. + It's okay to guess wrong since the guess + gets checked. + */ + if ( sp == NULL ) + { + return WRONG; + } + + for ( i = sp->typecnt - 1; i >= 0; --i ) + { + if ( sp->ttis[ i ].isdst != yourtm.tm_isdst ) + { + continue; + } + + for ( j = sp->typecnt - 1; j >= 0; --j ) + { + if ( sp->ttis[ j ].isdst == yourtm.tm_isdst ) + { + continue; + } + + newt = ( t + sp->ttis[ j ].utoff - sp->ttis[ i ].utoff ); + + if ( ! funcp( sp, &newt, offset, &mytm ) ) + { + continue; + } + + if ( tmcomp( &mytm, &yourtm ) != 0 ) + { + continue; + } + + if ( mytm.tm_isdst != yourtm.tm_isdst ) + { + continue; + } + + /* We have a match. */ + t = newt; + goto label; + } + } + + return WRONG; + } + +label: + newt = t + saved_seconds; + + if ( ( newt < t ) != ( saved_seconds < 0 ) ) + { + return WRONG; + } + + t = newt; + + if ( funcp( sp, &t, offset, tmp ) ) + { + *okayp = true; + } + + return t; +} + +static time_t time2( struct tm * tmp, struct tm *(*funcp)( struct state const *, time_t const *, int_fast32_t, struct tm * ), struct state const * sp, const int_fast32_t offset, bool * okayp ) +{ + time_t t; + + /* First try without normalization of seconds + (in case tm_sec contains a value associated with a leap second). + If that fails, try with normalization of seconds. + */ + t = time2sub( tmp, funcp, sp, offset, okayp, false ); + return *okayp ? t : time2sub( tmp, funcp, sp, offset, okayp, true ); +} + +static time_t time1( struct tm * tmp, struct tm *(*funcp)( struct state const *, time_t const *, int_fast32_t, struct tm * ), struct state const * sp, const int_fast32_t offset ) +{ + time_t t; + int samei, otheri; + int sameind, otherind; + int i; + int nseen; + char seen[TZ_MAX_TYPES]; + unsigned char types[TZ_MAX_TYPES]; + bool okay; + + if ( tmp == NULL ) + { + *_PDCLIB_errno_func() = _PDCLIB_EINVAL; + return WRONG; + } + + if ( tmp->tm_isdst > 1 ) + { + tmp->tm_isdst = 1; + } + + t = time2( tmp, funcp, sp, offset, &okay ); + + if ( okay ) + { + return t; + } + + if ( tmp->tm_isdst < 0 ) + { +#ifdef PCTS + /* POSIX Conformance Test Suite code courtesy Grant Sullivan. */ + tmp->tm_isdst = 0; /* reset to std and try again */ +#else + return t; +#endif + } + + /* We're supposed to assume that somebody took a time of one type + and did some math on it that yielded a "struct tm" that's bad. + We try to divine the type they started from and adjust to the + type they need. + */ + if ( sp == NULL ) + { + return WRONG; + } + + for ( i = 0; i < sp->typecnt; ++i ) + { + seen[ i ] = false; + } + + nseen = 0; + + for ( i = sp->timecnt - 1; i >= 0; --i ) + { + if ( ! seen[ sp->types[ i ] ] ) + { + seen[ sp->types[ i ] ] = true; + types[ nseen++ ] = sp->types[ i ]; + } + } + + for ( sameind = 0; sameind < nseen; ++sameind ) + { + samei = types[ sameind ]; + + if ( sp->ttis[ samei ].isdst != tmp->tm_isdst ) + { + continue; + } + + for ( otherind = 0; otherind < nseen; ++otherind ) + { + otheri = types[ otherind ]; + + if ( sp->ttis[ otheri ].isdst == tmp->tm_isdst ) + { + continue; + } + + tmp->tm_sec += ( sp->ttis[ otheri ].utoff - sp->ttis[ samei ].utoff ); + tmp->tm_isdst = ! tmp->tm_isdst; + t = time2( tmp, funcp, sp, offset, &okay ); + + if ( okay ) + { + return t; + } + + tmp->tm_sec -= ( sp->ttis[ otheri ].utoff - sp->ttis[ samei ].utoff ); + tmp->tm_isdst = ! tmp->tm_isdst; + } + } + + return WRONG; +} + +time_t _PDCLIB_mktime_tzname( struct state * sp, struct tm * tmp, bool setname ) +{ + if ( sp ) + { + return time1( tmp, _PDCLIB_localsub, sp, setname ); + } + else + { + _PDCLIB_gmtcheck(); + return time1( tmp, _PDCLIB_gmtsub, &_PDCLIB_gmtmem, 0 ); + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_timesub.c b/rocklibc/src/_tzcode/_PDCLIB_timesub.c new file mode 100644 index 0000000..d1b5136 --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_timesub.c @@ -0,0 +1,190 @@ +/* _PDCLIB_timesub( const time_t *, int_fast32_t, const struct state *, struct tm * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +/* Return the number of leap years through the end of the given year + where, to make the math easy, the answer for year zero is defined as zero. +*/ +static int leaps_thru_end_of_nonneg( int y ) +{ + return y / 4 - y / 100 + y / 400; +} + +static int leaps_thru_end_of( const int y ) +{ + return ( y < 0 + ? -1 - leaps_thru_end_of_nonneg( -1 - y ) + : leaps_thru_end_of_nonneg( y ) ); +} + +struct tm * _PDCLIB_timesub( const time_t * timep, int_fast32_t offset, const struct state * sp, struct tm * tmp ) +{ + const struct lsinfo * lp; + time_t tdays; + int idays; /* unsigned would be so 2003 */ + int_fast64_t rem; + int y; + const int * ip; + int_fast64_t corr; + bool hit; + int i; + + corr = 0; + hit = false; + i = ( sp == NULL ) ? 0 : sp->leapcnt; + + while ( --i >= 0 ) + { + lp = &sp->lsis[ i ]; + if ( *timep >= lp->trans ) + { + corr = lp->corr; + hit = ( *timep == lp->trans && ( i == 0 ? 0 : lp[ -1 ].corr ) < corr ); + break; + } + } + + y = EPOCH_YEAR; + tdays = *timep / SECSPERDAY; + rem = *timep % SECSPERDAY; + + while ( tdays < 0 || tdays >= year_lengths[ _PDCLIB_is_leap( y ) ] ) + { + int newy; + time_t tdelta; + int idelta; + int leapdays; + + tdelta = tdays / DAYSPERLYEAR; + + if ( ! ( ( ! _PDCLIB_TYPE_SIGNED( time_t ) || _PDCLIB_INT_MIN <= tdelta ) && tdelta <= _PDCLIB_INT_MAX ) ) + { + goto out_of_range; + } + + idelta = tdelta; + + if ( idelta == 0 ) + { + idelta = ( tdays < 0 ) ? -1 : 1; + } + + newy = y; + + if ( _PDCLIB_increment_overflow( &newy, idelta ) ) + { + goto out_of_range; + } + + leapdays = leaps_thru_end_of( newy - 1 ) - leaps_thru_end_of( y - 1 ); + tdays -= ( (time_t)newy - y ) * DAYSPERNYEAR; + tdays -= leapdays; + y = newy; + } + + /* Given the range, we can now fearlessly cast... */ + idays = tdays; + rem += offset - corr; + + while ( rem < 0 ) + { + rem += SECSPERDAY; + --idays; + } + + while ( rem >= SECSPERDAY ) + { + rem -= SECSPERDAY; + ++idays; + } + + while ( idays < 0 ) + { + if ( _PDCLIB_increment_overflow( &y, -1 ) ) + { + goto out_of_range; + } + + idays += year_lengths[ _PDCLIB_is_leap( y ) ]; + } + + while ( idays >= year_lengths[ _PDCLIB_is_leap( y ) ] ) + { + idays -= year_lengths[ _PDCLIB_is_leap( y ) ]; + + if ( _PDCLIB_increment_overflow( &y, 1 ) ) + { + goto out_of_range; + } + } + + tmp->tm_year = y; + + if ( _PDCLIB_increment_overflow( &tmp->tm_year, -TM_YEAR_BASE ) ) + { + goto out_of_range; + } + + tmp->tm_yday = idays; + /* The "extra" mods below avoid overflow problems. */ + tmp->tm_wday = EPOCH_WDAY + + ( ( y - EPOCH_YEAR ) % DAYSPERWEEK ) * + ( DAYSPERNYEAR % DAYSPERWEEK ) + + leaps_thru_end_of( y - 1 ) - + leaps_thru_end_of( EPOCH_YEAR - 1 ) + + idays; + tmp->tm_wday %= DAYSPERWEEK; + + if ( tmp->tm_wday < 0 ) + { + tmp->tm_wday += DAYSPERWEEK; + } + + tmp->tm_hour = (int)( rem / SECSPERHOUR ); + rem %= SECSPERHOUR; + tmp->tm_min = (int)( rem / SECSPERMIN ); + + /* A positive leap second requires a special + representation. This uses "... ??:59:60" et seq. + */ + tmp->tm_sec = (int) ( rem % SECSPERMIN ) + hit; + ip = mon_lengths[ _PDCLIB_is_leap( y ) ]; + + for ( tmp->tm_mon = 0; idays >= ip[ tmp->tm_mon ]; ++( tmp->tm_mon ) ) + { + idays -= ip[ tmp->tm_mon ]; + } + + tmp->tm_mday = (int)( idays + 1 ); + tmp->tm_isdst = 0; +#ifdef TM_GMTOFF + tmp->TM_GMTOFF = offset; +#endif /* defined TM_GMTOFF */ + return tmp; + + out_of_range: + *_PDCLIB_errno_func() = _PDCLIB_EOVERFLOW; + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_tzload.c b/rocklibc/src/_tzcode/_PDCLIB_tzload.c new file mode 100644 index 0000000..5e7e0cc --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_tzload.c @@ -0,0 +1,683 @@ +/* _PDCLIB_tzload( char const *, struct _PDCLIB_timezone *, bool ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +#include +#include +#include + +static int_fast32_t detzcode( const char * codep ) +{ + int_fast32_t result; + int i; + int_fast32_t one = 1; + int_fast32_t halfmaxval = one << ( 32 - 2 ); + int_fast32_t maxval = halfmaxval - 1 + halfmaxval; + int_fast32_t minval = -1 - maxval; + + result = codep[ 0 ] & 0x7f; + + for ( i = 1; i < 4; ++i ) + { + result = ( result << 8 ) | ( codep[ i ] & 0xff ); + } + + if ( codep[ 0 ] & 0x80 ) + { + /* Do two's-complement negation even on non-two's-complement machines. + If the result would be minval - 1, return minval. + */ + result -= ! _PDCLIB_TWOS_COMPLEMENT && result != 0; + result += minval; + } + + return result; +} + +static int_fast64_t detzcode64( const char * codep ) +{ + uint_fast64_t result; + int i; + int_fast64_t one = 1; + int_fast64_t halfmaxval = one << ( 64 - 2 ); + int_fast64_t maxval = halfmaxval - 1 + halfmaxval; + int_fast64_t minval = - _PDCLIB_TWOS_COMPLEMENT - maxval; + + result = codep[ 0 ] & 0x7f; + + for ( i = 1; i < 8; ++i ) + { + result = ( result << 8 ) | ( codep[ i ] & 0xff ); + } + + if ( codep[ 0 ] & 0x80 ) + { + /* Do two's-complement negation even on non-two's-complement machines. + If the result would be minval - 1, return minval. + */ + result -= ! _PDCLIB_TWOS_COMPLEMENT && result != 0; + result += minval; + } + + return result; +} + +static bool differ_by_repeat( const time_t t1, const time_t t0 ) +{ + if ( ( sizeof( time_t ) * _PDCLIB_CHAR_BIT ) - _PDCLIB_TYPE_SIGNED( time_t ) < SECSPERREPEAT_BITS ) + { + return 0; + } + + return ( t1 - t0 ) == SECSPERREPEAT; +} + +static bool typesequiv( const struct state * sp, int a, int b ) +{ + bool result; + + if ( sp == NULL || + a < 0 || a >= sp->typecnt || + b < 0 || b >= sp->typecnt ) + { + result = false; + } + else + { + const struct ttinfo * ap = &sp->ttis[ a ]; + const struct ttinfo * bp = &sp->ttis[ b ]; + + result = ( ap->utoff == bp->utoff && + ap->isdst == bp->isdst && + ap->ttisstd == bp->ttisstd && + ap->ttisut == bp->ttisut && + ( strcmp( &sp->chars[ ap->desigidx ], &sp->chars[ bp->desigidx ] ) == 0 ) + ); + } + + return result; +} + +#define TZ_MAGIC "TZif" + +struct tzhead +{ + char tzh_magic[ 4 ]; /* TZ_MAGIC */ + char tzh_version[ 1 ]; /* '\0' or '2' or '3' as of 2013 */ + char tzh_reserved[ 15 ]; /* reserved; must be zero */ + char tzh_ttisutcnt[ 4 ]; /* coded number of trans. time flags */ + char tzh_ttisstdcnt[ 4 ]; /* coded number of trans. time flags */ + char tzh_leapcnt[ 4 ]; /* coded number of leap seconds */ + char tzh_timecnt[ 4 ]; /* coded number of transition times */ + char tzh_typecnt[ 4 ]; /* coded number of local time types */ + char tzh_charcnt[ 4 ]; /* coded number of abbr. chars */ +}; + +/* Input buffer for data read from a compiled tz file. */ +union input_buffer +{ + /* The first part of the buffer, interpreted as a header. */ + struct tzhead tzhead; + + /* The entire buffer. */ + char buf[ 2 * sizeof ( struct tzhead ) + 2 * sizeof ( struct state ) + 4 * TZ_MAX_TIMES ]; +}; + +/* _PDCLIB_TZDIR with a trailing '/' rather than a trailing '\0'. */ +static char const tzdirslash[ sizeof _PDCLIB_TZDIR + 1 ] = _PDCLIB_TZDIR "/"; + +/* Local storage needed for 'tzloadbody'. */ +union local_storage +{ + /* The results of analyzing the file's contents after it is opened. */ + struct file_analysis + { + /* The input buffer. */ + union input_buffer u; + + /* A temporary state used for parsing a TZ string in the file. */ + struct state st; + } u; + + /* The file name to be opened. */ + char fullname[ BIGGEST ( sizeof ( struct file_analysis ), sizeof tzdirslash + 1024 ) ]; +}; + +static int_fast64_t leapcorr( struct state const * sp, time_t t ) +{ + struct lsinfo const * lp; + int i; + + i = sp->leapcnt; + + while ( --i >= 0 ) + { + lp = &sp->lsis[ i ]; + + if ( t >= lp->trans ) + { + return lp->corr; + } + } + + return 0; +} + +/* Load tz data from the file named NAME into *SP. Read extended + format if DOEXTEND. Use *LSP for temporary storage. Return 0 on + success, an errno value on failure. */ +static int tzloadbody( char const * name, struct state * sp, bool doextend, union local_storage * lsp ) +{ + int i; + FILE * fid; + int stored; + size_t nread; + bool doaccess; + union input_buffer * up = &lsp->u.u; + size_t tzheadsize = sizeof ( struct tzhead ); + + sp->goback = sp->goahead = false; + + if ( ! name ) + { + name = _PDCLIB_TZDEFAULT; + + if ( ! name ) + { + return _PDCLIB_EINVAL; + } + } + + if ( name[ 0 ] == ':' ) + { + ++name; + } + + doaccess = name[ 0 ] == '/'; + + if ( ! doaccess ) + { + char const * dot; + size_t namelen = strlen( name ); + + if ( sizeof lsp->fullname - sizeof tzdirslash <= namelen ) + { + return _PDCLIB_ENAMETOOLONG; + } + + /* Create a string "TZDIR/NAME". Using sprintf here + would pull in stdio (and would fail if the + resulting string length exceeded INT_MAX!). + */ + memcpy( lsp->fullname, tzdirslash, sizeof tzdirslash ); + strcpy( lsp->fullname + sizeof tzdirslash, name ); + + /* Set doaccess if NAME contains a ".." file name + component, as such a name could read a file outside + the TZDIR virtual subtree. + */ + for ( dot = name; ( dot = strchr( dot, '.' ) ); ++dot ) + { + if ( ( dot == name || dot[ -1 ] == '/' ) && dot[ 1 ] == '.' && ( dot[ 2 ] == '/' || ! dot[ 2 ] ) ) + { + doaccess = true; + break; + } + } + + name = lsp->fullname; + } + + fid = fopen( name, "rb" ); + + if ( fid == NULL ) + { + return errno; + } + + nread = fread( up->buf, 1, sizeof up->buf, fid ); + + if ( nread < tzheadsize ) + { + int err = errno; + + if ( ! ferror( fid ) ) + { + err = _PDCLIB_EINVAL; + } + + fclose( fid ); + return err; + } + + if ( fclose( fid ) == EOF ) + { + return errno; + } + + for ( stored = 4; stored <= 8; stored *= 2 ) + { + int_fast32_t ttisstdcnt = detzcode( up->tzhead.tzh_ttisstdcnt ); + int_fast32_t ttisutcnt = detzcode( up->tzhead.tzh_ttisutcnt ); + int_fast64_t prevtr = 0; + int_fast32_t prevcorr = 0; + int_fast32_t leapcnt = detzcode( up->tzhead.tzh_leapcnt ); + int_fast32_t timecnt = detzcode( up->tzhead.tzh_timecnt ); + int_fast32_t typecnt = detzcode( up->tzhead.tzh_typecnt ); + int_fast32_t charcnt = detzcode( up->tzhead.tzh_charcnt ); + char const *p = up->buf + tzheadsize; + /* Although tzfile(5) currently requires typecnt to be nonzero, + support future formats that may allow zero typecnt + in files that have a TZ string and no transitions. + */ + if ( ! ( 0 <= leapcnt && leapcnt < TZ_MAX_LEAPS + && 0 <= typecnt && typecnt < TZ_MAX_TYPES + && 0 <= timecnt && timecnt < TZ_MAX_TIMES + && 0 <= charcnt && charcnt < TZ_MAX_CHARS + && ( ttisstdcnt == typecnt || ttisstdcnt == 0 ) + && ( ttisutcnt == typecnt || ttisutcnt == 0 ) ) ) + { + return _PDCLIB_EINVAL; + } + + if ( nread + < ( tzheadsize /* struct tzhead */ + + timecnt * stored /* ats */ + + timecnt /* types */ + + typecnt * 6 /* ttinfos */ + + charcnt /* chars */ + + leapcnt * ( stored + 4 ) /* lsinfos */ + + ttisstdcnt /* ttisstds */ + + ttisutcnt ) ) /* ttisuts */ + { + return _PDCLIB_EINVAL; + } + + sp->leapcnt = leapcnt; + sp->timecnt = timecnt; + sp->typecnt = typecnt; + sp->charcnt = charcnt; + + /* Read transitions, discarding those out of time_t range. + But pretend the last transition before _PDCLIB_TIME_MIN + occurred at _PDCLIB_TIME_MIN. + */ + timecnt = 0; + + for ( i = 0; i < sp->timecnt; ++i ) + { + int_fast64_t at = stored == 4 ? detzcode( p ) : detzcode64( p ); + sp->types[ i ] = at <= _PDCLIB_TIME_MAX; + + if ( sp->types[ i ] ) + { + time_t attime = ( ( _PDCLIB_TYPE_SIGNED( time_t ) ? at < _PDCLIB_TIME_MIN : at < 0 ) ? _PDCLIB_TIME_MIN : at ); + + if ( timecnt && attime <= sp->ats[ timecnt - 1 ] ) + { + if ( attime < sp->ats[ timecnt - 1 ] ) + { + return _PDCLIB_EINVAL; + } + + sp->types[ i - 1 ] = 0; + timecnt--; + } + + sp->ats[ timecnt++ ] = attime; + } + + p += stored; + } + + timecnt = 0; + + for ( i = 0; i < sp->timecnt; ++i ) + { + unsigned char typ = *p++; + + if ( sp->typecnt <= typ ) + { + return _PDCLIB_EINVAL; + } + + if ( sp->types[ i ] ) + { + sp->types[ timecnt++ ] = typ; + } + } + + sp->timecnt = timecnt; + + for ( i = 0; i < sp->typecnt; ++i ) + { + struct ttinfo * ttisp; + unsigned char isdst, desigidx; + + ttisp = &sp->ttis[ i ]; + ttisp->utoff = detzcode( p ); + p += 4; + isdst = *p++; + + if ( ! ( isdst < 2 ) ) + { + return _PDCLIB_EINVAL; + } + + ttisp->isdst = isdst; + desigidx = *p++; + + if ( ! ( desigidx < sp->charcnt ) ) + { + return _PDCLIB_EINVAL; + } + + ttisp->desigidx = desigidx; + } + + for ( i = 0; i < sp->charcnt; ++i ) + { + sp->chars[ i ] = *p++; + } + + sp->chars[ i ] = '\0'; /* ensure '\0' at end */ + + /* Read leap seconds, discarding those out of time_t range. */ + leapcnt = 0; + + for ( i = 0; i < sp->leapcnt; ++i ) + { + int_fast64_t tr = stored == 4 ? detzcode( p ) : detzcode64( p ); + int_fast32_t corr = detzcode( p + stored ); + p += stored + 4; + + /* Leap seconds cannot occur before the Epoch. */ + if ( tr < 0 ) + { + return _PDCLIB_EINVAL; + } + + if ( tr <= _PDCLIB_TIME_MAX ) + { + /* Leap seconds cannot occur more than once per UTC month, + and UTC months are at least 28 days long (minus 1 + second for a negative leap second). Each leap second's + correction must differ from the previous one's by 1 + second. + */ + if ( tr - prevtr < 28 * SECSPERDAY - 1 || ( corr != prevcorr - 1 && corr != prevcorr + 1 ) ) + { + return _PDCLIB_EINVAL; + } + + sp->lsis[ leapcnt ].trans = prevtr = tr; + sp->lsis[ leapcnt ].corr = prevcorr = corr; + ++leapcnt; + } + } + + sp->leapcnt = leapcnt; + + for ( i = 0; i < sp->typecnt; ++i ) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[ i ]; + + if ( ttisstdcnt == 0 ) + { + ttisp->ttisstd = false; + } + else + { + if ( *p != true && *p != false ) + { + return _PDCLIB_EINVAL; + } + + ttisp->ttisstd = *p++; + } + } + + for ( i = 0; i < sp->typecnt; ++i ) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[ i ]; + + if ( ttisutcnt == 0 ) + { + ttisp->ttisut = false; + } + else + { + if ( *p != true && *p != false ) + { + return _PDCLIB_EINVAL; + } + + ttisp->ttisut = *p++; + } + } + + /* If this is an old file, we're done. */ + if ( up->tzhead.tzh_version[ 0 ] == '\0' ) + { + break; + } + + nread -= p - up->buf; + memmove( up->buf, p, nread ); + } + + if ( doextend && nread > 2 && up->buf[ 0 ] == '\n' && up->buf[ nread - 1 ] == '\n' && sp->typecnt + 2 <= TZ_MAX_TYPES ) + { + struct state *ts = &lsp->u.st; + + up->buf[ nread - 1 ] = '\0'; + + if ( _PDCLIB_tzparse( &up->buf[ 1 ], ts, false ) ) + { + /* Attempt to reuse existing abbreviations. + Without this, America/Anchorage would be right on + the edge after 2037 when TZ_MAX_CHARS is 50, as + sp->charcnt equals 40 (for LMT AST AWT APT AHST + AHDT YST AKDT AKST) and ts->charcnt equals 10 + (for AKST AKDT). Reusing means sp->charcnt can + stay 40 in this example. */ + int gotabbr = 0; + int charcnt = sp->charcnt; + + for ( i = 0; i < ts->typecnt; ++i ) + { + char * tsabbr = ts->chars + ts->ttis[ i ].desigidx; + int j; + + for ( j = 0; j < charcnt; ++j ) + { + if ( strcmp( sp->chars + j, tsabbr ) == 0 ) + { + ts->ttis[ i ].desigidx = j; + ++gotabbr; + break; + } + } + + if ( ! ( j < charcnt ) ) + { + int tsabbrlen = strlen( tsabbr ); + + if ( j + tsabbrlen < TZ_MAX_CHARS ) + { + strcpy( sp->chars + j, tsabbr ); + charcnt = j + tsabbrlen + 1; + ts->ttis[ i ].desigidx = j; + ++gotabbr; + } + } + } + + if ( gotabbr == ts->typecnt ) + { + sp->charcnt = charcnt; + + /* Ignore any trailing, no-op transitions generated + by zic as they don't help here and can run afoul + of bugs in zic 2016j or earlier. */ + while ( 1 < sp->timecnt && ( sp->types[ sp->timecnt - 1 ] == sp->types[ sp->timecnt - 2 ] ) ) + { + sp->timecnt--; + } + + for ( i = 0; i < ts->timecnt; ++i ) + { + if ( sp->timecnt == 0 || ( sp->ats[ sp->timecnt - 1 ] < ts->ats[ i ] + leapcorr( sp, ts->ats[ i ] ) ) ) + { + break; + } + } + + while ( i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES ) + { + sp->ats[ sp->timecnt ] = ts->ats[ i ] + leapcorr( sp, ts->ats[ i ] ); + sp->types[ sp->timecnt ] = ( sp->typecnt + ts->types[ i ] ); + sp->timecnt++; + ++i; + } + + for ( i = 0; i < ts->typecnt; ++i ) + { + sp->ttis[ sp->typecnt++ ] = ts->ttis[ i ]; + } + } + } + } + + if ( sp->typecnt == 0 ) + { + return _PDCLIB_EINVAL; + } + + if ( sp->timecnt > 1 ) + { + for ( i = 1; i < sp->timecnt; ++i ) + { + if ( typesequiv( sp, sp->types[ i ], sp->types[ 0 ] ) && differ_by_repeat( sp->ats[ i ], sp->ats[ 0 ] ) ) + { + sp->goback = true; + break; + } + } + + for ( i = sp->timecnt - 2; i >= 0; --i ) + { + if ( typesequiv( sp, sp->types[ sp->timecnt - 1 ], sp->types[ i ] ) && differ_by_repeat( sp->ats[ sp->timecnt - 1 ], sp->ats[ i ] ) ) + { + sp->goahead = true; + break; + } + } + } + + /* Infer sp->defaulttype from the data. Although this default + type is always zero for data from recent tzdb releases, + things are trickier for data from tzdb 2018e or earlier. + + The first set of heuristics work around bugs in 32-bit data + generated by tzdb 2013c or earlier. The workaround is for + zones like Australia/Macquarie where timestamps before the + first transition have a time type that is not the earliest + standard-time type. See: + https://mm.icann.org/pipermail/tz/2013-May/019368.html + */ + /* If type 0 is unused in transitions, it's the type to use for early times. */ + for ( i = 0; i < sp->timecnt; ++i ) + { + if ( sp->types[ i ] == 0 ) + { + break; + } + } + + i = i < sp->timecnt ? -1 : 0; + + /* Absent the above, + if there are transition times + and the first transition is to a daylight time + find the standard type less than and closest to + the type of the first transition. + */ + if ( i < 0 && sp->timecnt > 0 && sp->ttis[ sp->types[ 0 ] ].isdst ) + { + i = sp->types[ 0 ]; + + while ( --i >= 0 ) + { + if ( ! sp->ttis[ i ].isdst ) + { + break; + } + } + } + + /* The next heuristics are for data generated by tzdb 2018e or + earlier, for zones like EST5EDT where the first transition + is to DST. + */ + /* If no result yet, find the first standard type. + If there is none, punt to type zero. + */ + if ( i < 0 ) + { + i = 0; + + while ( sp->ttis[ i ].isdst ) + { + if ( ++i >= sp->typecnt ) + { + i = 0; + break; + } + } + } + + /* A simple 'sp->defaulttype = 0;' would suffice here if we + didn't have to worry about 2018e-or-earlier data. Even + simpler would be to remove the defaulttype member and just + use 0 in its place. + */ + sp->defaulttype = i; + + return 0; +} + +/* Load tz data from the file named NAME into *SP. Read extended + format if DOEXTEND. Return 0 on success, an errno value on failure. +*/ +int _PDCLIB_tzload( char const * name, struct state * sp, bool doextend ) +{ + union local_storage ls; + return tzloadbody( name, sp, doextend, &ls ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_tzparse.c b/rocklibc/src/_tzcode/_PDCLIB_tzparse.c new file mode 100644 index 0000000..d139bf5 --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_tzparse.c @@ -0,0 +1,775 @@ +/* _PDCLIB_tzparse( char const *, struct _PDCLIB_timezone *, bool ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +#include +#include + +/* The DST rules to use if TZ has no rules and we can't load TZDEFRULES. + Default to US rules as of 2017-05-07. + POSIX does not specify the default DST rules; + for historical reasons, US rules are a common default. +*/ +#ifndef TZDEFRULESTRING +#define TZDEFRULESTRING ",M3.2.0,M11.1.0" +#endif + +#ifndef TZDEFRULES +#define TZDEFRULES "posixrules" +#endif + +enum rule_t +{ + JULIAN_DAY, /* Jn = Julian day */ + DAY_OF_YEAR, /* n = day of year */ + MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */ +}; + +struct rule +{ + enum rule_t type; /* type of rule */ + int day; /* day number of rule */ + int week; /* week number of rule */ + int mon; /* month number of rule */ + int_fast32_t time; /* transition time of rule */ +}; + +/* Given a pointer into a timezone string, extract a number from that string. + Check that the number is within a specified range; if it is not, return + NULL. + Otherwise, return a pointer to the first character not part of the number. +*/ +static const char * getnum( const char * strp, int * nump, int min, int max ) +{ + char c; + int num; + + if ( strp == NULL || ! isdigit( (unsigned char)( c = *strp ) ) ) + { + return NULL; + } + + num = 0; + + do + { + num = num * 10 + ( c - '0' ); + + if ( num > max ) + { + return NULL; /* illegal value */ + } + + c = *++strp; + } while ( isdigit( (unsigned char)c ) ); + + if ( num < min ) + { + return NULL; /* illegal value */ + } + + *nump = num; + return strp; +} + +/* Given a pointer into a timezone string, extract a number of seconds, + in hh[:mm[:ss]] form, from the string. + If any error occurs, return NULL. + Otherwise, return a pointer to the first character not part of the number + of seconds. +*/ +static const char * getsecs( const char * strp, int_fast32_t * secsp ) +{ + int num; + + /* 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like + "M10.4.6/26", which does not conform to Posix, + but which specifies the equivalent of + "02:00 on the first Sunday on or after 23 Oct". + */ + strp = getnum( strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1 ); + + if ( strp == NULL ) + { + return NULL; + } + + *secsp = num * (int_fast32_t) SECSPERHOUR; + + if ( *strp == ':' ) + { + ++strp; + strp = getnum( strp, &num, 0, MINSPERHOUR - 1 ); + + if ( strp == NULL ) + { + return NULL; + } + + *secsp += num * SECSPERMIN; + + if ( *strp == ':' ) + { + ++strp; + /* 'SECSPERMIN' allows for leap seconds. */ + strp = getnum( strp, &num, 0, SECSPERMIN ); + + if ( strp == NULL ) + { + return NULL; + } + + *secsp += num; + } + } + + return strp; +} + +/* Given a pointer into a timezone string, extract an offset, in + [+-]hh[:mm[:ss]] form, from the string. + If any error occurs, return NULL. + Otherwise, return a pointer to the first character not part of the time. +*/ +static const char * getoffset( const char * strp, int_fast32_t * offsetp ) +{ + bool neg = false; + + if ( *strp == '-' ) + { + neg = true; + ++strp; + } + else if ( *strp == '+' ) + { + ++strp; + } + + strp = getsecs( strp, offsetp ); + + if ( strp == NULL ) + { + return NULL; /* illegal time */ + } + + if ( neg ) + { + *offsetp = - *offsetp; + } + + return strp; +} + +/* Given a pointer into a timezone string, extract a rule in the form + date[/time]. See POSIX section 8 for the format of "date" and "time". + If a valid rule is not found, return NULL. + Otherwise, return a pointer to the first character not part of the rule. +*/ +static const char * getrule( const char * strp, struct rule * rulep ) +{ + if ( *strp == 'J' ) + { + /* Julian day. */ + rulep->type = JULIAN_DAY; + ++strp; + strp = getnum( strp, &rulep->day, 1, DAYSPERNYEAR ); + } + else if ( *strp == 'M' ) + { + /* Month, week, day. */ + rulep->type = MONTH_NTH_DAY_OF_WEEK; + ++strp; + strp = getnum( strp, &rulep->mon, 1, MONSPERYEAR ); + + if ( strp == NULL ) + { + return NULL; + } + + if ( *strp++ != '.' ) + { + return NULL; + } + + strp = getnum( strp, &rulep->week, 1, 5 ); + + if ( strp == NULL ) + { + return NULL; + } + + if ( *strp++ != '.' ) + { + return NULL; + } + + strp = getnum( strp, &rulep->day, 0, DAYSPERWEEK - 1 ); + } + else if ( isdigit( (unsigned char)*strp ) ) + { + /* Day of year. */ + rulep->type = DAY_OF_YEAR; + strp = getnum( strp, &rulep->day, 0, DAYSPERLYEAR - 1 ); + } + else + { + return NULL; /* invalid format */ + } + + if ( strp == NULL ) + { + return NULL; + } + + if ( *strp == '/' ) + { + /* Time specified. */ + ++strp; + strp = getoffset( strp, &rulep->time ); + } + else + { + rulep->time = 2 * SECSPERHOUR; /* default = 2:00:00 */ + } + + return strp; +} + +/* Given a year, a rule, and the offset from UT at the time that rule takes + effect, calculate the year-relative time that rule takes effect. +*/ +static int_fast32_t transtime( const int year, struct rule const * rulep, const int_fast32_t offset ) +{ + bool leapyear; + int_fast32_t value = 0; + int i; + int d; + int m1; + int yy0; + int yy1; + int yy2; + int dow; + + leapyear = _PDCLIB_is_leap( year ); + + switch ( rulep->type ) + { + case JULIAN_DAY: + /* Jn - Julian day, 1 == January 1, 60 == March 1 even in leap + years. + In non-leap years, or if the day number is 59 or less, just + add SECSPERDAY times the day number-1 to the time of + January 1, midnight, to get the day. + */ + value = ( rulep->day - 1 ) * SECSPERDAY; + + if ( leapyear && rulep->day >= 60 ) + { + value += SECSPERDAY; + } + + break; + + case DAY_OF_YEAR: + /* n - day of year. + Just add SECSPERDAY times the day number to the time of + January 1, midnight, to get the day. + */ + value = rulep->day * SECSPERDAY; + break; + + case MONTH_NTH_DAY_OF_WEEK: + /* Mm.n.d - nth "dth day" of month m. */ + + /* Use Zeller's Congruence to get day-of-week of first day of + month. + */ + m1 = ( rulep->mon + 9 ) % 12 + 1; + yy0 = ( rulep->mon <= 2 ) ? ( year - 1 ) : year; + yy1 = yy0 / 100; + yy2 = yy0 % 100; + dow = ( ( 26 * m1 - 2 ) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1 ) % 7; + + if ( dow < 0 ) + { + dow += DAYSPERWEEK; + } + + /* "dow" is the day-of-week of the first day of the month. Get + the day-of-month (zero-origin) of the first "dow" day of the + month. + */ + d = rulep->day - dow; + + if ( d < 0 ) + { + d += DAYSPERWEEK; + } + + for ( i = 1; i < rulep->week; ++i ) + { + if ( d + DAYSPERWEEK >= mon_lengths[ leapyear ][ rulep->mon - 1 ] ) + { + break; + } + + d += DAYSPERWEEK; + } + + /* "d" is the day-of-month (zero-origin) of the day we want. */ + value = d * SECSPERDAY; + + for ( i = 0; i < rulep->mon - 1; ++i ) + { + value += mon_lengths[ leapyear ][ i ] * SECSPERDAY; + } + + break; + } + + /* "value" is the year-relative time of 00:00:00 UT on the day in + question. To get the year-relative time of the specified local + time on that day, add the transition time and the current offset + from UT. + */ + return value + rulep->time + offset; +} + +/* Given a pointer into a timezone string, scan until a character that is not + a valid character in a time zone abbreviation is found. + Return a pointer to that character. +*/ +static const char * getzname( const char * strp ) +{ + char c; + + while ( ( c = *strp ) != '\0' && ! isdigit( (unsigned char)c ) && c != ',' && c != '-' && c != '+' ) + { + ++strp; + } + + return strp; +} + +/* Given a pointer into an extended timezone string, scan until the ending + delimiter of the time zone abbreviation is located. + Return a pointer to the delimiter. + + As with getzname above, the legal character set is actually quite + restricted, with other characters producing undefined results. + We don't do any checking here; checking is done later in common-case code. +*/ +static const char * getqzname( const char *strp, const int delim ) +{ + int c; + + while ( ( c = *strp ) != '\0' && c != delim ) + { + ++strp; + } + + return strp; +} + +static bool increment_overflow_time( time_t * tp, int_fast32_t j ) +{ + /* This is like + 'if (! (_PDCLIB_TIME_MIN <= *tp + j && *tp + j <= _PDCLIB_TIME_MAX)) ...', + except that it does the right thing even if *tp + j would overflow. + */ + if ( ! ( j < 0 + ? ( _PDCLIB_TYPE_SIGNED( time_t ) ? _PDCLIB_TIME_MIN - j <= *tp : -1 - j < *tp ) + : *tp <= _PDCLIB_TIME_MAX - j ) ) + { + return true; + } + + *tp += j; + return false; +} + +/* Given a POSIX section 8-style TZ string, fill in the rule tables as + appropriate. +*/ +bool _PDCLIB_tzparse( const char * name, struct state * sp, bool lastditch ) +{ + const char * stdname; + const char * dstname; + size_t stdlen; + size_t dstlen; + size_t charcnt; + int_fast32_t stdoffset; + int_fast32_t dstoffset; + char * cp; + bool load_ok; + + stdname = name; + + if ( lastditch ) + { + stdlen = sizeof gmt - 1; + name += stdlen; + stdoffset = 0; + } + else + { + if ( *name == '<' ) + { + name++; + stdname = name; + name = getqzname( name, '>' ); + + if ( *name != '>' ) + { + return false; + } + + stdlen = name - stdname; + name++; + } + else + { + name = getzname( name ); + stdlen = name - stdname; + } + + if ( ! stdlen ) + { + return false; + } + + name = getoffset( name, &stdoffset ); + + if ( name == NULL ) + { + return false; + } + } + + charcnt = stdlen + 1; + + if ( sizeof sp->chars < charcnt ) + { + return false; + } + + load_ok = _PDCLIB_tzload( TZDEFRULES, sp, false ) == 0; + + if ( ! load_ok ) + { + sp->leapcnt = 0; /* so, we're off a little */ + } + + if ( *name != '\0' ) + { + if ( *name == '<' ) + { + dstname = ++name; + name = getqzname( name, '>' ); + + if ( *name != '>' ) + { + return false; + } + + dstlen = name - dstname; + name++; + } + else + { + dstname = name; + name = getzname( name ); + dstlen = name - dstname; /* length of DST abbr. */ + } + + if ( ! dstlen ) + { + return false; + } + + charcnt += dstlen + 1; + + if ( sizeof sp->chars < charcnt ) + { + return false; + } + + if ( *name != '\0' && *name != ',' && *name != ';' ) + { + name = getoffset( name, &dstoffset ); + + if ( name == NULL ) + { + return false; + } + } + else + { + dstoffset = stdoffset - SECSPERHOUR; + } + + if ( *name == '\0' && ! load_ok ) + { + name = TZDEFRULESTRING; + } + + if ( *name == ',' || *name == ';' ) + { + struct rule start; + struct rule end; + int year; + int yearlim; + int timecnt; + time_t janfirst; + int_fast32_t janoffset = 0; + int yearbeg; + + ++name; + + if ( ( name = getrule( name, &start ) ) == NULL ) + { + return false; + } + + if ( *name++ != ',' ) + { + return false; + } + + if ( ( name = getrule( name, &end ) ) == NULL ) + { + return false; + } + + if ( *name != '\0' ) + { + return false; + } + + sp->typecnt = 2; /* standard time and DST */ + /* Two transitions per year, from EPOCH_YEAR forward. */ + _PDCLIB_init_ttinfo( &sp->ttis[ 0 ], -stdoffset, false, 0 ); + _PDCLIB_init_ttinfo( &sp->ttis[ 1 ], -dstoffset, true, stdlen + 1 ); + sp->defaulttype = 0; + timecnt = 0; + janfirst = 0; + yearbeg = EPOCH_YEAR; + + do + { + int_fast32_t yearsecs = year_lengths[ _PDCLIB_is_leap( yearbeg - 1 ) ] * SECSPERDAY; + yearbeg--; + + if ( increment_overflow_time( &janfirst, -yearsecs ) ) + { + janoffset = -yearsecs; + break; + } + } while ( EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg ); + + yearlim = yearbeg + YEARSPERREPEAT + 1; + + for ( year = yearbeg; year < yearlim; year++ ) + { + int_fast32_t starttime = transtime( year, &start, stdoffset ), endtime = transtime( year, &end, dstoffset ); + int_fast32_t yearsecs = ( year_lengths[ _PDCLIB_is_leap( year ) ] * SECSPERDAY ); + bool reversed = endtime < starttime; + + if ( reversed ) + { + int_fast32_t swap = starttime; + starttime = endtime; + endtime = swap; + } + + if ( reversed + || ( starttime < endtime + && ( endtime - starttime + < ( yearsecs + + ( stdoffset - dstoffset ) ) ) ) ) + { + if ( TZ_MAX_TIMES - 2 < timecnt ) + { + break; + } + + sp->ats[ timecnt ] = janfirst; + + if ( ! increment_overflow_time( &sp->ats[ timecnt ], janoffset + starttime ) ) + { + sp->types[ timecnt++ ] = ! reversed; + } + + sp->ats[ timecnt ] = janfirst; + + if ( ! increment_overflow_time( &sp->ats[ timecnt ], janoffset + endtime ) ) + { + sp->types[ timecnt++ ] = reversed; + yearlim = year + YEARSPERREPEAT + 1; + } + } + + if ( increment_overflow_time ( &janfirst, janoffset + yearsecs ) ) + { + break; + } + + janoffset = 0; + } + + sp->timecnt = timecnt; + + if ( ! timecnt ) + { + sp->ttis[ 0 ] = sp->ttis[ 1 ]; + sp->typecnt = 1; /* Perpetual DST. */ + } + else if ( YEARSPERREPEAT < year - yearbeg ) + { + sp->goback = sp->goahead = true; + } + } + else + { + int_fast32_t theirstdoffset; + int_fast32_t theirdstoffset; + int_fast32_t theiroffset; + bool isdst; + int i; + int j; + + if ( *name != '\0' ) + { + return false; + } + + /* Initial values of theirstdoffset and theirdstoffset. */ + theirstdoffset = 0; + + for ( i = 0; i < sp->timecnt; ++i ) + { + j = sp->types[ i ]; + + if ( ! sp->ttis[ j ].isdst ) + { + theirstdoffset = - sp->ttis[ j ].utoff; + break; + } + } + + theirdstoffset = 0; + + for ( i = 0; i < sp->timecnt; ++i ) + { + j = sp->types[ i ]; + if ( sp->ttis[ j ].isdst ) + { + theirdstoffset = - sp->ttis[ j ].utoff; + break; + } + } + + /* Initially we're assumed to be in standard time. */ + isdst = false; + theiroffset = theirstdoffset; + + /* Now juggle transition times and types + tracking offsets as you do. + */ + for ( i = 0; i < sp->timecnt; ++i ) + { + j = sp->types[ i ]; + sp->types[ i ] = sp->ttis[ j ].isdst; + + if ( sp->ttis[ j ].ttisut ) + { + /* No adjustment to transition time */ + } + else + { + /* If daylight saving time is in + effect, and the transition time was + not specified as standard time, add + the daylight saving time offset to + the transition time; otherwise, add + the standard time offset to the + transition time. + */ + /* Transitions from DST to DDST + will effectively disappear since + POSIX provides for only one DST + offset. + */ + if ( isdst && ! sp->ttis[ j ].ttisstd ) + { + sp->ats[ i ] += dstoffset - theirdstoffset; + } + else + { + sp->ats[ i ] += stdoffset - theirstdoffset; + } + } + + theiroffset = -sp->ttis[ j ].utoff; + if ( sp->ttis[ j ].isdst ) + { + theirdstoffset = theiroffset; + } + else + { + theirstdoffset = theiroffset; + } + } + + /* Finally, fill in ttis. */ + _PDCLIB_init_ttinfo( &sp->ttis[ 0 ], -stdoffset, false, 0 ); + _PDCLIB_init_ttinfo( &sp->ttis[ 1 ], -dstoffset, true, stdlen + 1 ); + sp->typecnt = 2; + sp->defaulttype = 0; + } + } + else + { + dstlen = 0; + sp->typecnt = 1; /* only standard time */ + sp->timecnt = 0; + _PDCLIB_init_ttinfo( &sp->ttis[ 0 ], -stdoffset, false, 0 ); + sp->defaulttype = 0; + } + + sp->charcnt = charcnt; + cp = sp->chars; + memcpy( cp, stdname, stdlen ); + cp += stdlen; + *cp++ = '\0'; + + if ( dstlen != 0 ) + { + memcpy( cp, dstname, dstlen ); + *( cp + dstlen ) = '\0'; + } + + return true; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_tzset_unlocked.c b/rocklibc/src/_tzcode/_PDCLIB_tzset_unlocked.c new file mode 100644 index 0000000..fe0f53d --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_tzset_unlocked.c @@ -0,0 +1,185 @@ +/* _PDCLIB_tzset_unlocked( void ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +#include +#include + +#ifndef TZ_ABBR_MAX_LEN +#define TZ_ABBR_MAX_LEN 16 +#endif + +#ifndef TZ_ABBR_CHAR_SET +#define TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" +#endif + +#ifndef TZ_ABBR_ERR_CHAR +#define TZ_ABBR_ERR_CHAR '_' +#endif + +/* This string was in the Factory zone through version 2016f. */ +#define GRANDPARENTED "Local time zone must be set--see zic manual page" + +#ifndef TZ_STRLEN_MAX +#define TZ_STRLEN_MAX 255 +#endif + +static char lcl_TZname[ TZ_STRLEN_MAX + 1 ]; +int lcl_is_set = 0; + +static void scrub_abbrs( struct state * sp ) +{ + int i; + + /* First, replace bogus characters. */ + for ( i = 0; i < sp->charcnt; ++i ) + { + if ( strchr( TZ_ABBR_CHAR_SET, sp->chars[ i ] ) == NULL ) + { + sp->chars[ i ] = TZ_ABBR_ERR_CHAR; + } + } + + /* Second, truncate long abbreviations. */ + for ( i = 0; i < sp->typecnt; ++i ) + { + const struct ttinfo * const ttisp = &sp->ttis[ i ]; + char * cp = &sp->chars[ ttisp->desigidx ]; + + if ( strlen( cp ) > TZ_ABBR_MAX_LEN && strcmp( cp, GRANDPARENTED ) != 0 ) + { + *( cp + TZ_ABBR_MAX_LEN ) = '\0'; + } + } +} + +/* Initialize *SP to a value appropriate for the TZ setting NAME. + Return 0 on success, an errno value on failure. +*/ +static int zoneinit( struct state * sp, char const * name ) +{ + if (name && ! name[0]) + { + /* User wants it fast rather than right. */ + sp->leapcnt = 0; /* so, we're off a little */ + sp->timecnt = 0; + sp->typecnt = 0; + sp->charcnt = 0; + sp->goback = sp->goahead = false; + _PDCLIB_init_ttinfo( &sp->ttis[ 0 ], 0, false, 0 ); + strcpy( sp->chars, gmt ); + sp->defaulttype = 0; + return 0; + } + else + { + int err = _PDCLIB_tzload( name, sp, true ); + + if ( err != 0 && name && name[ 0 ] != ':' && _PDCLIB_tzparse( name, sp, false ) ) + { + err = 0; + } + + if ( err == 0 ) + { + scrub_abbrs( sp ); + } + + return err; + } +} + +static void settzname( void ) +{ + struct state * const sp = &_PDCLIB_lclmem; + int i; + +#if HAVE_TZNAME + tzname[ 0 ] = tzname[ 1 ] = (char *) ( sp ? wildabbr : gmt ); +#endif +#if USG_COMPAT + daylight = 0; + timezone = 0; +#endif +#if ALTZONE + altzone = 0; +#endif + if ( sp == NULL ) + { + return; + } + /* And to get the latest time zone abbreviations into tzname... */ + for ( i = 0; i < sp->typecnt; ++i ) + { + const struct ttinfo * const ttisp = &sp->ttis[ i ]; + _PDCLIB_update_tzname_etc( sp, ttisp ); + } + + for ( i = 0; i < sp->timecnt; ++i ) + { + const struct ttinfo * const ttisp = &sp->ttis[ sp->types[ i ] ]; + _PDCLIB_update_tzname_etc( sp, ttisp ); +#if USG_COMPAT + if ( ttisp->isdst ) + { + daylight = 1; + } +#endif + } +} + +static void tzsetlcl( char const * name ) +{ + struct state * sp = &_PDCLIB_lclmem; + int lcl = name ? strlen( name ) < sizeof lcl_TZname : -1; + + if ( lcl < 0 + ? lcl_is_set < 0 + : 0 < lcl_is_set && strcmp( lcl_TZname, name ) == 0 ) + { + return; + } + + if ( sp ) + { + if ( zoneinit( sp, name ) != 0 ) + { + zoneinit( sp, "" ); + } + + if ( 0 < lcl ) + { + strcpy( lcl_TZname, name ); + } + } + + settzname(); + lcl_is_set = lcl; +} + +void _PDCLIB_tzset_unlocked( void ) +{ + tzsetlcl( getenv( "TZ" ) ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/_tzcode/_PDCLIB_update_tzname_etc.c b/rocklibc/src/_tzcode/_PDCLIB_update_tzname_etc.c new file mode 100644 index 0000000..b54d4fa --- /dev/null +++ b/rocklibc/src/_tzcode/_PDCLIB_update_tzname_etc.c @@ -0,0 +1,44 @@ +/* _PDCLIB_update_tzname_etc( struct state const *, struct ttinfo const * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +void _PDCLIB_update_tzname_etc( struct state const * sp, struct ttinfo const * ttisp ) +{ +#if HAVE_TZNAME + tzname[ ttisp->isdst ] = (char *) &sp->chars[ ttisp->desigidx ]; +#endif +#if USG_COMPAT + if ( ! ttisp->isdst ) + { + timezone = - ttisp->utoff; + } +#endif +#if ALTZONE + if ( ttisp->isdst ) + { + altzone = - ttisp->utoff; + } +#endif +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isalnum.c b/rocklibc/src/ctype/isalnum.c new file mode 100644 index 0000000..d3ef7c9 --- /dev/null +++ b/rocklibc/src/ctype/isalnum.c @@ -0,0 +1,38 @@ +/* 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 + +#ifndef REGTEST + +#include + +int isalnum( int c ) +{ + return ( isdigit( c ) || isalpha( c ) ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isalnum( 'a' ) ); + TESTCASE( isalnum( 'z' ) ); + TESTCASE( isalnum( 'A' ) ); + TESTCASE( isalnum( 'Z' ) ); + TESTCASE( isalnum( '0' ) ); + TESTCASE( isalnum( '9' ) ); + TESTCASE( ! isalnum( ' ' ) ); + TESTCASE( ! isalnum( '\n' ) ); + TESTCASE( ! isalnum( '@' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isalpha.c b/rocklibc/src/ctype/isalpha.c new file mode 100644 index 0000000..371314d --- /dev/null +++ b/rocklibc/src/ctype/isalpha.c @@ -0,0 +1,34 @@ +/* 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 + +#ifndef REGTEST + +#include + +int isalpha( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_ALPHA ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isalpha( 'a' ) ); + TESTCASE( isalpha( 'z' ) ); + TESTCASE( ! isalpha( ' ' ) ); + TESTCASE( ! isalpha( '1' ) ); + TESTCASE( ! isalpha( '@' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isblank.c b/rocklibc/src/ctype/isblank.c new file mode 100644 index 0000000..6b2acee --- /dev/null +++ b/rocklibc/src/ctype/isblank.c @@ -0,0 +1,35 @@ +/* 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 + +#ifndef REGTEST + +#include + +int isblank( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_BLANK ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isblank( ' ' ) ); + TESTCASE( isblank( '\t' ) ); + TESTCASE( ! isblank( '\v' ) ); + TESTCASE( ! isblank( '\r' ) ); + TESTCASE( ! isblank( 'x' ) ); + TESTCASE( ! isblank( '@' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/iscntrl.c b/rocklibc/src/ctype/iscntrl.c new file mode 100644 index 0000000..cc482a8 --- /dev/null +++ b/rocklibc/src/ctype/iscntrl.c @@ -0,0 +1,33 @@ +/* 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 + +#ifndef REGTEST + +#include + +int iscntrl( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_CNTRL ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( iscntrl( '\a' ) ); + TESTCASE( iscntrl( '\b' ) ); + TESTCASE( iscntrl( '\n' ) ); + TESTCASE( ! iscntrl( ' ' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isdigit.c b/rocklibc/src/ctype/isdigit.c new file mode 100644 index 0000000..1a4f77b --- /dev/null +++ b/rocklibc/src/ctype/isdigit.c @@ -0,0 +1,34 @@ +/* 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 + +#ifndef REGTEST + +#include + +int isdigit( int c ) +{ + return ( c >= _PDCLIB_lc_ctype->digits_low && c <= _PDCLIB_lc_ctype->digits_high ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isdigit( '0' ) ); + TESTCASE( isdigit( '9' ) ); + TESTCASE( ! isdigit( ' ' ) ); + TESTCASE( ! isdigit( 'a' ) ); + TESTCASE( ! isdigit( '@' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isgraph.c b/rocklibc/src/ctype/isgraph.c new file mode 100644 index 0000000..73553a4 --- /dev/null +++ b/rocklibc/src/ctype/isgraph.c @@ -0,0 +1,37 @@ +/* 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 + +#ifndef REGTEST + +#include + +int isgraph( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_GRAPH ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isgraph( 'a' ) ); + TESTCASE( isgraph( 'z' ) ); + TESTCASE( isgraph( 'A' ) ); + TESTCASE( isgraph( 'Z' ) ); + TESTCASE( isgraph( '@' ) ); + TESTCASE( ! isgraph( '\t' ) ); + TESTCASE( ! isgraph( '\0' ) ); + TESTCASE( ! isgraph( ' ' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/islower.c b/rocklibc/src/ctype/islower.c new file mode 100644 index 0000000..5a1db77 --- /dev/null +++ b/rocklibc/src/ctype/islower.c @@ -0,0 +1,35 @@ +/* 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 + +#ifndef REGTEST + +#include + +int islower( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_LOWER ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( islower( 'a' ) ); + TESTCASE( islower( 'z' ) ); + TESTCASE( ! islower( 'A' ) ); + TESTCASE( ! islower( 'Z' ) ); + TESTCASE( ! islower( ' ' ) ); + TESTCASE( ! islower( '@' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isprint.c b/rocklibc/src/ctype/isprint.c new file mode 100644 index 0000000..5d50ee8 --- /dev/null +++ b/rocklibc/src/ctype/isprint.c @@ -0,0 +1,38 @@ +/* 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 + +#ifndef REGTEST + +#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 == ' ' ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isprint( 'a' ) ); + TESTCASE( isprint( 'z' ) ); + TESTCASE( isprint( 'A' ) ); + TESTCASE( isprint( 'Z' ) ); + TESTCASE( isprint( '@' ) ); + TESTCASE( ! isprint( '\t' ) ); + TESTCASE( ! isprint( '\0' ) ); + TESTCASE( isprint( ' ' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/ispunct.c b/rocklibc/src/ctype/ispunct.c new file mode 100644 index 0000000..1c5a58c --- /dev/null +++ b/rocklibc/src/ctype/ispunct.c @@ -0,0 +1,38 @@ +/* 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 + +#ifndef REGTEST + +#include + +int ispunct( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_PUNCT ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( ! ispunct( 'a' ) ); + TESTCASE( ! ispunct( 'z' ) ); + TESTCASE( ! ispunct( 'A' ) ); + TESTCASE( ! ispunct( 'Z' ) ); + TESTCASE( ispunct( '@' ) ); + TESTCASE( ispunct( '.' ) ); + TESTCASE( ! ispunct( '\t' ) ); + TESTCASE( ! ispunct( '\0' ) ); + TESTCASE( ! ispunct( ' ' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isspace.c b/rocklibc/src/ctype/isspace.c new file mode 100644 index 0000000..b7ee8cf --- /dev/null +++ b/rocklibc/src/ctype/isspace.c @@ -0,0 +1,36 @@ +/* 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 + +#ifndef REGTEST + +#include + +int isspace( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_SPACE ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isspace( ' ' ) ); + TESTCASE( isspace( '\f' ) ); + TESTCASE( isspace( '\n' ) ); + TESTCASE( isspace( '\r' ) ); + TESTCASE( isspace( '\t' ) ); + TESTCASE( isspace( '\v' ) ); + TESTCASE( ! isspace( 'a' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isupper.c b/rocklibc/src/ctype/isupper.c new file mode 100644 index 0000000..4207389 --- /dev/null +++ b/rocklibc/src/ctype/isupper.c @@ -0,0 +1,35 @@ +/* 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 + +#ifndef REGTEST + +#include + +int isupper( int c ) +{ + return ( _PDCLIB_lc_ctype->entry[c].flags & _PDCLIB_CTYPE_UPPER ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isupper( 'A' ) ); + TESTCASE( isupper( 'Z' ) ); + TESTCASE( ! isupper( 'a' ) ); + TESTCASE( ! isupper( 'z' ) ); + TESTCASE( ! isupper( ' ' ) ); + TESTCASE( ! isupper( '@' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/isxdigit.c b/rocklibc/src/ctype/isxdigit.c new file mode 100644 index 0000000..32bef4b --- /dev/null +++ b/rocklibc/src/ctype/isxdigit.c @@ -0,0 +1,42 @@ +/* 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 + +#ifndef REGTEST + +#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 ) + ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( isxdigit( '0' ) ); + TESTCASE( isxdigit( '9' ) ); + TESTCASE( isxdigit( 'a' ) ); + TESTCASE( isxdigit( 'f' ) ); + TESTCASE( ! isxdigit( 'g' ) ); + TESTCASE( isxdigit( 'A' ) ); + TESTCASE( isxdigit( 'F' ) ); + TESTCASE( ! isxdigit( 'G' ) ); + TESTCASE( ! isxdigit( '@' ) ); + TESTCASE( ! isxdigit( ' ' ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/tolower.c b/rocklibc/src/ctype/tolower.c new file mode 100644 index 0000000..bb14494 --- /dev/null +++ b/rocklibc/src/ctype/tolower.c @@ -0,0 +1,35 @@ +/* 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 + +#ifndef REGTEST + +#include + +int tolower( int c ) +{ + return _PDCLIB_lc_ctype->entry[c].lower; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( tolower( 'A' ) == 'a' ); + TESTCASE( tolower( 'Z' ) == 'z' ); + TESTCASE( tolower( 'a' ) == 'a' ); + TESTCASE( tolower( 'z' ) == 'z' ); + TESTCASE( tolower( '@' ) == '@' ); + TESTCASE( tolower( '[' ) == '[' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/ctype/toupper.c b/rocklibc/src/ctype/toupper.c new file mode 100644 index 0000000..a790a04 --- /dev/null +++ b/rocklibc/src/ctype/toupper.c @@ -0,0 +1,35 @@ +/* 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 + +#ifndef REGTEST + +#include + +int toupper( int c ) +{ + return _PDCLIB_lc_ctype->entry[c].upper; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( toupper( 'a' ) == 'A' ); + TESTCASE( toupper( 'z' ) == 'Z' ); + TESTCASE( toupper( 'A' ) == 'A' ); + TESTCASE( toupper( 'Z' ) == 'Z' ); + TESTCASE( toupper( '@' ) == '@' ); + TESTCASE( toupper( '[' ) == '[' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/inttypes/imaxabs.c b/rocklibc/src/inttypes/imaxabs.c new file mode 100644 index 0000000..445da06 --- /dev/null +++ b/rocklibc/src/inttypes/imaxabs.c @@ -0,0 +1,32 @@ +/* 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 + +#ifndef REGTEST + +intmax_t imaxabs( intmax_t j ) +{ + return ( j >= 0 ) ? j : -j; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + TESTCASE( imaxabs( ( intmax_t )0 ) == 0 ); + TESTCASE( imaxabs( INTMAX_MAX ) == INTMAX_MAX ); + TESTCASE( imaxabs( INTMAX_MIN + 1 ) == -( INTMAX_MIN + 1 ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/inttypes/imaxdiv.c b/rocklibc/src/inttypes/imaxdiv.c new file mode 100644 index 0000000..3b6b464 --- /dev/null +++ b/rocklibc/src/inttypes/imaxdiv.c @@ -0,0 +1,39 @@ +/* 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 + +#ifndef REGTEST + +imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom ) +{ + imaxdiv_t rc; + rc.quot = numer / denom; + rc.rem = numer % denom; + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + imaxdiv_t result; + result = imaxdiv( ( intmax_t )5, ( intmax_t )2 ); + TESTCASE( result.quot == 2 && result.rem == 1 ); + result = imaxdiv( ( intmax_t )-5, ( intmax_t )2 ); + TESTCASE( result.quot == -2 && result.rem == -1 ); + result = imaxdiv( ( intmax_t )5, ( intmax_t )-2 ); + TESTCASE( result.quot == -2 && result.rem == 1 ); + TESTCASE( sizeof( result.quot ) == sizeof( intmax_t ) ); + TESTCASE( sizeof( result.rem ) == sizeof( intmax_t ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/inttypes/strtoimax.c b/rocklibc/src/inttypes/strtoimax.c new file mode 100644 index 0000000..3c7683a --- /dev/null +++ b/rocklibc/src/inttypes/strtoimax.c @@ -0,0 +1,158 @@ +/* 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 + +#ifndef REGTEST + +#include + +intmax_t strtoimax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_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, &sign ); + } + else + { + rc = ( intmax_t )_PDCLIB_strtox_main( &p, ( unsigned )base, ( uintmax_t )INTMAX_MIN, ( ( uintmax_t )INTMAX_MAX + 1 ), &sign ); + } + + if ( endptr != NULL ) + { + *endptr = ( p != NULL ) ? ( char * ) p : ( char * ) nptr; + } + + return ( sign == '+' ) ? rc : -rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + char * endptr; + /* this, to base 36, overflows even a 256 bit integer */ + char overflow[] = "-ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ_"; + /* tricky border case */ + char tricky[] = "+0xz"; + errno = 0; + /* basic functionality */ + TESTCASE( strtoimax( "123", NULL, 10 ) == 123 ); + /* proper detecting of default base 10 */ + TESTCASE( strtoimax( "456", NULL, 0 ) == 456 ); + /* proper functioning to smaller base */ + TESTCASE( strtoimax( "14", NULL, 8 ) == 12 ); + /* proper autodetecting of octal */ + TESTCASE( strtoimax( "016", NULL, 0 ) == 14 ); + /* proper autodetecting of hexadecimal, lowercase 'x' */ + TESTCASE( strtoimax( "0xFF", NULL, 0 ) == 255 ); + /* proper autodetecting of hexadecimal, uppercase 'X' */ + TESTCASE( strtoimax( "0Xa1", NULL, 0 ) == 161 ); + /* proper handling of border case: 0x followed by non-hexdigit */ + TESTCASE( strtoimax( tricky, &endptr, 0 ) == 0 ); + /* newlib completely balks at this parse, so we _NOREG it */ + TESTCASE_NOREG( endptr == tricky + 2 ); + /* proper handling of border case: 0 followed by non-octdigit */ + TESTCASE( strtoimax( tricky, &endptr, 8 ) == 0 ); + TESTCASE( endptr == tricky + 2 ); + /* errno should still be 0 */ + TESTCASE( errno == 0 ); + /* overflowing subject sequence must still return proper endptr */ + TESTCASE( strtoimax( overflow, &endptr, 36 ) == INTMAX_MIN ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* same for positive */ + errno = 0; + TESTCASE( strtoimax( overflow + 1, &endptr, 36 ) == INTMAX_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* testing skipping of leading whitespace */ + TESTCASE( strtoimax( " \n\v\t\f789", NULL, 0 ) == 789 ); + /* testing conversion failure */ + TESTCASE( strtoimax( overflow, &endptr, 10 ) == 0 ); + TESTCASE( endptr == overflow ); + endptr = NULL; + TESTCASE( strtoimax( overflow, &endptr, 0 ) == 0 ); + TESTCASE( endptr == overflow ); + /* These tests assume two-complement, but conversion should work for */ + /* one-complement and signed magnitude just as well. Anyone having a */ + /* platform to test this on? */ + errno = 0; +#if INTMAX_MAX >> 62 == 1 + /* testing "odd" overflow, i.e. base is not a power of two */ + TESTCASE( strtoimax( "9223372036854775807", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "9223372036854775808", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtoimax( "-9223372036854775807", NULL, 0 ) == ( INTMAX_MIN + 1 ) ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-9223372036854775808", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-9223372036854775809", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == ERANGE ); + /* testing "even" overflow, i.e. base is power of two */ + errno = 0; + TESTCASE( strtoimax( "0x7fffffffffffffff", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "0x8000000000000000", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtoimax( "-0x7fffffffffffffff", NULL, 0 ) == ( INTMAX_MIN + 1 ) ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-0x8000000000000000", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-0x8000000000000001", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == ERANGE ); +#elif LLONG_MAX >> 126 == 1 + /* testing "odd" overflow, i.e. base is not a power of two */ + TESTCASE( strtoimax( "170141183460469231731687303715884105728", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "170141183460469231731687303715884105729", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtoimax( "-170141183460469231731687303715884105728", NULL, 0 ) == ( INTMAX_MIN + 1 ) ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-170141183460469231731687303715884105729", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-170141183460469231731687303715884105730", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == ERANGE ); + /* testing "even" overflow, i.e. base is power of two */ + errno = 0; + TESTCASE( strtoimax( "0x7fffffffffffffffffffffffffffffff", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "0x80000000000000000000000000000000", NULL, 0 ) == INTMAX_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtoimax( "-0x7fffffffffffffffffffffffffffffff", NULL, 0 ) == ( INTMAX_MIN + 1 ) ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-0x80000000000000000000000000000000", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == 0 ); + TESTCASE( strtoimax( "-0x80000000000000000000000000000001", NULL, 0 ) == INTMAX_MIN ); + TESTCASE( errno == ERANGE ); +#else +#error Unsupported width of 'intmax_t' (neither 64 nor 128 bit). +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/inttypes/strtoumax.c b/rocklibc/src/inttypes/strtoumax.c new file mode 100644 index 0000000..ddda21f --- /dev/null +++ b/rocklibc/src/inttypes/strtoumax.c @@ -0,0 +1,122 @@ +/* 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 + +#ifndef REGTEST + +#include + +uintmax_t strtoumax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_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, &sign ); + + if ( endptr != NULL ) + { + *endptr = ( p != NULL ) ? ( char * ) p : ( char * ) nptr; + } + + return ( sign == '+' ) ? rc : -rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + char * endptr; + /* this, to base 36, overflows even a 256 bit integer */ + char overflow[] = "-ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ_"; + /* tricky border case */ + char tricky[] = "+0xz"; + errno = 0; + /* basic functionality */ + TESTCASE( strtoumax( "123", NULL, 10 ) == 123 ); + /* proper detecting of default base 10 */ + TESTCASE( strtoumax( "456", NULL, 0 ) == 456 ); + /* proper functioning to smaller base */ + TESTCASE( strtoumax( "14", NULL, 8 ) == 12 ); + /* proper autodetecting of octal */ + TESTCASE( strtoumax( "016", NULL, 0 ) == 14 ); + /* proper autodetecting of hexadecimal, lowercase 'x' */ + TESTCASE( strtoumax( "0xFF", NULL, 0 ) == 255 ); + /* proper autodetecting of hexadecimal, uppercase 'X' */ + TESTCASE( strtoumax( "0Xa1", NULL, 0 ) == 161 ); + /* proper handling of border case: 0x followed by non-hexdigit */ + TESTCASE( strtoumax( tricky, &endptr, 0 ) == 0 ); + /* newlib completely balks at this parse, so we _NOREG it */ + TESTCASE_NOREG( endptr == tricky + 2 ); + /* proper handling of border case: 0 followed by non-octdigit */ + TESTCASE( strtoumax( tricky, &endptr, 8 ) == 0 ); + TESTCASE( endptr == tricky + 2 ); + /* errno should still be 0 */ + TESTCASE( errno == 0 ); + /* overflowing subject sequence must still return proper endptr */ + TESTCASE( strtoumax( overflow, &endptr, 36 ) == UINTMAX_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* same for positive */ + errno = 0; + TESTCASE( strtoumax( overflow + 1, &endptr, 36 ) == UINTMAX_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* testing skipping of leading whitespace */ + TESTCASE( strtoumax( " \n\v\t\f789", NULL, 0 ) == 789 ); + /* testing conversion failure */ + TESTCASE( strtoumax( overflow, &endptr, 10 ) == 0 ); + TESTCASE( endptr == overflow ); + endptr = NULL; + TESTCASE( strtoumax( overflow, &endptr, 0 ) == 0 ); + TESTCASE( endptr == overflow ); + errno = 0; +/* uintmax_t -> long long -> 64 bit */ +#if UINTMAX_MAX >> 63 == 1 + /* testing "odd" overflow, i.e. base is not power of two */ + TESTCASE( strtoumax( "18446744073709551615", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoumax( "18446744073709551616", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == ERANGE ); + /* testing "even" overflow, i.e. base is power of two */ + errno = 0; + TESTCASE( strtoumax( "0xFFFFFFFFFFFFFFFF", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoumax( "0x10000000000000000", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == ERANGE ); +/* uintmax_t -> long long -> 128 bit */ +#elif UINTMAX_MAX >> 127 == 1 + /* testing "odd" overflow, i.e. base is not power of two */ + TESTCASE( strtoumax( "340282366920938463463374607431768211455", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoumax( "340282366920938463463374607431768211456", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == ERANGE ); + /* testing "even" everflow, i.e. base is power of two */ + errno = 0; + TESTCASE( strtoumax( "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoumax( "0x100000000000000000000000000000000", NULL, 0 ) == UINTMAX_MAX ); + TESTCASE( errno == ERANGE ); +#else +#error Unsupported width of 'uintmax_t' (neither 64 nor 128 bit). +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/locale/localeconv.c b/rocklibc/src/locale/localeconv.c new file mode 100644 index 0000000..8fbc97f --- /dev/null +++ b/rocklibc/src/locale/localeconv.c @@ -0,0 +1,32 @@ +/* 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 + +#ifndef REGTEST + +struct lconv * localeconv( void ) +{ + return _PDCLIB_lc_numeric_monetary.lconv; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + struct lconv * lconv; + TESTCASE( ( lconv = localeconv() ) != NULL ); + TESTCASE( strcmp( lconv->decimal_point, "." ) == 0 ); + TESTCASE( strcmp( lconv->thousands_sep, "" ) == 0 ); + TESTCASE( ( strcmp( lconv->grouping, "" ) == 0 ) || ( strcmp( lconv->grouping, "\x7f" ) == 0 ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/locale/setlocale.c b/rocklibc/src/locale/setlocale.c new file mode 100644 index 0000000..fb0d0c1 --- /dev/null +++ b/rocklibc/src/locale/setlocale.c @@ -0,0 +1,269 @@ +/* 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 + +#ifndef REGTEST + +#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; + + /* The standard states (7.22.4.6 (3), "the implementation shall behave + as if no library function calls the getenv function." That is, + however, in context of the previous paragraph stating that getenv + "need not avoid data races with other threads of execution that + modify the environment list". + PDCLib does not provide means of modifying the environment list. + */ + 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 _PDCLIB_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_value2string( _PDCLIB_LOCALE_PATH_ENV ) ) != NULL ) + { + path = getenv( _PDCLIB_value2string( _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 +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strcmp( setlocale( LC_ALL, "C" ), "C" ) == 0 ); +#ifndef REGTEST + TESTCASE( setlocale( LC_ALL, "" ) == NULL ); +#endif + TESTCASE( strcmp( setlocale( LC_ALL, NULL ), "C" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/fabs.c b/rocklibc/src/math/fabs.c new file mode 100644 index 0000000..f7a3a8c --- /dev/null +++ b/rocklibc/src/math/fabs.c @@ -0,0 +1,114 @@ + +/* fabs( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +double fabs( double x ) +{ + if ( isnan( x ) ) + { + return NAN; + } + + return ( x < 0.0 ) ? -x : x; +} + +float fabsf( float x ) +{ + if ( isnan( x ) ) + { + return NAN; + } + + return ( x < 0.0 ) ? -x : x; +} + +long double fabsl( long double x ) +{ + if ( isnan( x ) ) + { + return NAN; + } + + return ( x < 0.0 ) ? -x : x; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + float f; + double d; + long double ld; + + TESTCASE( fabsf( 3.15f ) == 3.15f ); + TESTCASE( fabsf( -3.15f ) == 3.15f ); + errno = 0; + TESTCASE( fabsf( INFINITY ) == INFINITY ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( fabsf( -INFINITY ) == INFINITY ); + TESTCASE( errno == 0 ); + errno = 0; + f = fabsf( NAN ); + TESTCASE( isnan( f ) ); + TESTCASE( ! signbit( f ) ); + TESTCASE( errno == 0 ); + f = fabsf( -NAN ); + TESTCASE( isnan( f ) ); + TESTCASE( ! signbit( f ) ); + TESTCASE( errno == 0 ); + + TESTCASE( fabs( 3.15 ) == 3.15 ); + TESTCASE( fabs( -3.15 ) == 3.15 ); + errno = 0; + TESTCASE( fabs( INFINITY ) == INFINITY ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( fabs( -INFINITY ) == INFINITY ); + TESTCASE( errno == 0 ); + errno = 0; + d = fabs( NAN ); + TESTCASE( isnan( d ) ); + TESTCASE( ! signbit( d ) ); + TESTCASE( errno == 0 ); + d = fabs( -NAN ); + TESTCASE( isnan( d ) ); + TESTCASE( ! signbit( d ) ); + TESTCASE( errno == 0 ); + + TESTCASE( fabsl( 3.15l ) == 3.15l ); + TESTCASE( fabsl( -3.15l ) == 3.15l ); + errno = 0; + TESTCASE( fabsl( INFINITY ) == INFINITY ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( fabsl( -INFINITY ) == INFINITY ); + TESTCASE( errno == 0 ); + errno = 0; + ld = fabsl( NAN ); + TESTCASE( isnan( ld ) ); + TESTCASE( ! signbit( ld ) ); + TESTCASE( errno == 0 ); + ld = fabsl( -NAN ); + TESTCASE( isnan( ld ) ); + TESTCASE( ! signbit( ld ) ); + TESTCASE( errno == 0 ); + + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/fdim.c b/rocklibc/src/math/fdim.c new file mode 100644 index 0000000..02b4902 --- /dev/null +++ b/rocklibc/src/math/fdim.c @@ -0,0 +1,74 @@ +/* fdim( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +double fdim( double x, double y ) +{ + return fmax( x - y, 0 ); +} + +float fdimf( float x, float y ) +{ + return fmaxf( x - y, 0 ); +} + +long double fdiml( long double x, long double y ) +{ + return fmaxl( x - y, 0 ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + float f1, f2; + double d1, d2; + long double ld1, ld2; + + f1 = 3.5f; + f2 = 3.75f; + TESTCASE( fdimf( f1, f2 ) == 0.0f ); + TESTCASE( fdimf( f2, f1 ) == 0.25f ); + TESTCASE( fdimf( f1, INFINITY ) == 0.0f ); + TESTCASE( fdimf( INFINITY, f1 ) == INFINITY ); + TESTCASE( fdimf( f1, -INFINITY ) == INFINITY ); + TESTCASE( fdimf( -INFINITY, f1 ) == 0.0f ); + TESTCASE( fdimf( f1, NAN ) != f1 ); + TESTCASE( fdimf( NAN, f1 ) != f1 ); + + d1 = 3.5; + d2 = 3.75; + TESTCASE( fdim( d1, d2 ) == 0.0 ); + TESTCASE( fdim( d2, d1 ) == 0.25 ); + TESTCASE( fdim( d1, INFINITY ) == 0.0 ); + TESTCASE( fdim( INFINITY, d1 ) == INFINITY ); + TESTCASE( fdim( d1, -INFINITY ) == INFINITY ); + TESTCASE( fdim( -INFINITY, d1 ) == 0.0 ); + TESTCASE( fdim( d1, NAN ) != d1 ); + TESTCASE( fdim( NAN, d1 ) != d1 ); + + ld1 = 3.5l; + ld2 = 3.75l; + TESTCASE( fdiml( ld1, ld2 ) == 0.0l ); + TESTCASE( fdiml( ld2, ld1 ) == 0.25l ); + TESTCASE( fdiml( ld1, INFINITY ) == 0.0l ); + TESTCASE( fdiml( INFINITY, ld1 ) == INFINITY ); + TESTCASE( fdiml( ld1, -INFINITY ) == INFINITY ); + TESTCASE( fdiml( -INFINITY, ld1 ) == 0.0l ); + TESTCASE( fdiml( ld1, NAN ) != ld1 ); + TESTCASE( fdiml( NAN, ld1 ) != ld1 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/fmax.c b/rocklibc/src/math/fmax.c new file mode 100644 index 0000000..b6a4886 --- /dev/null +++ b/rocklibc/src/math/fmax.c @@ -0,0 +1,105 @@ + +/* fmax( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +double fmax( double x, double y ) +{ + if ( isnan( x ) ) return y; + if ( isnan( y ) ) return x; + return ( x > y ) ? x : y; +} + +float fmaxf( float x, float y ) +{ + if ( isnan( x ) ) return y; + if ( isnan( y ) ) return x; + return ( x > y ) ? x : y; +} + +long double fmaxl( long double x, long double y ) +{ + if ( isnan( x ) ) return y; + if ( isnan( y ) ) return x; + return ( x > y ) ? x : y; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + float f1, f2; + double d1, d2; + long double ld1, ld2; + + f1 = 3.15f; + f2 = 3.16f; + TESTCASE( fmaxf( f1, f2 ) == f2 ); + TESTCASE( fmaxf( f2, f1 ) == f2 ); + TESTCASE( fmaxf( f1, f1 ) == f1 ); + TESTCASE( fmaxf( f1, INFINITY ) == INFINITY ); + TESTCASE( fmaxf( INFINITY, f1 ) == INFINITY ); + TESTCASE( fmaxf( f1, -INFINITY ) == f1 ); + TESTCASE( fmaxf( -INFINITY, f1 ) == f1 ); + TESTCASE( fmaxf( f1, NAN ) == f1 ); + TESTCASE( fmaxf( NAN, f1 ) == f1 ); + TESTCASE( fmaxf( f1, -NAN ) == f1 ); + TESTCASE( fmaxf( -NAN, f1 ) == f1 ); + TESTCASE( fmaxf( NAN, NAN ) != fmaxf( NAN, NAN ) ); + f1 = 0.0f; + f2 = -0.0f; + TESTCASE( fmaxf( f1, f2 ) == f1 ); + TESTCASE( fmaxf( f2, f1 ) == f1 ); + + d1 = 3.15f; + d2 = 3.16f; + TESTCASE( fmax( d1, d2 ) == d2 ); + TESTCASE( fmax( d2, d1 ) == d2 ); + TESTCASE( fmax( d1, d1 ) == d1 ); + TESTCASE( fmax( d1, INFINITY ) == INFINITY ); + TESTCASE( fmax( INFINITY, d1 ) == INFINITY ); + TESTCASE( fmax( d1, -INFINITY ) == d1 ); + TESTCASE( fmax( -INFINITY, d1 ) == d1 ); + TESTCASE( fmax( d1, NAN ) == d1 ); + TESTCASE( fmax( NAN, d1 ) == d1 ); + TESTCASE( fmax( d1, -NAN ) == d1 ); + TESTCASE( fmax( -NAN, d1 ) == d1 ); + TESTCASE( fmax( NAN, NAN ) != fmax( NAN, NAN ) ); + d1 = 0.0; + d2 = -0.0; + TESTCASE( fmax( d1, d2 ) == d1 ); + TESTCASE( fmax( d2, d1 ) == d1 ); + + ld1 = 3.15f; + ld2 = 3.16f; + TESTCASE( fmaxl( ld1, ld2 ) == ld2 ); + TESTCASE( fmaxl( ld2, ld1 ) == ld2 ); + TESTCASE( fmaxl( ld1, ld1 ) == ld1 ); + TESTCASE( fmaxl( ld1, INFINITY ) == INFINITY ); + TESTCASE( fmaxl( INFINITY, ld1 ) == INFINITY ); + TESTCASE( fmaxl( ld1, -INFINITY ) == ld1 ); + TESTCASE( fmaxl( -INFINITY, ld1 ) == ld1 ); + TESTCASE( fmaxl( ld1, NAN ) == ld1 ); + TESTCASE( fmaxl( NAN, ld1 ) == ld1 ); + TESTCASE( fmaxl( ld1, -NAN ) == ld1 ); + TESTCASE( fmaxl( -NAN, ld1 ) == ld1 ); + TESTCASE( fmaxl( NAN, NAN ) != fmaxl( NAN, NAN ) ); + ld1 = 0.0; + ld2 = -0.0; + TESTCASE( fmaxl( ld1, ld2 ) == ld1 ); + TESTCASE( fmaxl( ld2, ld1 ) == ld1 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/fmin.c b/rocklibc/src/math/fmin.c new file mode 100644 index 0000000..90c2dc0 --- /dev/null +++ b/rocklibc/src/math/fmin.c @@ -0,0 +1,105 @@ + +/* fmin( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +double fmin( double x, double y ) +{ + if ( isnan( x ) ) return y; + if ( isnan( y ) ) return x; + return ( x < y ) ? x : y; +} + +float fminf( float x, float y ) +{ + if ( isnan( x ) ) return y; + if ( isnan( y ) ) return x; + return ( x < y ) ? x : y; +} + +long double fminl( long double x, long double y ) +{ + if ( isnan( x ) ) return y; + if ( isnan( y ) ) return x; + return ( x < y ) ? x : y; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + float f1, f2; + double d1, d2; + long double ld1, ld2; + + f1 = 3.16f; + f2 = 3.15f; + TESTCASE( fminf( f1, f2 ) == f2 ); + TESTCASE( fminf( f2, f1 ) == f2 ); + TESTCASE( fminf( f1, f1 ) == f1 ); + TESTCASE( fminf( f1, INFINITY ) == f1 ); + TESTCASE( fminf( INFINITY, f1 ) == f1 ); + TESTCASE( fminf( f1, -INFINITY ) == -INFINITY ); + TESTCASE( fminf( -INFINITY, f1 ) == -INFINITY ); + TESTCASE( fminf( f1, NAN ) == f1 ); + TESTCASE( fminf( NAN, f1 ) == f1 ); + TESTCASE( fminf( f1, -NAN ) == f1 ); + TESTCASE( fminf( -NAN, f1 ) == f1 ); + TESTCASE( fminf( NAN, NAN ) != fminf( NAN, NAN ) ); + f1 = -0.0f; + f2 = 0.0f; + TESTCASE( fminf( f1, f2 ) == f1 ); + TESTCASE( fminf( f2, f1 ) == f1 ); + + d1 = 3.16f; + d2 = 3.15f; + TESTCASE( fmin( d1, d2 ) == d2 ); + TESTCASE( fmin( d2, d1 ) == d2 ); + TESTCASE( fmin( d1, d1 ) == d1 ); + TESTCASE( fmin( d1, INFINITY ) == d1 ); + TESTCASE( fmin( INFINITY, d1 ) == d1 ); + TESTCASE( fmin( d1, -INFINITY ) == -INFINITY ); + TESTCASE( fmin( -INFINITY, d1 ) == -INFINITY ); + TESTCASE( fmin( d1, NAN ) == d1 ); + TESTCASE( fmin( NAN, d1 ) == d1 ); + TESTCASE( fmin( d1, -NAN ) == d1 ); + TESTCASE( fmin( -NAN, d1 ) == d1 ); + TESTCASE( fmin( NAN, NAN ) != fmin( NAN, NAN ) ); + d1 = -0.0; + d2 = 0.0; + TESTCASE( fmin( d1, d2 ) == d1 ); + TESTCASE( fmin( d2, d1 ) == d1 ); + + ld1 = 3.16f; + ld2 = 3.15f; + TESTCASE( fminl( ld1, ld2 ) == ld2 ); + TESTCASE( fminl( ld2, ld1 ) == ld2 ); + TESTCASE( fminl( ld1, ld1 ) == ld1 ); + TESTCASE( fminl( ld1, INFINITY ) == ld1 ); + TESTCASE( fminl( INFINITY, ld1 ) == ld1 ); + TESTCASE( fminl( ld1, -INFINITY ) == -INFINITY ); + TESTCASE( fminl( -INFINITY, ld1 ) == -INFINITY ); + TESTCASE( fminl( ld1, NAN ) == ld1 ); + TESTCASE( fminl( NAN, ld1 ) == ld1 ); + TESTCASE( fminl( ld1, -NAN ) == ld1 ); + TESTCASE( fminl( -NAN, ld1 ) == ld1 ); + TESTCASE( fminl( NAN, NAN ) != fminl( NAN, NAN ) ); + ld1 = -0.0; + ld2 = 0.0; + TESTCASE( fminl( ld1, ld2 ) == ld1 ); + TESTCASE( fminl( ld2, ld1 ) == ld1 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/fpclassify.c b/rocklibc/src/math/fpclassify.c new file mode 100644 index 0000000..059aa9a --- /dev/null +++ b/rocklibc/src/math/fpclassify.c @@ -0,0 +1,161 @@ +/* fpclassify( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +int _PDCLIB_fpclassifyd( double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + _PDCLIB_bigint_digit_t digit = 0; + size_t size; + size_t i; + int exp; + + memcpy( data, &x, sizeof( double ) ); + exp = _PDCLIB_DBL_EXP( data ); + size = _PDCLIB_DBL_SIZE( data ); + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + switch ( exp ) + { + case ( ( _PDCLIB_DBL_MAX_EXP - 1 ) + _PDCLIB_DBL_MAX_EXP ): + return ( digit == 0 ) ? FP_INFINITE : FP_NAN; + case 0: + return ( digit == 0 ) ? FP_ZERO : FP_SUBNORMAL; + default: + return FP_NORMAL; + } +} + +int _PDCLIB_fpclassifyf( float x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( float ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + _PDCLIB_bigint_digit_t digit = 0; + size_t size; + size_t i; + int exp; + + memcpy( data, &x, sizeof( float ) ); + exp = _PDCLIB_FLT_EXP( data ); + size = _PDCLIB_FLT_SIZE( data ); + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + switch ( exp ) + { + case ( ( _PDCLIB_FLT_MAX_EXP - 1 ) + _PDCLIB_FLT_MAX_EXP ): + return ( digit == 0 ) ? FP_INFINITE : FP_NAN; + case 0: + return ( digit == 0 ) ? FP_ZERO : FP_SUBNORMAL; + default: + return FP_NORMAL; + } +} + +int _PDCLIB_fpclassifyl( long double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( long double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + _PDCLIB_bigint_digit_t digit = 0; + size_t size; + size_t i; + int exp; + + memcpy( data, &x, sizeof( long double ) ); + exp = _PDCLIB_LDBL_EXP( data ); + size = _PDCLIB_LDBL_SIZE( data ); + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + switch ( exp ) + { + case ( ( _PDCLIB_LDBL_MAX_EXP - 1 ) + _PDCLIB_LDBL_MAX_EXP ): + return ( digit == 0 ) ? FP_INFINITE : FP_NAN; + case 0: + return ( digit == 0 ) ? FP_ZERO : FP_SUBNORMAL; + default: + return FP_NORMAL; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + float f; + double d; + long double ld; + + f = 0.123; + TESTCASE( fpclassify( f ) == FP_NORMAL ); + f = FLT_MIN; + TESTCASE( fpclassify( f ) == FP_NORMAL ); + f = FLT_MIN / 2; + TESTCASE( fpclassify( f ) == FP_SUBNORMAL ); + f = 0.0; + TESTCASE( fpclassify( f ) == FP_ZERO ); + f = FLT_MAX; + TESTCASE( fpclassify( f ) == FP_NORMAL ); + f = FLT_MAX * 2; + TESTCASE( fpclassify( f ) == FP_INFINITE ); + f = 0.0 / 0.0; + TESTCASE( fpclassify( f ) == FP_NAN ); + + d = 0.123; + TESTCASE( fpclassify( d ) == FP_NORMAL ); + d = DBL_MIN; + TESTCASE( fpclassify( d ) == FP_NORMAL ); + d = DBL_MIN / 2; + TESTCASE( fpclassify( d ) == FP_SUBNORMAL ); + d = 0.0; + TESTCASE( fpclassify( d ) == FP_ZERO ); + d = DBL_MAX; + TESTCASE( fpclassify( d ) == FP_NORMAL ); + d = DBL_MAX * 2; + TESTCASE( fpclassify( d ) == FP_INFINITE ); + d = 0.0 / 0.0; + TESTCASE( fpclassify( d ) == FP_NAN ); + + ld = 0.123; + TESTCASE( fpclassify( ld ) == FP_NORMAL ); + ld = LDBL_MIN; + TESTCASE( fpclassify( ld ) == FP_NORMAL ); + ld = LDBL_MIN / 2; + TESTCASE( fpclassify( ld ) == FP_SUBNORMAL ); + ld = 0.0; + TESTCASE( fpclassify( ld ) == FP_ZERO ); + ld = LDBL_MAX; + TESTCASE( fpclassify( ld ) == FP_NORMAL ); + ld = LDBL_MAX * 2; + TESTCASE( fpclassify( ld ) == FP_INFINITE ); + ld = 0.0 / 0.0; + TESTCASE( fpclassify( ld ) == FP_NAN ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/isfinite.c b/rocklibc/src/math/isfinite.c new file mode 100644 index 0000000..5c332af --- /dev/null +++ b/rocklibc/src/math/isfinite.c @@ -0,0 +1,92 @@ +/* isfinite( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +int _PDCLIB_isfinited( double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + memcpy( data, &x, sizeof( double ) ); + return _PDCLIB_DBL_EXP( data ) != ( ( _PDCLIB_DBL_MAX_EXP - 1 ) + _PDCLIB_DBL_MAX_EXP ); +} + +int _PDCLIB_isfinitef( float x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( float ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + memcpy( data, &x, sizeof( float ) ); + return _PDCLIB_FLT_EXP( data ) != ( ( _PDCLIB_FLT_MAX_EXP - 1 ) + _PDCLIB_FLT_MAX_EXP ); +} + +int _PDCLIB_isfinitel( long double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( long double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + memcpy( data, &x, sizeof( long double ) ); + return _PDCLIB_LDBL_EXP( data ) != ( ( _PDCLIB_LDBL_MAX_EXP - 1 ) + _PDCLIB_LDBL_MAX_EXP ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + float f; + double d; + long double ld; + + f = 0.123f; + TESTCASE( isfinite( f ) ); + f = FLT_MAX; + TESTCASE( isfinite( f ) ); + f *= 2; + TESTCASE( ! isfinite( f ) ); + f = FLT_MIN; + TESTCASE( isfinite( f ) ); + f /= 2; + TESTCASE( isfinite( f ) ); + f = 0.0f / 0.0f; + TESTCASE( ! isfinite( f ) ); + + d = 0.123; + TESTCASE( isfinite( d ) ); + d = DBL_MAX; + TESTCASE( isfinite( d ) ); + d *= 2; + TESTCASE( ! isfinite( d ) ); + d = DBL_MIN; + TESTCASE( isfinite( d ) ); + d /= 2; + TESTCASE( isfinite( d ) ); + d = 0.0 / 0.0; + TESTCASE( ! isfinite( d ) ); + + ld = 0.123l; + TESTCASE( isfinite( ld ) ); + ld = LDBL_MAX; + TESTCASE( isfinite( ld ) ); + ld *= 2; + TESTCASE( ! isfinite( ld ) ); + ld = LDBL_MIN; + TESTCASE( isfinite( ld ) ); + ld /= 2; + TESTCASE( isfinite( ld ) ); + ld = 0.0l / 0.0l; + TESTCASE( ! isfinite( ld ) ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/isinf.c b/rocklibc/src/math/isinf.c new file mode 100644 index 0000000..bc1e62a --- /dev/null +++ b/rocklibc/src/math/isinf.c @@ -0,0 +1,123 @@ +/* isinf( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +int _PDCLIB_isinfd( double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + size_t size; + int exp; + + memcpy( data, &x, sizeof( double ) ); + exp = _PDCLIB_DBL_EXP( data ); + size = _PDCLIB_DBL_SIZE( data ); + + if ( exp == ( ( _PDCLIB_DBL_MAX_EXP - 1 ) + _PDCLIB_DBL_MAX_EXP ) ) + { + _PDCLIB_bigint_digit_t digit = 0; + size_t i; + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + return digit == 0; + } + + return 0; +} + +int _PDCLIB_isinff( float x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( float ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + size_t size; + int exp; + + memcpy( data, &x, sizeof( float ) ); + exp = _PDCLIB_FLT_EXP( data ); + size = _PDCLIB_FLT_SIZE( data ); + + if ( exp == ( ( _PDCLIB_FLT_MAX_EXP - 1 ) + _PDCLIB_FLT_MAX_EXP ) ) + { + _PDCLIB_bigint_digit_t digit = 0; + size_t i; + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + return digit == 0; + } + + return 0; +} + +int _PDCLIB_isinfl( long double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( long double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + size_t size; + int exp; + + memcpy( data, &x, sizeof( long double ) ); + exp = _PDCLIB_LDBL_EXP( data ); + size = _PDCLIB_LDBL_SIZE( data ); + + if ( exp == ( ( _PDCLIB_LDBL_MAX_EXP - 1 ) + _PDCLIB_LDBL_MAX_EXP ) ) + { + _PDCLIB_bigint_digit_t digit = 0; + size_t i; + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + return digit == 0; + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + float f; + double d; + long double ld; + + f = 1e100; + TESTCASE( isinf( f ) == 1 ); + f = 0.0 / 0.0; + TESTCASE( isinf( f ) == 0 ); + + d = 1e500; + TESTCASE( isinf( d ) == 1 ); + d = 0.0 / 0.0; + TESTCASE( isinf( d ) == 0 ); + + ld = 1e500; + TESTCASE( isinf( ld ) == 1 ); + ld = 0.0 / 0.0; + TESTCASE( isinf( ld ) == 0 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/isnan.c b/rocklibc/src/math/isnan.c new file mode 100644 index 0000000..32eb3ed --- /dev/null +++ b/rocklibc/src/math/isnan.c @@ -0,0 +1,123 @@ +/* isnan( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +int _PDCLIB_isnand( double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + size_t size; + int exp; + + memcpy( data, &x, sizeof( double ) ); + exp = _PDCLIB_DBL_EXP( data ); + size = _PDCLIB_DBL_SIZE( data ); + + if ( exp == ( ( _PDCLIB_DBL_MAX_EXP - 1 ) + _PDCLIB_DBL_MAX_EXP ) ) + { + _PDCLIB_bigint_digit_t digit = 0; + size_t i; + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + return digit != 0; + } + + return 0; +} + +int _PDCLIB_isnanf( float x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( float ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + size_t size; + int exp; + + memcpy( data, &x, sizeof( float ) ); + exp = _PDCLIB_FLT_EXP( data ); + size = _PDCLIB_FLT_SIZE( data ); + + if ( exp == ( ( _PDCLIB_FLT_MAX_EXP - 1 ) + _PDCLIB_FLT_MAX_EXP ) ) + { + _PDCLIB_bigint_digit_t digit = 0; + size_t i; + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + return digit != 0; + } + + return 0; +} + +int _PDCLIB_isnanl( long double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( long double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + size_t size; + int exp; + + memcpy( data, &x, sizeof( long double ) ); + exp = _PDCLIB_LDBL_EXP( data ); + size = _PDCLIB_LDBL_SIZE( data ); + + if ( exp == ( ( _PDCLIB_LDBL_MAX_EXP - 1 ) + _PDCLIB_LDBL_MAX_EXP ) ) + { + _PDCLIB_bigint_digit_t digit = 0; + size_t i; + + for ( i = 0; i < size; ++i ) + { + digit |= data[i]; + } + + return digit != 0; + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + float f; + double d; + long double ld; + + f = 1e100; + TESTCASE( isnan( f ) == 0 ); + f = 0.0 / 0.0; + TESTCASE( isnan( f ) == 1 ); + + d = 1e500; + TESTCASE( isnan( d ) == 0 ); + d = 0.0 / 0.0; + TESTCASE( isnan( d ) == 1 ); + + ld = 1e500; + TESTCASE( isnan( ld ) == 0 ); + ld = 0.0 / 0.0; + TESTCASE( isnan( ld ) == 1 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/isnormal.c b/rocklibc/src/math/isnormal.c new file mode 100644 index 0000000..2c3ed1d --- /dev/null +++ b/rocklibc/src/math/isnormal.c @@ -0,0 +1,110 @@ +/* isnormal( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +int _PDCLIB_isnormald( double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + int exp; + memcpy( data, &x, sizeof( double ) ); + exp = _PDCLIB_DBL_EXP( data ); + return ( exp != ( ( _PDCLIB_DBL_MAX_EXP - 1 ) + _PDCLIB_DBL_MAX_EXP ) ) && ( exp != 0 ); +} + +int _PDCLIB_isnormalf( float x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( float ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + int exp; + memcpy( data, &x, sizeof( float ) ); + exp = _PDCLIB_FLT_EXP( data ); + return ( exp != ( ( _PDCLIB_FLT_MAX_EXP - 1 ) + _PDCLIB_FLT_MAX_EXP ) ) && ( exp != 0 ); +} + +int _PDCLIB_isnormall( long double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( long double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + int exp; + memcpy( data, &x, sizeof( long double ) ); + exp = _PDCLIB_LDBL_EXP( data ); + return ( exp != ( ( _PDCLIB_LDBL_MAX_EXP - 1 ) + _PDCLIB_LDBL_MAX_EXP ) ) && ( exp != 0 ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + float f; + double d; + long double ld; + + f = 0.123f; + TESTCASE( isnormal( f ) ); + f = FLT_MAX; + TESTCASE( isnormal( f ) ); + f = FLT_MAX * 2; + TESTCASE( ! isnormal( f ) ); + f = FLT_MIN; + TESTCASE( isnormal( f ) ); + f = FLT_MIN / 2; + TESTCASE( ! isnormal( f ) ); + f = 0.0f; + TESTCASE( ! isnormal( f ) ); + f = 1e100; + TESTCASE( ! isnormal( f ) ); + f = 0.0 / 0.0; + TESTCASE( ! isnormal( f ) ); + + d = 0.123f; + TESTCASE( isnormal( d ) ); + d = DBL_MAX; + TESTCASE( isnormal( d ) ); + d = DBL_MAX * 2; + TESTCASE( ! isnormal( d ) ); + d = DBL_MIN; + TESTCASE( isnormal( d ) ); + d = DBL_MIN / 2; + TESTCASE( ! isnormal( d ) ); + d = 0.0f; + TESTCASE( ! isnormal( d ) ); + d = 1e500; + TESTCASE( ! isnormal( d ) ); + d = 0.0 / 0.0; + TESTCASE( ! isnormal( d ) ); + + ld = 0.123f; + TESTCASE( isnormal( ld ) ); + ld = LDBL_MAX; + TESTCASE( isnormal( ld ) ); + ld = LDBL_MAX * 2; + TESTCASE( ! isnormal( ld ) ); + ld = LDBL_MIN; + TESTCASE( isnormal( ld ) ); + ld = LDBL_MIN / 2; + TESTCASE( ! isnormal( ld ) ); + ld = 0.0f; + TESTCASE( ! isnormal( ld ) ); + ld = 1e1000; + TESTCASE( ! isnormal( ld ) ); + ld = 0.0 / 0.0; + TESTCASE( ! isnormal( ld ) ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/math/signbit.c b/rocklibc/src/math/signbit.c new file mode 100644 index 0000000..4113450 --- /dev/null +++ b/rocklibc/src/math/signbit.c @@ -0,0 +1,69 @@ +/* signbit( double ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_print.h" + +#include + +int _PDCLIB_signbitd( double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + + memcpy( data, &x, sizeof( double ) ); + return _PDCLIB_DBL_SIGN( data ) != 0; +} + +int _PDCLIB_signbitf( float x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( float ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + + memcpy( data, &x, sizeof( float ) ); + return _PDCLIB_FLT_SIGN( data ) != 0; +} + +int _PDCLIB_signbitl( long double x ) +{ + _PDCLIB_bigint_digit_t data[ sizeof( long double ) / sizeof( _PDCLIB_bigint_digit_t ) ]; + + memcpy( data, &x, sizeof( long double ) ); + return _PDCLIB_LDBL_SIGN( data ) != 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + float f; + double d; + long double ld; + + f = 0.123f; + TESTCASE( ! signbit( f ) ); + f = -0.123f; + TESTCASE( signbit( f ) ); + + d = 0.123; + TESTCASE( ! signbit( d ) ); + d = -0.123; + TESTCASE( signbit( d ) ); + + ld = 0.123l; + TESTCASE( ! signbit( ld ) ); + ld = -0.123l; + TESTCASE( signbit( ld ) ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/rockos/syscall.c b/rocklibc/src/rockos/syscall.c new file mode 100644 index 0000000..08a2a0c --- /dev/null +++ b/rocklibc/src/rockos/syscall.c @@ -0,0 +1,97 @@ +#include +#include + +typedef int _PDCLIB_fd_t; + +static inline int32_t inline_syscall(uint32_t num, uint32_t arg1, uint32_t arg2, uint32_t arg3) { + int32_t ret; + asm volatile ( + "int $0x80" + : "=a" (ret) + : "a" (num), "b" (arg1), "c" (arg2), "d" (arg3) + : "memory" + ); + return ret; +} + +void _PDCLIB_exit(int status) { + inline_syscall(1, (uint32_t)status, 0, 0); + while(1); // Halt if exit fails to yield +} + +int _PDCLIB_read(_PDCLIB_fd_t fd, void *buf, size_t count) { + return inline_syscall(3, (uint32_t)fd, (uint32_t)buf, (uint32_t)count); +} + +// 3. sys_write (eax = 4) +int _PDCLIB_write(_PDCLIB_fd_t fd, const void *buf, size_t count) { + return inline_syscall(4, (uint32_t)fd, (uint32_t)buf, (uint32_t)count); +} + +_PDCLIB_fd_t _PDCLIB_open(const char *filename, unsigned int mode) { + _PDCLIB_fd_t fd; + fd = inline_syscall(5, (uint32_t)filename, (uint32_t)mode, 0); + return fd; +} + +int _PDCLIB_close(_PDCLIB_fd_t fd) { + return inline_syscall(6, (uint32_t)fd, 0, 0); +} + +void * _PDCLIB_allocpages(size_t n) { + // n is the number of PAGES PDCLib wants (usually 4096 bytes per page) + size_t bytes_requested = n * 4096; + + // Call your sys_brk with 0 to find the current break address + uint32_t current_break = inline_syscall(12, 0, 0, 0); + + // Request the new break point + uint32_t new_break = current_break + bytes_requested; + uint32_t result = inline_syscall(12, new_break, 0, 0); + + if (result == 0) { + return (void *)current_break; // Return the start of the newly allocated region + } + return NULL; // Allocation failed +} + +int _PDCLIB_remove(const char *filename) { return -1; } +int _PDCLIB_rename(const char *old, const char *new) { return -1; } +long _PDCLIB_lseek(_PDCLIB_fd_t fd, long offset, int whence) { return -1; } + +int open(const char *pathname, int flags, ...) { + // Wrap to your internal _PDCLIB_open or inline_syscall directly + _PDCLIB_fd_t fd = _PDCLIB_open(pathname, (unsigned int)flags); + return fd; +} + +int read(int fd, void *buf, size_t count) { + _PDCLIB_fd_t file_desc = fd; + return _PDCLIB_read(file_desc, buf, count); +} + +int write(int fd, const void *buf, size_t count) { + return _PDCLIB_write(fd, buf, count); +} + +int close(int fd) { + _PDCLIB_fd_t file_desc = fd; + return _PDCLIB_close(file_desc); +} + +void _exit(int status) { + _PDCLIB_exit(status); +} + +void * sbrk(intptr_t increment) { + // If increment is 0, dlmalloc is querying the current boundary. + // For a simple implementation, let's look up memory by pages. + if (increment == 0) { + return _PDCLIB_allocpages(0); + } + + // Convert bytes requested by sbrk into page increments (4KB blocks) + // You can also change your syscall wrapper to use regular byte increments + size_t pages_needed = ((size_t)increment + 4095) / 4096; + return _PDCLIB_allocpages(pages_needed); +} \ No newline at end of file diff --git a/rocklibc/src/rockos/time.c b/rocklibc/src/rockos/time.c new file mode 100644 index 0000000..f042989 --- /dev/null +++ b/rocklibc/src/rockos/time.c @@ -0,0 +1,10 @@ +#include +#include + +int gettimeofday(struct timeval *restrict tv, void *restrict tz) { + if (tv) { + tv->tv_sec = 0; /* Default to Jan 1, 1970 */ + tv->tv_usec = 0; + } + return 0; // Return success code +} \ No newline at end of file diff --git a/rocklibc/src/rockos/times.c b/rocklibc/src/rockos/times.c new file mode 100644 index 0000000..4cdb950 --- /dev/null +++ b/rocklibc/src/rockos/times.c @@ -0,0 +1,12 @@ +#include + +clock_t times(struct tms *buffer) { + if (buffer) { + buffer->tms_utime = 0; + buffer->tms_stime = 0; + buffer->tms_cutime = 0; + buffer->tms_cstime = 0; + } + // Return -1 to safely indicate that timing information is not available + return (clock_t)-1; +} \ No newline at end of file diff --git a/rocklibc/src/signal/raise.c b/rocklibc/src/signal/raise.c new file mode 100644 index 0000000..9fb428c --- /dev/null +++ b/rocklibc/src/signal/raise.c @@ -0,0 +1,135 @@ +/* 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 + +#ifndef REGTEST + +#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 ); + 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 ) + { + /* FIXME: "The implementation shall behave as if no library function + calls the signal function." + */ + sighandler = signal( sig, SIG_DFL ); + sighandler( sig ); + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +static volatile sig_atomic_t flag = 0; + +static int expected_signal = 0; + +static void test_handler( int sig ) +{ + TESTCASE( sig == expected_signal ); + flag = 1; +} + +int main( void ) +{ + void ( *sighandler )( int ); + /* Could be other than SIG_DFL if you changed the implementation. */ + sighandler = signal( SIGABRT, SIG_IGN ); +#ifndef REGTEST + TESTCASE( sighandler == SIG_DFL ); +#endif + /* Should be ignored. */ + TESTCASE( raise( SIGABRT ) == 0 ); + /* Installing test handler, old handler should be returned */ + TESTCASE( signal( SIGABRT, test_handler ) == SIG_IGN ); + /* Raising and checking SIGABRT */ + expected_signal = SIGABRT; + TESTCASE( raise( SIGABRT ) == 0 ); + TESTCASE( flag == 1 ); + /* Re-installing test handler, should have been reset to default */ + /* Could be other than SIG_DFL if you changed the implementation. */ + sighandler = signal( SIGABRT, test_handler ); +#ifndef REGTEST + TESTCASE( sighandler == SIG_DFL ); +#endif + /* Raising and checking SIGABRT */ + flag = 0; + TESTCASE( raise( SIGABRT ) == 0 ); + TESTCASE( flag == 1 ); + /* Installing test handler for different signal... */ + TESTCASE( signal( SIGTERM, test_handler ) == SIG_DFL ); + /* Raising and checking SIGTERM */ + expected_signal = SIGTERM; + TESTCASE( raise( SIGTERM ) == 0 ); + TESTCASE( flag == 1 ); + /* void expression to avoid "unused" warning in regtest */ + (void)sighandler; + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/signal/signal.c b/rocklibc/src/signal/signal.c new file mode 100644 index 0000000..54d52ac --- /dev/null +++ b/rocklibc/src/signal/signal.c @@ -0,0 +1,84 @@ +/* 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 + +#ifndef REGTEST + +#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". + Copying Linux' behaviour of setting EINVAL. + */ + *_PDCLIB_errno_func() = _PDCLIB_EINVAL; + return SIG_ERR; + } + + return oldhandler; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by raise.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/clearerr.c b/rocklibc/src/stdio/clearerr.c new file mode 100644 index 0000000..12d8ce0 --- /dev/null +++ b/rocklibc/src/stdio/clearerr.c @@ -0,0 +1,54 @@ +/* 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 + +#ifndef REGTEST + +void clearerr( struct _PDCLIB_file_t * stream ) +{ + stream->status &= ~( _PDCLIB_ERRORFLAG | _PDCLIB_EOFFLAG ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + FILE * fh; + TESTCASE( ( fh = tmpfile() ) != NULL ); + /* Flags should be clear */ + TESTCASE( ! ferror( fh ) ); + TESTCASE( ! feof( fh ) ); + /* Reading from empty stream - should provoke EOF */ + rewind( fh ); + TESTCASE( fgetc( fh ) == EOF ); + TESTCASE( ! ferror( fh ) ); + TESTCASE( feof( fh ) ); + /* clearerr() should clear flags */ + clearerr( fh ); + TESTCASE( ! ferror( fh ) ); + TESTCASE( ! feof( fh ) ); +#ifndef __ANDROID__ + /* reopen() the file write-only -- this fails on Termix */ + TESTCASE( ( fh = freopen( NULL, "w", fh ) ) != NULL ); + /* Reading from write-only stream - should provoke error */ + TESTCASE( fgetc( fh ) == EOF ); + TESTCASE( ferror( fh ) ); + TESTCASE( ! feof( fh ) ); +#endif + /* clearerr() should clear flags */ + clearerr( fh ); + TESTCASE( ! ferror( fh ) ); + TESTCASE( ! feof( fh ) ); + TESTCASE( fclose( fh ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fclose.c b/rocklibc/src/stdio/fclose.c new file mode 100644 index 0000000..23e01c4 --- /dev/null +++ b/rocklibc/src/stdio/fclose.c @@ -0,0 +1,117 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_filelist_mtx; +#endif + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +int fclose( struct _PDCLIB_file_t * stream ) +{ + _PDCLIB_LOCK( _PDCLIB_filelist_mtx ); + _PDCLIB_LOCK( stream->mtx ); + + /* Flush buffer */ + if ( stream->status & _PDCLIB_FWRITE ) + { + if ( _PDCLIB_flushbuffer( stream ) == EOF ) + { + /* Flush failed, errno already set */ + _PDCLIB_UNLOCK( stream->mtx ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return EOF; + } + } + + /* Close handle */ + _PDCLIB_close( stream->handle ); + + /* Remove stream from list */ + if ( _PDCLIB_getstream( stream ) ) + { + _PDCLIB_UNLOCK( stream->mtx ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return EOF; + } + + /* Delete tmpfile() */ + if ( stream->status & _PDCLIB_DELONCLOSE ) + { + _PDCLIB_remove( stream->filename ); + } + + /* Free buffer */ + if ( stream->status & _PDCLIB_FREEBUFFER ) + { + free( stream->buffer ); + } + + /* Free filename (standard streams do not have one, but free( NULL ) + is a valid no-op) + */ + free( stream->filename ); + + _PDCLIB_UNLOCK( stream->mtx ); + +#ifndef __STDC_NO_THREADS__ + mtx_destroy( &stream->mtx ); +#endif + + /* Free stream */ + if ( stream != stdin && stream != stdout && stream != stderr ) + { + free( stream ); + } + + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + struct _PDCLIB_file_t * file1; + struct _PDCLIB_file_t * file2; + remove( testfile1 ); + remove( testfile2 ); + TESTCASE( _PDCLIB_filelist == stdin ); + TESTCASE( ( file1 = fopen( testfile1, "w" ) ) != NULL ); + TESTCASE( _PDCLIB_filelist == file1 ); + TESTCASE( ( file2 = fopen( testfile2, "w" ) ) != NULL ); + TESTCASE( _PDCLIB_filelist == file2 ); + TESTCASE( fclose( file2 ) == 0 ); + TESTCASE( _PDCLIB_filelist == file1 ); + TESTCASE( ( file2 = fopen( testfile2, "w" ) ) != NULL ); + TESTCASE( _PDCLIB_filelist == file2 ); + TESTCASE( fclose( file1 ) == 0 ); + TESTCASE( _PDCLIB_filelist == file2 ); + TESTCASE( fclose( file2 ) == 0 ); + TESTCASE( _PDCLIB_filelist == stdin ); + TESTCASE( remove( testfile1 ) == 0 ); + TESTCASE( remove( testfile2 ) == 0 ); +#else + puts( " NOTEST fclose() test driver is PDCLib-specific." ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/feof.c b/rocklibc/src/stdio/feof.c new file mode 100644 index 0000000..a57071f --- /dev/null +++ b/rocklibc/src/stdio/feof.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +int feof( struct _PDCLIB_file_t * stream ) +{ + return stream->status & _PDCLIB_EOFFLAG; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by clearerr(). */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/ferror.c b/rocklibc/src/stdio/ferror.c new file mode 100644 index 0000000..54f43f0 --- /dev/null +++ b/rocklibc/src/stdio/ferror.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +int ferror( struct _PDCLIB_file_t * stream ) +{ + return stream->status & _PDCLIB_ERRORFLAG; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by clearerr(). */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fflush.c b/rocklibc/src/stdio/fflush.c new file mode 100644 index 0000000..8f73bae --- /dev/null +++ b/rocklibc/src/stdio/fflush.c @@ -0,0 +1,71 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_filelist_mtx; +#endif + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +int fflush( struct _PDCLIB_file_t * stream ) +{ + int rc = 0; + + if ( stream == NULL ) + { + _PDCLIB_LOCK( _PDCLIB_filelist_mtx ); + stream = _PDCLIB_filelist; + + /* TODO: Check what happens when fflush( NULL ) encounters write errors, in other libs */ + while ( stream != NULL ) + { + _PDCLIB_LOCK( stream->mtx ); + + if ( stream->status & _PDCLIB_FWRITE ) + { + if ( _PDCLIB_flushbuffer( stream ) == EOF ) + { + rc = EOF; + } + } + + _PDCLIB_UNLOCK( stream->mtx ); + + stream = stream->next; + } + + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + } + else + { + _PDCLIB_LOCK( stream->mtx ); + rc = _PDCLIB_flushbuffer( stream ); + _PDCLIB_UNLOCK( stream->mtx ); + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fgetc.c b/rocklibc/src/stdio/fgetc.c new file mode 100644 index 0000000..7dec82f --- /dev/null +++ b/rocklibc/src/stdio/fgetc.c @@ -0,0 +1,48 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int fgetc( struct _PDCLIB_file_t * stream ) +{ + int rc = EOF; + + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepread( stream ) != EOF ) + { + if ( _PDCLIB_CHECKBUFFER( stream ) != EOF ) + { + rc = _PDCLIB_GETC( stream ); + } + } + + _PDCLIB_UNLOCK( stream->mtx ); + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fgetpos.c b/rocklibc/src/stdio/fgetpos.c new file mode 100644 index 0000000..eb3d74f --- /dev/null +++ b/rocklibc/src/stdio/fgetpos.c @@ -0,0 +1,49 @@ +/* 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 + +#ifndef REGTEST + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int fgetpos( struct _PDCLIB_file_t * _PDCLIB_restrict stream, struct _PDCLIB_fpos_t * _PDCLIB_restrict pos ) +{ + _PDCLIB_LOCK( stream->mtx ); + pos->offset = ( stream->pos.offset - ( ( ( int )stream->bufend - ( int )stream->bufidx ) + stream->ungetidx ) ); + pos->status = stream->pos.status; + /* TODO: Add mbstate. */ + _PDCLIB_UNLOCK( stream->mtx ); + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + FILE * fh; + fpos_t pos1, pos2; + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( fgetpos( fh, &pos1 ) == 0 ); + TESTCASE( fwrite( teststring, 1, strlen( teststring ), fh ) == strlen( teststring ) ); + TESTCASE( fgetpos( fh, &pos2 ) == 0 ); + TESTCASE( fsetpos( fh, &pos1 ) == 0 ); + TESTCASE( ftell( fh ) == 0 ); + TESTCASE( fsetpos( fh, &pos2 ) == 0 ); + TESTCASE( ( size_t )ftell( fh ) == strlen( teststring ) ); + TESTCASE( fclose( fh ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fgets.c b/rocklibc/src/stdio/fgets.c new file mode 100644 index 0000000..12550b7 --- /dev/null +++ b/rocklibc/src/stdio/fgets.c @@ -0,0 +1,98 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +char * fgets( char * _PDCLIB_restrict s, int size, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + char * dest = s; + + if ( size == 0 ) + { + return NULL; + } + + if ( size == 1 ) + { + *s = '\0'; + return s; + } + + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepread( stream ) != EOF ) + { + do + { + if ( _PDCLIB_CHECKBUFFER( 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; + } + } + while ( ( ( *dest++ = _PDCLIB_GETC( stream ) ) != '\n' ) && ( --size > 0 ) ); + } + + _PDCLIB_UNLOCK( stream->mtx ); + + *dest = '\0'; + return ( dest == s ) ? NULL : s; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + FILE * fh; + char buffer[10]; + const char * fgets_test = "foo\nbar\0baz\nweenie"; + TESTCASE( ( fh = fopen( testfile, "wb+" ) ) != NULL ); + TESTCASE( fwrite( fgets_test, 1, 18, fh ) == 18 ); + rewind( fh ); + TESTCASE( fgets( buffer, 10, fh ) == buffer ); + TESTCASE( strcmp( buffer, "foo\n" ) == 0 ); + TESTCASE( fgets( buffer, 10, fh ) == buffer ); + TESTCASE( memcmp( buffer, "bar\0baz\n", 8 ) == 0 ); + TESTCASE( fgets( buffer, 10, fh ) == buffer ); + TESTCASE( strcmp( buffer, "weenie" ) == 0 ); + TESTCASE( feof( fh ) ); + TESTCASE( fseek( fh, -1, SEEK_END ) == 0 ); + /* newlib returns NULL on any n < 2, so we _NOREG these tests. */ + TESTCASE_NOREG( fgets( buffer, 1, fh ) == buffer ); + TESTCASE_NOREG( strcmp( buffer, "" ) == 0 ); + TESTCASE( fgets( buffer, 0, fh ) == NULL ); + TESTCASE( ! feof( fh ) ); + TESTCASE_NOREG( fgets( buffer, 1, fh ) == buffer ); + TESTCASE_NOREG( strcmp( buffer, "" ) == 0 ); + TESTCASE( ! feof( fh ) ); + TESTCASE( fgets( buffer, 2, fh ) == buffer ); + TESTCASE( strcmp( buffer, "e" ) == 0 ); + TESTCASE( fseek( fh, 0, SEEK_END ) == 0 ); + TESTCASE( fgets( buffer, 2, fh ) == NULL ); + TESTCASE( feof( fh ) ); + TESTCASE( fclose( fh ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fopen.c b/rocklibc/src/stdio/fopen.c new file mode 100644 index 0000000..3553e82 --- /dev/null +++ b/rocklibc/src/stdio/fopen.c @@ -0,0 +1,104 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#include + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_filelist_mtx; +#endif + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode ) +{ + struct _PDCLIB_file_t * rc; + unsigned int filemode = _PDCLIB_filemode( mode ); + + if ( filemode == 0 ) + { + /* mode invalid */ + return NULL; + } + + if ( filename == NULL || filename[0] == '\0' ) + { + /* filename invalid */ + return NULL; + } + + /* See tmpfile(), which does much of the same. */ + + if ( ( rc = _PDCLIB_init_file_t( NULL ) ) == NULL ) + { + /* initializing FILE structure failed */ + return NULL; + } + + /* 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 |= filemode | _IOLBF; + + /* _PDCLIB_realpath() gives us an absolute path to the file, which + a later reopen() would need. + */ + if ( ( rc->handle = _PDCLIB_open( filename, rc->status ) ) == _PDCLIB_NOHANDLE + || ( rc->filename = _PDCLIB_realpath( filename ) ) == NULL ) + { + /* OS open() or realpath() failed */ +#ifndef __STDC_NO_THREADS__ + mtx_destroy( &rc->mtx ); +#endif + free( rc->buffer ); + free( rc ); + return NULL; + } + + /* Adding to list of open files */ + _PDCLIB_LOCK( _PDCLIB_filelist_mtx ); + rc->next = _PDCLIB_filelist; + _PDCLIB_filelist = rc; + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Some of the tests are not executed for regression tests, as the libc on + my system is at once less forgiving (segfaults on mode NULL) and more + forgiving (accepts undefined modes). + */ + FILE * fh; + remove( testfile ); + TESTCASE_NOREG( fopen( NULL, NULL ) == NULL ); + TESTCASE_NOREG( fopen( NULL, "w" ) == NULL ); + TESTCASE_NOREG( fopen( "", NULL ) == NULL ); + TESTCASE( fopen( "", "w" ) == NULL ); + TESTCASE( fopen( testfile, "" ) == NULL ); + TESTCASE_NOREG( fopen( testfile, "wq" ) == NULL ); /* Undefined mode */ + TESTCASE_NOREG( fopen( testfile, "wr" ) == NULL ); /* Undefined mode */ + TESTCASE( ( fh = fopen( testfile, "w" ) ) != NULL ); + TESTCASE( fclose( fh ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fopen_s.c b/rocklibc/src/stdio/fopen_s.c new file mode 100644 index 0000000..17ce907 --- /dev/null +++ b/rocklibc/src/stdio/fopen_s.c @@ -0,0 +1,79 @@ +/* fopen_s( FILE **, 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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include + +#ifndef REGTEST + +errno_t fopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode ) +{ + if ( streamptr == NULL || filename == NULL || mode == NULL ) + { + if ( streamptr != NULL ) + { + *streamptr = NULL; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + if ( ( *streamptr = fopen( filename, mode ) ) == NULL ) + { + return *_PDCLIB_errno_func(); + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + /* Some of the tests are not executed for regression tests, as the libc on + my system is at once less forgiving (segfaults on mode NULL) and more + forgiving (accepts undefined modes). + */ + FILE * fh; + remove( testfile ); + set_constraint_handler_s( test_handler ); + + TESTCASE( fopen_s( NULL, NULL, NULL ) != 0 ); + TESTCASE( fopen_s( &fh, NULL, "w" ) != 0 ); + TESTCASE( fopen_s( &fh, "", "w" ) != 0 ); + TESTCASE( fopen_s( &fh, testfile, "" ) != 0 ); + TESTCASE( fopen_s( &fh, testfile, NULL ) != 0 ); + TESTCASE( fopen_s( &fh, testfile, "wq" ) != 0 ); + TESTCASE( fopen_s( &fh, testfile, "wr" ) != 0 ); + TESTCASE( fopen_s( &fh, testfile, "w" ) == 0 ); + TESTCASE( fclose( fh ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + TESTCASE( HANDLER_CALLS == 3 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fprintf.c b/rocklibc/src/stdio/fprintf.c new file mode 100644 index 0000000..522f161 --- /dev/null +++ b/rocklibc/src/stdio/fprintf.c @@ -0,0 +1,46 @@ +/* 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 + +#ifndef REGTEST + +int fprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vfprintf( stream, format, ap ); + va_end( ap ); + return rc; +} + +#endif + +#ifdef TEST + +#include +#include +#include + +#define _PDCLIB_FILEID "stdio/fprintf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +#define testprintf( stream, ... ) fprintf( stream, __VA_ARGS__ ) + +int main( void ) +{ + FILE * target; + TESTCASE( ( target = tmpfile() ) != NULL ); +#include "printf_testcases.h" + TESTCASE( fclose( target ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fputc.c b/rocklibc/src/stdio/fputc.c new file mode 100644 index 0000000..bcf1e61 --- /dev/null +++ b/rocklibc/src/stdio/fputc.c @@ -0,0 +1,55 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int fputc( int c, struct _PDCLIB_file_t * stream ) +{ + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepwrite( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + 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. */ + c = ( _PDCLIB_flushbuffer( stream ) == 0 ) ? c : EOF; + } + + _PDCLIB_UNLOCK( stream->mtx ); + + return c; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fputs.c b/rocklibc/src/stdio/fputs.c new file mode 100644 index 0000000..5f9df7d --- /dev/null +++ b/rocklibc/src/stdio/fputs.c @@ -0,0 +1,87 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int fputs( const char * _PDCLIB_restrict s, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepwrite( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + 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 ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + } + + ++s; + } + + if ( stream->status & _IONBF ) + { + if ( _PDCLIB_flushbuffer( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + } + + _PDCLIB_UNLOCK( stream->mtx ); + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + const char * const message = "SUCCESS testing fputs()"; + FILE * fh; + size_t i; + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( fputs( message, fh ) >= 0 ); + rewind( fh ); + + for ( i = 0; i < 23; ++i ) + { + TESTCASE( fgetc( fh ) == message[i] ); + } + + TESTCASE( fclose( fh ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fread.c b/rocklibc/src/stdio/fread.c new file mode 100644 index 0000000..8d2cde8 --- /dev/null +++ b/rocklibc/src/stdio/fread.c @@ -0,0 +1,93 @@ +/* fread( void *, size_t, size_t, struct * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +size_t fread( void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + char * dest = ( char * )ptr; + size_t nmemb_i = 0; + + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepread( stream ) != EOF ) + { + for ( nmemb_i = 0; nmemb_i < nmemb; ++nmemb_i ) + { + size_t size_i; + + /* TODO: For better performance, move from stream buffer + to destination block-wise, not byte-wise. + */ + for ( size_i = 0; size_i < size; ++size_i ) + { + if ( _PDCLIB_CHECKBUFFER( stream ) == EOF ) + { + /* Could not read requested data */ + _PDCLIB_UNLOCK( stream->mtx ); + return nmemb_i; + } + + dest[ nmemb_i * size + size_i ] = _PDCLIB_GETC( stream ); + } + } + } + + _PDCLIB_UNLOCK( stream->mtx ); + + return nmemb_i; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + FILE * fh; + const char * message = "Testing fwrite()...\n"; + char buffer[21]; + buffer[20] = 'x'; + TESTCASE( ( fh = tmpfile() ) != NULL ); + /* fwrite() / readback */ + TESTCASE( fwrite( message, 1, 20, fh ) == 20 ); + rewind( fh ); + TESTCASE( fread( buffer, 1, 20, fh ) == 20 ); + TESTCASE( memcmp( buffer, message, 20 ) == 0 ); + TESTCASE( buffer[20] == 'x' ); + /* same, different nmemb / size settings */ + rewind( fh ); + TESTCASE( memset( buffer, '\0', 20 ) == buffer ); + TESTCASE( fwrite( message, 5, 4, fh ) == 4 ); + rewind( fh ); + TESTCASE( fread( buffer, 5, 4, fh ) == 4 ); + TESTCASE( memcmp( buffer, message, 20 ) == 0 ); + TESTCASE( buffer[20] == 'x' ); + /* same... */ + rewind( fh ); + TESTCASE( memset( buffer, '\0', 20 ) == buffer ); + TESTCASE( fwrite( message, 20, 1, fh ) == 1 ); + rewind( fh ); + TESTCASE( fread( buffer, 20, 1, fh ) == 1 ); + TESTCASE( memcmp( buffer, message, 20 ) == 0 ); + TESTCASE( buffer[20] == 'x' ); + /* Done. */ + TESTCASE( fclose( fh ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/freopen.c b/rocklibc/src/stdio/freopen.c new file mode 100644 index 0000000..960dd6c --- /dev/null +++ b/rocklibc/src/stdio/freopen.c @@ -0,0 +1,242 @@ +/* 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 +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_filelist_mtx; +#endif + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +struct _PDCLIB_file_t * freopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + unsigned int filemode = _PDCLIB_filemode( mode ); + + if ( stream == NULL ) + { + errno = EBADF; + return NULL; + } + + _PDCLIB_LOCK( _PDCLIB_filelist_mtx ); + + if ( _PDCLIB_isstream( stream, NULL ) ) + { + /* May lock only after established that stream is valid */ + _PDCLIB_LOCK( stream->mtx ); + + /* Flush buffer */ + if ( stream->status & _PDCLIB_FWRITE ) + { + _PDCLIB_flushbuffer( stream ); + } + + if ( filename == NULL ) + { + /* Attempt to change mode without closing stream */ + switch ( _PDCLIB_changemode( stream, filemode ) ) + { + case INT_MIN: + /* fail completely */ + _PDCLIB_UNLOCK( stream->mtx ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return NULL; + + case 0: + /* fail; try close / reopen */ + filename = stream->filename; + /* Setting to NULL to make the free() below a non-op. */ + stream->filename = NULL; + break; + + default: + /* success */ + _PDCLIB_UNLOCK( stream->mtx ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return stream; + } + } + + /* Close handle */ + _PDCLIB_close( stream->handle ); + + /* Remove stream from list */ + _PDCLIB_getstream( stream ); + + /* Delete tmpfile() */ + if ( stream->status & _PDCLIB_DELONCLOSE ) + { + /* Have to switch here; stream->filename may have moved to + filename after failed in-place mode change above. + */ + _PDCLIB_remove( ( stream->filename == NULL ) ? filename : stream->filename ); + stream->status &= ~_PDCLIB_DELONCLOSE; + } + + /* Free buffer */ + if ( stream->status & _PDCLIB_FREEBUFFER ) + { + free( stream->buffer ); + } + + if ( filename == NULL ) + { + /* Input was filename NULL, stream->filename NULL. + No filename means there is nothing to reopen. In-place + mode change was already attempted (and failed) above. + */ + return NULL; + } + else + { + /* We have a filename, either from input or (if filename + was NULL) from stream. We will attempt the re-open with + that, and will retrieve _PDCLIB_realpath() from that. + So stream->filename is no longer needed. + */ + free( stream->filename ); + } + } + else + { + /* Not a valid stream. As _PDCLIB_init_file_t() cannot tell the + difference, only knows that it has been called by freopen() + (by the non-NULL parameter), we need to initialize the mutex + here (so that either way, _PDCLIB_init_file_t() gets a pre- + initialized mutex). + */ +#ifndef __STDC_NO_THREADS__ + if ( mtx_init( &stream->mtx, mtx_plain | mtx_recursive ) != thrd_success ) + { + /* Could not initialize stream mutex */ + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return NULL; + } + +#endif + + /* Locking the mutex, so we come out of the if-else with a locked + mutex either way. + */ + _PDCLIB_LOCK( stream->mtx ); + } + + /* Stream is closed, or never was open (even though its mutex exists + and is locked) at this point. + Now we check if we have the whereabouts to open it. + */ + + if ( filemode == 0 ) + { + /* Mode invalid */ + _PDCLIB_UNLOCK( stream->mtx ); +#ifndef __STDC_NO_THREADS__ + mtx_destroy( &stream->mtx ); +#endif + free( stream->filename ); + free( stream ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return NULL; + } + + if ( filename == NULL || filename[0] == '\0' ) + { + /* No filename available (standard stream?) */ + _PDCLIB_UNLOCK( stream->mtx ); +#ifndef __STDC_NO_THREADS__ + mtx_destroy( &stream->mtx ); +#endif + free( stream->filename ); + free( stream ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return NULL; + } + + /* (Re-)initializing the structure. */ + if ( _PDCLIB_init_file_t( stream ) == NULL ) + { + /* Re-init failed. */ + _PDCLIB_UNLOCK( stream->mtx ); +#ifndef __STDC_NO_THREADS__ + mtx_destroy( &stream->mtx ); +#endif + free( stream->filename ); + free( stream ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return NULL; + } + + /* Resetting buffer mode and filemode */ + stream->status |= filemode | _IOLBF; + + /* Attempt open */ + if ( ( stream->handle = _PDCLIB_open( filename, stream->status ) ) == _PDCLIB_NOHANDLE ) + { + /* OS open() failed */ + _PDCLIB_UNLOCK( stream->mtx ); +#ifndef __STDC_NO_THREADS__ + mtx_destroy( &stream->mtx ); +#endif + free( stream->filename ); + free( stream->buffer ); + free( stream ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return NULL; + } + + /* Getting absolute filename */ + stream->filename = _PDCLIB_realpath( filename ); + + /* Adding to list of open files */ + stream->next = _PDCLIB_filelist; + _PDCLIB_filelist = stream; + + _PDCLIB_UNLOCK( stream->mtx ); + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + + return stream; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + FILE * fin; + FILE * fout; + TESTCASE( ( fin = fopen( testfile1, "wb+" ) ) != NULL ); + TESTCASE( fputc( 'x', fin ) == 'x' ); + TESTCASE( fclose( fin ) == 0 ); + TESTCASE( ( fin = freopen( testfile1, "rb", stdin ) ) != NULL ); + TESTCASE( getchar() == 'x' ); + + TESTCASE( ( fout = freopen( testfile2, "wb+", stdout ) ) != NULL ); + TESTCASE( putchar( 'x' ) == 'x' ); + rewind( fout ); + TESTCASE( fgetc( fout ) == 'x' ); + + TESTCASE( fclose( fin ) == 0 ); + TESTCASE( fclose( fout ) == 0 ); + TESTCASE( remove( testfile1 ) == 0 ); + TESTCASE( remove( testfile2 ) == 0 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/freopen_s.c b/rocklibc/src/stdio/freopen_s.c new file mode 100644 index 0000000..f5c7b07 --- /dev/null +++ b/rocklibc/src/stdio/freopen_s.c @@ -0,0 +1,88 @@ +/* freopen_s( FILE **, 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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include + +#ifndef REGTEST + +_PDCLIB_PUBLIC errno_t freopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict newstreamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, FILE * _PDCLIB_restrict stream ) +{ + if ( newstreamptr == NULL || mode == NULL || stream == NULL ) + { + if ( newstreamptr != NULL ) + { + *newstreamptr = NULL; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + if ( ( *newstreamptr = freopen( filename, mode, stream ) ) == NULL ) + { + return *_PDCLIB_errno_func(); + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + FILE * fin; + FILE * fout; + FILE * dummy; + set_constraint_handler_s( test_handler ); + + TESTCASE( ( fin = fopen( testfile1, "wb+" ) ) != NULL ); + TESTCASE( fputc( 'x', fin ) == 'x' ); + TESTCASE( fclose( fin ) == 0 ); + TESTCASE( freopen_s( &fin, testfile1, "rb", stdin ) == 0 ); + TESTCASE( getchar() == 'x' ); + + TESTCASE( freopen_s( &fout, testfile2, "wb+", stdout ) == 0 ); + TESTCASE( putchar( 'x' ) == 'x' ); + rewind( fout ); + TESTCASE( fgetc( fout ) == 'x' ); + + dummy = fin; + TESTCASE( freopen_s( &dummy, testfile1, "rb", NULL ) != 0 ); + dummy = fin; + TESTCASE( freopen_s( &dummy, testfile1, NULL, stdin ) != 0 ); + TESTCASE( freopen_s( NULL, testfile1, "rb", fin ) != 0 ); + + TESTCASE( fclose( fin ) == 0 ); + TESTCASE( fclose( fout ) == 0 ); + TESTCASE( remove( testfile1 ) == 0 ); + TESTCASE( remove( testfile2 ) == 0 ); + + TESTCASE( HANDLER_CALLS == 3 ); +#else + TESTCASE( NO_TESTDRIVER ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fscanf.c b/rocklibc/src/stdio/fscanf.c new file mode 100644 index 0000000..b828141 --- /dev/null +++ b/rocklibc/src/stdio/fscanf.c @@ -0,0 +1,41 @@ +/* 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 + +#ifndef REGTEST + +int fscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vfscanf( stream, format, ap ); + va_end( ap ); + return rc; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "stdio/fscanf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +#define testscanf( stream, format, ... ) fscanf( stream, format, __VA_ARGS__ ) + +int main( void ) +{ + FILE * source; + TESTCASE( ( source = fopen( testfile, "wb+" ) ) != NULL ); +#include "scanf_testcases.h" + TESTCASE( fclose( source ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fseek.c b/rocklibc/src/stdio/fseek.c new file mode 100644 index 0000000..1da70c2 --- /dev/null +++ b/rocklibc/src/stdio/fseek.c @@ -0,0 +1,103 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int fseek( struct _PDCLIB_file_t * stream, long offset, int whence ) +{ + int rc; + _PDCLIB_LOCK( stream->mtx ); + + if ( stream->status & _PDCLIB_FWRITE ) + { + if ( _PDCLIB_flushbuffer( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + } + + stream->status &= ~ _PDCLIB_EOFFLAG; + + if ( stream->status & _PDCLIB_FRW ) + { + stream->status &= ~( _PDCLIB_FREAD | _PDCLIB_FWRITE ); + } + + if ( whence == SEEK_CUR ) + { + offset -= ( ( ( int )stream->bufend - ( int )stream->bufidx ) + stream->ungetidx ); + } + + rc = ( _PDCLIB_seek( stream, offset, whence ) != EOF ) ? 0 : EOF; + _PDCLIB_UNLOCK( stream->mtx ); + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + FILE * fh; + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( fwrite( teststring, 1, strlen( teststring ), fh ) == strlen( teststring ) ); + /* General functionality */ + TESTCASE( fseek( fh, -1, SEEK_END ) == 0 ); + TESTCASE( ( size_t )ftell( fh ) == strlen( teststring ) - 1 ); + TESTCASE( fseek( fh, 0, SEEK_END ) == 0 ); + TESTCASE( ( size_t )ftell( fh ) == strlen( teststring ) ); + TESTCASE( fseek( fh, 0, SEEK_SET ) == 0 ); + TESTCASE( ftell( fh ) == 0 ); + TESTCASE( fseek( fh, 5, SEEK_CUR ) == 0 ); + TESTCASE( ftell( fh ) == 5 ); + TESTCASE( fseek( fh, -3, SEEK_CUR ) == 0 ); + TESTCASE( ftell( fh ) == 2 ); + /* Checking behaviour around EOF */ + TESTCASE( fseek( fh, 0, SEEK_END ) == 0 ); + TESTCASE( ! feof( fh ) ); + TESTCASE( fgetc( fh ) == EOF ); + TESTCASE( feof( fh ) ); + TESTCASE( fseek( fh, 0, SEEK_END ) == 0 ); + TESTCASE( ! feof( fh ) ); + /* Checking undo of ungetc() */ + TESTCASE( fseek( fh, 0, SEEK_SET ) == 0 ); + TESTCASE( fgetc( fh ) == teststring[0] ); + TESTCASE( fgetc( fh ) == teststring[1] ); + TESTCASE( fgetc( fh ) == teststring[2] ); + TESTCASE( ftell( fh ) == 3 ); + TESTCASE( ungetc( teststring[2], fh ) == teststring[2] ); + TESTCASE( ftell( fh ) == 2 ); + TESTCASE( fgetc( fh ) == teststring[2] ); + TESTCASE( ftell( fh ) == 3 ); + TESTCASE( ungetc( 'x', fh ) == 'x' ); + TESTCASE( ftell( fh ) == 2 ); + TESTCASE( fgetc( fh ) == 'x' ); + TESTCASE( ungetc( 'x', fh ) == 'x' ); + TESTCASE( ftell( fh ) == 2 ); + TESTCASE( fseek( fh, 2, SEEK_SET ) == 0 ); + TESTCASE( fgetc( fh ) == teststring[2] ); + /* Checking error handling */ + TESTCASE( fseek( fh, -5, SEEK_SET ) == -1 ); + TESTCASE( fseek( fh, 0, SEEK_END ) == 0 ); + TESTCASE( fclose( fh ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fsetpos.c b/rocklibc/src/stdio/fsetpos.c new file mode 100644 index 0000000..638493a --- /dev/null +++ b/rocklibc/src/stdio/fsetpos.c @@ -0,0 +1,56 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int fsetpos( struct _PDCLIB_file_t * stream, const struct _PDCLIB_fpos_t * pos ) +{ + _PDCLIB_LOCK( stream->mtx ); + + if ( stream->status & _PDCLIB_FWRITE ) + { + if ( _PDCLIB_flushbuffer( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + } + + if ( _PDCLIB_seek( stream, pos->offset, SEEK_SET ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + + stream->pos.status = pos->status; + /* TODO: Add mbstate. */ + + _PDCLIB_UNLOCK( stream->mtx ); + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* fsetpos() tested together with fsetpos(). */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/ftell.c b/rocklibc/src/stdio/ftell.c new file mode 100644 index 0000000..13cfa2d --- /dev/null +++ b/rocklibc/src/stdio/ftell.c @@ -0,0 +1,113 @@ +/* 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 + +#ifndef REGTEST + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +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. + */ + long int rc; + _PDCLIB_LOCK( stream->mtx ); + + if ( ( stream->pos.offset - stream->bufend ) > ( LONG_MAX - ( stream->bufidx - stream->ungetidx ) ) ) + { + /* integer overflow */ + _PDCLIB_UNLOCK( stream->mtx ); + *_PDCLIB_errno_func() = _PDCLIB_ERANGE; + return -1; + } + + rc = ( stream->pos.offset - ( ( ( int )stream->bufend - ( int )stream->bufidx ) + stream->ungetidx ) ); + _PDCLIB_UNLOCK( stream->mtx ); + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + /* Testing all the basic I/O functions individually would result in lots + of duplicated code, so I took the liberty of lumping it all together + here. + */ + /* The following functions delegate their tests to here: + fgetc fflush rewind fputc ungetc fseek + flushbuffer seek fillbuffer prepread prepwrite + */ + char buffer[4]; + FILE * fh; + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( setvbuf( fh, buffer, _IOLBF, 4 ) == 0 ); + /* Testing ungetc() at offset 0 */ + rewind( fh ); + TESTCASE( ungetc( 'x', fh ) == 'x' ); + TESTCASE( ftell( fh ) == -1l ); + rewind( fh ); + TESTCASE( ftell( fh ) == 0l ); + /* Commence "normal" tests */ + TESTCASE( fputc( '1', fh ) == '1' ); + TESTCASE( fputc( '2', fh ) == '2' ); + TESTCASE( fputc( '3', fh ) == '3' ); + /* Positions incrementing as expected? */ + TESTCASE( ftell( fh ) == 3l ); + TESTCASE_NOREG( fh->pos.offset == 0l ); + TESTCASE_NOREG( fh->bufidx == 3l ); + /* Buffer properly flushed when full? */ + TESTCASE( fputc( '4', fh ) == '4' ); + TESTCASE_NOREG( fh->pos.offset == 4l ); + TESTCASE_NOREG( fh->bufidx == 0 ); + /* fflush() resetting positions as expected? */ + TESTCASE( fputc( '5', fh ) == '5' ); + TESTCASE( fflush( fh ) == 0 ); + TESTCASE( ftell( fh ) == 5l ); + TESTCASE_NOREG( fh->pos.offset == 5l ); + TESTCASE_NOREG( fh->bufidx == 0l ); + /* rewind() resetting positions as expected? */ + rewind( fh ); + TESTCASE( ftell( fh ) == 0l ); + TESTCASE_NOREG( fh->pos.offset == 0 ); + TESTCASE_NOREG( fh->bufidx == 0 ); + /* Reading back first character after rewind for basic read check */ + TESTCASE( fgetc( fh ) == '1' ); + /* Check that SEEK_CUR actually uses internal position */ + TESTCASE( fseek( fh, 1l, SEEK_CUR ) == 0 ); + TESTCASE( ftell( fh ) == 2l ); + /* TODO: t.b.c. */ + TESTCASE( fclose( fh ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/fwrite.c b/rocklibc/src/stdio/fwrite.c new file mode 100644 index 0000000..6149f73 --- /dev/null +++ b/rocklibc/src/stdio/fwrite.c @@ -0,0 +1,117 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + _PDCLIB_size_t offset = 0; + /* TODO: lineend */ + /* int lineend = 0; */ + size_t nmemb_i; + + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepwrite( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + 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 */ + _PDCLIB_UNLOCK( stream->mtx ); + return nmemb_i; + } + + offset = 0; + /* 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. + */ + _PDCLIB_UNLOCK( stream->mtx ); + return nmemb_i - 1; + } + + break; + + case _IOLBF: + if ( offset > 0 ) + { + size_t bufidx = stream->bufidx; + stream->bufidx = offset; + + if ( _PDCLIB_flushbuffer( stream ) == EOF ) + { + /* See comment above. */ + stream->bufidx = bufidx; + _PDCLIB_UNLOCK( stream->mtx ); + return nmemb_i - 1; + } + + stream->bufidx = bufidx - offset; + memmove( stream->buffer, stream->buffer + offset, stream->bufidx ); + } + } + + _PDCLIB_UNLOCK( stream->mtx ); + return nmemb_i; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by fread(). */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/getc.c b/rocklibc/src/stdio/getc.c new file mode 100644 index 0000000..3d082b3 --- /dev/null +++ b/rocklibc/src/stdio/getc.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +int getc( struct _PDCLIB_file_t * stream ) +{ + return fgetc( stream ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/getchar.c b/rocklibc/src/stdio/getchar.c new file mode 100644 index 0000000..34ee545 --- /dev/null +++ b/rocklibc/src/stdio/getchar.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +int getchar( void ) +{ + return fgetc( stdin ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/perror.c b/rocklibc/src/stdio/perror.c new file mode 100644 index 0000000..c84961a --- /dev/null +++ b/rocklibc/src/stdio/perror.c @@ -0,0 +1,67 @@ +/* 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 + +#ifndef REGTEST + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +/* TODO: Doing this via a static array is not the way to do it. */ +void perror( const char * s ) +{ + _PDCLIB_LOCK( stderr->mtx ); + + if ( ( s != NULL ) && ( s[0] != '\n' ) ) + { + fprintf( stderr, "%s: ", s ); + } + + if ( errno >= _PDCLIB_ERRNO_MAX || errno < 0 ) + { + fprintf( stderr, "%s\n", _PDCLIB_EUNKNOWN_TEXT ); + } + else + { + fprintf( stderr, "%s\n", _PDCLIB_lc_messages->errno_texts[errno] ); + } + + _PDCLIB_UNLOCK( stderr->mtx ); + return; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include +#include + +int main( void ) +{ + FILE * fh; + unsigned long long max = ULLONG_MAX; + char buffer[100]; + sprintf( buffer, "%llu", max ); + TESTCASE( ( fh = freopen( testfile, "wb+", stderr ) ) != NULL ); + TESTCASE( strtol( buffer, NULL, 10 ) == LONG_MAX ); + perror( "Test" ); + rewind( fh ); + TESTCASE( fread( buffer, 1, 7, fh ) == 7 ); + TESTCASE( memcmp( buffer, "Test: ", 6 ) == 0 ); + TESTCASE( fclose( fh ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/printf.c b/rocklibc/src/stdio/printf.c new file mode 100644 index 0000000..5db0a45 --- /dev/null +++ b/rocklibc/src/stdio/printf.c @@ -0,0 +1,47 @@ +/* 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 + +#ifndef REGTEST + +int printf( const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vfprintf( stdout, format, ap ); + va_end( ap ); + return rc; +} + +#endif + +#ifdef TEST + +#include +#include +#include + +#define _PDCLIB_FILEID "stdio/printf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +#define testprintf( stream, ... ) printf( __VA_ARGS__ ) + +int main( void ) +{ + FILE * target; + TESTCASE( ( target = freopen( testfile, "wb+", stdout ) ) != NULL ); +#include "printf_testcases.h" + TESTCASE( fclose( target ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/putc.c b/rocklibc/src/stdio/putc.c new file mode 100644 index 0000000..c1eb2b0 --- /dev/null +++ b/rocklibc/src/stdio/putc.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +int putc( int c, struct _PDCLIB_file_t * stream ) +{ + return fputc( c, stream ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/putchar.c b/rocklibc/src/stdio/putchar.c new file mode 100644 index 0000000..ea01de7 --- /dev/null +++ b/rocklibc/src/stdio/putchar.c @@ -0,0 +1,29 @@ +/* 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 + +#ifndef REGTEST + +int putchar( int c ) +{ + return fputc( c, stdout ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + putchar( 'x' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/puts.c b/rocklibc/src/stdio/puts.c new file mode 100644 index 0000000..51585af --- /dev/null +++ b/rocklibc/src/stdio/puts.c @@ -0,0 +1,80 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int puts( const char * s ) +{ + _PDCLIB_LOCK( stdout->mtx ); + + if ( _PDCLIB_prepwrite( stdout ) == EOF ) + { + _PDCLIB_UNLOCK( stdout->mtx ); + return EOF; + } + + while ( *s != '\0' ) + { + stdout->buffer[ stdout->bufidx++ ] = *s++; + + if ( stdout->bufidx == stdout->bufsize ) + { + if ( _PDCLIB_flushbuffer( stdout ) == EOF ) + { + _PDCLIB_UNLOCK( stdout->mtx ); + return EOF; + } + } + } + + stdout->buffer[ stdout->bufidx++ ] = '\n'; + + if ( ( stdout->bufidx == stdout->bufsize ) || + ( stdout->status & ( _IOLBF | _IONBF ) ) ) + { + int rc = _PDCLIB_flushbuffer( stdout ); + _PDCLIB_UNLOCK( stdout->mtx ); + return rc; + } + else + { + _PDCLIB_UNLOCK( stdout->mtx ); + return 0; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + FILE * fh; + const char * message = "SUCCESS testing puts()"; + char buffer[23]; + buffer[22] = 'x'; + TESTCASE( ( fh = freopen( testfile, "wb+", stdout ) ) != NULL ); + TESTCASE( puts( message ) >= 0 ); + rewind( fh ); + TESTCASE( fread( buffer, 1, 22, fh ) == 22 ); + TESTCASE( memcmp( buffer, message, 22 ) == 0 ); + TESTCASE( buffer[22] == 'x' ); + TESTCASE( fclose( fh ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/remove.c b/rocklibc/src/stdio/remove.c new file mode 100644 index 0000000..25cbdbc --- /dev/null +++ b/rocklibc/src/stdio/remove.c @@ -0,0 +1,66 @@ +/* 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 + +#ifndef REGTEST + +#include + +#include "pdclib/_PDCLIB_platform_errno.h" + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +#ifdef __cplusplus +extern "C" { +#endif + +extern int unlink( const char * pathname ); + +#ifdef __cplusplus +} +#endif + +int remove( const char * pathname ) +{ + int rc; + struct _PDCLIB_file_t * current = _PDCLIB_filelist; + + while ( current != NULL ) + { + if ( ( current->filename != NULL ) && ( strcmp( current->filename, pathname ) == 0 ) ) + { + return EOF; + } + + current = current->next; + } + + if ( ( rc = unlink( pathname ) ) == -1 ) + { + /* The 1:1 mapping in _PDCLIB_config.h ensures this works. */ + *_PDCLIB_errno_func() = errno; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c (and several others) */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/rename.c b/rocklibc/src/stdio/rename.c new file mode 100644 index 0000000..966170b --- /dev/null +++ b/rocklibc/src/stdio/rename.c @@ -0,0 +1,103 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#include + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_filelist_mtx; +#endif + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +int rename( const char * oldpath, const char * newpath ) +{ + _PDCLIB_LOCK( _PDCLIB_filelist_mtx ); + + { + struct _PDCLIB_file_t * current = _PDCLIB_filelist; + + while ( current != NULL ) + { + if ( ( current->filename != NULL ) && ( strcmp( current->filename, oldpath ) == 0 ) ) + { + /* File of that name currently open. Do not rename. */ + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return EOF; + } + + current = current->next; + } + } + + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return _PDCLIB_rename( oldpath, newpath ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include + +int main( void ) +{ + FILE * file; + remove( testfile1 ); + remove( testfile2 ); + /* make sure that neither file exists */ + TESTCASE( fopen( testfile1, "r" ) == NULL ); + TESTCASE( fopen( testfile2, "r" ) == NULL ); + /* rename file 1 to file 2 - expected to fail */ + TESTCASE( rename( testfile1, testfile2 ) == -1 ); + /* create file 1 */ + TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL ); + TESTCASE( fputs( "x", file ) != EOF ); + TESTCASE( fclose( file ) == 0 ); + /* check that file 1 exists */ + TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL ); + TESTCASE( fclose( file ) == 0 ); + /* rename file 1 to file 2 */ + TESTCASE( rename( testfile1, testfile2 ) == 0 ); + /* check that file 2 exists, file 1 does not */ + TESTCASE( fopen( testfile1, "r" ) == NULL ); + TESTCASE( ( file = fopen( testfile2, "r" ) ) != NULL ); + TESTCASE( fclose( file ) == 0 ); + /* create another file 1 */ + TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL ); + TESTCASE( fputs( "x", file ) != EOF ); + TESTCASE( fclose( file ) == 0 ); + /* check that file 1 exists */ + TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL ); + TESTCASE( fclose( file ) == 0 ); + /* rename file 1 to file 2 - expected to fail, see comment in + _PDCLIB_rename() itself. + */ + /* Whether existing destination files are overwritten or not + is implementation-defined. + See functions/_PDCLIB/_PDCLIB_rename.c for your platform + for details. + */ + /*TESTCASE( rename( testfile1, testfile2 ) == [0|1] );*/ + /* remove both files */ + TESTCASE( remove( testfile1 ) == 0 ); + TESTCASE( remove( testfile2 ) == 0 ); + /* check that they're gone */ + TESTCASE( fopen( testfile1, "r" ) == NULL ); + TESTCASE( fopen( testfile2, "r" ) == NULL ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/rewind.c b/rocklibc/src/stdio/rewind.c new file mode 100644 index 0000000..a449b7d --- /dev/null +++ b/rocklibc/src/stdio/rewind.c @@ -0,0 +1,29 @@ +/* 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 + +#ifndef REGTEST + +void rewind( struct _PDCLIB_file_t * stream ) +{ + stream->status &= ~ _PDCLIB_ERRORFLAG; + fseek( stream, 0L, SEEK_SET ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/scanf.c b/rocklibc/src/stdio/scanf.c new file mode 100644 index 0000000..c2c8313 --- /dev/null +++ b/rocklibc/src/stdio/scanf.c @@ -0,0 +1,42 @@ +/* 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 + +#ifndef REGTEST + +int scanf( const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vfscanf( stdin, format, ap ); + va_end( ap ); + return rc; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "stdio/scanf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +#define testscanf( stream, format, ... ) scanf( format, __VA_ARGS__ ) + +int main( void ) +{ + FILE * source; + TESTCASE( ( source = freopen( testfile, "wb+", stdin ) ) != NULL ); +#include "scanf_testcases.h" + TESTCASE( fclose( source ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/setbuf.c b/rocklibc/src/stdio/setbuf.c new file mode 100644 index 0000000..6c32072 --- /dev/null +++ b/rocklibc/src/stdio/setbuf.c @@ -0,0 +1,55 @@ +/* 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 + +#ifndef REGTEST + +void setbuf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf ) +{ + if ( buf == NULL ) + { + setvbuf( stream, buf, _IONBF, BUFSIZ ); + } + else + { + setvbuf( stream, buf, _IOFBF, BUFSIZ ); + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + /* TODO: Extend testing once setvbuf() is finished. */ +#ifndef REGTEST + char buffer[ BUFSIZ + 1 ]; + FILE * fh; + /* full buffered */ + TESTCASE( ( fh = tmpfile() ) != NULL ); + setbuf( fh, buffer ); + TESTCASE( fh->buffer == buffer ); + TESTCASE( fh->bufsize == BUFSIZ ); + TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOFBF ); + TESTCASE( fclose( fh ) == 0 ); + /* not buffered */ + TESTCASE( ( fh = tmpfile() ) != NULL ); + setbuf( fh, NULL ); + TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IONBF ); + TESTCASE( fclose( fh ) == 0 ); +#else + puts( " NOTEST setbuf() test driver is PDCLib-specific." ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/setvbuf.c b/rocklibc/src/stdio/setvbuf.c new file mode 100644 index 0000000..3de51b1 --- /dev/null +++ b/rocklibc/src/stdio/setvbuf.c @@ -0,0 +1,141 @@ +/* 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 + +#ifndef REGTEST + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int setvbuf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, char * _PDCLIB_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. + */ + _PDCLIB_LOCK( stream->mtx ); + 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 provided buffer. Deallocate existing buffer, and mark + the stream so that fclose() does not try to deallocate the + user's buffer. + */ + if ( stream->status & _PDCLIB_FREEBUFFER ) + { + free( stream->buffer ); + } + + stream->status &= ~_PDCLIB_FREEBUFFER; + } + else + { + /* 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. + */ + _PDCLIB_LOCK( stream->mtx ); + + 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. */ + _PDCLIB_UNLOCK( stream->mtx ); + return -1; + } + + if ( stream->status & _PDCLIB_FREEBUFFER ) + { + free( stream->buffer ); + } + + /* 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; + _PDCLIB_UNLOCK( stream->mtx ); + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +#define BUFFERSIZE 500 + +int main( void ) +{ +#ifndef REGTEST + char buffer[ BUFFERSIZE ]; + FILE * fh; + /* full buffered, user-supplied buffer */ + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( setvbuf( fh, buffer, _IOFBF, BUFFERSIZE ) == 0 ); + TESTCASE( fh->buffer == buffer ); + TESTCASE( fh->bufsize == BUFFERSIZE ); + TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOFBF ); + TESTCASE( fclose( fh ) == 0 ); + /* line buffered, lib-supplied buffer */ + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( setvbuf( fh, NULL, _IOLBF, BUFFERSIZE ) == 0 ); + TESTCASE( fh->buffer != NULL ); + TESTCASE( fh->bufsize == BUFFERSIZE ); + TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOLBF ); + TESTCASE( fclose( fh ) == 0 ); + /* not buffered, user-supplied buffer */ + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( setvbuf( fh, buffer, _IONBF, BUFFERSIZE ) == 0 ); + TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IONBF ); + TESTCASE( fclose( fh ) == 0 ); +#else + puts( " NOTEST setvbuf() test driver is PDCLib-specific." ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/snprintf.c b/rocklibc/src/stdio/snprintf.c new file mode 100644 index 0000000..b92f245 --- /dev/null +++ b/rocklibc/src/stdio/snprintf.c @@ -0,0 +1,46 @@ +/* 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 + +#ifndef REGTEST + +int snprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vsnprintf( s, n, format, ap ); + va_end( ap ); + return rc; +} + +#endif + +#ifdef TEST + +#include +#include +#include + +#define _PDCLIB_FILEID "stdio/snprintf.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +#define testprintf( s, ... ) snprintf( s, 100, __VA_ARGS__ ) + +int main( void ) +{ + char target[100]; +#include "printf_testcases.h" + TESTCASE( snprintf( NULL, 0, "foo" ) == 3 ); + TESTCASE( snprintf( NULL, 0, "%d", 100 ) == 3 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/sprintf.c b/rocklibc/src/stdio/sprintf.c new file mode 100644 index 0000000..6ad6cce --- /dev/null +++ b/rocklibc/src/stdio/sprintf.c @@ -0,0 +1,44 @@ +/* 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 + +#ifndef REGTEST + +int sprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_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; +} + +#endif + +#ifdef TEST + +#include +#include + +#define _PDCLIB_FILEID "stdio/sprintf.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +#define testprintf( s, ... ) sprintf( s, __VA_ARGS__ ) + +int main( void ) +{ + char target[100]; +#include "printf_testcases.h" + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/sscanf.c b/rocklibc/src/stdio/sscanf.c new file mode 100644 index 0000000..9ba830d --- /dev/null +++ b/rocklibc/src/stdio/sscanf.c @@ -0,0 +1,39 @@ +/* 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 + +#ifndef REGTEST + +int sscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vsscanf( s, format, ap ); + va_end( ap ); + return rc; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "stdio/sscanf.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +#define testscanf( s, format, ... ) sscanf( s, format, __VA_ARGS__ ) + +int main( void ) +{ + char source[100]; +#include "scanf_testcases.h" + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/tmpfile.c b/rocklibc/src/stdio/tmpfile.c new file mode 100644 index 0000000..3b41f3e --- /dev/null +++ b/rocklibc/src/stdio/tmpfile.c @@ -0,0 +1,133 @@ +/* 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 + +#ifndef REGTEST + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_filelist_mtx; +#endif + +#include "pdclib/_PDCLIB_glue.h" +#include "pdclib/_PDCLIB_defguard.h" + +#include +#include + +#include "sys/types.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "unistd.h" + +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 ) +{ + FILE * rc; + char const * tmpdir = getenv("TMPDIR"); + + /* This is the chosen way to get high-quality randomness. Replace as + appropriate. + */ + int randomsource = open( "/dev/urandom", O_RDONLY ); + /* Working under the assumption that the tempfile location is canonical + (absolute), and does not require going through _PDCLIB_realpath(). + */ + char * filename = ( char * )malloc( L_tmpnam ); + _PDCLIB_fd_t fd; + + if ( randomsource == -1 ) + { + return NULL; + } + + for ( ;; ) + { + /* Get a filename candidate. What constitutes a valid filename and + where temporary files are usually located is platform-dependent, + which is one reason why this function is located in the platform + overlay. The other reason is that a *good* implementation should + use high-quality randomness instead of a pseudo-random sequence to + generate the filename candidate, which is *also* platform-dependent. + */ + unsigned int random; + read( randomsource, (void *)&random, sizeof( unsigned int ) ); + sprintf( filename, "%s/%u.tmp", (tmpdir == NULL) ? "/tmp" : tmpdir, random ); + /* Check if file of this name exists. Note that fopen() is a very weak + check, which does not take e.g. access permissions into account + (file might exist but not readable). Replace with something more + appropriate. + */ + fd = open( filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR ); + + if ( fd != -1 ) + { + /* Found a file that does not exist yet */ + break; + } + + close( fd ); + } + + close( randomsource ); + + /* See fopen(), which does much of the same. */ + + if ( ( rc = _PDCLIB_init_file_t( NULL ) ) == NULL ) + { + /* initializing FILE structure failed */ + close( fd ); + return NULL; + } + + rc->status |= _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE; + rc->handle = fd; + + /* Filename (for potential freopen()) */ + rc->filename = filename; + + /* Adding to list of open files */ + _PDCLIB_LOCK( _PDCLIB_filelist_mtx ); + rc->next = _PDCLIB_filelist; + _PDCLIB_filelist = rc; + _PDCLIB_UNLOCK( _PDCLIB_filelist_mtx ); + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + FILE * fh; +#ifndef REGTEST + char filename[ L_tmpnam ]; + FILE * fhtest; +#endif + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( fputc( 'x', fh ) == 'x' ); + /* Checking that file is actually there */ + TESTCASE_NOREG( strcpy( filename, fh->filename ) == filename ); + TESTCASE_NOREG( ( fhtest = fopen( filename, "r" ) ) != NULL ); + TESTCASE_NOREG( fclose( fhtest ) == 0 ); + /* Closing tmpfile */ + TESTCASE( fclose( fh ) == 0 ); + /* Checking that file was deleted */ + TESTCASE_NOREG( fopen( filename, "r" ) == NULL ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/tmpfile_s.c b/rocklibc/src/stdio/tmpfile_s.c new file mode 100644 index 0000000..98f53c9 --- /dev/null +++ b/rocklibc/src/stdio/tmpfile_s.c @@ -0,0 +1,79 @@ +/* tmpfile_s( FILE * * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t tmpfile_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr ) +{ + if ( streamptr == NULL ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + *streamptr = tmpfile(); + + if ( *streamptr == NULL ) + { + assert( *_PDCLIB_errno_func() != 0 ); + return *_PDCLIB_errno_func(); + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + FILE * fh; + char filename[ L_tmpnam ]; + FILE * fhtest; + set_constraint_handler_s( test_handler ); + + TESTCASE( ( tmpfile_s( &fh ) ) == 0 ); + TESTCASE( fputc( 'x', fh ) == 'x' ); + /* Checking that file is actually there */ + TESTCASE_NOREG( strcpy( filename, fh->filename ) == filename ); + TESTCASE_NOREG( ( fhtest = fopen( filename, "r" ) ) != NULL ); + TESTCASE_NOREG( fclose( fhtest ) == 0 ); + /* Closing tmpfile */ + TESTCASE( fclose( fh ) == 0 ); + /* Checking that file was deleted */ + TESTCASE_NOREG( fopen( filename, "r" ) == NULL ); + + /* Constraint violation */ + TESTCASE( ( tmpfile_s( NULL ) ) != 0 ); + + TESTCASE( HANDLER_CALLS == 1 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/tmpnam.c b/rocklibc/src/stdio/tmpnam.c new file mode 100644 index 0000000..14e0378 --- /dev/null +++ b/rocklibc/src/stdio/tmpnam.c @@ -0,0 +1,47 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + TESTCASE( strlen( tmpnam( NULL ) ) < L_tmpnam ); +#pragma GCC diagnostic pop + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/ungetc.c b/rocklibc/src/stdio/ungetc.c new file mode 100644 index 0000000..51a4cb8 --- /dev/null +++ b/rocklibc/src/stdio/ungetc.c @@ -0,0 +1,93 @@ +/* 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 + +#ifndef REGTEST + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int ungetc( int c, struct _PDCLIB_file_t * stream ) +{ + int rc; + + _PDCLIB_LOCK( stream->mtx ); + + if ( c == EOF || stream->ungetidx == _PDCLIB_UNGETCBUFSIZE ) + { + rc = -1; + } + else + { + rc = stream->ungetbuf[stream->ungetidx++] = ( unsigned char ) c; + } + + _PDCLIB_UNLOCK( stream->mtx ); + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + char buffer[4]; + char input[4]; + FILE * fh; + int read; + fpos_t pos; + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( setvbuf( fh, buffer, _IOLBF, 4 ) == 0 ); + rewind( fh ); + TESTCASE( fprintf( fh, "123" ) == 3 ); + TESTCASE( ftell( fh ) == 3 ); + rewind( fh ); + TESTCASE( fscanf( fh, "12%n", &read ) == 0 ); + TESTCASE( read == 2 ); + TESTCASE( ftell( fh ) == 2 ); + TESTCASE( ungetc( 'x', fh ) == 'x' ); + TESTCASE( ftell( fh ) == 1 ); + read = 0; + TESTCASE( fscanf( fh, "x3%n", &read ) == 0 ); + TESTCASE( ftell( fh ) == 3 ); + TESTCASE( read == 2 ); + TESTCASE( ungetc( 'y', fh ) == 'y' ); + TESTCASE( ftell( fh ) == 2 ); + TESTCASE( fread( input, 1, 1, fh ) == 1 ); + TESTCASE( ftell( fh ) == 3 ); + TESTCASE( input[0] == 'y' ); + rewind( fh ); + TESTCASE( ungetc( 'z', fh ) == 'z' ); + TESTCASE( ftell( fh ) == -1 ); + TESTCASE( fread( input, 1, 4, fh ) == 4 ); + TESTCASE( memcmp( input, "z123", 4 ) == 0 ); + rewind( fh ); + TESTCASE( ungetc( 'z', fh ) == 'z' ); + TESTCASE( ftell( fh ) == -1 ); + TESTCASE( fscanf( fh, "%4c", input ) == 1 ); + TESTCASE( memcmp( input, "z123", 4 ) == 0 ); + rewind( fh ); + TESTCASE( fgetc( fh ) == '1' ); + TESTCASE( ftell( fh ) == 1 ); + TESTCASE( ungetc( 'z', fh ) == 'z' ); + TESTCASE( ftell( fh ) == 0 ); + TESTCASE( fgetpos( fh, &pos ) == 0 ); + TESTCASE( fsetpos( fh, &pos ) == 0 ); + TESTCASE( ftell( fh ) == 0 ); + TESTCASE( fgetc( fh ) == '1' ); + TESTCASE( fclose( fh ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/vfprintf.c b/rocklibc/src/stdio/vfprintf.c new file mode 100644 index 0000000..9cc0949 --- /dev/null +++ b/rocklibc/src/stdio/vfprintf.c @@ -0,0 +1,110 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int vfprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, const char * _PDCLIB_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; + + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepwrite( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + + va_copy( status.arg, arg ); + + while ( *format != '\0' ) + { + const char * rc; + + if ( ( *format != '%' ) || ( ( rc = _PDCLIB_print( format, &status ) ) == format ) ) + { + /* No conversion specifier, print verbatim */ + stream->buffer[ stream->bufidx++ ] = *format; + + if ( ( stream->bufidx == stream->bufsize ) + || ( ( stream->status & _IOLBF ) && ( *format == '\n' ) ) + || ( stream->status & _IONBF ) + ) + { + if ( _PDCLIB_flushbuffer( stream ) != 0 ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + } + + ++format; + status.i++; + } + else + { + /* Continue parsing after conversion specifier */ + format = rc; + } + } + + va_end( status.arg ); + _PDCLIB_UNLOCK( stream->mtx ); + return status.i; +} + +#endif + +#ifdef TEST + +#include +#include + +#define _PDCLIB_FILEID "stdio/vfprintf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +static int testprintf( FILE * stream, const char * format, ... ) +{ + int i; + va_list arg; + va_start( arg, format ); + i = vfprintf( stream, format, arg ); + va_end( arg ); + return i; +} + +int main( void ) +{ + FILE * target; + TESTCASE( ( target = tmpfile() ) != NULL ); +#include "printf_testcases.h" + TESTCASE( fclose( target ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/vfscanf.c b/rocklibc/src/stdio/vfscanf.c new file mode 100644 index 0000000..667b8af --- /dev/null +++ b/rocklibc/src/stdio/vfscanf.c @@ -0,0 +1,138 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +#ifndef __STDC_NO_THREADS__ +#include +#endif + +int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_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; + + _PDCLIB_LOCK( stream->mtx ); + + if ( _PDCLIB_prepread( stream ) == EOF || _PDCLIB_CHECKBUFFER( stream ) == EOF ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + + 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( (unsigned char)*format ) ) + { + /* Whitespace char in format string: Skip all whitespaces */ + /* No whitespaces in input does not result in matching error */ + while ( isspace( (unsigned char)( 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 ) + { + _PDCLIB_UNLOCK( stream->mtx ); + return EOF; + } + + _PDCLIB_UNLOCK( stream->mtx ); + 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 ); + _PDCLIB_UNLOCK( stream->mtx ); + return status.n; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "stdio/vfscanf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +static int testscanf( FILE * stream, const char * format, ... ) +{ + va_list ap; + int result; + va_start( ap, format ); + result = vfscanf( stream, format, ap ); + va_end( ap ); + return result; +} + +int main( void ) +{ + FILE * source; + TESTCASE( ( source = fopen( testfile, "wb+" ) ) != NULL ); +#include "scanf_testcases.h" + TESTCASE( fclose( source ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/vprintf.c b/rocklibc/src/stdio/vprintf.c new file mode 100644 index 0000000..342f227 --- /dev/null +++ b/rocklibc/src/stdio/vprintf.c @@ -0,0 +1,50 @@ +/* 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 + +#ifndef REGTEST + +int vprintf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) +{ + return vfprintf( stdout, format, arg ); +} + +#endif + +#ifdef TEST + +#include +#include +#include + +#define _PDCLIB_FILEID "stdio/vprintf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +static int testprintf( FILE * stream, const char * format, ... ) +{ + int i; + va_list arg; + va_start( arg, format ); + i = vprintf( format, arg ); + va_end( arg ); + return i; +} + +int main( void ) +{ + FILE * target; + TESTCASE( ( target = freopen( testfile, "wb+", stdout ) ) != NULL ); +#include "printf_testcases.h" + TESTCASE( fclose( target ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/vscanf.c b/rocklibc/src/stdio/vscanf.c new file mode 100644 index 0000000..d5ae5b3 --- /dev/null +++ b/rocklibc/src/stdio/vscanf.c @@ -0,0 +1,45 @@ +/* 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 + +#ifndef REGTEST + +int vscanf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) +{ + return vfscanf( stdin, format, arg ); +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "stdio/vscanf.c" +#define _PDCLIB_FILEIO + +#include "_PDCLIB_test.h" + +static int testscanf( FILE * stream, const char * format, ... ) +{ + int i; + va_list arg; + va_start( arg, format ); + i = vscanf( format, arg ); + va_end( arg ); + return i; +} + +int main( void ) +{ + FILE * source; + TESTCASE( ( source = freopen( testfile, "wb+", stdin ) ) != NULL ); +#include "scanf_testcases.h" + TESTCASE( fclose( source ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/vsnprintf.c b/rocklibc/src/stdio/vsnprintf.c new file mode 100644 index 0000000..0d3aa65 --- /dev/null +++ b/rocklibc/src/stdio/vsnprintf.c @@ -0,0 +1,88 @@ +/* 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 + +#ifndef REGTEST + +int vsnprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_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; +} + +#endif + +#ifdef TEST + +#include +#include +#include + +#define _PDCLIB_FILEID "stdio/vsnprintf.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +static int testprintf( char * s, const char * format, ... ) +{ + int i; + va_list arg; + va_start( arg, format ); + i = vsnprintf( s, 100, format, arg ); + va_end( arg ); + return i; +} + +int main( void ) +{ + char target[100]; +#include "printf_testcases.h" + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/vsprintf.c b/rocklibc/src/stdio/vsprintf.c new file mode 100644 index 0000000..3c539d9 --- /dev/null +++ b/rocklibc/src/stdio/vsprintf.c @@ -0,0 +1,47 @@ +/* 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 + +#ifndef REGTEST + +int vsprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, va_list arg ) +{ + return vsnprintf( s, SIZE_MAX, format, arg ); /* TODO: Replace with a non-checking call */ +} + +#endif + +#ifdef TEST + +#include +#include + +#define _PDCLIB_FILEID "stdio/vsprintf.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +static int testprintf( char * s, const char * format, ... ) +{ + int i; + va_list arg; + va_start( arg, format ); + i = vsprintf( s, format, arg ); + va_end( arg ); + return i; +} + +int main( void ) +{ + char target[100]; +#include "printf_testcases.h" + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdio/vsscanf.c b/rocklibc/src/stdio/vsscanf.c new file mode 100644 index 0000000..aec34ce --- /dev/null +++ b/rocklibc/src/stdio/vsscanf.c @@ -0,0 +1,115 @@ +/* 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 + +#ifndef REGTEST + +int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_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( (unsigned char)*format ) ) + { + /* Whitespace char in format string: Skip all whitespaces */ + /* No whitespaces in input do not result in matching error */ + while ( isspace( (unsigned char)*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; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "stdio/vsscanf.c" +#define _PDCLIB_STRINGIO + +#include "_PDCLIB_test.h" + +static int testscanf( const char * stream, const char * format, ... ) +{ + va_list ap; + int result; + va_start( ap, format ); + result = vsscanf( stream, format, ap ); + va_end( ap ); + return result; +} + +int main( void ) +{ + char source[100]; +#include "scanf_testcases.h" + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/_Exit.c b/rocklibc/src/stdlib/_Exit.c new file mode 100644 index 0000000..e5548ed --- /dev/null +++ b/rocklibc/src/stdlib/_Exit.c @@ -0,0 +1,34 @@ +/* _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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_glue.h" + +void _Exit( int status ) +{ + _PDCLIB_closeall(); + _PDCLIB_Exit( status ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + int UNEXPECTED_RETURN = 0; + _Exit( 0 ); + TESTCASE( UNEXPECTED_RETURN ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/abort.c b/rocklibc/src/stdlib/abort.c new file mode 100644 index 0000000..69422f9 --- /dev/null +++ b/rocklibc/src/stdlib/abort.c @@ -0,0 +1,40 @@ +/* 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 + +#ifndef REGTEST + +void abort( void ) +{ + raise( SIGABRT ); + exit( EXIT_FAILURE ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +static void aborthandler( int sig ) +{ + exit( 0 ); +} + +int main( void ) +{ + int UNEXPECTED_RETURN_FROM_ABORT = 0; + TESTCASE( signal( SIGABRT, &aborthandler ) != SIG_ERR ); + abort(); + TESTCASE( UNEXPECTED_RETURN_FROM_ABORT ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/abort_handler_s.c b/rocklibc/src/stdlib/abort_handler_s.c new file mode 100644 index 0000000..995eba3 --- /dev/null +++ b/rocklibc/src/stdlib/abort_handler_s.c @@ -0,0 +1,32 @@ +/* abort_handler_s( const char *, void *, errno_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + +#ifndef REGTEST + +#include + +void abort_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t errno ) +{ + fprintf( stderr, "abort handler called:\n%s\n", msg ); + abort(); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/abs.c b/rocklibc/src/stdlib/abs.c new file mode 100644 index 0000000..7a634e3 --- /dev/null +++ b/rocklibc/src/stdlib/abs.c @@ -0,0 +1,32 @@ +/* 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 + +#ifndef REGTEST + +int abs( int j ) +{ + return ( j >= 0 ) ? j : -j; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + TESTCASE( abs( 0 ) == 0 ); + TESTCASE( abs( INT_MAX ) == INT_MAX ); + TESTCASE( abs( INT_MIN + 1 ) == -( INT_MIN + 1 ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/at_quick_exit.c b/rocklibc/src/stdlib/at_quick_exit.c new file mode 100644 index 0000000..d576b0f --- /dev/null +++ b/rocklibc/src/stdlib/at_quick_exit.c @@ -0,0 +1,73 @@ +/* at_quick_exit( 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 + +#ifndef REGTEST + +extern void ( *_PDCLIB_quickexitstack[] )( void ); +extern size_t _PDCLIB_quickexitptr; + +int at_quick_exit( void ( *func )( void ) ) +{ + if ( _PDCLIB_quickexitptr == _PDCLIB_ATEXIT_SLOTS ) + { + return -1; + } + else + { + _PDCLIB_quickexitstack[ _PDCLIB_quickexitptr++ ] = func; + return 0; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +#if ! defined( REGTEST ) || __STDC_VERSION__ >= 201112L + +static int flags[ 32 ]; + +static void counthandler( void ) +{ + static int count = 0; + flags[ count ] = count; + ++count; +} + +static void checkhandler( void ) +{ + int i; + + for ( i = 0; i < 32; ++i ) + { + assert( flags[ i ] == i ); + } +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || __STDC_VERSION__ >= 201112L + int i; + TESTCASE( at_quick_exit( &checkhandler ) == 0 ); + + for ( i = 0; i < 32; ++i ) + { + TESTCASE( at_quick_exit( &counthandler ) == 0 ); + } + +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/atexit.c b/rocklibc/src/stdlib/atexit.c new file mode 100644 index 0000000..779da1e --- /dev/null +++ b/rocklibc/src/stdlib/atexit.c @@ -0,0 +1,67 @@ +/* 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 + +#ifndef REGTEST + +extern void ( *_PDCLIB_exitstack[] )( void ); +extern size_t _PDCLIB_exitptr; + +int atexit( void ( *func )( void ) ) +{ + if ( _PDCLIB_exitptr == _PDCLIB_ATEXIT_SLOTS ) + { + return -1; + } + else + { + _PDCLIB_exitstack[ _PDCLIB_exitptr++ ] = func; + return 0; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +static int flags[ 32 ]; + +static void counthandler( void ) +{ + static int count = 0; + flags[ count ] = count; + ++count; +} + +static void checkhandler( void ) +{ + int i; + + for ( i = 0; i < 32; ++i ) + { + assert( flags[ i ] == i ); + } +} + +int main( void ) +{ + int i; + TESTCASE( atexit( &checkhandler ) == 0 ); + + for ( i = 0; i < 32; ++i ) + { + TESTCASE( atexit( &counthandler ) == 0 ); + } + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/atoi.c b/rocklibc/src/stdlib/atoi.c new file mode 100644 index 0000000..5d0c2fb --- /dev/null +++ b/rocklibc/src/stdlib/atoi.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +int atoi( const char * s ) +{ + return ( int ) _PDCLIB_atomax( s ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* no tests for a simple wrapper */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/atol.c b/rocklibc/src/stdlib/atol.c new file mode 100644 index 0000000..750d64d --- /dev/null +++ b/rocklibc/src/stdlib/atol.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +long int atol( const char * s ) +{ + return ( long int ) _PDCLIB_atomax( s ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* no tests for a simple wrapper */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/atoll.c b/rocklibc/src/stdlib/atoll.c new file mode 100644 index 0000000..212b4f3 --- /dev/null +++ b/rocklibc/src/stdlib/atoll.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +long long int atoll( const char * s ) +{ + return ( long long int ) _PDCLIB_atomax( s ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* no tests for a simple wrapper */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/bsearch.c b/rocklibc/src/stdlib/bsearch.c new file mode 100644 index 0000000..6f578d4 --- /dev/null +++ b/rocklibc/src/stdlib/bsearch.c @@ -0,0 +1,64 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +static int compare( const void * left, const void * right ) +{ + return *( ( unsigned char * )left ) - *( ( unsigned char * )right ); +} + +int main( void ) +{ + TESTCASE( bsearch( "e", abcde, 4, 1, compare ) == NULL ); + TESTCASE( bsearch( "e", abcde, 5, 1, compare ) == &abcde[4] ); + TESTCASE( bsearch( "a", abcde + 1, 4, 1, compare ) == NULL ); + TESTCASE( bsearch( "0", abcde, 1, 1, compare ) == NULL ); + TESTCASE( bsearch( "a", abcde, 1, 1, compare ) == &abcde[0] ); + TESTCASE( bsearch( "a", abcde, 0, 1, compare ) == NULL ); + TESTCASE( bsearch( "e", abcde, 3, 2, compare ) == &abcde[4] ); + TESTCASE( bsearch( "b", abcde, 3, 2, compare ) == NULL ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/bsearch_s.c b/rocklibc/src/stdlib/bsearch_s.c new file mode 100644 index 0000000..133f0ee --- /dev/null +++ b/rocklibc/src/stdlib/bsearch_s.c @@ -0,0 +1,78 @@ +/* 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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include + +#ifndef REGTEST + +void * bsearch_s( const void * key, const void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void *, const void *, void * ), void * context ) +{ + const void * pivot; + int rc; + size_t corr; + + if ( nmemb > RSIZE_MAX || size > RSIZE_MAX || ( nmemb > 0 && ( key == NULL || base == NULL || compar == NULL ) ) ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return NULL; + } + + 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, context ); + + if ( rc > 0 ) + { + base = ( const char * )pivot + size; + /* applying correction */ + nmemb -= ( 1 - corr ); + } + else if ( rc == 0 ) + { + return ( void * )pivot; + } + } + + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int compare( const void * left, const void * right, void * context ) +{ + return *( ( unsigned char * )left ) - *( ( unsigned char * )right ); +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + TESTCASE( bsearch_s( "e", abcde, 4, 1, compare, NULL ) == NULL ); + TESTCASE( bsearch_s( "e", abcde, 5, 1, compare, NULL ) == &abcde[4] ); + TESTCASE( bsearch_s( "a", abcde + 1, 4, 1, compare, NULL ) == NULL ); + TESTCASE( bsearch_s( "0", abcde, 1, 1, compare, NULL ) == NULL ); + TESTCASE( bsearch_s( "a", abcde, 1, 1, compare, NULL ) == &abcde[0] ); + TESTCASE( bsearch_s( "a", abcde, 0, 1, compare, NULL ) == NULL ); + TESTCASE( bsearch_s( "e", abcde, 3, 2, compare, NULL ) == &abcde[4] ); + TESTCASE( bsearch_s( "b", abcde, 3, 2, compare, NULL ) == NULL ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/div.c b/rocklibc/src/stdlib/div.c new file mode 100644 index 0000000..5d502c8 --- /dev/null +++ b/rocklibc/src/stdlib/div.c @@ -0,0 +1,40 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + div_t result; + result = div( 5, 2 ); + TESTCASE( result.quot == 2 && result.rem == 1 ); + result = div( -5, 2 ); + TESTCASE( result.quot == -2 && result.rem == -1 ); + result = div( 5, -2 ); + TESTCASE( result.quot == -2 && result.rem == 1 ); + TESTCASE( sizeof( result.quot ) == sizeof( int ) ); + TESTCASE( sizeof( result.rem ) == sizeof( int ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/exit.c b/rocklibc/src/stdlib/exit.c new file mode 100644 index 0000000..89a6d7b --- /dev/null +++ b/rocklibc/src/stdlib/exit.c @@ -0,0 +1,40 @@ +/* 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 + +#ifndef REGTEST + +/* TODO - "...except that a function is called after any previously registered + functions that had already been called at the time it was registered." +*/ + +void ( *_PDCLIB_exitstack[ _PDCLIB_ATEXIT_SLOTS ] )( void ); +size_t _PDCLIB_exitptr = 0; + +void exit( int status ) +{ + while ( _PDCLIB_exitptr != 0 ) + { + _PDCLIB_exitstack[ --_PDCLIB_exitptr ](); + } + + _Exit( status ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Unwinding of regstack tested in atexit(). */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/getenv.c b/rocklibc/src/stdlib/getenv.c new file mode 100644 index 0000000..0cc991b --- /dev/null +++ b/rocklibc/src/stdlib/getenv.c @@ -0,0 +1,56 @@ +/* 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. +*/ + +/* This is an example implementation of getenv() fit for use with POSIX kernels. +*/ + +#include +#include + +#ifndef REGTEST + +extern char ** environ; + +/* The standard states (7.22.4.6 (3), "the implementation shall behave + as if no library function calls the getenv function." That is, + however, in context of the previous paragraph stating that getenv + "need not avoid data races with other threads of execution that + modify the environment list". + PDCLib does not provide means of modifying the environment list. +*/ +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char * env = getenv( "SHELL" ); + size_t len = strlen( env ); + TESTCASE( strcmp( env + ( len - 2 ), "sh" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/getenv_s.c b/rocklibc/src/stdlib/getenv_s.c new file mode 100644 index 0000000..7e01506 --- /dev/null +++ b/rocklibc/src/stdlib/getenv_s.c @@ -0,0 +1,110 @@ +/* getenv_s( size_t *, char *, rsize_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. +*/ + +/* This is an example implementation of getenv() fit for use with POSIX kernels. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +extern char ** environ; + +/* The standard states (7.22.4.6 (3), "the implementation shall behave + as if no library function calls the getenv function." That is, + however, in context of the previous paragraph stating that getenv + "need not avoid data races with other threads of execution that + modify the environment list". + PDCLib does not provide means of modifying the environment list. +*/ +errno_t getenv_s( size_t * _PDCLIB_restrict len, char * _PDCLIB_restrict value, rsize_t maxsize, const char * _PDCLIB_restrict name ) +{ + size_t nlen; + size_t index = 0; + size_t vlen = 0; + char const * environ_value = ""; + errno_t rc = -1; + + if ( name == NULL || maxsize == 0 || maxsize > RSIZE_MAX || value == NULL ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + nlen = strlen( name ); + + while ( environ[ index ] != NULL ) + { + if ( strncmp( environ[ index ], name, nlen ) == 0 ) + { + environ_value = environ[ index ] + nlen + 1; + vlen = strlen( environ_value ); + rc = 0; + break; + } + + index++; + } + + if ( len != NULL ) + { + *len = vlen; + } + + if ( vlen < maxsize ) + { + strcpy( value, environ_value ); + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + size_t len; + char value[100]; + set_constraint_handler_s( test_handler ); + + TESTCASE( getenv_s( &len, value, 100, "SHELL" ) == 0 ); + TESTCASE( strcmp( value + ( len - 2 ), "sh" ) == 0 ); + /* TESTCASE( strcmp( value, "/bin/sh" ) == 0 ); */ + + /* constraint violations */ + TESTCASE( getenv_s( &len, NULL, 100, "SHELL" ) != 0 ); + TESTCASE( getenv_s( &len, value, 0, "SHELL" ) != 0 ); + TESTCASE( getenv_s( &len, value, RSIZE_MAX + 1, "SHELL" ) != 0 ); + TESTCASE( getenv_s( &len, value, 100, NULL ) != 0 ); + + /* non-existing (hopefully), != 0 but not constraint violation */ + TESTCASE( getenv_s( &len, value, 100, "supercalifragilisticexpialidocius" ) != 0 ); + + TESTCASE( HANDLER_CALLS == 4 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/ignore_handler_s.c b/rocklibc/src/stdlib/ignore_handler_s.c new file mode 100644 index 0000000..7f220a1 --- /dev/null +++ b/rocklibc/src/stdlib/ignore_handler_s.c @@ -0,0 +1,31 @@ +/* ignore_handler_s( const char *, void *, errno_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + +#ifndef REGTEST + +#include + +void ignore_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t errno ) +{ + return; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/labs.c b/rocklibc/src/stdlib/labs.c new file mode 100644 index 0000000..3653453 --- /dev/null +++ b/rocklibc/src/stdlib/labs.c @@ -0,0 +1,32 @@ +/* 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 + +#ifndef REGTEST + +long int labs( long int j ) +{ + return ( j >= 0 ) ? j : -j; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + TESTCASE( labs( 0 ) == 0 ); + TESTCASE( labs( LONG_MAX ) == LONG_MAX ); + TESTCASE( labs( LONG_MIN + 1 ) == -( LONG_MIN + 1 ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/ldiv.c b/rocklibc/src/stdlib/ldiv.c new file mode 100644 index 0000000..0f51944 --- /dev/null +++ b/rocklibc/src/stdlib/ldiv.c @@ -0,0 +1,40 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + ldiv_t result; + result = ldiv( 5, 2 ); + TESTCASE( result.quot == 2 && result.rem == 1 ); + result = ldiv( -5, 2 ); + TESTCASE( result.quot == -2 && result.rem == -1 ); + result = ldiv( 5, -2 ); + TESTCASE( result.quot == -2 && result.rem == 1 ); + TESTCASE( sizeof( result.quot ) == sizeof( long ) ); + TESTCASE( sizeof( result.rem ) == sizeof( long ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/llabs.c b/rocklibc/src/stdlib/llabs.c new file mode 100644 index 0000000..bc05bf3 --- /dev/null +++ b/rocklibc/src/stdlib/llabs.c @@ -0,0 +1,32 @@ +/* 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 + +#ifndef REGTEST + +long long int llabs( long long int j ) +{ + return ( j >= 0 ) ? j : -j; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + TESTCASE( llabs( 0ll ) == 0 ); + TESTCASE( llabs( LLONG_MAX ) == LLONG_MAX ); + TESTCASE( llabs( LLONG_MIN + 1 ) == -( LLONG_MIN + 1 ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/lldiv.c b/rocklibc/src/stdlib/lldiv.c new file mode 100644 index 0000000..4219e31 --- /dev/null +++ b/rocklibc/src/stdlib/lldiv.c @@ -0,0 +1,40 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + lldiv_t result; + result = lldiv( 5ll, 2ll ); + TESTCASE( result.quot == 2 && result.rem == 1 ); + result = lldiv( -5ll, 2ll ); + TESTCASE( result.quot == -2 && result.rem == -1 ); + result = lldiv( 5ll, -2ll ); + TESTCASE( result.quot == -2 && result.rem == 1 ); + TESTCASE( sizeof( result.quot ) == sizeof( long long ) ); + TESTCASE( sizeof( result.rem ) == sizeof( long long ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/qsort.c b/rocklibc/src/stdlib/qsort.c new file mode 100644 index 0000000..26e9f2e --- /dev/null +++ b/rocklibc/src/stdlib/qsort.c @@ -0,0 +1,188 @@ +/* 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 + +#ifndef REGTEST + +/* 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 _PDCLIB_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 _PDCLIB_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; + _PDCLIB_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; + } + } + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include + +static int compare( const void * left, const void * right ) +{ + return *( ( unsigned char * )left ) - *( ( unsigned char * )right ); +} + +int main( void ) +{ + char presort[] = { "shreicnyjqpvozxmbt" }; + char sorted1[] = { "bcehijmnopqrstvxyz" }; + char sorted2[] = { "bticjqnyozpvreshxm" }; + char s[19]; + strcpy( s, presort ); + qsort( s, 18, 1, compare ); + TESTCASE( strcmp( s, sorted1 ) == 0 ); + strcpy( s, presort ); + qsort( s, 9, 2, compare ); + TESTCASE( strcmp( s, sorted2 ) == 0 ); + strcpy( s, presort ); + qsort( s, 1, 1, compare ); + TESTCASE( strcmp( s, presort ) == 0 ); +#if defined( REGTEST ) && ( defined( __BSD_VISIBLE ) || defined( __APPLE__ ) ) + puts( "qsort.c: Skipping test #4 for BSD as it goes into endless loop here." ); +#elif defined( REGTEST ) && defined( __ANDROID__ ) + puts( "qsort.c: Skipping test #4 for Android as it crashes." ); +#else + qsort( s, 100, 0, compare ); + TESTCASE( strcmp( s, presort ) == 0 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/qsort_s.c b/rocklibc/src/stdlib/qsort_s.c new file mode 100644 index 0000000..3bca1c2 --- /dev/null +++ b/rocklibc/src/stdlib/qsort_s.c @@ -0,0 +1,202 @@ +/* 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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include + +#ifndef REGTEST + +/* 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 _PDCLIB_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 _PDCLIB_config.h. +*/ +#define STACKSIZE 64 + +errno_t qsort_s( void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void *, const void *, void * ), void * context ) +{ + char * i; + char * j; + _PDCLIB_size_t thresh = T * size; + char * base_ = ( char * )base; + char * limit = base_ + nmemb * size; + PREPARE_STACK; + + if ( nmemb > RSIZE_MAX || size > RSIZE_MAX || ( nmemb > 0 && ( base == NULL || compar == NULL ) ) ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + 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, context ) > 0 ) + { + memswp( i, j, size ); + } + + if ( compar( base_, j, context ) > 0 ) + { + memswp( base_, j, size ); + } + + if ( compar( i, base_, context ) > 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_, context ) < 0 ); + + do + { + /* move j left until *j <= pivot */ + j -= size; + } while ( compar( j, base_, context ) > 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, context ) > 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; + } + } + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int compare( const void * left, const void * right, void * context ) +{ + return *( ( unsigned char * )left ) - *( ( unsigned char * )right ); +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char presort[] = { "shreicnyjqpvozxmbt" }; + char sorted1[] = { "bcehijmnopqrstvxyz" }; + char sorted2[] = { "bticjqnyozpvreshxm" }; + char s[19]; + strcpy( s, presort ); + qsort_s( s, 18, 1, compare, NULL ); + TESTCASE( strcmp( s, sorted1 ) == 0 ); + strcpy( s, presort ); + qsort_s( s, 9, 2, compare, NULL ); + TESTCASE( strcmp( s, sorted2 ) == 0 ); + strcpy( s, presort ); + qsort_s( s, 1, 1, compare, NULL ); + TESTCASE( strcmp( s, presort ) == 0 ); +#if defined( REGTEST ) && ( defined( __BSD_VISIBLE ) || defined( __APPLE__ ) ) + puts( "qsort_s.c: Skipping test #4 for BSD as it goes into endless loop here." ); +#else + qsort_s( s, 100, 0, compare, NULL ); + TESTCASE( strcmp( s, presort ) == 0 ); +#endif +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/quick_exit.c b/rocklibc/src/stdlib/quick_exit.c new file mode 100644 index 0000000..cc01f79 --- /dev/null +++ b/rocklibc/src/stdlib/quick_exit.c @@ -0,0 +1,40 @@ +/* quick_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 + +#ifndef REGTEST + +/* TODO - "...except that a function is called after any previously registered + functions that had already been called at the time it was registered." +*/ + +void ( *_PDCLIB_quickexitstack[ _PDCLIB_ATEXIT_SLOTS ] )( void ); +size_t _PDCLIB_quickexitptr = 0; + +void quick_exit( int status ) +{ + while ( _PDCLIB_quickexitptr != 0 ) + { + _PDCLIB_quickexitstack[ --_PDCLIB_quickexitptr ](); + } + + _Exit( status ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* Unwinding of regstack tested in at_quick_exit(). */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/rand.c b/rocklibc/src/stdlib/rand.c new file mode 100644 index 0000000..36ce9f3 --- /dev/null +++ b/rocklibc/src/stdlib/rand.c @@ -0,0 +1,34 @@ +/* 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 + +#ifndef REGTEST + +int rand( void ) +{ + _PDCLIB_seed = _PDCLIB_seed * 1103515245 + 12345; + return ( int )( _PDCLIB_seed / 65536 ) % 32768; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + int rnd1, rnd2; + TESTCASE( ( rnd1 = rand() ) < RAND_MAX ); + TESTCASE( ( rnd2 = rand() ) < RAND_MAX ); + srand( 1 ); + TESTCASE( rand() == rnd1 ); + TESTCASE( rand() == rnd2 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/set_constraint_handler_s.c b/rocklibc/src/stdlib/set_constraint_handler_s.c new file mode 100644 index 0000000..89914e1 --- /dev/null +++ b/rocklibc/src/stdlib/set_constraint_handler_s.c @@ -0,0 +1,48 @@ +/* set_constraint_handler_s( constraint_handler_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + +#ifndef REGTEST + +constraint_handler_t _PDCLIB_constraint_handler = abort_handler_s; + +constraint_handler_t set_constraint_handler_s( constraint_handler_t handler ) +{ + constraint_handler_t previous = _PDCLIB_constraint_handler; + + if ( handler == NULL ) + { + _PDCLIB_constraint_handler = abort_handler_s; + } + else + { + _PDCLIB_constraint_handler = handler; + } + + return previous; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + TESTCASE( _PDCLIB_constraint_handler == abort_handler_s ); + TESTCASE( set_constraint_handler_s( ignore_handler_s ) == abort_handler_s ); + TESTCASE( _PDCLIB_constraint_handler == ignore_handler_s ); + TESTCASE( set_constraint_handler_s( NULL ) == ignore_handler_s ); + TESTCASE( _PDCLIB_constraint_handler == abort_handler_s ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/srand.c b/rocklibc/src/stdlib/srand.c new file mode 100644 index 0000000..39c37ec --- /dev/null +++ b/rocklibc/src/stdlib/srand.c @@ -0,0 +1,28 @@ +/* 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 + +#ifndef REGTEST + +void srand( unsigned int seed ) +{ + _PDCLIB_seed = seed; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* tested in rand.c */ + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/strtod.c b/rocklibc/src/stdlib/strtod.c new file mode 100644 index 0000000..5f87486 --- /dev/null +++ b/rocklibc/src/stdlib/strtod.c @@ -0,0 +1,171 @@ +/* strtod( const char *, char ** ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +#include + +double strtod( const char * s, char ** endptr ) +{ + double rc = 0; + char sign = '+'; + int base = _PDCLIB_strtod_prelim( s, &sign, endptr ); + + s = *endptr; + + switch ( base ) + { + case -2: + rc = 0.0/0.0 * -1; + break; + case -1: + /* INF */ + rc = DBL_MAX * 2; + break; + case 0: + /* No match */ + break; + case 10: + rc = (double)_PDCLIB_naive_etod( s, endptr ); + break; + case 16: + rc = (double)_PDCLIB_naive_ptod( s, endptr ); + break; + } + + if ( sign == '-' ) + { + rc *= -1.0; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include +#include + +typedef struct +{ + const char * s; + double d; + ptrdiff_t l; +} testdata_t; + +extern int dprintf( int, char const *, ... ); + +int main( void ) +{ + double d; + char * s; + testdata_t testdata[] = + { + { "123", 123.0, 3 }, + { "123.45", 123.45, 6 }, + { ".45", 0.45, 3 }, + { "123.", 123, 4 }, + { " -0123f", -123.0, 7 }, + { " -.45", -0.45, 5 }, + { " 0.a", 0.0, 3 }, + { "1.23e2", 123.0, 6 }, + { "1.23e-2", 0.0123, 7 }, + { "-0.000123e+6", -123.0, 12 }, + { "-123000e-3", -123, 10 }, + { "-123e-003", -0.123, 9 }, + { " infx", DBL_MAX * 2, 4 }, + { " nanx", 0.0 / 0.0 * -1, 4 }, + { " -infx", DBL_MAX * 2 * -1, 5 }, + { " -nanx", 0.0 / 0.0, 5 }, + { " nan(foo)", 0.0 / 0.0 * -1, 9 }, + { " nan(foo", 0.0 / 0.0 * -1, 4 } + }; + + d = strtod( testdata[0].s, &s ); + TESTCASE( d == testdata[0].d ); + TESTCASE( (s - testdata[0].s) == testdata[0].l ); + + d = strtod( testdata[1].s, &s ); + TESTCASE( d == testdata[1].d ); + TESTCASE( (s - testdata[1].s) == testdata[1].l ); + + d = strtod( testdata[2].s, &s ); + TESTCASE( d == testdata[2].d ); + TESTCASE( (s - testdata[2].s) == testdata[2].l ); + + d = strtod( testdata[3].s, &s ); + TESTCASE( d == testdata[3].d ); + TESTCASE( (s - testdata[3].s) == testdata[3].l ); + + d = strtod( testdata[4].s, &s ); + TESTCASE( d == testdata[4].d ); + TESTCASE( (s - testdata[4].s) == testdata[4].l ); + + d = strtod( testdata[5].s, &s ); + TESTCASE( d == testdata[5].d ); + TESTCASE( (s - testdata[5].s) == testdata[5].l ); + + d = strtod( testdata[6].s, &s ); + TESTCASE( d == testdata[6].d ); + TESTCASE( (s - testdata[6].s) == testdata[6].l ); + + d = strtod( testdata[7].s, &s ); + TESTCASE( d == testdata[7].d ); + TESTCASE( (s - testdata[7].s) == testdata[7].l ); + + d = strtod( testdata[8].s, &s ); + TESTCASE( d == testdata[8].d ); + TESTCASE( (s - testdata[8].s) == testdata[8].l ); + + d = strtod( testdata[9].s, &s ); + TESTCASE( d == testdata[9].d ); + TESTCASE( (s - testdata[9].s) == testdata[9].l ); + + d = strtod( testdata[10].s, &s ); + TESTCASE( d == testdata[10].d ); + TESTCASE( (s - testdata[10].s) == testdata[10].l ); + + d = strtod( testdata[11].s, &s ); + TESTCASE( d == testdata[11].d ); + TESTCASE( (s - testdata[11].s) == testdata[11].l ); + + d = strtod( testdata[12].s, &s ); + TESTCASE( d == testdata[12].d ); + TESTCASE( (s - testdata[12].s) == testdata[12].l ); + + d = strtod( testdata[13].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[13].s) == testdata[13].l ); + + d = strtod( testdata[14].s, &s ); + TESTCASE( d == testdata[14].d ); + TESTCASE( (s - testdata[14].s) == testdata[14].l ); + + d = strtod( testdata[15].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[15].s) == testdata[15].l ); + + d = strtod( testdata[16].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[16].s) == testdata[16].l ); + + d = strtod( testdata[17].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[17].s) == testdata[17].l ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/strtof.c b/rocklibc/src/stdlib/strtof.c new file mode 100644 index 0000000..0a81951 --- /dev/null +++ b/rocklibc/src/stdlib/strtof.c @@ -0,0 +1,169 @@ +/* strtof( const char *, char ** ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +#include + +float strtof( const char * s, char ** endptr ) +{ + float rc = 0; + char sign = '+'; + int base = _PDCLIB_strtod_prelim( s, &sign, endptr ); + + s = *endptr; + + switch ( base ) + { + case -2: + rc = 0.0/0.0 * -1; + break; + case -1: + /* INF */ + rc = FLT_MAX * 2; + break; + case 0: + /* No match */ + break; + case 10: + rc = (float)_PDCLIB_naive_etod( s, endptr ); + break; + case 16: + rc = (float)_PDCLIB_naive_ptod( s, endptr ); + break; + } + + if ( sign == '-' ) + { + rc *= -1.0; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include +#include + +typedef struct +{ + const char * s; + float d; + ptrdiff_t l; +} testdata_t; + +int main( void ) +{ + float d; + char * s; + testdata_t testdata[] = + { + { "123", 123.0, 3 }, + { "123.45", 123.45, 6 }, + { ".45", 0.45, 3 }, + { "123.", 123, 4 }, + { " -0123f", -123.0, 7 }, + { " -.45", -0.45, 5 }, + { " 0.a", 0.0, 3 }, + { "1.23e2", 123.0, 6 }, + { "1.23e-2", 0.0123, 7 }, + { "-0.000123e+6", -123.0, 12 }, + { "-123000e-3", -123, 10 }, + { "-123e-003", -0.123, 9 }, + { " infx", FLT_MAX * 2, 4 }, + { " nanx", 0.0 / 0.0 * -1, 4 }, + { " -infx", FLT_MAX * 2 * -1, 5 }, + { " -nanx", 0.0 / 0.0, 5 }, + { " nan(foo)", 0.0 / 0.0 * -1, 9 }, + { " nan(foo", 0.0 / 0.0 * -1, 4 } + }; + + d = strtod( testdata[0].s, &s ); + TESTCASE( d == testdata[0].d ); + TESTCASE( (s - testdata[0].s) == testdata[0].l ); + + d = strtod( testdata[1].s, &s ); + TESTCASE( d == testdata[1].d ); + TESTCASE( (s - testdata[1].s) == testdata[1].l ); + + d = strtod( testdata[2].s, &s ); + TESTCASE( d == testdata[2].d ); + TESTCASE( (s - testdata[2].s) == testdata[2].l ); + + d = strtod( testdata[3].s, &s ); + TESTCASE( d == testdata[3].d ); + TESTCASE( (s - testdata[3].s) == testdata[3].l ); + + d = strtod( testdata[4].s, &s ); + TESTCASE( d == testdata[4].d ); + TESTCASE( (s - testdata[4].s) == testdata[4].l ); + + d = strtod( testdata[5].s, &s ); + TESTCASE( d == testdata[5].d ); + TESTCASE( (s - testdata[5].s) == testdata[5].l ); + + d = strtod( testdata[6].s, &s ); + TESTCASE( d == testdata[6].d ); + TESTCASE( (s - testdata[6].s) == testdata[6].l ); + + d = strtod( testdata[7].s, &s ); + TESTCASE( d == testdata[7].d ); + TESTCASE( (s - testdata[7].s) == testdata[7].l ); + + d = strtod( testdata[8].s, &s ); + TESTCASE( d == testdata[8].d ); + TESTCASE( (s - testdata[8].s) == testdata[8].l ); + + d = strtod( testdata[9].s, &s ); + TESTCASE( d == testdata[9].d ); + TESTCASE( (s - testdata[9].s) == testdata[9].l ); + + d = strtod( testdata[10].s, &s ); + TESTCASE( d == testdata[10].d ); + TESTCASE( (s - testdata[10].s) == testdata[10].l ); + + d = strtod( testdata[11].s, &s ); + TESTCASE( d == testdata[11].d ); + TESTCASE( (s - testdata[11].s) == testdata[11].l ); + + d = strtod( testdata[12].s, &s ); + TESTCASE( d == testdata[12].d ); + TESTCASE( (s - testdata[12].s) == testdata[12].l ); + + d = strtod( testdata[13].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[13].s) == testdata[13].l ); + + d = strtod( testdata[14].s, &s ); + TESTCASE( d == testdata[14].d ); + TESTCASE( (s - testdata[14].s) == testdata[14].l ); + + d = strtod( testdata[15].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[15].s) == testdata[15].l ); + + d = strtod( testdata[16].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[16].s) == testdata[16].l ); + + d = strtod( testdata[17].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[17].s) == testdata[17].l ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/strtol.c b/rocklibc/src/stdlib/strtol.c new file mode 100644 index 0000000..6d6d657 --- /dev/null +++ b/rocklibc/src/stdlib/strtol.c @@ -0,0 +1,144 @@ +/* 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 + +#ifndef REGTEST + +#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, &sign ); + } + else + { + rc = ( long int )_PDCLIB_strtox_main( &p, ( unsigned )base, ( uintmax_t )( unsigned long )LONG_MIN, ( ( uintmax_t )LONG_MAX + 1 ), &sign ); + } + + if ( endptr != NULL ) + { + *endptr = ( p != NULL ) ? ( char * ) p : ( char * ) s; + } + + return ( sign == '+' ) ? rc : -rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + char * endptr; + /* this, to base 36, overflows even a 256 bit integer */ + char overflow[] = "-ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ_"; + /* tricky border case */ + char tricky[] = "+0xz"; + errno = 0; + /* basic functionality */ + TESTCASE( strtol( "123", NULL, 10 ) == 123 ); + /* proper detecting of default base 10 */ + TESTCASE( strtol( "456", NULL, 0 ) == 456 ); + /* proper functioning to smaller base */ + TESTCASE( strtol( "14", NULL, 8 ) == 12 ); + /* proper autodetecting of octal */ + TESTCASE( strtol( "016", NULL, 0 ) == 14 ); + /* proper autodetecting of hexadecimal, lowercase 'x' */ + TESTCASE( strtol( "0xFF", NULL, 0 ) == 255 ); + /* proper autodetecting of hexadecimal, uppercase 'X' */ + TESTCASE( strtol( "0Xa1", NULL, 0 ) == 161 ); + /* proper handling of border case: 0x followed by non-hexdigit */ + TESTCASE( strtol( tricky, &endptr, 0 ) == 0 ); + /* newlib completely balks at this parse, so we _NOREG it. */ + TESTCASE_NOREG( endptr == tricky + 2 ); + /* proper handling of border case: 0 followed by non-octdigit */ + TESTCASE( strtol( tricky, &endptr, 8 ) == 0 ); + TESTCASE( endptr == tricky + 2 ); + /* errno should still be 0 */ + TESTCASE( errno == 0 ); + /* correctly decoding zero */ + TESTCASE( strtol( "0", &endptr, 0 ) == 0 ); + TESTCASE( *endptr == '\0' ); + TESTCASE( errno == 0 ); + /* overflowing subject sequence must still return proper endptr */ + TESTCASE( strtol( overflow, &endptr, 36 ) == LONG_MIN ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* same for positive */ + errno = 0; + TESTCASE( strtol( overflow + 1, &endptr, 36 ) == LONG_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* testing skipping of leading whitespace */ + TESTCASE( strtol( " \n\v\t\f789", NULL, 0 ) == 789 ); + /* testing conversion failure */ + TESTCASE( strtol( overflow, &endptr, 10 ) == 0 ); + TESTCASE( endptr == overflow ); + endptr = NULL; + TESTCASE( strtol( overflow, &endptr, 0 ) == 0 ); + TESTCASE( endptr == overflow ); + /* TODO: These tests assume two-complement, but conversion should work */ + /* for one-complement and signed magnitude just as well. Anyone having */ + /* a platform to test this on? */ + errno = 0; +#if LONG_MAX >> 30 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtol( "2147483647", NULL, 0 ) == 0x7fffffff ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtol( "2147483648", NULL, 0 ) == LONG_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtol( "-2147483647", NULL, 0 ) == ( long )0x80000001 ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtol( "-2147483648", NULL, 0 ) == LONG_MIN ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtol( "-2147483649", NULL, 0 ) == LONG_MIN ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ +#elif LONG_MAX >> 62 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtol( "9223372036854775807", NULL, 0 ) == 0x7fffffffffffffff ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtol( "9223372036854775808", NULL, 0 ) == LONG_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtol( "-9223372036854775807", NULL, 0 ) == ( long )0x8000000000000001 ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtol( "-9223372036854775808", NULL, 0 ) == LONG_MIN ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtol( "-9223372036854775809", NULL, 0 ) == LONG_MIN ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ +#else +#error Unsupported width of 'long' (neither 32 nor 64 bit). +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/strtold.c b/rocklibc/src/stdlib/strtold.c new file mode 100644 index 0000000..4c473c7 --- /dev/null +++ b/rocklibc/src/stdlib/strtold.c @@ -0,0 +1,169 @@ +/* strtold( const char *, char ** ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_internal.h" + +#include + +long double strtold( const char * s, char ** endptr ) +{ + long double rc = 0; + char sign = '+'; + int base = _PDCLIB_strtod_prelim( s, &sign, endptr ); + + s = *endptr; + + switch ( base ) + { + case -2: + rc = 0.0/0.0 * -1; + break; + case -1: + /* INF */ + rc = LDBL_MAX * 2; + break; + case 0: + /* No match */ + break; + case 10: + rc = (long double)_PDCLIB_naive_etod( s, endptr ); + break; + case 16: + rc = (long double)_PDCLIB_naive_ptod( s, endptr ); + break; + } + + if ( sign == '-' ) + { + rc *= -1.0; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include +#include + +typedef struct +{ + const char * s; + long double d; + ptrdiff_t l; +} testdata_t; + +int main( void ) +{ + long double d; + char * s; + testdata_t testdata[] = + { + { "123", 123.0, 3 }, + { "123.45", 123.45, 6 }, + { ".45", 0.45, 3 }, + { "123.", 123, 4 }, + { " -0123f", -123.0, 7 }, + { " -.45", -0.45, 5 }, + { " 0.a", 0.0, 3 }, + { "1.23e2", 123.0, 6 }, + { "1.23e-2", 0.0123, 7 }, + { "-0.000123e+6", -123.0, 12 }, + { "-123000e-3", -123, 10 }, + { "-123e-003", -0.123, 9 }, + { " infx", LDBL_MAX * 2, 4 }, + { " nanx", 0.0 / 0.0 * -1, 4 }, + { " -infx", LDBL_MAX * 2 * -1, 5 }, + { " -nanx", 0.0 / 0.0, 5 }, + { " nan(foo)", 0.0 / 0.0 * -1, 9 }, + { " nan(foo", 0.0 / 0.0 * -1, 4 } + }; + + d = strtod( testdata[0].s, &s ); + TESTCASE( d == testdata[0].d ); + TESTCASE( (s - testdata[0].s) == testdata[0].l ); + + d = strtod( testdata[1].s, &s ); + TESTCASE( d == testdata[1].d ); + TESTCASE( (s - testdata[1].s) == testdata[1].l ); + + d = strtod( testdata[2].s, &s ); + TESTCASE( d == testdata[2].d ); + TESTCASE( (s - testdata[2].s) == testdata[2].l ); + + d = strtod( testdata[3].s, &s ); + TESTCASE( d == testdata[3].d ); + TESTCASE( (s - testdata[3].s) == testdata[3].l ); + + d = strtod( testdata[4].s, &s ); + TESTCASE( d == testdata[4].d ); + TESTCASE( (s - testdata[4].s) == testdata[4].l ); + + d = strtod( testdata[5].s, &s ); + TESTCASE( d == testdata[5].d ); + TESTCASE( (s - testdata[5].s) == testdata[5].l ); + + d = strtod( testdata[6].s, &s ); + TESTCASE( d == testdata[6].d ); + TESTCASE( (s - testdata[6].s) == testdata[6].l ); + + d = strtod( testdata[7].s, &s ); + TESTCASE( d == testdata[7].d ); + TESTCASE( (s - testdata[7].s) == testdata[7].l ); + + d = strtod( testdata[8].s, &s ); + TESTCASE( d == testdata[8].d ); + TESTCASE( (s - testdata[8].s) == testdata[8].l ); + + d = strtod( testdata[9].s, &s ); + TESTCASE( d == testdata[9].d ); + TESTCASE( (s - testdata[9].s) == testdata[9].l ); + + d = strtod( testdata[10].s, &s ); + TESTCASE( d == testdata[10].d ); + TESTCASE( (s - testdata[10].s) == testdata[10].l ); + + d = strtod( testdata[11].s, &s ); + TESTCASE( d == testdata[11].d ); + TESTCASE( (s - testdata[11].s) == testdata[11].l ); + + d = strtod( testdata[12].s, &s ); + TESTCASE( d == testdata[12].d ); + TESTCASE( (s - testdata[12].s) == testdata[12].l ); + + d = strtod( testdata[13].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[13].s) == testdata[13].l ); + + d = strtod( testdata[14].s, &s ); + TESTCASE( d == testdata[14].d ); + TESTCASE( (s - testdata[14].s) == testdata[14].l ); + + d = strtod( testdata[15].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[15].s) == testdata[15].l ); + + d = strtod( testdata[16].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[16].s) == testdata[16].l ); + + d = strtod( testdata[17].s, &s ); + TESTCASE( d != d ); + TESTCASE( (s - testdata[17].s) == testdata[17].l ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/strtoll.c b/rocklibc/src/stdlib/strtoll.c new file mode 100644 index 0000000..0be6b78 --- /dev/null +++ b/rocklibc/src/stdlib/strtoll.c @@ -0,0 +1,138 @@ +/* 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 + +#ifndef REGTEST + +#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, &sign ); + } + else + { + rc = ( long long int )_PDCLIB_strtox_main( &p, ( unsigned )base, ( uintmax_t )( unsigned long long )LLONG_MIN, ( ( uintmax_t )LLONG_MAX + 1 ), &sign ); + } + + if ( endptr != NULL ) + { + *endptr = ( p != NULL ) ? ( char * ) p : ( char * ) s; + } + + return ( sign == '+' ) ? rc : -rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + char * endptr; + /* this, to base 36, overflows even a 256 bit integer */ + char overflow[] = "-ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ_"; + /* tricky border case */ + char tricky[] = "+0xz"; + errno = 0; + /* basic functionality */ + TESTCASE( strtoll( "123", NULL, 10 ) == 123 ); + /* proper detecting of default base 10 */ + TESTCASE( strtoll( "456", NULL, 0 ) == 456 ); + /* proper functioning to smaller base */ + TESTCASE( strtoll( "14", NULL, 8 ) == 12 ); + /* proper autodetecting of octal */ + TESTCASE( strtoll( "016", NULL, 0 ) == 14 ); + /* proper autodetecting of hexadecimal, lowercase 'x' */ + TESTCASE( strtoll( "0xFF", NULL, 0 ) == 255 ); + /* proper autodetecting of hexadecimal, uppercase 'X' */ + TESTCASE( strtoll( "0Xa1", NULL, 0 ) == 161 ); + /* proper handling of border case: 0x followed by non-hexdigit */ + TESTCASE( strtoll( tricky, &endptr, 0 ) == 0 ); + /* newlib completely balks at this parse, so we _NOREG it */ + TESTCASE_NOREG( endptr == tricky + 2 ); + /* proper handling of border case: 0 followed by non-octdigit */ + TESTCASE( strtoll( tricky, &endptr, 8 ) == 0 ); + TESTCASE( endptr == tricky + 2 ); + /* errno should still be 0 */ + TESTCASE( errno == 0 ); + /* correctly decoding zero */ + TESTCASE( strtoll( "0", &endptr, 0 ) == 0 ); + TESTCASE( *endptr == '\0' ); + TESTCASE( errno == 0 ); + /* overflowing subject sequence must still return proper endptr */ + TESTCASE( strtoll( overflow, &endptr, 36 ) == LLONG_MIN ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* same for positive */ + errno = 0; + TESTCASE( strtoll( overflow + 1, &endptr, 36 ) == LLONG_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* testing skipping of leading whitespace */ + TESTCASE( strtoll( " \n\v\t\f789", NULL, 0 ) == 789 ); + /* testing conversion failure */ + TESTCASE( strtoll( overflow, &endptr, 10 ) == 0 ); + TESTCASE( endptr == overflow ); + endptr = NULL; + TESTCASE( strtoll( overflow, &endptr, 0 ) == 0 ); + TESTCASE( endptr == overflow ); + /* TODO: These tests assume two-complement, but conversion should work */ + /* for one-complement and signed magnitude just as well. Anyone having */ + /* a platform to test this on? */ + errno = 0; +#if LLONG_MAX >> 62 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtoll( "9223372036854775807", NULL, 0 ) == 0x7fffffffffffffff ); + TESTCASE( errno == 0 ); + TESTCASE( strtoll( "9223372036854775808", NULL, 0 ) == LLONG_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtoll( "-9223372036854775807", NULL, 0 ) == ( long long )0x8000000000000001 ); + TESTCASE( errno == 0 ); + TESTCASE( strtoll( "-9223372036854775808", NULL, 0 ) == LLONG_MIN ); + TESTCASE( errno == 0 ); + TESTCASE( strtoll( "-9223372036854775809", NULL, 0 ) == LLONG_MIN ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ +#elif LLONG_MAX >> 126 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtoll( "170141183460469231731687303715884105728", NULL, 0 ) == 0x7fffffffffffffffffffffffffffffff ); + TESTCASE( errno == 0 ); + TESTCASE( strtoll( "170141183460469231731687303715884105729", NULL, 0 ) == LLONG_MAX ); + TESTCASE( errno == ERANGE ); + errno = 0; + TESTCASE( strtoll( "-170141183460469231731687303715884105728", NULL, 0 ) == -0x80000000000000000000000000000001 ); + TESTCASE( errno == 0 ); + TESTCASE( strtoll( "-170141183460469231731687303715884105729", NULL, 0 ) == LLONG_MIN ); + TESTCASE( errno == 0 ); + TESTCASE( strtoll( "-170141183460469231731687303715884105730", NULL, 0 ) == LLONG_MIN ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ +#else +#error Unsupported width of 'long long' (neither 64 nor 128 bit). +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/strtoul.c b/rocklibc/src/stdlib/strtoul.c new file mode 100644 index 0000000..c889e2b --- /dev/null +++ b/rocklibc/src/stdlib/strtoul.c @@ -0,0 +1,124 @@ +/* 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 + +#ifndef REGTEST + +#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, &sign ); + + if ( endptr != NULL ) + { + *endptr = ( p != NULL ) ? ( char * ) p : ( char * ) s; + } + + return ( sign == '+' ) ? rc : -rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + char * endptr; + /* this, to base 36, overflows even a 256 bit integer */ + char overflow[] = "-ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ_"; + /* tricky border case */ + char tricky[] = "+0xz"; + errno = 0; + /* basic functionality */ + TESTCASE( strtoul( "123", NULL, 10 ) == 123 ); + /* proper detecting of default base 10 */ + TESTCASE( strtoul( "456", NULL, 0 ) == 456 ); + /* proper functioning to smaller base */ + TESTCASE( strtoul( "14", NULL, 8 ) == 12 ); + /* proper autodetecting of octal */ + TESTCASE( strtoul( "016", NULL, 0 ) == 14 ); + /* proper autodetecting of hexadecimal, lowercase 'x' */ + TESTCASE( strtoul( "0xFF", NULL, 0 ) == 255 ); + /* proper autodetecting of hexadecimal, uppercase 'X' */ + TESTCASE( strtoul( "0Xa1", NULL, 0 ) == 161 ); + /* proper handling of border case: 0x followed by non-hexdigit */ + TESTCASE( strtoul( tricky, &endptr, 0 ) == 0 ); + /* newlib completely balks at this parse, so we _NOREG it */ + TESTCASE_NOREG( endptr == tricky + 2 ); + /* proper handling of border case: 0 followed by non-octdigit */ + TESTCASE( strtoul( tricky, &endptr, 8 ) == 0 ); + TESTCASE( endptr == tricky + 2 ); + /* errno should still be 0 */ + TESTCASE( errno == 0 ); + /* correctly decoding zero */ + TESTCASE( strtoul( "0", &endptr, 0 ) == 0 ); + TESTCASE( *endptr == '\0' ); + TESTCASE( errno == 0 ); + /* overflowing subject sequence must still return proper endptr */ + TESTCASE( strtoul( overflow, &endptr, 36 ) == ULONG_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* same for positive */ + errno = 0; + TESTCASE( strtoul( overflow + 1, &endptr, 36 ) == ULONG_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* testing skipping of leading whitespace */ + TESTCASE( strtoul( " \n\v\t\f789", NULL, 0 ) == 789 ); + /* testing conversion failure */ + TESTCASE( strtoul( overflow, &endptr, 10 ) == 0 ); + TESTCASE( endptr == overflow ); + endptr = NULL; + TESTCASE( strtoul( overflow, &endptr, 0 ) == 0 ); + TESTCASE( endptr == overflow ); + /* TODO: These tests assume two-complement, but conversion should work */ + /* for one-complement and signed magnitude just as well. Anyone having */ + /* a platform to test this on? */ + errno = 0; + /* long -> 32 bit */ +#if ULONG_MAX >> 31 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtoul( "4294967295", NULL, 0 ) == ULONG_MAX ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtoul( "4294967296", NULL, 0 ) == ULONG_MAX ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ + /* long -> 64 bit */ +#elif ULONG_MAX >> 63 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtoul( "18446744073709551615", NULL, 0 ) == ULONG_MAX ); + TESTCASE( errno == 0 ); + errno = 0; + TESTCASE( strtoul( "18446744073709551616", NULL, 0 ) == ULONG_MAX ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ +#else +#error Unsupported width of 'long' (neither 32 nor 64 bit). +#endif + errno = 0; + TESTCASE( strtoul( "-1", NULL, 0 ) == ULONG_MAX ); + TESTCASE( errno == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/strtoull.c b/rocklibc/src/stdlib/strtoull.c new file mode 100644 index 0000000..f890912 --- /dev/null +++ b/rocklibc/src/stdlib/strtoull.c @@ -0,0 +1,119 @@ +/* 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 + +#ifndef REGTEST + +#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, &sign ); + + if ( endptr != NULL ) + { + *endptr = ( p != NULL ) ? ( char * ) p : ( char * ) s; + } + + return ( sign == '+' ) ? rc : -rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + char * endptr; + /* this, to base 36, overflows even a 256 bit integer */ + char overflow[] = "-ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ_"; + /* tricky border case */ + char tricky[] = "+0xz"; + errno = 0; + /* basic functionality */ + TESTCASE( strtoull( "123", NULL, 10 ) == 123 ); + /* proper detecting of default base 10 */ + TESTCASE( strtoull( "456", NULL, 0 ) == 456 ); + /* proper functioning to smaller base */ + TESTCASE( strtoull( "14", NULL, 8 ) == 12 ); + /* proper autodetecting of octal */ + TESTCASE( strtoull( "016", NULL, 0 ) == 14 ); + /* proper autodetecting of hexadecimal, lowercase 'x' */ + TESTCASE( strtoull( "0xFF", NULL, 0 ) == 255 ); + /* proper autodetecting of hexadecimal, uppercase 'X' */ + TESTCASE( strtoull( "0Xa1", NULL, 0 ) == 161 ); + /* proper handling of border case: 0x followed by non-hexdigit */ + TESTCASE( strtoull( tricky, &endptr, 0 ) == 0 ); + /* newlib completely balks at this parse, so we _NOREG it */ + TESTCASE_NOREG( endptr == tricky + 2 ); + /* proper handling of border case: 0 followed by non-octdigit */ + TESTCASE( strtoull( tricky, &endptr, 8 ) == 0 ); + TESTCASE( endptr == tricky + 2 ); + /* errno should still be 0 */ + TESTCASE( errno == 0 ); + /* correctly decoding zero */ + TESTCASE( strtoull( "0", &endptr, 0 ) == 0 ); + TESTCASE( *endptr == '\0' ); + TESTCASE( errno == 0 ); + /* overflowing subject sequence must still return proper endptr */ + TESTCASE( strtoull( overflow, &endptr, 36 ) == ULLONG_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* same for positive */ + errno = 0; + TESTCASE( strtoull( overflow + 1, &endptr, 36 ) == ULLONG_MAX ); + TESTCASE( errno == ERANGE ); + TESTCASE( ( endptr - overflow ) == 53 ); + /* testing skipping of leading whitespace */ + TESTCASE( strtoull( " \n\v\t\f789", NULL, 0 ) == 789 ); + /* testing conversion failure */ + TESTCASE( strtoull( overflow, &endptr, 10 ) == 0 ); + TESTCASE( endptr == overflow ); + endptr = NULL; + TESTCASE( strtoull( overflow, &endptr, 0 ) == 0 ); + TESTCASE( endptr == overflow ); + errno = 0; + /* long long -> 64 bit */ +#if ULLONG_MAX >> 63 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtoull( "18446744073709551615", NULL, 0 ) == ULLONG_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoull( "18446744073709551616", NULL, 0 ) == ULLONG_MAX ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ + /* long long -> 128 bit */ +#elif ULLONG_MAX >> 127 == 1 + /* testing "even" overflow, i.e. base is power of two */ + TESTCASE( strtoull( "340282366920938463463374607431768211455", NULL, 0 ) == ULLONG_MAX ); + TESTCASE( errno == 0 ); + TESTCASE( strtoull( "340282366920938463463374607431768211456", NULL, 0 ) == ULLONG_MAX ); + TESTCASE( errno == ERANGE ); + /* TODO: test "odd" overflow, i.e. base is not power of two */ +#else +#error Unsupported width of 'long long' (neither 64 nor 128 bit). +#endif + errno = 0; + TESTCASE( strtoull( "-1", NULL, 0 ) == ULLONG_MAX ); + TESTCASE( errno == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/stdlib/system.c b/rocklibc/src/stdlib/system.c new file mode 100644 index 0000000..f8b3b80 --- /dev/null +++ b/rocklibc/src/stdlib/system.c @@ -0,0 +1,71 @@ +/* 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. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int fork( void ); +extern int execve( const char * filename, char * const argv[], char * const envp[] ); +extern int wait( int * status ); + +#ifdef __cplusplus +} +#endif + +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 ) + { + /* EMPTY */ + } + } + } + + return -1; +} + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#define SHELLCOMMAND "echo 'SUCCESS testing system()'" + +int main( void ) +{ + FILE * fh; + char buffer[25]; + buffer[24] = 'x'; + TESTCASE( ( fh = freopen( testfile, "wb+", stdout ) ) != NULL ); + TESTCASE( system( SHELLCOMMAND ) ); + rewind( fh ); + TESTCASE( fread( buffer, 1, 24, fh ) == 24 ); + TESTCASE( memcmp( buffer, "SUCCESS testing system()", 24 ) == 0 ); + TESTCASE( buffer[24] == 'x' ); + TESTCASE( fclose( fh ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/memchr.c b/rocklibc/src/string/memchr.c new file mode 100644 index 0000000..5e0186c --- /dev/null +++ b/rocklibc/src/string/memchr.c @@ -0,0 +1,44 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( memchr( abcde, 'c', 5 ) == &abcde[2] ); + TESTCASE( memchr( abcde, 'a', 1 ) == &abcde[0] ); + TESTCASE( memchr( abcde, 'a', 0 ) == NULL ); + TESTCASE( memchr( abcde, '\0', 5 ) == NULL ); + TESTCASE( memchr( abcde, '\0', 6 ) == &abcde[5] ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/memcmp.c b/rocklibc/src/string/memcmp.c new file mode 100644 index 0000000..2c9fdfe --- /dev/null +++ b/rocklibc/src/string/memcmp.c @@ -0,0 +1,46 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + const char xxxxx[] = "xxxxx"; + TESTCASE( memcmp( abcde, abcdx, 5 ) < 0 ); + TESTCASE( memcmp( abcde, abcdx, 4 ) == 0 ); + TESTCASE( memcmp( abcde, xxxxx, 0 ) == 0 ); + TESTCASE( memcmp( xxxxx, abcde, 1 ) > 0 ); + return 0; +} + +#endif diff --git a/rocklibc/src/string/memcpy.c b/rocklibc/src/string/memcpy.c new file mode 100644 index 0000000..d2cabb3 --- /dev/null +++ b/rocklibc/src/string/memcpy.c @@ -0,0 +1,42 @@ +/* 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 + +#ifndef REGTEST + +void * memcpy( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n ) +{ + char * dest = ( char * ) s1; + const char * src = ( const char * ) s2; + + while ( n-- ) + { + *dest++ = *src++; + } + + return s1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxxxxxx"; + TESTCASE( memcpy( s, abcde, 6 ) == s ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( memcpy( s + 5, abcde, 5 ) == s + 5 ); + TESTCASE( s[9] == 'e' ); + TESTCASE( s[10] == 'x' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/memcpy_s.c b/rocklibc/src/string/memcpy_s.c new file mode 100644 index 0000000..b5a2f66 --- /dev/null +++ b/rocklibc/src/string/memcpy_s.c @@ -0,0 +1,92 @@ +/* memcpy_s( void *, rsize_t, const void *, rsize_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t memcpy_s( void * _PDCLIB_restrict s1, rsize_t s1max, const void * _PDCLIB_restrict s2, rsize_t n ) +{ + char * dest = ( char * ) s1; + const char * src = ( const char * ) s2; + + if ( s1 != NULL && s2 != NULL && s1max <= RSIZE_MAX && n <= RSIZE_MAX && n <= s1max ) + { + while ( n-- ) + { + if ( dest == s2 || src == s1 ) + { + goto runtime_constraint_violation; + } + + *dest++ = *src++; + } + + return 0; + } + +runtime_constraint_violation: + + if ( s1 != NULL && s1max <= RSIZE_MAX ) + { + memset( s1, 0, s1max ); + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "xxxxxxxxxxx"; + set_constraint_handler_s( test_handler ); + + TESTCASE( memcpy_s( s, 11, abcde, 6 ) == 0 ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( memcpy_s( s + 5, 6, abcde, 5 ) == 0 ); + TESTCASE( s[9] == 'e' ); + TESTCASE( s[10] == 'x' ); + + s[5] = 'x'; + + TESTCASE( memcpy_s( s, 5, abcde, 6 ) != 0 ); + TESTCASE( memcmp( s, "\0\0\0\0\0x", 6 ) == 0 ); + + TESTCASE( memcpy_s( s, 3, s + 2, 3 ) != 0 ); + TESTCASE( memcpy_s( s + 2, 3, s, 3 ) != 0 ); + + /* Overlapping */ + TESTCASE( memcpy_s( s, 4, s + 3, 4 ) != 0 ); + TESTCASE( memcpy_s( s + 3, 4, s, 4 ) != 0 ); + + TESTCASE( HANDLER_CALLS == 5 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/memmove.c b/rocklibc/src/string/memmove.c new file mode 100644 index 0000000..d361bb5 --- /dev/null +++ b/rocklibc/src/string/memmove.c @@ -0,0 +1,55 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxabcde"; + TESTCASE( memmove( s, s + 4, 5 ) == s ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == 'b' ); + TESTCASE( memmove( s + 4, s, 5 ) == s + 4 ); + TESTCASE( s[4] == 'a' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/memmove_s.c b/rocklibc/src/string/memmove_s.c new file mode 100644 index 0000000..1b02fb1 --- /dev/null +++ b/rocklibc/src/string/memmove_s.c @@ -0,0 +1,87 @@ +/* memmove_s( void *, rsize_t, const void *, rsize_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t memmove_s( void * s1, rsize_t s1max, const void * s2, rsize_t n ) +{ + char * dest = ( char * ) s1; + const char * src = ( const char * ) s2; + + if ( s1 == NULL || s2 == NULL || s1max > RSIZE_MAX || n > RSIZE_MAX || n > s1max ) + { + if ( s1 != NULL && s1max <= RSIZE_MAX ) + { + memset( s1, 0, s1max ); + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + while ( n ) + { + if ( dest == s2 || src == s1 ) + { + src += n; + dest += n; + + while ( n-- ) + { + *--dest = *--src; + } + + return 0; + } + + *dest++ = *src++; + --n; + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "xxxxabcde"; + set_constraint_handler_s( test_handler ); + + TESTCASE( memmove_s( s, 10, s + 4, 5 ) == 0 ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == 'b' ); + TESTCASE( memmove_s( s + 4, 6, s, 5 ) == 0 ); + TESTCASE( s[4] == 'a' ); + + TESTCASE( HANDLER_CALLS == 0 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/memset.c b/rocklibc/src/string/memset.c new file mode 100644 index 0000000..4871246 --- /dev/null +++ b/rocklibc/src/string/memset.c @@ -0,0 +1,42 @@ +/* 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 + +#ifndef REGTEST + +void * memset( void * s, int c, size_t n ) +{ + unsigned char * p = ( unsigned char * ) s; + + while ( n-- ) + { + *p++ = ( unsigned char ) c; + } + + return s; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxxxx"; + TESTCASE( memset( s, 'o', 10 ) == s ); + TESTCASE( s[9] == 'o' ); + TESTCASE( memset( s, '_', ( 0 ) ) == s ); + TESTCASE( s[0] == 'o' ); + TESTCASE( memset( s, '_', 1 ) == s ); + TESTCASE( s[0] == '_' ); + TESTCASE( s[1] == 'o' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/memset_s.c b/rocklibc/src/string/memset_s.c new file mode 100644 index 0000000..622c0a8 --- /dev/null +++ b/rocklibc/src/string/memset_s.c @@ -0,0 +1,73 @@ +/* memset_s( void *, rsize_t, int, rsize_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t memset_s( void * s, rsize_t smax, int c, rsize_t n ) +{ + unsigned char * p = ( unsigned char * ) s; + + if ( s == NULL || smax > RSIZE_MAX || n > RSIZE_MAX || n > smax ) + { + if ( s != NULL && smax <= RSIZE_MAX ) + { + memset( s, c, smax ); + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + while ( n-- ) + { + *p++ = ( unsigned char ) c; + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "xxxxxxxxx"; + set_constraint_handler_s( test_handler ); + + TESTCASE( memset_s( s, 10, 'o', 10 ) == 0 ); + TESTCASE( s[9] == 'o' ); + TESTCASE( memset_s( s, 10, '_', ( 0 ) ) == 0 ); + TESTCASE( s[0] == 'o' ); + TESTCASE( memset_s( s, 10, '_', 1 ) == 0 ); + TESTCASE( s[0] == '_' ); + TESTCASE( s[1] == 'o' ); + + TESTCASE( HANDLER_CALLS == 0 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strcat.c b/rocklibc/src/string/strcat.c new file mode 100644 index 0000000..f9187cc --- /dev/null +++ b/rocklibc/src/string/strcat.c @@ -0,0 +1,55 @@ +/* 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 + +#ifndef REGTEST + +char * strcat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ) +{ + char * rc = s1; + + if ( *s1 ) + { + while ( *++s1 ) + { + /* EMPTY */ + } + } + + while ( ( *s1++ = *s2++ ) ) + { + /* EMPTY */ + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xx\0xxxxxx"; + TESTCASE( strcat( s, abcde ) == s ); + TESTCASE( s[2] == 'a' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( s[7] == '\0' ); + TESTCASE( s[8] == 'x' ); + s[0] = '\0'; + TESTCASE( strcat( s, abcdx ) == s ); + TESTCASE( s[4] == 'x' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strcat( s, "\0" ) == s ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strcat_s.c b/rocklibc/src/string/strcat_s.c new file mode 100644 index 0000000..e356174 --- /dev/null +++ b/rocklibc/src/string/strcat_s.c @@ -0,0 +1,103 @@ +/* strcat_s( char *, rsize_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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t strcat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 ) +{ + char * dest = s1; + const char * src = s2; + + if ( s1 != NULL && s2 != NULL && s1max <= RSIZE_MAX && s1max != 0 ) + { + while ( *dest ) + { + if ( s1max-- == 0 || dest++ == s2 ) + { + goto runtime_constraint_violation; + } + } + + do + { + if ( s1max-- == 0 || dest == s2 || src == s1 ) + { + goto runtime_constraint_violation; + } + } while ( ( *dest++ = *src++ ) ); + + return 0; + } + +runtime_constraint_violation: + + if ( s1 != NULL && s1max > 0 && s1max <= RSIZE_MAX ) + { + s1[0] = '\0'; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "xx\0xxxxxx"; + set_constraint_handler_s( test_handler ); + + TESTCASE( strcat_s( s, 10, abcde ) == 0 ); + TESTCASE( s[2] == 'a' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( s[7] == '\0' ); + TESTCASE( s[8] == 'x' ); + s[0] = '\0'; + TESTCASE( strcat_s( s, 10, abcdx ) == 0 ); + TESTCASE( s[4] == 'x' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strcat_s( s, 10, "\0" ) == 0 ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + + TESTCASE( strcat_s( s, 6, "" ) == 0 ); + TESTCASE( strcat_s( s, 5, "" ) != 0 ); + TESTCASE( strcat_s( s, 7, "x" ) == 0 ); + TESTCASE( s[5] == 'x' ); + TESTCASE( s[6] == '\0' ); + + /* Overlapping */ + TESTCASE( strcat_s( s, 7, s + 6 ) != 0 ); + s[3] = '\0'; + TESTCASE( strcat_s( s + 3, 4, s ) != 0 ); + + TESTCASE( HANDLER_CALLS == 3 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strchr.c b/rocklibc/src/string/strchr.c new file mode 100644 index 0000000..140a2cf --- /dev/null +++ b/rocklibc/src/string/strchr.c @@ -0,0 +1,41 @@ +/* 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 + +#ifndef REGTEST + +char * strchr( const char * s, int c ) +{ + do + { + if ( *s == ( char ) c ) + { + return ( char * ) s; + } + } while ( *s++ ); + + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char abccd[] = "abccd"; + TESTCASE( strchr( abccd, 'x' ) == NULL ); + TESTCASE( strchr( abccd, 'a' ) == &abccd[0] ); + TESTCASE( strchr( abccd, 'd' ) == &abccd[4] ); + TESTCASE( strchr( abccd, '\0' ) == &abccd[5] ); + TESTCASE( strchr( abccd, 'c' ) == &abccd[2] ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strcmp.c b/rocklibc/src/string/strcmp.c new file mode 100644 index 0000000..ac17d22 --- /dev/null +++ b/rocklibc/src/string/strcmp.c @@ -0,0 +1,42 @@ +/* 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 + +#ifndef REGTEST + +int strcmp( const char * s1, const char * s2 ) +{ + while ( ( *s1 ) && ( *s1 == *s2 ) ) + { + ++s1; + ++s2; + } + + return ( *( unsigned char * )s1 - * ( unsigned char * )s2 ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char cmpabcde[] = "abcde"; + char cmpabcd_[] = "abcd\xfc"; + char empty[] = ""; + TESTCASE( strcmp( abcde, cmpabcde ) == 0 ); + TESTCASE( strcmp( abcde, abcdx ) < 0 ); + TESTCASE( strcmp( abcdx, abcde ) > 0 ); + TESTCASE( strcmp( empty, abcde ) < 0 ); + TESTCASE( strcmp( abcde, empty ) > 0 ); + TESTCASE( strcmp( abcde, cmpabcd_ ) < 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strcoll.c b/rocklibc/src/string/strcoll.c new file mode 100644 index 0000000..2b1cb5f --- /dev/null +++ b/rocklibc/src/string/strcoll.c @@ -0,0 +1,37 @@ +/* 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 + +#ifndef REGTEST + +#include + +int strcoll( const char * s1, const char * s2 ) +{ + /* FIXME: This should access _PDCLIB_lc_collate. */ + return strcmp( s1, s2 ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char cmpabcde[] = "abcde"; + char empty[] = ""; + TESTCASE( strcmp( abcde, cmpabcde ) == 0 ); + TESTCASE( strcmp( abcde, abcdx ) < 0 ); + TESTCASE( strcmp( abcdx, abcde ) > 0 ); + TESTCASE( strcmp( empty, abcde ) < 0 ); + TESTCASE( strcmp( abcde, empty ) > 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strcpy.c b/rocklibc/src/string/strcpy.c new file mode 100644 index 0000000..86059c2 --- /dev/null +++ b/rocklibc/src/string/strcpy.c @@ -0,0 +1,42 @@ +/* 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 + +#ifndef REGTEST + +char * strcpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ) +{ + char * rc = s1; + + while ( ( *s1++ = *s2++ ) ) + { + /* EMPTY */ + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxx"; + TESTCASE( strcpy( s, "" ) == s ); + TESTCASE( s[0] == '\0' ); + TESTCASE( s[1] == 'x' ); + TESTCASE( strcpy( s, abcde ) == s ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strcpy_s.c b/rocklibc/src/string/strcpy_s.c new file mode 100644 index 0000000..4c89f82 --- /dev/null +++ b/rocklibc/src/string/strcpy_s.c @@ -0,0 +1,89 @@ +/* strcpy_s( char *, rsize_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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t strcpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 ) +{ + char * dest = s1; + const char * src = s2; + + if ( s1 != NULL && s2 != NULL && s1max <= RSIZE_MAX && s1max != 0 ) + { + while ( s1max-- ) + { + if ( dest == s2 || src == s1 ) + { + goto runtime_constraint_violation; + } + + if ( ( *dest++ = *src++ ) == '\0' ) + { + return 0; + } + } + } + +runtime_constraint_violation: + + if ( s1 != NULL && s1max > 0 && s1max <= RSIZE_MAX ) + { + s1[0] = '\0'; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "xxxxx"; + set_constraint_handler_s( test_handler ); + + TESTCASE( strcpy_s( s, 6, "" ) == 0 ); + TESTCASE( s[0] == '\0' ); + TESTCASE( s[1] == 'x' ); + TESTCASE( strcpy_s( s, 6, abcde ) == 0 ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + + /* Overrun. */ + TESTCASE( strcpy_s( s, 6, "abcdef" ) != 0 ); + + /* Overlapping. */ + TESTCASE( strcpy_s( s, 3, s + 2 ) != 0 ); + TESTCASE( strcpy_s( s + 2, 3, s ) != 0 ); + + TESTCASE( HANDLER_CALLS == 3 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strcspn.c b/rocklibc/src/string/strcspn.c new file mode 100644 index 0000000..4a28931 --- /dev/null +++ b/rocklibc/src/string/strcspn.c @@ -0,0 +1,54 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strcspn( abcde, "x" ) == 5 ); + TESTCASE( strcspn( abcde, "xyz" ) == 5 ); + TESTCASE( strcspn( abcde, "zyx" ) == 5 ); + TESTCASE( strcspn( abcdx, "x" ) == 4 ); + TESTCASE( strcspn( abcdx, "xyz" ) == 4 ); + TESTCASE( strcspn( abcdx, "zyx" ) == 4 ); + TESTCASE( strcspn( abcde, "a" ) == 0 ); + TESTCASE( strcspn( abcde, "abc" ) == 0 ); + TESTCASE( strcspn( abcde, "cba" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strerror.c b/rocklibc/src/string/strerror.c new file mode 100644 index 0000000..e35d450 --- /dev/null +++ b/rocklibc/src/string/strerror.c @@ -0,0 +1,41 @@ +/* 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 + +#ifndef REGTEST + +#include + +/* TODO: Doing this via a static array is not the way to do it. */ +char * strerror( int errnum ) +{ + if ( errnum >= _PDCLIB_ERRNO_MAX || errnum < 0 ) + { + return _PDCLIB_EUNKNOWN_TEXT; + } + else + { + return _PDCLIB_lc_messages->errno_texts[errnum]; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include + +int main( void ) +{ + TESTCASE( strerror( ERANGE ) != strerror( EDOM ) ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strerror_s.c b/rocklibc/src/string/strerror_s.c new file mode 100644 index 0000000..80adced --- /dev/null +++ b/rocklibc/src/string/strerror_s.c @@ -0,0 +1,69 @@ +/* strerror_s( char *, rsize_t, errno_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#ifndef REGTEST + +#include + +errno_t strerror_s( char * s, rsize_t maxsize, errno_t errnum ) +{ + size_t len = strerrorlen_s( errnum ); + + if ( s == NULL || maxsize > RSIZE_MAX || maxsize == 0 ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + if ( len < maxsize ) + { + strcpy( s, strerror( errnum ) ); + } + else + { + strncpy( s, strerror( errnum ), maxsize - 1 ); + + if ( maxsize > 3 ) + { + strcpy( &s[ maxsize - 4 ], "..." ); + } + else + { + s[ maxsize - 1 ] = '\0'; + } + } + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include +#include + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[14]; + TESTCASE( strerror_s( s, 14, _PDCLIB_ERRNO_MAX ) == 0 ); + TESTCASE( strcmp( s, "unknown error" ) == 0 ); + TESTCASE( strerror_s( s, 13, _PDCLIB_ERRNO_MAX ) == 0 ); + TESTCASE( strcmp( s, "unknown e..." ) == 0 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strerrorlen_s.c b/rocklibc/src/string/strerrorlen_s.c new file mode 100644 index 0000000..4188c02 --- /dev/null +++ b/rocklibc/src/string/strerrorlen_s.c @@ -0,0 +1,29 @@ +/* strerrorlen_s( errno_t error ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + +#ifndef REGTEST + +size_t strerrorlen_s( errno_t errnum ) +{ + return strlen( strerror( errnum ) ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strlen.c b/rocklibc/src/string/strlen.c new file mode 100644 index 0000000..b97582b --- /dev/null +++ b/rocklibc/src/string/strlen.c @@ -0,0 +1,36 @@ +/* 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 + +#ifndef REGTEST + +size_t strlen( const char * s ) +{ + size_t rc = 0; + + while ( s[rc] ) + { + ++rc; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strlen( abcde ) == 5 ); + TESTCASE( strlen( "" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strncat.c b/rocklibc/src/string/strncat.c new file mode 100644 index 0000000..c1bca7e --- /dev/null +++ b/rocklibc/src/string/strncat.c @@ -0,0 +1,64 @@ +/* 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 + +#ifndef REGTEST + +char * strncat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n ) +{ + char * rc = s1; + + while ( *s1 ) + { + ++s1; + } + + while ( n && ( *s1++ = *s2++ ) ) + { + --n; + } + + if ( n == 0 ) + { + *s1 = '\0'; + } + + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xx\0xxxxxx"; + TESTCASE( strncat( s, abcde, 10 ) == s ); + TESTCASE( s[2] == 'a' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( s[7] == '\0' ); + TESTCASE( s[8] == 'x' ); + s[0] = '\0'; + TESTCASE( strncat( s, abcdx, 10 ) == s ); + TESTCASE( s[4] == 'x' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strncat( s, "\0", 10 ) == s ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( strncat( s, abcde, 0 ) == s ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( strncat( s, abcde, 3 ) == s ); + TESTCASE( s[5] == 'a' ); + TESTCASE( s[7] == 'c' ); + TESTCASE( s[8] == '\0' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strncat_s.c b/rocklibc/src/string/strncat_s.c new file mode 100644 index 0000000..898e1f9 --- /dev/null +++ b/rocklibc/src/string/strncat_s.c @@ -0,0 +1,118 @@ +/* strncat_s( char *, rsize_t, const char *, rsize_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t strncat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n ) +{ + char * dest = s1; + const char * src = s2; + + if ( s1 != NULL && s2 != NULL && s1max <= RSIZE_MAX && n <= RSIZE_MAX && s1max != 0 ) + { + while ( *dest ) + { + if ( --s1max == 0 || dest++ == s2 ) + { + goto runtime_constraint_violation; + } + } + + do + { + if ( n-- == 0 ) + { + *dest = '\0'; + return 0; + } + + if ( s1max-- == 0 || dest == s2 || src == s1 ) + { + goto runtime_constraint_violation; + } + } while ( ( *dest++ = *src++ ) ); + + return 0; + } + +runtime_constraint_violation: + + if ( s1 != NULL && s1max > 0 && s1max <= RSIZE_MAX ) + { + s1[0] = '\0'; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "xx\0xxxxxx"; + set_constraint_handler_s( test_handler ); + + TESTCASE( strncat_s( s, 10, abcde, 10 ) == 0 ); + TESTCASE( s[2] == 'a' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( s[7] == '\0' ); + TESTCASE( s[8] == 'x' ); + s[0] = '\0'; + TESTCASE( strncat_s( s, 10, abcdx, 10 ) == 0 ); + TESTCASE( s[4] == 'x' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strncat_s( s, 10, "\0", 10 ) == 0 ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( strncat_s( s, 10, abcde, 0 ) == 0 ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( strncat_s( s, 10, abcde, 3 ) == 0 ); + TESTCASE( s[5] == 'a' ); + TESTCASE( s[7] == 'c' ); + TESTCASE( s[8] == '\0' ); + + TESTCASE( strncat_s( s, 9, "", 0 ) == 0 ); + TESTCASE( strncat_s( s, 8, "", 0 ) != 0 ); + TESTCASE( strncat_s( s, 8, "x", 0 ) != 0 ); + TESTCASE( strncat_s( s, 9, "x", 0 ) == 0 ); + TESTCASE( strncat_s( s, 10, "x", 1 ) == 0 ); + TESTCASE( s[8] == 'x' ); + TESTCASE( s[9] == '\0' ); + + /* Overlapping */ + TESTCASE( strcat_s( s, 7, s + 6 ) != 0 ); + s[3] = '\0'; + TESTCASE( strcat_s( s + 3, 4, s ) != 0 ); + + TESTCASE( HANDLER_CALLS == 4 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strncmp.c b/rocklibc/src/string/strncmp.c new file mode 100644 index 0000000..6b35763 --- /dev/null +++ b/rocklibc/src/string/strncmp.c @@ -0,0 +1,55 @@ +/* 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 + +#ifndef REGTEST + +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 ); + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char cmpabcde[] = "abcde\0f"; + char cmpabcd_[] = "abcde\xfc"; + char empty[] = ""; + char x[] = "x"; + TESTCASE( strncmp( abcde, cmpabcde, 5 ) == 0 ); + TESTCASE( strncmp( abcde, cmpabcde, 10 ) == 0 ); + TESTCASE( strncmp( abcde, abcdx, 5 ) < 0 ); + TESTCASE( strncmp( abcdx, abcde, 5 ) > 0 ); + TESTCASE( strncmp( empty, abcde, 5 ) < 0 ); + TESTCASE( strncmp( abcde, empty, 5 ) > 0 ); + TESTCASE( strncmp( abcde, abcdx, 4 ) == 0 ); + TESTCASE( strncmp( abcde, x, 0 ) == 0 ); + TESTCASE( strncmp( abcde, x, 1 ) < 0 ); + TESTCASE( strncmp( abcde, cmpabcd_, 10 ) < 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strncpy.c b/rocklibc/src/string/strncpy.c new file mode 100644 index 0000000..c69703c --- /dev/null +++ b/rocklibc/src/string/strncpy.c @@ -0,0 +1,59 @@ +/* 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 + +#ifndef REGTEST + +char * strncpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxx"; + TESTCASE( strncpy( s, "", 1 ) == s ); + TESTCASE( s[0] == '\0' ); + TESTCASE( s[1] == 'x' ); + TESTCASE( strncpy( s, abcde, 6 ) == s ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'x' ); + TESTCASE( strncpy( s, abcde, 7 ) == s ); + TESTCASE( s[6] == '\0' ); + TESTCASE( strncpy( s, "xxxx", 3 ) == s ); + TESTCASE( s[0] == 'x' ); + TESTCASE( s[2] == 'x' ); + TESTCASE( s[3] == 'd' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strncpy_s.c b/rocklibc/src/string/strncpy_s.c new file mode 100644 index 0000000..f9dc1ca --- /dev/null +++ b/rocklibc/src/string/strncpy_s.c @@ -0,0 +1,95 @@ +/* strncpy_s( char *, rsize_t, const char *, rsize_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t strncpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n ) +{ + char * dest = s1; + const char * src = s2; + + if ( s1 != NULL && s2 != NULL && s1max <= RSIZE_MAX && n <= RSIZE_MAX && s1max != 0 ) + { + while ( s1max-- ) + { + if ( dest == s2 || src == s1 ) + { + goto runtime_constraint_violation; + } + + if ( n-- == 0 || ( *dest++ = *src++ ) == '\0' ) + { + return 0; + } + } + } + +runtime_constraint_violation: + + if ( s1 != NULL && s1max > 0 && s1max <= RSIZE_MAX ) + { + s1[0] = '\0'; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + +static int HANDLER_CALLS = 0; + +static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ) +{ + ++HANDLER_CALLS; +} + +#endif + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "xxxxxxx"; + set_constraint_handler_s( test_handler ); + + TESTCASE( strncpy_s( s, 8, "", 1 ) == 0 ); + TESTCASE( s[0] == '\0' ); + TESTCASE( s[1] == 'x' ); + TESTCASE( strncpy_s( s, 8, abcde, 6 ) == 0 ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'x' ); + TESTCASE( strncpy_s( s, 8, abcde, 7 ) == 0 ); + /* Different from strncpy()! */ + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'x' ); + TESTCASE( strncpy_s( s, 8, "xxxx", 3 ) == 0 ); + TESTCASE( s[0] == 'x' ); + TESTCASE( s[2] == 'x' ); + TESTCASE( s[3] == 'd' ); + + /* Overrun. */ + TESTCASE( strncpy_s( s, 8, "abcdefgh", 9 ) != 0 ); + TESTCASE( strncpy_s( s, 8, "abcdefgh", 9 ) != 0 ); + + TESTCASE( HANDLER_CALLS == 2 ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strpbrk.c b/rocklibc/src/string/strpbrk.c new file mode 100644 index 0000000..f68e2e6 --- /dev/null +++ b/rocklibc/src/string/strpbrk.c @@ -0,0 +1,53 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strpbrk( abcde, "x" ) == NULL ); + TESTCASE( strpbrk( abcde, "xyz" ) == NULL ); + TESTCASE( strpbrk( abcdx, "x" ) == &abcdx[4] ); + TESTCASE( strpbrk( abcdx, "xyz" ) == &abcdx[4] ); + TESTCASE( strpbrk( abcdx, "zyx" ) == &abcdx[4] ); + TESTCASE( strpbrk( abcde, "a" ) == &abcde[0] ); + TESTCASE( strpbrk( abcde, "abc" ) == &abcde[0] ); + TESTCASE( strpbrk( abcde, "cba" ) == &abcde[0] ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strrchr.c b/rocklibc/src/string/strrchr.c new file mode 100644 index 0000000..5314d70 --- /dev/null +++ b/rocklibc/src/string/strrchr.c @@ -0,0 +1,47 @@ +/* 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 + +#ifndef REGTEST + +char * strrchr( const char * s, int c ) +{ + size_t i = 0; + + while ( s[i++] ) + { + /* EMPTY */ + } + + do + { + if ( s[--i] == ( char ) c ) + { + return ( char * ) s + i; + } + } while ( i ); + + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char abccd[] = "abccd"; + TESTCASE( strrchr( abcde, '\0' ) == &abcde[5] ); + TESTCASE( strrchr( abcde, 'e' ) == &abcde[4] ); + TESTCASE( strrchr( abcde, 'a' ) == &abcde[0] ); + TESTCASE( strrchr( abccd, 'c' ) == &abccd[3] ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strspn.c b/rocklibc/src/string/strspn.c new file mode 100644 index 0000000..f5fec24 --- /dev/null +++ b/rocklibc/src/string/strspn.c @@ -0,0 +1,55 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strspn( abcde, "abc" ) == 3 ); + TESTCASE( strspn( abcde, "b" ) == 0 ); + TESTCASE( strspn( abcde, abcde ) == 5 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strstr.c b/rocklibc/src/string/strstr.c new file mode 100644 index 0000000..1da7417 --- /dev/null +++ b/rocklibc/src/string/strstr.c @@ -0,0 +1,56 @@ +/* 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 + +#ifndef REGTEST + +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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "abcabcabcdabcde"; + TESTCASE( strstr( s, "x" ) == NULL ); + TESTCASE( strstr( s, "xyz" ) == NULL ); + TESTCASE( strstr( s, "a" ) == &s[0] ); + TESTCASE( strstr( s, "abc" ) == &s[0] ); + TESTCASE( strstr( s, "abcd" ) == &s[6] ); + TESTCASE( strstr( s, "abcde" ) == &s[10] ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strtok.c b/rocklibc/src/string/strtok.c new file mode 100644 index 0000000..b405100 --- /dev/null +++ b/rocklibc/src/string/strtok.c @@ -0,0 +1,64 @@ +/* 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. +*/ + +#ifndef REGTEST +#define __STDC_WANT_LIB_EXT1__ 1 +#endif + +#include + +#ifndef REGTEST + +char * strtok( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ) +{ + static char * tmp = NULL; + static rsize_t max; + + if ( s1 != NULL ) + { + /* new string */ + tmp = s1; + max = strlen( tmp ); + } + + return _PDCLIB_strtok( s1, &max, s2, &tmp ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "_a_bc__d_"; + TESTCASE( strtok( s, "_" ) == &s[1] ); + TESTCASE( s[1] == 'a' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == &s[3] ); + TESTCASE( s[3] == 'b' ); + TESTCASE( s[4] == 'c' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == &s[7] ); + TESTCASE( s[6] == '_' ); + TESTCASE( s[7] == 'd' ); + TESTCASE( s[8] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == NULL ); + strcpy( s, "ab_cd" ); + TESTCASE( strtok( s, "_" ) == &s[0] ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[1] == 'b' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == &s[3] ); + TESTCASE( s[3] == 'c' ); + TESTCASE( s[4] == 'd' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == NULL ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strtok_s.c b/rocklibc/src/string/strtok_s.c new file mode 100644 index 0000000..e9fd9f4 --- /dev/null +++ b/rocklibc/src/string/strtok_s.c @@ -0,0 +1,72 @@ +/* strtok_s( char *, rsize_t *, const char *, char ** ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + +#ifndef REGTEST + +char * strtok_s( char * _PDCLIB_restrict s1, rsize_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr ) +{ + return _PDCLIB_strtok( s1, s1max, s2, ptr ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ ) + char s[] = "_a_bc__d_"; + char str1[] = "?a???b,,,#c"; + char str2[] = "\t \t"; + rsize_t max = sizeof( s ); + rsize_t max1 = sizeof( str1 ); + rsize_t max2 = sizeof( str2 ); + char * p; + char * ptr1; + char * ptr2; + + TESTCASE( _PDCLIB_strtok( s, &max, "_", &p ) == &s[1] ); + TESTCASE( s[1] == 'a' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[3] ); + TESTCASE( s[3] == 'b' ); + TESTCASE( s[4] == 'c' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[7] ); + TESTCASE( s[6] == '_' ); + TESTCASE( s[7] == 'd' ); + TESTCASE( s[8] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == NULL ); + strcpy( s, "ab_cd" ); + max = strlen( s ); + TESTCASE( _PDCLIB_strtok( s, &max, "_", &p ) == &s[0] ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[1] == 'b' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[3] ); + TESTCASE( s[3] == 'c' ); + TESTCASE( s[4] == 'd' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == NULL ); + + TESTCASE( _PDCLIB_strtok( str1, &max1, "?", &ptr1 ) == &str1[1] ); + TESTCASE( _PDCLIB_strtok( NULL, &max1, ",", &ptr1 ) == &str1[3] ); + TESTCASE( _PDCLIB_strtok( str2, &max2, " \t", &ptr2 ) == NULL ); + TESTCASE( _PDCLIB_strtok( NULL, &max1, "#,", &ptr1 ) == &str1[10] ); + TESTCASE( _PDCLIB_strtok( NULL, &max1, "?", &ptr1 ) == NULL ); +#else + /* Most libraries do not implement this function. */ + TESTCASE( NO_TESTDRIVER ); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/string/strxfrm.c b/rocklibc/src/string/strxfrm.c new file mode 100644 index 0000000..ac380e2 --- /dev/null +++ b/rocklibc/src/string/strxfrm.c @@ -0,0 +1,54 @@ +/* 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 + +#ifndef REGTEST + +#include + +size_t strxfrm( char * _PDCLIB_restrict s1, const char * _PDCLIB_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: This should access _PDCLIB_lc_collate. */ + while ( n-- && ( *s1++ = ( unsigned char )*s2++ ) ) + { + /* EMPTY */ + } + } + + return len; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxxxxxx"; + TESTCASE( strxfrm( NULL, "123456789012", 0 ) == 12 ); + TESTCASE( strxfrm( s, "123456789012", 12 ) == 12 ); + /* + The following test case is true in *this* implementation, but doesn't have to. + TESTCASE( s[0] == 'x' ); + */ + TESTCASE( strxfrm( s, "1234567890", 11 ) == 10 ); + TESTCASE( s[0] == '1' ); + TESTCASE( s[9] == '0' ); + TESTCASE( s[10] == '\0' ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/asctime.c b/rocklibc/src/time/asctime.c new file mode 100644 index 0000000..b591d57 --- /dev/null +++ b/rocklibc/src/time/asctime.c @@ -0,0 +1,47 @@ +/* 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 + +#ifndef REGTEST + +#include + +char * asctime( const struct tm * timeptr ) +{ + static char rc[26]; + sprintf( rc, "%s %s%3d %.2d:%.2d:%.2d %d\n", + _PDCLIB_lc_time_C.day_name_abbr[ timeptr->tm_wday ], + _PDCLIB_lc_time_C.month_name_abbr[ timeptr->tm_mon ], + timeptr->tm_mday, + timeptr->tm_hour, + timeptr->tm_min, + timeptr->tm_sec, + timeptr->tm_year + 1900 ); + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + struct tm time; + MKTIME( time, 52, 3, 1, 16, 8, 73, 0, 0 ); + TESTCASE( strcmp( asctime( &time ), "Sun Sep 16 01:03:52 1973\n" ) == 0 ); + MKTIME( time, 0, 0, 0, 1, 0, 0, 0, 0 ); + TESTCASE( strcmp( asctime( &time ), "Sun Jan 1 00:00:00 1900\n" ) == 0 ); + MKTIME( time, 60, 59, 23, 31, 11, 8099, 6, 0 ); + TESTCASE( strcmp( asctime( &time ), "Sat Dec 31 23:59:60 9999\n" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/asctime_s.c b/rocklibc/src/time/asctime_s.c new file mode 100644 index 0000000..4d71d07 --- /dev/null +++ b/rocklibc/src/time/asctime_s.c @@ -0,0 +1,63 @@ +/* asctime_s( char *, rsize_t, 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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +#include + +errno_t asctime_s( char * s, rsize_t maxsize, const struct tm * timeptr ) +{ + if ( s == NULL || timeptr == NULL || maxsize < 26 || maxsize > RSIZE_MAX || timeptr->tm_year < -1900 || timeptr->tm_year > 8099 /* TODO: || not normalized */ ) + { + if ( s != NULL && maxsize > 0 && maxsize <= RSIZE_MAX ) + { + s[0] = '\0'; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + sprintf( s, "%s %s %2d %.2d:%.2d:%.2d %4d\n", + _PDCLIB_lc_time_C.day_name_abbr[ timeptr->tm_wday ], + _PDCLIB_lc_time_C.month_name_abbr[ timeptr->tm_mon ], + timeptr->tm_mday, + timeptr->tm_hour, + timeptr->tm_min, + timeptr->tm_sec, + timeptr->tm_year + 1900 ); + + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + /* TODO: Constraint handling */ + + struct tm time; + MKTIME( time, 52, 3, 1, 16, 8, 73, 0, 0 ); + TESTCASE( strcmp( asctime( &time ), "Sun Sep 16 01:03:52 1973\n" ) == 0 ); + MKTIME( time, 0, 0, 0, 1, 0, 0, 0, 0 ); + TESTCASE( strcmp( asctime( &time ), "Sun Jan 1 00:00:00 1900\n" ) == 0 ); + MKTIME( time, 60, 59, 23, 31, 11, 8099, 6, 0 ); + TESTCASE( strcmp( asctime( &time ), "Sat Dec 31 23:59:60 9999\n" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/clock.c b/rocklibc/src/time/clock.c new file mode 100644 index 0000000..adb7d2a --- /dev/null +++ b/rocklibc/src/time/clock.c @@ -0,0 +1,37 @@ +/* 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 + +#ifndef REGTEST + +#include "sys/times.h" + +clock_t clock( void ) +{ + struct tms buf; + + if ( times( &buf ) != ( clock_t )-1 ) + { + return buf.tms_utime + buf.tms_stime; + } + + return -1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/ctime.c b/rocklibc/src/time/ctime.c new file mode 100644 index 0000000..9073e47 --- /dev/null +++ b/rocklibc/src/time/ctime.c @@ -0,0 +1,44 @@ +/* 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 + +#ifndef REGTEST + +char * ctime( const time_t * timer ) +{ + /* Section 4.12.3.2 of X3.159-1989 requires that + The ctime function converts the calendar time pointed to by timer + to local time in the form of a string. It is equivalent to + asctime(localtime(timer)) + */ + struct tm * tmp = localtime( timer ); + return tmp ? asctime( tmp ) : NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + /* TODO: System Clock DST */ + time_t t; + + t = -2147483648l; + TESTCASE( strcmp( ctime( &t ), "Fri Dec 13 21:45:52 1901\n" ) == 0 ); + + t = 2147483647l; + TESTCASE( strcmp( ctime( &t ), "Tue Jan 19 04:14:07 2038\n" ) == 0 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/ctime_s.c b/rocklibc/src/time/ctime_s.c new file mode 100644 index 0000000..95e4db6 --- /dev/null +++ b/rocklibc/src/time/ctime_s.c @@ -0,0 +1,61 @@ +/* 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. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +errno_t ctime_s( char * s, rsize_t maxsize, const time_t * timer ) +{ + struct tm tm; + + if ( s == NULL || timer == NULL || maxsize < 26 || maxsize > RSIZE_MAX ) + { + if ( s != NULL && maxsize > 0 && maxsize <= RSIZE_MAX ) + { + s[0] = '\0'; + } + + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return _PDCLIB_EINVAL; + } + + return asctime_s( s, maxsize, localtime_s( timer, &tm ) ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ +#ifndef REGTEST + /* TODO: System Clock DST */ + time_t t; + char s[27]; + + /* TODO: Constraint handling */ + + t = -2147483648l; + TESTCASE( ctime_s( s, 27, &t ) == 0 ); + TESTCASE( strcmp( s, "Fri Dec 13 21:45:52 1901\n" ) == 0 ); + + t = 2147483647l; + TESTCASE( ctime_s( s, 27, &t ) == 0 ); + TESTCASE( strcmp( s, "Tue Jan 19 04:14:07 2038\n" ) == 0 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/difftime.c b/rocklibc/src/time/difftime.c new file mode 100644 index 0000000..dd2a11d --- /dev/null +++ b/rocklibc/src/time/difftime.c @@ -0,0 +1,70 @@ +/* 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 REGTEST + +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( _PDCLIB_uintmax_t ) ) + { + _PDCLIB_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 + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/gmtime.c b/rocklibc/src/time/gmtime.c new file mode 100644 index 0000000..159f455 --- /dev/null +++ b/rocklibc/src/time/gmtime.c @@ -0,0 +1,55 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +struct tm * gmtime( const time_t * timer ) +{ + _PDCLIB_gmtcheck(); + return _PDCLIB_gmtsub( &_PDCLIB_gmtmem, timer, 0, &_PDCLIB_tm ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + time_t t; + struct tm * time; + + t = -2147483648l; + time = gmtime( &t ); + TESTCASE( time->tm_sec == 52 ); + TESTCASE( time->tm_min == 45 ); + TESTCASE( time->tm_hour == 20 ); + TESTCASE( time->tm_mday == 13 ); + TESTCASE( time->tm_mon == 11 ); + TESTCASE( time->tm_year == 1 ); + TESTCASE( time->tm_wday == 5 ); + TESTCASE( time->tm_yday == 346 ); + + t = 2147483647l; + time = gmtime( &t ); + TESTCASE( time->tm_sec == 7 ); + TESTCASE( time->tm_min == 14 ); + TESTCASE( time->tm_hour == 3 ); + TESTCASE( time->tm_mday == 19 ); + TESTCASE( time->tm_mon == 0 ); + TESTCASE( time->tm_year == 138 ); + TESTCASE( time->tm_wday == 2 ); + TESTCASE( time->tm_yday == 18 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/gmtime_s.c b/rocklibc/src/time/gmtime_s.c new file mode 100644 index 0000000..698477d --- /dev/null +++ b/rocklibc/src/time/gmtime_s.c @@ -0,0 +1,68 @@ +/* gmtime_s( const time_t *, struct tm * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +struct tm * gmtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result ) +{ + if ( timer == NULL || result == NULL ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return NULL; + } + + _PDCLIB_gmtcheck(); + return _PDCLIB_gmtsub( &_PDCLIB_gmtmem, timer, 0, result ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + time_t t; + struct tm time; + + /* TODO: Constraint handling */ + + t = -2147483648l; + TESTCASE( gmtime_s( &t, &time ) != NULL ); + TESTCASE( time.tm_sec == 52 ); + TESTCASE( time.tm_min == 45 ); + TESTCASE( time.tm_hour == 20 ); + TESTCASE( time.tm_mday == 13 ); + TESTCASE( time.tm_mon == 11 ); + TESTCASE( time.tm_year == 1 ); + TESTCASE( time.tm_wday == 5 ); + TESTCASE( time.tm_yday == 346 ); + + t = 2147483647l; + TESTCASE( gmtime_s( &t, &time ) != NULL ); + TESTCASE( time.tm_sec == 7 ); + TESTCASE( time.tm_min == 14 ); + TESTCASE( time.tm_hour == 3 ); + TESTCASE( time.tm_mday == 19 ); + TESTCASE( time.tm_mon == 0 ); + TESTCASE( time.tm_year == 138 ); + TESTCASE( time.tm_wday == 2 ); + TESTCASE( time.tm_yday == 18 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/localtime.c b/rocklibc/src/time/localtime.c new file mode 100644 index 0000000..02740d2 --- /dev/null +++ b/rocklibc/src/time/localtime.c @@ -0,0 +1,56 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +struct tm * localtime( const time_t * timer ) +{ + return _PDCLIB_localtime_tzset( timer, &_PDCLIB_tm, true ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + /* TODO: System Clock DST */ + + time_t t; + struct tm * time; + + t = -2147483648l; + time = localtime( &t ); + TESTCASE( time->tm_sec == 52 ); + TESTCASE( time->tm_min == 45 ); + TESTCASE( time->tm_hour == 21 ); + TESTCASE( time->tm_mday == 13 ); + TESTCASE( time->tm_mon == 11 ); + TESTCASE( time->tm_year == 1 ); + TESTCASE( time->tm_wday == 5 ); + TESTCASE( time->tm_yday == 346 ); + + t = 2147483647l; + time = localtime( &t ); + TESTCASE( time->tm_sec == 7 ); + TESTCASE( time->tm_min == 14 ); + TESTCASE( time->tm_hour == 4 ); + TESTCASE( time->tm_mday == 19 ); + TESTCASE( time->tm_mon == 0 ); + TESTCASE( time->tm_year == 138 ); + TESTCASE( time->tm_wday == 2 ); + TESTCASE( time->tm_yday == 18 ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/localtime_s.c b/rocklibc/src/time/localtime_s.c new file mode 100644 index 0000000..bc88150 --- /dev/null +++ b/rocklibc/src/time/localtime_s.c @@ -0,0 +1,67 @@ +/* localtime_s( const time_t *, struct tm * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +struct tm * localtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result ) +{ + if ( timer == NULL || result == NULL ) + { + _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) ); + return NULL; + } + + return _PDCLIB_localtime_tzset( timer, result, true ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + time_t t; + struct tm time; + + /* TODO: Constraint handling, System Clock DST */ + + t = -2147483648l; + TESTCASE( localtime_s( &t, &time ) != NULL ); + TESTCASE( time.tm_sec == 52 ); + TESTCASE( time.tm_min == 45 ); + TESTCASE( time.tm_hour == 21 ); + TESTCASE( time.tm_mday == 13 ); + TESTCASE( time.tm_mon == 11 ); + TESTCASE( time.tm_year == 1 ); + TESTCASE( time.tm_wday == 5 ); + TESTCASE( time.tm_yday == 346 ); + + t = 2147483647l; + TESTCASE( localtime_s( &t, &time ) != NULL ); + TESTCASE( time.tm_sec == 7 ); + TESTCASE( time.tm_min == 14 ); + TESTCASE( time.tm_hour == 4 ); + TESTCASE( time.tm_mday == 19 ); + TESTCASE( time.tm_mon == 0 ); + TESTCASE( time.tm_year == 138 ); + TESTCASE( time.tm_wday == 2 ); + TESTCASE( time.tm_yday == 18 ); +#endif + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/mktime.c b/rocklibc/src/time/mktime.c new file mode 100644 index 0000000..37a6c85 --- /dev/null +++ b/rocklibc/src/time/mktime.c @@ -0,0 +1,53 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_tzcode.h" + +#ifndef __STDC_NO_THREADS__ +#include +extern mtx_t _PDCLIB_time_mtx; +#endif + +time_t mktime( struct tm * timeptr ) +{ + time_t t; + _PDCLIB_LOCK( _PDCLIB_time_mtx ); + _PDCLIB_tzset_unlocked(); + t = _PDCLIB_mktime_tzname( &_PDCLIB_lclmem, timeptr, true ); + _PDCLIB_UNLOCK( _PDCLIB_time_mtx ); + return t; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include + +int main( void ) +{ + /* System Clock DST */ + struct tm time; + time_t t; + + MKTIME( time, 52, 45, 21, 13, 11, 1, 0, 0 ); + t = mktime( &time ); + TESTCASE( t == -2147483648l ); + + MKTIME( time, 7, 14, 4, 19, 0, 138, 0, 0 ); + t = mktime( &time ); + TESTCASE( t == 2147483647l ); + + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/strftime.c b/rocklibc/src/time/strftime.c new file mode 100644 index 0000000..6968907 --- /dev/null +++ b/rocklibc/src/time/strftime.c @@ -0,0 +1,1788 @@ +/* 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 + +#ifndef REGTEST + +/* 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 * _PDCLIB_restrict s, size_t maxsize, const char * _PDCLIB_restrict format, const struct tm * _PDCLIB_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; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +/* Test data generated by reference mktime() / strftime(), listing: + * tm_year + * tm_wday + * tm_yday + * '%U' result + * '%V' result + * '%W' result +*/ +int data[1020][6] = +{ + { 70, 4, 0, 0, 1, 0 }, + { 70, 5, 1, 0, 1, 0 }, + { 70, 6, 2, 0, 1, 0 }, + { 70, 0, 3, 1, 1, 0 }, + { 70, 1, 4, 1, 2, 1 }, + { 70, 2, 5, 1, 2, 1 }, + { 70, 3, 6, 1, 2, 1 }, + { 70, 4, 357, 51, 52, 51 }, + { 70, 5, 358, 51, 52, 51 }, + { 70, 6, 359, 51, 52, 51 }, + { 70, 0, 360, 52, 52, 51 }, + { 70, 1, 361, 52, 53, 52 }, + { 70, 2, 362, 52, 53, 52 }, + { 70, 3, 363, 52, 53, 52 }, + { 70, 4, 364, 52, 53, 52 }, + { 71, 5, 0, 0, 53, 0 }, + { 71, 6, 1, 0, 53, 0 }, + { 71, 0, 2, 1, 53, 0 }, + { 71, 1, 3, 1, 1, 1 }, + { 71, 2, 4, 1, 1, 1 }, + { 71, 3, 5, 1, 1, 1 }, + { 71, 4, 6, 1, 1, 1 }, + { 71, 5, 357, 51, 51, 51 }, + { 71, 6, 358, 51, 51, 51 }, + { 71, 0, 359, 52, 51, 51 }, + { 71, 1, 360, 52, 52, 52 }, + { 71, 2, 361, 52, 52, 52 }, + { 71, 3, 362, 52, 52, 52 }, + { 71, 4, 363, 52, 52, 52 }, + { 71, 5, 364, 52, 52, 52 }, + { 72, 6, 0, 0, 52, 0 }, + { 72, 0, 1, 1, 52, 0 }, + { 72, 1, 2, 1, 1, 1 }, + { 72, 2, 3, 1, 1, 1 }, + { 72, 3, 4, 1, 1, 1 }, + { 72, 4, 5, 1, 1, 1 }, + { 72, 5, 6, 1, 1, 1 }, + { 72, 0, 358, 52, 51, 51 }, + { 72, 1, 359, 52, 52, 52 }, + { 72, 2, 360, 52, 52, 52 }, + { 72, 3, 361, 52, 52, 52 }, + { 72, 4, 362, 52, 52, 52 }, + { 72, 5, 363, 52, 52, 52 }, + { 72, 6, 364, 52, 52, 52 }, + { 72, 0, 365, 53, 52, 52 }, + { 73, 1, 0, 0, 1, 1 }, + { 73, 2, 1, 0, 1, 1 }, + { 73, 3, 2, 0, 1, 1 }, + { 73, 4, 3, 0, 1, 1 }, + { 73, 5, 4, 0, 1, 1 }, + { 73, 6, 5, 0, 1, 1 }, + { 73, 0, 6, 1, 1, 1 }, + { 73, 1, 357, 51, 52, 52 }, + { 73, 2, 358, 51, 52, 52 }, + { 73, 3, 359, 51, 52, 52 }, + { 73, 4, 360, 51, 52, 52 }, + { 73, 5, 361, 51, 52, 52 }, + { 73, 6, 362, 51, 52, 52 }, + { 73, 0, 363, 52, 52, 52 }, + { 73, 1, 364, 52, 1, 53 }, + { 74, 2, 0, 0, 1, 0 }, + { 74, 3, 1, 0, 1, 0 }, + { 74, 4, 2, 0, 1, 0 }, + { 74, 5, 3, 0, 1, 0 }, + { 74, 6, 4, 0, 1, 0 }, + { 74, 0, 5, 1, 1, 0 }, + { 74, 1, 6, 1, 2, 1 }, + { 74, 2, 357, 51, 52, 51 }, + { 74, 3, 358, 51, 52, 51 }, + { 74, 4, 359, 51, 52, 51 }, + { 74, 5, 360, 51, 52, 51 }, + { 74, 6, 361, 51, 52, 51 }, + { 74, 0, 362, 52, 52, 51 }, + { 74, 1, 363, 52, 1, 52 }, + { 74, 2, 364, 52, 1, 52 }, + { 75, 3, 0, 0, 1, 0 }, + { 75, 4, 1, 0, 1, 0 }, + { 75, 5, 2, 0, 1, 0 }, + { 75, 6, 3, 0, 1, 0 }, + { 75, 0, 4, 1, 1, 0 }, + { 75, 1, 5, 1, 2, 1 }, + { 75, 2, 6, 1, 2, 1 }, + { 75, 3, 357, 51, 52, 51 }, + { 75, 4, 358, 51, 52, 51 }, + { 75, 5, 359, 51, 52, 51 }, + { 75, 6, 360, 51, 52, 51 }, + { 75, 0, 361, 52, 52, 51 }, + { 75, 1, 362, 52, 1, 52 }, + { 75, 2, 363, 52, 1, 52 }, + { 75, 3, 364, 52, 1, 52 }, + { 76, 4, 0, 0, 1, 0 }, + { 76, 5, 1, 0, 1, 0 }, + { 76, 6, 2, 0, 1, 0 }, + { 76, 0, 3, 1, 1, 0 }, + { 76, 1, 4, 1, 2, 1 }, + { 76, 2, 5, 1, 2, 1 }, + { 76, 3, 6, 1, 2, 1 }, + { 76, 5, 358, 51, 52, 51 }, + { 76, 6, 359, 51, 52, 51 }, + { 76, 0, 360, 52, 52, 51 }, + { 76, 1, 361, 52, 53, 52 }, + { 76, 2, 362, 52, 53, 52 }, + { 76, 3, 363, 52, 53, 52 }, + { 76, 4, 364, 52, 53, 52 }, + { 76, 5, 365, 52, 53, 52 }, + { 77, 6, 0, 0, 53, 0 }, + { 77, 0, 1, 1, 53, 0 }, + { 77, 1, 2, 1, 1, 1 }, + { 77, 2, 3, 1, 1, 1 }, + { 77, 3, 4, 1, 1, 1 }, + { 77, 4, 5, 1, 1, 1 }, + { 77, 5, 6, 1, 1, 1 }, + { 77, 6, 357, 51, 51, 51 }, + { 77, 0, 358, 52, 51, 51 }, + { 77, 1, 359, 52, 52, 52 }, + { 77, 2, 360, 52, 52, 52 }, + { 77, 3, 361, 52, 52, 52 }, + { 77, 4, 362, 52, 52, 52 }, + { 77, 5, 363, 52, 52, 52 }, + { 77, 6, 364, 52, 52, 52 }, + { 78, 0, 0, 1, 52, 0 }, + { 78, 1, 1, 1, 1, 1 }, + { 78, 2, 2, 1, 1, 1 }, + { 78, 3, 3, 1, 1, 1 }, + { 78, 4, 4, 1, 1, 1 }, + { 78, 5, 5, 1, 1, 1 }, + { 78, 6, 6, 1, 1, 1 }, + { 78, 0, 357, 52, 51, 51 }, + { 78, 1, 358, 52, 52, 52 }, + { 78, 2, 359, 52, 52, 52 }, + { 78, 3, 360, 52, 52, 52 }, + { 78, 4, 361, 52, 52, 52 }, + { 78, 5, 362, 52, 52, 52 }, + { 78, 6, 363, 52, 52, 52 }, + { 78, 0, 364, 53, 52, 52 }, + { 79, 1, 0, 0, 1, 1 }, + { 79, 2, 1, 0, 1, 1 }, + { 79, 3, 2, 0, 1, 1 }, + { 79, 4, 3, 0, 1, 1 }, + { 79, 5, 4, 0, 1, 1 }, + { 79, 6, 5, 0, 1, 1 }, + { 79, 0, 6, 1, 1, 1 }, + { 79, 1, 357, 51, 52, 52 }, + { 79, 2, 358, 51, 52, 52 }, + { 79, 3, 359, 51, 52, 52 }, + { 79, 4, 360, 51, 52, 52 }, + { 79, 5, 361, 51, 52, 52 }, + { 79, 6, 362, 51, 52, 52 }, + { 79, 0, 363, 52, 52, 52 }, + { 79, 1, 364, 52, 1, 53 }, + { 80, 2, 0, 0, 1, 0 }, + { 80, 3, 1, 0, 1, 0 }, + { 80, 4, 2, 0, 1, 0 }, + { 80, 5, 3, 0, 1, 0 }, + { 80, 6, 4, 0, 1, 0 }, + { 80, 0, 5, 1, 1, 0 }, + { 80, 1, 6, 1, 2, 1 }, + { 80, 3, 358, 51, 52, 51 }, + { 80, 4, 359, 51, 52, 51 }, + { 80, 5, 360, 51, 52, 51 }, + { 80, 6, 361, 51, 52, 51 }, + { 80, 0, 362, 52, 52, 51 }, + { 80, 1, 363, 52, 1, 52 }, + { 80, 2, 364, 52, 1, 52 }, + { 80, 3, 365, 52, 1, 52 }, + { 81, 4, 0, 0, 1, 0 }, + { 81, 5, 1, 0, 1, 0 }, + { 81, 6, 2, 0, 1, 0 }, + { 81, 0, 3, 1, 1, 0 }, + { 81, 1, 4, 1, 2, 1 }, + { 81, 2, 5, 1, 2, 1 }, + { 81, 3, 6, 1, 2, 1 }, + { 81, 4, 357, 51, 52, 51 }, + { 81, 5, 358, 51, 52, 51 }, + { 81, 6, 359, 51, 52, 51 }, + { 81, 0, 360, 52, 52, 51 }, + { 81, 1, 361, 52, 53, 52 }, + { 81, 2, 362, 52, 53, 52 }, + { 81, 3, 363, 52, 53, 52 }, + { 81, 4, 364, 52, 53, 52 }, + { 82, 5, 0, 0, 53, 0 }, + { 82, 6, 1, 0, 53, 0 }, + { 82, 0, 2, 1, 53, 0 }, + { 82, 1, 3, 1, 1, 1 }, + { 82, 2, 4, 1, 1, 1 }, + { 82, 3, 5, 1, 1, 1 }, + { 82, 4, 6, 1, 1, 1 }, + { 82, 5, 357, 51, 51, 51 }, + { 82, 6, 358, 51, 51, 51 }, + { 82, 0, 359, 52, 51, 51 }, + { 82, 1, 360, 52, 52, 52 }, + { 82, 2, 361, 52, 52, 52 }, + { 82, 3, 362, 52, 52, 52 }, + { 82, 4, 363, 52, 52, 52 }, + { 82, 5, 364, 52, 52, 52 }, + { 83, 6, 0, 0, 52, 0 }, + { 83, 0, 1, 1, 52, 0 }, + { 83, 1, 2, 1, 1, 1 }, + { 83, 2, 3, 1, 1, 1 }, + { 83, 3, 4, 1, 1, 1 }, + { 83, 4, 5, 1, 1, 1 }, + { 83, 5, 6, 1, 1, 1 }, + { 83, 6, 357, 51, 51, 51 }, + { 83, 0, 358, 52, 51, 51 }, + { 83, 1, 359, 52, 52, 52 }, + { 83, 2, 360, 52, 52, 52 }, + { 83, 3, 361, 52, 52, 52 }, + { 83, 4, 362, 52, 52, 52 }, + { 83, 5, 363, 52, 52, 52 }, + { 83, 6, 364, 52, 52, 52 }, + { 84, 0, 0, 1, 52, 0 }, + { 84, 1, 1, 1, 1, 1 }, + { 84, 2, 2, 1, 1, 1 }, + { 84, 3, 3, 1, 1, 1 }, + { 84, 4, 4, 1, 1, 1 }, + { 84, 5, 5, 1, 1, 1 }, + { 84, 6, 6, 1, 1, 1 }, + { 84, 1, 358, 52, 52, 52 }, + { 84, 2, 359, 52, 52, 52 }, + { 84, 3, 360, 52, 52, 52 }, + { 84, 4, 361, 52, 52, 52 }, + { 84, 5, 362, 52, 52, 52 }, + { 84, 6, 363, 52, 52, 52 }, + { 84, 0, 364, 53, 52, 52 }, + { 84, 1, 365, 53, 1, 53 }, + { 85, 2, 0, 0, 1, 0 }, + { 85, 3, 1, 0, 1, 0 }, + { 85, 4, 2, 0, 1, 0 }, + { 85, 5, 3, 0, 1, 0 }, + { 85, 6, 4, 0, 1, 0 }, + { 85, 0, 5, 1, 1, 0 }, + { 85, 1, 6, 1, 2, 1 }, + { 85, 2, 357, 51, 52, 51 }, + { 85, 3, 358, 51, 52, 51 }, + { 85, 4, 359, 51, 52, 51 }, + { 85, 5, 360, 51, 52, 51 }, + { 85, 6, 361, 51, 52, 51 }, + { 85, 0, 362, 52, 52, 51 }, + { 85, 1, 363, 52, 1, 52 }, + { 85, 2, 364, 52, 1, 52 }, + { 86, 3, 0, 0, 1, 0 }, + { 86, 4, 1, 0, 1, 0 }, + { 86, 5, 2, 0, 1, 0 }, + { 86, 6, 3, 0, 1, 0 }, + { 86, 0, 4, 1, 1, 0 }, + { 86, 1, 5, 1, 2, 1 }, + { 86, 2, 6, 1, 2, 1 }, + { 86, 3, 357, 51, 52, 51 }, + { 86, 4, 358, 51, 52, 51 }, + { 86, 5, 359, 51, 52, 51 }, + { 86, 6, 360, 51, 52, 51 }, + { 86, 0, 361, 52, 52, 51 }, + { 86, 1, 362, 52, 1, 52 }, + { 86, 2, 363, 52, 1, 52 }, + { 86, 3, 364, 52, 1, 52 }, + { 87, 4, 0, 0, 1, 0 }, + { 87, 5, 1, 0, 1, 0 }, + { 87, 6, 2, 0, 1, 0 }, + { 87, 0, 3, 1, 1, 0 }, + { 87, 1, 4, 1, 2, 1 }, + { 87, 2, 5, 1, 2, 1 }, + { 87, 3, 6, 1, 2, 1 }, + { 87, 4, 357, 51, 52, 51 }, + { 87, 5, 358, 51, 52, 51 }, + { 87, 6, 359, 51, 52, 51 }, + { 87, 0, 360, 52, 52, 51 }, + { 87, 1, 361, 52, 53, 52 }, + { 87, 2, 362, 52, 53, 52 }, + { 87, 3, 363, 52, 53, 52 }, + { 87, 4, 364, 52, 53, 52 }, + { 88, 5, 0, 0, 53, 0 }, + { 88, 6, 1, 0, 53, 0 }, + { 88, 0, 2, 1, 53, 0 }, + { 88, 1, 3, 1, 1, 1 }, + { 88, 2, 4, 1, 1, 1 }, + { 88, 3, 5, 1, 1, 1 }, + { 88, 4, 6, 1, 1, 1 }, + { 88, 6, 358, 51, 51, 51 }, + { 88, 0, 359, 52, 51, 51 }, + { 88, 1, 360, 52, 52, 52 }, + { 88, 2, 361, 52, 52, 52 }, + { 88, 3, 362, 52, 52, 52 }, + { 88, 4, 363, 52, 52, 52 }, + { 88, 5, 364, 52, 52, 52 }, + { 88, 6, 365, 52, 52, 52 }, + { 89, 0, 0, 1, 52, 0 }, + { 89, 1, 1, 1, 1, 1 }, + { 89, 2, 2, 1, 1, 1 }, + { 89, 3, 3, 1, 1, 1 }, + { 89, 4, 4, 1, 1, 1 }, + { 89, 5, 5, 1, 1, 1 }, + { 89, 6, 6, 1, 1, 1 }, + { 89, 0, 357, 52, 51, 51 }, + { 89, 1, 358, 52, 52, 52 }, + { 89, 2, 359, 52, 52, 52 }, + { 89, 3, 360, 52, 52, 52 }, + { 89, 4, 361, 52, 52, 52 }, + { 89, 5, 362, 52, 52, 52 }, + { 89, 6, 363, 52, 52, 52 }, + { 89, 0, 364, 53, 52, 52 }, + { 90, 1, 0, 0, 1, 1 }, + { 90, 2, 1, 0, 1, 1 }, + { 90, 3, 2, 0, 1, 1 }, + { 90, 4, 3, 0, 1, 1 }, + { 90, 5, 4, 0, 1, 1 }, + { 90, 6, 5, 0, 1, 1 }, + { 90, 0, 6, 1, 1, 1 }, + { 90, 1, 357, 51, 52, 52 }, + { 90, 2, 358, 51, 52, 52 }, + { 90, 3, 359, 51, 52, 52 }, + { 90, 4, 360, 51, 52, 52 }, + { 90, 5, 361, 51, 52, 52 }, + { 90, 6, 362, 51, 52, 52 }, + { 90, 0, 363, 52, 52, 52 }, + { 90, 1, 364, 52, 1, 53 }, + { 91, 2, 0, 0, 1, 0 }, + { 91, 3, 1, 0, 1, 0 }, + { 91, 4, 2, 0, 1, 0 }, + { 91, 5, 3, 0, 1, 0 }, + { 91, 6, 4, 0, 1, 0 }, + { 91, 0, 5, 1, 1, 0 }, + { 91, 1, 6, 1, 2, 1 }, + { 91, 2, 357, 51, 52, 51 }, + { 91, 3, 358, 51, 52, 51 }, + { 91, 4, 359, 51, 52, 51 }, + { 91, 5, 360, 51, 52, 51 }, + { 91, 6, 361, 51, 52, 51 }, + { 91, 0, 362, 52, 52, 51 }, + { 91, 1, 363, 52, 1, 52 }, + { 91, 2, 364, 52, 1, 52 }, + { 92, 3, 0, 0, 1, 0 }, + { 92, 4, 1, 0, 1, 0 }, + { 92, 5, 2, 0, 1, 0 }, + { 92, 6, 3, 0, 1, 0 }, + { 92, 0, 4, 1, 1, 0 }, + { 92, 1, 5, 1, 2, 1 }, + { 92, 2, 6, 1, 2, 1 }, + { 92, 4, 358, 51, 52, 51 }, + { 92, 5, 359, 51, 52, 51 }, + { 92, 6, 360, 51, 52, 51 }, + { 92, 0, 361, 52, 52, 51 }, + { 92, 1, 362, 52, 53, 52 }, + { 92, 2, 363, 52, 53, 52 }, + { 92, 3, 364, 52, 53, 52 }, + { 92, 4, 365, 52, 53, 52 }, + { 93, 5, 0, 0, 53, 0 }, + { 93, 6, 1, 0, 53, 0 }, + { 93, 0, 2, 1, 53, 0 }, + { 93, 1, 3, 1, 1, 1 }, + { 93, 2, 4, 1, 1, 1 }, + { 93, 3, 5, 1, 1, 1 }, + { 93, 4, 6, 1, 1, 1 }, + { 93, 5, 357, 51, 51, 51 }, + { 93, 6, 358, 51, 51, 51 }, + { 93, 0, 359, 52, 51, 51 }, + { 93, 1, 360, 52, 52, 52 }, + { 93, 2, 361, 52, 52, 52 }, + { 93, 3, 362, 52, 52, 52 }, + { 93, 4, 363, 52, 52, 52 }, + { 93, 5, 364, 52, 52, 52 }, + { 94, 6, 0, 0, 52, 0 }, + { 94, 0, 1, 1, 52, 0 }, + { 94, 1, 2, 1, 1, 1 }, + { 94, 2, 3, 1, 1, 1 }, + { 94, 3, 4, 1, 1, 1 }, + { 94, 4, 5, 1, 1, 1 }, + { 94, 5, 6, 1, 1, 1 }, + { 94, 6, 357, 51, 51, 51 }, + { 94, 0, 358, 52, 51, 51 }, + { 94, 1, 359, 52, 52, 52 }, + { 94, 2, 360, 52, 52, 52 }, + { 94, 3, 361, 52, 52, 52 }, + { 94, 4, 362, 52, 52, 52 }, + { 94, 5, 363, 52, 52, 52 }, + { 94, 6, 364, 52, 52, 52 }, + { 95, 0, 0, 1, 52, 0 }, + { 95, 1, 1, 1, 1, 1 }, + { 95, 2, 2, 1, 1, 1 }, + { 95, 3, 3, 1, 1, 1 }, + { 95, 4, 4, 1, 1, 1 }, + { 95, 5, 5, 1, 1, 1 }, + { 95, 6, 6, 1, 1, 1 }, + { 95, 0, 357, 52, 51, 51 }, + { 95, 1, 358, 52, 52, 52 }, + { 95, 2, 359, 52, 52, 52 }, + { 95, 3, 360, 52, 52, 52 }, + { 95, 4, 361, 52, 52, 52 }, + { 95, 5, 362, 52, 52, 52 }, + { 95, 6, 363, 52, 52, 52 }, + { 95, 0, 364, 53, 52, 52 }, + { 96, 1, 0, 0, 1, 1 }, + { 96, 2, 1, 0, 1, 1 }, + { 96, 3, 2, 0, 1, 1 }, + { 96, 4, 3, 0, 1, 1 }, + { 96, 5, 4, 0, 1, 1 }, + { 96, 6, 5, 0, 1, 1 }, + { 96, 0, 6, 1, 1, 1 }, + { 96, 2, 358, 51, 52, 52 }, + { 96, 3, 359, 51, 52, 52 }, + { 96, 4, 360, 51, 52, 52 }, + { 96, 5, 361, 51, 52, 52 }, + { 96, 6, 362, 51, 52, 52 }, + { 96, 0, 363, 52, 52, 52 }, + { 96, 1, 364, 52, 1, 53 }, + { 96, 2, 365, 52, 1, 53 }, + { 97, 3, 0, 0, 1, 0 }, + { 97, 4, 1, 0, 1, 0 }, + { 97, 5, 2, 0, 1, 0 }, + { 97, 6, 3, 0, 1, 0 }, + { 97, 0, 4, 1, 1, 0 }, + { 97, 1, 5, 1, 2, 1 }, + { 97, 2, 6, 1, 2, 1 }, + { 97, 3, 357, 51, 52, 51 }, + { 97, 4, 358, 51, 52, 51 }, + { 97, 5, 359, 51, 52, 51 }, + { 97, 6, 360, 51, 52, 51 }, + { 97, 0, 361, 52, 52, 51 }, + { 97, 1, 362, 52, 1, 52 }, + { 97, 2, 363, 52, 1, 52 }, + { 97, 3, 364, 52, 1, 52 }, + { 98, 4, 0, 0, 1, 0 }, + { 98, 5, 1, 0, 1, 0 }, + { 98, 6, 2, 0, 1, 0 }, + { 98, 0, 3, 1, 1, 0 }, + { 98, 1, 4, 1, 2, 1 }, + { 98, 2, 5, 1, 2, 1 }, + { 98, 3, 6, 1, 2, 1 }, + { 98, 4, 357, 51, 52, 51 }, + { 98, 5, 358, 51, 52, 51 }, + { 98, 6, 359, 51, 52, 51 }, + { 98, 0, 360, 52, 52, 51 }, + { 98, 1, 361, 52, 53, 52 }, + { 98, 2, 362, 52, 53, 52 }, + { 98, 3, 363, 52, 53, 52 }, + { 98, 4, 364, 52, 53, 52 }, + { 99, 5, 0, 0, 53, 0 }, + { 99, 6, 1, 0, 53, 0 }, + { 99, 0, 2, 1, 53, 0 }, + { 99, 1, 3, 1, 1, 1 }, + { 99, 2, 4, 1, 1, 1 }, + { 99, 3, 5, 1, 1, 1 }, + { 99, 4, 6, 1, 1, 1 }, + { 99, 5, 357, 51, 51, 51 }, + { 99, 6, 358, 51, 51, 51 }, + { 99, 0, 359, 52, 51, 51 }, + { 99, 1, 360, 52, 52, 52 }, + { 99, 2, 361, 52, 52, 52 }, + { 99, 3, 362, 52, 52, 52 }, + { 99, 4, 363, 52, 52, 52 }, + { 99, 5, 364, 52, 52, 52 }, + { 100, 6, 0, 0, 52, 0 }, + { 100, 0, 1, 1, 52, 0 }, + { 100, 1, 2, 1, 1, 1 }, + { 100, 2, 3, 1, 1, 1 }, + { 100, 3, 4, 1, 1, 1 }, + { 100, 4, 5, 1, 1, 1 }, + { 100, 5, 6, 1, 1, 1 }, + { 100, 0, 358, 52, 51, 51 }, + { 100, 1, 359, 52, 52, 52 }, + { 100, 2, 360, 52, 52, 52 }, + { 100, 3, 361, 52, 52, 52 }, + { 100, 4, 362, 52, 52, 52 }, + { 100, 5, 363, 52, 52, 52 }, + { 100, 6, 364, 52, 52, 52 }, + { 100, 0, 365, 53, 52, 52 }, + { 101, 1, 0, 0, 1, 1 }, + { 101, 2, 1, 0, 1, 1 }, + { 101, 3, 2, 0, 1, 1 }, + { 101, 4, 3, 0, 1, 1 }, + { 101, 5, 4, 0, 1, 1 }, + { 101, 6, 5, 0, 1, 1 }, + { 101, 0, 6, 1, 1, 1 }, + { 101, 1, 357, 51, 52, 52 }, + { 101, 2, 358, 51, 52, 52 }, + { 101, 3, 359, 51, 52, 52 }, + { 101, 4, 360, 51, 52, 52 }, + { 101, 5, 361, 51, 52, 52 }, + { 101, 6, 362, 51, 52, 52 }, + { 101, 0, 363, 52, 52, 52 }, + { 101, 1, 364, 52, 1, 53 }, + { 102, 2, 0, 0, 1, 0 }, + { 102, 3, 1, 0, 1, 0 }, + { 102, 4, 2, 0, 1, 0 }, + { 102, 5, 3, 0, 1, 0 }, + { 102, 6, 4, 0, 1, 0 }, + { 102, 0, 5, 1, 1, 0 }, + { 102, 1, 6, 1, 2, 1 }, + { 102, 2, 357, 51, 52, 51 }, + { 102, 3, 358, 51, 52, 51 }, + { 102, 4, 359, 51, 52, 51 }, + { 102, 5, 360, 51, 52, 51 }, + { 102, 6, 361, 51, 52, 51 }, + { 102, 0, 362, 52, 52, 51 }, + { 102, 1, 363, 52, 1, 52 }, + { 102, 2, 364, 52, 1, 52 }, + { 103, 3, 0, 0, 1, 0 }, + { 103, 4, 1, 0, 1, 0 }, + { 103, 5, 2, 0, 1, 0 }, + { 103, 6, 3, 0, 1, 0 }, + { 103, 0, 4, 1, 1, 0 }, + { 103, 1, 5, 1, 2, 1 }, + { 103, 2, 6, 1, 2, 1 }, + { 103, 3, 357, 51, 52, 51 }, + { 103, 4, 358, 51, 52, 51 }, + { 103, 5, 359, 51, 52, 51 }, + { 103, 6, 360, 51, 52, 51 }, + { 103, 0, 361, 52, 52, 51 }, + { 103, 1, 362, 52, 1, 52 }, + { 103, 2, 363, 52, 1, 52 }, + { 103, 3, 364, 52, 1, 52 }, + { 104, 4, 0, 0, 1, 0 }, + { 104, 5, 1, 0, 1, 0 }, + { 104, 6, 2, 0, 1, 0 }, + { 104, 0, 3, 1, 1, 0 }, + { 104, 1, 4, 1, 2, 1 }, + { 104, 2, 5, 1, 2, 1 }, + { 104, 3, 6, 1, 2, 1 }, + { 104, 5, 358, 51, 52, 51 }, + { 104, 6, 359, 51, 52, 51 }, + { 104, 0, 360, 52, 52, 51 }, + { 104, 1, 361, 52, 53, 52 }, + { 104, 2, 362, 52, 53, 52 }, + { 104, 3, 363, 52, 53, 52 }, + { 104, 4, 364, 52, 53, 52 }, + { 104, 5, 365, 52, 53, 52 }, + { 105, 6, 0, 0, 53, 0 }, + { 105, 0, 1, 1, 53, 0 }, + { 105, 1, 2, 1, 1, 1 }, + { 105, 2, 3, 1, 1, 1 }, + { 105, 3, 4, 1, 1, 1 }, + { 105, 4, 5, 1, 1, 1 }, + { 105, 5, 6, 1, 1, 1 }, + { 105, 6, 357, 51, 51, 51 }, + { 105, 0, 358, 52, 51, 51 }, + { 105, 1, 359, 52, 52, 52 }, + { 105, 2, 360, 52, 52, 52 }, + { 105, 3, 361, 52, 52, 52 }, + { 105, 4, 362, 52, 52, 52 }, + { 105, 5, 363, 52, 52, 52 }, + { 105, 6, 364, 52, 52, 52 }, + { 106, 0, 0, 1, 52, 0 }, + { 106, 1, 1, 1, 1, 1 }, + { 106, 2, 2, 1, 1, 1 }, + { 106, 3, 3, 1, 1, 1 }, + { 106, 4, 4, 1, 1, 1 }, + { 106, 5, 5, 1, 1, 1 }, + { 106, 6, 6, 1, 1, 1 }, + { 106, 0, 357, 52, 51, 51 }, + { 106, 1, 358, 52, 52, 52 }, + { 106, 2, 359, 52, 52, 52 }, + { 106, 3, 360, 52, 52, 52 }, + { 106, 4, 361, 52, 52, 52 }, + { 106, 5, 362, 52, 52, 52 }, + { 106, 6, 363, 52, 52, 52 }, + { 106, 0, 364, 53, 52, 52 }, + { 107, 1, 0, 0, 1, 1 }, + { 107, 2, 1, 0, 1, 1 }, + { 107, 3, 2, 0, 1, 1 }, + { 107, 4, 3, 0, 1, 1 }, + { 107, 5, 4, 0, 1, 1 }, + { 107, 6, 5, 0, 1, 1 }, + { 107, 0, 6, 1, 1, 1 }, + { 107, 1, 357, 51, 52, 52 }, + { 107, 2, 358, 51, 52, 52 }, + { 107, 3, 359, 51, 52, 52 }, + { 107, 4, 360, 51, 52, 52 }, + { 107, 5, 361, 51, 52, 52 }, + { 107, 6, 362, 51, 52, 52 }, + { 107, 0, 363, 52, 52, 52 }, + { 107, 1, 364, 52, 1, 53 }, + { 108, 2, 0, 0, 1, 0 }, + { 108, 3, 1, 0, 1, 0 }, + { 108, 4, 2, 0, 1, 0 }, + { 108, 5, 3, 0, 1, 0 }, + { 108, 6, 4, 0, 1, 0 }, + { 108, 0, 5, 1, 1, 0 }, + { 108, 1, 6, 1, 2, 1 }, + { 108, 3, 358, 51, 52, 51 }, + { 108, 4, 359, 51, 52, 51 }, + { 108, 5, 360, 51, 52, 51 }, + { 108, 6, 361, 51, 52, 51 }, + { 108, 0, 362, 52, 52, 51 }, + { 108, 1, 363, 52, 1, 52 }, + { 108, 2, 364, 52, 1, 52 }, + { 108, 3, 365, 52, 1, 52 }, + { 109, 4, 0, 0, 1, 0 }, + { 109, 5, 1, 0, 1, 0 }, + { 109, 6, 2, 0, 1, 0 }, + { 109, 0, 3, 1, 1, 0 }, + { 109, 1, 4, 1, 2, 1 }, + { 109, 2, 5, 1, 2, 1 }, + { 109, 3, 6, 1, 2, 1 }, + { 109, 4, 357, 51, 52, 51 }, + { 109, 5, 358, 51, 52, 51 }, + { 109, 6, 359, 51, 52, 51 }, + { 109, 0, 360, 52, 52, 51 }, + { 109, 1, 361, 52, 53, 52 }, + { 109, 2, 362, 52, 53, 52 }, + { 109, 3, 363, 52, 53, 52 }, + { 109, 4, 364, 52, 53, 52 }, + { 110, 5, 0, 0, 53, 0 }, + { 110, 6, 1, 0, 53, 0 }, + { 110, 0, 2, 1, 53, 0 }, + { 110, 1, 3, 1, 1, 1 }, + { 110, 2, 4, 1, 1, 1 }, + { 110, 3, 5, 1, 1, 1 }, + { 110, 4, 6, 1, 1, 1 }, + { 110, 5, 357, 51, 51, 51 }, + { 110, 6, 358, 51, 51, 51 }, + { 110, 0, 359, 52, 51, 51 }, + { 110, 1, 360, 52, 52, 52 }, + { 110, 2, 361, 52, 52, 52 }, + { 110, 3, 362, 52, 52, 52 }, + { 110, 4, 363, 52, 52, 52 }, + { 110, 5, 364, 52, 52, 52 }, + { 111, 6, 0, 0, 52, 0 }, + { 111, 0, 1, 1, 52, 0 }, + { 111, 1, 2, 1, 1, 1 }, + { 111, 2, 3, 1, 1, 1 }, + { 111, 3, 4, 1, 1, 1 }, + { 111, 4, 5, 1, 1, 1 }, + { 111, 5, 6, 1, 1, 1 }, + { 111, 6, 357, 51, 51, 51 }, + { 111, 0, 358, 52, 51, 51 }, + { 111, 1, 359, 52, 52, 52 }, + { 111, 2, 360, 52, 52, 52 }, + { 111, 3, 361, 52, 52, 52 }, + { 111, 4, 362, 52, 52, 52 }, + { 111, 5, 363, 52, 52, 52 }, + { 111, 6, 364, 52, 52, 52 }, + { 112, 0, 0, 1, 52, 0 }, + { 112, 1, 1, 1, 1, 1 }, + { 112, 2, 2, 1, 1, 1 }, + { 112, 3, 3, 1, 1, 1 }, + { 112, 4, 4, 1, 1, 1 }, + { 112, 5, 5, 1, 1, 1 }, + { 112, 6, 6, 1, 1, 1 }, + { 112, 1, 358, 52, 52, 52 }, + { 112, 2, 359, 52, 52, 52 }, + { 112, 3, 360, 52, 52, 52 }, + { 112, 4, 361, 52, 52, 52 }, + { 112, 5, 362, 52, 52, 52 }, + { 112, 6, 363, 52, 52, 52 }, + { 112, 0, 364, 53, 52, 52 }, + { 112, 1, 365, 53, 1, 53 }, + { 113, 2, 0, 0, 1, 0 }, + { 113, 3, 1, 0, 1, 0 }, + { 113, 4, 2, 0, 1, 0 }, + { 113, 5, 3, 0, 1, 0 }, + { 113, 6, 4, 0, 1, 0 }, + { 113, 0, 5, 1, 1, 0 }, + { 113, 1, 6, 1, 2, 1 }, + { 113, 2, 357, 51, 52, 51 }, + { 113, 3, 358, 51, 52, 51 }, + { 113, 4, 359, 51, 52, 51 }, + { 113, 5, 360, 51, 52, 51 }, + { 113, 6, 361, 51, 52, 51 }, + { 113, 0, 362, 52, 52, 51 }, + { 113, 1, 363, 52, 1, 52 }, + { 113, 2, 364, 52, 1, 52 }, + { 114, 3, 0, 0, 1, 0 }, + { 114, 4, 1, 0, 1, 0 }, + { 114, 5, 2, 0, 1, 0 }, + { 114, 6, 3, 0, 1, 0 }, + { 114, 0, 4, 1, 1, 0 }, + { 114, 1, 5, 1, 2, 1 }, + { 114, 2, 6, 1, 2, 1 }, + { 114, 3, 357, 51, 52, 51 }, + { 114, 4, 358, 51, 52, 51 }, + { 114, 5, 359, 51, 52, 51 }, + { 114, 6, 360, 51, 52, 51 }, + { 114, 0, 361, 52, 52, 51 }, + { 114, 1, 362, 52, 1, 52 }, + { 114, 2, 363, 52, 1, 52 }, + { 114, 3, 364, 52, 1, 52 }, + { 115, 4, 0, 0, 1, 0 }, + { 115, 5, 1, 0, 1, 0 }, + { 115, 6, 2, 0, 1, 0 }, + { 115, 0, 3, 1, 1, 0 }, + { 115, 1, 4, 1, 2, 1 }, + { 115, 2, 5, 1, 2, 1 }, + { 115, 3, 6, 1, 2, 1 }, + { 115, 4, 357, 51, 52, 51 }, + { 115, 5, 358, 51, 52, 51 }, + { 115, 6, 359, 51, 52, 51 }, + { 115, 0, 360, 52, 52, 51 }, + { 115, 1, 361, 52, 53, 52 }, + { 115, 2, 362, 52, 53, 52 }, + { 115, 3, 363, 52, 53, 52 }, + { 115, 4, 364, 52, 53, 52 }, + { 116, 5, 0, 0, 53, 0 }, + { 116, 6, 1, 0, 53, 0 }, + { 116, 0, 2, 1, 53, 0 }, + { 116, 1, 3, 1, 1, 1 }, + { 116, 2, 4, 1, 1, 1 }, + { 116, 3, 5, 1, 1, 1 }, + { 116, 4, 6, 1, 1, 1 }, + { 116, 6, 358, 51, 51, 51 }, + { 116, 0, 359, 52, 51, 51 }, + { 116, 1, 360, 52, 52, 52 }, + { 116, 2, 361, 52, 52, 52 }, + { 116, 3, 362, 52, 52, 52 }, + { 116, 4, 363, 52, 52, 52 }, + { 116, 5, 364, 52, 52, 52 }, + { 116, 6, 365, 52, 52, 52 }, + { 117, 0, 0, 1, 52, 0 }, + { 117, 1, 1, 1, 1, 1 }, + { 117, 2, 2, 1, 1, 1 }, + { 117, 3, 3, 1, 1, 1 }, + { 117, 4, 4, 1, 1, 1 }, + { 117, 5, 5, 1, 1, 1 }, + { 117, 6, 6, 1, 1, 1 }, + { 117, 0, 357, 52, 51, 51 }, + { 117, 1, 358, 52, 52, 52 }, + { 117, 2, 359, 52, 52, 52 }, + { 117, 3, 360, 52, 52, 52 }, + { 117, 4, 361, 52, 52, 52 }, + { 117, 5, 362, 52, 52, 52 }, + { 117, 6, 363, 52, 52, 52 }, + { 117, 0, 364, 53, 52, 52 }, + { 118, 1, 0, 0, 1, 1 }, + { 118, 2, 1, 0, 1, 1 }, + { 118, 3, 2, 0, 1, 1 }, + { 118, 4, 3, 0, 1, 1 }, + { 118, 5, 4, 0, 1, 1 }, + { 118, 6, 5, 0, 1, 1 }, + { 118, 0, 6, 1, 1, 1 }, + { 118, 1, 357, 51, 52, 52 }, + { 118, 2, 358, 51, 52, 52 }, + { 118, 3, 359, 51, 52, 52 }, + { 118, 4, 360, 51, 52, 52 }, + { 118, 5, 361, 51, 52, 52 }, + { 118, 6, 362, 51, 52, 52 }, + { 118, 0, 363, 52, 52, 52 }, + { 118, 1, 364, 52, 1, 53 }, + { 119, 2, 0, 0, 1, 0 }, + { 119, 3, 1, 0, 1, 0 }, + { 119, 4, 2, 0, 1, 0 }, + { 119, 5, 3, 0, 1, 0 }, + { 119, 6, 4, 0, 1, 0 }, + { 119, 0, 5, 1, 1, 0 }, + { 119, 1, 6, 1, 2, 1 }, + { 119, 2, 357, 51, 52, 51 }, + { 119, 3, 358, 51, 52, 51 }, + { 119, 4, 359, 51, 52, 51 }, + { 119, 5, 360, 51, 52, 51 }, + { 119, 6, 361, 51, 52, 51 }, + { 119, 0, 362, 52, 52, 51 }, + { 119, 1, 363, 52, 1, 52 }, + { 119, 2, 364, 52, 1, 52 }, + { 120, 3, 0, 0, 1, 0 }, + { 120, 4, 1, 0, 1, 0 }, + { 120, 5, 2, 0, 1, 0 }, + { 120, 6, 3, 0, 1, 0 }, + { 120, 0, 4, 1, 1, 0 }, + { 120, 1, 5, 1, 2, 1 }, + { 120, 2, 6, 1, 2, 1 }, + { 120, 4, 358, 51, 52, 51 }, + { 120, 5, 359, 51, 52, 51 }, + { 120, 6, 360, 51, 52, 51 }, + { 120, 0, 361, 52, 52, 51 }, + { 120, 1, 362, 52, 53, 52 }, + { 120, 2, 363, 52, 53, 52 }, + { 120, 3, 364, 52, 53, 52 }, + { 120, 4, 365, 52, 53, 52 }, + { 121, 5, 0, 0, 53, 0 }, + { 121, 6, 1, 0, 53, 0 }, + { 121, 0, 2, 1, 53, 0 }, + { 121, 1, 3, 1, 1, 1 }, + { 121, 2, 4, 1, 1, 1 }, + { 121, 3, 5, 1, 1, 1 }, + { 121, 4, 6, 1, 1, 1 }, + { 121, 5, 357, 51, 51, 51 }, + { 121, 6, 358, 51, 51, 51 }, + { 121, 0, 359, 52, 51, 51 }, + { 121, 1, 360, 52, 52, 52 }, + { 121, 2, 361, 52, 52, 52 }, + { 121, 3, 362, 52, 52, 52 }, + { 121, 4, 363, 52, 52, 52 }, + { 121, 5, 364, 52, 52, 52 }, + { 122, 6, 0, 0, 52, 0 }, + { 122, 0, 1, 1, 52, 0 }, + { 122, 1, 2, 1, 1, 1 }, + { 122, 2, 3, 1, 1, 1 }, + { 122, 3, 4, 1, 1, 1 }, + { 122, 4, 5, 1, 1, 1 }, + { 122, 5, 6, 1, 1, 1 }, + { 122, 6, 357, 51, 51, 51 }, + { 122, 0, 358, 52, 51, 51 }, + { 122, 1, 359, 52, 52, 52 }, + { 122, 2, 360, 52, 52, 52 }, + { 122, 3, 361, 52, 52, 52 }, + { 122, 4, 362, 52, 52, 52 }, + { 122, 5, 363, 52, 52, 52 }, + { 122, 6, 364, 52, 52, 52 }, + { 123, 0, 0, 1, 52, 0 }, + { 123, 1, 1, 1, 1, 1 }, + { 123, 2, 2, 1, 1, 1 }, + { 123, 3, 3, 1, 1, 1 }, + { 123, 4, 4, 1, 1, 1 }, + { 123, 5, 5, 1, 1, 1 }, + { 123, 6, 6, 1, 1, 1 }, + { 123, 0, 357, 52, 51, 51 }, + { 123, 1, 358, 52, 52, 52 }, + { 123, 2, 359, 52, 52, 52 }, + { 123, 3, 360, 52, 52, 52 }, + { 123, 4, 361, 52, 52, 52 }, + { 123, 5, 362, 52, 52, 52 }, + { 123, 6, 363, 52, 52, 52 }, + { 123, 0, 364, 53, 52, 52 }, + { 124, 1, 0, 0, 1, 1 }, + { 124, 2, 1, 0, 1, 1 }, + { 124, 3, 2, 0, 1, 1 }, + { 124, 4, 3, 0, 1, 1 }, + { 124, 5, 4, 0, 1, 1 }, + { 124, 6, 5, 0, 1, 1 }, + { 124, 0, 6, 1, 1, 1 }, + { 124, 2, 358, 51, 52, 52 }, + { 124, 3, 359, 51, 52, 52 }, + { 124, 4, 360, 51, 52, 52 }, + { 124, 5, 361, 51, 52, 52 }, + { 124, 6, 362, 51, 52, 52 }, + { 124, 0, 363, 52, 52, 52 }, + { 124, 1, 364, 52, 1, 53 }, + { 124, 2, 365, 52, 1, 53 }, + { 125, 3, 0, 0, 1, 0 }, + { 125, 4, 1, 0, 1, 0 }, + { 125, 5, 2, 0, 1, 0 }, + { 125, 6, 3, 0, 1, 0 }, + { 125, 0, 4, 1, 1, 0 }, + { 125, 1, 5, 1, 2, 1 }, + { 125, 2, 6, 1, 2, 1 }, + { 125, 3, 357, 51, 52, 51 }, + { 125, 4, 358, 51, 52, 51 }, + { 125, 5, 359, 51, 52, 51 }, + { 125, 6, 360, 51, 52, 51 }, + { 125, 0, 361, 52, 52, 51 }, + { 125, 1, 362, 52, 1, 52 }, + { 125, 2, 363, 52, 1, 52 }, + { 125, 3, 364, 52, 1, 52 }, + { 126, 4, 0, 0, 1, 0 }, + { 126, 5, 1, 0, 1, 0 }, + { 126, 6, 2, 0, 1, 0 }, + { 126, 0, 3, 1, 1, 0 }, + { 126, 1, 4, 1, 2, 1 }, + { 126, 2, 5, 1, 2, 1 }, + { 126, 3, 6, 1, 2, 1 }, + { 126, 4, 357, 51, 52, 51 }, + { 126, 5, 358, 51, 52, 51 }, + { 126, 6, 359, 51, 52, 51 }, + { 126, 0, 360, 52, 52, 51 }, + { 126, 1, 361, 52, 53, 52 }, + { 126, 2, 362, 52, 53, 52 }, + { 126, 3, 363, 52, 53, 52 }, + { 126, 4, 364, 52, 53, 52 }, + { 127, 5, 0, 0, 53, 0 }, + { 127, 6, 1, 0, 53, 0 }, + { 127, 0, 2, 1, 53, 0 }, + { 127, 1, 3, 1, 1, 1 }, + { 127, 2, 4, 1, 1, 1 }, + { 127, 3, 5, 1, 1, 1 }, + { 127, 4, 6, 1, 1, 1 }, + { 127, 5, 357, 51, 51, 51 }, + { 127, 6, 358, 51, 51, 51 }, + { 127, 0, 359, 52, 51, 51 }, + { 127, 1, 360, 52, 52, 52 }, + { 127, 2, 361, 52, 52, 52 }, + { 127, 3, 362, 52, 52, 52 }, + { 127, 4, 363, 52, 52, 52 }, + { 127, 5, 364, 52, 52, 52 }, + { 128, 6, 0, 0, 52, 0 }, + { 128, 0, 1, 1, 52, 0 }, + { 128, 1, 2, 1, 1, 1 }, + { 128, 2, 3, 1, 1, 1 }, + { 128, 3, 4, 1, 1, 1 }, + { 128, 4, 5, 1, 1, 1 }, + { 128, 5, 6, 1, 1, 1 }, + { 128, 0, 358, 52, 51, 51 }, + { 128, 1, 359, 52, 52, 52 }, + { 128, 2, 360, 52, 52, 52 }, + { 128, 3, 361, 52, 52, 52 }, + { 128, 4, 362, 52, 52, 52 }, + { 128, 5, 363, 52, 52, 52 }, + { 128, 6, 364, 52, 52, 52 }, + { 128, 0, 365, 53, 52, 52 }, + { 129, 1, 0, 0, 1, 1 }, + { 129, 2, 1, 0, 1, 1 }, + { 129, 3, 2, 0, 1, 1 }, + { 129, 4, 3, 0, 1, 1 }, + { 129, 5, 4, 0, 1, 1 }, + { 129, 6, 5, 0, 1, 1 }, + { 129, 0, 6, 1, 1, 1 }, + { 129, 1, 357, 51, 52, 52 }, + { 129, 2, 358, 51, 52, 52 }, + { 129, 3, 359, 51, 52, 52 }, + { 129, 4, 360, 51, 52, 52 }, + { 129, 5, 361, 51, 52, 52 }, + { 129, 6, 362, 51, 52, 52 }, + { 129, 0, 363, 52, 52, 52 }, + { 129, 1, 364, 52, 1, 53 }, + { 130, 2, 0, 0, 1, 0 }, + { 130, 3, 1, 0, 1, 0 }, + { 130, 4, 2, 0, 1, 0 }, + { 130, 5, 3, 0, 1, 0 }, + { 130, 6, 4, 0, 1, 0 }, + { 130, 0, 5, 1, 1, 0 }, + { 130, 1, 6, 1, 2, 1 }, + { 130, 2, 357, 51, 52, 51 }, + { 130, 3, 358, 51, 52, 51 }, + { 130, 4, 359, 51, 52, 51 }, + { 130, 5, 360, 51, 52, 51 }, + { 130, 6, 361, 51, 52, 51 }, + { 130, 0, 362, 52, 52, 51 }, + { 130, 1, 363, 52, 1, 52 }, + { 130, 2, 364, 52, 1, 52 }, + { 131, 3, 0, 0, 1, 0 }, + { 131, 4, 1, 0, 1, 0 }, + { 131, 5, 2, 0, 1, 0 }, + { 131, 6, 3, 0, 1, 0 }, + { 131, 0, 4, 1, 1, 0 }, + { 131, 1, 5, 1, 2, 1 }, + { 131, 2, 6, 1, 2, 1 }, + { 131, 3, 357, 51, 52, 51 }, + { 131, 4, 358, 51, 52, 51 }, + { 131, 5, 359, 51, 52, 51 }, + { 131, 6, 360, 51, 52, 51 }, + { 131, 0, 361, 52, 52, 51 }, + { 131, 1, 362, 52, 1, 52 }, + { 131, 2, 363, 52, 1, 52 }, + { 131, 3, 364, 52, 1, 52 }, + { 132, 4, 0, 0, 1, 0 }, + { 132, 5, 1, 0, 1, 0 }, + { 132, 6, 2, 0, 1, 0 }, + { 132, 0, 3, 1, 1, 0 }, + { 132, 1, 4, 1, 2, 1 }, + { 132, 2, 5, 1, 2, 1 }, + { 132, 3, 6, 1, 2, 1 }, + { 132, 5, 358, 51, 52, 51 }, + { 132, 6, 359, 51, 52, 51 }, + { 132, 0, 360, 52, 52, 51 }, + { 132, 1, 361, 52, 53, 52 }, + { 132, 2, 362, 52, 53, 52 }, + { 132, 3, 363, 52, 53, 52 }, + { 132, 4, 364, 52, 53, 52 }, + { 132, 5, 365, 52, 53, 52 }, + { 133, 6, 0, 0, 53, 0 }, + { 133, 0, 1, 1, 53, 0 }, + { 133, 1, 2, 1, 1, 1 }, + { 133, 2, 3, 1, 1, 1 }, + { 133, 3, 4, 1, 1, 1 }, + { 133, 4, 5, 1, 1, 1 }, + { 133, 5, 6, 1, 1, 1 }, + { 133, 6, 357, 51, 51, 51 }, + { 133, 0, 358, 52, 51, 51 }, + { 133, 1, 359, 52, 52, 52 }, + { 133, 2, 360, 52, 52, 52 }, + { 133, 3, 361, 52, 52, 52 }, + { 133, 4, 362, 52, 52, 52 }, + { 133, 5, 363, 52, 52, 52 }, + { 133, 6, 364, 52, 52, 52 }, + { 134, 0, 0, 1, 52, 0 }, + { 134, 1, 1, 1, 1, 1 }, + { 134, 2, 2, 1, 1, 1 }, + { 134, 3, 3, 1, 1, 1 }, + { 134, 4, 4, 1, 1, 1 }, + { 134, 5, 5, 1, 1, 1 }, + { 134, 6, 6, 1, 1, 1 }, + { 134, 0, 357, 52, 51, 51 }, + { 134, 1, 358, 52, 52, 52 }, + { 134, 2, 359, 52, 52, 52 }, + { 134, 3, 360, 52, 52, 52 }, + { 134, 4, 361, 52, 52, 52 }, + { 134, 5, 362, 52, 52, 52 }, + { 134, 6, 363, 52, 52, 52 }, + { 134, 0, 364, 53, 52, 52 }, + { 135, 1, 0, 0, 1, 1 }, + { 135, 2, 1, 0, 1, 1 }, + { 135, 3, 2, 0, 1, 1 }, + { 135, 4, 3, 0, 1, 1 }, + { 135, 5, 4, 0, 1, 1 }, + { 135, 6, 5, 0, 1, 1 }, + { 135, 0, 6, 1, 1, 1 }, + { 135, 1, 357, 51, 52, 52 }, + { 135, 2, 358, 51, 52, 52 }, + { 135, 3, 359, 51, 52, 52 }, + { 135, 4, 360, 51, 52, 52 }, + { 135, 5, 361, 51, 52, 52 }, + { 135, 6, 362, 51, 52, 52 }, + { 135, 0, 363, 52, 52, 52 }, + { 135, 1, 364, 52, 1, 53 }, + { 136, 2, 0, 0, 1, 0 }, + { 136, 3, 1, 0, 1, 0 }, + { 136, 4, 2, 0, 1, 0 }, + { 136, 5, 3, 0, 1, 0 }, + { 136, 6, 4, 0, 1, 0 }, + { 136, 0, 5, 1, 1, 0 }, + { 136, 1, 6, 1, 2, 1 }, + { 136, 3, 358, 51, 52, 51 }, + { 136, 4, 359, 51, 52, 51 }, + { 136, 5, 360, 51, 52, 51 }, + { 136, 6, 361, 51, 52, 51 }, + { 136, 0, 362, 52, 52, 51 }, + { 136, 1, 363, 52, 1, 52 }, + { 136, 2, 364, 52, 1, 52 }, + { 136, 3, 365, 52, 1, 52 }, + { 137, 4, 0, 0, 1, 0 }, + { 137, 5, 1, 0, 1, 0 }, + { 137, 6, 2, 0, 1, 0 }, + { 137, 0, 3, 1, 1, 0 }, + { 137, 1, 4, 1, 2, 1 }, + { 137, 2, 5, 1, 2, 1 }, + { 137, 3, 6, 1, 2, 1 }, + { 137, 4, 357, 51, 52, 51 }, + { 137, 5, 358, 51, 52, 51 }, + { 137, 6, 359, 51, 52, 51 }, + { 137, 0, 360, 52, 52, 51 }, + { 137, 1, 361, 52, 53, 52 }, + { 137, 2, 362, 52, 53, 52 }, + { 137, 3, 363, 52, 53, 52 }, + { 137, 4, 364, 52, 53, 52 }, +}; + +static int test_week_calc( void ) +{ + char buffer[100]; + int rc = 1; + int i; + + for ( i = 0; i < 1020; ++i ) + { +#ifdef __cplusplus + struct tm t = {}; +#else + struct tm t = { 0 }; +#endif + int U, V, W; + t.tm_year = data[i][0]; + t.tm_wday = data[i][1]; + t.tm_yday = data[i][2]; + assert( strftime( buffer, 100, "%U %V %W", &t ) == 8 ); + assert( sscanf( buffer, "%d %d %d", &U, &V, &W ) == 3 ); + + if ( data[i][3] != U || data[i][4] != V || data[i][5] != W ) + { + printf( "Fehler in { %d, %d, %d, %d, %d, %d } (encountered { %d, %d, %d })\n", data[i][0], data[i][1], data[i][2], data[i][3], data[i][4], data[i][5], U, V, W ); + rc = 0; + } + } + + return rc; +} + +int main( void ) +{ + char buffer[100]; + /* Basic functionality */ + struct tm timeptr; + MKTIME( timeptr, 59, 30, 12, 1, 9, 72, 0, 274 ); + TESTCASE( strftime( buffer, 100, "%a ", &timeptr ) == 4 ); + TESTCASE( strcmp( buffer, "Sun " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%A ", &timeptr ) == 7 ); + TESTCASE( strcmp( buffer, "Sunday " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%b ", &timeptr ) == 4 ); + TESTCASE( strcmp( buffer, "Oct " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%h ", &timeptr ) == 4 ); + TESTCASE( strcmp( buffer, "Oct " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%B ", &timeptr ) == 8 ); + TESTCASE( strcmp( buffer, "October " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%c ", &timeptr ) == 25 ); + TESTCASE( strcmp( buffer, "Sun Oct 1 12:30:59 1972 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%C ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "19 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%d ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "01 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%D ", &timeptr ) == 9 ); + TESTCASE( strcmp( buffer, "10/01/72 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%e ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, " 1 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%F ", &timeptr ) == 11 ); + TESTCASE( strcmp( buffer, "1972-10-01 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%H ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "12 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%I ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "12 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%j ", &timeptr ) == 4 ); + TESTCASE( strcmp( buffer, "275 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%m ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "10 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%M ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "30 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%p ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "PM " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%r ", &timeptr ) == 12 ); + TESTCASE( strcmp( buffer, "12:30:59 PM " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%R ", &timeptr ) == 6 ); + TESTCASE( strcmp( buffer, "12:30 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%S ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "59 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%T ", &timeptr ) == 9 ); + TESTCASE( strcmp( buffer, "12:30:59 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%u ", &timeptr ) == 2 ); + TESTCASE( strcmp( buffer, "7 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%w ", &timeptr ) == 2 ); + TESTCASE( strcmp( buffer, "0 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%x ", &timeptr ) == 9 ); + TESTCASE( strcmp( buffer, "10/01/72 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%X ", &timeptr ) == 9 ); + TESTCASE( strcmp( buffer, "12:30:59 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%y ", &timeptr ) == 3 ); + TESTCASE( strcmp( buffer, "72 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%Y ", &timeptr ) == 5 ); + TESTCASE( strcmp( buffer, "1972 " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%% ", &timeptr ) == 2 ); + TESTCASE( strcmp( buffer, "% " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%n ", &timeptr ) == 2 ); + TESTCASE( strcmp( buffer, "\n " ) == 0 ); + TESTCASE( strftime( buffer, 100, "%t ", &timeptr ) == 2 ); + TESTCASE( strcmp( buffer, "\t " ) == 0 ); + TESTCASE( test_week_calc() ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/time.c b/rocklibc/src/time/time.c new file mode 100644 index 0000000..358d7f0 --- /dev/null +++ b/rocklibc/src/time/time.c @@ -0,0 +1,48 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_defguard.h" + +#include "sys/time.h" + +/* See comments in _PDCLIB_config.h on the semantics of time_t. */ + +time_t time( time_t * timer ) +{ + struct timeval tv; + + if ( gettimeofday( &tv, NULL ) == 0 ) + { + if ( timer != NULL ) + { + *timer = tv.tv_sec; + } + + return tv.tv_sec; + } + + return -1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + time_t t = time( NULL ); + printf( "%d\n", (int)t ); + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/rocklibc/src/time/timespec_get.c b/rocklibc/src/time/timespec_get.c new file mode 100644 index 0000000..13be220 --- /dev/null +++ b/rocklibc/src/time/timespec_get.c @@ -0,0 +1,46 @@ +/* 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 + +#ifndef REGTEST + +#include "pdclib/_PDCLIB_defguard.h" + +#include "sys/time.h" + +int timespec_get( struct timespec * ts, int base ) +{ + if ( base == TIME_UTC ) + { + /* We can make do with a really thin wrapper here. */ + struct timeval tv; + + if ( gettimeofday( &tv, NULL ) == 0 ) + { + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = tv.tv_usec * 1000; + return base; + } + } + + /* Not supporting any other time base than TIME_UTC for now. */ + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/sysroot/usr/include/assert.h b/sysroot/usr/include/assert.h new file mode 100644 index 0000000..34bea52 --- /dev/null +++ b/sysroot/usr/include/assert.h @@ -0,0 +1,50 @@ +/* Diagnostics + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_ASSERT_H +#define _PDCLIB_ASSERT_H _PDCLIB_ASSERT_H +_PDCLIB_PUBLIC void _PDCLIB_assert99( const char * const, const char * const, const char * const ); +_PDCLIB_PUBLIC void _PDCLIB_assert89( const char * const ); +#endif + +/* If NDEBUG is set, assert() is a null operation. */ +#undef assert + +#ifdef NDEBUG +#define assert( ignore ) ( (void) 0 ) +#else +#if __STDC_VERSION__ >= 199901L +#define assert( expression ) ( ( expression ) ? (void) 0 \ + : _PDCLIB_assert99( "Assertion failed: " #expression \ + ", function ", __func__, \ + ", file " __FILE__ \ + ", line " _PDCLIB_value2string( __LINE__ ) \ + ".\n" ) ) +#else +#define assert( expression ) ( ( expression ) ? (void) 0 \ + : _PDCLIB_assert89( "Assertion failed: " #expression \ + ", file " __FILE__ \ + ", line " _PDCLIB_value2string( __LINE__ ) \ + ".\n" ) ) +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_ASSERT_H +#include _PDCLIB_EXTEND_ASSERT_H +#endif + +#ifdef __cplusplus +} +#endif diff --git a/sysroot/usr/include/ctype.h b/sysroot/usr/include/ctype.h new file mode 100644 index 0000000..551667a --- /dev/null +++ b/sysroot/usr/include/ctype.h @@ -0,0 +1,110 @@ +/* Character handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_CTYPE_H +#define _PDCLIB_CTYPE_H _PDCLIB_CTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +/* 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 ) */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int isalpha( int c ); + +/* Returns true if the character isspace() and used for separating words within + a line of text. In the "C" locale, only ' ' and '\t' are considered blanks. +*/ +_PDCLIB_PUBLIC int isblank( int c ); + +/* Returns true if the character is a control character. */ +_PDCLIB_PUBLIC int iscntrl( int c ); + +/* Returns true if the character is a decimal digit. Locale-independent. */ +_PDCLIB_PUBLIC 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 ' '. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC int islower( int c ); + +/* Returns true for every printing character including space (' '). */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC int isupper( int c ); + +/* Returns true for any hexadecimal-digit character. Locale-independent. */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int tolower( int c ); + +/* Converts a lowercase letter to a corresponding uppercase letter. Input that + is not a lowercase letter remains unchanged. +*/ +_PDCLIB_PUBLIC int toupper( int c ); + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_CTYPE_H +#include _PDCLIB_EXTEND_CTYPE_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/errno.h b/sysroot/usr/include/errno.h new file mode 100644 index 0000000..28eaf5b --- /dev/null +++ b/sysroot/usr/include/errno.h @@ -0,0 +1,202 @@ +/* Errors + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_ERRNO_H +#define _PDCLIB_ERRNO_H _PDCLIB_ERRNO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +/* FIXME: With , this needs to be in thread-specific storage. */ +#define errno (*_PDCLIB_errno_func()) + +/* C only requires the following three */ + +/* Result too large */ +#define ERANGE _PDCLIB_ERANGE +/* Mathematics argument out of domain of function */ +#define EDOM _PDCLIB_EDOM +/* Illegal byte sequence */ +#define EILSEQ _PDCLIB_EILSEQ + +/* C++ additionally requires the folloing */ + +/* Argument list too long */ +#define E2BIG _PDCLIB_E2BIG +/* Permission denied */ +#define EACCES _PDCLIB_EACCES +/* Address in use */ +#define EADDRINUSE _PDCLIB_EADDRINUSE +/* Address not available */ +#define EADDRNOTAVAIL _PDCLIB_EADDRNOTAVAIL +/* Address family not supported */ +#define EAFNOSUPPORT _PDCLIB_EAFNOSUPPORT +/* Resource unavailable, try again */ +#define EAGAIN _PDCLIB_EAGAIN +/* Connection already in progress */ +#define EALREADY _PDCLIB_EALREADY +/* Bad file descriptor */ +#define EBADF _PDCLIB_EBADF +/* Bad message */ +#define EBADMSG _PDCLIB_EBADMSG +/* Device or resource busy */ +#define EBUSY _PDCLIB_EBUSY +/* Operation canceled */ +#define ECANCELED _PDCLIB_ECANCELED +/* No child processes */ +#define ECHILD _PDCLIB_ECHILD +/* Connection aborted */ +#define ECONNABORTED _PDCLIB_ECONNABORTED +/* Connection refused */ +#define ECONNREFUSED _PDCLIB_ECONNREFUSED +/* Connection reset */ +#define ECONNRESET _PDCLIB_ECONNRESET +/* Resource deadlock would occur */ +#define EDEADLK _PDCLIB_EDEADLK +/* Destination address required */ +#define EDESTADDRREQ _PDCLIB_EDESTADDRREQ +/* File exists */ +#define EEXIST _PDCLIB_EEXIST +/* Bad address */ +#define EFAULT _PDCLIB_EFAULT +/* File too large */ +#define EFBIG _PDCLIB_EFBIG +/* Host is unreachable */ +#define EHOSTUNREACH _PDCLIB_EHOSTUNREACH +/* Identifier removed */ +#define EIDRM _PDCLIB_EIDRM +/* Operation in progress */ +#define EINPROGRESS _PDCLIB_EINPROGRESS +/* Interrupted function */ +#define EINTR _PDCLIB_EINTR +/* Invalid argument */ +#define EINVAL _PDCLIB_EINVAL +/* I/O error */ +#define EIO _PDCLIB_EIO +/* Socket is connected */ +#define EISCONN _PDCLIB_EISCONN +/* Is a directory */ +#define EISDIR _PDCLIB_EISDIR +/* Too many levels of symbolic links */ +#define ELOOP _PDCLIB_ELOOP +/* File descriptor value too large */ +#define EMFILE _PDCLIB_EMFILE +/* Too many links */ +#define EMLINK _PDCLIB_EMLINK +/* Message too large */ +#define EMSGSIZE _PDCLIB_EMSGSIZE +/* Filename too long */ +#define ENAMETOOLONG _PDCLIB_ENAMETOOLONG +/* Network is down */ +#define ENETDOWN _PDCLIB_ENETDOWN +/* Connection aborted by network */ +#define ENETRESET _PDCLIB_ENETRESET +/* Network unreachable */ +#define ENETUNREACH _PDCLIB_ENETUNREACH +/* Too many files open in system */ +#define ENFILE _PDCLIB_ENFILE +/* No buffer space available */ +#define ENOBUFS _PDCLIB_ENOBUFS +/* No message is available on the STREAM head read queue */ +#define ENODATA _PDCLIB_ENODATA +/* No such device */ +#define ENODEV _PDCLIB_ENODEV +/* No such file or directory */ +#define ENOENT _PDCLIB_ENOENT +/* Executable file format error */ +#define ENOEXEC _PDCLIB_ENOEXEC +/* No locks available */ +#define ENOLCK _PDCLIB_ENOLCK +/* Link has been severed */ +#define ENOLINK _PDCLIB_ENOLINK +/* Not enough space */ +#define ENOMEM _PDCLIB_ENOMEM +/* No message of the desired type */ +#define ENOMSG _PDCLIB_ENOMSG +/* Protocol not available */ +#define ENOPROTOOPT _PDCLIB_ENOPROTOOPT +/* No space left on device */ +#define ENOSPC _PDCLIB_ENOSPC +/* No STREAM resources */ +#define ENOSR _PDCLIB_ENOSR +/* Not a STREAM */ +#define ENOSTR _PDCLIB_ENOSTR +/* Function not supported */ +#define ENOSYS _PDCLIB_ENOSYS +/* The socket is not connected */ +#define ENOTCONN _PDCLIB_ENOTCONN +/* Not a directory */ +#define ENOTDIR _PDCLIB_ENOTDIR +/* Directory not empty */ +#define ENOTEMPTY _PDCLIB_ENOTEMPTY +/* State not recoverable */ +#define ENOTRECOVERABLE _PDCLIB_ENOTRECOVERABLE +/* Not a socket */ +#define ENOTSOCK _PDCLIB_ENOTSOCK +/* Not supported */ +#define ENOTSUP _PDCLIB_ENOTSUP +/* Inappropriate I/O control operation */ +#define ENOTTY _PDCLIB_ENOTTY +/* No such device or address */ +#define ENXIO _PDCLIB_ENXIO +/* Operation not supported on socket */ +#define EOPNOTSUPP _PDCLIB_EOPNOTSUPP +/* Value too large to be stored in data type */ +#define EOVERFLOW _PDCLIB_EOVERFLOW +/* Previous owner died */ +#define EOWNERDEAD _PDCLIB_EOWNERDEAD +/* Operation not permitted */ +#define EPERM _PDCLIB_EPERM +/* Broken pipe */ +#define EPIPE _PDCLIB_EPIPE +/* Protocol error */ +#define EPROTO _PDCLIB_EPROTO +/* Protocol not supported */ +#define EPROTONOSUPPORT _PDCLIB_EPROTONOSUPPORT +/* Protocol wrong type for socket */ +#define EPROTOTYPE _PDCLIB_EPROTOTYPE +/* Read-only file system */ +#define EROFS _PDCLIB_EROFS +/* Invalid seek */ +#define ESPIPE _PDCLIB_ESPIPE +/* No such process */ +#define ESRCH _PDCLIB_ESRCH +/* Stream ioctl() timeout */ +#define ETIME _PDCLIB_ETIME +/* Connection timed out */ +#define ETIMEDOUT _PDCLIB_ETIMEDOUT +/* Text file busy */ +#define ETXTBSY _PDCLIB_ETXTBSY +/* Operation would block */ +#define EWOULDBLOCK _PDCLIB_EWOULDBLOCK +/* Cross-device link */ +#define EXDEV _PDCLIB_EXDEV + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_ERRNO_H +#include _PDCLIB_EXTEND_ERRNO_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/fcntl.h b/sysroot/usr/include/fcntl.h new file mode 100644 index 0000000..99d530f --- /dev/null +++ b/sysroot/usr/include/fcntl.h @@ -0,0 +1,19 @@ +#ifndef _FCNTL_H +#define _FCNTL_H + +/* File access modes for open() */ +#define O_RDONLY 00000000 +#define O_WRONLY 00000001 +#define O_RDWR 00000002 + +/* File creation flags */ +#define O_CREAT 00000100 +#define O_EXCL 00000200 +#define O_NOCTTY 00000400 +#define O_TRUNC 00001000 +#define O_APPEND 00002000 +#define O_NONBLOCK 00004000 + +#define AT_FDCWD (-100) + +#endif /* _FCNTL_H */ \ No newline at end of file diff --git a/sysroot/usr/include/float.h b/sysroot/usr/include/float.h new file mode 100644 index 0000000..49d5d2e --- /dev/null +++ b/sysroot/usr/include/float.h @@ -0,0 +1,82 @@ +/* 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. +*/ + +#ifndef _PDCLIB_FLOAT_H +#define _PDCLIB_FLOAT_H _PDCLIB_FLOAT_H + +#include "pdclib/_PDCLIB_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__ + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_FLOAT_H +#include _PDCLIB_EXTEND_FLOAT_H +#endif + +#endif diff --git a/sysroot/usr/include/inttypes.h b/sysroot/usr/include/inttypes.h new file mode 100644 index 0000000..0be401d --- /dev/null +++ b/sysroot/usr/include/inttypes.h @@ -0,0 +1,368 @@ +/* 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. +*/ + +#ifndef _PDCLIB_INTTYPES_H +#define _PDCLIB_INTTYPES_H _PDCLIB_INTTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct _PDCLIB_imaxdiv_t imaxdiv_t; + +/* 7.8.1 Macros for format specifiers */ + +/* The various leastN_t, fastN_t, intmax_t, and intptr_t types are typedefs + to native types. But the user does not know which ones, which gives some + problems when trying to *printf() / *scanf() those types. The various + macros defined below allow to give the correct conversion specifiers + without knowing the actual native type they represent. +*/ + +#if _PDCLIB_INT_LEAST8_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define PRIiLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define PRIoLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define PRIuLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define PRIxLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) +#define PRIXLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, X ) ) +#else +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#endif + +#if _PDCLIB_INT_FAST8_MAX > _PDCLIB_INT_MAX +#define PRIdFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, d ) ) +#define PRIiFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, i ) ) +#define PRIoFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, o ) ) +#define PRIuFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, u ) ) +#define PRIxFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, x ) ) +#define PRIXFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, X ) ) +#else +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" +#endif + +#if _PDCLIB_INT_LEAST16_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define PRIiLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define PRIoLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define PRIuLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define PRIxLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) +#define PRIXLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, X ) ) +#else +#define PRIdLEAST16 "d" +#define PRIiLEAST16 "i" +#define PRIoLEAST16 "o" +#define PRIuLEAST16 "u" +#define PRIxLEAST16 "x" +#define PRIXLEAST16 "X" +#endif + +#if _PDCLIB_INT_FAST16_MAX > _PDCLIB_INT_MAX +#define PRIdFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, d ) ) +#define PRIiFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, i ) ) +#define PRIoFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, o ) ) +#define PRIuFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, u ) ) +#define PRIxFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, x ) ) +#define PRIXFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, X ) ) +#else +#define PRIdFAST16 "d" +#define PRIiFAST16 "i" +#define PRIoFAST16 "o" +#define PRIuFAST16 "u" +#define PRIxFAST16 "x" +#define PRIXFAST16 "X" +#endif + +#if _PDCLIB_INT_LEAST32_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define PRIiLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define PRIoLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define PRIuLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define PRIxLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) +#define PRIXLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, X ) ) +#else +#define PRIdLEAST32 "d" +#define PRIiLEAST32 "i" +#define PRIoLEAST32 "o" +#define PRIuLEAST32 "u" +#define PRIxLEAST32 "x" +#define PRIXLEAST32 "X" +#endif + +#if _PDCLIB_INT_FAST32_MAX > _PDCLIB_INT_MAX +#define PRIdFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, d ) ) +#define PRIiFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, i ) ) +#define PRIoFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, o ) ) +#define PRIuFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, u ) ) +#define PRIxFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, x ) ) +#define PRIXFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, X ) ) +#else +#define PRIdFAST32 "d" +#define PRIiFAST32 "i" +#define PRIoFAST32 "o" +#define PRIuFAST32 "u" +#define PRIxFAST32 "x" +#define PRIXFAST32 "X" +#endif + +#if _PDCLIB_INT_LEAST64_MAX > _PDCLIB_INT_MAX +#define PRIdLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define PRIiLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define PRIoLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define PRIuLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define PRIxLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) +#define PRIXLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, X ) ) +#else +#define PRIdLEAST64 "d" +#define PRIiLEAST64 "i" +#define PRIoLEAST64 "o" +#define PRIuLEAST64 "u" +#define PRIxLEAST64 "x" +#define PRIXLEAST64 "X" +#endif + +#if _PDCLIB_INT_FAST64_MAX > _PDCLIB_INT_MAX +#define PRIdFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, d ) ) +#define PRIiFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, i ) ) +#define PRIoFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, o ) ) +#define PRIuFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, u ) ) +#define PRIxFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, x ) ) +#define PRIXFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, X ) ) +#else +#define PRIdFAST64 "d" +#define PRIiFAST64 "i" +#define PRIoFAST64 "o" +#define PRIuFAST64 "u" +#define PRIxFAST64 "x" +#define PRIXFAST64 "X" +#endif + +#if _PDCLIB_INTMAX_MAX > _PDCLIB_INT_MAX +#define PRIdMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, d ) ) +#define PRIiMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, i ) ) +#define PRIoMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, o ) ) +#define PRIuMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, u ) ) +#define PRIxMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, x ) ) +#define PRIXMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, X ) ) +#else +#define PRIdMAX "d" +#define PRIiMAX "i" +#define PRIoMAX "o" +#define PRIuMAX "u" +#define PRIxMAX "x" +#define PRIXMAX "X" +#endif + +#if _PDCLIB_INTPTR_MAX > _PDCLIB_INT_MAX +#define PRIdPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, d ) ) +#define PRIiPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, i ) ) +#define PRIoPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, o ) ) +#define PRIuPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, u ) ) +#define PRIxPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, x ) ) +#define PRIXPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, X ) ) +#else +#define PRIdPTR "d" +#define PRIiPTR "i" +#define PRIoPTR "o" +#define PRIuPTR "u" +#define PRIxPTR "x" +#define PRIXPTR "X" +#endif + +#define SCNdLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define SCNiLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define SCNoLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define SCNuLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define SCNxLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) + +#define SCNdFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, d ) ) +#define SCNiFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, i ) ) +#define SCNoFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, o ) ) +#define SCNuFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, u ) ) +#define SCNxFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, x ) ) + +#define SCNdLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define SCNiLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define SCNoLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define SCNuLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define SCNxLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) + +#define SCNdFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, d ) ) +#define SCNiFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, i ) ) +#define SCNoFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, o ) ) +#define SCNuFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, u ) ) +#define SCNxFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, x ) ) + +#define SCNdLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define SCNiLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define SCNoLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define SCNuLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define SCNxLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) + +#define SCNdFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, d ) ) +#define SCNiFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, i ) ) +#define SCNoFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, o ) ) +#define SCNuFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, u ) ) +#define SCNxFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, x ) ) + +#define SCNdLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define SCNiLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define SCNoLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define SCNuLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define SCNxLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) + +#define SCNdFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, d ) ) +#define SCNiFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, i ) ) +#define SCNoFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, o ) ) +#define SCNuFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, u ) ) +#define SCNxFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, x ) ) + +#define SCNdMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, d ) ) +#define SCNiMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, i ) ) +#define SCNoMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, o ) ) +#define SCNuMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, u ) ) +#define SCNxMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, x ) ) + +#define SCNdPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, d ) ) +#define SCNiPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, i ) ) +#define SCNoPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, o ) ) +#define SCNuPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, u ) ) +#define SCNxPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, x ) ) + +/* The exact-width types (int8_t, int16_t, ...) are *optional*, as not all + architectures support the necessary 8-bits-per-byte two's complement + native types. +*/ + +#if _PDCLIB_TWOS_COMPLEMENT == 1 + +#if _PDCLIB_INT_LEAST8_MAX == 0x7f +#if _PDCLIB_INT_LEAST8_MAX > _PDCLIB_INT_MAX +#define PRId8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define PRIi8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define PRIo8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define PRIu8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define PRIx8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) +#define PRIX8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, X ) ) +#endif +#define SCNd8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) ) +#define SCNi8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) ) +#define SCNo8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) ) +#define SCNu8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) ) +#define SCNx8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) ) +#endif + +#if _PDCLIB_INT_LEAST16_MAX == 0x7fff +#if _PDCLIB_INT_LEAST16_MAX > _PDCLIB_INT_MAX +#define PRId16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define PRIi16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define PRIo16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define PRIu16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define PRIx16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) +#define PRIX16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, X ) ) +#endif +#define SCNd16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) ) +#define SCNi16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) ) +#define SCNo16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) ) +#define SCNu16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) ) +#define SCNx16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) ) +#endif + +#if _PDCLIB_INT_LEAST32_MAX == 0x7fffffffl +#if _PDCLIB_INT_LEAST32_MAX > _PDCLIB_INT_MAX +#define PRId32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define PRIi32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define PRIo32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define PRIu32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define PRIx32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) +#define PRIX32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, X ) ) +#endif +#define SCNd32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) ) +#define SCNi32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) ) +#define SCNo32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) ) +#define SCNu32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) ) +#define SCNx32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) ) +#endif + +#if _PDCLIB_INT_LEAST64_MAX == 0x7fffffffffffffffll +#if _PDCLIB_INT_LEAST64_MAX > _PDCLIB_INT_MAX +#define PRId64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define PRIi64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define PRIo64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define PRIu64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define PRIx64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) +#define PRIX64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, X ) ) +#endif +#define SCNd64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) ) +#define SCNi64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) ) +#define SCNo64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) ) +#define SCNu64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) ) +#define SCNx64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) ) +#endif + +#endif + +/* 7.8.2 Functions for greatest-width integer types */ + +/* Calculate the absolute value of j */ +_PDCLIB_PUBLIC intmax_t imaxabs( intmax_t j ); + +/* Return quotient (quot) and remainder (rem) of an integer division in the + imaxdiv_t struct. +*/ +_PDCLIB_PUBLIC imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom ); + +/* Separate 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. +*/ +_PDCLIB_PUBLIC intmax_t strtoimax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC uintmax_t strtoumax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); + +/* TODO: wcstoimax(), wcstoumax() */ + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_INTTYPES_H +#include _PDCLIB_EXTEND_INTTYPES_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/iso646.h b/sysroot/usr/include/iso646.h new file mode 100644 index 0000000..88e521c --- /dev/null +++ b/sysroot/usr/include/iso646.h @@ -0,0 +1,31 @@ +/* Alternative spellings + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_ISO646_H +#define _PDCLIB_ISO646_H _PDCLIB_ISO646_H + +#ifndef __cplusplus +#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 ^= +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_ISO646_H +#include _PDCLIB_EXTEND_ISO646_H +#endif + +#endif diff --git a/sysroot/usr/include/limits.h b/sysroot/usr/include/limits.h new file mode 100644 index 0000000..72268a4 --- /dev/null +++ b/sysroot/usr/include/limits.h @@ -0,0 +1,50 @@ +/* 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. +*/ + +#ifndef _PDCLIB_LIMITS_H +#define _PDCLIB_LIMITS_H _PDCLIB_LIMITS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +/* TODO: Defined to 1 as multibyte characters are not supported yet. */ +#define MB_LEN_MAX 1 + +#define LLONG_MIN _PDCLIB_LLONG_MIN +#define LLONG_MAX _PDCLIB_LLONG_MAX +#define ULLONG_MAX _PDCLIB_ULLONG_MAX + +#define CHAR_BIT _PDCLIB_CHAR_BIT +#define CHAR_MAX _PDCLIB_CHAR_MAX +#define CHAR_MIN _PDCLIB_CHAR_MIN +#define SCHAR_MAX _PDCLIB_SCHAR_MAX +#define SCHAR_MIN _PDCLIB_SCHAR_MIN +#define UCHAR_MAX _PDCLIB_UCHAR_MAX +#define SHRT_MAX _PDCLIB_SHRT_MAX +#define SHRT_MIN _PDCLIB_SHRT_MIN +#define INT_MAX _PDCLIB_INT_MAX +#define INT_MIN _PDCLIB_INT_MIN +#define LONG_MAX _PDCLIB_LONG_MAX +#define LONG_MIN _PDCLIB_LONG_MIN +#define USHRT_MAX _PDCLIB_USHRT_MAX +#define UINT_MAX _PDCLIB_UINT_MAX +#define ULONG_MAX _PDCLIB_ULONG_MAX + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_LIMITS_H +#include _PDCLIB_EXTEND_LIMITS_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/locale.h b/sysroot/usr/include/locale.h new file mode 100644 index 0000000..0c18446 --- /dev/null +++ b/sysroot/usr/include/locale.h @@ -0,0 +1,114 @@ +/* Localization + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_LOCALE_H +#define _PDCLIB_LOCALE_H _PDCLIB_LOCALE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* The structure returned by localeconv(). + + The values for *_sep_by_space: + 0 - no space + 1 - if symbol and sign are adjacent, a space separates them from the value; + otherwise a space separates the symbol from the value + 2 - if symbol and sign are adjacent, a space separates them; otherwise a + space separates 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 separating 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 separated by space from pos. qty. */ /* LC_MONETARY */ + char n_sep_by_space; /* if it is separated 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. +*/ +_PDCLIB_PUBLIC char * setlocale( int category, const char * locale ); + +/* Returns a struct lconv initialized to the values appropriate for the current + locale setting. +*/ +_PDCLIB_PUBLIC struct lconv * localeconv( void ); + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_LOCALE_H +#include _PDCLIB_EXTEND_LOCALE_H +#endif + +#endif diff --git a/sysroot/usr/include/math.h b/sysroot/usr/include/math.h new file mode 100644 index 0000000..88b6619 --- /dev/null +++ b/sysroot/usr/include/math.h @@ -0,0 +1,467 @@ +/* Mathematics + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_MATH_H +#define _PDCLIB_MATH_H _PDCLIB_MATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +typedef float float_t; +typedef double double_t; + +#define HUGE_VALF _PDCLIB_HUGE_VALF; +#define HUGE_VAL _PDCLIB_HUGE_VAL; +#define HUGE_VALL _PDCLIB_HUGE_VALL; + +#define INFINITY (_PDCLIB_FLT_MAX * 2) +#define NAN ( -(0.0f / 0.0f) ) + +#define FP_FAST_FMAF +#define FP_FAST_FMA +#define FP_FAST_FMAL + +#define FP_ILOGB0 INT_MIN +#define FP_ILOGBNAN INT_MAX + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 + +#define math_errhandling + +/* Classification */ + +/* FP_ZERO, FP_SUBNORMAL, FP_NORMAL */ +#define isfinite( x ) _PDCLIB_GENERIC( isfinite, x ) + +/* FP_INFINITE */ +#define isinf( x ) _PDCLIB_GENERIC( isinf, x ) + +/* FP_NAN */ +#define isnan( x ) _PDCLIB_GENERIC( isnan, x ) + +/* FP_NORMAL */ +#define isnormal( x ) _PDCLIB_GENERIC( isnormal, x ) + +/* Negative */ +#define signbit( x ) _PDCLIB_GENERIC( signbit, x ) + +/* See FP_* classes */ +#define fpclassify( x ) _PDCLIB_GENERIC( fpclassify, x ) + +#define FP_INFINITE 1 +#define FP_NAN 2 +#define FP_NORMAL 3 +#define FP_SUBNORMAL 4 +#define FP_ZERO 5 + +/* Trigonometric functions */ + +/* The principal value of the arc cosine of x. + Domain error for arguments not in the interval -1..+1. + Returns the interval 0..Pi radians. +*/ +double acos( double x ); +float acosf( float x ); +long double acosl( long double x ); + +/* The principal value of the arc sine of x. + Domain error for arguments not in the interval -1..+1. + Returns the interval -Pi/2..Pi/2 radians. +*/ +double asin( double x ); +float asinf( float x ); +long double asinl( long double x ); + +/* The principal value of the arc tangent of x. + Returns the interval -Pi/2..Pi/2 radians. +*/ +double atan( double x ); +float atanf( float x ); +long double atanl( long double x ); + +/* The value of the arc tangent of y/x, using the signs of both + arguments to determine the quadrant of the return value. + Domain error if both arguments are zero. + Returns the interval -Pi..Pi radians. +*/ +double atan2( double y, double x ); +float atan2f( float y, float x ); +long double atan2l( long double y, long double x ); + +/* Cosine of x in radians. */ +double cos( double x ); +float cosf( float x ); +long double cosl( long double x ); + +/* Sine of x in radians. */ +double sin( double x ); +float sinf( float x ); +long double sinl( long double x ); + +/* Tangent of x in radians. */ +double tan( double x ); +float tanf( float x ); +long double tanl( long double x ); + +/* Hyperbolic functions */ + +/* The (nonnegative) arc hyberbolic cosine of x. + Domain error for arguments less than 1. + Returns the interval 0..INF. +*/ +double acosh( double x ); +float acoshf( float x ); +long double acoshl( long double x ); + +/* The arc hyberbolic sine of x. +*/ +double asinh( double x ); +float asinhf( float x ); +long double asinhl( long double x ); + +/* The arc hyberbolic tangent of x. + Domain error for arguments not in -1..1. + Range error if -1 or +1. +*/ +double atanh( double x ); +float atanhf( float x ); +long double atanhl( long double x ); + +/* The hyberbolic cosine of x. + Range error if magnitude of x is too large. +*/ +double cosh( double x ); +float coshf( float x ); +long double coshl( long double x ); + +/* The hyberbolic sine of x. + Range error if magnitude of x is too large. +*/ +double sinh( double x ); +float sinhf( float x ); +long double sinhl( long double x ); + +/* The hyberbolic tangent of x. + Range error if magnitude of x is too large. +*/ +double tanh( double x ); +float tanhf( float x ); +long double tanhl( long double x ); + +/* Exponential and logarithmic functions */ + +/* The base-e exponential of x. + Range error if magnitude of x is too large. +*/ +double exp( double x ); +float expf( float x ); +long double expl( long double x ); + +/* The base-2 exponential of x. + Range error if magnitude of x is too large. +*/ +double exp2( double x ); +float exp2f( float x ); +long double exp2l( long double x ); + +/* The base-e exponential of x, minus 1. + Range error if magnitude of x is too large. + Returns e^x - 1. +*/ +double expm1( double x ); +float expm1f( float x ); +long double expm1l( long double x ); + +/* Breaks a floating-point number into a normalized fraction + and an integral power of 2 (stored in the object pointed + to by exp). +*/ +double frexp( double value, int * exp ); +float frexpf( float value, int * exp ); +long double frexpl( long double value, int * exp ); + +/* Extract the exponent of x as a signed int. + * Returns FP_ILOGB0 if x is zero, INT_MAX if x is infinite, + * FP_ILOGBNAN if x is a NaN. Range error may occur if x is 0. +*/ +double ilogb( double x ); +float ilogbf( float x ); +long double ilogbl( long double x ); + +/* Multiply x by 2^exp. Range error may occur. */ +double ldexp( double x, int exp ); +float ldexpf( float x, int exp ); +long double ldexpl( long double x, int exp ); + +/* Compute the base-e logarithm of x. + Domain error if argument is negative. + Range error if argument is zero. +*/ +double log( double x ); +float logf( float x ); +long double logl( long double x ); + +/* Compute the base-10 logarithm of x. + Domain error if argument is negative. + Range error if argument is zero. +*/ +double log10( double x ); +float log10f( float x ); +long double log10l( long double x ); + +/* Compute the base-e logarithm of 1 plus x. + Domain error if argument is less than -1. + Range error if argument is -1. +*/ +double log1p( double x ); +float log1pf( float x ); +long double log1pl( long double x ); + +/* Compute the base-2 logarithm of x. + Domain error if argument is negative. + Range error if argument is zero. +*/ +double log2( double x ); +float log2f( float x ); +long double log2l( long double x ); + +/* Extract exponent of x, as signed integer in floating-point format. + Subnormal is treated as though normalized. + Domain error if argument is zero. +*/ +double logb( double x ); +float logbf( float x ); +long double logbl( long double x ); + +/* Breaks value into integral and fractional parts, each having + the same type and sign as the argument. The integral part is + stored in the object pointed to by iptr. +*/ +double modf( double value, double * exp ); +float modff( float value, float * exp ); +long double modfl( long double value, long double * exp ); + +/* Compute x * FLT_RADIX^n efficiently. Range error may occur. */ +double scalbn( double x, int n ); +float scalbnf( float x, int n ); +long double scalbnl( long double x, int n ); + +double scalbln( double x, long int * n ); +float scalblnf( float x, long int * n ); +long double scalblnl( long double x, long int * n ); + +/* Power and absolute-value functions */ + +/* Returns x^1/3. */ +double cbrt( double x ); +float cbrtf( float x ); +long double cbrtl( long double x ); + +/* Returns absolute value of x. */ +double fabs( double x ); +float fabsf( float x ); +long double fabsl( long double x ); + +/* Returns square root of the sum of squares of x and y. + Range error may occur. +*/ +double hypot( double x, double y ); +float hypotf( float x, float y ); +long double hypotl( long double x, long double y ); + +/* Returns x^y. + Domain error if x is finite and negative and y is finite and not + an integer value. + Domain error if x is zero and y is less or equal zero. + Range error may occur. +*/ +double pow( double x, double y ); +float powf( float x, float y ); +long double powl( long double x, long double y ); + +/* Returns x^1/2. */ +double sqrt( double x ); +float sqrtf( float x ); +long double sqrtl( long double x ); + +/* Error and gamma functions */ + +/* Compute the error function of x. */ +double erf( double x ); +float erff( float x ); +long double erfl( long double x ); + +/* Compute the complementary error function of x. + Range error if x is too large. +*/ +double erfc( double x ); +float erfcf( float x ); +long double erfcl( long double x ); + +/* Compute the natural logarithm of the absolute value of gamma(x). + Range error if x is too lange, x is negative, or zero. +*/ +double lgamma( double x ); +float lgammaf( float x ); +long double lgammal( long double x ); + +/* Compute the gamma function of x. + Range error if x is negative, or zero, too large or too small. +*/ +double tgamma( double x ); +float tgammaf( float x ); +long double tgammal( long double x ); + +/* Nearest integer functions */ + +/* The smallest integer no less than x. */ +double ceil( double x ); +float ceilf( float x ); +long double ceill( long double x ); + +/* The largest integer no greater than x. */ +double floor( double x ); +float floorf( float x ); +long double floorl( long double x ); + +/* Round in current rounding direction. No "inexact" exception. */ +double nearbyint( double x ); +float nearbyintf( float x ); +long double nearbyintl( long double x ); + +/* Round in current rounding direction. Raises "inexact" exception. */ +double rint( double x ); +float rintf( float x ); +long double rintl( long double x ); + +/* Round in current rounding direction. + Range error if magnitude is too large. +*/ +long int lrint( double x ); +long int lrintf( float x ); +long int lrintl( long double x ); +long long int llrint( double x ); +long long int llrintf( float x ); +long long int llrintl( long double x ); + +/* Round to nearest, breaking ties away from zero. */ +double round( double x ); +float roundf( float x ); +long double roundl( long double x ); + +/* Round to nearest, breaking ties away from zero. + Range error if magnitude is too large. +*/ +long int lround( double x ); +long int lroundf( float x ); +long int lroundl( long double x ); +long long int llround( double x ); +long long int llroundf( float x ); +long long int llroundl( long double x ); + +/* Round toward zero. */ +double trunc( double x ); +float truncf( float x ); +long double truncl( long double x ); + +/* Remainder functions */ + +/* Compute the remainder of x / y. */ +double fmod( double x, double y ); +float fmodf( float x, float y ); +long double fmodl( long double x, long double y ); + +/* Compute the remainder of x REM y. */ +double remainder( double x, double y ); +float remainderf( float x, float y ); +long double remainderl( long double x, long double y ); + +/* Compute the remainder of x REM y. In quo store a value with + the sign of the quotient and magnitude congruent mod 2^n to + the magnitude of the integral quotient of x / y, with n + an implementation-defined integer greater than or equal to 3. +*/ +double rmquo( double x, double y ); +float rmquof( float x, float y ); +long double rmquol( long double x, long double y ); + +/* Manipulation functions */ + +/* Returns a value with magnitude of x and sign of y. */ +double copysign( double x, double y ); +float copysignf( float x, float y ); +long double copysignl( long double x, long double y ); + +/* Returns a NaN value with the given n-char sequence. */ +double nan( const char * tagp ); +float nanf( const char * tagp ); +long double nanl( const char * tagp ); + +/* Determine the next representable value after x in direction y. + Range error if result is not representable. +*/ +double nextafter( double x, double y ); +float nextafterf( float x, float y ); +long double nextafterl( long double x, long double y ); + +/* As nextafter but with long double as second parameter. */ +double nexttoward( double x, double y ); +float nexttowardf( float x, float y ); +long double nexttowardl( long double x, long double y ); + +/* Maximum, minimum, and positive difference functions */ + +/* Positive difference. */ +double fdim( double x, double y ); +float fdimf( float x, float y ); +long double fdiml( long double x, long double y ); + +/* Maximum. */ +double fmax( double x, double y ); +float fmaxf( float x, float y ); +long double fmaxl( long double x, long double y ); + +/* Minimum. */ +double fmin( double x, double y ); +float fminf( float x, float y ); +long double fminl( long double x, long double y ); + +/* Multiply-add. */ +double fma( double x, double y, double z ); +float fmaf( float x, float y, float z ); +long double fmal( long double x, long double y, long double z ); + +/* Comparison macros (without "invalid" FP exception) */ + +#define isgreater( x, y ) + +#define isgreaterequal( x, y ) + +#define isless( x, y ) + +#define islessequal( x, y ) + +#define islessgreater( x, y ) + +#define isunordered( x, y ) + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_MATH_H +#include _PDCLIB_EXTEND_MATH_H +#endif + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_config.h b/sysroot/usr/include/pdclib/_PDCLIB_config.h new file mode 100644 index 0000000..653f89e --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_config.h @@ -0,0 +1,915 @@ +/* Internal PDCLib configuration <_PDCLIB_config.h> + ("Example" platform target, for PDCLib development) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_CONFIG_H +#define _PDCLIB_CONFIG_H _PDCLIB_CONFIG_H + +/* -------------------------------------------------------------------------- */ +/* Misc */ +/* -------------------------------------------------------------------------- */ + +/* Helper macros also documented in _PDCLIB_internal.h, but defined here as */ +/* they are needed in this file already. */ +/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending. */ +/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */ +#define _PDCLIB_cc( x, y ) x ## y +#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y ) + +/* 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 ); + +/* Define this to some compiler directive that can be written after the */ +/* parameter list of a function declaration to indicate the function does */ +/* never return. If your compiler does not support such a directive, define */ +/* to nothing. (This is to avoid warnings with the exit functions under GCC */ +/* when compiling with C99/C++ settings, where C11 _Noreturn is unavailable.) */ +#define _PDCLIB_NORETURN __attribute__(( noreturn )) + +/* -------------------------------------------------------------------------- */ +/* Symbol Visibility */ +/* -------------------------------------------------------------------------- */ + +/* This defines _PDCLIB_PUBLIC to indicate external linkage, and _PDCLIB_LOCAL + to indicate local linkage. +*/ + +#ifdef _PDCLIB_STATIC_DEFINE + #define _PDCLIB_PUBLIC + #define _PDCLIB_LOCAL +#else + #if defined _WIN32 || defined __CYGWIN__ + #ifdef _PDCLIB_BUILD + #ifdef __GNUC__ + #define _PDCLIB_PUBLIC __attribute__ ((dllexport)) + #else + #define _PDCLIB_PUBLIC __declspec(dllexport) + #endif + #else + #ifdef __GNUC__ + #define _PDCLIB_PUBLIC __attribute__ ((dllimport)) + #else + #define _PDCLIB_PUBLIC __declspec(dllimport) + #endif + #endif + #define _PDCLIB_LOCAL + #else + #if __GNUC__ >= 4 + #define _PDCLIB_PUBLIC __attribute__ ((visibility ("default"))) + #define _PDCLIB_LOCAL __attribute__ ((visibility ("hidden"))) + #else + #define _PDCLIB_PUBLIC + #define _PDCLIB_LOCAL + #endif + #endif +#endif + +/* -------------------------------------------------------------------------- */ +/* Integers */ +/* -------------------------------------------------------------------------- */ +/* The defines below make use of predefines offered by GCC and clang. If you */ +/* adapt PDCLib for a different compiler family, you will have to use what */ +/* that compiler provides, or enter actual values. */ +/* -------------------------------------------------------------------------- */ + +/* At the point of writing, PDCLib makes no provisions for, nor has it been */ +/* tested, on a platform that uses signed magnitude or one's complement to */ +/* encode its integers. Most importantly, there are no guarantees that the */ +/* negative zero of those encodings is in any form handled gracefully. */ +#define _PDCLIB_TWOS_COMPLEMENT 1 + +/* 1234 for little endian, 4321 for big endian; other types not supported. */ +#define _PDCLIB_ENDIANESS __BYTE_ORDER__ + +/* Calculation of a minimum value from a given maximum for two's complement. */ +/* (For convenience only, used only in this header file below.) */ +#define _PDCLIB_MIN_CALC( max ) ( ( - max ) - 1 ) + +/* Now, introducting the various predefines to the _PDCLIB_* namespace, so */ +/* the rest of PDCLib can work with that and adapting to a different compiler */ +/* will require changes only in this one file. */ + +/* Bits in a char */ +#define _PDCLIB_CHAR_BIT __CHAR_BIT__ + +/* Maximum and minimum values of signed / unsigned char */ +#define _PDCLIB_SCHAR_MAX __SCHAR_MAX__ +#define _PDCLIB_SCHAR_MIN _PDCLIB_MIN_CALC( __SCHAR_MAX__ ) +#define _PDCLIB_UCHAR_MAX ( __SCHAR_MAX__ * 2 + 1 ) + +/* Whether the 'char' type is unsigned */ +#ifdef __CHAR_UNSIGNED__ +#define _PDCLIB_CHAR_MAX _PDCLIB_UCHAR_MAX +#define _PDCLIB_CHAR_MIN 0 +#else +#define _PDCLIB_CHAR_MAX _PDCLIB_SCHAR_MAX +#define _PDCLIB_CHAR_MIN _PDCLIB_SCHAR_MIN +#endif + +/* Maximum and minimum values of signed / unsigned short */ +#define _PDCLIB_SHRT_MAX __SHRT_MAX__ +#define _PDCLIB_SHRT_MIN _PDCLIB_MIN_CALC( __SHRT_MAX__ ) +#define _PDCLIB_USHRT_MAX ( __SHRT_MAX__ * 2u + 1 ) + +/* Maximum and minimum values of signed / unsigned int */ +#define _PDCLIB_INT_MAX __INT_MAX__ +#define _PDCLIB_INT_MIN _PDCLIB_MIN_CALC( __INT_MAX__ ) +#define _PDCLIB_UINT_MAX ( __INT_MAX__ * 2u + 1 ) + +/* Maximum and minimum values of signed / unsigned long */ +#define _PDCLIB_LONG_MAX __LONG_MAX__ +#define _PDCLIB_LONG_MIN _PDCLIB_MIN_CALC( __LONG_MAX__ ) +#define _PDCLIB_ULONG_MAX ( __LONG_MAX__ * 2ul + 1 ) + +/* Maximum and minimum values of signed / unsigned long long */ +#define _PDCLIB_LLONG_MAX __LONG_LONG_MAX__ +#define _PDCLIB_LLONG_MIN _PDCLIB_MIN_CALC( __LONG_LONG_MAX__ ) +#define _PDCLIB_ULLONG_MAX ( __LONG_LONG_MAX__ * 2ull + 1 ) + +/* -------------------------------------------------------------------------- */ +/* defines a set of integer types that are of a minimum width, and */ +/* "usually fastest" on the system. (If, for example, accessing a single char */ +/* requires the CPU to access a complete int and then mask out the char, the */ +/* "usually fastest" type of at least 8 bits would be int, not char.) */ +/* If you do not have information on the relative performance of the types, */ +/* the standard allows you to define any type that meets minimum width and */ +/* signedness requirements. */ +/* The first define is the appropriate basic type (e.g. "long int"), second */ +/* its max value, the third its min value (both expressed in the given type). */ +/* The same follows for the unsigned type (for which the minimum value is */ +/* obviously zero and need not be defined). */ +/* There *are* predefines provided for the printf()/scanf() length specifiers */ +/* but tunneling them through here would have added many lines of repetitive */ +/* and mostly redundant defines. They are determined in <_PDCLIB_internal.h>. */ +/* -------------------------------------------------------------------------- */ + +/* int_fast8_t / uint_fast8_t */ +#define _PDCLIB_int_fast8_t __INT_FAST8_TYPE__ +#define _PDCLIB_INT_FAST8_MAX __INT_FAST8_MAX__ +#define _PDCLIB_INT_FAST8_MIN _PDCLIB_MIN_CALC( __INT_FAST8_MAX__ ) +#define _PDCLIB_uint_fast8_t __UINT_FAST8_TYPE__ +#define _PDCLIB_UINT_FAST8_MAX __UINT_FAST8_MAX__ + +/* int_least8_t / uint_least8_t */ +#define _PDCLIB_int_least8_t __INT_LEAST8_TYPE__ +#define _PDCLIB_INT_LEAST8_MAX __INT_LEAST8_MAX__ +#define _PDCLIB_INT_LEAST8_MIN _PDCLIB_MIN_CALC( __INT_LEAST8_MAX__ ) +#define _PDCLIB_uint_least8_t __UINT_LEAST8_TYPE__ +#define _PDCLIB_UINT_LEAST8_MAX __UINT_LEAST8_MAX__ + +/* int_fast16_t / uint_fast16_t */ +#define _PDCLIB_int_fast16_t __INT_FAST16_TYPE__ +#define _PDCLIB_INT_FAST16_MAX __INT_FAST16_MAX__ +#define _PDCLIB_INT_FAST16_MIN _PDCLIB_MIN_CALC( __INT_FAST16_MAX__ ) +#define _PDCLIB_uint_fast16_t __UINT_FAST16_TYPE__ +#define _PDCLIB_UINT_FAST16_MAX __UINT_FAST16_MAX__ + +/* int_least16_t / uint_least16_t */ +#define _PDCLIB_int_least16_t __INT_LEAST16_TYPE__ +#define _PDCLIB_INT_LEAST16_MAX __INT_LEAST16_MAX__ +#define _PDCLIB_INT_LEAST16_MIN _PDCLIB_MIN_CALC( __INT_LEAST16_MAX__ ) +#define _PDCLIB_uint_least16_t __UINT_LEAST16_TYPE__ +#define _PDCLIB_UINT_LEAST16_MAX __UINT_LEAST16_MAX__ + +/* int_fast32_t / uint_fast32_t */ +#define _PDCLIB_int_fast32_t __INT_FAST32_TYPE__ +#define _PDCLIB_INT_FAST32_MAX __INT_FAST32_MAX__ +#define _PDCLIB_INT_FAST32_MIN _PDCLIB_MIN_CALC( __INT_FAST32_MAX__ ) +#define _PDCLIB_uint_fast32_t __UINT_FAST32_TYPE__ +#define _PDCLIB_UINT_FAST32_MAX __UINT_FAST32_MAX__ + +/* int_least32_t / uint_least32_t */ +#define _PDCLIB_int_least32_t __INT_LEAST32_TYPE__ +#define _PDCLIB_INT_LEAST32_MAX __INT_LEAST32_MAX__ +#define _PDCLIB_INT_LEAST32_MIN _PDCLIB_MIN_CALC( __INT_LEAST32_MAX__ ) +#define _PDCLIB_uint_least32_t __UINT_LEAST32_TYPE__ +#define _PDCLIB_UINT_LEAST32_MAX __UINT_LEAST32_MAX__ + +/* int_fast64_t / uint_fast64_t */ +#define _PDCLIB_int_fast64_t __INT_FAST64_TYPE__ +#define _PDCLIB_INT_FAST64_MAX __INT_FAST64_MAX__ +#define _PDCLIB_INT_FAST64_MIN _PDCLIB_MIN_CALC( __INT_FAST64_MAX__ ) +#define _PDCLIB_uint_fast64_t __UINT_FAST64_TYPE__ +#define _PDCLIB_UINT_FAST64_MAX __UINT_FAST64_MAX__ + +/* int_least64_t / uint_least64_t */ +#define _PDCLIB_int_least64_t __INT_LEAST64_TYPE__ +#define _PDCLIB_INT_LEAST64_MAX __INT_LEAST64_MAX__ +#define _PDCLIB_INT_LEAST64_MIN _PDCLIB_MIN_CALC( __INT_LEAST64_MAX__ ) +#define _PDCLIB_uint_least64_t __UINT_LEAST64_TYPE__ +#define _PDCLIB_UINT_LEAST64_MAX __UINT_LEAST64_MAX__ + +/* Exact-width integer types. These are *optional*. If your platform does not */ +/* support types of these exact widths in two's complement encoding, just */ +/* leave them undefined. */ +#define _PDCLIB_int8_t __INT8_TYPE__ +#define _PDCLIB_int16_t __INT16_TYPE__ +#define _PDCLIB_int32_t __INT32_TYPE__ +#define _PDCLIB_int64_t __INT64_TYPE__ +#define _PDCLIB_uint8_t __UINT8_TYPE__ +#define _PDCLIB_uint16_t __UINT16_TYPE__ +#define _PDCLIB_uint32_t __UINT32_TYPE__ +#define _PDCLIB_uint64_t __UINT64_TYPE__ + +/* INTn_C / UINTn_C macros to define int_leastN_t / uint_leastN_t literals. */ +#if defined( __INT8_C ) +/* GCC */ +#define _PDCLIB_INT_LEAST8_C __INT8_C +#define _PDCLIB_UINT_LEAST8_C __UINT8_C +#define _PDCLIB_INT_LEAST16_C __INT16_C +#define _PDCLIB_UINT_LEAST16_C __UINT16_C +#define _PDCLIB_INT_LEAST32_C __INT32_C +#define _PDCLIB_UINT_LEAST32_C __UINT32_C +#define _PDCLIB_INT_LEAST64_C __INT64_C +#define _PDCLIB_UINT_LEAST64_C __UINT64_C +#elif defined( __INT8_C_SUFFIX__ ) +/* Clang */ +#define _PDCLIB_INT_LEAST8_C(c) _PDCLIB_concat( c, __INT8_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST8_C(c) _PDCLIB_concat( c, __UINT8_C_SUFFIX__ ) +#define _PDCLIB_INT_LEAST16_C(c) _PDCLIB_concat( c, __INT16_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST16_C(c) _PDCLIB_concat( c, __UINT16_C_SUFFIX__ ) +#define _PDCLIB_INT_LEAST32_C(c) _PDCLIB_concat( c, __INT32_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST32_C(c) _PDCLIB_concat( c, __UINT32_C_SUFFIX__ ) +#define _PDCLIB_INT_LEAST64_C(c) _PDCLIB_concat( c, __INT64_C_SUFFIX__ ) +#define _PDCLIB_UINT_LEAST64_C(c) _PDCLIB_concat( c, __UINT64_C_SUFFIX__ ) +#else +#error Please create your own _PDCLIB_config.h. Using the existing one as-is will not work. (Unsupported *INTn_C macros.) +#endif + +/* 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; +}; + +/* -------------------------------------------------------------------------- */ +/* What follows are a couple of "special" typedefs and their limits. */ +/* -------------------------------------------------------------------------- */ + +/* The result type of substracting two pointers */ +#define _PDCLIB_ptrdiff_t __PTRDIFF_TYPE__ +#define _PDCLIB_PTRDIFF_MAX __PTRDIFF_MAX__ +#define _PDCLIB_PTRDIFF_MIN _PDCLIB_MIN_CALC( __PTRDIFF_MAX__ ) + +/* An integer type that can be accessed as atomic entity (think asynchronous */ +/* interrupts). In a freestanding environment, the type itself need not be */ +/* defined, but its limits must. (Don't ask.) GCC is so kind to predefine it, */ +/* but clang is only giving us its MAX value, so we use that to identify the */ +/* type in _PDCLIB_int.h if the type definition is unavailable. */ +#ifdef __SIG_ATOMIC_TYPE__ +#define _PDCLIB_sig_atomic_t __SIG_ATOMIC_TYPE__ +#endif +#define _PDCLIB_SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ +#define _PDCLIB_SIG_ATOMIC_MIN _PDCLIB_MIN_CALC( __SIG_ATOMIC_MAX__ ) + +/* Result type of the 'sizeof' operator (must be unsigned). */ +/* Note: In , this is taken as the base for RSIZE_MAX, the limit */ +/* for the bounds-checking interfaces of Annex K. The recommendation by the */ +/* standard is to use ( SIZE_MAX >> 1 ) when "targeting machines with large */ +/* addess spaces", whereas small address spaces should use SIZE_MAX directly. */ +#define _PDCLIB_size_t __SIZE_TYPE__ +#define _PDCLIB_SIZE_MAX __SIZE_MAX__ + +/* Large enough an integer to hold all character codes of the widest */ +/* supported locale. */ +#define _PDCLIB_wchar_t __WCHAR_TYPE__ +#define _PDCLIB_WCHAR_MAX __WCHAR_MAX__ +#define _PDCLIB_WCHAR_MIN __WCHAR_MIN__ + +/* Large enough an integer to hold all character codes of the widest */ +/* supported locale plus WEOF (which needs not to be equal to EOF, nor needs */ +/* to be of negative value). */ +#define _PDCLIB_wint_t __WINT_TYPE__ +#define _PDCLIB_WINT_MAX __WINT_MAX__ +#define _PDCLIB_WINT_MIN __WINT_MIN__ + +/* Integer types capable of taking the (cast) value of a void *, and having */ +/* the value cast back to void *, comparing equal to the original. */ +#define _PDCLIB_intptr_t __INTPTR_TYPE__ +#define _PDCLIB_INTPTR_MAX __INTPTR_MAX__ +#define _PDCLIB_INTPTR_MIN _PDCLIB_MIN_CALC( __INTPTR_MAX__ ) +#define _PDCLIB_uintptr_t __UINTPTR_TYPE__ +#define _PDCLIB_UINTPTR_MAX __UINTPTR_MAX__ + +/* Largest supported integer type. Implementation note: see _PDCLIB_atomax(). */ +#define _PDCLIB_intmax_t __INTMAX_TYPE__ +#define _PDCLIB_INTMAX_MAX __INTMAX_MAX__ +#define _PDCLIB_INTMAX_MIN _PDCLIB_MIN_CALC( __INTMAX_MAX__ ) +#define _PDCLIB_INTMAX_C __INTMAX_C +#define _PDCLIB_uintmax_t __UINTMAX_TYPE__ +#define _PDCLIB_UINTMAX_MAX __UINTMAX_MAX__ +#define _PDCLIB_UINTMAX_C __UINTMAX_C + +/* defines imaxdiv(), which is equivalent to the div() function */ +/* family (see further above) with intmax_t as basis. */ +struct _PDCLIB_imaxdiv_t +{ + _PDCLIB_intmax_t quot; + _PDCLIB_intmax_t rem; +}; + +/* -------------------------------------------------------------------------- */ +/* Time types, limits, constants, and paths */ +/* -------------------------------------------------------------------------- */ + +/* _PDCLIB_time is the type for type_t; _PDCLIB_clock for clock_t. Both types */ +/* are defined as "real types capable of representing times". The "range and */ +/* precision of times representable" is implementation-defined. */ + +/* For clock_t, the standard defines that dividing the result of clock() by */ +/* CLOCKS_PER_SEC gives the seconds elapsed. */ +#ifdef __CYGWIN__ +#define _PDCLIB_clock_t unsigned long +#else +#define _PDCLIB_clock_t long +#endif +#define _PDCLIB_CLOCKS_PER_SEC 1000000 + +/* For time_t, no such divider exists. Most implementations use a count of */ +/* seconds since a specified epoch. While PDCLib really should support other */ +/* encodings as well, for now "count of seconds" is the only supported one. */ +/* MIN / MAX values for time_t are not required by the standard (and they are */ +/* not "exported" from the _PDCLIB namespace), but they are useful in support */ +/* of the _tzcode implementation. */ +#ifdef __MINGW64__ +#define _PDCLIB_time_t long long +#define _PDCLIB_TIME_MAX __LONG_LONG_MAX__ +#define _PDCLIB_TIME_MIN _PDCLIB_MIN_CALC( __LONG_LONG_MAX__ ) +#else +#define _PDCLIB_time_t long +#define _PDCLIB_TIME_MAX __LONG_MAX__ +#define _PDCLIB_TIME_MIN _PDCLIB_MIN_CALC( __LONG_MAX__ ) +#endif + +/* "Unix time" uses 1970-01-01T00:00:00 as "epoch". If your system uses a */ +/* different "zero point" for its timestamps, set this to the offset between */ +/* your epoch and Unix epoch. (For example, NTP uses 1900-01-01T00:00:00 as */ +/* epoch, giving an offset of (70 * 365 + 17) * 86400 = 220898800 seconds.) */ +#define _PDCLIB_EPOCH_BIAS INT64_C( 0 ) + +/* Leave this alone for now. */ +#define _PDCLIB_TIME_UTC 1 + +/* Path to TZ data. */ +/* IMPORTANT: *Must* end with separator character! */ +/* It does make it much easier for the time data handling code if this detail */ +/* can be relied upon and need not be handled in code. */ +#define _PDCLIB_TZDIR "/usr/share/zoneinfo/" + +/* Path to default (local) timezone */ +#define _PDCLIB_TZDEFAULT "/etc/localtime" + +/* -------------------------------------------------------------------------- */ +/* 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 + +/* Check for explanations on each of these values. */ +#define _PDCLIB_FLT_EVAL_METHOD __FLT_EVAL_METHOD__ + +#define _PDCLIB_FLT_HAS_SUBNORM __FLT_HAS_DENORM__ +#define _PDCLIB_DBL_HAS_SUBNORM __DBL_HAS_DENORM__ +#define _PDCLIB_LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__ + +#define _PDCLIB_FLT_RADIX __FLT_RADIX__ + +#define _PDCLIB_FLT_MANT_DIG __FLT_MANT_DIG__ +#define _PDCLIB_DBL_MANT_DIG __DBL_MANT_DIG__ +#define _PDCLIB_LDBL_MANT_DIG __LDBL_MANT_DIG__ + +#define _PDCLIB_FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__ +#define _PDCLIB_DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ +#define _PDCLIB_LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__ + +#define _PDCLIB_DECIMAL_DIG __DECIMAL_DIG__ + +#define _PDCLIB_FLT_DIG __FLT_DIG__ +#define _PDCLIB_DBL_DIG __DBL_DIG__ +#define _PDCLIB_LDBL_DIG __LDBL_DIG__ + +#define _PDCLIB_FLT_MIN_EXP __FLT_MIN_EXP__ +#define _PDCLIB_DBL_MIN_EXP __DBL_MIN_EXP__ +#define _PDCLIB_LDBL_MIN_EXP __LDBL_MIN_EXP__ + +#define _PDCLIB_FLT_MIN_10_EXP __FLT_MIN_10_EXP__ +#define _PDCLIB_DBL_MIN_10_EXP __DBL_MIN_10_EXP__ +#define _PDCLIB_LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ + +#define _PDCLIB_FLT_MAX_EXP __FLT_MAX_EXP__ +#define _PDCLIB_DBL_MAX_EXP __DBL_MAX_EXP__ +#define _PDCLIB_LDBL_MAX_EXP __LDBL_MAX_EXP__ + +#define _PDCLIB_FLT_MAX_10_EXP __FLT_MAX_10_EXP__ +#define _PDCLIB_DBL_MAX_10_EXP __DBL_MAX_10_EXP__ +#define _PDCLIB_LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ + +#define _PDCLIB_FLT_MAX __FLT_MAX__ +#define _PDCLIB_DBL_MAX __DBL_MAX__ +#define _PDCLIB_LDBL_MAX __LDBL_MAX__ + +#define _PDCLIB_FLT_EPSILON __FLT_EPSILON__ +#define _PDCLIB_DBL_EPSILON __DBL_EPSILON__ +#define _PDCLIB_LDBL_EPSILON __LDBL_EPSILON__ + +#define _PDCLIB_FLT_MIN __FLT_MIN__ +#define _PDCLIB_DBL_MIN __DBL_MIN__ +#define _PDCLIB_LDBL_MIN __LDBL_MIN__ + +#define _PDCLIB_FLT_TRUE_MIN __FLT_DENORM_MIN__ +#define _PDCLIB_DBL_TRUE_MIN __DBL_DENORM_MIN__ +#define _PDCLIB_LDBL_TRUE_MIN __LDBL_DENORM_MIN__ + +/* Macros for deconstructing floating point values */ +/* This assumes that the floating point value has been memcpy'd into an array */ +/* of _PDCLIB_bigint_digit_t (see _PDCLIB_bigint_from_*dbl.c with the array */ +/* passed to the macro as parameter. */ +#define _PDCLIB_FLT_SIGN( data ) ( ( data[1] & 0x8000 ) >> 15 ) +#define _PDCLIB_FLT_EXP( data ) ( ( data[1] & 0x7f80 ) >> 7 ) +#define _PDCLIB_FLT_SIZE( data ) ( data[1] &= 0x007f, 2 ) + +#define _PDCLIB_DBL_SIGN( data ) ( ( data[3] & 0x8000 ) >> 15 ) +#define _PDCLIB_DBL_EXP( data ) ( ( data[3] & 0x7ff0u ) >> 4 ) +#define _PDCLIB_DBL_SIZE( data ) ( data[3] &= 0x000fu, 4 ) + +/* Most platforms today use IEEE 754 single precision for 'float', and double */ +/* precision for 'double'. But type 'long double' varies. We use what the */ +/* compiler states about LDBL_MANT_DIG to determine the type. */ +#if _PDCLIB_LDBL_MANT_DIG == 64 + +/* Intel "Extended Precision" format, using 80 bits (64bit mantissa) */ +#define _PDCLIB_LDBL_SIGN( data ) ( ( data[4] & 0x8000u ) >> 15 ) +#define _PDCLIB_LDBL_EXP( data ) ( data[4] & 0x7fffu ) +#define _PDCLIB_LDBL_SIZE( data ) ( data[3] &= 0x7fffu, 4 ) + +#elif _PDCLIB_LDBL_MANT_DIG == 113 + +/* IEEE "Quadruple Precision" format, using 128 bits (113bit mantissa) */ +#define _PDCLIB_LDBL_SIGN( data ) ( ( data[7] & 0x8000u ) >> 15 ) +#define _PDCLIB_LDBL_EXP( data ) ( data[7] & 0x7fffu ) +#define _PDCLIB_LDBL_SIZE( data ) 7 + +#else + +/* IEEE "Double Precision" format, using 64 bits (53bit mantissa) */ +/* (Same as DBL above) */ +#define _PDCLIB_LDBL_SIGN( data ) ( ( data[3] & 0x8000 ) >> 15 ) +#define _PDCLIB_LDBL_EXP( data ) ( ( data[3] & 0x7ff0u ) >> 4 ) +#define _PDCLIB_LDBL_SIZE( data ) ( data[3] &= 0x000fu, 4 ) + +#endif + +/* Given the definitions for *_MANT_START above, which resolve to "pointer + to most dignificant byte of mantissa", the operand to use to get at the + less significant bytes. (That would be - for i386, x86_64, and ARM.) +*/ +#define _PDCLIB_FLT_OP - + +/* -------------------------------------------------------------------------- */ +/* Big Integer Arithmetic */ +/* -------------------------------------------------------------------------- */ +/* In support of the floating point converstions required by printf() etc., */ +/* PDCLib provides rudimentary big integer arithmetics. The _PDCLIB_bigint_t */ +/* type stores values in a sequence of integer "digits", which may be of any */ +/* uint_leastN_t type with N being 32 or 16. Note that multiplication and */ +/* division require the help of the next larger type. So set the define to */ +/* 32 if efficient 64bit integer arithmetics are available on your platform, */ +/* and to 16 otherwise. */ +/* (The value range of _PDCLIB_bigint_t is not affected by this setting.) */ + +#define _PDCLIB_BIGINT_DIGIT_BITS 16 + +/* -------------------------------------------------------------------------- */ +/* 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__ ) || defined( __ARM_NEON ) + +/* 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 _PDCLIB_config.h. Using the existing one as-is will not work. (Unsupported varargs.) + +#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 _PDCLIB_glue.h. */ +/* -------------------------------------------------------------------------- */ + +/* I/O ---------------------------------------------------------------------- */ + +/* The type of the file descriptor returned by _PDCLIB_open(), i.e. whatever */ +/* the underlying kernel uses for stream identification. */ +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 guarantees can opened */ +/* simultaneously. Must be at least 8. Depends largely on how the platform */ +/* does the bookkeeping in whatever is called by _PDCLIB_open(). PDCLib puts */ +/* no further limits on the number of open files other than 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 52 + +/* 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, you should 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); PDCLib supports larger values, but applications */ +/* relying on this would rely on implementation-defined behaviour (not good). */ +#define _PDCLIB_UNGETCBUFSIZE 1 + +/* The number of functions that can be registered with atexit(). Needs to be */ +/* at least 33 (32 guaranteed by the standard, plus _PDCLIB_closeall() which */ +/* is used internally by PDCLib to close all open streams). */ +/* TODO: Should expand dynamically. */ +#define _PDCLIB_ATEXIT_SLOTS 40 + +/* 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 of "translating" between errno values used by the hosting OS 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 'errno == EISDIR', and set '*_PDCLIB_errno_func() */ +/* = _PDCLIB_EPERM'. Anyone using PDCLib's will "see" EPERM instead */ +/* of EISDIR. */ +/* */ +/* 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, to avoid confusion. */ +/* auxiliary/errno/errno_readout.c provides a convenience program to read */ +/* those errno values mandated by the standard from a platform's , */ +/* giving output that can readily be pasted here. */ +/* Either way, note that the list below, the list in PDCLib's , and */ +/* the list in _PDCLIB_stdinit.h, need to be kept in sync. */ +/* */ +/* The values below are read from a Linux system. */ + +/* Argument list too long */ +#define _PDCLIB_E2BIG 7 +/* Permission denied */ +#define _PDCLIB_EACCES 13 +/* Address in use */ +#define _PDCLIB_EADDRINUSE 98 +/* Address not available */ +#define _PDCLIB_EADDRNOTAVAIL 99 +/* Address family not supported */ +#define _PDCLIB_EAFNOSUPPORT 97 +/* Resource unavailable, try again */ +#define _PDCLIB_EAGAIN 11 +/* Connection already in progress */ +#define _PDCLIB_EALREADY 114 +/* Bad file descriptor */ +#define _PDCLIB_EBADF 9 +/* Bad message */ +#define _PDCLIB_EBADMSG 74 +/* Device or resource busy */ +#define _PDCLIB_EBUSY 16 +/* Operation canceled */ +#define _PDCLIB_ECANCELED 125 +/* No child processes */ +#define _PDCLIB_ECHILD 10 +/* Connection aborted */ +#define _PDCLIB_ECONNABORTED 103 +/* Connection refused */ +#define _PDCLIB_ECONNREFUSED 111 +/* Connection reset */ +#define _PDCLIB_ECONNRESET 104 +/* Resource deadlock would occur */ +#define _PDCLIB_EDEADLK 35 +/* Destination address required */ +#define _PDCLIB_EDESTADDRREQ 89 +/* Mathematics argument out of domain of function */ +#define _PDCLIB_EDOM 33 +/* File exists */ +#define _PDCLIB_EEXIST 17 +/* Bad address */ +#define _PDCLIB_EFAULT 14 +/* File too large */ +#define _PDCLIB_EFBIG 27 +/* Host is unreachable */ +#define _PDCLIB_EHOSTUNREACH 113 +/* Identifier removed */ +#define _PDCLIB_EIDRM 43 +/* Illegal byte sequence */ +#define _PDCLIB_EILSEQ 84 +/* Operation in progress */ +#define _PDCLIB_EINPROGRESS 115 +/* Interrupted function */ +#define _PDCLIB_EINTR 4 +/* Invalid argument */ +#define _PDCLIB_EINVAL 22 +/* I/O error */ +#define _PDCLIB_EIO 5 +/* Socket is connected */ +#define _PDCLIB_EISCONN 106 +/* Is a directory */ +#define _PDCLIB_EISDIR 21 +/* Too many levels of symbolic links */ +#define _PDCLIB_ELOOP 40 +/* File descriptor value too large */ +#define _PDCLIB_EMFILE 24 +/* Too many links */ +#define _PDCLIB_EMLINK 31 +/* Message too large */ +#define _PDCLIB_EMSGSIZE 90 +/* Filename too long */ +#define _PDCLIB_ENAMETOOLONG 36 +/* Network is down */ +#define _PDCLIB_ENETDOWN 100 +/* Connection aborted by network */ +#define _PDCLIB_ENETRESET 102 +/* Network unreachable */ +#define _PDCLIB_ENETUNREACH 101 +/* Too many files open in system */ +#define _PDCLIB_ENFILE 23 +/* No buffer space available */ +#define _PDCLIB_ENOBUFS 105 +/* No message is available on the STREAM head read queue */ +#define _PDCLIB_ENODATA 61 +/* No such device */ +#define _PDCLIB_ENODEV 19 +/* No such file or directory */ +#define _PDCLIB_ENOENT 2 +/* Executable file format error */ +#define _PDCLIB_ENOEXEC 8 +/* No locks available */ +#define _PDCLIB_ENOLCK 37 +/* Link has been severed */ +#define _PDCLIB_ENOLINK 67 +/* Not enough space */ +#define _PDCLIB_ENOMEM 12 +/* No message of the desired type */ +#define _PDCLIB_ENOMSG 42 +/* Protocol not available */ +#define _PDCLIB_ENOPROTOOPT 92 +/* No space left on device */ +#define _PDCLIB_ENOSPC 28 +/* No STREAM resources */ +#define _PDCLIB_ENOSR 63 +/* Not a STREAM */ +#define _PDCLIB_ENOSTR 60 +/* Function not supported */ +#define _PDCLIB_ENOSYS 38 +/* The socket is not connected */ +#define _PDCLIB_ENOTCONN 107 +/* Not a directory */ +#define _PDCLIB_ENOTDIR 20 +/* Directory not empty */ +#define _PDCLIB_ENOTEMPTY 39 +/* State not recoverable */ +#define _PDCLIB_ENOTRECOVERABLE 131 +/* Not a socket */ +#define _PDCLIB_ENOTSOCK 88 +/* Not supported */ +#define _PDCLIB_ENOTSUP 95 +/* Inappropriate I/O control operation */ +#define _PDCLIB_ENOTTY 25 +/* No such device or address */ +#define _PDCLIB_ENXIO 6 +/* Operation not supported on socket */ +#define _PDCLIB_EOPNOTSUPP 95 +/* Value too large to be stored in data type */ +#define _PDCLIB_EOVERFLOW 75 +/* Previous owner died */ +#define _PDCLIB_EOWNERDEAD 130 +/* Operation not permitted */ +#define _PDCLIB_EPERM 1 +/* Broken pipe */ +#define _PDCLIB_EPIPE 32 +/* Protocol error */ +#define _PDCLIB_EPROTO 71 +/* Protocol not supported */ +#define _PDCLIB_EPROTONOSUPPORT 93 +/* Protocol wrong type for socket */ +#define _PDCLIB_EPROTOTYPE 91 +/* Result too large */ +#define _PDCLIB_ERANGE 34 +/* Read-only file system */ +#define _PDCLIB_EROFS 30 +/* Invalid seek */ +#define _PDCLIB_ESPIPE 29 +/* No such process */ +#define _PDCLIB_ESRCH 3 +/* Stream ioctl() timeout */ +#define _PDCLIB_ETIME 62 +/* Connection timed out */ +#define _PDCLIB_ETIMEDOUT 110 +/* Text file busy */ +#define _PDCLIB_ETXTBSY 26 +/* Operation would block */ +#define _PDCLIB_EWOULDBLOCK 11 +/* Cross-device link */ +#define _PDCLIB_EXDEV 18 + +/* The highest defined errno value, plus one. 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.) */ +#define _PDCLIB_ERRNO_MAX 132 + +/* The error message used for unknown error codes (generated by errno_readout */ +/* for consistency between the 'holes' in the list of defined error messages */ +/* and the text generated by e.g. strerror() for out-of-range error values.) */ +#define _PDCLIB_EUNKNOWN_TEXT (char*)"unknown error" + +/* 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 + +/* threads ------------------------------------------------------------------ */ + +/* This is relying on underlying implementation to provide thread */ +/* support. */ +/* The problem here is we cannot just #include and access the */ +/* original definitions. The standard library must not drag identifiers into */ +/* the user's namespace, so we have to set our own definitions in the _PDCLIB */ +/* namespace. Which are, obviously, platform-specific. */ +/* If you do NOT want to provide threads support, define __STDC_NO_THREADS__ */ +/* to 1 and simply delete the threads.h header and the corresponding files in */ +/* functions/threads/. This makes PDCLib non-thread-safe (obviously), as the */ +/* safeguards against race conditions (e.g. in ) will be omitted. */ + +/* auxiliary/pthread/pthread_readout.c provides a convenience program to read */ +/* appropriate definitions from a platform's , giving output that */ +/* can be copy & pasted here. */ + +#define __STDC_NO_THREADS__ + +#ifndef __STDC_NO_THREADS__ + +typedef unsigned long int _PDCLIB_thrd_t; +typedef union { unsigned char _PDCLIB_cnd_t_data[ 48 ]; long long int _PDCLIB_cnd_t_align; } _PDCLIB_cnd_t; +#if defined( __arm__ ) || defined( __ARM_NEON ) +typedef union { unsigned char _PDCLIB_mtx_t_data[ 24 ]; long int _PDCLIB_mtx_t_align; } _PDCLIB_mtx_t; +#else +typedef union { unsigned char _PDCLIB_mtx_t_data[ 40 ]; long int _PDCLIB_mtx_t_align; } _PDCLIB_mtx_t; +#endif +typedef unsigned int _PDCLIB_tss_t; +typedef int _PDCLIB_once_flag; +#define _PDCLIB_ONCE_FLAG_INIT 0 +#define _PDCLIB_RECURSIVE_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +/* This one is actually hidden in , and only if __USE_POSIX is */ +/* defined prior to #include (PTHREAD_DESTRUCTOR_ITERATIONS). */ +#define _PDCLIB_TSS_DTOR_ITERATIONS 4 +/* The following are not made public in any header, but used internally for */ +/* interfacing with the pthread API. */ +typedef union { unsigned char _PDCLIB_cnd_attr_t_data[ 4 ]; int _PDCLIB_cnd_attr_t_align; } _PDCLIB_cnd_attr_t; +typedef union { unsigned char _PDCLIB_mtx_attr_t_data[ 4 ]; int _PDCLIB_mtx_attr_t_align; } _PDCLIB_mtx_attr_t; +#if defined( __arm__ ) || defined( __ARM_NEON ) +typedef union { unsigned char _PDCLIB_thrd_attr_t_data[ 36 ]; long int _PDCLIB_thrd_attr_t_align; } _PDCLIB_thrd_attr_t; +#else +typedef union { unsigned char _PDCLIB_thrd_attr_t_data[ 56 ]; long int _PDCLIB_thrd_attr_t_align; } _PDCLIB_thrd_attr_t; +#endif +/* Static initialization of recursive mutex. */ +#if defined( __arm__ ) || defined( __ARM_NEON ) +#define _PDCLIB_MTX_RECURSIVE_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +/* Static initialization of plain / timeout mutex (identical with pthread). */ +#define _PDCLIB_MTX_PLAIN_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +#else +#define _PDCLIB_MTX_RECURSIVE_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +/* Static initialization of plain / timeout mutex (identical with pthread). */ +#define _PDCLIB_MTX_PLAIN_INIT { {\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +#endif + +#endif + +/* Termux defines atexit in crtbegin_so.o leading to a multiple definition */ +/* error from the linker. This is a crude workaround, which does NOT fix */ +/* various run-time issues on Termux likely also related to crt linkage. But */ +/* at least things compile OK, and SOME tests can be run. */ +#if defined( __ARM_NEON ) +#define atexit _PDCLIB_atexit +#endif + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_defguard.h b/sysroot/usr/include/pdclib/_PDCLIB_defguard.h new file mode 100644 index 0000000..cd51abe --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_defguard.h @@ -0,0 +1,29 @@ +/* Definition guard <_PDCLIB_defguard.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_DEFGUARD_H +#define _PDCLIB_DEFGUARD_H _PDCLIB_DEFGUARD_H + +#if defined( __ANDROID__ ) +/* typedef sigset_t */ +#include "bits/signal_types.h" +#endif + +/* Linux defines its own version of struct timespec (from ) in + some internal header (depending on clib implementation), which leads + to problems when accessing e.g. sys/time.h (type redefinition). + The solution is to set the Linux header's include guard (to avoid + Linux' definition), and to include PDCLib's to define the + type unambiguously. +*/ + +#define _TIMESPEC_DEFINED +#define _SYS__TIMESPEC_H_ +#define _STRUCT_TIMESPEC + +#include + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_glue.h b/sysroot/usr/include/pdclib/_PDCLIB_glue.h new file mode 100644 index 0000000..3e59302 --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_glue.h @@ -0,0 +1,93 @@ +/* OS glue functions declaration <_PDCLIB_glue.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_GLUE_H +#define _PDCLIB_GLUE_H _PDCLIB_GLUE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.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 _PDCLIB_config.h. */ +/* -------------------------------------------------------------------------- */ + +/* stdlib.h */ + +/* A system call that terminates the calling process, returning a given status + to the environment. +*/ +_PDCLIB_LOCAL _PDCLIB_Noreturn void _PDCLIB_Exit( int status ) _PDCLIB_NORETURN; + + +/* 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_LOCAL _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. +*/ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL _PDCLIB_int_least64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int_least64_t offset, int whence ); + +/* A system call that closes a file identified by given file descriptor. Return + zero on success, non-zero otherwise. +*/ +_PDCLIB_LOCAL int _PDCLIB_close( _PDCLIB_fd_t fd ); + +/* A system call that changes the mode of a given stream to that passed as + argument (the argument being the value returned by _PDCLIB_filemode()), + *without* closing the stream. See comments in example implementation + for details. Return zero if the requested mode change is not supported + for this stream and freopen() should try to close and reopen the stream; + return INT_MIN if the change is not supported and freopen() should close + and NOT try to close / reopen (i.e., fail). Return any other value on + success. +*/ +_PDCLIB_LOCAL int _PDCLIB_changemode( struct _PDCLIB_file_t * stream, unsigned int mode ); + +/* A system call that returns a canonicalized absolute filename in + dynamically allocated memory, or NULL if the file does not exist. +*/ +_PDCLIB_LOCAL char * _PDCLIB_realpath( const char * path ); + +/* A system call that removes a file. Return zero on success, non-zero + otherwise. +*/ +_PDCLIB_LOCAL int _PDCLIB_remove( const char * pathname ); + +/* 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. +*/ +_PDCLIB_LOCAL int _PDCLIB_rename( const char * oldpath, const char * newpath ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_internal.h b/sysroot/usr/include/pdclib/_PDCLIB_internal.h new file mode 100644 index 0000000..1ad3c66 --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_internal.h @@ -0,0 +1,686 @@ +/* PDCLib internal logic <_PDCLIB_internal.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_INTERNAL_H +#define _PDCLIB_INTERNAL_H _PDCLIB_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------------------------------------------------------- */ +/* 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 "pdclib/_PDCLIB_config.h" + +/* -------------------------------------------------------------------------- */ +/* 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 + +#ifndef __STDC_HOSTED__ +#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)! +#elif __STDC_HOSTED__ != 0 && __STDC_HOSTED__ != 1 +#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)! +#endif + +/* null pointer constant -- ((void *)0) in C, 0 in C++98, nullptr since C++11 */ +#ifdef __cplusplus +#if __cplusplus >= 201103L +#define _PDCLIB_NULL nullptr +#else +#define _PDCLIB_NULL 0 +#endif +#else +#define _PDCLIB_NULL ((void *)0) +#endif + +/* restrict / inline enabled for C99 onward only */ +#if defined( __cplusplus ) || ! defined( __STDC_VERSION ) || __STDC_VERSION__ < 199901L +#define _PDCLIB_restrict +#define _PDCLIB_inline +#else +#define _PDCLIB_restrict restrict +#define _PDCLIB_inline inline +#endif + +/* noreturn enabled for C11 onward only */ +#if defined( __cplusplus ) && __cplusplus >= 201103L +#define _PDCLIB_Noreturn [[noreturn]] +#else +#if defined( __STDC_VERSION__ ) >= 201112L +#define _PDCLIB_Noreturn _Noreturn +#else +#define _PDCLIB_Noreturn +#endif +#endif + +/* -------------------------------------------------------------------------- */ +/* Helper macros: */ +/* */ +/* (defined in _PDCLIB_config.h) */ +/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending. */ +/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */ +/* */ +/* (defined below) */ +/* _PDCLIB_static_assert( e, m ) does a compile-time assertion of expression */ +/* e, with m as the failure message. */ +/* _PDCLIB_symbol2string( x ) turn symbol into string literal (by adding ""). */ +/* _PDCLIB_value2string( x ) expands a preprocessor token and turns it into a */ +/* string literal (by adding ""). */ +/* _PDCLIB_TYPE_SIGNED( type ) resolves to true if type is signed. */ +/* _PDCLIB_LOCK( mtx ) lock a mutex if library has threads support. */ +/* _PDCLIB_UNLOCK( mtx ) unlock a mutex if library has threads support. */ +/* _PDCLIB_CONSTRAINT_VIOLATION( e ) expand errno number e to parameter list */ +/* fit for Annex K constraint violation */ +/* handler. */ +/* _PDCLIB_Generic( f, fp ) expand to _PDCLIB_f, _PDCLIB_ff, _PDCLIB_fl */ +/* depending on fp being sizeof double, float, or */ +/* long double. */ +/* -------------------------------------------------------------------------- */ + +#define _PDCLIB_static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) } + +#define _PDCLIB_TYPE_SIGNED( type ) (((type) -1) < 0) + +#define _PDCLIB_symbol2string( x ) #x +#define _PDCLIB_value2string( x ) _PDCLIB_symbol2string( x ) + +#ifndef __STDC_NO_THREADS__ +#define _PDCLIB_LOCK( mtx ) mtx_lock( &mtx ) +#define _PDCLIB_UNLOCK( mtx ) mtx_unlock( &mtx ) +#else +#define _PDCLIB_LOCK( mtx ) +#define _PDCLIB_UNLOCK( mtx ) +#endif + +#define _PDCLIB_CONSTRAINT_VIOLATION( e ) _PDCLIB_lc_messages->errno_texts[e], NULL, e + +#define _PDCLIB_GETC( fh ) ( ( fh->ungetidx == 0 ) ? ( unsigned char )fh->buffer[ fh->bufidx++ ] : ( unsigned char )fh->ungetbuf[ --fh->ungetidx ] ) + +#define _PDCLIB_CHECKBUFFER( fh ) ( ( ( fh->bufidx == fh->bufend ) && ( fh->ungetidx == 0 ) ) ? _PDCLIB_fillbuffer( fh ) : 0 ) + +#define _PDCLIB_GENERIC( func, x ) ( ( sizeof( x ) == sizeof( double ) ) ? _PDCLIB_ ## func ## d( x ) : \ + ( sizeof( x ) == sizeof( float ) ) ? _PDCLIB_ ## func ## f( x ) : \ + ( _PDCLIB_ ## func ## l( x ) ) ) + +/* -------------------------------------------------------------------------- */ +/* Preparing the length modifiers used in . */ +/* -------------------------------------------------------------------------- */ + +/* We use the _MAX value as a proxy for the actual type here. That is crude + but the best we can do, cross-platform wise. + Identifying which type the leastN_t / fastN_t / intmax_t / intptr_t are + and providing the appropriate printf()/scanf() length modifier. +*/ + +#if _PDCLIB_INT_FAST8_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST8_PREFIX hh +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST8_PREFIX h +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST8_PREFIX +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST8_PREFIX l +#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST8_PREFIX ll +#else +#error No matching native type for int_fast8_t. Please check your setup. +#endif + +#if _PDCLIB_INT_FAST16_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST16_PREFIX hh +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST16_PREFIX h +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST16_PREFIX +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST16_PREFIX l +#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST16_PREFIX ll +#else +#error No matching native type for int_fast16_t. Please check your setup. +#endif + +#if _PDCLIB_INT_FAST32_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST32_PREFIX hh +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST32_PREFIX h +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST32_PREFIX +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST32_PREFIX l +#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST32_PREFIX ll +#else +#error No matching native type for int_fast32_t. Please check your setup. +#endif + +#if _PDCLIB_INT_FAST64_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_FAST64_PREFIX hh +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_FAST64_PREFIX h +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_FAST64_PREFIX +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_FAST64_PREFIX l +#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_FAST64_PREFIX ll +#else +#error No matching native type for int_fast64_t. Please check your setup. +#endif + +/* Many of the combinations below can very likely be ruled out logically. + All combinations are still listed for simplicity's sake (and to not fall + into the trap of false assumptions). +*/ + +#if _PDCLIB_INT_LEAST8_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST8_PREFIX hh +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST8_PREFIX h +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST8_PREFIX +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST8_PREFIX l +#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST8_PREFIX ll +#else +#error No matching native type for int_least8_t. Please check your setup. +#endif + +#if _PDCLIB_INT_LEAST16_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST16_PREFIX hh +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST16_PREFIX h +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST16_PREFIX +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST16_PREFIX l +#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST16_PREFIX ll +#else +#error No matching native type for int_least16_t. Please check your setup. +#endif + +#if _PDCLIB_INT_LEAST32_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST32_PREFIX hh +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST32_PREFIX h +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST32_PREFIX +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST32_PREFIX l +#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST32_PREFIX ll +#else +#error No matching native type for int_least32_t. Please check your setup. +#endif + +#if _PDCLIB_INT_LEAST64_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INT_LEAST64_PREFIX hh +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INT_LEAST64_PREFIX h +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INT_LEAST64_PREFIX +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INT_LEAST64_PREFIX l +#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INT_LEAST64_PREFIX ll +#else +#error No matching native type for int_least64_t. Please check your setup. +#endif + +#if _PDCLIB_INTMAX_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INTMAX_PREFIX hh +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INTMAX_PREFIX h +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INTMAX_PREFIX +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INTMAX_PREFIX l +#elif _PDCLIB_INTMAX_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INTMAX_PREFIX ll +#else +#error No matching native type for intmax_t. Please check your setup. +#endif + +#if _PDCLIB_INTPTR_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_INTPTR_PREFIX hh +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_INTPTR_PREFIX h +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_INTPTR_PREFIX +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_INTPTR_PREFIX l +#elif _PDCLIB_INTPTR_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_INTPTR_PREFIX ll +#else +#error No matching native type for intptr_t. Please check your setup. +#endif + +/* We might not have a type definition for sig_atomic_t at this point. The */ +/* clang compiler does not provide an appropriate predefine for it. So if we */ +/* do not have _PDCLIB_sig_atomic_t, identify the type trough its MAX value. */ + +#ifndef _PDCLIB_sig_atomic_t + +#if _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_SCHAR_MAX +#define _PDCLIB_sig_atomic_t char +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_SHRT_MAX +#define _PDCLIB_sig_atomic_t short +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_INT_MAX +#define _PDCLIB_sig_atomic_t int +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_LONG_MAX +#define _PDCLIB_sig_atomic_t long +#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_LLONG_MAX +#define _PDCLIB_sig_atomic_t long long +#else +#error No matching native type for sig_atomic_t. Please check your setup. +#endif + +#endif + +/* -------------------------------------------------------------------------- */ +/* 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 (1u<<3) +#define _PDCLIB_FWRITE (1u<<4) +#define _PDCLIB_FAPPEND (1u<<5) +#define _PDCLIB_FRW (1u<<6) +#define _PDCLIB_FBIN (1u<<7) + +/* Internal flags, made to fit the same status field as the flags above. */ +/* -------------------------------------------------------------------------- */ +/* free() the buffer memory on closing (setvbuf()) */ +#define _PDCLIB_FREEBUFFER (1u<<8) +/* stream has encountered error / EOF */ +#define _PDCLIB_ERRORFLAG (1u<<9) +#define _PDCLIB_EOFFLAG (1u<<10) +/* stream is wide-oriented */ +#define _PDCLIB_WIDESTREAM (1u<<11) +/* stream is byte-oriented */ +#define _PDCLIB_BYTESTREAM (1u<<12) +/* file associated with stream should be remove()d on closing (tmpfile()) */ +#define _PDCLIB_DELONCLOSE (1u<<13) + +/* Position / status structure for getpos() / fsetpos(). */ +struct _PDCLIB_fpos_t +{ + _PDCLIB_uint_least64_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 */ + _PDCLIB_size_t bufsize; /* Size of buffer */ + _PDCLIB_size_t bufidx; /* Index of current position in buffer */ + _PDCLIB_size_t bufend; /* Index of last pre-read character in buffer */ + struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */ + _PDCLIB_size_t ungetidx; /* Number of ungetc()'ed characters */ + unsigned char ungetbuf[_PDCLIB_UNGETCBUFSIZE]; /* ungetc() buffer */ + unsigned int status; /* Status flags; see above */ + /* multibyte parsing status to be added later */ +#ifndef __STDC_NO_THREADS__ + _PDCLIB_mtx_t mtx; /* Multithreading safety */ +#endif + char * filename; /* Name the current stream has been opened with */ + struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */ +}; + +/* -------------------------------------------------------------------------- */ +/* 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 ); +}; + +/* Status structure required by _PDCLIB_print(). */ +struct _PDCLIB_status_t +{ + int base; /* base to which the value shall be converted */ + _PDCLIB_int_fast32_t flags; /* flags and length modifiers */ + _PDCLIB_size_t n; /* print: maximum characters to be written */ + /* scan: number matched conversion specifiers */ + _PDCLIB_size_t i; /* number of characters read/written */ + _PDCLIB_size_t current;/* chars read/written in the CURRENT conversion */ + char * s; /* *sprintf(): target buffer */ + /* *sscanf(): source string */ + _PDCLIB_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(). */ +_PDCLIB_LOCAL _PDCLIB_intmax_t _PDCLIB_atomax( const char * s ); + +/* Two helper functions used by strtol(), strtoul() and long long variants. */ +_PDCLIB_LOCAL const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base ); +_PDCLIB_LOCAL _PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, _PDCLIB_uintmax_t error, _PDCLIB_uintmax_t limit, char * sign ); + +/* Helper function used by strtof(), strtod(), and strtold(). */ +_PDCLIB_LOCAL int _PDCLIB_strtod_prelim( const char * p, char * sign, char ** endptr ); + +/* 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. +*/ +_PDCLIB_LOCAL 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 +*/ +_PDCLIB_LOCAL const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ); + +/* Parsing any fopen() style filemode string into a number of flags. */ +_PDCLIB_LOCAL unsigned int _PDCLIB_filemode( const char * mode ); + +/* Initialize a FILE structure. If the parameter is NULL, a new FILE structure + is malloc'ed. Returns a pointer to the stream if successful, NULL otherwise. +*/ +_PDCLIB_LOCAL struct _PDCLIB_file_t * _PDCLIB_init_file_t( struct _PDCLIB_file_t * stream ); + +/* 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. +*/ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream ); + +/* Closing all streams on program exit */ +_PDCLIB_LOCAL void _PDCLIB_closeall( void ); + +/* Check if a given year is a leap year. Parameter is offset to 1900. */ +_PDCLIB_LOCAL 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. +*/ +_PDCLIB_LOCAL char * _PDCLIB_load_lines( struct _PDCLIB_file_t * stream, _PDCLIB_size_t lines ); + +/* Returns the (locale dependent) error message associated with the argument + errno value. +*/ +_PDCLIB_LOCAL char * _PDCLIB_geterrtext( int errnum ); + +/* Returns non-zero if the given stream is on the internal list of open files, + zero otherwise. Sets the second paramenter (if not NULL) to the previous + stream on the list (or NULL if the given stream is the first on the list). + This function does not lock _PDCLIB_filelist_mtx, this needs to be done by + the calling function (_PDCLIB_getstream() or freopen()). +*/ +_PDCLIB_LOCAL int _PDCLIB_isstream( struct _PDCLIB_file_t * stream, struct _PDCLIB_file_t ** previous ); + +/* Removes the given stream from the internal list of open files. Returns zero + if successful, non-zero otherwise. In case of error, sets errno to EBADF. + This function does not lock _PDCLIB_filelist_mtx, this needs to be done by + the calling function (fclose()). +*/ +_PDCLIB_LOCAL int _PDCLIB_getstream( struct _PDCLIB_file_t * stream ); + +/* Backend for strtok and strtok_s (plus potential extensions like strtok_r). */ +_PDCLIB_LOCAL char * _PDCLIB_strtok( char * _PDCLIB_restrict s1, _PDCLIB_size_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr ); + +/* Conversion of exponent notation to floating point */ +_PDCLIB_LOCAL long double _PDCLIB_naive_etod( const char * s, char ** endptr ); + +/* Conversion of hexadecimal notation to floating point */ +_PDCLIB_LOCAL long double _PDCLIB_naive_ptod( const char * s, char ** endptr ); + +/* -------------------------------------------------------------------------- */ +/* Declaration of math helper functions (implemented in functions/math). */ +/* -------------------------------------------------------------------------- */ + +int _PDCLIB_isnand( double x ); +int _PDCLIB_isnanf( float x ); +int _PDCLIB_isnanl( long double x ); + +int _PDCLIB_isinfd( double x ); +int _PDCLIB_isinff( float x ); +int _PDCLIB_isinfl( long double x ); + +int _PDCLIB_signbitd( double x ); +int _PDCLIB_signbitf( float x ); +int _PDCLIB_signbitl( long double x ); + +int _PDCLIB_isfinited( double x ); +int _PDCLIB_isfinitef( float x ); +int _PDCLIB_isfinitel( long double x ); + +int _PDCLIB_isnormald( double x ); +int _PDCLIB_isnormalf( float x ); +int _PDCLIB_isnormall( long double x ); + +int _PDCLIB_fpclassifyd( double x ); +int _PDCLIB_fpclassifyf( float x ); +int _PDCLIB_fpclassifyl( long double x ); + +/* -------------------------------------------------------------------------- */ +/* errno */ +/* -------------------------------------------------------------------------- */ + +/* A mechanism for delayed evaluation. + 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 . +*/ +_PDCLIB_PUBLIC 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 << _PDCLIB_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_C; +extern struct _PDCLIB_lc_collate_t * _PDCLIB_lc_collate; + +/* One entry to the _PDCLIB_lc_ctype_t.entry data table */ +struct _PDCLIB_lc_ctype_entry_t +{ + _PDCLIB_uint_least16_t flags; /* Whether a character is of a given CTYPE */ + unsigned char upper; /* Result for toupper() */ + unsigned char lower; /* Result for tolower() */ +}; + +struct _PDCLIB_lc_ctype_t +{ + int alloced; /* .entry dynamically allocated? */ + int digits_low; /* Where decimal digits start */ + int digits_high; /* Where decimal digits end */ + int Xdigits_low; /* Where A..F start */ + int Xdigits_high; /* Where A..F end */ + int xdigits_low; /* Where a..f start */ + int xdigits_high; /* Where a..f end */ + struct _PDCLIB_lc_ctype_entry_t * entry; /* The data table */ +}; + +extern struct _PDCLIB_lc_ctype_t _PDCLIB_lc_ctype_C; +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_C; +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_C; +extern struct _PDCLIB_lc_time_t * _PDCLIB_lc_time; + +_PDCLIB_LOCAL struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale ); +_PDCLIB_LOCAL struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale ); + +/* -------------------------------------------------------------------------- */ +/* Sanity checks */ +/* -------------------------------------------------------------------------- */ + +/* signed-ness of char */ +_PDCLIB_static_assert( _PDCLIB_CHAR_MIN == ((((char) -1) < 0) ? _PDCLIB_SCHAR_MIN : 0), "Compiler disagrees on signed-ness of 'char'." ); + +/* two's complement */ +#if _PDCLIB_TWOS_COMPLEMENT == 1 +#if _PDCLIB_CHAR_MIN < 0 +_PDCLIB_static_assert( ((char) ~ (char) 0 < 0), "Not two's complement on 'char'." ); +#endif +_PDCLIB_static_assert( ((short) ~ (short) 0 < 0), "Not two's complement on 'short'." ); +_PDCLIB_static_assert( ((int) ~ (int) 0 < 0), "Not two's complement on 'int'." ); +_PDCLIB_static_assert( ((long) ~ (long) 0 < 0), "Not two's complement on 'long'." ); +_PDCLIB_static_assert( ((long long) ~ (long long) 0 < 0), "Not two's complement on 'long long'." ); +#endif + +/* size_t as the result of sizeof */ +_PDCLIB_static_assert( sizeof( sizeof( int ) ) == sizeof( _PDCLIB_size_t ), "Compiler disagrees on size_t." ); + +/* wchar_t as the type of wide character literals */ +_PDCLIB_static_assert( sizeof( _PDCLIB_wchar_t ) == sizeof( L'x' ), "Compiler disagrees on wchar_t." ); +#ifdef __cplusplus +_PDCLIB_static_assert( sizeof( _PDCLIB_wchar_t ) == sizeof( wchar_t ), "Compiler disagrees on wchar_t (C++)." ); +#endif + +/* intptr_t/uintptr_t being wide enough to store the value of a pointer */ +_PDCLIB_static_assert( sizeof( void * ) == sizeof( _PDCLIB_intptr_t ), "Compiler disagrees on intptr_t." ); +_PDCLIB_static_assert( sizeof( void * ) == sizeof( _PDCLIB_uintptr_t ), "Compiler disagrees on uintptr_t." ); + +/* ptrdiff_t as the result of pointer arithmetic */ +_PDCLIB_static_assert( sizeof( &_PDCLIB_digits[1] - &_PDCLIB_digits[0] ) == sizeof( _PDCLIB_ptrdiff_t ), "Compiler disagrees on ptrdiff_t." ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_lib_ext1.h b/sysroot/usr/include/pdclib/_PDCLIB_lib_ext1.h new file mode 100644 index 0000000..fe96bca --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_lib_ext1.h @@ -0,0 +1,32 @@ +/* __STDC_WANT_LIB_EXT1__ redefinition guard + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef __STDC_WANT_LIB_EXT1__ + #ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__ + #if __STDC_WANT_LIB_EXT1_PREVIOUS__ != -1 + #error __STDC_WANT_LIB_EXT1__ undefined when it was defined earlier. + #endif + #else + #define __STDC_WANT_LIB_EXT1_PREVIOUS__ -1 + #endif +#else + #if ( __STDC_WANT_LIB_EXT1__ + 0 ) == 0 && ( 0 - __STDC_WANT_LIB_EXT1__ - 1 ) == 1 + #error __STDC_WANT_LIB_EXT1__ defined but empty. Should be an integer value. + #endif + #ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__ + #if ( __STDC_WANT_LIB_EXT1__ + 0 ) != __STDC_WANT_LIB_EXT1_PREVIOUS__ + #error __STDC_WANT_LIB_EXT1__ redefined from previous value. + #endif + #else + #if ( __STDC_WANT_LIB_EXT1__ + 0 ) == 0 + #define __STDC_WANT_LIB_EXT1_PREVIOUS__ 0 + #elif ( __STDC_WANT_LIB_EXT1__ + 0 ) == 1 + #define __STDC_WANT_LIB_EXT1_PREVIOUS__ 1 + #else + #error __STDC_WANT_LIB_EXT1__ set to value other than 0,1 -- undefined behavior + #endif + #endif +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_platform_errno.h b/sysroot/usr/include/pdclib/_PDCLIB_platform_errno.h new file mode 100644 index 0000000..04e4f3d --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_platform_errno.h @@ -0,0 +1,6 @@ +#ifndef _PDCLIB_PLATFORM_ERRNO +#define _PDCLIB_PLATFORM_ERRNO + +#include "errno.h" + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_platform_fcntl.h b/sysroot/usr/include/pdclib/_PDCLIB_platform_fcntl.h new file mode 100644 index 0000000..8c7c026 --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_platform_fcntl.h @@ -0,0 +1,6 @@ +#ifndef _PDCLIB_PLATFORM_FCNTL +#define _PDCLIB_PLATFORM_FCNTL + +#include "fcntl.h" + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_print.h b/sysroot/usr/include/pdclib/_PDCLIB_print.h new file mode 100644 index 0000000..015b0ff --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_print.h @@ -0,0 +1,145 @@ +/* PDCLib printf logic <_PDCLIB_print.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_PRINT_H +#define _PDCLIB_PRINT_H _PDCLIB_PRINT_H + +#include "pdclib/_PDCLIB_internal.h" + +#include +#include +#include + +/* 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 ) + + +/* Using an integer's bits as flags for both the conversion flags and length + modifiers. +*/ +#define E_minus (INT32_C(1)<<0) +#define E_plus (INT32_C(1)<<1) +#define E_alt (INT32_C(1)<<2) +#define E_space (INT32_C(1)<<3) + +#define E_zero (INT32_C(1)<<4) +#define E_done (INT32_C(1)<<5) +#define E_char (INT32_C(1)<<6) +#define E_short (INT32_C(1)<<7) + +#define E_long (INT32_C(1)<<8) +#define E_llong (INT32_C(1)<<9) +#define E_intmax (INT32_C(1)<<10) +#define E_size (INT32_C(1)<<11) + +#define E_ptrdiff (INT32_C(1)<<12) +#define E_pointer (INT32_C(1)<<13) +#define E_double (INT32_C(1)<<14) +#define E_ldouble (INT32_C(1)<<15) + +#define E_lower (INT32_C(1)<<16) +#define E_unsigned (INT32_C(1)<<17) +#define E_decimal (INT32_C(1)<<18) +#define E_exponent (INT32_C(1)<<19) + +#define E_generic (INT32_C(1)<<20) +#define E_hexa (INT32_C(1)<<21) + +/* -------------------------------------------------------------------------- */ +/* _PDCLIB_bigint_t support (required for floating point conversions) */ +/* -------------------------------------------------------------------------- */ + +/* Must be divisible by 32. */ +/* 1120 is enough for 64bit floats. A 128 float takes 16544 bits. */ +#define _PDCLIB_BIGINT_BITS 1120 + +#if _PDCLIB_BIGINT_DIGIT_BITS == 32 +#define _PDCLIB_BIGINT_DIGIT_MAX _PDCLIB_UINT_LEAST32_C( 0xFFFFFFFF ) +typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_digit_t; +typedef _PDCLIB_int_least32_t _PDCLIB_bigint_sdigit_t; +typedef _PDCLIB_uint_least64_t _PDCLIB_bigint_arith_t; +#elif _PDCLIB_BIGINT_DIGIT_BITS == 16 +#define _PDCLIB_BIGINT_DIGIT_MAX _PDCLIB_UINT_LEAST16_C( 0xFFFF ) +typedef _PDCLIB_uint_least16_t _PDCLIB_bigint_digit_t; +typedef _PDCLIB_int_least16_t _PDCLIB_bigint_sdigit_t; +typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_arith_t; +#else +#error _PDCLIB_BIGINT_DIGIT_BITS.needs to be 16 or 32. +#endif + +/* How many "digits" a _PDCLIB_bigint_t holds. */ +#define _PDCLIB_BIGINT_DIGITS _PDCLIB_BIGINT_BITS / _PDCLIB_BIGINT_DIGIT_BITS + +/* Maximum number of characters needed for _PDCLIB_bigint_tostring() */ +#define _PDCLIB_BIGINT_CHARS ( _PDCLIB_BIGINT_BITS / 4 + _PDCLIB_BIGINT_DIGITS + 2 ) + +/* Type */ +/* ---- */ + +typedef struct +{ + /* Number of digits used; zero value == zero size */ + _PDCLIB_size_t size; + /* Least significant digit first */ + _PDCLIB_bigint_digit_t data[ _PDCLIB_BIGINT_DIGITS ]; +} _PDCLIB_bigint_t; + +typedef struct +{ + _PDCLIB_bigint_t mantissa; + _PDCLIB_int_least16_t exponent; + _PDCLIB_int_least16_t scale; + enum + { + _PDCLIB_FP_NORMAL, + _PDCLIB_FP_SUBNORMAL, + _PDCLIB_FP_INF, + _PDCLIB_FP_NAN + } state; + char sign; +} _PDCLIB_fp_t; + +void _PDCLIB_fp_from_dbl( _PDCLIB_fp_t * fp, double value ); +void _PDCLIB_fp_from_ldbl( _PDCLIB_fp_t * fp, long double value ); + +void _PDCLIB_bigint_from_digit( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_digit_t digit ); +void _PDCLIB_bigint_from_pow2( _PDCLIB_bigint_t * bigint, unsigned pow ); +void _PDCLIB_bigint_from_pow10( _PDCLIB_bigint_t * bigint, unsigned pow ); +void _PDCLIB_bigint_from_bigint( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); +void _PDCLIB_bigint_add( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); +void _PDCLIB_bigint_mul( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); +void _PDCLIB_bigint_mul_pow10( _PDCLIB_bigint_t * bigint, int pow10 ); +int _PDCLIB_bigint_cmp( _PDCLIB_bigint_t const * lhs, _PDCLIB_bigint_t const * rhs ); +void _PDCLIB_bigint_shl( _PDCLIB_bigint_t * bigint, _PDCLIB_size_t bits ); +void _PDCLIB_bigint_mul10( _PDCLIB_bigint_t * bigint ); +int _PDCLIB_bigint_digit_log2( _PDCLIB_bigint_digit_t digit ); +int _PDCLIB_bigint_log2( _PDCLIB_bigint_t const * bigint ); +unsigned _PDCLIB_bigint_div( _PDCLIB_bigint_t * dividend, _PDCLIB_bigint_t const * divisor ); + +void _PDCLIB_print_integer( struct _PDCLIB_imaxdiv_t div, struct _PDCLIB_status_t * status ); +void _PDCLIB_print_string( const char * s, struct _PDCLIB_status_t * status ); +void _PDCLIB_print_fp( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status ); +int _PDCLIB_print_fp_deci( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer ); +void _PDCLIB_print_fp_hexa( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer ); +void _PDCLIB_print_fp_dragon4( _PDCLIB_bigint_t * fp, struct _PDCLIB_status_t * status ); + +#endif diff --git a/sysroot/usr/include/pdclib/_PDCLIB_tzcode.h b/sysroot/usr/include/pdclib/_PDCLIB_tzcode.h new file mode 100644 index 0000000..d12c4a7 --- /dev/null +++ b/sysroot/usr/include/pdclib/_PDCLIB_tzcode.h @@ -0,0 +1,153 @@ +/* TZ Code declarations and definitions <_PDCLIB_tzcode.h> + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_TZCODE_H +#define _PDCLIB_TZCODE_H _PDCLIB_TZCODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include + +/* Handy macros that are independent of tzfile implementation. */ +#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define AVGSECSPERYEAR 31556952L +#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR) +#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +extern struct tm _PDCLIB_tm; +extern int lcl_is_set; + +static const char gmt[] = "GMT"; + +static const int mon_lengths[ 2 ][ MONSPERYEAR ] = +{ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static const int year_lengths[2] = +{ + DAYSPERNYEAR, DAYSPERLYEAR +}; + +/* time type information */ +struct ttinfo +{ + int_fast32_t utoff; /* UT offset in seconds */ + bool isdst; /* used to set tm_isdst */ + int desigidx; /* abbreviation list index */ + bool ttisstd; /* transition is std time */ + bool ttisut; /* transition is UT */ +}; + +/* leap second information */ +struct lsinfo +{ + time_t trans; /* transition time */ + int_fast64_t corr; /* correction to apply */ +}; + +#define BIGGEST( a, b ) (((a) > (b)) ? (a) : (b)) + +#ifndef TZ_MAX_TIMES +#define TZ_MAX_TIMES 2000 +#endif + +#ifndef TZ_MAX_TYPES +/* This must be at least 17 for Europe/Vilnius. */ +/* Limited by what (unsigned char)s can hold */ +#define TZ_MAX_TYPES 256 +#endif + +#ifndef TZ_MAX_CHARS +/* Maximum number of abbreviation characters */ +/* Limited by what (unsigned char)s can hold */ +#define TZ_MAX_CHARS 50 +#endif + +#ifndef TZ_MAX_LEAPS +/* Maximum number of leap second corrections */ +#define TZ_MAX_LEAPS 50 +#endif + +#ifdef TZNAME_MAX +#define MY_TZNAME_MAX TZNAME_MAX +#else +#define MY_TZNAME_MAX 255 +#endif + +struct state +{ + int leapcnt; + int timecnt; + int typecnt; + int charcnt; + bool goback; + bool goahead; + time_t ats[ TZ_MAX_TIMES ]; + unsigned char types[ TZ_MAX_TIMES ]; + struct ttinfo ttis[ TZ_MAX_TYPES ]; + char chars[ BIGGEST( BIGGEST( TZ_MAX_CHARS + 1, sizeof gmt ), ( 2 * ( MY_TZNAME_MAX + 1 ) ) ) ]; + struct lsinfo lsis[ TZ_MAX_LEAPS ]; + + /* The time type to use for early times or if no transitions. + It is always zero for recent tzdb releases. + It might be nonzero for data from tzdb 2018e or earlier. + */ + int defaulttype; +}; + +extern struct state _PDCLIB_lclmem; +extern struct state _PDCLIB_gmtmem; + +void _PDCLIB_gmtcheck(void); +struct tm * _PDCLIB_gmtsub( struct state const * sp, time_t const * timep, int_fast32_t offset, struct tm * tmp ); +bool _PDCLIB_increment_overflow( int * ip, int j ); +void _PDCLIB_init_ttinfo( struct ttinfo * s, int_fast32_t utoff, bool isdst, int desigidx ); +struct tm * _PDCLIB_localsub( struct state const * sp, time_t const * timep, int_fast32_t setname, struct tm * const tmp ); +struct tm * _PDCLIB_localtime_tzset( time_t const * timep, struct tm * tmp, bool setname ); +time_t _PDCLIB_mktime_tzname( struct state * sp, struct tm * tmp, bool setname ); +struct tm * _PDCLIB_timesub( const time_t * timep, int_fast32_t offset, const struct state * sp, struct tm * tmp ); +int _PDCLIB_tzload( char const * name, struct state * sp, bool doextend ); +bool _PDCLIB_tzparse(char const *, struct state *, bool); +void _PDCLIB_tzset_unlocked( void ); +void _PDCLIB_update_tzname_etc( struct state const * sp, struct ttinfo const * ttisp ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/signal.h b/sysroot/usr/include/signal.h new file mode 100644 index 0000000..1f679ec --- /dev/null +++ b/sysroot/usr/include/signal.h @@ -0,0 +1,91 @@ +/* Signal handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_SIGNAL_H +#define _PDCLIB_SIGNAL_H _PDCLIB_SIGNAL_H + +#include "pdclib/_PDCLIB_internal.h" + +/* 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 + +/* 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 (void (*)( int ))0 +#define SIG_ERR (void (*)( int ))-1 +#define SIG_IGN (void (*)( int ))1 + +typedef _PDCLIB_sig_atomic_t sig_atomic_t; + +/* 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. +*/ +_PDCLIB_PUBLIC void ( *signal( int sig, void ( *func )( int ) ) )( int ); + +/* 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. */ +_PDCLIB_PUBLIC int raise( int sig ); + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_SIGNAL_H +#include _PDCLIB_EXTEND_SIGNAL_H +#endif + +#endif diff --git a/sysroot/usr/include/stdalign.h b/sysroot/usr/include/stdalign.h new file mode 100644 index 0000000..b302601 --- /dev/null +++ b/sysroot/usr/include/stdalign.h @@ -0,0 +1,30 @@ +/* Alignment + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDALIGN_H +#define _PDCLIB_STDALIGN_H _PDCLIB_STDALIGN_H + +#ifndef __cplusplus +#define __alignas_is_defined 1 +#define __alignof_is_defined 1 + +#if ! defined( __STDC_VERSION__ ) || ( __STDC_VERSION__ < 202311L ) +#define alignas _Alignas +#define alignof _Alignof +#elif __STDC_VERSION__ >= 202311L +#warning has been deprecated as of C23. +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDALIGN_H +#include _PDCLIB_EXTEND_STDALIGN_H +#endif + +#endif + diff --git a/sysroot/usr/include/stdarg.h b/sysroot/usr/include/stdarg.h new file mode 100644 index 0000000..7741b70 --- /dev/null +++ b/sysroot/usr/include/stdarg.h @@ -0,0 +1,34 @@ +/* Variable arguments + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDARG_H +#define _PDCLIB_STDARG_H _PDCLIB_STDARG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_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 ) + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDARG_H +#include _PDCLIB_EXTEND_STDARG_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/stdbool.h b/sysroot/usr/include/stdbool.h new file mode 100644 index 0000000..e901f63 --- /dev/null +++ b/sysroot/usr/include/stdbool.h @@ -0,0 +1,24 @@ +/* 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 _PDCLIB_STDBOOL_H +#define _PDCLIB_STDBOOL_H _PDCLIB_STDBOOL_H + +#ifndef __cplusplus +#define bool _Bool +#define true 1 +#define false 0 +#endif +#define __bool_true_false_are_defined 1 + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDBOOL_H +#include _PDCLIB_EXTEND_STDBOOL_H +#endif + +#endif diff --git a/sysroot/usr/include/stddef.h b/sysroot/usr/include/stddef.h new file mode 100644 index 0000000..7d03d07 --- /dev/null +++ b/sysroot/usr/include/stddef.h @@ -0,0 +1,55 @@ +/* Common definitions + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDDEF_H +#define _PDCLIB_STDDEF_H _PDCLIB_STDDEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +typedef _PDCLIB_ptrdiff_t ptrdiff_t; + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef __cplusplus +typedef _PDCLIB_wchar_t wchar_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +#define offsetof( type, member ) _PDCLIB_offsetof( type, member ) + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef size_t rsize_t; +#endif +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDDEF_H +#include _PDCLIB_EXTEND_STDDEF_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/stdint.h b/sysroot/usr/include/stdint.h new file mode 100644 index 0000000..04af6b0 --- /dev/null +++ b/sysroot/usr/include/stdint.h @@ -0,0 +1,236 @@ +/* Integer types + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDINT_H +#define _PDCLIB_STDINT_H _PDCLIB_STDINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +/* 7.18.1.1 Exact-width integer types. */ + +#ifdef _PDCLIB_int8_t +typedef _PDCLIB_int8_t int8_t; +typedef _PDCLIB_uint8_t uint8_t; +#endif + +#ifdef _PDCLIB_int16_t +typedef _PDCLIB_int16_t int16_t; +typedef _PDCLIB_uint16_t uint16_t; +#endif + +#ifdef _PDCLIB_int32_t +typedef _PDCLIB_int32_t int32_t; +typedef _PDCLIB_uint32_t uint32_t; +#endif + +#ifdef _PDCLIB_int64_t +typedef _PDCLIB_int64_t int64_t; +typedef _PDCLIB_uint64_t uint64_t; +#endif + +/* 7.18.1.2 Minimum-width integer types */ + +/* You are allowed to add more types here, e.g. int_least24_t. */ + +typedef _PDCLIB_int_least8_t int_least8_t; +typedef _PDCLIB_int_least16_t int_least16_t; +typedef _PDCLIB_int_least32_t int_least32_t; +typedef _PDCLIB_int_least64_t int_least64_t; + +typedef _PDCLIB_uint_least8_t uint_least8_t; +typedef _PDCLIB_uint_least16_t uint_least16_t; +typedef _PDCLIB_uint_least32_t uint_least32_t; +typedef _PDCLIB_uint_least64_t 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 _PDCLIB_int_fast8_t int_fast8_t; +typedef _PDCLIB_int_fast16_t int_fast16_t; +typedef _PDCLIB_int_fast32_t int_fast32_t; +typedef _PDCLIB_int_fast64_t int_fast64_t; + +typedef _PDCLIB_uint_fast8_t uint_fast8_t; +typedef _PDCLIB_uint_fast16_t uint_fast16_t; +typedef _PDCLIB_uint_fast32_t uint_fast32_t; +typedef _PDCLIB_uint_fast64_t uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +typedef _PDCLIB_intptr_t intptr_t; +typedef _PDCLIB_uintptr_t uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ + +typedef _PDCLIB_intmax_t intmax_t; +typedef _PDCLIB_uintmax_t uintmax_t; + +/* 7.18.2 Limits of specified-width integer types */ + +#if defined( __cplusplus ) && __cplusplus < 201103L +#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 */ + +#if _PDCLIB_TWOS_COMPLEMENT == 1 + +#if _PDCLIB_INT_LEAST8_MAX == 0x7f +#define INT8_MAX _PDCLIB_INT_LEAST8_MAX +#define INT8_MIN _PDCLIB_INT_LEAST8_MIN +#define UINT8_MAX _PDCLIB_UINT_LEAST8_MAX +#endif + +#if _PDCLIB_INT_LEAST16_MAX == 0x7fff +#define INT16_MAX _PDCLIB_INT_LEAST16_MAX +#define INT16_MIN _PDCLIB_INT_LEAST16_MIN +#define UINT16_MAX _PDCLIB_UINT_LEAST16_MAX +#endif + +#if _PDCLIB_INT_LEAST32_MAX == 0x7fffffffl +#define INT32_MAX _PDCLIB_INT_LEAST32_MAX +#define INT32_MIN _PDCLIB_INT_LEAST32_MIN +#define UINT32_MAX _PDCLIB_UINT_LEAST32_MAX +#endif + +#if _PDCLIB_INT_LEAST64_MAX == 0x7fffffffffffffffll +#define INT64_MAX _PDCLIB_INT_LEAST64_MAX +#define INT64_MIN _PDCLIB_INT_LEAST64_MIN +#define UINT64_MAX _PDCLIB_UINT_LEAST64_MAX +#endif + +#endif + +/* 7.18.2.2 Limits of minimum-width integer types */ + +#define INT_LEAST8_MIN _PDCLIB_INT_LEAST8_MIN +#define INT_LEAST8_MAX _PDCLIB_INT_LEAST8_MAX +#define UINT_LEAST8_MAX _PDCLIB_UINT_LEAST8_MAX + +#define INT_LEAST16_MIN _PDCLIB_INT_LEAST16_MIN +#define INT_LEAST16_MAX _PDCLIB_INT_LEAST16_MAX +#define UINT_LEAST16_MAX _PDCLIB_UINT_LEAST16_MAX + +#define INT_LEAST32_MIN _PDCLIB_INT_LEAST32_MIN +#define INT_LEAST32_MAX _PDCLIB_INT_LEAST32_MAX +#define UINT_LEAST32_MAX _PDCLIB_UINT_LEAST32_MAX + +#define INT_LEAST64_MIN _PDCLIB_INT_LEAST64_MIN +#define INT_LEAST64_MAX _PDCLIB_INT_LEAST64_MAX +#define UINT_LEAST64_MAX _PDCLIB_UINT_LEAST64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ + +#define INT_FAST8_MIN _PDCLIB_INT_FAST8_MIN +#define INT_FAST8_MAX _PDCLIB_INT_FAST8_MAX +#define UINT_FAST8_MAX _PDCLIB_UINT_FAST8_MAX + +#define INT_FAST16_MIN _PDCLIB_INT_FAST16_MIN +#define INT_FAST16_MAX _PDCLIB_INT_FAST16_MAX +#define UINT_FAST16_MAX _PDCLIB_UINT_FAST16_MAX + +#define INT_FAST32_MIN _PDCLIB_INT_FAST32_MIN +#define INT_FAST32_MAX _PDCLIB_INT_FAST32_MAX +#define UINT_FAST32_MAX _PDCLIB_UINT_FAST32_MAX + +#define INT_FAST64_MIN _PDCLIB_INT_FAST64_MIN +#define INT_FAST64_MAX _PDCLIB_INT_FAST64_MAX +#define UINT_FAST64_MAX _PDCLIB_UINT_FAST64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ + +#define INTPTR_MIN _PDCLIB_INTPTR_MIN +#define INTPTR_MAX _PDCLIB_INTPTR_MAX +#define UINTPTR_MAX _PDCLIB_UINTPTR_MAX + +/* 7.18.2.5 Limits of greatest-width integer types */ + +#define INTMAX_MIN _PDCLIB_INTMAX_MIN +#define INTMAX_MAX _PDCLIB_INTMAX_MAX +#define UINTMAX_MAX _PDCLIB_UINTMAX_MAX + +/* 7.18.3 Limits of other integer types */ + +#define PTRDIFF_MIN _PDCLIB_PTRDIFF_MIN +#define PTRDIFF_MAX _PDCLIB_PTRDIFF_MAX + +#define SIG_ATOMIC_MIN _PDCLIB_SIG_ATOMIC_MIN +#define SIG_ATOMIC_MAX _PDCLIB_SIG_ATOMIC_MAX + +#define SIZE_MAX _PDCLIB_SIZE_MAX + +#define WCHAR_MIN _PDCLIB_WCHAR_MIN +#define WCHAR_MAX _PDCLIB_WCHAR_MAX + +#define WINT_MIN _PDCLIB_WINT_MIN +#define WINT_MAX _PDCLIB_WINT_MAX + +#endif + +/* 7.18.4 Macros for integer constants */ + +#if defined( __cplusplus ) && __cplusplus < 201103L +#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 */ + +/* Expand to an integer constant of specified value and type int_leastN_t */ + +#define INT8_C _PDCLIB_INT_LEAST8_C +#define INT16_C _PDCLIB_INT_LEAST16_C +#define INT32_C _PDCLIB_INT_LEAST32_C +#define INT64_C _PDCLIB_INT_LEAST64_C + +/* Expand to an integer constant of specified value and type uint_leastN_t */ + +#define UINT8_C _PDCLIB_UINT_LEAST8_C +#define UINT16_C _PDCLIB_UINT_LEAST16_C +#define UINT32_C _PDCLIB_UINT_LEAST32_C +#define UINT64_C _PDCLIB_UINT_LEAST64_C + +/* 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_INTMAX_C( value ) + +/* Expand to an integer constant of specified value and type uintmax_t */ +#define UINTMAX_C( value ) _PDCLIB_UINTMAX_C( value ) + +#endif + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 +#define RSIZE_MAX ( _PDCLIB_SIZE_MAX >> 1 ) +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDINT_H +#include _PDCLIB_EXTEND_STDINT_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/stdio.h b/sysroot/usr/include/stdio.h new file mode 100644 index 0000000..4ee538f --- /dev/null +++ b/sysroot/usr/include/stdio.h @@ -0,0 +1,935 @@ +/* Input/output + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDIO_H +#define _PDCLIB_STDIO_H _PDCLIB_STDIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* See setvbuf(), third argument */ +#define _IOFBF (1u<<0) +#define _IOLBF (1u<<1) +#define _IONBF (1u<<2) + +/* The following are platform-dependent, and defined in _PDCLIB_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"). +*/ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC int rename( const char * oldpath, const char * newpath ); + +/* 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()). +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC FILE * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_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.) + + Returns a pointer to the stream handle if successfull, NULL otherwise. +*/ +_PDCLIB_PUBLIC FILE * freopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, FILE * _PDCLIB_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 ). +*/ +_PDCLIB_PUBLIC void setbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int setvbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int fprintf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int fscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fprintf( stdout, format, ... ). */ +_PDCLIB_PUBLIC int printf( const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fscanf( stdin, format, ... ). */ +_PDCLIB_PUBLIC int scanf( const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC int snprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fprintf( stdout, format, ... ), except that the result is + written into the buffer pointed to by s, instead of stdout. +*/ +_PDCLIB_PUBLIC int sprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... ); + +/* Equivalent to fscanf( stdin, format, ... ), except that the input is read + from the buffer pointed to by s, instead of stdin. +*/ +_PDCLIB_PUBLIC int sscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vfprintf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vprintf( const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vscanf( const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vsnprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vsprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_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 + . +*/ +_PDCLIB_PUBLIC int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC char * fgets( char * _PDCLIB_restrict s, int n, FILE * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int fputs( const char * _PDCLIB_restrict s, FILE * _PDCLIB_restrict stream ); + +/* Equivalent to fgetc( stream ), but may be overloaded by a macro that + evaluates its parameter more than once. +*/ +_PDCLIB_PUBLIC int getc( FILE * stream ); + +/* Equivalent to fgetc( stdin ). */ +_PDCLIB_PUBLIC int getchar( void ); + +/* Equivalent to fputc( c, stream ), but may be overloaded by a macro that + evaluates its parameter more than once. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC size_t fread( void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_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(). +*/ +_PDCLIB_PUBLIC int fgetpos( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC long int ftell( FILE * stream ); + +/* Equivalent to (void)fseek( stream, 0L, SEEK_SET ), except that the error + indicator for the stream is also cleared. +*/ +_PDCLIB_PUBLIC void rewind( FILE * stream ); + +/* Error-handling functions */ + +/* Clear the end-of-file and error indicators for the given stream. */ +_PDCLIB_PUBLIC void clearerr( FILE * stream ); + +/* Return zero if the end-of-file indicator for the given stream is not set, + nonzero otherwise. +*/ +_PDCLIB_PUBLIC int feof( FILE * stream ); + +/* Return zero if the error indicator for the given stream is not set, nonzero + otherwise. +*/ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC void perror( const char * s ); + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#define L_tmpnam_s _PDCLIB_L_tmpnam +#define TMP_MAX_S _PDCLIB_TMP_MAX + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef _PDCLIB_size_t rsize_t; +#endif + +/* 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()). + If successful, the FILE * pointed to by streamptr will be set to point at + the opened file handle, and the function returns zero. If unsuccessful, + the FILE * pointed to by streamptr will be set to NULL and a non-zero + value is returned. + The following conditions will be considered runtime constraint violations: + - streamptr being NULL. + In case of a constraint violation, no file is being created. + This implementation does not remove temporary files if the process aborts + abnormally (e.g. abort()). +*/ +_PDCLIB_PUBLIC errno_t tmpfile_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr ); + +/* Open the file with the given filename in the given mode, and sets the given + streamptr to point at the file handle for that file, 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. + + The following conditions will be considered runtime constraint violations: + - streamptr being NULL. + - filename being NULL. + - mode being NULL. + In case of a constraint violation, no file is opened. If streamptr is not + NULL, *streamptr is set to NULL. + + Returns zero if successful, non-zero otherwise. +*/ +_PDCLIB_PUBLIC errno_t fopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_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.) + + The following conditions will be considered runtime constraint violations: + - newstreamptr being NULL. + - mode being NULL. + - stream being NULL. + In case of a constraint violation, no attempt is made to close or open any + file. If newstreamptr is not NULL, *newstreamptr is set to NULL. + + Returns zero if successfull, non-zero otherwise. +*/ +_PDCLIB_PUBLIC errno_t freopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict newstreamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, FILE * _PDCLIB_restrict stream ); + +/* None of these are implemented yet. Placeholder declarations. */ +_PDCLIB_PUBLIC errno_t tmpnam_s( char * s, rsize_t maxsize ); +_PDCLIB_PUBLIC int fprintf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int fscanf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int printf_s( const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int scanf_s( const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int snprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int sprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int sscanf_s( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... ); +_PDCLIB_PUBLIC int vfprintf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vfscanf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vprintf_s( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vscanf_s( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vsnprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vsprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC int vsscanf_s( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ); +_PDCLIB_PUBLIC char * gets_s( char * s, rsize_t n ); + +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDIO_H +#include _PDCLIB_EXTEND_STDIO_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/stdlib.h b/sysroot/usr/include/stdlib.h new file mode 100644 index 0000000..9dc8b33 --- /dev/null +++ b/sysroot/usr/include/stdlib.h @@ -0,0 +1,379 @@ +/* General utilities + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDLIB_H +#define _PDCLIB_STDLIB_H _PDCLIB_STDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* Numeric conversion functions */ + +/* TODO: atof(), strtof(), strtod(), strtold() */ + +_PDCLIB_PUBLIC double atof( const char * nptr ); +_PDCLIB_PUBLIC double strtod( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr ); +_PDCLIB_PUBLIC float strtof( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr ); +_PDCLIB_PUBLIC long double strtold( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr ); + +/* Separate 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. +*/ +_PDCLIB_PUBLIC long int strtol( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC long long int strtoll( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC unsigned long int strtoul( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base ); +_PDCLIB_PUBLIC unsigned long long int strtoull( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_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.) +*/ +_PDCLIB_PUBLIC int atoi( const char * nptr ); +_PDCLIB_PUBLIC long int atol( const char * nptr ); +_PDCLIB_PUBLIC 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;) +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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(). +*/ +_PDCLIB_PUBLIC void * realloc( void * ptr, size_t size ); + +/* 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. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void abort( void ) _PDCLIB_NORETURN; + +/* Register a function that will be called on quick_exit(). + 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. +*/ +_PDCLIB_PUBLIC int at_quick_exit( void ( *func )( 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void exit( int status ) _PDCLIB_NORETURN; + +/* Normal process termination. Functions registered by at_quick_exit() (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.) + quick_exit() does not return. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void quick_exit( int status ) _PDCLIB_NORETURN; + +/* Normal process termination. Functions registered by atexit()/at_quick_exit() + (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. +*/ +_PDCLIB_PUBLIC _PDCLIB_Noreturn void _Exit( int status ) _PDCLIB_NORETURN; + +/* 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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 a matching element found, or NULL if no + match is found. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int abs( int j ); +_PDCLIB_PUBLIC long int labs( long int j ); +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC div_t div( int numer, int denom ); +_PDCLIB_PUBLIC ldiv_t ldiv( long int numer, long int denom ); +_PDCLIB_PUBLIC lldiv_t lldiv( long long int numer, long long int denom ); + +/* TODO: Multibyte / wide character conversion functions */ + +/* TODO: Macro MB_CUR_MAX */ + +/* +_PDCLIB_PUBLIC int mblen( const char * s, size_t n ); +_PDCLIB_PUBLIC int mbtowc( wchar_t * _PDCLIB_restrict pwc, const char * _PDCLIB_restrict s, size_t n ); +_PDCLIB_PUBLIC int wctomb( char * s, wchar_t wc ); +_PDCLIB_PUBLIC size_t mbstowcs( wchar_t * _PDCLIB_restrict pwcs, const char * _PDCLIB_restrict s, size_t n ); +_PDCLIB_PUBLIC size_t wcstombs( char * _PDCLIB_restrict s, const wchar_t * _PDCLIB_restrict pwcs, size_t n ); +*/ + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef size_t rsize_t; +#endif + +/* A function type that can serve as a constraint handler (see below). The + first parameter is an error message on the constraint violation, the + second parameter a pointer to an implementation-defined object, the + third an error code related to the constraint violation. + If the function calling the constraint handler is defined to return + errno_t, the third parameter will be identical to the return value of + that function. + This implementation sets the second parameter of the constraint handler + call to NULL. +*/ +typedef void ( *constraint_handler_t )( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ); + +/* The currently active constraint violation handler. This implementation + sets abort_handler_s as the default constraint violation handler. +*/ +extern constraint_handler_t _PDCLIB_constraint_handler; + +/* Set the given function as the new constraint violation handler. */ +_PDCLIB_PUBLIC constraint_handler_t set_constraint_handler_s( constraint_handler_t handler ); + +/* One of two predefined constraint violation handlers. When called, it will + print an error message (including the message passed as the first + parameter to the handler function) and call abort(). +*/ +_PDCLIB_PUBLIC void abort_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ); + +/* One of two predefined constraint violation handlers. Simply returns, + ignoring the constraint violation. +*/ +_PDCLIB_PUBLIC void ignore_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error ); + +/* Search an environment-provided key-value map for the given key name. + If the name is found, + - if len is not NULL, the length of the associated value string is stored + in that location. + - if len < maxsize, the value string is copied to the indicated location. + If the name is not found, + - if len is not NULL, a zero is stored in that location. + - if maxsize > 0, value[0] is set to the null character. + Details on the provided keys and how to set / change them are determined by + the hosting OS and its glue function. + The following conditions will be considered runtime constraint violations: + - value being a NULL pointer. + - maxsize == 0 or maxsize > RSIZE_MAX. + In case of a constraint violation, if len is not NULL a zero will be + stored at that location, and the environment key-value map not searched. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t getenv_s( size_t * _PDCLIB_restrict len, char * _PDCLIB_restrict value, rsize_t maxsize, const char * _PDCLIB_restrict name ); + +/* 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, a pointer to the array member as + second parameter, and the context parameter passed to bsearch_s() as third + 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 a matching element found, or NULL if no + match is found. + The following conditions will be considered runtime constraint violations: + - nmemb or size > RSIZE_MAX. + - nmemb > 0 and either of key, base, or compar being a null pointer. + In case of a constraint violation, the array will not be searched. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC void * bsearch_s( const void * key, const void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void * k, const void * y, void * context ), void * context ); + +/* 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, with the first two arguments + being pointers to the two objects to be compared, and the third argument + being the context parameter passed to qsort_s. The compar function 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. + The following conditions will be considered runtime constraint violations: + - nmemb or size > RSIZE_MAX. + - nmemb > 0 and either of base or compar being a null pointer. + In case of a constraint violation, the array will not be sorted. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t qsort_s( void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void * x, const void * y, void * context ), void * context ); + +/* TODO: Multibyte / wide character functions */ + +#endif + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDLIB_H +#include _PDCLIB_EXTEND_STDLIB_H +#endif + +#endif diff --git a/sysroot/usr/include/stdnoreturn.h b/sysroot/usr/include/stdnoreturn.h new file mode 100644 index 0000000..ab4ddb4 --- /dev/null +++ b/sysroot/usr/include/stdnoreturn.h @@ -0,0 +1,26 @@ +/* _Noreturn + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STDNORETURN_H +#define _PDCLIB_STDNORETURN_H _PDCLIB_STDNORETURN_H + +#include "pdclib/_PDCLIB_internal.h" + +/* This basically breaks the letter of the standard (which states that + noreturn be defined to _Noreturn). This defines noreturn -> _Noreturn + on C11 compliant compilers only (as older compilers do not know about + _Noreturn). +*/ +#define noreturn _PDCLIB_Noreturn + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STDNORETURN_H +#include _PDCLIB_EXTEND_STDNORETURN_H +#endif + +#endif diff --git a/sysroot/usr/include/string.h b/sysroot/usr/include/string.h new file mode 100644 index 0000000..05062fd --- /dev/null +++ b/sysroot/usr/include/string.h @@ -0,0 +1,394 @@ +/* String handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_STRING_H +#define _PDCLIB_STRING_H _PDCLIB_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* 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. +*/ +_PDCLIB_PUBLIC void * memcpy( void * _PDCLIB_restrict s1, const void * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC void * memmove( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n ); + +/* Copy the character array s2 (including terminating '\0' byte) into the + character array s1. + Returns the value of s1. +*/ +_PDCLIB_PUBLIC char * strcpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC char * strncpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC char * strcat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ); + +/* Append a maximum of n characters from the character array s2 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. +*/ +_PDCLIB_PUBLIC char * strncat( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC size_t strxfrm( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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 separator characters + which can differ from call to call. Leading separators are skipped, the first + trailing separator overwritten with '\0'. + Returns a pointer to the next token. + WARNING: This function uses static storage, and as such is not reentrant. +*/ +_PDCLIB_PUBLIC char * strtok( char * _PDCLIB_restrict s1, const char * _PDCLIB_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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC char * strerror( int errnum ); + +/* Returns the length of the string s (excluding terminating '\0'). +*/ +_PDCLIB_PUBLIC size_t strlen( const char * s ); + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef _PDCLIB_size_t rsize_t; +#endif + +/* Copy a number of n characters from the memory area pointed to by s2 to the + area pointed to by s1 of size s1max. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - n > s1max (not enough space in s1). + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX + then the first s1max characters of s1 will be set to zero. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t memcpy_s( void * _PDCLIB_restrict s1, rsize_t s1max, const void * _PDCLIB_restrict s2, rsize_t n ); + +/* Copy a number of n characters from the memory area pointed to by s2 to the + area pointed to by s1 of size s1max. The two areas may overlap. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - n > s1max (not enough space in s1). + In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX + then the first s1max characters of s1 will be set to zero. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t memmove_s( void * _PDCLIB_restrict s1, rsize_t s1max, const void * _PDCLIB_restrict s2, rsize_t n ); + +/* Copy the character array s2 (including terminating '\0' byte) into the + character array s1. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max being zero or > RSIZE_MAX. + - s1max not greater than strnlen_s( s2, s1max ) (not enough space in s1). + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX + then s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strcpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 ); + +/* Copy a maximum of n characters from the character array s2 into the character + array s1. If s2 is longer than n, s1[n] will be set to '\0'. + Returns zero if successful, non-zero otherwise. + + ATTENTION ATTENTION ATTENTION + + This function differs in two fundamental ways from strncpy(): + - remaining space in s1 will NOT be zeroed. Their value is unspecified. + - s1 WILL be zero-terminated even if there is not enough space to hold + all n characters from s2. + + THANK YOU FOR YOUR ATTENTION. + + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - s1max being zero. + - n >= s1max and s1max <= strnlen_s( s2, s1max ) (not enough space in s1). + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strncpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n ); + +/* 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). + Elements following the terminating null character (if any) take unspecified + values. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max being > RSIZE_MAX. + - s1max being zero. + - not enough space in s1 for both s1 and the characters copied from s2. + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strcat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 ); + +/* Append a maximum of n characters from the character array s2 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. + Elements following the terminating null character (if any) take unspecified + values. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s1 or s2 being NULL. + - s1max or n being > RSIZE_MAX. + - s1max being zero. + - not enough space in s1 for both s1 and the characters copied from s2. + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strncat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n ); + +/* 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 of size *s1max. On subsequent calls, the first argument is + NULL unless you want to start parsing a new string. s2 holds an array of + separator characters which can differ from call to call. Leading separators + are skipped, the first trailing separator overwritten with '\0'. + Returns a pointer to the next token. + The following conditions will be considered runtime constraint violations: + - s1max, s2, or ptr being NULL. + - s1max or n being > RSIZE_MAX. + - s1max being zero. + - not enough space in s1 for both s1 and the characters copied from s2. + - copying between overlapping objects. + In case of a constraint violation, if s1 is not NULL and s1max is greater + zero and <= RSIZE_MAX, s1[0] will be set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC char * strtok_s( char * _PDCLIB_restrict s1, rsize_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr ); + +/* Write the character c (interpreted as unsigned char) to the first n + characters of the memory area pointed to by s of size smax. + Returns zero if successful, non-zero otherwise. + The following conditions will be considered runtime constraint violations: + - s being NULL. + - smax or n being > RSIZE_MAX. + - n being > smax. + In case of a constraint violation, if s is not NULL and smax is <= RSIZE_MAX + the value of c (interpreted as unsigned char) is written to the first smax + characters of s. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t memset_s( void * s, rsize_t smax, int c, rsize_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. + If the length of the mapped string is < maxsize, the string is copied to s. + Otherwise, if maxsize is greater than zero, as much of the string as does + fit is copied, and s[maxsize-1] set to '\0'. If maxsize is greater than 3, + the partial string is made to end in "...". + Returns zero if the string was copied successfully in full, non-zero + otherwise. + The following conditions will be considered runtime constraint violations: + - s being NULL. + - maxsize being zero or > RSIZE_MAX. + In case of a constraint violation, s is not modified. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t strerror_s( char * s, rsize_t maxsize, errno_t errnum ); + +/* Map an error number to a (locale-specific) error message string, the same + way as strerror_s() would do. Error numbers are typically errno values, + but any number is mapped to a message. + TODO: PDCLib does not yet support locales. + Returns the length of the mapped string. +*/ +_PDCLIB_PUBLIC size_t strerrorlen_s( errno_t errnum ); + +/* Returns the length of the string s (excluding terminating '\0'). + If there is no null character in the first maxsize characters of s, + rerturns maxsize. If s is NULL, returns zero. + At most the first maxsize characters of s shall be accessed by the + function. +*/ +_PDCLIB_PUBLIC size_t strnlen_s( const char * s, size_t maxsize ); + +#endif + +#ifdef __cplusplus +} +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_STRING_H +#include _PDCLIB_EXTEND_STRING_H +#endif + +#endif diff --git a/sysroot/usr/include/sys/stat.h b/sysroot/usr/include/sys/stat.h new file mode 100644 index 0000000..7225b36 --- /dev/null +++ b/sysroot/usr/include/sys/stat.h @@ -0,0 +1,50 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include + +// Basic POSIX types for i686 execution +typedef uint32_t dev_t; +typedef uint32_t ino_t; +typedef uint32_t mode_t; +typedef uint32_t nlink_t; +typedef uint32_t uid_t; +typedef uint32_t gid_t; +typedef int32_t off_t; +typedef int32_t time_t; + +// The stat layout expected by standard C files +struct stat { + dev_t st_dev; /* ID of device containing file */ + ino_t st_ino; /* Inode number */ + mode_t st_mode; /* File type and mode flags */ + nlink_t st_nlink; /* Number of hard links */ + uid_t st_uid; /* User ID of owner */ + gid_t st_gid; /* Group ID of owner */ + dev_t st_rdev; /* Device ID (if special file) */ + off_t st_size; /* Total size, in bytes */ + time_t st_atime; /* Time of last access */ + time_t st_mtime; /* Time of last modification */ + time_t st_ctime; /* Time of last status change */ +}; + +// Traditional POSIX file permission/type bitmasks +#define S_IFMT 0170000 /* Bitmask for the file type bit fields */ +#define S_IFSOCK 0140000 /* Socket */ +#define S_IFLNK 0120000 /* Symbolic link */ +#define S_IFREG 0100000 /* Regular file */ +#define S_IFBLK 0060000 /* Block device */ +#define S_IFDIR 0040000 /* Directory */ +#define S_IFCHR 0020000 /* Character device */ +#define S_IFIFO 0010000 /* FIFO */ + +#define S_IRUSR 00400 /* Owner has read permission */ +#define S_IWUSR 00200 /* Owner has write permission */ +#define S_IXUSR 00100 /* Owner has execute permission */ +#define S_IRWXU 00700 /* Owner has read, write, and execute permission */ + +// Helper check macros commonly used in PDCLib +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) + +#endif /* _SYS_STAT_H */ \ No newline at end of file diff --git a/sysroot/usr/include/sys/time.h b/sysroot/usr/include/sys/time.h new file mode 100644 index 0000000..de1d7ce --- /dev/null +++ b/sysroot/usr/include/sys/time.h @@ -0,0 +1,21 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#include + +// Represents an exact elapsed time signature +struct timeval { + time_t tv_sec; /* Seconds since Unix Epoch */ + int32_t tv_usec; /* Microseconds component */ +}; + +// Represents traditional timezone offsets (largely obsolete but required) +struct timezone { + int tz_minuteswest; /* Minutes west of Greenwich */ + int tz_dsttime; /* Type of DST correction */ +}; + +/* Prototype for time fetching system operation */ +int gettimeofday(struct timeval *restrict tv, void *restrict tz); + +#endif /* _SYS_TIME_H */ \ No newline at end of file diff --git a/sysroot/usr/include/sys/times.h b/sysroot/usr/include/sys/times.h new file mode 100644 index 0000000..0ca899e --- /dev/null +++ b/sysroot/usr/include/sys/times.h @@ -0,0 +1,17 @@ +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#include + +/* Structure describing CPU time used by a process and its children */ +struct tms { + clock_t tms_utime; /* User CPU time */ + clock_t tms_stime; /* System CPU time */ + clock_t tms_cutime; /* User CPU time of dead children */ + clock_t tms_cstime; /* System CPU time of dead children */ +}; + +/* Function prototype for timing system call */ +clock_t times(struct tms *buffer); + +#endif /* _SYS_TIMES_H */ \ No newline at end of file diff --git a/sysroot/usr/include/sys/types.h b/sysroot/usr/include/sys/types.h new file mode 100644 index 0000000..be32cab --- /dev/null +++ b/sysroot/usr/include/sys/types.h @@ -0,0 +1,29 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include + +// Standard signed and unsigned size primitives +typedef int32_t ssize_t; +typedef uint32_t size_t; + +// Process and Thread IDs +typedef int32_t pid_t; +typedef int32_t id_t; + +// File system block and reference markers +typedef int32_t blkcnt_t; +typedef int32_t blksize_t; +typedef uint32_t dev_t; +typedef uint32_t gid_t; +typedef uint32_t ino_t; +typedef uint32_t mode_t; +typedef uint32_t nlink_t; +typedef int32_t off_t; +typedef uint32_t uid_t; + +// Clock and Timing fields +typedef int32_t time_t; +typedef int32_t clock_t; + +#endif /* _SYS_TYPES_H */ \ No newline at end of file diff --git a/sysroot/usr/include/time.h b/sysroot/usr/include/time.h new file mode 100644 index 0000000..17ae34f --- /dev/null +++ b/sysroot/usr/include/time.h @@ -0,0 +1,191 @@ +/* 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. +*/ + +#ifndef _PDCLIB_TIME_H +#define _PDCLIB_TIME_H _PDCLIB_TIMEH + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_lib_ext1.h" +#include "pdclib/_PDCLIB_internal.h" + +#ifndef _PDCLIB_SIZE_T_DEFINED +#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED +typedef _PDCLIB_size_t size_t; +#endif + +#ifndef _PDCLIB_NULL_DEFINED +#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED +#define NULL _PDCLIB_NULL +#endif + +/* See comments in _PDCLIB_config.h on the semantics of time_t and clock_t. */ + +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 + +/* Implementor's note: If you change this structure, and are using Pthread + threading support, check auxiliary/pthread/pthread_readout.c for its + twin. It is imperative that Pthread and PDCLib use identical layouts for + struct timespec, as they are implicitly cast from one to the other. This + cannot be checked for in this header (as we may not include host system + headers here), so the assert()s are in pthread_readout.c (which, in turn, + cannot include *this* header, which is why this admonishment to keep the + definitions in sync exists...). +*/ +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. +*/ +_PDCLIB_PUBLIC clock_t clock( void ); + +/* Returns the difference between two calendar times in seconds. */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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". +*/ +_PDCLIB_PUBLIC char * asctime( const struct tm * timeptr ); + +/* Equivalent to asctime( localtime( timer ) ). */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC size_t strftime( char * _PDCLIB_restrict s, size_t maxsize, const char * _PDCLIB_restrict format, const struct tm * _PDCLIB_restrict timeptr ); + +/* Annex K -- Bounds-checking interfaces */ + +#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0 + +#ifndef _PDCLIB_ERRNO_T_DEFINED +#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef _PDCLIB_RSIZE_T_DEFINED +#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED +typedef _PDCLIB_size_t rsize_t; +#endif + +/* Converts the broken-down time pointed to by timeptr into a string in the + form "Sun Sep 16 01:03:52 1973\n\0", which is stored in buffer s of maxsize. + Returns zero if the time was successfully converted and stored, non-zero + otherwise. + The following conditions will be considered runtime constraint violations: + - s or timeptr being NULL. + - maxsize being < 26 or > RSIZE_MAX. + - the broken-down time pointed to by timeptr not being normalized. + - the year represented by the broken-down time pointed to by timeptr + being < 0 or > 9999. + In case of a constraint violation, the time will not be converted. If + s is not NULL and maxsize is neither zero nor > RSIZE_MAX, s[0] will be + set to '\0'. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC errno_t asctime_s( char * s, rsize_t maxsize, const struct tm * timeptr ); + +/* Equivalent to asctime_s( s, maxsize, localtime( timer ) ). */ +_PDCLIB_PUBLIC errno_t ctime_s( char * s, rsize_t maxsize, const time_t * timer ); + +/* Converts the calender time pointed to by timer into a broken-down time + expressed as UTC, which gets stored in the result struct. + Returns a pointer to the broken-down time, or a NULL pointer if if + cannot be represented or stored. + The following conditions will be considered runtime constraint violations: + - timer or result being NULL. + In case of a constraint violation, the time will not be converted. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC struct tm * gmtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result ); + +/* Converts the calender time pointed to by timer into a broken-down time + expressed as local time, which gets stored in the result struct. + Returns a pointer to the broken-down time, or a NULL pointer if if + cannot be represented or stored. + The following conditions will be considered runtime constraint violations: + - timer or result being NULL. + In case of a constraint violation, the time will not be converted. + The currently active constraint violation handler function will be called + (see set_constraint_handler_s()). +*/ +_PDCLIB_PUBLIC struct tm * localtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result ); + +#endif + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_TIME_H +#include _PDCLIB_EXTEND_TIME_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/include/unistd.h b/sysroot/usr/include/unistd.h new file mode 100644 index 0000000..35ce2bb --- /dev/null +++ b/sysroot/usr/include/unistd.h @@ -0,0 +1,28 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +/* Standard file descriptors used by streams */ +#define STDIN_FILENO 0 /* Standard input */ +#define STDOUT_FILENO 1 /* Standard output */ +#define STDERR_FILENO 2 /* Standard error output */ + +/* Seek constants for lseek() / _PDCLIB_lseek() */ +#ifndef SEEK_SET +#define SEEK_SET 0 /* Seek from beginning of file */ +#define SEEK_CUR 1 /* Seek from current position */ +#define SEEK_END 2 /* Seek from end of file */ +#endif + +/* Null pointer declaration constant */ +#ifndef NULL +#define NULL ((void *)0) +#endif + +int open(const char *pathname, int flags, ...); +int read(int fd, void *buf, size_t count); +int close(int fd); + + +#endif /* _UNISTD_H */ \ No newline at end of file diff --git a/sysroot/usr/include/wctype.h b/sysroot/usr/include/wctype.h new file mode 100644 index 0000000..3776b7a --- /dev/null +++ b/sysroot/usr/include/wctype.h @@ -0,0 +1,152 @@ +/* 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. +*/ + +#ifndef _PDCLIB_WCTYPE_H +#define _PDCLIB_WCTYPE_H _PDCLIB_WCTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pdclib/_PDCLIB_internal.h" + +typedef _PDCLIB_wint_t wint_t; +typedef int wctrans_t; +typedef int 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 ) */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int iswblank( wint_t wc ); + +/* Returns true if the wide character is a control character. */ +_PDCLIB_PUBLIC int iswcntrl( wint_t wc ); + +/* Returns true if the wide character is a decimal digit. Locale- + independent. */ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int iswlower( wint_t wc ); + +/* Returns true for every printing wide character. */ +_PDCLIB_PUBLIC int iswprint( wint_t wc ); + +/* Returns true for a locale-specific set of punctuation characters that + are neither whitespace nor alphanumeric. +*/ +_PDCLIB_PUBLIC int iswpunct( wint_t wc ); + +/* Returns true for a locale-specific set of whitespace characters that + are neither alphanumeric, graphic, or punctuation. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC int iswupper( wint_t wc ); + +/* Returns true if the wide character is a hexadecimal digit. Locale- + independent. */ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC 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). +*/ +_PDCLIB_PUBLIC 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. +*/ +_PDCLIB_PUBLIC wctrans_t wctrans( const char * property ); + +/* Extension hook for downstream projects that want to have non-standard + extensions to standard headers. +*/ +#ifdef _PDCLIB_EXTEND_WCTYPE_H +#include _PDCLIB_EXTEND_WCTYPE_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/usr/lib/rlibc.a b/sysroot/usr/lib/rlibc.a new file mode 100644 index 0000000000000000000000000000000000000000..f367739e2ef2ef3410195f8dadf7b4530956a9a4 GIT binary patch literal 271538 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
9P{9O!iUTK)rW&1*W( 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