From d1c90ca8b2301ed53e3a6847f6cc77a8cb038da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 23 Mar 2003 23:57:50 +0000 Subject: [PATCH] Initial revision git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3008 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../libroot/posix/glibc/stdio-common/Jamfile | 47 + .../posix/glibc/stdio-common/_i18n_number.h | 49 + .../libroot/posix/glibc/stdio-common/_itoa.c | 426 +++ .../libroot/posix/glibc/stdio-common/_itoa.h | 92 + .../libroot/posix/glibc/stdio-common/_itowa.c | 346 +++ .../libroot/posix/glibc/stdio-common/_itowa.h | 65 + .../posix/glibc/stdio-common/asprintf.c | 44 + .../posix/glibc/stdio-common/dprintf.c | 41 + .../posix/glibc/stdio-common/fprintf.c | 44 + .../libroot/posix/glibc/stdio-common/fscanf.c | 35 + .../posix/glibc/stdio-common/getline.c | 38 + .../libroot/posix/glibc/stdio-common/getw.c | 36 + .../posix/glibc/stdio-common/itoa-digits.c | 23 + .../posix/glibc/stdio-common/itoa-udigits.c | 23 + .../posix/glibc/stdio-common/itowa-digits.c | 27 + .../libroot/posix/glibc/stdio-common/perror.c | 93 + .../posix/glibc/stdio-common/printf-parse.h | 454 +++ .../posix/glibc/stdio-common/printf-prs.c | 122 + .../libroot/posix/glibc/stdio-common/printf.c | 43 + .../libroot/posix/glibc/stdio-common/printf.h | 145 + .../posix/glibc/stdio-common/printf_fp.c | 1232 +++++++++ .../posix/glibc/stdio-common/printf_size.c | 266 ++ .../posix/glibc/stdio-common/psignal.c | 74 + .../libroot/posix/glibc/stdio-common/putw.c | 34 + .../posix/glibc/stdio-common/reg-printf.c | 61 + .../libroot/posix/glibc/stdio-common/scanf.c | 44 + .../posix/glibc/stdio-common/snprintf.c | 42 + .../posix/glibc/stdio-common/sprintf.c | 45 + .../libroot/posix/glibc/stdio-common/sscanf.c | 47 + .../posix/glibc/stdio-common/stdio_ext.h | 87 + .../posix/glibc/stdio-common/stdio_lim.h.in | 41 + .../posix/glibc/stdio-common/tempnam.c | 44 + .../libroot/posix/glibc/stdio-common/tmpnam.c | 52 + .../posix/glibc/stdio-common/tmpnam_r.c | 38 + .../posix/glibc/stdio-common/vfprintf.c | 2284 +++++++++++++++ .../posix/glibc/stdio-common/vfscanf.c | 2456 +++++++++++++++++ .../posix/glibc/stdio-common/vfwprintf.c | 3 + .../posix/glibc/stdio-common/vfwscanf.c | 2 + .../posix/glibc/stdio-common/vprintf.c | 33 + .../libroot/posix/glibc/stdlib/Makefile | 119 + .../libroot/posix/glibc/stdlib/Versions | 105 + src/kernel/libroot/posix/glibc/stdlib/a64l.c | 66 + src/kernel/libroot/posix/glibc/stdlib/abs.c | 28 + .../libroot/posix/glibc/stdlib/alloca.h | 41 + .../libroot/posix/glibc/stdlib/atexit.c | 39 + src/kernel/libroot/posix/glibc/stdlib/atof.c | 29 + src/kernel/libroot/posix/glibc/stdlib/atoi.c | 29 + src/kernel/libroot/posix/glibc/stdlib/atol.c | 29 + src/kernel/libroot/posix/glibc/stdlib/atoll.c | 29 + .../libroot/posix/glibc/stdlib/bsearch.c | 49 + .../libroot/posix/glibc/stdlib/canonicalize.c | 240 ++ .../libroot/posix/glibc/stdlib/cxa_atexit.c | 96 + .../libroot/posix/glibc/stdlib/cxa_finalize.c | 47 + .../libroot/posix/glibc/stdlib/drand48-iter.c | 59 + .../libroot/posix/glibc/stdlib/drand48.c | 31 + .../libroot/posix/glibc/stdlib/drand48_r.c | 30 + .../libroot/posix/glibc/stdlib/erand48.c | 32 + .../libroot/posix/glibc/stdlib/erand48_r.c | 50 + src/kernel/libroot/posix/glibc/stdlib/errno.h | 73 + src/kernel/libroot/posix/glibc/stdlib/exit.c | 84 + src/kernel/libroot/posix/glibc/stdlib/exit.h | 63 + .../libroot/posix/glibc/stdlib/fmtmsg.c | 408 +++ .../libroot/posix/glibc/stdlib/fmtmsg.h | 106 + .../libroot/posix/glibc/stdlib/fpioconst.c | 462 ++++ .../libroot/posix/glibc/stdlib/fpioconst.h | 69 + .../libroot/posix/glibc/stdlib/gen-mpn-copy | 35 + .../libroot/posix/glibc/stdlib/getsubopt.c | 75 + .../libroot/posix/glibc/stdlib/gmp-impl.h | 372 +++ src/kernel/libroot/posix/glibc/stdlib/gmp.h | 622 +++++ .../libroot/posix/glibc/stdlib/grouping.h | 186 ++ .../libroot/posix/glibc/stdlib/isomac.c | 445 +++ .../libroot/posix/glibc/stdlib/jrand48.c | 32 + .../libroot/posix/glibc/stdlib/jrand48_r.c | 37 + src/kernel/libroot/posix/glibc/stdlib/l64a.c | 58 + .../libroot/posix/glibc/stdlib/lcong48.c | 28 + .../libroot/posix/glibc/stdlib/lcong48_r.c | 39 + .../libroot/posix/glibc/stdlib/longlong.h | 1333 +++++++++ .../libroot/posix/glibc/stdlib/lrand48.c | 31 + .../libroot/posix/glibc/stdlib/lrand48_r.c | 33 + src/kernel/libroot/posix/glibc/stdlib/mblen.c | 69 + .../libroot/posix/glibc/stdlib/mbstowcs.c | 40 + .../libroot/posix/glibc/stdlib/mbtowc.c | 75 + .../libroot/posix/glibc/stdlib/monetary.h | 55 + .../libroot/posix/glibc/stdlib/mrand48.c | 31 + .../libroot/posix/glibc/stdlib/mrand48_r.c | 32 + src/kernel/libroot/posix/glibc/stdlib/msort.c | 156 ++ .../libroot/posix/glibc/stdlib/nrand48.c | 32 + .../libroot/posix/glibc/stdlib/nrand48_r.c | 40 + .../libroot/posix/glibc/stdlib/old_atexit.c | 8 + .../libroot/posix/glibc/stdlib/on_exit.c | 36 + src/kernel/libroot/posix/glibc/stdlib/qsort.c | 248 ++ src/kernel/libroot/posix/glibc/stdlib/rand.c | 29 + .../libroot/posix/glibc/stdlib/rand_r.c | 49 + .../libroot/posix/glibc/stdlib/random.c | 305 ++ .../libroot/posix/glibc/stdlib/random_r.c | 407 +++ .../libroot/posix/glibc/stdlib/rpmatch.c | 64 + .../posix/glibc/stdlib/secure-getenv.c | 31 + .../libroot/posix/glibc/stdlib/seed48.c | 30 + .../libroot/posix/glibc/stdlib/seed48_r.c | 42 + .../libroot/posix/glibc/stdlib/srand48.c | 28 + .../libroot/posix/glibc/stdlib/srand48_r.c | 42 + .../libroot/posix/glibc/stdlib/stdlib.h | 919 ++++++ .../libroot/posix/glibc/stdlib/strfmon.c | 657 +++++ .../libroot/posix/glibc/stdlib/strfmon_l.c | 24 + .../libroot/posix/glibc/stdlib/strtod.c | 1583 +++++++++++ .../libroot/posix/glibc/stdlib/strtod_l.c | 31 + .../libroot/posix/glibc/stdlib/strtof.c | 22 + .../libroot/posix/glibc/stdlib/strtof_l.c | 31 + .../libroot/posix/glibc/stdlib/strtold_l.c | 53 + .../libroot/posix/glibc/stdlib/sys/errno.h | 1 + .../libroot/posix/glibc/stdlib/ucontext.h | 53 + .../libroot/posix/glibc/stdlib/wcstombs.c | 36 + .../libroot/posix/glibc/stdlib/wctomb.c | 57 + .../libroot/posix/glibc/stdlib/xpg_basename.c | 72 + src/kernel/libroot/posix/glibc/wcsmbs/Depend | 1 + .../libroot/posix/glibc/wcsmbs/Makefile | 68 + .../libroot/posix/glibc/wcsmbs/Versions | 27 + src/kernel/libroot/posix/glibc/wcsmbs/btowc.c | 87 + .../libroot/posix/glibc/wcsmbs/mbrlen.c | 36 + .../libroot/posix/glibc/wcsmbs/mbrtowc.c | 110 + .../libroot/posix/glibc/wcsmbs/mbsinit.c | 37 + .../libroot/posix/glibc/wcsmbs/mbsnrtowcs.c | 140 + .../libroot/posix/glibc/wcsmbs/mbsrtowcs.c | 167 ++ .../libroot/posix/glibc/wcsmbs/mbsrtowcs_l.c | 25 + src/kernel/libroot/posix/glibc/wcsmbs/wchar.h | 741 +++++ .../libroot/posix/glibc/wcsmbs/wcpcpy.c | 47 + .../libroot/posix/glibc/wcsmbs/wcpncpy.c | 89 + .../libroot/posix/glibc/wcsmbs/wcrtomb.c | 112 + .../libroot/posix/glibc/wcsmbs/wcscasecmp.c | 73 + .../libroot/posix/glibc/wcsmbs/wcscasecmp_l.c | 24 + .../libroot/posix/glibc/wcsmbs/wcscat.c | 51 + .../libroot/posix/glibc/wcsmbs/wcschr.c | 35 + .../libroot/posix/glibc/wcsmbs/wcschrnul.c | 36 + .../libroot/posix/glibc/wcsmbs/wcscmp.c | 44 + .../libroot/posix/glibc/wcsmbs/wcscoll.c | 42 + .../libroot/posix/glibc/wcsmbs/wcscoll_l.c | 23 + .../libroot/posix/glibc/wcsmbs/wcscpy.c | 59 + .../libroot/posix/glibc/wcsmbs/wcscspn.c | 39 + .../libroot/posix/glibc/wcsmbs/wcsdup.c | 37 + .../libroot/posix/glibc/wcsmbs/wcslen.c | 43 + .../libroot/posix/glibc/wcsmbs/wcsmbs-tst1.c | 59 + .../libroot/posix/glibc/wcsmbs/wcsmbsload.c | 269 ++ .../libroot/posix/glibc/wcsmbs/wcsmbsload.h | 81 + .../libroot/posix/glibc/wcsmbs/wcsncase.c | 76 + .../libroot/posix/glibc/wcsmbs/wcsncase_l.c | 24 + .../libroot/posix/glibc/wcsmbs/wcsncat.c | 80 + .../libroot/posix/glibc/wcsmbs/wcsncmp.c | 71 + .../libroot/posix/glibc/wcsmbs/wcsncpy.c | 86 + .../libroot/posix/glibc/wcsmbs/wcsnlen.c | 45 + .../libroot/posix/glibc/wcsmbs/wcsnrtombs.c | 146 + .../libroot/posix/glibc/wcsmbs/wcspbrk.c | 37 + .../libroot/posix/glibc/wcsmbs/wcsrchr.c | 37 + .../libroot/posix/glibc/wcsmbs/wcsrtombs.c | 147 + .../libroot/posix/glibc/wcsmbs/wcsspn.c | 47 + .../libroot/posix/glibc/wcsmbs/wcsstr.c | 100 + .../libroot/posix/glibc/wcsmbs/wcstod.c | 25 + .../libroot/posix/glibc/wcsmbs/wcstod_l.c | 35 + .../libroot/posix/glibc/wcsmbs/wcstof.c | 43 + .../libroot/posix/glibc/wcsmbs/wcstof_l.c | 35 + .../libroot/posix/glibc/wcsmbs/wcstok.c | 66 + .../libroot/posix/glibc/wcsmbs/wcstold.c | 62 + .../libroot/posix/glibc/wcsmbs/wcstold_l.c | 56 + .../libroot/posix/glibc/wcsmbs/wcswidth.c | 39 + .../libroot/posix/glibc/wcsmbs/wcsxfrm.c | 38 + .../libroot/posix/glibc/wcsmbs/wcsxfrm_l.c | 23 + src/kernel/libroot/posix/glibc/wcsmbs/wctob.c | 74 + .../libroot/posix/glibc/wcsmbs/wcwidth.c | 27 + .../libroot/posix/glibc/wcsmbs/wcwidth.h | 40 + .../libroot/posix/glibc/wcsmbs/wmemchr.c | 63 + .../libroot/posix/glibc/wcsmbs/wmemcmp.c | 84 + .../libroot/posix/glibc/wcsmbs/wmemcpy.c | 32 + .../libroot/posix/glibc/wcsmbs/wmemmove.c | 32 + .../libroot/posix/glibc/wcsmbs/wmempcpy.c | 33 + .../libroot/posix/glibc/wcsmbs/wmemset.c | 56 + 174 files changed, 24566 insertions(+) create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/Jamfile create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/_i18n_number.h create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/_itoa.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/_itoa.h create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/_itowa.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/_itowa.h create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/asprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/dprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/fprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/fscanf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/getline.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/getw.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/itoa-digits.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/itoa-udigits.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/itowa-digits.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/perror.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/printf-parse.h create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/printf-prs.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/printf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/printf.h create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/printf_fp.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/printf_size.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/psignal.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/putw.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/reg-printf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/scanf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/snprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/sprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/sscanf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/stdio_ext.h create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/stdio_lim.h.in create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/tempnam.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/tmpnam.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/tmpnam_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/vfprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/vfscanf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/vfwprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/vfwscanf.c create mode 100644 src/kernel/libroot/posix/glibc/stdio-common/vprintf.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/Makefile create mode 100644 src/kernel/libroot/posix/glibc/stdlib/Versions create mode 100644 src/kernel/libroot/posix/glibc/stdlib/a64l.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/abs.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/alloca.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/atexit.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/atof.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/atoi.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/atol.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/atoll.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/bsearch.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/canonicalize.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/cxa_atexit.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/cxa_finalize.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/drand48-iter.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/drand48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/drand48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/erand48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/erand48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/errno.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/exit.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/exit.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/fmtmsg.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/fmtmsg.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/fpioconst.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/fpioconst.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/gen-mpn-copy create mode 100644 src/kernel/libroot/posix/glibc/stdlib/getsubopt.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/gmp-impl.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/gmp.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/grouping.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/isomac.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/jrand48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/jrand48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/l64a.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/lcong48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/lcong48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/longlong.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/lrand48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/lrand48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/mblen.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/mbstowcs.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/mbtowc.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/monetary.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/mrand48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/mrand48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/msort.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/nrand48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/nrand48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/old_atexit.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/on_exit.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/qsort.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/rand.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/rand_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/random.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/random_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/rpmatch.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/secure-getenv.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/seed48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/seed48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/srand48.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/srand48_r.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/stdlib.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/strfmon.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/strfmon_l.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/strtod.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/strtod_l.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/strtof.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/strtof_l.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/strtold_l.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/sys/errno.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/ucontext.h create mode 100644 src/kernel/libroot/posix/glibc/stdlib/wcstombs.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/wctomb.c create mode 100644 src/kernel/libroot/posix/glibc/stdlib/xpg_basename.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/Depend create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/Makefile create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/Versions create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/btowc.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/mbrlen.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/mbrtowc.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/mbsinit.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/mbsnrtowcs.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wchar.h create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcpcpy.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcpncpy.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcrtomb.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscat.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcschr.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcschrnul.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscmp.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscoll.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscoll_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscpy.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcscspn.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsdup.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcslen.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsmbs-tst1.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.h create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsncase.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsncase_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsncat.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsncmp.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsncpy.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsnlen.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsnrtombs.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcspbrk.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsrchr.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsrtombs.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsspn.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsstr.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcstod.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcstod_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcstof.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcstof_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcstok.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcstold.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcstold_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcswidth.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm_l.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wctob.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.h create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wmemchr.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wmemcmp.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wmemcpy.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wmemmove.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wmempcpy.c create mode 100644 src/kernel/libroot/posix/glibc/wcsmbs/wmemset.c diff --git a/src/kernel/libroot/posix/glibc/stdio-common/Jamfile b/src/kernel/libroot/posix/glibc/stdio-common/Jamfile new file mode 100644 index 0000000000..3d5a15216b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/Jamfile @@ -0,0 +1,47 @@ +SubDir OBOS_TOP src kernel libroot posix glibc stdio-common ; + +SubDirHdrs $(OBOS_TOP) src kernel libroot posix glibc include arch $(OBOS_ARCH) ; +SubDirHdrs $(OBOS_TOP) src kernel libroot posix glibc stdio-common ; +SubDirHdrs $(OBOS_TOP) src kernel libroot posix glibc libio ; +SubDirHdrs $(OBOS_TOP) src kernel libroot posix glibc include ; +SubDirHdrs $(OBOS_TOP) src kernel libroot posix glibc locale ; +SubDirHdrs $(OBOS_TOP) src kernel libroot posix glibc ; + +SubDirCcFlags -imacrolibc-symbols.h ; + +# ToDo: for now, all wide character functions are disabled + +KernelMergeObject posix_gnu_stdio_common.o : + <$(SOURCE_GRIST)>_itoa.c +# <$(SOURCE_GRIST)>_itowa.c + <$(SOURCE_GRIST)>asprintf.c + <$(SOURCE_GRIST)>dprintf.c + <$(SOURCE_GRIST)>fprintf.c + <$(SOURCE_GRIST)>fscanf.c + <$(SOURCE_GRIST)>getline.c + <$(SOURCE_GRIST)>getw.c + <$(SOURCE_GRIST)>itoa-digits.c + <$(SOURCE_GRIST)>itoa-udigits.c +# <$(SOURCE_GRIST)>itowa-digits.c +# <$(SOURCE_GRIST)>perror.c + <$(SOURCE_GRIST)>printf-prs.c + <$(SOURCE_GRIST)>printf.c + <$(SOURCE_GRIST)>printf_fp.c + <$(SOURCE_GRIST)>printf_size.c + <$(SOURCE_GRIST)>putw.c + <$(SOURCE_GRIST)>reg-printf.c + <$(SOURCE_GRIST)>scanf.c + <$(SOURCE_GRIST)>snprintf.c + <$(SOURCE_GRIST)>sprintf.c + <$(SOURCE_GRIST)>sscanf.c + <$(SOURCE_GRIST)>tempnam.c + <$(SOURCE_GRIST)>tmpnam.c + <$(SOURCE_GRIST)>tmpnam_r.c + <$(SOURCE_GRIST)>vfprintf.c + <$(SOURCE_GRIST)>vfscanf.c +# <$(SOURCE_GRIST)>vfwprintf.c +# <$(SOURCE_GRIST)>vfwscanf.c + <$(SOURCE_GRIST)>vprintf.c + : + -fPIC -DPIC + ; diff --git a/src/kernel/libroot/posix/glibc/stdio-common/_i18n_number.h b/src/kernel/libroot/posix/glibc/stdio-common/_i18n_number.h new file mode 100644 index 0000000000..046657cc28 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/_i18n_number.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../locale/outdigits.h" +#include "../locale/outdigitswc.h" + +static CHAR_T * +_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr) +{ + CHAR_T *src, *s; + + /* Copy existing string so that nothing gets overwritten. */ + src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T)); + s = (CHAR_T *) __mempcpy (src, w, + (rear_ptr - w) * sizeof (CHAR_T)); + w = rear_ptr; + + /* Process all characters in the string. */ + while (--s >= src) + { + if (*s >= '0' && *s <= '9') + { + if (sizeof (CHAR_T) == 1) + w = (CHAR_T *) outdigit_value ((char *) w, *s - '0'); + else + *--w = (CHAR_T) outdigitwc_value (*s - '0'); + } + else + *--w = *s; + } + + return w; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/_itoa.c b/src/kernel/libroot/posix/glibc/stdio-common/_itoa.c new file mode 100644 index 0000000000..7bc6c08115 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/_itoa.c @@ -0,0 +1,426 @@ +/* Internal function for converting integers to ASCII. + Copyright (C) 1994, 1995, 1996, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund + and Ulrich Drepper . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include "_itoa.h" + + +/* Canonize environment. For some architectures not all values might + be defined in the GMP header files. */ +#ifndef UMUL_TIME +# define UMUL_TIME 1 +#endif +#ifndef UDIV_TIME +# define UDIV_TIME 3 +#endif + +/* Control memory layout. */ +#ifdef PACK +# undef PACK +# define PACK __attribute__ ((packed)) +#else +# define PACK +#endif + + +/* Declare local types. */ +struct base_table_t +{ +#if (UDIV_TIME > 2 * UMUL_TIME) + mp_limb_t base_multiplier; +#endif + char flag; + char post_shift; +#if BITS_PER_MP_LIMB == 32 + struct + { + char normalization_steps; + char ndigits; + mp_limb_t base PACK; +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb_t base_ninv PACK; +#endif + } big; +#endif +}; + +/* To reduce the memory needed we include some fields of the tables + only conditionally. */ +#if UDIV_TIME > 2 * UMUL_TIME +# define SEL1(X) X, +# define SEL2(X) ,X +#else +# define SEL1(X) +# define SEL2(X) +#endif + + +/* Local variables. */ +const struct base_table_t _itoa_base_table[] attribute_hidden = +{ +#if BITS_PER_MP_LIMB == 64 + /* 2 */ {SEL1(0ull) 1, 1}, + /* 3 */ {SEL1(0xaaaaaaaaaaaaaaabull) 0, 1}, + /* 4 */ {SEL1(0ull) 1, 2}, + /* 5 */ {SEL1(0xcccccccccccccccdull) 0, 2}, + /* 6 */ {SEL1(0xaaaaaaaaaaaaaaabull) 0, 2}, + /* 7 */ {SEL1(0x2492492492492493ull) 1, 3}, + /* 8 */ {SEL1(0ull) 1, 3}, + /* 9 */ {SEL1(0xe38e38e38e38e38full) 0, 3}, + /* 10 */ {SEL1(0xcccccccccccccccdull) 0, 3}, + /* 11 */ {SEL1(0x2e8ba2e8ba2e8ba3ull) 0, 1}, + /* 12 */ {SEL1(0xaaaaaaaaaaaaaaabull) 0, 3}, + /* 13 */ {SEL1(0x4ec4ec4ec4ec4ec5ull) 0, 2}, + /* 14 */ {SEL1(0x2492492492492493ull) 1, 4}, + /* 15 */ {SEL1(0x8888888888888889ull) 0, 3}, + /* 16 */ {SEL1(0ull) 1, 4}, + /* 17 */ {SEL1(0xf0f0f0f0f0f0f0f1ull) 0, 4}, + /* 18 */ {SEL1(0xe38e38e38e38e38full) 0, 4}, + /* 19 */ {SEL1(0xd79435e50d79435full) 0, 4}, + /* 20 */ {SEL1(0xcccccccccccccccdull) 0, 4}, + /* 21 */ {SEL1(0x8618618618618619ull) 1, 5}, + /* 22 */ {SEL1(0x2e8ba2e8ba2e8ba3ull) 0, 2}, + /* 23 */ {SEL1(0x642c8590b21642c9ull) 1, 5}, + /* 24 */ {SEL1(0xaaaaaaaaaaaaaaabull) 0, 4}, + /* 25 */ {SEL1(0x47ae147ae147ae15ull) 1, 5}, + /* 26 */ {SEL1(0x4ec4ec4ec4ec4ec5ull) 0, 3}, + /* 27 */ {SEL1(0x97b425ed097b425full) 0, 4}, + /* 28 */ {SEL1(0x2492492492492493ull) 1, 5}, + /* 29 */ {SEL1(0x1a7b9611a7b9611bull) 1, 5}, + /* 30 */ {SEL1(0x8888888888888889ull) 0, 4}, + /* 31 */ {SEL1(0x0842108421084211ull) 1, 5}, + /* 32 */ {SEL1(0ull) 1, 5}, + /* 33 */ {SEL1(0x0f83e0f83e0f83e1ull) 0, 1}, + /* 34 */ {SEL1(0xf0f0f0f0f0f0f0f1ull) 0, 5}, + /* 35 */ {SEL1(0xea0ea0ea0ea0ea0full) 0, 5}, + /* 36 */ {SEL1(0xe38e38e38e38e38full) 0, 5} +#endif +#if BITS_PER_MP_LIMB == 32 + /* 2 */ {SEL1(0ul) 1, 1, {0, 31, 0x80000000ul SEL2(0xfffffffful)}}, + /* 3 */ {SEL1(0xaaaaaaabul) 0, 1, {0, 20, 0xcfd41b91ul SEL2(0x3b563c24ul)}}, + /* 4 */ {SEL1(0ul) 1, 2, {1, 15, 0x40000000ul SEL2(0xfffffffful)}}, + /* 5 */ {SEL1(0xcccccccdul) 0, 2, {1, 13, 0x48c27395ul SEL2(0xc25c2684ul)}}, + /* 6 */ {SEL1(0xaaaaaaabul) 0, 2, {0, 12, 0x81bf1000ul SEL2(0xf91bd1b6ul)}}, + /* 7 */ {SEL1(0x24924925ul) 1, 3, {1, 11, 0x75db9c97ul SEL2(0x1607a2cbul)}}, + /* 8 */ {SEL1(0ul) 1, 3, {1, 10, 0x40000000ul SEL2(0xfffffffful)}}, + /* 9 */ {SEL1(0x38e38e39ul) 0, 1, {0, 10, 0xcfd41b91ul SEL2(0x3b563c24ul)}}, + /* 10 */ {SEL1(0xcccccccdul) 0, 3, {2, 9, 0x3b9aca00ul SEL2(0x12e0be82ul)}}, + /* 11 */ {SEL1(0xba2e8ba3ul) 0, 3, {0, 9, 0x8c8b6d2bul SEL2(0xd24cde04ul)}}, + /* 12 */ {SEL1(0xaaaaaaabul) 0, 3, {3, 8, 0x19a10000ul SEL2(0x3fa39ab5ul)}}, + /* 13 */ {SEL1(0x4ec4ec4ful) 0, 2, {2, 8, 0x309f1021ul SEL2(0x50f8ac5ful)}}, + /* 14 */ {SEL1(0x24924925ul) 1, 4, {1, 8, 0x57f6c100ul SEL2(0x74843b1eul)}}, + /* 15 */ {SEL1(0x88888889ul) 0, 3, {0, 8, 0x98c29b81ul SEL2(0xad0326c2ul)}}, + /* 16 */ {SEL1(0ul) 1, 4, {3, 7, 0x10000000ul SEL2(0xfffffffful)}}, + /* 17 */ {SEL1(0xf0f0f0f1ul) 0, 4, {3, 7, 0x18754571ul SEL2(0x4ef0b6bdul)}}, + /* 18 */ {SEL1(0x38e38e39ul) 0, 2, {2, 7, 0x247dbc80ul SEL2(0xc0fc48a1ul)}}, + /* 19 */ {SEL1(0xaf286bcbul) 1, 5, {2, 7, 0x3547667bul SEL2(0x33838942ul)}}, + /* 20 */ {SEL1(0xcccccccdul) 0, 4, {1, 7, 0x4c4b4000ul SEL2(0xad7f29abul)}}, + /* 21 */ {SEL1(0x86186187ul) 1, 5, {1, 7, 0x6b5a6e1dul SEL2(0x313c3d15ul)}}, + /* 22 */ {SEL1(0xba2e8ba3ul) 0, 4, {0, 7, 0x94ace180ul SEL2(0xb8cca9e0ul)}}, + /* 23 */ {SEL1(0xb21642c9ul) 0, 4, {0, 7, 0xcaf18367ul SEL2(0x42ed6de9ul)}}, + /* 24 */ {SEL1(0xaaaaaaabul) 0, 4, {4, 6, 0x0b640000ul SEL2(0x67980e0bul)}}, + /* 25 */ {SEL1(0x51eb851ful) 0, 3, {4, 6, 0x0e8d4a51ul SEL2(0x19799812ul)}}, + /* 26 */ {SEL1(0x4ec4ec4ful) 0, 3, {3, 6, 0x1269ae40ul SEL2(0xbce85396ul)}}, + /* 27 */ {SEL1(0x2f684bdbul) 1, 5, {3, 6, 0x17179149ul SEL2(0x62c103a9ul)}}, + /* 28 */ {SEL1(0x24924925ul) 1, 5, {3, 6, 0x1cb91000ul SEL2(0x1d353d43ul)}}, + /* 29 */ {SEL1(0x8d3dcb09ul) 0, 4, {2, 6, 0x23744899ul SEL2(0xce1deceaul)}}, + /* 30 */ {SEL1(0x88888889ul) 0, 4, {2, 6, 0x2b73a840ul SEL2(0x790fc511ul)}}, + /* 31 */ {SEL1(0x08421085ul) 1, 5, {2, 6, 0x34e63b41ul SEL2(0x35b865a0ul)}}, + /* 32 */ {SEL1(0ul) 1, 5, {1, 6, 0x40000000ul SEL2(0xfffffffful)}}, + /* 33 */ {SEL1(0x3e0f83e1ul) 0, 3, {1, 6, 0x4cfa3cc1ul SEL2(0xa9aed1b3ul)}}, + /* 34 */ {SEL1(0xf0f0f0f1ul) 0, 5, {1, 6, 0x5c13d840ul SEL2(0x63dfc229ul)}}, + /* 35 */ {SEL1(0xd41d41d5ul) 1, 6, {1, 6, 0x6d91b519ul SEL2(0x2b0fee30ul)}}, + /* 36 */ {SEL1(0x38e38e39ul) 0, 3, {0, 6, 0x81bf1000ul SEL2(0xf91bd1b6ul)}} +#endif +}; + +/* Lower-case digits. */ +extern const char _itoa_lower_digits[]; +extern const char _itoa_lower_digits_internal[] attribute_hidden; +/* Upper-case digits. */ +extern const char _itoa_upper_digits[]; +extern const char _itoa_upper_digits_internal[] attribute_hidden; + + +char * +_itoa (value, buflim, base, upper_case) + unsigned long long int value; + char *buflim; + unsigned int base; + int upper_case; +{ + const char *digits = (upper_case + ? INTUSE(_itoa_upper_digits) + : INTUSE(_itoa_lower_digits)); + const struct base_table_t *brec = &_itoa_base_table[base - 2]; + + switch (base) + { +#define RUN_2N(BITS) \ + do \ + { \ + /* `unsigned long long int' always has 64 bits. */ \ + mp_limb_t work_hi = value >> (64 - BITS_PER_MP_LIMB); \ + \ + if (BITS_PER_MP_LIMB == 32) \ + { \ + if (work_hi != 0) \ + { \ + mp_limb_t work_lo; \ + int cnt; \ + \ + work_lo = value & 0xfffffffful; \ + for (cnt = BITS_PER_MP_LIMB / BITS; cnt > 0; --cnt) \ + { \ + *--buflim = digits[work_lo & ((1ul << BITS) - 1)]; \ + work_lo >>= BITS; \ + } \ + if (BITS_PER_MP_LIMB % BITS != 0) \ + { \ + work_lo \ + |= ((work_hi \ + & ((1 << (BITS - BITS_PER_MP_LIMB%BITS)) \ + - 1)) \ + << BITS_PER_MP_LIMB % BITS); \ + work_hi >>= BITS - BITS_PER_MP_LIMB % BITS; \ + if (work_hi == 0) \ + work_hi = work_lo; \ + else \ + *--buflim = digits[work_lo]; \ + } \ + } \ + else \ + work_hi = value & 0xfffffffful; \ + } \ + do \ + { \ + *--buflim = digits[work_hi & ((1 << BITS) - 1)]; \ + work_hi >>= BITS; \ + } \ + while (work_hi != 0); \ + } \ + while (0) + case 8: + RUN_2N (3); + break; + + case 16: + RUN_2N (4); + break; + + default: + { +#if BITS_PER_MP_LIMB == 64 + mp_limb_t base_multiplier = brec->base_multiplier; + if (brec->flag) + while (value != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, value, base_multiplier); + quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1); + rem = value - quo * base; + *--buflim = digits[rem]; + value = quo; + } + else + while (value != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, value, base_multiplier); + quo = x >> brec->post_shift; + rem = value - quo * base; + *--buflim = digits[rem]; + value = quo; + } +#endif +#if BITS_PER_MP_LIMB == 32 + mp_limb_t t[3]; + int n; + + /* First convert x0 to 1-3 words in base s->big.base. + Optimize for frequent cases of 32 bit numbers. */ + if ((mp_limb_t) (value >> 32) >= 1) + { +#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION + int big_normalization_steps = brec->big.normalization_steps; + mp_limb_t big_base_norm + = brec->big.base << big_normalization_steps; +#endif + if ((mp_limb_t) (value >> 32) >= brec->big.base) + { + mp_limb_t x1hi, x1lo, r; + /* If you want to optimize this, take advantage of + that the quotient in the first udiv_qrnnd will + always be very small. It might be faster just to + subtract in a tight loop. */ + +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb_t x, xh, xl; + + if (big_normalization_steps == 0) + xh = 0; + else + xh = (mp_limb_t) (value >> (64 - big_normalization_steps)); + xl = (mp_limb_t) (value >> (32 - big_normalization_steps)); + udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm, + brec->big.base_ninv); + + xl = ((mp_limb_t) value) << big_normalization_steps; + udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm, + brec->big.base_ninv); + t[2] = x >> big_normalization_steps; + + if (big_normalization_steps == 0) + xh = x1hi; + else + xh = ((x1hi << big_normalization_steps) + | (x1lo >> (32 - big_normalization_steps))); + xl = x1lo << big_normalization_steps; + udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm, + brec->big.base_ninv); + t[1] = x >> big_normalization_steps; +#elif UDIV_NEEDS_NORMALIZATION + mp_limb_t x, xh, xl; + + if (big_normalization_steps == 0) + xh = 0; + else + xh = (mp_limb_t) (value >> 64 - big_normalization_steps); + xl = (mp_limb_t) (value >> 32 - big_normalization_steps); + udiv_qrnnd (x1hi, r, xh, xl, big_base_norm); + + xl = ((mp_limb_t) value) << big_normalization_steps; + udiv_qrnnd (x1lo, x, r, xl, big_base_norm); + t[2] = x >> big_normalization_steps; + + if (big_normalization_steps == 0) + xh = x1hi; + else + xh = ((x1hi << big_normalization_steps) + | (x1lo >> 32 - big_normalization_steps)); + xl = x1lo << big_normalization_steps; + udiv_qrnnd (t[0], x, xh, xl, big_base_norm); + t[1] = x >> big_normalization_steps; +#else + udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32), + brec->big.base); + udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base); + udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base); +#endif + n = 3; + } + else + { +#if (UDIV_TIME > 2 * UMUL_TIME) + mp_limb_t x; + + value <<= brec->big.normalization_steps; + udiv_qrnnd_preinv (t[0], x, (mp_limb_t) (value >> 32), + (mp_limb_t) value, big_base_norm, + brec->big.base_ninv); + t[1] = x >> brec->big.normalization_steps; +#elif UDIV_NEEDS_NORMALIZATION + mp_limb_t x; + + value <<= big_normalization_steps; + udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32), + (mp_limb_t) value, big_base_norm); + t[1] = x >> big_normalization_steps; +#else + udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32), + (mp_limb_t) value, brec->big.base); +#endif + n = 2; + } + } + else + { + t[0] = value; + n = 1; + } + + /* Convert the 1-3 words in t[], word by word, to ASCII. */ + do + { + mp_limb_t ti = t[--n]; + int ndig_for_this_limb = 0; + +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb_t base_multiplier = brec->base_multiplier; + if (brec->flag) + while (ti != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, ti, base_multiplier); + quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1); + rem = ti - quo * base; + *--buflim = digits[rem]; + ti = quo; + ++ndig_for_this_limb; + } + else + while (ti != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, ti, base_multiplier); + quo = x >> brec->post_shift; + rem = ti - quo * base; + *--buflim = digits[rem]; + ti = quo; + ++ndig_for_this_limb; + } +#else + while (ti != 0) + { + mp_limb_t quo, rem; + + quo = ti / base; + rem = ti % base; + *--buflim = digits[rem]; + ti = quo; + ++ndig_for_this_limb; + } +#endif + /* If this wasn't the most significant word, pad with zeros. */ + if (n != 0) + while (ndig_for_this_limb < brec->big.ndigits) + { + *--buflim = '0'; + ++ndig_for_this_limb; + } + } + while (n != 0); +#endif + } + break; + } + + return buflim; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/_itoa.h b/src/kernel/libroot/posix/glibc/stdio-common/_itoa.h new file mode 100644 index 0000000000..6249adca91 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/_itoa.h @@ -0,0 +1,92 @@ +/* Internal function for converting integers to ASCII. + Copyright (C) 1994, 95, 96, 97, 98, 99, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ITOA_H +#define _ITOA_H +#include + +/* Convert VALUE into ASCII in base BASE (2..36). + Write backwards starting the character just before BUFLIM. + Return the address of the first (left-to-right) character in the number. + Use upper case letters iff UPPER_CASE is nonzero. */ + +extern char *_itoa (unsigned long long int value, char *buflim, + unsigned int base, int upper_case); + +extern const char _itoa_upper_digits[]; +extern const char _itoa_upper_digits_internal[] attribute_hidden; +extern const char _itoa_lower_digits[]; +extern const char _itoa_lower_digits_internal[] attribute_hidden; + +static inline char * __attribute__ ((unused)) +_itoa_word (unsigned long value, char *buflim, + unsigned int base, int upper_case) +{ + const char *digits = (upper_case +#if !defined NOT_IN_libc || defined IS_IN_rtld + ? INTUSE(_itoa_upper_digits) + : INTUSE(_itoa_lower_digits) +#else + ? _itoa_upper_digits + : _itoa_lower_digits +#endif + ); + + switch (base) + { +#define SPECIAL(Base) \ + case Base: \ + do \ + *--buflim = digits[value % Base]; \ + while ((value /= Base) != 0); \ + break + + SPECIAL (10); + SPECIAL (16); + SPECIAL (8); + default: + do + *--buflim = digits[value % base]; + while ((value /= base) != 0); + } + return buflim; +} +#undef SPECIAL + +static inline char * __attribute__ ((unused)) +_fitoa_word (unsigned long value, char *buf, unsigned int base, int upper_case) +{ + char tmpbuf[sizeof (value) * 4]; /* Worst case length: base 2. */ + char *cp = _itoa_word (value, tmpbuf + sizeof (value) * 4, base, upper_case); + while (cp < tmpbuf + sizeof (value) * 4) + *buf++ = *cp++; + return buf; +} + +static inline char * __attribute__ ((unused)) +_fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case) +{ + char tmpbuf[sizeof (value) * 4]; /* Worst case length: base 2. */ + char *cp = _itoa (value, tmpbuf + sizeof (value) * 4, base, upper_case); + while (cp < tmpbuf + sizeof (value) * 4) + *buf++ = *cp++; + return buf; +} + +#endif /* itoa.h */ diff --git a/src/kernel/libroot/posix/glibc/stdio-common/_itowa.c b/src/kernel/libroot/posix/glibc/stdio-common/_itowa.c new file mode 100644 index 0000000000..b9cc341dd9 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/_itowa.c @@ -0,0 +1,346 @@ +/* Internal function for converting integers to ASCII. + Copyright (C) 1994,1995,1996,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund + and Ulrich Drepper . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include "_itowa.h" + + +/* Canonize environment. For some architectures not all values might + be defined in the GMP header files. */ +#ifndef UMUL_TIME +# define UMUL_TIME 1 +#endif +#ifndef UDIV_TIME +# define UDIV_TIME 3 +#endif + +/* Control memory layout. */ +#ifdef PACK +# undef PACK +# define PACK __attribute__ ((packed)) +#else +# define PACK +#endif + + +/* Declare local types. */ +struct base_table_t +{ +#if (UDIV_TIME > 2 * UMUL_TIME) + mp_limb_t base_multiplier; +#endif + char flag; + char post_shift; +#if BITS_PER_MP_LIMB == 32 + struct + { + char normalization_steps; + char ndigits; + mp_limb_t base PACK; +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb_t base_ninv PACK; +#endif + } big; +#endif +}; + +/* To reduce the memory needed we include some fields of the tables + only conditionally. */ +#if UDIV_TIME > 2 * UMUL_TIME +# define SEL1(X) X, +# define SEL2(X) ,X +#else +# define SEL1(X) +# define SEL2(X) +#endif + +/* Factor table for the different bases. */ +extern const struct base_table_t _itoa_base_table[] attribute_hidden; + +/* Lower-case digits. */ +extern const wchar_t _itowa_lower_digits[] attribute_hidden; +/* Upper-case digits. */ +extern const wchar_t _itowa_upper_digits[] attribute_hidden; + + +wchar_t * +_itowa (value, buflim, base, upper_case) + unsigned long long int value; + wchar_t *buflim; + unsigned int base; + int upper_case; +{ + const wchar_t *digits = (upper_case + ? _itowa_upper_digits : _itowa_lower_digits); + wchar_t *bp = buflim; + const struct base_table_t *brec = &_itoa_base_table[base - 2]; + + switch (base) + { +#define RUN_2N(BITS) \ + do \ + { \ + /* `unsigned long long int' always has 64 bits. */ \ + mp_limb_t work_hi = value >> (64 - BITS_PER_MP_LIMB); \ + \ + if (BITS_PER_MP_LIMB == 32) \ + { \ + if (work_hi != 0) \ + { \ + mp_limb_t work_lo; \ + int cnt; \ + \ + work_lo = value & 0xfffffffful; \ + for (cnt = BITS_PER_MP_LIMB / BITS; cnt > 0; --cnt) \ + { \ + *--bp = digits[work_lo & ((1ul << BITS) - 1)]; \ + work_lo >>= BITS; \ + } \ + if (BITS_PER_MP_LIMB % BITS != 0) \ + { \ + work_lo \ + |= ((work_hi \ + & ((1 << (BITS - BITS_PER_MP_LIMB%BITS)) \ + - 1)) \ + << BITS_PER_MP_LIMB % BITS); \ + work_hi >>= BITS - BITS_PER_MP_LIMB % BITS; \ + if (work_hi == 0) \ + work_hi = work_lo; \ + else \ + *--bp = digits[work_lo]; \ + } \ + } \ + else \ + work_hi = value & 0xfffffffful; \ + } \ + do \ + { \ + *--bp = digits[work_hi & ((1 << BITS) - 1)]; \ + work_hi >>= BITS; \ + } \ + while (work_hi != 0); \ + } \ + while (0) + case 8: + RUN_2N (3); + break; + + case 16: + RUN_2N (4); + break; + + default: + { +#if BITS_PER_MP_LIMB == 64 + mp_limb_t base_multiplier = brec->base_multiplier; + if (brec->flag) + while (value != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, value, base_multiplier); + quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1); + rem = value - quo * base; + *--bp = digits[rem]; + value = quo; + } + else + while (value != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, value, base_multiplier); + quo = x >> brec->post_shift; + rem = value - quo * base; + *--bp = digits[rem]; + value = quo; + } +#endif +#if BITS_PER_MP_LIMB == 32 + mp_limb_t t[3]; + int n; + + /* First convert x0 to 1-3 words in base s->big.base. + Optimize for frequent cases of 32 bit numbers. */ + if ((mp_limb_t) (value >> 32) >= 1) + { +#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION + int big_normalization_steps = brec->big.normalization_steps; + mp_limb_t big_base_norm + = brec->big.base << big_normalization_steps; +#endif + if ((mp_limb_t) (value >> 32) >= brec->big.base) + { + mp_limb_t x1hi, x1lo, r; + /* If you want to optimize this, take advantage of + that the quotient in the first udiv_qrnnd will + always be very small. It might be faster just to + subtract in a tight loop. */ + +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb_t x, xh, xl; + + if (big_normalization_steps == 0) + xh = 0; + else + xh = (mp_limb_t) (value >> (64 - big_normalization_steps)); + xl = (mp_limb_t) (value >> (32 - big_normalization_steps)); + udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm, + brec->big.base_ninv); + + xl = ((mp_limb_t) value) << big_normalization_steps; + udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm, + brec->big.base_ninv); + t[2] = x >> big_normalization_steps; + + if (big_normalization_steps == 0) + xh = x1hi; + else + xh = ((x1hi << big_normalization_steps) + | (x1lo >> (32 - big_normalization_steps))); + xl = x1lo << big_normalization_steps; + udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm, + brec->big.base_ninv); + t[1] = x >> big_normalization_steps; +#elif UDIV_NEEDS_NORMALIZATION + mp_limb_t x, xh, xl; + + if (big_normalization_steps == 0) + xh = 0; + else + xh = (mp_limb_t) (value >> 64 - big_normalization_steps); + xl = (mp_limb_t) (value >> 32 - big_normalization_steps); + udiv_qrnnd (x1hi, r, xh, xl, big_base_norm); + + xl = ((mp_limb_t) value) << big_normalization_steps; + udiv_qrnnd (x1lo, x, r, xl, big_base_norm); + t[2] = x >> big_normalization_steps; + + if (big_normalization_steps == 0) + xh = x1hi; + else + xh = ((x1hi << big_normalization_steps) + | (x1lo >> 32 - big_normalization_steps)); + xl = x1lo << big_normalization_steps; + udiv_qrnnd (t[0], x, xh, xl, big_base_norm); + t[1] = x >> big_normalization_steps; +#else + udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32), + brec->big.base); + udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base); + udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base); +#endif + n = 3; + } + else + { +#if (UDIV_TIME > 2 * UMUL_TIME) + mp_limb_t x; + + value <<= brec->big.normalization_steps; + udiv_qrnnd_preinv (t[0], x, (mp_limb_t) (value >> 32), + (mp_limb_t) value, big_base_norm, + brec->big.base_ninv); + t[1] = x >> brec->big.normalization_steps; +#elif UDIV_NEEDS_NORMALIZATION + mp_limb_t x; + + value <<= big_normalization_steps; + udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32), + (mp_limb_t) value, big_base_norm); + t[1] = x >> big_normalization_steps; +#else + udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32), + (mp_limb_t) value, brec->big.base); +#endif + n = 2; + } + } + else + { + t[0] = value; + n = 1; + } + + /* Convert the 1-3 words in t[], word by word, to ASCII. */ + do + { + mp_limb_t ti = t[--n]; + int ndig_for_this_limb = 0; + +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb_t base_multiplier = brec->base_multiplier; + if (brec->flag) + while (ti != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, ti, base_multiplier); + quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1); + rem = ti - quo * base; + *--bp = digits[rem]; + ti = quo; + ++ndig_for_this_limb; + } + else + while (ti != 0) + { + mp_limb_t quo, rem, x, dummy; + + umul_ppmm (x, dummy, ti, base_multiplier); + quo = x >> brec->post_shift; + rem = ti - quo * base; + *--bp = digits[rem]; + ti = quo; + ++ndig_for_this_limb; + } +#else + while (ti != 0) + { + mp_limb_t quo, rem; + + quo = ti / base; + rem = ti % base; + *--bp = digits[rem]; + ti = quo; + ++ndig_for_this_limb; + } +#endif + /* If this wasn't the most significant word, pad with zeros. */ + if (n != 0) + while (ndig_for_this_limb < brec->big.ndigits) + { + *--bp = '0'; + ++ndig_for_this_limb; + } + } + while (n != 0); +#endif + } + break; + } + + return bp; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/_itowa.h b/src/kernel/libroot/posix/glibc/stdio-common/_itowa.h new file mode 100644 index 0000000000..d3a5447304 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/_itowa.h @@ -0,0 +1,65 @@ +/* Internal function for converting integers to ASCII. + Copyright (C) 1994, 95, 96, 97, 98, 99, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ITOWA_H +#define _ITOWA_H 1 +#include +#include + +/* Convert VALUE into ASCII in base BASE (2..36). + Write backwards starting the character just before BUFLIM. + Return the address of the first (left-to-right) character in the number. + Use upper case letters iff UPPER_CASE is nonzero. */ + +extern wchar_t *_itowa (unsigned long long int value, wchar_t *buflim, + unsigned int base, int upper_case); + +static inline wchar_t * +__attribute__ ((unused)) +_itowa_word (unsigned long value, wchar_t *buflim, + unsigned int base, int upper_case) +{ + extern const wchar_t _itowa_upper_digits[] attribute_hidden; + extern const wchar_t _itowa_lower_digits[] attribute_hidden; + const wchar_t *digits = (upper_case + ? _itowa_upper_digits : _itowa_lower_digits); + wchar_t *bp = buflim; + + switch (base) + { +#define SPECIAL(Base) \ + case Base: \ + do \ + *--bp = digits[value % Base]; \ + while ((value /= Base) != 0); \ + break + + SPECIAL (10); + SPECIAL (16); + SPECIAL (8); + default: + do + *--bp = digits[value % base]; + while ((value /= base) != 0); + } + return bp; +} +#undef SPECIAL + +#endif /* itowa.h */ diff --git a/src/kernel/libroot/posix/glibc/stdio-common/asprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/asprintf.c new file mode 100644 index 0000000000..3b211d62b8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/asprintf.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991, 1995, 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef USE_IN_LIBIO +# include +# define vasprintf(s, f, a) _IO_vasprintf (s, f, a) +#endif +#undef __asprintf + +/* Write formatted output from FORMAT to a string which is + allocated with malloc and stored in *STRING_PTR. */ +/* VARARGS2 */ +int +__asprintf (char **string_ptr, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vasprintf (string_ptr, format, arg); + va_end (arg); + + return done; +} +INTDEF(__asprintf) +weak_alias (__asprintf, asprintf) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/dprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/dprintf.c new file mode 100644 index 0000000000..534b3f0df7 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/dprintf.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991,95,97,98,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef USE_IN_LIBIO +# include +# define vdprintf(d, f, a) _IO_vdprintf (d, f, a) +#endif + +/* Write formatted output to D, according to the format string FORMAT. */ +/* VARARGS2 */ +int +dprintf (int d, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vdprintf (d, format, arg); + va_end (arg); + + return done; +} +libc_hidden_def (dprintf) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/fprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/fprintf.c new file mode 100644 index 0000000000..9243a4ec02 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/fprintf.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Write formatted output to STREAM from the format string FORMAT. */ +/* VARARGS2 */ +int +fprintf (FILE *stream, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vfprintf (stream, format, arg); + va_end (arg); + + return done; +} +libc_hidden_def (fprintf) + +#ifdef USE_IN_LIBIO +/* We define the function with the real name here. But deep down in + libio the original function _IO_fprintf is also needed. So make + an alias. */ +weak_alias (fprintf, _IO_fprintf) +#endif diff --git a/src/kernel/libroot/posix/glibc/stdio-common/fscanf.c b/src/kernel/libroot/posix/glibc/stdio-common/fscanf.c new file mode 100644 index 0000000000..58a66eaf30 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/fscanf.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Read formatted input from STREAM according to the format string FORMAT. */ +/* VARARGS2 */ +int +fscanf (FILE *stream, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vfscanf (stream, format, arg); + va_end (arg); + + return done; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/getline.c b/src/kernel/libroot/posix/glibc/stdio-common/getline.c new file mode 100644 index 0000000000..4acb41de77 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/getline.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#undef __getline + +#ifdef USE_IN_LIBIO +# include "../libio/libioP.h" +# undef ssize_t +# define ssize_t _IO_ssize_t +# define __getdelim _IO_getdelim +#endif + +/* Like getdelim, but always looks for a newline. */ +ssize_t +__getline (char **lineptr, size_t *n, FILE *stream) +{ + return __getdelim (lineptr, n, '\n', stream); +} + +weak_alias (__getline, getline) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/getw.c b/src/kernel/libroot/posix/glibc/stdio-common/getw.c new file mode 100644 index 0000000000..81156e6781 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/getw.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef USE_IN_LIBIO +# include +# define fread(p, m, n, s) INTUSE(_IO_fread) (p, m, n, s) +#endif + +/* Read a word (int) from STREAM. */ +int +getw (FILE *stream) +{ + int w; + + /* Is there a better way? */ + if (fread ((void *) &w, sizeof (w), 1, stream) != 1) + return EOF; + return w; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/itoa-digits.c b/src/kernel/libroot/posix/glibc/stdio-common/itoa-digits.c new file mode 100644 index 0000000000..cbdc09b105 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/itoa-digits.c @@ -0,0 +1,23 @@ +/* Digits. + Copyright (C) 1994,1995,1996,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Lower-case digits. */ +const char _itoa_lower_digits[36] + = "0123456789abcdefghijklmnopqrstuvwxyz"; +INTVARDEF(_itoa_lower_digits) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/itoa-udigits.c b/src/kernel/libroot/posix/glibc/stdio-common/itoa-udigits.c new file mode 100644 index 0000000000..0ed4dc119a --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/itoa-udigits.c @@ -0,0 +1,23 @@ +/* Digits. + Copyright (C) 1994,1995,1996,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Upper-case digits. */ +const char _itoa_upper_digits[36] + = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +INTVARDEF(_itoa_upper_digits) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/itowa-digits.c b/src/kernel/libroot/posix/glibc/stdio-common/itowa-digits.c new file mode 100644 index 0000000000..ce5b9c3b92 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/itowa-digits.c @@ -0,0 +1,27 @@ +/* Digits. + Copyright (C) 1994, 1995, 1996, 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Lower-case digits. */ +const wchar_t _itowa_lower_digits[36] attribute_hidden + = L"0123456789abcdefghijklmnopqrstuvwxyz"; +/* Upper-case digits. */ +const wchar_t _itowa_upper_digits[36] attribute_hidden + = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; diff --git a/src/kernel/libroot/posix/glibc/stdio-common/perror.c b/src/kernel/libroot/posix/glibc/stdio-common/perror.c new file mode 100644 index 0000000000..9899c7d509 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/perror.c @@ -0,0 +1,93 @@ +/* Copyright (C) 1991-1993,1997,1998,2000-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include "libioP.h" +#endif + +static void +perror_internal (FILE *fp, const char *s, int errnum) +{ + char buf[1024]; + const char *colon; + const char *errstring; + + if (s == NULL || *s == '\0') + s = colon = ""; + else + colon = ": "; + + errstring = __strerror_r (errnum, buf, sizeof buf); + +#ifdef USE_IN_LIBIO + if (_IO_fwide (fp, 0) > 0) + (void) __fwprintf (fp, L"%s%s%s\n", s, colon, errstring); + else +#endif + (void) fprintf (fp, "%s%s%s\n", s, colon, errstring); +} + + +/* Print a line on stderr consisting of the text in S, a colon, a space, + a message describing the meaning of the contents of `errno' and a newline. + If S is NULL or "", the colon and space are omitted. */ +void +perror (const char *s) +{ + int errnum = errno; +#ifdef USE_IN_LIBIO + FILE *fp; + int fd = -1; + + + /* The standard says that 'perror' must not change the orientation + of the stream. What is supposed to happen when the stream isn't + oriented yet? In this case we'll create a new stream which is + using the same underlying file descriptor. */ + if (__builtin_expect (_IO_fwide (stderr, 0) != 0, 1) + || (fd = fileno (stderr)) == -1 + || (fd = __dup (fd)) == -1 + || (fp = fdopen (fd, "w+")) == NULL) + { + if (__builtin_expect (fd != -1, 0)) + __close (fd); + + /* Use standard error as is. */ + perror_internal (stderr, s, errnum); + } + else + { + /* We don't have to do any special hacks regarding the file + position. Since the stderr stream wasn't used so far we just + write to the descriptor. */ + perror_internal (fp, s, errnum); + /* Close the stream. */ + fclose (fp); + + ((_IO_FILE *) stderr)->_offset = _IO_pos_BAD; + } +#else + perror_internal (stderr, s, errnum); +#endif +} +libc_hidden_def (perror) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/printf-parse.h b/src/kernel/libroot/posix/glibc/stdio-common/printf-parse.h new file mode 100644 index 0000000000..eff2816607 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/printf-parse.h @@ -0,0 +1,454 @@ +/* Internal header for parsing printf format strings. + Copyright (C) 1995-1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of th GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG 1 +#include + + +struct printf_spec + { + /* Information parsed from the format spec. */ + struct printf_info info; + + /* Pointers into the format string for the end of this format + spec and the next (or to the end of the string if no more). */ + const UCHAR_T *end_of_fmt, *next_fmt; + + /* Position of arguments for precision and width, or -1 if `info' has + the constant value. */ + int prec_arg, width_arg; + + int data_arg; /* Position of data argument. */ + int data_arg_type; /* Type of first argument. */ + /* Number of arguments consumed by this format specifier. */ + size_t ndata_args; + }; + + +/* The various kinds off arguments that can be passed to printf. */ +union printf_arg + { + unsigned char pa_char; + wchar_t pa_wchar; + short int pa_short_int; + int pa_int; + long int pa_long_int; + long long int pa_long_long_int; + unsigned short int pa_u_short_int; + unsigned int pa_u_int; + unsigned long int pa_u_long_int; + unsigned long long int pa_u_long_long_int; + float pa_float; + double pa_double; + long double pa_long_double; + const char *pa_string; + const wchar_t *pa_wstring; + void *pa_pointer; + }; + + +/* Read a simple integer from a string and update the string pointer. + It is assumed that the first character is a digit. */ +static inline unsigned int +read_int (const UCHAR_T * *pstr) +{ + unsigned int retval = **pstr - L_('0'); + + while (ISDIGIT (*++(*pstr))) + { + retval *= 10; + retval += **pstr - L_('0'); + } + + return retval; +} + + + +/* Find the next spec in FORMAT, or the end of the string. Returns + a pointer into FORMAT, to a '%' or a '\0'. */ +static inline const UCHAR_T * +#ifdef COMPILE_WPRINTF +find_spec (const UCHAR_T *format) +#else +find_spec (const UCHAR_T *format, mbstate_t *ps) +#endif +{ +#ifdef COMPILE_WPRINTF + return (const UCHAR_T *) __wcschrnul ((const CHAR_T *) format, L'%'); +#else + while (*format != L_('\0') && *format != L_('%')) + { + int len; + + /* Remove any hints of a wrong encoding. */ + ps->__count = 0; + if (! isascii (*format) && (len = __mbrlen (format, MB_CUR_MAX, ps)) > 0) + format += len; + else + ++format; + } + return format; +#endif +} + + +/* These are defined in reg-printf.c. */ +extern printf_arginfo_function **__printf_arginfo_table attribute_hidden; +extern printf_function **__printf_function_table attribute_hidden; + + +/* FORMAT must point to a '%' at the beginning of a spec. Fills in *SPEC + with the parsed details. POSN is the number of arguments already + consumed. At most MAXTYPES - POSN types are filled in TYPES. Return + the number of args consumed by this spec; *MAX_REF_ARG is updated so it + remains the highest argument index used. */ +static inline size_t +#ifdef COMPILE_WPRINTF +parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec, + size_t *max_ref_arg) +#else +parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec, + size_t *max_ref_arg, mbstate_t *ps) +#endif +{ + unsigned int n; + size_t nargs = 0; + + /* Skip the '%'. */ + ++format; + + /* Clear information structure. */ + spec->data_arg = -1; + spec->info.alt = 0; + spec->info.space = 0; + spec->info.left = 0; + spec->info.showsign = 0; + spec->info.group = 0; + spec->info.i18n = 0; + spec->info.pad = ' '; + spec->info.wide = sizeof (UCHAR_T) > 1; + + /* Test for positional argument. */ + if (ISDIGIT (*format)) + { + const UCHAR_T *begin = format; + + n = read_int (&format); + + if (n > 0 && *format == L_('$')) + /* Is positional parameter. */ + { + ++format; /* Skip the '$'. */ + spec->data_arg = n - 1; + *max_ref_arg = MAX (*max_ref_arg, n); + } + else + /* Oops; that was actually the width and/or 0 padding flag. + Step back and read it again. */ + format = begin; + } + + /* Check for spec modifiers. */ + do + { + switch (*format) + { + case L_(' '): + /* Output a space in place of a sign, when there is no sign. */ + spec->info.space = 1; + continue; + case L_('+'): + /* Always output + or - for numbers. */ + spec->info.showsign = 1; + continue; + case L_('-'): + /* Left-justify things. */ + spec->info.left = 1; + continue; + case L_('#'): + /* Use the "alternate form": + Hex has 0x or 0X, FP always has a decimal point. */ + spec->info.alt = 1; + continue; + case L_('0'): + /* Pad with 0s. */ + spec->info.pad = '0'; + continue; + case L_('\''): + /* Show grouping in numbers if the locale information + indicates any. */ + spec->info.group = 1; + continue; + case L_('I'): + /* Use the internationalized form of the output. Currently + means to use the `outdigits' of the current locale. */ + spec->info.i18n = 1; + continue; + default: + break; + } + break; + } + while (*++format); + + if (spec->info.left) + spec->info.pad = ' '; + + /* Get the field width. */ + spec->width_arg = -1; + spec->info.width = 0; + if (*format == L_('*')) + { + /* The field width is given in an argument. + A negative field width indicates left justification. */ + const UCHAR_T *begin = ++format; + + if (ISDIGIT (*format)) + { + /* The width argument might be found in a positional parameter. */ + n = read_int (&format); + + if (n > 0 && *format == L_('$')) + { + spec->width_arg = n - 1; + *max_ref_arg = MAX (*max_ref_arg, n); + ++format; /* Skip '$'. */ + } + } + + if (spec->width_arg < 0) + { + /* Not in a positional parameter. Consume one argument. */ + spec->width_arg = posn++; + ++nargs; + format = begin; /* Step back and reread. */ + } + } + else if (ISDIGIT (*format)) + /* Constant width specification. */ + spec->info.width = read_int (&format); + + /* Get the precision. */ + spec->prec_arg = -1; + /* -1 means none given; 0 means explicit 0. */ + spec->info.prec = -1; + if (*format == L_('.')) + { + ++format; + if (*format == L_('*')) + { + /* The precision is given in an argument. */ + const UCHAR_T *begin = ++format; + + if (ISDIGIT (*format)) + { + n = read_int (&format); + + if (n > 0 && *format == L_('$')) + { + spec->prec_arg = n - 1; + *max_ref_arg = MAX (*max_ref_arg, n); + ++format; + } + } + + if (spec->prec_arg < 0) + { + /* Not in a positional parameter. */ + spec->prec_arg = posn++; + ++nargs; + format = begin; + } + } + else if (ISDIGIT (*format)) + spec->info.prec = read_int (&format); + else + /* "%.?" is treated like "%.0?". */ + spec->info.prec = 0; + } + + /* Check for type modifiers. */ + spec->info.is_long_double = 0; + spec->info.is_short = 0; + spec->info.is_long = 0; + spec->info.is_char = 0; + + switch (*format++) + { + case L_('h'): + /* ints are short ints or chars. */ + if (*format != L_('h')) + spec->info.is_short = 1; + else + { + ++format; + spec->info.is_char = 1; + } + break; + case L_('l'): + /* ints are long ints. */ + spec->info.is_long = 1; + if (*format != L_('l')) + break; + ++format; + /* FALLTHROUGH */ + case L_('L'): + /* doubles are long doubles, and ints are long long ints. */ + case L_('q'): + /* 4.4 uses this for long long. */ + spec->info.is_long_double = 1; + break; + case L_('z'): + case L_('Z'): + /* ints are size_ts. */ + assert (sizeof (size_t) <= sizeof (unsigned long long int)); +#if LONG_MAX != LONG_LONG_MAX + spec->info.is_long_double = sizeof (size_t) > sizeof (unsigned long int); +#endif + spec->info.is_long = sizeof (size_t) > sizeof (unsigned int); + break; + case L_('t'): + assert (sizeof (ptrdiff_t) <= sizeof (long long int)); +#if LONG_MAX != LONG_LONG_MAX + spec->info.is_long_double = (sizeof (ptrdiff_t) > sizeof (long int)); +#endif + spec->info.is_long = sizeof (ptrdiff_t) > sizeof (int); + break; + case L_('j'): + assert (sizeof (uintmax_t) <= sizeof (unsigned long long int)); +#if LONG_MAX != LONG_LONG_MAX + spec->info.is_long_double = (sizeof (uintmax_t) + > sizeof (unsigned long int)); +#endif + spec->info.is_long = sizeof (uintmax_t) > sizeof (unsigned int); + break; + default: + /* Not a recognized modifier. Backup. */ + --format; + break; + } + + /* Get the format specification. */ + spec->info.spec = (wchar_t) *format++; + if (__builtin_expect (__printf_function_table != NULL, 0) + && spec->info.spec <= UCHAR_MAX + && __printf_arginfo_table[spec->info.spec] != NULL) + /* We don't try to get the types for all arguments if the format + uses more than one. The normal case is covered though. */ + spec->ndata_args = (*__printf_arginfo_table[spec->info.spec]) + (&spec->info, 1, &spec->data_arg_type); + else + { + /* Find the data argument types of a built-in spec. */ + spec->ndata_args = 1; + + switch (spec->info.spec) + { + case L'i': + case L'd': + case L'u': + case L'o': + case L'X': + case L'x': +#if LONG_MAX != LONG_LONG_MAX + if (spec->info.is_long_double) + spec->data_arg_type = PA_INT|PA_FLAG_LONG_LONG; + else +#endif + if (spec->info.is_long) + spec->data_arg_type = PA_INT|PA_FLAG_LONG; + else if (spec->info.is_short) + spec->data_arg_type = PA_INT|PA_FLAG_SHORT; + else if (spec->info.is_char) + spec->data_arg_type = PA_CHAR; + else + spec->data_arg_type = PA_INT; + break; + case L'e': + case L'E': + case L'f': + case L'F': + case L'g': + case L'G': + case L'a': + case L'A': + if (spec->info.is_long_double) + spec->data_arg_type = PA_DOUBLE|PA_FLAG_LONG_DOUBLE; + else + spec->data_arg_type = PA_DOUBLE; + break; + case L'c': + spec->data_arg_type = PA_CHAR; + break; + case L'C': + spec->data_arg_type = PA_WCHAR; + break; + case L's': + spec->data_arg_type = PA_STRING; + break; + case L'S': + spec->data_arg_type = PA_WSTRING; + break; + case L'p': + spec->data_arg_type = PA_POINTER; + break; + case L'n': + spec->data_arg_type = PA_INT|PA_FLAG_PTR; + break; + + case L'm': + default: + /* An unknown spec will consume no args. */ + spec->ndata_args = 0; + break; + } + } + + if (spec->data_arg == -1 && spec->ndata_args > 0) + { + /* There are args consumed, but no positional spec. Use the + next sequential arg position. */ + spec->data_arg = posn; + nargs += spec->ndata_args; + } + + if (spec->info.spec == L'\0') + /* Format ended before this spec was complete. */ + spec->end_of_fmt = spec->next_fmt = format - 1; + else + { + /* Find the next format spec. */ + spec->end_of_fmt = format; +#ifdef COMPILE_WPRINTF + spec->next_fmt = find_spec (format); +#else + spec->next_fmt = find_spec (format, ps); +#endif + } + + return nargs; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/printf-prs.c b/src/kernel/libroot/posix/glibc/stdio-common/printf-prs.c new file mode 100644 index 0000000000..ecbb47d41c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/printf-prs.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1991,92,95,96,99,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include "../locale/localeinfo.h" + +#ifndef COMPILE_WPRINTF +# define CHAR_T char +# define UCHAR_T unsigned char +# define INT_T int +# define L_(Str) Str +# define ISDIGIT(Ch) isdigit (Ch) +# define ISASCII(Ch) isascii (Ch) +# define MBRLEN(Cp, L, St) __mbrlen (Cp, L, St) + +# ifdef USE_IN_LIBIO +# define PUT(F, S, N) _IO_sputn (F, S, N) +# define PAD(Padchar) \ + if (width > 0) \ + done += INTUSE(_IO_padn) (s, Padchar, width) +# else +# define PUTC(C, F) putc (C, F) +ssize_t __printf_pad __P ((FILE *, char pad, size_t n)); +# define PAD(Padchar) \ + if (width > 0) \ + { if (__printf_pad (s, Padchar, width) == -1) \ + return -1; else done += width; } +# endif +#else +# define vfprintf vfwprintf +# define CHAR_T wchar_t +# define UCHAR_T uwchar_t +# define INT_T wint_t +# define L_(Str) L##Str +# define ISDIGIT(Ch) iswdigit (Ch) + +# ifdef USE_IN_LIBIO +# define PUT(F, S, N) _IO_sputn (F, S, N) +# define PAD(Padchar) \ + if (width > 0) \ + done += _IO_wpadn (s, Padchar, width) +# else +# define PUTC(C, F) wputc (C, F) +ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n)); +# define PAD(Padchar) \ + if (width > 0) \ + { if (__wprintf_pad (s, Padchar, width) == -1) \ + return -1; else done += width; } +# endif +#endif + +#include "printf-parse.h" + + +size_t +parse_printf_format (fmt, n, argtypes) + const char *fmt; + size_t n; + int *argtypes; +{ + size_t nargs; /* Number of arguments. */ + size_t max_ref_arg; /* Highest index used in a positional arg. */ + struct printf_spec spec; + mbstate_t mbstate; + + nargs = 0; + max_ref_arg = 0; + + /* Search for format specifications. */ + for (fmt = find_spec (fmt, &mbstate); *fmt != '\0'; fmt = spec.next_fmt) + { + /* Parse this spec. */ + nargs += parse_one_spec (fmt, nargs, &spec, &max_ref_arg, &mbstate); + + /* If the width is determined by an argument this is an int. */ + if (spec.width_arg != -1 && (size_t) spec.width_arg < n) + argtypes[spec.width_arg] = PA_INT; + + /* If the precision is determined by an argument this is an int. */ + if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n) + argtypes[spec.prec_arg] = PA_INT; + + if ((size_t) spec.data_arg < n) + switch (spec.ndata_args) + { + case 0: /* No arguments. */ + break; + case 1: /* One argument; we already have the type. */ + argtypes[spec.data_arg] = spec.data_arg_type; + break; + default: + /* We have more than one argument for this format spec. We must + call the arginfo function again to determine all the types. */ + (void) (*__printf_arginfo_table[spec.info.spec]) + (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg]); + break; + } + } + + return MAX (nargs, max_ref_arg); +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/printf.c b/src/kernel/libroot/posix/glibc/stdio-common/printf.c new file mode 100644 index 0000000000..fa013bbcc3 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/printf.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#undef printf + +/* Write formatted output to stdout from the format string FORMAT. */ +/* VARARGS1 */ +int +printf (const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vfprintf (stdout, format, arg); + va_end (arg); + + return done; +} + +#ifdef USE_IN_LIBIO +# undef _IO_printf +/* This is for libg++. */ +strong_alias (printf, _IO_printf); +#endif diff --git a/src/kernel/libroot/posix/glibc/stdio-common/printf.h b/src/kernel/libroot/posix/glibc/stdio-common/printf.h new file mode 100644 index 0000000000..c16569b59b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/printf.h @@ -0,0 +1,145 @@ +/* Copyright (C) 1991-1993,1995-1999,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PRINTF_H + +#define _PRINTF_H 1 +#include + +__BEGIN_DECLS + +#define __need_FILE +#include +#define __need_size_t +#define __need_wchar_t +#include + + +struct printf_info +{ + int prec; /* Precision. */ + int width; /* Width. */ + wchar_t spec; /* Format letter. */ + unsigned int is_long_double:1;/* L flag. */ + unsigned int is_short:1; /* h flag. */ + unsigned int is_long:1; /* l flag. */ + unsigned int alt:1; /* # flag. */ + unsigned int space:1; /* Space flag. */ + unsigned int left:1; /* - flag. */ + unsigned int showsign:1; /* + flag. */ + unsigned int group:1; /* ' flag. */ + unsigned int extra:1; /* For special use. */ + unsigned int is_char:1; /* hh flag. */ + unsigned int wide:1; /* Nonzero for wide character streams. */ + unsigned int i18n:1; /* I flag. */ + wchar_t pad; /* Padding character. */ +}; + + +/* Type of a printf specifier-handler function. + STREAM is the FILE on which to write output. + INFO gives information about the format specification. + ARGS is a vector of pointers to the argument data; + the number of pointers will be the number returned + by the associated arginfo function for the same INFO. + + The function should return the number of characters written, + or -1 for errors. */ + +typedef int printf_function (FILE *__stream, + __const struct printf_info *__info, + __const void *__const *__args); + +/* Type of a printf specifier-arginfo function. + INFO gives information about the format specification. + N, ARGTYPES, and return value are as for parse_printf_format. */ + +typedef int printf_arginfo_function (__const struct printf_info *__info, + size_t __n, int *__argtypes); + + +/* Register FUNC to be called to format SPEC specifiers; ARGINFO must be + specified to determine how many arguments a SPEC conversion requires and + what their types are. */ + +extern int register_printf_function (int __spec, printf_function __func, + printf_arginfo_function __arginfo); + + +/* Parse FMT, and fill in N elements of ARGTYPES with the + types needed for the conversions FMT specifies. Returns + the number of arguments required by FMT. + + The ARGINFO function registered with a user-defined format is passed a + `struct printf_info' describing the format spec being parsed. A width + or precision of INT_MIN means a `*' was used to indicate that the + width/precision will come from an arg. The function should fill in the + array it is passed with the types of the arguments it wants, and return + the number of arguments it wants. */ + +extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n, + int *__restrict __argtypes) __THROW; + + +/* Codes returned by `parse_printf_format' for basic types. + + These values cover all the standard format specifications. + Users can add new values after PA_LAST for their own types. */ + +enum +{ /* C type: */ + PA_INT, /* int */ + PA_CHAR, /* int, cast to char */ + PA_WCHAR, /* wide char */ + PA_STRING, /* const char *, a '\0'-terminated string */ + PA_WSTRING, /* const wchar_t *, wide character string */ + PA_POINTER, /* void * */ + PA_FLOAT, /* float */ + PA_DOUBLE, /* double */ + PA_LAST +}; + +/* Flag bits that can be set in a type returned by `parse_printf_format'. */ +#define PA_FLAG_MASK 0xff00 +#define PA_FLAG_LONG_LONG (1 << 8) +#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG +#define PA_FLAG_LONG (1 << 9) +#define PA_FLAG_SHORT (1 << 10) +#define PA_FLAG_PTR (1 << 11) + + + +/* Function which can be registered as `printf'-handlers. */ + +/* Print floating point value using using abbreviations for the orders + of magnitude used for numbers ('k' for kilo, 'm' for mega etc). If + the format specifier is a uppercase character powers of 1000 are + used. Otherwise powers of 1024. */ +extern int printf_size (FILE *__restrict __fp, + __const struct printf_info *__info, + __const void *__const *__restrict __args) __THROW; + +/* This is the appropriate argument information function for `printf_size'. */ +extern int printf_size_info (__const struct printf_info *__restrict + __info, size_t __n, int *__restrict __argtypes) + __THROW; + + +__END_DECLS + +#endif /* printf.h */ diff --git a/src/kernel/libroot/posix/glibc/stdio-common/printf_fp.c b/src/kernel/libroot/posix/glibc/stdio-common/printf_fp.c new file mode 100644 index 0000000000..0f0c68eb88 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/printf_fp.c @@ -0,0 +1,1232 @@ +/* Floating point output for `printf'. + Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The gmp headers need some configuration frobs. */ +#define HAVE_ALLOCA 1 + +#ifdef USE_IN_LIBIO +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NDEBUG +# define NDEBUG /* Undefine this for debugging assertions. */ +#endif +#include + +/* This defines make it possible to use the same code for GNU C library and + the GNU I/O library. */ +#ifdef USE_IN_LIBIO +# define PUT(f, s, n) _IO_sputn (f, s, n) +# define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : INTUSE(_IO_padn) (f, c, n)) +/* We use this file GNU C library and GNU I/O library. So make + names equal. */ +# undef putc +# define putc(c, f) (wide \ + ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f)) +# define size_t _IO_size_t +# define FILE _IO_FILE +#else /* ! USE_IN_LIBIO */ +# define PUT(f, s, n) fwrite (s, 1, n, f) +# define PAD(f, c, n) __printf_pad (f, c, n) +ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */ +#endif /* USE_IN_LIBIO */ + +/* Macros for doing the actual output. */ + +#define outchar(ch) \ + do \ + { \ + register const int outc = (ch); \ + if (putc (outc, fp) == EOF) \ + return -1; \ + ++done; \ + } while (0) + +#define PRINT(ptr, wptr, len) \ + do \ + { \ + register size_t outlen = (len); \ + if (len > 20) \ + { \ + if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen) \ + return -1; \ + ptr += outlen; \ + done += outlen; \ + } \ + else \ + { \ + if (wide) \ + while (outlen-- > 0) \ + outchar (*wptr++); \ + else \ + while (outlen-- > 0) \ + outchar (*ptr++); \ + } \ + } while (0) + +#define PADN(ch, len) \ + do \ + { \ + if (PAD (fp, ch, len) != len) \ + return -1; \ + done += len; \ + } \ + while (0) + +/* We use the GNU MP library to handle large numbers. + + An MP variable occupies a varying number of entries in its array. We keep + track of this number for efficiency reasons. Otherwise we would always + have to process the whole array. */ +#define MPN_VAR(name) mp_limb_t *name; mp_size_t name##size + +#define MPN_ASSIGN(dst,src) \ + memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t)) +#define MPN_GE(u,v) \ + (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0)) + +extern int __isinfl_internal (long double) attribute_hidden; +extern int __isnanl_internal (long double) attribute_hidden; + +extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size, + int *expt, int *is_neg, + double value); +extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, + int *expt, int *is_neg, + long double value); +extern unsigned int __guess_grouping (unsigned int intdig_max, + const char *grouping); + + +static wchar_t *group_number (wchar_t *buf, wchar_t *bufend, + unsigned int intdig_no, const char *grouping, + wchar_t thousands_sep, int ngroups) + internal_function; + + +int +__printf_fp (FILE *fp, + const struct printf_info *info, + const void *const *args) +{ + /* The floating-point value to output. */ + union + { + double dbl; + __long_double_t ldbl; + } + fpnum; + + /* Locale-dependent representation of decimal point. */ + const char *decimal; + wchar_t decimalwc; + + /* Locale-dependent thousands separator and grouping specification. */ + const char *thousands_sep = NULL; + wchar_t thousands_sepwc = 0; + const char *grouping; + + /* "NaN" or "Inf" for the special cases. */ + const char *special = NULL; + const wchar_t *wspecial = NULL; + + /* We need just a few limbs for the input before shifting to the right + position. */ + mp_limb_t fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB]; + /* We need to shift the contents of fp_input by this amount of bits. */ + int to_shift = 0; + + /* The fraction of the floting-point value in question */ + MPN_VAR(frac); + /* and the exponent. */ + int exponent; + /* Sign of the exponent. */ + int expsign = 0; + /* Sign of float number. */ + int is_neg = 0; + + /* Scaling factor. */ + MPN_VAR(scale); + + /* Temporary bignum value. */ + MPN_VAR(tmp); + + /* Digit which is result of last hack_digit() call. */ + wchar_t digit; + + /* The type of output format that will be used: 'e'/'E' or 'f'. */ + int type; + + /* Counter for number of written characters. */ + int done = 0; + + /* General helper (carry limb). */ + mp_limb_t cy; + + /* Nonzero if this is output on a wide character stream. */ + int wide = info->wide; + + auto wchar_t hack_digit (void); + + wchar_t hack_digit (void) + { + mp_limb_t hi; + + if (expsign != 0 && type == 'f' && exponent-- > 0) + hi = 0; + else if (scalesize == 0) + { + hi = frac[fracsize - 1]; + frac[fracsize - 1] = __mpn_mul_1 (frac, frac, fracsize - 1, 10); + } + else + { + if (fracsize < scalesize) + hi = 0; + else + { + hi = mpn_divmod (tmp, frac, fracsize, scale, scalesize); + tmp[fracsize - scalesize] = hi; + hi = tmp[0]; + + fracsize = scalesize; + while (fracsize != 0 && frac[fracsize - 1] == 0) + --fracsize; + if (fracsize == 0) + { + /* We're not prepared for an mpn variable with zero + limbs. */ + fracsize = 1; + return L'0' + hi; + } + } + + mp_limb_t _cy = __mpn_mul_1 (frac, frac, fracsize, 10); + if (_cy != 0) + frac[fracsize++] = _cy; + } + + return L'0' + hi; + } + + + /* Figure out the decimal point character. */ + if (info->extra == 0) + { + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); + decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); + } + else + { + decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT); + if (*decimal == '\0') + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); + decimalwc = _NL_CURRENT_WORD (LC_MONETARY, + _NL_MONETARY_DECIMAL_POINT_WC); + if (decimalwc == L'\0') + decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, + _NL_NUMERIC_DECIMAL_POINT_WC); + } + /* The decimal point character must not be zero. */ + assert (*decimal != '\0'); + assert (decimalwc != L'\0'); + + if (info->group) + { + if (info->extra == 0) + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + else + grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING); + + if (*grouping <= 0 || *grouping == CHAR_MAX) + grouping = NULL; + else + { + /* Figure out the thousands separator character. */ + if (wide) + { + if (info->extra == 0) + thousands_sepwc = + _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); + else + thousands_sepwc = + _NL_CURRENT_WORD (LC_MONETARY, + _NL_MONETARY_THOUSANDS_SEP_WC); + } + else + { + if (info->extra == 0) + thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); + else + thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP); + } + + if ((wide && thousands_sepwc == L'\0') + || (! wide && *thousands_sep == '\0')) + grouping = NULL; + else if (thousands_sepwc == L'\0') + /* If we are printing multibyte characters and there is a + multibyte representation for the thousands separator, + we must ensure the wide character thousands separator + is available, even if it is fake. */ + thousands_sepwc = 0xfffffffe; + } + } + else + grouping = NULL; + + /* Fetch the argument value. */ +#ifndef __NO_LONG_DOUBLE_MATH + if (info->is_long_double && sizeof (long double) > sizeof (double)) + { + fpnum.ldbl = *(const long double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnanl (fpnum.ldbl)) + { + if (isupper (info->spec)) + { + special = "NAN"; + wspecial = L"NAN"; + } + else + { + special = "nan"; + wspecial = L"nan"; + } + is_neg = 0; + } + else if (__isinfl (fpnum.ldbl)) + { + if (isupper (info->spec)) + { + special = "INF"; + wspecial = L"INF"; + } + else + { + special = "inf"; + wspecial = L"inf"; + } + is_neg = fpnum.ldbl < 0; + } + else + { + fracsize = __mpn_extract_long_double (fp_input, + (sizeof (fp_input) / + sizeof (fp_input[0])), + &exponent, &is_neg, + fpnum.ldbl); + to_shift = 1 + fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG; + } + } + else +#endif /* no long double */ + { + fpnum.dbl = *(const double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnan (fpnum.dbl)) + { + is_neg = 0; + if (isupper (info->spec)) + { + special = "NAN"; + wspecial = L"NAN"; + } + else + { + special = "nan"; + wspecial = L"nan"; + } + } + else if (__isinf (fpnum.dbl)) + { + is_neg = fpnum.dbl < 0; + if (isupper (info->spec)) + { + special = "INF"; + wspecial = L"INF"; + } + else + { + special = "inf"; + wspecial = L"inf"; + } + } + else + { + fracsize = __mpn_extract_double (fp_input, + (sizeof (fp_input) + / sizeof (fp_input[0])), + &exponent, &is_neg, fpnum.dbl); + to_shift = 1 + fracsize * BITS_PER_MP_LIMB - DBL_MANT_DIG; + } + } + + if (special) + { + int width = info->width; + + if (is_neg || info->showsign || info->space) + --width; + width -= 3; + + if (!info->left && width > 0) + PADN (' ', width); + + if (is_neg) + outchar ('-'); + else if (info->showsign) + outchar ('+'); + else if (info->space) + outchar (' '); + + PRINT (special, wspecial, 3); + + if (info->left && width > 0) + PADN (' ', width); + + return done; + } + + + /* We need three multiprecision variables. Now that we have the exponent + of the number we can allocate the needed memory. It would be more + efficient to use variables of the fixed maximum size but because this + would be really big it could lead to memory problems. */ + { + mp_size_t bignum_size = ((ABS (exponent) + BITS_PER_MP_LIMB - 1) + / BITS_PER_MP_LIMB + 4) * sizeof (mp_limb_t); + frac = (mp_limb_t *) alloca (bignum_size); + tmp = (mp_limb_t *) alloca (bignum_size); + scale = (mp_limb_t *) alloca (bignum_size); + } + + /* We now have to distinguish between numbers with positive and negative + exponents because the method used for the one is not applicable/efficient + for the other. */ + scalesize = 0; + if (exponent > 2) + { + /* |FP| >= 8.0. */ + int scaleexpo = 0; + int explog = LDBL_MAX_10_EXP_LOG; + int exp10 = 0; + const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; + int cnt_h, cnt_l, i; + + if ((exponent + to_shift) % BITS_PER_MP_LIMB == 0) + { + MPN_COPY_DECR (frac + (exponent + to_shift) / BITS_PER_MP_LIMB, + fp_input, fracsize); + fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB; + } + else + { + cy = __mpn_lshift (frac + (exponent + to_shift) / BITS_PER_MP_LIMB, + fp_input, fracsize, + (exponent + to_shift) % BITS_PER_MP_LIMB); + fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB; + if (cy) + frac[fracsize++] = cy; + } + MPN_ZERO (frac, (exponent + to_shift) / BITS_PER_MP_LIMB); + + assert (powers > &_fpioconst_pow10[0]); + do + { + --powers; + + /* The number of the product of two binary numbers with n and m + bits respectively has m+n or m+n-1 bits. */ + if (exponent >= scaleexpo + powers->p_expo - 1) + { + if (scalesize == 0) + { +#ifndef __NO_LONG_DOUBLE_MATH + if (LDBL_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB + && info->is_long_double) + { +#define _FPIO_CONST_SHIFT \ + (((LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \ + - _FPIO_CONST_OFFSET) + /* 64bit const offset is not enough for + IEEE quad long double. */ + tmpsize = powers->arraysize + _FPIO_CONST_SHIFT; + memcpy (tmp + _FPIO_CONST_SHIFT, + &__tens[powers->arrayoff], + tmpsize * sizeof (mp_limb_t)); + MPN_ZERO (tmp, _FPIO_CONST_SHIFT); + /* Adjust exponent, as scaleexpo will be this much + bigger too. */ + exponent += _FPIO_CONST_SHIFT * BITS_PER_MP_LIMB; + } + else +#endif + { + tmpsize = powers->arraysize; + memcpy (tmp, &__tens[powers->arrayoff], + tmpsize * sizeof (mp_limb_t)); + } + } + else + { + cy = __mpn_mul (tmp, scale, scalesize, + &__tens[powers->arrayoff + + _FPIO_CONST_OFFSET], + powers->arraysize - _FPIO_CONST_OFFSET); + tmpsize = scalesize + powers->arraysize - _FPIO_CONST_OFFSET; + if (cy == 0) + --tmpsize; + } + + if (MPN_GE (frac, tmp)) + { + int cnt; + MPN_ASSIGN (scale, tmp); + count_leading_zeros (cnt, scale[scalesize - 1]); + scaleexpo = (scalesize - 2) * BITS_PER_MP_LIMB - cnt - 1; + exp10 |= 1 << explog; + } + } + --explog; + } + while (powers > &_fpioconst_pow10[0]); + exponent = exp10; + + /* Optimize number representations. We want to represent the numbers + with the lowest number of bytes possible without losing any + bytes. Also the highest bit in the scaling factor has to be set + (this is a requirement of the MPN division routines). */ + if (scalesize > 0) + { + /* Determine minimum number of zero bits at the end of + both numbers. */ + for (i = 0; scale[i] == 0 && frac[i] == 0; i++) + ; + + /* Determine number of bits the scaling factor is misplaced. */ + count_leading_zeros (cnt_h, scale[scalesize - 1]); + + if (cnt_h == 0) + { + /* The highest bit of the scaling factor is already set. So + we only have to remove the trailing empty limbs. */ + if (i > 0) + { + MPN_COPY_INCR (scale, scale + i, scalesize - i); + scalesize -= i; + MPN_COPY_INCR (frac, frac + i, fracsize - i); + fracsize -= i; + } + } + else + { + if (scale[i] != 0) + { + count_trailing_zeros (cnt_l, scale[i]); + if (frac[i] != 0) + { + int cnt_l2; + count_trailing_zeros (cnt_l2, frac[i]); + if (cnt_l2 < cnt_l) + cnt_l = cnt_l2; + } + } + else + count_trailing_zeros (cnt_l, frac[i]); + + /* Now shift the numbers to their optimal position. */ + if (i == 0 && BITS_PER_MP_LIMB - cnt_h > cnt_l) + { + /* We cannot save any memory. So just roll both numbers + so that the scaling factor has its highest bit set. */ + + (void) __mpn_lshift (scale, scale, scalesize, cnt_h); + cy = __mpn_lshift (frac, frac, fracsize, cnt_h); + if (cy != 0) + frac[fracsize++] = cy; + } + else if (BITS_PER_MP_LIMB - cnt_h <= cnt_l) + { + /* We can save memory by removing the trailing zero limbs + and by packing the non-zero limbs which gain another + free one. */ + + (void) __mpn_rshift (scale, scale + i, scalesize - i, + BITS_PER_MP_LIMB - cnt_h); + scalesize -= i + 1; + (void) __mpn_rshift (frac, frac + i, fracsize - i, + BITS_PER_MP_LIMB - cnt_h); + fracsize -= frac[fracsize - i - 1] == 0 ? i + 1 : i; + } + else + { + /* We can only save the memory of the limbs which are zero. + The non-zero parts occupy the same number of limbs. */ + + (void) __mpn_rshift (scale, scale + (i - 1), + scalesize - (i - 1), + BITS_PER_MP_LIMB - cnt_h); + scalesize -= i; + (void) __mpn_rshift (frac, frac + (i - 1), + fracsize - (i - 1), + BITS_PER_MP_LIMB - cnt_h); + fracsize -= frac[fracsize - (i - 1) - 1] == 0 ? i : i - 1; + } + } + } + } + else if (exponent < 0) + { + /* |FP| < 1.0. */ + int exp10 = 0; + int explog = LDBL_MAX_10_EXP_LOG; + const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; + mp_size_t used_limbs = fracsize - 1; + + /* Now shift the input value to its right place. */ + cy = __mpn_lshift (frac, fp_input, fracsize, to_shift); + frac[fracsize++] = cy; + assert (cy == 1 || (frac[fracsize - 2] == 0 && frac[0] == 0)); + + expsign = 1; + exponent = -exponent; + + assert (powers != &_fpioconst_pow10[0]); + do + { + --powers; + + if (exponent >= powers->m_expo) + { + int i, incr, cnt_h, cnt_l; + mp_limb_t topval[2]; + + /* The __mpn_mul function expects the first argument to be + bigger than the second. */ + if (fracsize < powers->arraysize - _FPIO_CONST_OFFSET) + cy = __mpn_mul (tmp, &__tens[powers->arrayoff + + _FPIO_CONST_OFFSET], + powers->arraysize - _FPIO_CONST_OFFSET, + frac, fracsize); + else + cy = __mpn_mul (tmp, frac, fracsize, + &__tens[powers->arrayoff + _FPIO_CONST_OFFSET], + powers->arraysize - _FPIO_CONST_OFFSET); + tmpsize = fracsize + powers->arraysize - _FPIO_CONST_OFFSET; + if (cy == 0) + --tmpsize; + + count_leading_zeros (cnt_h, tmp[tmpsize - 1]); + incr = (tmpsize - fracsize) * BITS_PER_MP_LIMB + + BITS_PER_MP_LIMB - 1 - cnt_h; + + assert (incr <= powers->p_expo); + + /* If we increased the exponent by exactly 3 we have to test + for overflow. This is done by comparing with 10 shifted + to the right position. */ + if (incr == exponent + 3) + { + if (cnt_h <= BITS_PER_MP_LIMB - 4) + { + topval[0] = 0; + topval[1] + = ((mp_limb_t) 10) << (BITS_PER_MP_LIMB - 4 - cnt_h); + } + else + { + topval[0] = ((mp_limb_t) 10) << (BITS_PER_MP_LIMB - 4); + topval[1] = 0; + (void) __mpn_lshift (topval, topval, 2, + BITS_PER_MP_LIMB - cnt_h); + } + } + + /* We have to be careful when multiplying the last factor. + If the result is greater than 1.0 be have to test it + against 10.0. If it is greater or equal to 10.0 the + multiplication was not valid. This is because we cannot + determine the number of bits in the result in advance. */ + if (incr < exponent + 3 + || (incr == exponent + 3 && + (tmp[tmpsize - 1] < topval[1] + || (tmp[tmpsize - 1] == topval[1] + && tmp[tmpsize - 2] < topval[0])))) + { + /* The factor is right. Adapt binary and decimal + exponents. */ + exponent -= incr; + exp10 |= 1 << explog; + + /* If this factor yields a number greater or equal to + 1.0, we must not shift the non-fractional digits down. */ + if (exponent < 0) + cnt_h += -exponent; + + /* Now we optimize the number representation. */ + for (i = 0; tmp[i] == 0; ++i); + if (cnt_h == BITS_PER_MP_LIMB - 1) + { + MPN_COPY (frac, tmp + i, tmpsize - i); + fracsize = tmpsize - i; + } + else + { + count_trailing_zeros (cnt_l, tmp[i]); + + /* Now shift the numbers to their optimal position. */ + if (i == 0 && BITS_PER_MP_LIMB - 1 - cnt_h > cnt_l) + { + /* We cannot save any memory. Just roll the + number so that the leading digit is in a + separate limb. */ + + cy = __mpn_lshift (frac, tmp, tmpsize, cnt_h + 1); + fracsize = tmpsize + 1; + frac[fracsize - 1] = cy; + } + else if (BITS_PER_MP_LIMB - 1 - cnt_h <= cnt_l) + { + (void) __mpn_rshift (frac, tmp + i, tmpsize - i, + BITS_PER_MP_LIMB - 1 - cnt_h); + fracsize = tmpsize - i; + } + else + { + /* We can only save the memory of the limbs which + are zero. The non-zero parts occupy the same + number of limbs. */ + + (void) __mpn_rshift (frac, tmp + (i - 1), + tmpsize - (i - 1), + BITS_PER_MP_LIMB - 1 - cnt_h); + fracsize = tmpsize - (i - 1); + } + } + used_limbs = fracsize - 1; + } + } + --explog; + } + while (powers != &_fpioconst_pow10[1] && exponent > 0); + /* All factors but 10^-1 are tested now. */ + if (exponent > 0) + { + int cnt_l; + + cy = __mpn_mul_1 (tmp, frac, fracsize, 10); + tmpsize = fracsize; + assert (cy == 0 || tmp[tmpsize - 1] < 20); + + count_trailing_zeros (cnt_l, tmp[0]); + if (cnt_l < MIN (4, exponent)) + { + cy = __mpn_lshift (frac, tmp, tmpsize, + BITS_PER_MP_LIMB - MIN (4, exponent)); + if (cy != 0) + frac[tmpsize++] = cy; + } + else + (void) __mpn_rshift (frac, tmp, tmpsize, MIN (4, exponent)); + fracsize = tmpsize; + exp10 |= 1; + assert (frac[fracsize - 1] < 10); + } + exponent = exp10; + } + else + { + /* This is a special case. We don't need a factor because the + numbers are in the range of 0.0 <= fp < 8.0. We simply + shift it to the right place and divide it by 1.0 to get the + leading digit. (Of course this division is not really made.) */ + assert (0 <= exponent && exponent < 3 && + exponent + to_shift < BITS_PER_MP_LIMB); + + /* Now shift the input value to its right place. */ + cy = __mpn_lshift (frac, fp_input, fracsize, (exponent + to_shift)); + frac[fracsize++] = cy; + exponent = 0; + } + + { + int width = info->width; + wchar_t *wbuffer, *wstartp, *wcp; + int buffer_malloced; + int chars_needed; + int expscale; + int intdig_max, intdig_no = 0; + int fracdig_min, fracdig_max, fracdig_no = 0; + int dig_max; + int significant; + int ngroups = 0; + + if (_tolower (info->spec) == 'e') + { + type = info->spec; + intdig_max = 1; + fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec; + chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4; + /* d . ddd e +- ddd */ + dig_max = INT_MAX; /* Unlimited. */ + significant = 1; /* Does not matter here. */ + } + else if (_tolower (info->spec) == 'f') + { + type = 'f'; + fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec; + dig_max = INT_MAX; /* Unlimited. */ + significant = 1; /* Does not matter here. */ + if (expsign == 0) + { + intdig_max = exponent + 1; + /* This can be really big! */ /* XXX Maybe malloc if too big? */ + chars_needed = exponent + 1 + 1 + fracdig_max; + } + else + { + intdig_max = 1; + chars_needed = 1 + 1 + fracdig_max; + } + } + else + { + dig_max = info->prec < 0 ? 6 : (info->prec == 0 ? 1 : info->prec); + if ((expsign == 0 && exponent >= dig_max) + || (expsign != 0 && exponent > 4)) + { + if ('g' - 'G' == 'e' - 'E') + type = 'E' + (info->spec - 'G'); + else + type = isupper (info->spec) ? 'E' : 'e'; + fracdig_max = dig_max - 1; + intdig_max = 1; + chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4; + } + else + { + type = 'f'; + intdig_max = expsign == 0 ? exponent + 1 : 0; + fracdig_max = dig_max - intdig_max; + /* We need space for the significant digits and perhaps + for leading zeros when < 1.0. The number of leading + zeros can be as many as would be required for + exponential notation with a negative two-digit + exponent, which is 4. */ + chars_needed = dig_max + 1 + 4; + } + fracdig_min = info->alt ? fracdig_max : 0; + significant = 0; /* We count significant digits. */ + } + + if (grouping) + { + /* Guess the number of groups we will make, and thus how + many spaces we need for separator characters. */ + ngroups = __guess_grouping (intdig_max, grouping); + chars_needed += ngroups; + } + + /* Allocate buffer for output. We need two more because while rounding + it is possible that we need two more characters in front of all the + other output. If the amount of memory we have to allocate is too + large use `malloc' instead of `alloca'. */ + buffer_malloced = ! __libc_use_alloca (chars_needed * 2 * sizeof (wchar_t)); + if (buffer_malloced) + { + wbuffer = (wchar_t *) malloc ((2 + chars_needed) * sizeof (wchar_t)); + if (wbuffer == NULL) + /* Signal an error to the caller. */ + return -1; + } + else + wbuffer = (wchar_t *) alloca ((2 + chars_needed) * sizeof (wchar_t)); + wcp = wstartp = wbuffer + 2; /* Let room for rounding. */ + + /* Do the real work: put digits in allocated buffer. */ + if (expsign == 0 || type != 'f') + { + assert (expsign == 0 || intdig_max == 1); + while (intdig_no < intdig_max) + { + ++intdig_no; + *wcp++ = hack_digit (); + } + significant = 1; + if (info->alt + || fracdig_min > 0 + || (fracdig_max > 0 && (fracsize > 1 || frac[0] != 0))) + *wcp++ = decimalwc; + } + else + { + /* |fp| < 1.0 and the selected type is 'f', so put "0." + in the buffer. */ + *wcp++ = L'0'; + --exponent; + *wcp++ = decimalwc; + } + + /* Generate the needed number of fractional digits. */ + while (fracdig_no < fracdig_min + || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0))) + { + ++fracdig_no; + *wcp = hack_digit (); + if (*wcp++ != L'0') + significant = 1; + else if (significant == 0) + { + ++fracdig_max; + if (fracdig_min > 0) + ++fracdig_min; + } + } + + /* Do rounding. */ + digit = hack_digit (); + if (digit > L'4') + { + wchar_t *wtp = wcp; + + if (digit == L'5' + && ((*(wcp - 1) != decimalwc && (*(wcp - 1) & 1) == 0) + || ((*(wcp - 1) == decimalwc && (*(wcp - 2) & 1) == 0)))) + { + /* This is the critical case. */ + if (fracsize == 1 && frac[0] == 0) + /* Rest of the number is zero -> round to even. + (IEEE 754-1985 4.1 says this is the default rounding.) */ + goto do_expo; + else if (scalesize == 0) + { + /* Here we have to see whether all limbs are zero since no + normalization happened. */ + size_t lcnt = fracsize; + while (lcnt >= 1 && frac[lcnt - 1] == 0) + --lcnt; + if (lcnt == 0) + /* Rest of the number is zero -> round to even. + (IEEE 754-1985 4.1 says this is the default rounding.) */ + goto do_expo; + } + } + + if (fracdig_no > 0) + { + /* Process fractional digits. Terminate if not rounded or + radix character is reached. */ + while (*--wtp != decimalwc && *wtp == L'9') + *wtp = '0'; + if (*wtp != decimalwc) + /* Round up. */ + (*wtp)++; + } + + if (fracdig_no == 0 || *wtp == decimalwc) + { + /* Round the integer digits. */ + if (*(wtp - 1) == decimalwc) + --wtp; + + while (--wtp >= wstartp && *wtp == L'9') + *wtp = L'0'; + + if (wtp >= wstartp) + /* Round up. */ + (*wtp)++; + else + /* It is more critical. All digits were 9's. */ + { + if (type != 'f') + { + *wstartp = '1'; + exponent += expsign == 0 ? 1 : -1; + } + else if (intdig_no == dig_max) + { + /* This is the case where for type %g the number fits + really in the range for %f output but after rounding + the number of digits is too big. */ + *--wstartp = decimalwc; + *--wstartp = L'1'; + + if (info->alt || fracdig_no > 0) + { + /* Overwrite the old radix character. */ + wstartp[intdig_no + 2] = L'0'; + ++fracdig_no; + } + + fracdig_no += intdig_no; + intdig_no = 1; + fracdig_max = intdig_max - intdig_no; + ++exponent; + /* Now we must print the exponent. */ + type = isupper (info->spec) ? 'E' : 'e'; + } + else + { + /* We can simply add another another digit before the + radix. */ + *--wstartp = L'1'; + ++intdig_no; + } + + /* While rounding the number of digits can change. + If the number now exceeds the limits remove some + fractional digits. */ + if (intdig_no + fracdig_no > dig_max) + { + wcp -= intdig_no + fracdig_no - dig_max; + fracdig_no -= intdig_no + fracdig_no - dig_max; + } + } + } + } + + do_expo: + /* Now remove unnecessary '0' at the end of the string. */ + while (fracdig_no > fracdig_min && *(wcp - 1) == L'0') + { + --wcp; + --fracdig_no; + } + /* If we eliminate all fractional digits we perhaps also can remove + the radix character. */ + if (fracdig_no == 0 && !info->alt && *(wcp - 1) == decimalwc) + --wcp; + + if (grouping) + /* Add in separator characters, overwriting the same buffer. */ + wcp = group_number (wstartp, wcp, intdig_no, grouping, thousands_sepwc, + ngroups); + + /* Write the exponent if it is needed. */ + if (type != 'f') + { + *wcp++ = (wchar_t) type; + *wcp++ = expsign ? L'-' : L'+'; + + /* Find the magnitude of the exponent. */ + expscale = 10; + while (expscale <= exponent) + expscale *= 10; + + if (exponent < 10) + /* Exponent always has at least two digits. */ + *wcp++ = L'0'; + else + do + { + expscale /= 10; + *wcp++ = L'0' + (exponent / expscale); + exponent %= expscale; + } + while (expscale > 10); + *wcp++ = L'0' + exponent; + } + + /* Compute number of characters which must be filled with the padding + character. */ + if (is_neg || info->showsign || info->space) + --width; + width -= wcp - wstartp; + + if (!info->left && info->pad != '0' && width > 0) + PADN (info->pad, width); + + if (is_neg) + outchar ('-'); + else if (info->showsign) + outchar ('+'); + else if (info->space) + outchar (' '); + + if (!info->left && info->pad == '0' && width > 0) + PADN ('0', width); + + { + char *buffer = NULL; + char *cp = NULL; + char *tmpptr; + + if (! wide) + { + /* Create the single byte string. */ + size_t decimal_len; + size_t thousands_sep_len; + wchar_t *copywc; + + decimal_len = strlen (decimal); + + if (thousands_sep == NULL) + thousands_sep_len = 0; + else + thousands_sep_len = strlen (thousands_sep); + + if (buffer_malloced) + { + buffer = (char *) malloc (2 + chars_needed + decimal_len + + ngroups * thousands_sep_len); + if (buffer == NULL) + /* Signal an error to the caller. */ + return -1; + } + else + buffer = (char *) alloca (2 + chars_needed + decimal_len + + ngroups * thousands_sep_len); + + /* Now copy the wide character string. Since the character + (except for the decimal point and thousands separator) must + be coming from the ASCII range we can esily convert the + string without mapping tables. */ + for (cp = buffer, copywc = wstartp; copywc < wcp; ++copywc) + if (*copywc == decimalwc) + cp = (char *) __mempcpy (cp, decimal, decimal_len); + else if (*copywc == thousands_sepwc) + cp = (char *) __mempcpy (cp, thousands_sep, thousands_sep_len); + else + *cp++ = (char) *copywc; + } + + tmpptr = buffer; + PRINT (tmpptr, wstartp, wide ? wcp - wstartp : cp - tmpptr); + + /* Free the memory if necessary. */ + if (buffer_malloced) + { + free (buffer); + free (wbuffer); + } + } + + if (info->left && width > 0) + PADN (info->pad, width); + } + return done; +} +libc_hidden_def (__printf_fp) + +/* Return the number of extra grouping characters that will be inserted + into a number with INTDIG_MAX integer digits. */ + +unsigned int +__guess_grouping (unsigned int intdig_max, const char *grouping) +{ + unsigned int groups; + + /* We treat all negative values like CHAR_MAX. */ + + if (*grouping == CHAR_MAX || *grouping <= 0) + /* No grouping should be done. */ + return 0; + + groups = 0; + while (intdig_max > (unsigned int) *grouping) + { + ++groups; + intdig_max -= *grouping++; + + if (*grouping == CHAR_MAX +#if CHAR_MIN < 0 + || *grouping < 0 +#endif + ) + /* No more grouping should be done. */ + break; + else if (*grouping == 0) + { + /* Same grouping repeats. */ + groups += (intdig_max - 1) / grouping[-1]; + break; + } + } + + return groups; +} + +/* Group the INTDIG_NO integer digits of the number in [BUF,BUFEND). + There is guaranteed enough space past BUFEND to extend it. + Return the new end of buffer. */ + +static wchar_t * +internal_function +group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no, + const char *grouping, wchar_t thousands_sep, int ngroups) +{ + wchar_t *p; + + if (ngroups == 0) + return bufend; + + /* Move the fractional part down. */ + __wmemmove (buf + intdig_no + ngroups, buf + intdig_no, + bufend - (buf + intdig_no)); + + p = buf + intdig_no + ngroups - 1; + do + { + unsigned int len = *grouping++; + do + *p-- = buf[--intdig_no]; + while (--len > 0); + *p-- = thousands_sep; + + if (*grouping == CHAR_MAX +#if CHAR_MIN < 0 + || *grouping < 0 +#endif + ) + /* No more grouping should be done. */ + break; + else if (*grouping == 0) + /* Same grouping repeats. */ + --grouping; + } while (intdig_no > (unsigned int) *grouping); + + /* Copy the remaining ungrouped digits. */ + do + *p-- = buf[--intdig_no]; + while (p > buf); + + return bufend + ngroups; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/printf_size.c b/src/kernel/libroot/posix/glibc/stdio-common/printf_size.c new file mode 100644 index 0000000000..4f2807bf77 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/printf_size.c @@ -0,0 +1,266 @@ +/* Print size value using units for orders of magnitude. + Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + Based on a proposal by Larry McVoy . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#else +# include +#endif + + +/* This defines make it possible to use the same code for GNU C library and + the GNU I/O library. */ +#ifdef USE_IN_LIBIO +# define PUT(f, s, n) _IO_sputn (f, s, n) +# define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : INTUSE(_IO_padn) (f, c, n)) +/* We use this file GNU C library and GNU I/O library. So make + names equal. */ +# undef putc +# define putc(c, f) (wide \ + ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f)) +# define size_t _IO_size_t +# define FILE _IO_FILE +#else /* ! USE_IN_LIBIO */ +# define PUT(f, s, n) fwrite (s, 1, n, f) +# define PAD(f, c, n) __printf_pad (f, c, n) +ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */ +#endif /* USE_IN_LIBIO */ + +/* Macros for doing the actual output. */ + +#define outchar(ch) \ + do \ + { \ + register const int outc = (ch); \ + if (putc (outc, fp) == EOF) \ + return -1; \ + ++done; \ + } while (0) + +#define PRINT(ptr, wptr, len) \ + do \ + { \ + register size_t outlen = (len); \ + if (len > 20) \ + { \ + if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen) \ + return -1; \ + ptr += outlen; \ + done += outlen; \ + } \ + else \ + { \ + if (wide) \ + while (outlen-- > 0) \ + outchar (*wptr++); \ + else \ + while (outlen-- > 0) \ + outchar (*ptr++); \ + } \ + } while (0) + +#define PADN(ch, len) \ + do \ + { \ + if (PAD (fp, ch, len) != len) \ + return -1; \ + done += len; \ + } \ + while (0) + +/* Prototype for helper functions. */ +extern int __printf_fp (FILE *fp, const struct printf_info *info, + const void *const *args); + + +int +printf_size (FILE *fp, const struct printf_info *info, const void *const *args) +{ + /* Units for the both formats. */ +#define BINARY_UNITS " kmgtpezy" +#define DECIMAL_UNITS " KMGTPEZY" + static const char units[2][sizeof (BINARY_UNITS)] = + { + BINARY_UNITS, /* For binary format. */ + DECIMAL_UNITS /* For decimal format. */ + }; + const char *tag = units[isupper (info->spec) != 0]; + int divisor = isupper (info->spec) ? 1000 : 1024; + + /* The floating-point value to output. */ + union + { + union ieee754_double dbl; + union ieee854_long_double ldbl; + } + fpnum; + const void *ptr = &fpnum; + + int negative = 0; + + /* "NaN" or "Inf" for the special cases. */ + const char *special = NULL; + const wchar_t *wspecial = NULL; + + struct printf_info fp_info; + int done = 0; + int wide = info->wide; + + + /* Fetch the argument value. */ +#ifndef __NO_LONG_DOUBLE_MATH + if (info->is_long_double && sizeof (long double) > sizeof (double)) + { + fpnum.ldbl.d = *(const long double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnanl (fpnum.ldbl.d)) + { + special = "nan"; + wspecial = L"nan"; + negative = 0; + } + else if (__isinfl (fpnum.ldbl.d)) + { + special = "inf"; + wspecial = L"inf"; + + negative = fpnum.ldbl.d < 0; + } + else + while (fpnum.ldbl.d >= divisor && tag[1] != '\0') + { + fpnum.ldbl.d /= divisor; + ++tag; + } + } + else +#endif /* no long double */ + { + fpnum.dbl.d = *(const double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnan (fpnum.dbl.d)) + { + special = "nan"; + wspecial = L"nan"; + negative = 0; + } + else if (__isinf (fpnum.dbl.d)) + { + special = "inf"; + wspecial = L"inf"; + + negative = fpnum.dbl.d < 0; + } + else + while (fpnum.dbl.d >= divisor && tag[1] != '\0') + { + fpnum.dbl.d /= divisor; + ++tag; + } + } + + if (special) + { + int width = info->prec > width ? info->prec : width; + + if (negative || info->showsign || info->space) + --width; + width -= 3; + + if (!info->left && width > 0) + PADN (' ', width); + + if (negative) + outchar ('-'); + else if (info->showsign) + outchar ('+'); + else if (info->space) + outchar (' '); + + PRINT (special, wspecial, 3); + + if (info->left && width > 0) + PADN (' ', width); + + return done; + } + + /* Prepare to print the number. We want to use `__printf_fp' so we + have to prepare a `printf_info' structure. */ + fp_info.spec = 'f'; + fp_info.prec = info->prec < 0 ? 3 : info->prec; + fp_info.is_long_double = info->is_long_double; + fp_info.is_short = info->is_short; + fp_info.is_long = info->is_long; + fp_info.alt = info->alt; + fp_info.space = info->space; + fp_info.left = info->left; + fp_info.showsign = info->showsign; + fp_info.group = info->group; + fp_info.extra = info->extra; + fp_info.pad = info->pad; + fp_info.wide = wide; + + if (fp_info.left && fp_info.pad == L' ') + { + /* We must do the padding ourself since the unit character must + be placed before the padding spaces. */ + fp_info.width = 0; + + done = __printf_fp (fp, &fp_info, &ptr); + if (done > 0) + { + outchar (*tag); + if (info->width > done) + PADN (' ', info->width - done); + } + } + else + { + /* We can let __printf_fp do all the printing and just add our + unit character afterwards. */ + fp_info.width = info->width - 1; + + done = __printf_fp (fp, &fp_info, &ptr); + if (done > 0) + outchar (*tag); + } + + return done; +} + +/* This is the function used by `vfprintf' to determine number and + type of the arguments. */ +int +printf_size_info (const struct printf_info *info, size_t n, int *argtypes) +{ + /* We need only one double or long double argument. */ + if (n >= 1) + argtypes[0] = PA_DOUBLE | (info->is_long_double ? PA_FLAG_LONG_DOUBLE : 0); + + return 1; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/psignal.c b/src/kernel/libroot/posix/glibc/stdio-common/psignal.c new file mode 100644 index 0000000000..c756394e8c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/psignal.c @@ -0,0 +1,74 @@ +/* Copyright (C) 1991,1992,1995-1997,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#endif + + +#ifndef HAVE_GNU_LD +#define _sys_siglist sys_siglist +#endif + +/* Defined in sys_siglist.c. */ +extern const char *const _sys_siglist[]; +extern const char *const _sys_siglist_internal[] attribute_hidden; + + +/* Print out on stderr a line consisting of the test in S, a colon, a space, + a message describing the meaning of the signal number SIG and a newline. + If S is NULL or "", the colon and space are omitted. */ +void +psignal (int sig, const char *s) +{ + const char *colon, *desc; + + if (s == NULL || s == '\0') + s = colon = ""; + else + colon = ": "; + + if (sig >= 0 && sig < NSIG && (desc = INTUSE(_sys_siglist)[sig]) != NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s%s%s\n", s, colon, _(desc)); + else +#endif + (void) fprintf (stderr, "%s%s%s\n", s, colon, _(desc)); + } + else + { + char *buf; + + (void) __asprintf (&buf, _("%s%sUnknown signal %d\n"), s, colon, sig); + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", buf); + else +#endif + (void) fputs (buf, stderr); + + free (buf); + } +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/putw.c b/src/kernel/libroot/posix/glibc/stdio-common/putw.c new file mode 100644 index 0000000000..ddf9cedb8d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/putw.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef USE_IN_LIBIO +# include +# define fwrite(p, n, m, s) INTUSE(_IO_fwrite) (p, n, m, s) +#endif + +/* Write the word (int) W to STREAM. */ +int +putw (int w, FILE *stream) +{ + /* Is there a better way? */ + if (fwrite ((const void *) &w, sizeof (w), 1, stream) < 1) + return EOF; + return 0; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/reg-printf.c b/src/kernel/libroot/posix/glibc/stdio-common/reg-printf.c new file mode 100644 index 0000000000..672652ab20 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/reg-printf.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1991, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* Array of functions indexed by format character. */ +libc_freeres_ptr (printf_arginfo_function **__printf_arginfo_table) + attribute_hidden; +printf_function **__printf_function_table attribute_hidden; + +int __register_printf_function __P ((int, printf_function, + printf_arginfo_function)); + +/* Register FUNC to be called to format SPEC specifiers. */ +int +__register_printf_function (spec, converter, arginfo) + int spec; + printf_function converter; + printf_arginfo_function arginfo; +{ + if (spec < 0 || spec > (int) UCHAR_MAX) + { + __set_errno (EINVAL); + return -1; + } + + if (__printf_function_table == NULL) + { + __printf_arginfo_table = (printf_arginfo_function **) + malloc ((UCHAR_MAX + 1) * sizeof (void *) * 2); + if (__printf_arginfo_table == NULL) + return -1; + __printf_function_table = (printf_function **) + (__printf_arginfo_table + UCHAR_MAX + 1); + } + + __printf_function_table[spec] = converter; + __printf_arginfo_table[spec] = arginfo; + + return 0; +} +weak_alias (__register_printf_function, register_printf_function) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/scanf.c b/src/kernel/libroot/posix/glibc/stdio-common/scanf.c new file mode 100644 index 0000000000..268aa905f8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/scanf.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef USE_IN_LIBIO +# include +#endif + + +/* Read formatted input from stdin according to the format string FORMAT. */ +/* VARARGS1 */ +int +scanf (const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); +#ifdef USE_IN_LIBIO + done = INTUSE(_IO_vfscanf) (stdin, format, arg, NULL); +#else + done = vfscanf (stdin, format, arg); +#endif + va_end (arg); + + return done; +} diff --git a/src/kernel/libroot/posix/glibc/stdio-common/snprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/snprintf.c new file mode 100644 index 0000000000..a880c4a126 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/snprintf.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef USE_IN_LIBIO +# include +# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) +#endif + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS3 */ +int +__snprintf (char *s, size_t maxlen, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vsnprintf (s, maxlen, format, arg); + va_end (arg); + + return done; +} +weak_alias (__snprintf, snprintf) diff --git a/src/kernel/libroot/posix/glibc/stdio-common/sprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/sprintf.c new file mode 100644 index 0000000000..07e2654993 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/sprintf.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991, 1995, 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef USE_IN_LIBIO +# include +# define vsprintf(s, f, a) INTUSE(_IO_vsprintf) (s, f, a) +#endif + +/* Write formatted output into S, according to the format string FORMAT. */ +/* VARARGS2 */ +int +sprintf (char *s, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vsprintf (s, format, arg); + va_end (arg); + + return done; +} +libc_hidden_def (sprintf) + +#ifdef USE_IN_LIBIO +strong_alias(sprintf, _IO_sprintf) +#endif diff --git a/src/kernel/libroot/posix/glibc/stdio-common/sscanf.c b/src/kernel/libroot/posix/glibc/stdio-common/sscanf.c new file mode 100644 index 0000000000..ed4cb1d3a1 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/sscanf.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991,1995,1996,1998,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef USE_IN_LIBIO +# include +# define __vsscanf(s, f, a) _IO_vsscanf (s, f, a) +#endif + +/* Read formatted input from S, according to the format string FORMAT. */ +/* VARARGS2 */ +int +sscanf (const char *s, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vsscanf (s, format, arg); + va_end (arg); + + return done; +} +libc_hidden_def (sscanf) + +#ifdef USE_IN_LIBIO +# undef _IO_sscanf +/* This is for libg++. */ +strong_alias (sscanf, _IO_sscanf) +#endif diff --git a/src/kernel/libroot/posix/glibc/stdio-common/stdio_ext.h b/src/kernel/libroot/posix/glibc/stdio-common/stdio_ext.h new file mode 100644 index 0000000000..55586ea841 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/stdio_ext.h @@ -0,0 +1,87 @@ +/* Functions to access FILE structure internals. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This header contains the same definitions as the header of the same name + on Sun's Solaris OS. */ + +#ifndef _STDIO_EXT_H +#define _STDIO_EXT_H 1 + +#include + +enum +{ + /* Query current state of the locking status. */ + FSETLOCKING_QUERY = 0, +#define FSETLOCKING_QUERY FSETLOCKING_QUERY + /* The library protects all uses of the stream functions, except for + uses of the *_unlocked functions, by calls equivalent to flockfile(). */ + FSETLOCKING_INTERNAL, +#define FSETLOCKING_INTERNAL FSETLOCKING_INTERNAL + /* The user will take care of locking. */ + FSETLOCKING_BYCALLER +#define FSETLOCKING_BYCALLER FSETLOCKING_BYCALLER +}; + + +__BEGIN_DECLS + +/* Return the size of the buffer of FP in bytes currently in use by + the given stream. */ +extern size_t __fbufsize (FILE *__fp); + + +/* Return non-zero value iff the stream FP is opened readonly, or if the + last operation on the stream was a read operation. */ +extern int __freading (FILE *__fp); + +/* Return non-zero value iff the stream FP is opened write-only or + append-only, or if the last operation on the stream was a write + operation. */ +extern int __fwriting (FILE *__fp); + + +/* Return non-zero value iff stream FP is not opened write-only or + append-only. */ +extern int __freadable (FILE *__fp); + +/* Return non-zero value iff stream FP is not opened read-only. */ +extern int __fwritable (FILE *__fp); + + +/* Return non-zero value iff the stream FP is line-buffered. */ +extern int __flbf (FILE *__fp); + + +/* Discard all pending buffered I/O on the stream FP. */ +extern void __fpurge (FILE *__fp); + +/* Return amount of output in bytes pending on a stream FP. */ +extern size_t __fpending (FILE *__fp); + +/* Flush all line-buffered files. */ +extern void _flushlbf (void); + + +/* Set locking status of stream FP to TYPE. */ +extern int __fsetlocking (FILE *__fp, int __type); + +__END_DECLS + +#endif /* stdio_ext.h */ diff --git a/src/kernel/libroot/posix/glibc/stdio-common/stdio_lim.h.in b/src/kernel/libroot/posix/glibc/stdio-common/stdio_lim.h.in new file mode 100644 index 0000000000..bb496c59de --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/stdio_lim.h.in @@ -0,0 +1,41 @@ +/* Copyright (C) 1994, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _STDIO_H && !defined __need_FOPEN_MAX && !defined __need_IOV_MAX +# error "Never include directly; use instead." +#endif + +#ifdef _STDIO_H +# define L_tmpnam @L_tmpnam@ +# define TMP_MAX @TMP_MAX@ +# define FILENAME_MAX @FILENAME_MAX@ + +# ifdef __USE_POSIX +# define L_ctermid @L_ctermid@ +# define L_cuserid @L_cuserid@ +# endif +#endif + +#if defined __need_FOPEN_MAX || defined _STDIO_H +# undef FOPEN_MAX +# define FOPEN_MAX @FOPEN_MAX@ +#endif + +#if defined __need_IOV_MAX && !defined IOV_MAX +@define_IOV_MAX@ +#endif diff --git a/src/kernel/libroot/posix/glibc/stdio-common/tempnam.c b/src/kernel/libroot/posix/glibc/stdio-common/tempnam.c new file mode 100644 index 0000000000..cd3dd40f90 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/tempnam.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Generate a unique temporary filename using up to five characters of PFX + if it is not NULL. The directory to put this file in is searched for + as follows: First the environment variable "TMPDIR" is checked. + If it contains the name of a writable directory, that directory is used. + If not and if DIR is not NULL, that value is checked. If that fails, + P_tmpdir is tried and finally "/tmp". The storage for the filename + is allocated by `malloc'. */ +char * +tempnam (const char *dir, const char *pfx) +{ + char buf[FILENAME_MAX]; + + if (__path_search (buf, FILENAME_MAX, dir, pfx, 1)) + return NULL; + + if (__gen_tempname (buf, __GT_NOCREATE)) + return NULL; + + return __strdup (buf); +} + +link_warning (tempnam, + "the use of `tempnam' is dangerous, better use `mkstemp'") diff --git a/src/kernel/libroot/posix/glibc/stdio-common/tmpnam.c b/src/kernel/libroot/posix/glibc/stdio-common/tmpnam.c new file mode 100644 index 0000000000..6b26f4fff6 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/tmpnam.c @@ -0,0 +1,52 @@ +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +static char tmpnam_buffer[L_tmpnam]; + +/* Generate a unique filename in P_tmpdir. + + This function is *not* thread safe! */ +char * +tmpnam (char *s) +{ + /* By using two buffers we manage to be thread safe in the case + where S != NULL. */ + char tmpbufmem[L_tmpnam]; + char *tmpbuf = s ?: tmpbufmem; + + /* In the following call we use the buffer pointed to by S if + non-NULL although we don't know the size. But we limit the size + to L_tmpnam characters in any case. */ + if (__builtin_expect (__path_search (tmpbuf, L_tmpnam, NULL, NULL, 0), + 0)) + return NULL; + + if (__builtin_expect (__gen_tempname (tmpbuf, __GT_NOCREATE), 0)) + return NULL; + + if (s == NULL) + return (char *) memcpy (tmpnam_buffer, tmpbuf, L_tmpnam); + + return s; +} + +link_warning (tmpnam, + "the use of `tmpnam' is dangerous, better use `mkstemp'") diff --git a/src/kernel/libroot/posix/glibc/stdio-common/tmpnam_r.c b/src/kernel/libroot/posix/glibc/stdio-common/tmpnam_r.c new file mode 100644 index 0000000000..565a42401f --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/tmpnam_r.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Generate a unique filename in P_tmpdir. If S is NULL return NULL. + This makes this function thread safe. */ +char * +tmpnam_r (char *s) +{ + if (s == NULL) + return NULL; + + if (__path_search (s, L_tmpnam, NULL, NULL, 0)) + return NULL; + if (__gen_tempname (s, __GT_NOCREATE)) + return NULL; + + return s; +} + +link_warning (tmpnam_r, + "the use of `tmpnam_r' is dangerous, better use `mkstemp'") diff --git a/src/kernel/libroot/posix/glibc/stdio-common/vfprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/vfprintf.c new file mode 100644 index 0000000000..087bf91b21 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/vfprintf.c @@ -0,0 +1,2284 @@ +/* Copyright (C) 1991-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "_itoa.h" +#include +#include + +/* This code is shared between the standard stdio implementation found + in GNU C library and the libio implementation originally found in + GNU libg++. + + Beside this it is also shared between the normal and wide character + implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995. */ + + +#ifdef USE_IN_LIBIO +/* This code is for use in libio. */ +# include +# define FILE _IO_FILE +# undef va_list +# define va_list _IO_va_list +# undef BUFSIZ +# define BUFSIZ _IO_BUFSIZ +# define ARGCHECK(S, Format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + CHECK_FILE (S, -1); \ + if (S->_flags & _IO_NO_WRITES) \ + { \ + __set_errno (EBADF); \ + return -1; \ + } \ + if (Format == NULL) \ + { \ + MAYBE_SET_EINVAL; \ + return -1; \ + } \ + } while (0) +# define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED) + +# ifndef COMPILE_WPRINTF +# define vfprintf _IO_vfprintf +# define CHAR_T char +# define UCHAR_T unsigned char +# define INT_T int +# define L_(Str) Str +# define ISDIGIT(Ch) ((unsigned int) ((Ch) - '0') < 10) + +# define PUT(F, S, N) _IO_sputn ((F), (S), (N)) +# define PAD(Padchar) \ + if (width > 0) \ + done += INTUSE(_IO_padn) (s, (Padchar), width) +# define PUTC(C, F) _IO_putc_unlocked (C, F) +# define ORIENT if (s->_vtable_offset == 0 && _IO_fwide (s, -1) != -1)\ + return -1 +# else +# define vfprintf _IO_vfwprintf +# define CHAR_T wchar_t +/* This is a hack!!! There should be a type uwchar_t. */ +# define UCHAR_T unsigned int /* uwchar_t */ +# define INT_T wint_t +# define L_(Str) L##Str +# define ISDIGIT(Ch) ((unsigned int) ((Ch) - L'0') < 10) + +# include "_itowa.h" + +# define PUT(F, S, N) _IO_sputn ((F), (S), (N)) +# define PAD(Padchar) \ + if (width > 0) \ + done += _IO_wpadn (s, (Padchar), width) +# define PUTC(C, F) _IO_putwc_unlocked (C, F) +# define ORIENT if (_IO_fwide (s, 1) != 1) return -1 + +# define _itoa(Val, Buf, Base, Case) _itowa (Val, Buf, Base, Case) +# define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, Buf, Base, Case) +# undef EOF +# define EOF WEOF +# endif +#else /* ! USE_IN_LIBIO */ +/* This code is for use in the GNU C library. */ +# define ARGCHECK(S, Format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + if (!__validfp (S) || !S->__mode.__write) \ + { \ + __set_errno (EBADF); \ + return -1; \ + } \ + if (Format == NULL) \ + { \ + __set_errno (EINVAL); \ + return -1; \ + } \ + if (!S->__seen) \ + { \ + if (__flshfp (S, EOF) == EOF) \ + return -1; \ + } \ + } \ + while (0) +# define UNBUFFERED_P(s) ((s)->__buffer == NULL) + +# define CHAR_T char +# define UCHAR_T unsigned char +# define INT_T int +# define L_(Str) Str +# define ISDIGIT(Ch) isdigit (Ch) + +# define PUT(F, S, N) fwrite (S, 1, N, F) +ssize_t __printf_pad __P ((FILE *, char pad, size_t n)); +# define PAD(Padchar) \ + if (width > 0) \ + { ssize_t __res = __printf_pad (s, (Padchar), width); \ + if (__res == -1) \ + { \ + done = -1; \ + goto all_done; \ + } \ + done += __res; } +# define PUTC(C, F) putc (C, F) + +/* XXX These declarations should go as soon as the stdio header files + have these prototypes. */ +extern void __flockfile (FILE *); +extern void __funlockfile (FILE *); +#endif /* USE_IN_LIBIO */ + +#include "_i18n_number.h" + +/* Include the shared code for parsing the format string. */ +#include "printf-parse.h" + + +#define outchar(Ch) \ + do \ + { \ + register const INT_T outc = (Ch); \ + if (PUTC (outc, s) == EOF) \ + { \ + done = -1; \ + goto all_done; \ + } \ + else \ + ++done; \ + } \ + while (0) + +#define outstring(String, Len) \ + do \ + { \ + if ((size_t) PUT (s, (String), (Len)) != (size_t) (Len)) \ + { \ + done = -1; \ + goto all_done; \ + } \ + done += (Len); \ + } \ + while (0) + +/* For handling long_double and longlong we use the same flag. If + `long' and `long long' are effectively the same type define it to + zero. */ +#if LONG_MAX == LONG_LONG_MAX +# define is_longlong 0 +#else +# define is_longlong is_long_double +#endif + +/* If `long' and `int' is effectively the same type we don't have to + handle `long separately. */ +#if INT_MAX == LONG_MAX +# define is_long_num 0 +#else +# define is_long_num is_long +#endif + + +/* Global variables. */ +static const CHAR_T null[] = L_("(null)"); + + +/* Helper function to provide temporary buffering for unbuffered streams. */ +static int buffered_vfprintf __P ((FILE *stream, const CHAR_T *fmt, va_list)) + internal_function; + +/* Handle unknown format specifier. */ +static int printf_unknown __P ((FILE *, const struct printf_info *, + const void *const *)); + +/* Group digits of number string. */ +#ifdef COMPILE_WPRINTF +static CHAR_T *group_number __P ((CHAR_T *, CHAR_T *, const char *, wchar_t)) + internal_function; +#else +static CHAR_T *group_number __P ((CHAR_T *, CHAR_T *, const char *, + const char *)) internal_function; +#endif + + +/* The function itself. */ +int +vfprintf (FILE *s, const CHAR_T *format, va_list ap) +{ + /* The character used as thousands separator. */ +#ifdef COMPILE_WPRINTF + wchar_t thousands_sep = L'\0'; +#else + const char *thousands_sep = NULL; +#endif + + /* The string describing the size of groups of digits. */ + const char *grouping; + + /* Place to accumulate the result. */ + int done; + + /* Current character in format string. */ + const UCHAR_T *f; + + /* End of leading constant string. */ + const UCHAR_T *lead_str_end; + + /* Points to next format specifier. */ + const UCHAR_T *end_of_spec; + + /* Buffer intermediate results. */ + CHAR_T work_buffer[1000]; + CHAR_T *workstart = NULL; + CHAR_T *workend; + + /* State for restartable multibyte character handling functions. */ +#ifndef COMPILE_WPRINTF + mbstate_t mbstate; +#endif + + /* We have to save the original argument pointer. */ + va_list ap_save; + + /* Count number of specifiers we already processed. */ + int nspecs_done; + + /* For the %m format we may need the current `errno' value. */ + int save_errno = errno; + + + /* This table maps a character into a number representing a + class. In each step there is a destination label for each + class. */ + static const int jump_table[] = + { + /* ' ' */ 1, 0, 0, /* '#' */ 4, + 0, /* '%' */ 14, 0, /* '\''*/ 6, + 0, 0, /* '*' */ 7, /* '+' */ 2, + 0, /* '-' */ 3, /* '.' */ 9, 0, + /* '0' */ 5, /* '1' */ 8, /* '2' */ 8, /* '3' */ 8, + /* '4' */ 8, /* '5' */ 8, /* '6' */ 8, /* '7' */ 8, + /* '8' */ 8, /* '9' */ 8, 0, 0, + 0, 0, 0, 0, + 0, /* 'A' */ 26, 0, /* 'C' */ 25, + 0, /* 'E' */ 19, /* F */ 19, /* 'G' */ 19, + 0, /* 'I' */ 29, 0, 0, + /* 'L' */ 12, 0, 0, 0, + 0, 0, 0, /* 'S' */ 21, + 0, 0, 0, 0, + /* 'X' */ 18, 0, /* 'Z' */ 13, 0, + 0, 0, 0, 0, + 0, /* 'a' */ 26, 0, /* 'c' */ 20, + /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19, + /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28, 0, + /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17, + /* 'p' */ 22, /* 'q' */ 12, 0, /* 's' */ 21, + /* 't' */ 27, /* 'u' */ 16, 0, 0, + /* 'x' */ 18, 0, /* 'z' */ 13 + }; + +#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < L_(' ') || (Ch) > L_('z')) +#define CHAR_CLASS(Ch) (jump_table[(INT_T) (Ch) - L_(' ')]) +#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED + /* 'int' is enough and it saves some space on 64 bit systems. */ +# define JUMP_TABLE_TYPE const int +# define JUMP(ChExpr, table) \ + do \ + { \ + int offset; \ + void *__unbounded ptr; \ + spec = (ChExpr); \ + offset = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown) \ + : table[CHAR_CLASS (spec)]; \ + ptr = &&do_form_unknown + offset; \ + goto *ptr; \ + } \ + while (0) +#else +# define JUMP_TABLE_TYPE const void *const +# define JUMP(ChExpr, table) \ + do \ + { \ + const void *__unbounded ptr; \ + spec = (ChExpr); \ + ptr = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown) \ + : table[CHAR_CLASS (spec)]; \ + goto *ptr; \ + } \ + while (0) +#endif + +#define STEP0_3_TABLE \ + /* Step 0: at the beginning. */ \ + static JUMP_TABLE_TYPE step0_jumps[30] = \ + { \ + REF (form_unknown), \ + REF (flag_space), /* for ' ' */ \ + REF (flag_plus), /* for '+' */ \ + REF (flag_minus), /* for '-' */ \ + REF (flag_hash), /* for '' */ \ + REF (flag_zero), /* for '0' */ \ + REF (flag_quote), /* for '\'' */ \ + REF (width_asterics), /* for '*' */ \ + REF (width), /* for '1'...'9' */ \ + REF (precision), /* for '.' */ \ + REF (mod_half), /* for 'h' */ \ + REF (mod_long), /* for 'l' */ \ + REF (mod_longlong), /* for 'L', 'q' */ \ + REF (mod_size_t), /* for 'z', 'Z' */ \ + REF (form_percent), /* for '%' */ \ + REF (form_integer), /* for 'd', 'i' */ \ + REF (form_unsigned), /* for 'u' */ \ + REF (form_octal), /* for 'o' */ \ + REF (form_hexa), /* for 'X', 'x' */ \ + REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \ + REF (form_character), /* for 'c' */ \ + REF (form_string), /* for 's', 'S' */ \ + REF (form_pointer), /* for 'p' */ \ + REF (form_number), /* for 'n' */ \ + REF (form_strerror), /* for 'm' */ \ + REF (form_wcharacter), /* for 'C' */ \ + REF (form_floathex), /* for 'A', 'a' */ \ + REF (mod_ptrdiff_t), /* for 't' */ \ + REF (mod_intmax_t), /* for 'j' */ \ + REF (flag_i18n), /* for 'I' */ \ + }; \ + /* Step 1: after processing width. */ \ + static JUMP_TABLE_TYPE step1_jumps[30] = \ + { \ + REF (form_unknown), \ + REF (form_unknown), /* for ' ' */ \ + REF (form_unknown), /* for '+' */ \ + REF (form_unknown), /* for '-' */ \ + REF (form_unknown), /* for '' */ \ + REF (form_unknown), /* for '0' */ \ + REF (form_unknown), /* for '\'' */ \ + REF (form_unknown), /* for '*' */ \ + REF (form_unknown), /* for '1'...'9' */ \ + REF (precision), /* for '.' */ \ + REF (mod_half), /* for 'h' */ \ + REF (mod_long), /* for 'l' */ \ + REF (mod_longlong), /* for 'L', 'q' */ \ + REF (mod_size_t), /* for 'z', 'Z' */ \ + REF (form_percent), /* for '%' */ \ + REF (form_integer), /* for 'd', 'i' */ \ + REF (form_unsigned), /* for 'u' */ \ + REF (form_octal), /* for 'o' */ \ + REF (form_hexa), /* for 'X', 'x' */ \ + REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \ + REF (form_character), /* for 'c' */ \ + REF (form_string), /* for 's', 'S' */ \ + REF (form_pointer), /* for 'p' */ \ + REF (form_number), /* for 'n' */ \ + REF (form_strerror), /* for 'm' */ \ + REF (form_wcharacter), /* for 'C' */ \ + REF (form_floathex), /* for 'A', 'a' */ \ + REF (mod_ptrdiff_t), /* for 't' */ \ + REF (mod_intmax_t), /* for 'j' */ \ + REF (flag_i18n) /* for 'I' */ \ + }; \ + /* Step 2: after processing precision. */ \ + static JUMP_TABLE_TYPE step2_jumps[30] = \ + { \ + REF (form_unknown), \ + REF (form_unknown), /* for ' ' */ \ + REF (form_unknown), /* for '+' */ \ + REF (form_unknown), /* for '-' */ \ + REF (form_unknown), /* for '' */ \ + REF (form_unknown), /* for '0' */ \ + REF (form_unknown), /* for '\'' */ \ + REF (form_unknown), /* for '*' */ \ + REF (form_unknown), /* for '1'...'9' */ \ + REF (form_unknown), /* for '.' */ \ + REF (mod_half), /* for 'h' */ \ + REF (mod_long), /* for 'l' */ \ + REF (mod_longlong), /* for 'L', 'q' */ \ + REF (mod_size_t), /* for 'z', 'Z' */ \ + REF (form_percent), /* for '%' */ \ + REF (form_integer), /* for 'd', 'i' */ \ + REF (form_unsigned), /* for 'u' */ \ + REF (form_octal), /* for 'o' */ \ + REF (form_hexa), /* for 'X', 'x' */ \ + REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \ + REF (form_character), /* for 'c' */ \ + REF (form_string), /* for 's', 'S' */ \ + REF (form_pointer), /* for 'p' */ \ + REF (form_number), /* for 'n' */ \ + REF (form_strerror), /* for 'm' */ \ + REF (form_wcharacter), /* for 'C' */ \ + REF (form_floathex), /* for 'A', 'a' */ \ + REF (mod_ptrdiff_t), /* for 't' */ \ + REF (mod_intmax_t), /* for 'j' */ \ + REF (flag_i18n) /* for 'I' */ \ + }; \ + /* Step 3a: after processing first 'h' modifier. */ \ + static JUMP_TABLE_TYPE step3a_jumps[30] = \ + { \ + REF (form_unknown), \ + REF (form_unknown), /* for ' ' */ \ + REF (form_unknown), /* for '+' */ \ + REF (form_unknown), /* for '-' */ \ + REF (form_unknown), /* for '' */ \ + REF (form_unknown), /* for '0' */ \ + REF (form_unknown), /* for '\'' */ \ + REF (form_unknown), /* for '*' */ \ + REF (form_unknown), /* for '1'...'9' */ \ + REF (form_unknown), /* for '.' */ \ + REF (mod_halfhalf), /* for 'h' */ \ + REF (form_unknown), /* for 'l' */ \ + REF (form_unknown), /* for 'L', 'q' */ \ + REF (form_unknown), /* for 'z', 'Z' */ \ + REF (form_percent), /* for '%' */ \ + REF (form_integer), /* for 'd', 'i' */ \ + REF (form_unsigned), /* for 'u' */ \ + REF (form_octal), /* for 'o' */ \ + REF (form_hexa), /* for 'X', 'x' */ \ + REF (form_unknown), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \ + REF (form_unknown), /* for 'c' */ \ + REF (form_unknown), /* for 's', 'S' */ \ + REF (form_unknown), /* for 'p' */ \ + REF (form_number), /* for 'n' */ \ + REF (form_unknown), /* for 'm' */ \ + REF (form_unknown), /* for 'C' */ \ + REF (form_unknown), /* for 'A', 'a' */ \ + REF (form_unknown), /* for 't' */ \ + REF (form_unknown), /* for 'j' */ \ + REF (form_unknown) /* for 'I' */ \ + }; \ + /* Step 3b: after processing first 'l' modifier. */ \ + static JUMP_TABLE_TYPE step3b_jumps[30] = \ + { \ + REF (form_unknown), \ + REF (form_unknown), /* for ' ' */ \ + REF (form_unknown), /* for '+' */ \ + REF (form_unknown), /* for '-' */ \ + REF (form_unknown), /* for '' */ \ + REF (form_unknown), /* for '0' */ \ + REF (form_unknown), /* for '\'' */ \ + REF (form_unknown), /* for '*' */ \ + REF (form_unknown), /* for '1'...'9' */ \ + REF (form_unknown), /* for '.' */ \ + REF (form_unknown), /* for 'h' */ \ + REF (mod_longlong), /* for 'l' */ \ + REF (form_unknown), /* for 'L', 'q' */ \ + REF (form_unknown), /* for 'z', 'Z' */ \ + REF (form_percent), /* for '%' */ \ + REF (form_integer), /* for 'd', 'i' */ \ + REF (form_unsigned), /* for 'u' */ \ + REF (form_octal), /* for 'o' */ \ + REF (form_hexa), /* for 'X', 'x' */ \ + REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \ + REF (form_character), /* for 'c' */ \ + REF (form_string), /* for 's', 'S' */ \ + REF (form_pointer), /* for 'p' */ \ + REF (form_number), /* for 'n' */ \ + REF (form_strerror), /* for 'm' */ \ + REF (form_wcharacter), /* for 'C' */ \ + REF (form_floathex), /* for 'A', 'a' */ \ + REF (form_unknown), /* for 't' */ \ + REF (form_unknown), /* for 'j' */ \ + REF (form_unknown) /* for 'I' */ \ + } + +#define STEP4_TABLE \ + /* Step 4: processing format specifier. */ \ + static JUMP_TABLE_TYPE step4_jumps[30] = \ + { \ + REF (form_unknown), \ + REF (form_unknown), /* for ' ' */ \ + REF (form_unknown), /* for '+' */ \ + REF (form_unknown), /* for '-' */ \ + REF (form_unknown), /* for '' */ \ + REF (form_unknown), /* for '0' */ \ + REF (form_unknown), /* for '\'' */ \ + REF (form_unknown), /* for '*' */ \ + REF (form_unknown), /* for '1'...'9' */ \ + REF (form_unknown), /* for '.' */ \ + REF (form_unknown), /* for 'h' */ \ + REF (form_unknown), /* for 'l' */ \ + REF (form_unknown), /* for 'L', 'q' */ \ + REF (form_unknown), /* for 'z', 'Z' */ \ + REF (form_percent), /* for '%' */ \ + REF (form_integer), /* for 'd', 'i' */ \ + REF (form_unsigned), /* for 'u' */ \ + REF (form_octal), /* for 'o' */ \ + REF (form_hexa), /* for 'X', 'x' */ \ + REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \ + REF (form_character), /* for 'c' */ \ + REF (form_string), /* for 's', 'S' */ \ + REF (form_pointer), /* for 'p' */ \ + REF (form_number), /* for 'n' */ \ + REF (form_strerror), /* for 'm' */ \ + REF (form_wcharacter), /* for 'C' */ \ + REF (form_floathex), /* for 'A', 'a' */ \ + REF (form_unknown), /* for 't' */ \ + REF (form_unknown), /* for 'j' */ \ + REF (form_unknown) /* for 'I' */ \ + } + + +#define process_arg(fspec) \ + /* Start real work. We know about all flags and modifiers and \ + now process the wanted format specifier. */ \ + LABEL (form_percent): \ + /* Write a literal "%". */ \ + outchar (L_('%')); \ + break; \ + \ + LABEL (form_integer): \ + /* Signed decimal integer. */ \ + base = 10; \ + \ + if (is_longlong) \ + { \ + long long int signed_number; \ + \ + if (fspec == NULL) \ + signed_number = va_arg (ap, long long int); \ + else \ + signed_number = args_value[fspec->data_arg].pa_long_long_int; \ + \ + is_negative = signed_number < 0; \ + number.longlong = is_negative ? (- signed_number) : signed_number; \ + \ + goto LABEL (longlong_number); \ + } \ + else \ + { \ + long int signed_number; \ + \ + if (fspec == NULL) \ + { \ + if (is_long_num) \ + signed_number = va_arg (ap, long int); \ + else /* `char' and `short int' will be promoted to `int'. */ \ + signed_number = va_arg (ap, int); \ + } \ + else \ + if (is_long_num) \ + signed_number = args_value[fspec->data_arg].pa_long_int; \ + else if (!is_short) \ + signed_number = args_value[fspec->data_arg].pa_int; \ + else \ + signed_number = args_value[fspec->data_arg].pa_short_int; \ + \ + is_negative = signed_number < 0; \ + number.word = is_negative ? (- signed_number) : signed_number; \ + \ + goto LABEL (number); \ + } \ + /* NOTREACHED */ \ + \ + LABEL (form_unsigned): \ + /* Unsigned decimal integer. */ \ + base = 10; \ + goto LABEL (unsigned_number); \ + /* NOTREACHED */ \ + \ + LABEL (form_octal): \ + /* Unsigned octal integer. */ \ + base = 8; \ + goto LABEL (unsigned_number); \ + /* NOTREACHED */ \ + \ + LABEL (form_hexa): \ + /* Unsigned hexadecimal integer. */ \ + base = 16; \ + \ + LABEL (unsigned_number): /* Unsigned number of base BASE. */ \ + \ + /* ISO specifies the `+' and ` ' flags only for signed \ + conversions. */ \ + is_negative = 0; \ + showsign = 0; \ + space = 0; \ + \ + if (is_longlong) \ + { \ + if (fspec == NULL) \ + number.longlong = va_arg (ap, unsigned long long int); \ + else \ + number.longlong = args_value[fspec->data_arg].pa_u_long_long_int; \ + \ + LABEL (longlong_number): \ + if (prec < 0) \ + /* Supply a default precision if none was given. */ \ + prec = 1; \ + else \ + /* We have to take care for the '0' flag. If a precision \ + is given it must be ignored. */ \ + pad = L_(' '); \ + \ + /* If the precision is 0 and the number is 0 nothing has to \ + be written for the number, except for the 'o' format in \ + alternate form. */ \ + if (prec == 0 && number.longlong == 0) \ + { \ + string = workend; \ + if (base == 8 && alt) \ + *--string = L_('0'); \ + } \ + else \ + { \ + /* Put the number in WORK. */ \ + string = _itoa (number.longlong, workend, base, \ + spec == L_('X')); \ + if (group && grouping) \ + string = group_number (string, workend, grouping, \ + thousands_sep); \ + \ + if (use_outdigits && base == 10) \ + string = _i18n_number_rewrite (string, workend); \ + } \ + /* Simplify further test for num != 0. */ \ + number.word = number.longlong != 0; \ + } \ + else \ + { \ + if (fspec == NULL) \ + { \ + if (is_long_num) \ + number.word = va_arg (ap, unsigned long int); \ + else if (is_char) \ + number.word = (unsigned char) va_arg (ap, unsigned int); \ + else if (!is_short) \ + number.word = va_arg (ap, unsigned int); \ + else \ + number.word = (unsigned short int) va_arg (ap, unsigned int); \ + } \ + else \ + if (is_long_num) \ + number.word = args_value[fspec->data_arg].pa_u_long_int; \ + else if (is_char) \ + number.word = (unsigned char) \ + args_value[fspec->data_arg].pa_char; \ + else if (!is_short) \ + number.word = args_value[fspec->data_arg].pa_u_int; \ + else \ + number.word = (unsigned short int) \ + args_value[fspec->data_arg].pa_u_short_int; \ + \ + LABEL (number): \ + if (prec < 0) \ + /* Supply a default precision if none was given. */ \ + prec = 1; \ + else \ + /* We have to take care for the '0' flag. If a precision \ + is given it must be ignored. */ \ + pad = L_(' '); \ + \ + /* If the precision is 0 and the number is 0 nothing has to \ + be written for the number, except for the 'o' format in \ + alternate form. */ \ + if (prec == 0 && number.word == 0) \ + { \ + string = workend; \ + if (base == 8 && alt) \ + *--string = L_('0'); \ + } \ + else \ + { \ + /* Put the number in WORK. */ \ + string = _itoa_word (number.word, workend, base, \ + spec == L_('X')); \ + if (group && grouping) \ + string = group_number (string, workend, grouping, \ + thousands_sep); \ + \ + if (use_outdigits && base == 10) \ + string = _i18n_number_rewrite (string, workend); \ + } \ + } \ + \ + if (prec <= workend - string && number.word != 0 && alt && base == 8) \ + /* Add octal marker. */ \ + *--string = L_('0'); \ + \ + prec = MAX (0, prec - (workend - string)); \ + \ + if (!left) \ + { \ + width -= workend - string + prec; \ + \ + if (number.word != 0 && alt && base == 16) \ + /* Account for 0X hex marker. */ \ + width -= 2; \ + \ + if (is_negative || showsign || space) \ + --width; \ + \ + if (pad == L_(' ')) \ + { \ + PAD (L_(' ')); \ + width = 0; \ + } \ + \ + if (is_negative) \ + outchar (L_('-')); \ + else if (showsign) \ + outchar (L_('+')); \ + else if (space) \ + outchar (L_(' ')); \ + \ + if (number.word != 0 && alt && base == 16) \ + { \ + outchar (L_('0')); \ + outchar (spec); \ + } \ + \ + width += prec; \ + PAD (L_('0')); \ + \ + outstring (string, workend - string); \ + \ + break; \ + } \ + else \ + { \ + if (is_negative) \ + { \ + outchar (L_('-')); \ + --width; \ + } \ + else if (showsign) \ + { \ + outchar (L_('+')); \ + --width; \ + } \ + else if (space) \ + { \ + outchar (L_(' ')); \ + --width; \ + } \ + \ + if (number.word != 0 && alt && base == 16) \ + { \ + outchar (L_('0')); \ + outchar (spec); \ + width -= 2; \ + } \ + \ + width -= workend - string + prec; \ + \ + if (prec > 0) \ + { \ + int temp = width; \ + width = prec; \ + PAD (L_('0'));; \ + width = temp; \ + } \ + \ + outstring (string, workend - string); \ + \ + PAD (L_(' ')); \ + break; \ + } \ + \ + LABEL (form_float): \ + { \ + /* Floating-point number. This is handled by printf_fp.c. */ \ + const void *ptr; \ + int function_done; \ + \ + if (fspec == NULL) \ + { \ + struct printf_info info = { .prec = prec, \ + .width = width, \ + .spec = spec, \ + .is_long_double = is_long_double, \ + .is_short = is_short, \ + .is_long = is_long, \ + .alt = alt, \ + .space = space, \ + .left = left, \ + .showsign = showsign, \ + .group = group, \ + .pad = pad, \ + .extra = 0, \ + .wide = sizeof (CHAR_T) != 1 }; \ + \ + if (is_long_double) \ + the_arg.pa_long_double = va_arg (ap, long double); \ + else \ + the_arg.pa_double = va_arg (ap, double); \ + ptr = (const void *) &the_arg; \ + \ + function_done = __printf_fp (s, &info, &ptr); \ + } \ + else \ + { \ + ptr = (const void *) &args_value[fspec->data_arg]; \ + \ + function_done = __printf_fp (s, &fspec->info, &ptr); \ + } \ + \ + if (function_done < 0) \ + { \ + /* Error in print handler. */ \ + done = -1; \ + goto all_done; \ + } \ + \ + done += function_done; \ + } \ + break; \ + \ + LABEL (form_floathex): \ + { \ + /* Floating point number printed as hexadecimal number. */ \ + const void *ptr; \ + int function_done; \ + \ + if (fspec == NULL) \ + { \ + struct printf_info info = { .prec = prec, \ + .width = width, \ + .spec = spec, \ + .is_long_double = is_long_double, \ + .is_short = is_short, \ + .is_long = is_long, \ + .alt = alt, \ + .space = space, \ + .left = left, \ + .showsign = showsign, \ + .group = group, \ + .pad = pad, \ + .extra = 0, \ + .wide = sizeof (CHAR_T) != 1 }; \ + \ + if (is_long_double) \ + the_arg.pa_long_double = va_arg (ap, long double); \ + else \ + the_arg.pa_double = va_arg (ap, double); \ + ptr = (const void *) &the_arg; \ + \ + function_done = __printf_fphex (s, &info, &ptr); \ + } \ + else \ + { \ + ptr = (const void *) &args_value[fspec->data_arg]; \ + \ + function_done = __printf_fphex (s, &fspec->info, &ptr); \ + } \ + \ + if (function_done < 0) \ + { \ + /* Error in print handler. */ \ + done = -1; \ + goto all_done; \ + } \ + \ + done += function_done; \ + } \ + break; \ + \ + LABEL (form_pointer): \ + /* Generic pointer. */ \ + { \ + const void *ptr; \ + if (fspec == NULL) \ + ptr = va_arg (ap, void *); \ + else \ + ptr = args_value[fspec->data_arg].pa_pointer; \ + if (ptr != NULL) \ + { \ + /* If the pointer is not NULL, write it as a %#x spec. */ \ + base = 16; \ + number.word = (unsigned long int) ptr; \ + is_negative = 0; \ + alt = 1; \ + group = 0; \ + spec = L_('x'); \ + goto LABEL (number); \ + } \ + else \ + { \ + /* Write "(nil)" for a nil pointer. */ \ + string = (CHAR_T *) L_("(nil)"); \ + /* Make sure the full string "(nil)" is printed. */ \ + if (prec < 5) \ + prec = 5; \ + is_long = 0; /* This is no wide-char string. */ \ + goto LABEL (print_string); \ + } \ + } \ + /* NOTREACHED */ \ + \ + LABEL (form_number): \ + /* Answer the count of characters written. */ \ + if (fspec == NULL) \ + { \ + if (is_longlong) \ + *(long long int *) va_arg (ap, void *) = done; \ + else if (is_long_num) \ + *(long int *) va_arg (ap, void *) = done; \ + else if (is_char) \ + *(char *) va_arg (ap, void *) = done; \ + else if (!is_short) \ + *(int *) va_arg (ap, void *) = done; \ + else \ + *(short int *) va_arg (ap, void *) = done; \ + } \ + else \ + if (is_longlong) \ + *(long long int *) args_value[fspec->data_arg].pa_pointer = done; \ + else if (is_long_num) \ + *(long int *) args_value[fspec->data_arg].pa_pointer = done; \ + else if (is_char) \ + *(char *) args_value[fspec->data_arg].pa_pointer = done; \ + else if (!is_short) \ + *(int *) args_value[fspec->data_arg].pa_pointer = done; \ + else \ + *(short int *) args_value[fspec->data_arg].pa_pointer = done; \ + break; \ + \ + LABEL (form_strerror): \ + /* Print description of error ERRNO. */ \ + string = \ + (CHAR_T *) __strerror_r (save_errno, (char *) work_buffer, \ + sizeof work_buffer); \ + is_long = 0; /* This is no wide-char string. */ \ + goto LABEL (print_string) + +#ifdef COMPILE_WPRINTF +# define process_string_arg(fspec) \ + LABEL (form_character): \ + /* Character. */ \ + if (is_long) \ + goto LABEL (form_wcharacter); \ + --width; /* Account for the character itself. */ \ + if (!left) \ + PAD (L' '); \ + if (fspec == NULL) \ + outchar (__btowc ((unsigned char) va_arg (ap, int))); /* Promoted. */ \ + else \ + outchar (__btowc ((unsigned char) \ + args_value[fspec->data_arg].pa_char)); \ + if (left) \ + PAD (L' '); \ + break; \ + \ + LABEL (form_wcharacter): \ + { \ + /* Wide character. */ \ + --width; \ + if (!left) \ + PAD (L' '); \ + if (fspec == NULL) \ + outchar (va_arg (ap, wchar_t)); \ + else \ + outchar (args_value[fspec->data_arg].pa_wchar); \ + if (left) \ + PAD (L' '); \ + } \ + break; \ + \ + LABEL (form_string): \ + { \ + size_t len; \ + int string_malloced; \ + \ + /* The string argument could in fact be `char *' or `wchar_t *'. \ + But this should not make a difference here. */ \ + if (fspec == NULL) \ + string = (CHAR_T *) va_arg (ap, const wchar_t *); \ + else \ + string = (CHAR_T *) args_value[fspec->data_arg].pa_wstring; \ + \ + /* Entry point for printing other strings. */ \ + LABEL (print_string): \ + \ + string_malloced = 0; \ + if (string == NULL) \ + { \ + /* Write "(null)" if there's space. */ \ + if (prec == -1 \ + || prec >= (int) (sizeof (null) / sizeof (null[0])) - 1) \ + { \ + string = (CHAR_T *) null; \ + len = (sizeof (null) / sizeof (null[0])) - 1; \ + } \ + else \ + { \ + string = (CHAR_T *) L""; \ + len = 0; \ + } \ + } \ + else if (!is_long && spec != L_('S')) \ + { \ + /* This is complicated. We have to transform the multibyte \ + string into a wide character string. */ \ + const char *mbs = (const char *) string; \ + mbstate_t mbstate; \ + \ + len = prec != -1 ? (size_t) prec : strlen (mbs); \ + \ + /* Allocate dynamically an array which definitely is long \ + enough for the wide character version. */ \ + if (__libc_use_alloca (len * sizeof (wchar_t))) \ + string = (CHAR_T *) alloca (len * sizeof (wchar_t)); \ + else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t))) \ + == NULL) \ + { \ + done = -1; \ + goto all_done; \ + } \ + else \ + string_malloced = 1; \ + \ + memset (&mbstate, '\0', sizeof (mbstate_t)); \ + len = __mbsrtowcs (string, &mbs, len, &mbstate); \ + if (len == (size_t) -1) \ + { \ + /* Illegal multibyte character. */ \ + done = -1; \ + goto all_done; \ + } \ + } \ + else \ + { \ + if (prec != -1) \ + /* Search for the end of the string, but don't search past \ + the length specified by the precision. */ \ + len = __wcsnlen (string, prec); \ + else \ + len = __wcslen (string); \ + } \ + \ + if ((width -= len) < 0) \ + { \ + outstring (string, len); \ + break; \ + } \ + \ + if (!left) \ + PAD (L' '); \ + outstring (string, len); \ + if (left) \ + PAD (L' '); \ + if (__builtin_expect (string_malloced, 0)) \ + free (string); \ + } \ + break; +#else +# define process_string_arg(fspec) \ + LABEL (form_character): \ + /* Character. */ \ + if (is_long) \ + goto LABEL (form_wcharacter); \ + --width; /* Account for the character itself. */ \ + if (!left) \ + PAD (' '); \ + if (fspec == NULL) \ + outchar ((unsigned char) va_arg (ap, int)); /* Promoted. */ \ + else \ + outchar ((unsigned char) args_value[fspec->data_arg].pa_char); \ + if (left) \ + PAD (' '); \ + break; \ + \ + LABEL (form_wcharacter): \ + { \ + /* Wide character. */ \ + char buf[MB_CUR_MAX]; \ + mbstate_t mbstate; \ + size_t len; \ + \ + memset (&mbstate, '\0', sizeof (mbstate_t)); \ + len = __wcrtomb (buf, (fspec == NULL ? va_arg (ap, wchar_t) \ + : args_value[fspec->data_arg].pa_wchar), \ + &mbstate); \ + if (len == (size_t) -1) \ + { \ + /* Something went wron gduring the conversion. Bail out. */ \ + done = -1; \ + goto all_done; \ + } \ + width -= len; \ + if (!left) \ + PAD (' '); \ + outstring (buf, len); \ + if (left) \ + PAD (' '); \ + } \ + break; \ + \ + LABEL (form_string): \ + { \ + size_t len; \ + int string_malloced; \ + \ + /* The string argument could in fact be `char *' or `wchar_t *'. \ + But this should not make a difference here. */ \ + if (fspec == NULL) \ + string = (char *) va_arg (ap, const char *); \ + else \ + string = (char *) args_value[fspec->data_arg].pa_string; \ + \ + /* Entry point for printing other strings. */ \ + LABEL (print_string): \ + \ + string_malloced = 0; \ + if (string == NULL) \ + { \ + /* Write "(null)" if there's space. */ \ + if (prec == -1 || prec >= (int) sizeof (null) - 1) \ + { \ + string = (char *) null; \ + len = sizeof (null) - 1; \ + } \ + else \ + { \ + string = (char *) ""; \ + len = 0; \ + } \ + } \ + else if (!is_long && spec != L_('S')) \ + { \ + if (prec != -1) \ + { \ + /* Search for the end of the string, but don't search past \ + the length (in bytes) specified by the precision. Also \ + don't use incomplete characters. */ \ + if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1) \ + len = __strnlen (string, prec); \ + else \ + { \ + /* In case we have a multibyte character set the \ + situation is more compilcated. We must not copy \ + bytes at the end which form an incomplete character. */\ + wchar_t ignore[prec]; \ + const char *str2 = string; \ + mbstate_t ps; \ + \ + memset (&ps, '\0', sizeof (ps)); \ + if (__mbsnrtowcs (ignore, &str2, prec, prec, &ps) \ + == (size_t) -1) \ + { \ + done = -1; \ + goto all_done; \ + } \ + if (str2 == NULL) \ + len = strlen (string); \ + else \ + len = str2 - string - (ps.__count & 7); \ + } \ + } \ + else \ + len = strlen (string); \ + } \ + else \ + { \ + const wchar_t *s2 = (const wchar_t *) string; \ + mbstate_t mbstate; \ + \ + memset (&mbstate, '\0', sizeof (mbstate_t)); \ + \ + if (prec >= 0) \ + { \ + /* The string `s2' might not be NUL terminated. */ \ + if (__libc_use_alloca (prec)) \ + string = (char *) alloca (prec); \ + else if ((string = (char *) malloc (prec)) == NULL) \ + { \ + done = -1; \ + goto all_done; \ + } \ + else \ + string_malloced = 1; \ + len = __wcsrtombs (string, &s2, prec, &mbstate); \ + } \ + else \ + { \ + len = __wcsrtombs (NULL, &s2, 0, &mbstate); \ + if (len != (size_t) -1) \ + { \ + assert (__mbsinit (&mbstate)); \ + s2 = (const wchar_t *) string; \ + if (__libc_use_alloca (len + 1)) \ + string = (char *) alloca (len + 1); \ + else if ((string = (char *) malloc (len + 1)) == NULL) \ + { \ + done = -1; \ + goto all_done; \ + } \ + else \ + string_malloced = 1; \ + (void) __wcsrtombs (string, &s2, len + 1, &mbstate); \ + } \ + } \ + \ + if (len == (size_t) -1) \ + { \ + /* Illegal wide-character string. */ \ + done = -1; \ + goto all_done; \ + } \ + } \ + \ + if ((width -= len) < 0) \ + { \ + outstring (string, len); \ + break; \ + } \ + \ + if (!left) \ + PAD (' '); \ + outstring (string, len); \ + if (left) \ + PAD (' '); \ + if (__builtin_expect (string_malloced, 0)) \ + free (string); \ + } \ + break; +#endif + + /* Orient the stream. */ +#ifdef ORIENT + ORIENT; +#endif + + /* Sanity check of arguments. */ + ARGCHECK (s, format); + +#ifdef ORIENT + /* Check for correct orientation. */ + if ( +# ifdef USE_IN_LIBIO + s->_vtable_offset == 0 && +# endif + _IO_fwide (s, sizeof (CHAR_T) == 1 ? -1 : 1) + != (sizeof (CHAR_T) == 1 ? -1 : 1)) + /* The stream is already oriented otherwise. */ + return EOF; +#endif + + if (UNBUFFERED_P (s)) + /* Use a helper function which will allocate a local temporary buffer + for the stream and then call us again. */ + return buffered_vfprintf (s, format, ap); + + /* Initialize local variables. */ + done = 0; + grouping = (const char *) -1; +#ifdef __va_copy + /* This macro will be available soon in gcc's . We need it + since on some systems `va_list' is not an integral type. */ + __va_copy (ap_save, ap); +#else + ap_save = ap; +#endif + nspecs_done = 0; + +#ifdef COMPILE_WPRINTF + /* Find the first format specifier. */ + f = lead_str_end = find_spec ((const UCHAR_T *) format); +#else + /* Put state for processing format string in initial state. */ + memset (&mbstate, '\0', sizeof (mbstate_t)); + + /* Find the first format specifier. */ + f = lead_str_end = find_spec (format, &mbstate); +#endif + + /* Lock stream. */ +#ifdef USE_IN_LIBIO + _IO_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s); + _IO_flockfile (s); +#else + __libc_cleanup_region_start (1, (void (*) (void *)) &__funlockfile, s); + __flockfile (s); +#endif + + /* Write the literal text before the first format. */ + outstring ((const UCHAR_T *) format, + lead_str_end - (const UCHAR_T *) format); + + /* If we only have to print a simple string, return now. */ + if (*f == L_('\0')) + goto all_done; + + /* Process whole format string. */ + do + { +#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED +# define REF(Name) &&do_##Name - &&do_form_unknown +#else +# define REF(Name) &&do_##Name +#endif +#define LABEL(Name) do_##Name + STEP0_3_TABLE; + STEP4_TABLE; + + union printf_arg *args_value; /* This is not used here but ... */ + int is_negative; /* Flag for negative number. */ + union + { + unsigned long long int longlong; + unsigned long int word; + } number; + int base; + union printf_arg the_arg; + CHAR_T *string; /* Pointer to argument string. */ + int alt = 0; /* Alternate format. */ + int space = 0; /* Use space prefix if no sign is needed. */ + int left = 0; /* Left-justify output. */ + int showsign = 0; /* Always begin with plus or minus sign. */ + int group = 0; /* Print numbers according grouping rules. */ + int is_long_double = 0; /* Argument is long double/ long long int. */ + int is_short = 0; /* Argument is short int. */ + int is_long = 0; /* Argument is long int. */ + int is_char = 0; /* Argument is promoted (unsigned) char. */ + int width = 0; /* Width of output; 0 means none specified. */ + int prec = -1; /* Precision of output; -1 means none specified. */ + /* This flag is set by the 'I' modifier and selects the use of the + `outdigits' as determined by the current locale. */ + int use_outdigits = 0; + UCHAR_T pad = L_(' ');/* Padding character. */ + CHAR_T spec; + + workstart = NULL; + workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; + + /* Get current character in format string. */ + JUMP (*++f, step0_jumps); + + /* ' ' flag. */ + LABEL (flag_space): + space = 1; + JUMP (*++f, step0_jumps); + + /* '+' flag. */ + LABEL (flag_plus): + showsign = 1; + JUMP (*++f, step0_jumps); + + /* The '-' flag. */ + LABEL (flag_minus): + left = 1; + pad = L_(' '); + JUMP (*++f, step0_jumps); + + /* The '#' flag. */ + LABEL (flag_hash): + alt = 1; + JUMP (*++f, step0_jumps); + + /* The '0' flag. */ + LABEL (flag_zero): + if (!left) + pad = L_('0'); + JUMP (*++f, step0_jumps); + + /* The '\'' flag. */ + LABEL (flag_quote): + group = 1; + + if (grouping == (const char *) -1) + { +#ifdef COMPILE_WPRINTF + thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, + _NL_NUMERIC_THOUSANDS_SEP_WC); +#else + thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); +#endif + + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + if (*grouping == '\0' || *grouping == CHAR_MAX +#ifdef COMPILE_WPRINTF + || thousands_sep == L'\0' +#else + || *thousands_sep == '\0' +#endif + ) + grouping = NULL; + } + JUMP (*++f, step0_jumps); + + LABEL (flag_i18n): + use_outdigits = 1; + JUMP (*++f, step0_jumps); + + /* Get width from argument. */ + LABEL (width_asterics): + { + const UCHAR_T *tmp; /* Temporary value. */ + + tmp = ++f; + if (ISDIGIT (*tmp) && read_int (&tmp) && *tmp == L_('$')) + /* The width comes from a positional parameter. */ + goto do_positional; + + width = va_arg (ap, int); + + /* Negative width means left justified. */ + if (width < 0) + { + width = -width; + pad = L_(' '); + left = 1; + } + + if (width + 32 >= (int) (sizeof (work_buffer) + / sizeof (work_buffer[0]))) + { + /* We have to use a special buffer. The "32" is just a safe + bet for all the output which is not counted in the width. */ + if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T))) + workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T)) + + (width + 32)); + else + { + workstart = (CHAR_T *) malloc ((width + 32) * sizeof (CHAR_T)); + if (workstart == NULL) + { + done = -1; + goto all_done; + } + workend = workstart + (width + 32); + } + } + } + JUMP (*f, step1_jumps); + + /* Given width in format string. */ + LABEL (width): + width = read_int (&f); + + if (width + 32 >= (int) (sizeof (work_buffer) / sizeof (work_buffer[0]))) + { + /* We have to use a special buffer. The "32" is just a safe + bet for all the output which is not counted in the width. */ + if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T))) + workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T)) + + (width + 32)); + else + { + workstart = (CHAR_T *) malloc ((width + 32) * sizeof (CHAR_T)); + if (workstart == NULL) + { + done = -1; + goto all_done; + } + workend = workstart + (width + 32); + } + } + if (*f == L_('$')) + /* Oh, oh. The argument comes from a positional parameter. */ + goto do_positional; + JUMP (*f, step1_jumps); + + LABEL (precision): + ++f; + if (*f == L_('*')) + { + const UCHAR_T *tmp; /* Temporary value. */ + + tmp = ++f; + if (ISDIGIT (*tmp) && read_int (&tmp) > 0 && *tmp == L_('$')) + /* The precision comes from a positional parameter. */ + goto do_positional; + + prec = va_arg (ap, int); + + /* If the precision is negative the precision is omitted. */ + if (prec < 0) + prec = -1; + } + else if (ISDIGIT (*f)) + prec = read_int (&f); + else + prec = 0; + if (prec > width + && prec + 32 > (int)(sizeof (work_buffer) / sizeof (work_buffer[0]))) + { + if (__libc_use_alloca ((prec + 32) * sizeof (CHAR_T))) + workend = ((CHAR_T *) alloca ((prec + 32) * sizeof (CHAR_T))) + + (prec + 32); + else + { + workstart = (CHAR_T *) malloc ((prec + 32) * sizeof (CHAR_T)); + if (workstart == NULL) + { + done = -1; + goto all_done; + } + workend = workstart + (prec + 32); + } + } + JUMP (*f, step2_jumps); + + /* Process 'h' modifier. There might another 'h' following. */ + LABEL (mod_half): + is_short = 1; + JUMP (*++f, step3a_jumps); + + /* Process 'hh' modifier. */ + LABEL (mod_halfhalf): + is_short = 0; + is_char = 1; + JUMP (*++f, step4_jumps); + + /* Process 'l' modifier. There might another 'l' following. */ + LABEL (mod_long): + is_long = 1; + JUMP (*++f, step3b_jumps); + + /* Process 'L', 'q', or 'll' modifier. No other modifier is + allowed to follow. */ + LABEL (mod_longlong): + is_long_double = 1; + is_long = 1; + JUMP (*++f, step4_jumps); + + LABEL (mod_size_t): + is_long_double = sizeof (size_t) > sizeof (unsigned long int); + is_long = sizeof (size_t) > sizeof (unsigned int); + JUMP (*++f, step4_jumps); + + LABEL (mod_ptrdiff_t): + is_long_double = sizeof (ptrdiff_t) > sizeof (unsigned long int); + is_long = sizeof (ptrdiff_t) > sizeof (unsigned int); + JUMP (*++f, step4_jumps); + + LABEL (mod_intmax_t): + is_long_double = sizeof (intmax_t) > sizeof (unsigned long int); + is_long = sizeof (intmax_t) > sizeof (unsigned int); + JUMP (*++f, step4_jumps); + + /* Process current format. */ + while (1) + { + process_arg (((struct printf_spec *) NULL)); + process_string_arg (((struct printf_spec *) NULL)); + + LABEL (form_unknown): + if (spec == L_('\0')) + { + /* The format string ended before the specifier is complete. */ + done = -1; + goto all_done; + } + + /* If we are in the fast loop force entering the complicated + one. */ + goto do_positional; + } + + /* The format is correctly handled. */ + ++nspecs_done; + + if (__builtin_expect (workstart != NULL, 0)) + free (workstart); + workstart = NULL; + + /* Look for next format specifier. */ +#ifdef COMPILE_WPRINTF + f = find_spec ((end_of_spec = ++f)); +#else + f = find_spec ((end_of_spec = ++f), &mbstate); +#endif + + /* Write the following constant string. */ + outstring (end_of_spec, f - end_of_spec); + } + while (*f != L_('\0')); + + /* Unlock stream and return. */ + goto all_done; + + /* Here starts the more complex loop to handle positional parameters. */ +do_positional: + { + /* Array with information about the needed arguments. This has to + be dynamically extensible. */ + size_t nspecs = 0; + size_t nspecs_max = 32; /* A more or less arbitrary start value. */ + struct printf_spec *specs + = alloca (nspecs_max * sizeof (struct printf_spec)); + + /* The number of arguments the format string requests. This will + determine the size of the array needed to store the argument + attributes. */ + size_t nargs = 0; + int *args_type; + union printf_arg *args_value = NULL; + + /* Positional parameters refer to arguments directly. This could + also determine the maximum number of arguments. Track the + maximum number. */ + size_t max_ref_arg = 0; + + /* Just a counter. */ + size_t cnt; + + + if (grouping == (const char *) -1) + { +#ifdef COMPILE_WPRINTF + thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, + _NL_NUMERIC_THOUSANDS_SEP_WC); +#else + thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); +#endif + + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + if (*grouping == '\0' || *grouping == CHAR_MAX) + grouping = NULL; + } + + for (f = lead_str_end; *f != L_('\0'); f = specs[nspecs++].next_fmt) + { + if (nspecs >= nspecs_max) + { + /* Extend the array of format specifiers. */ + struct printf_spec *old = specs; + + nspecs_max *= 2; + specs = alloca (nspecs_max * sizeof (struct printf_spec)); + + if (specs == &old[nspecs]) + /* Stack grows up, OLD was the last thing allocated; + extend it. */ + nspecs_max += nspecs_max / 2; + else + { + /* Copy the old array's elements to the new space. */ + memcpy (specs, old, nspecs * sizeof (struct printf_spec)); + if (old == &specs[nspecs]) + /* Stack grows down, OLD was just below the new + SPECS. We can use that space when the new space + runs out. */ + nspecs_max += nspecs_max / 2; + } + } + + /* Parse the format specifier. */ +#ifdef COMPILE_WPRINTF + nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg); +#else + nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg, + &mbstate); +#endif + } + + /* Determine the number of arguments the format string consumes. */ + nargs = MAX (nargs, max_ref_arg); + + /* Allocate memory for the argument descriptions. */ + args_type = alloca (nargs * sizeof (int)); + memset (args_type, 0, nargs * sizeof (int)); + args_value = alloca (nargs * sizeof (union printf_arg)); + + /* XXX Could do sanity check here: If any element in ARGS_TYPE is + still zero after this loop, format is invalid. For now we + simply use 0 as the value. */ + + /* Fill in the types of all the arguments. */ + for (cnt = 0; cnt < nspecs; ++cnt) + { + /* If the width is determined by an argument this is an int. */ + if (specs[cnt].width_arg != -1) + args_type[specs[cnt].width_arg] = PA_INT; + + /* If the precision is determined by an argument this is an int. */ + if (specs[cnt].prec_arg != -1) + args_type[specs[cnt].prec_arg] = PA_INT; + + switch (specs[cnt].ndata_args) + { + case 0: /* No arguments. */ + break; + case 1: /* One argument; we already have the type. */ + args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type; + break; + default: + /* We have more than one argument for this format spec. + We must call the arginfo function again to determine + all the types. */ + (void) (*__printf_arginfo_table[specs[cnt].info.spec]) + (&specs[cnt].info, + specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]); + break; + } + } + + /* Now we know all the types and the order. Fill in the argument + values. */ + for (cnt = 0; cnt < nargs; ++cnt) + switch (args_type[cnt]) + { +#define T(tag, mem, type) \ + case tag: \ + args_value[cnt].mem = va_arg (ap_save, type); \ + break + + T (PA_CHAR, pa_char, int); /* Promoted. */ + T (PA_WCHAR, pa_wchar, wint_t); + T (PA_INT|PA_FLAG_SHORT, pa_short_int, int); /* Promoted. */ + T (PA_INT, pa_int, int); + T (PA_INT|PA_FLAG_LONG, pa_long_int, long int); + T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int); + T (PA_FLOAT, pa_float, double); /* Promoted. */ + T (PA_DOUBLE, pa_double, double); + T (PA_DOUBLE|PA_FLAG_LONG_DOUBLE, pa_long_double, long double); + T (PA_STRING, pa_string, const char *); + T (PA_WSTRING, pa_wstring, const wchar_t *); + T (PA_POINTER, pa_pointer, void *); +#undef T + default: + if ((args_type[cnt] & PA_FLAG_PTR) != 0) + args_value[cnt].pa_pointer = va_arg (ap_save, void *); + else + args_value[cnt].pa_long_double = 0.0; + break; + } + + /* Now walk through all format specifiers and process them. */ + for (; (size_t) nspecs_done < nspecs; ++nspecs_done) + { +#undef REF +#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED +# define REF(Name) &&do2_##Name - &&do_form_unknown +#else +# define REF(Name) &&do2_##Name +#endif +#undef LABEL +#define LABEL(Name) do2_##Name + STEP4_TABLE; + + int is_negative; + union + { + unsigned long long int longlong; + unsigned long int word; + } number; + int base; + union printf_arg the_arg; + CHAR_T *string; /* Pointer to argument string. */ + + /* Fill variables from values in struct. */ + int alt = specs[nspecs_done].info.alt; + int space = specs[nspecs_done].info.space; + int left = specs[nspecs_done].info.left; + int showsign = specs[nspecs_done].info.showsign; + int group = specs[nspecs_done].info.group; + int is_long_double = specs[nspecs_done].info.is_long_double; + int is_short = specs[nspecs_done].info.is_short; + int is_char = specs[nspecs_done].info.is_char; + int is_long = specs[nspecs_done].info.is_long; + int width = specs[nspecs_done].info.width; + int prec = specs[nspecs_done].info.prec; + int use_outdigits = specs[nspecs_done].info.i18n; + char pad = specs[nspecs_done].info.pad; + CHAR_T spec = specs[nspecs_done].info.spec; + CHAR_T *workstart = NULL; + + /* Fill in last information. */ + if (specs[nspecs_done].width_arg != -1) + { + /* Extract the field width from an argument. */ + specs[nspecs_done].info.width = + args_value[specs[nspecs_done].width_arg].pa_int; + + if (specs[nspecs_done].info.width < 0) + /* If the width value is negative left justification is + selected and the value is taken as being positive. */ + { + specs[nspecs_done].info.width *= -1; + left = specs[nspecs_done].info.left = 1; + } + width = specs[nspecs_done].info.width; + } + + if (specs[nspecs_done].prec_arg != -1) + { + /* Extract the precision from an argument. */ + specs[nspecs_done].info.prec = + args_value[specs[nspecs_done].prec_arg].pa_int; + + if (specs[nspecs_done].info.prec < 0) + /* If the precision is negative the precision is + omitted. */ + specs[nspecs_done].info.prec = -1; + + prec = specs[nspecs_done].info.prec; + } + + /* Maybe the buffer is too small. */ + if (MAX (prec, width) + 32 > (int) (sizeof (work_buffer) + / sizeof (CHAR_T))) + { + if (__libc_use_alloca ((MAX (prec, width) + 32) + * sizeof (CHAR_T))) + workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32) + * sizeof (CHAR_T)) + + (MAX (prec, width) + 32)); + else + { + workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32) + * sizeof (CHAR_T)); + workend = workstart + (MAX (prec, width) + 32); + } + } + + /* Process format specifiers. */ + while (1) + { + JUMP (spec, step4_jumps); + + process_arg ((&specs[nspecs_done])); + process_string_arg ((&specs[nspecs_done])); + + LABEL (form_unknown): + { + extern printf_function **__printf_function_table; + int function_done; + printf_function *function; + unsigned int i; + const void **ptr; + + function = + (__printf_function_table == NULL ? NULL : + __printf_function_table[specs[nspecs_done].info.spec]); + + if (function == NULL) + function = &printf_unknown; + + ptr = alloca (specs[nspecs_done].ndata_args + * sizeof (const void *)); + + /* Fill in an array of pointers to the argument values. */ + for (i = 0; i < specs[nspecs_done].ndata_args; ++i) + ptr[i] = &args_value[specs[nspecs_done].data_arg + i]; + + /* Call the function. */ + function_done = (*function) (s, &specs[nspecs_done].info, ptr); + + /* If an error occurred we don't have information about # + of chars. */ + if (function_done < 0) + { + done = -1; + goto all_done; + } + + done += function_done; + } + break; + } + + if (__builtin_expect (workstart != NULL, 0)) + free (workstart); + workstart = NULL; + + /* Write the following constant string. */ + outstring (specs[nspecs_done].end_of_fmt, + specs[nspecs_done].next_fmt + - specs[nspecs_done].end_of_fmt); + } + } + +all_done: + if (__builtin_expect (workstart != NULL, 0)) + free (workstart); + /* Unlock the stream. */ +#ifdef USE_IN_LIBIO + _IO_funlockfile (s); + _IO_cleanup_region_end (0); +#else + __funlockfile (s); + __libc_cleanup_region_end (0); +#endif + + return done; +} + +/* Handle an unknown format specifier. This prints out a canonicalized + representation of the format spec itself. */ +static int +printf_unknown (FILE *s, const struct printf_info *info, + const void *const *args) + +{ + int done = 0; + CHAR_T work_buffer[MAX (info->width, info->spec) + 32]; + CHAR_T *const workend + = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; + register CHAR_T *w; + + outchar (L_('%')); + + if (info->alt) + outchar (L_('#')); + if (info->group) + outchar (L_('\'')); + if (info->showsign) + outchar (L_('+')); + else if (info->space) + outchar (L_(' ')); + if (info->left) + outchar (L_('-')); + if (info->pad == L_('0')) + outchar (L_('0')); + if (info->i18n) + outchar (L_('I')); + + if (info->width != 0) + { + w = _itoa_word (info->width, workend, 10, 0); + while (w < workend) + outchar (*w++); + } + + if (info->prec != -1) + { + outchar (L_('.')); + w = _itoa_word (info->prec, workend, 10, 0); + while (w < workend) + outchar (*w++); + } + + if (info->spec != L_('\0')) + outchar (info->spec); + + all_done: + return done; +} + +/* Group the digits according to the grouping rules of the current locale. + The interpretation of GROUPING is as in `struct lconv' from . */ +static CHAR_T * +internal_function +group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping, +#ifdef COMPILE_WPRINTF + wchar_t thousands_sep +#else + const char *thousands_sep +#endif + ) +{ + int len; + CHAR_T *src, *s; +#ifndef COMPILE_WPRINTF + int tlen = strlen (thousands_sep); +#endif + + /* We treat all negative values like CHAR_MAX. */ + + if (*grouping == CHAR_MAX || *grouping <= 0) + /* No grouping should be done. */ + return w; + + len = *grouping; + + /* Copy existing string so that nothing gets overwritten. */ + src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T)); + s = (CHAR_T *) __mempcpy (src, w, + (rear_ptr - w) * sizeof (CHAR_T)); + w = rear_ptr; + + /* Process all characters in the string. */ + while (s > src) + { + *--w = *--s; + + if (--len == 0 && s > src) + { + /* A new group begins. */ +#ifdef COMPILE_WPRINTF + *--w = thousands_sep; +#else + int cnt = tlen; + do + *--w = thousands_sep[--cnt]; + while (cnt > 0); +#endif + + len = *grouping++; + if (*grouping == '\0') + /* The previous grouping repeats ad infinitum. */ + --grouping; + else if (*grouping == CHAR_MAX +#if CHAR_MIN < 0 + || *grouping < 0 +#endif + ) + { + /* No further grouping to be done. + Copy the rest of the number. */ + do + *--w = *--s; + while (s > src); + break; + } + } + } + return w; +} + +#ifdef USE_IN_LIBIO +/* Helper "class" for `fprintf to unbuffered': creates a temporary buffer. */ +struct helper_file + { + struct _IO_FILE_plus _f; +#ifdef COMPILE_WPRINTF + struct _IO_wide_data _wide_data; +#endif + _IO_FILE *_put_stream; +#ifdef _IO_MTSAFE_IO + _IO_lock_t lock; +#endif + }; + +static int +_IO_helper_overflow (_IO_FILE *s, int c) +{ + _IO_FILE *target = ((struct helper_file*) s)->_put_stream; +#ifdef COMPILE_WPRINTF + int used = s->_wide_data->_IO_write_ptr - s->_wide_data->_IO_write_base; + if (used) + { + _IO_size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base, + used); + s->_wide_data->_IO_write_ptr -= written; + } +#else + int used = s->_IO_write_ptr - s->_IO_write_base; + if (used) + { + _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used); + s->_IO_write_ptr -= written; + } +#endif + return PUTC (c, s); +} + +#ifdef COMPILE_WPRINTF +static const struct _IO_jump_t _IO_helper_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT (finish, INTUSE(_IO_wdefault_finish)), + JUMP_INIT (overflow, _IO_helper_overflow), + JUMP_INIT (underflow, _IO_default_underflow), + JUMP_INIT (uflow, INTUSE(_IO_default_uflow)), + JUMP_INIT (pbackfail, (_IO_pbackfail_t) INTUSE(_IO_wdefault_pbackfail)), + JUMP_INIT (xsputn, INTUSE(_IO_wdefault_xsputn)), + JUMP_INIT (xsgetn, INTUSE(_IO_wdefault_xsgetn)), + JUMP_INIT (seekoff, _IO_default_seekoff), + JUMP_INIT (seekpos, _IO_default_seekpos), + JUMP_INIT (setbuf, _IO_default_setbuf), + JUMP_INIT (sync, _IO_default_sync), + JUMP_INIT (doallocate, INTUSE(_IO_wdefault_doallocate)), + JUMP_INIT (read, _IO_default_read), + JUMP_INIT (write, _IO_default_write), + JUMP_INIT (seek, _IO_default_seek), + JUMP_INIT (close, _IO_default_close), + JUMP_INIT (stat, _IO_default_stat) +}; +#else +static const struct _IO_jump_t _IO_helper_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT (finish, INTUSE(_IO_default_finish)), + JUMP_INIT (overflow, _IO_helper_overflow), + JUMP_INIT (underflow, _IO_default_underflow), + JUMP_INIT (uflow, INTUSE(_IO_default_uflow)), + JUMP_INIT (pbackfail, INTUSE(_IO_default_pbackfail)), + JUMP_INIT (xsputn, INTUSE(_IO_default_xsputn)), + JUMP_INIT (xsgetn, INTUSE(_IO_default_xsgetn)), + JUMP_INIT (seekoff, _IO_default_seekoff), + JUMP_INIT (seekpos, _IO_default_seekpos), + JUMP_INIT (setbuf, _IO_default_setbuf), + JUMP_INIT (sync, _IO_default_sync), + JUMP_INIT (doallocate, INTUSE(_IO_default_doallocate)), + JUMP_INIT (read, _IO_default_read), + JUMP_INIT (write, _IO_default_write), + JUMP_INIT (seek, _IO_default_seek), + JUMP_INIT (close, _IO_default_close), + JUMP_INIT (stat, _IO_default_stat) +}; +#endif + +static int +internal_function +buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format, + _IO_va_list args) +{ + CHAR_T buf[_IO_BUFSIZ]; + struct helper_file helper; + register _IO_FILE *hp = (_IO_FILE *) &helper._f; + int result, to_flush; + + /* Orient the stream. */ +#ifdef ORIENT + ORIENT; +#endif + + /* Initialize helper. */ + helper._put_stream = s; +#ifdef COMPILE_WPRINTF + hp->_wide_data = &helper._wide_data; + _IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T)); + hp->_mode = 1; +#else + _IO_setp (hp, buf, buf + sizeof buf); + hp->_mode = -1; +#endif + hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS|_IO_USER_LOCK; +#if _IO_JUMPS_OFFSET + hp->_vtable_offset = 0; +#endif +#ifdef _IO_MTSAFE_IO + hp->_lock = NULL; +#endif + _IO_JUMPS (&helper._f) = (struct _IO_jump_t *) &_IO_helper_jumps; + + /* Now print to helper instead. */ +#if defined USE_IN_LIBIO && !defined COMPILE_WPRINTF + result = INTUSE(_IO_vfprintf) (hp, format, args); +#else + result = vfprintf (hp, format, args); +#endif + + /* Lock stream. */ + __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, s); + _IO_flockfile (s); + + /* Now flush anything from the helper to the S. */ +#ifdef COMPILE_WPRINTF + if ((to_flush = (hp->_wide_data->_IO_write_ptr + - hp->_wide_data->_IO_write_base)) > 0) + { + if ((int) _IO_sputn (s, hp->_wide_data->_IO_write_base, to_flush) + != to_flush) + result = -1; + } +#else + if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0) + { + if ((int) _IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush) + result = -1; + } +#endif + + /* Unlock the stream. */ + _IO_funlockfile (s); + __libc_cleanup_region_end (0); + + return result; +} + +#else /* !USE_IN_LIBIO */ + +static int +internal_function +buffered_vfprintf (register FILE *s, const CHAR_T *format, va_list args) +{ + char buf[BUFSIZ]; + int result; + + /* Orient the stream. */ +#ifdef ORIENT + ORIENT; +#endif + + s->__bufp = s->__buffer = buf; + s->__bufsize = sizeof buf; + s->__put_limit = s->__buffer + s->__bufsize; + s->__get_limit = s->__buffer; + + /* Now use buffer to print. */ + result = vfprintf (s, format, args); + + if (fflush (s) == EOF) + result = -1; + s->__buffer = s->__bufp = s->__get_limit = s->__put_limit = NULL; + s->__bufsize = 0; + + return result; +} + +/* Pads string with given number of a specified character. + This code is taken from iopadn.c of the GNU I/O library. */ +#define PADSIZE 16 +static const CHAR_T blanks[PADSIZE] = +{ L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), + L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' ') }; +static const CHAR_T zeroes[PADSIZE] = +{ L_('0'), L_('0'), L_('0'), L_('0'), L_('0'), L_('0'), L_('0'), L_('0'), + L_('0'), L_('0'), L_('0'), L_('0'), L_('0'), L_('0'), L_('0'), L_('0') }; + +ssize_t +#ifndef COMPILE_WPRINTF +__printf_pad (FILE *s, char pad, size_t count) +#else +__wprintf_pad (FILE *s, wchar_t pad, size_t count) +#endif +{ + const CHAR_T *padptr; + register size_t i; + + padptr = pad == L_(' ') ? blanks : zeroes; + + for (i = count; i >= PADSIZE; i -= PADSIZE) + if (PUT (s, padptr, PADSIZE) != PADSIZE) + return -1; + if (i > 0) + if (PUT (s, padptr, i) != i) + return -1; + + return count; +} +#undef PADSIZE +#endif /* USE_IN_LIBIO */ + +#ifdef USE_IN_LIBIO +# undef vfprintf +# ifdef strong_alias +/* This is for glibc. */ +# ifdef COMPILE_WPRINTF +strong_alias (_IO_vfwprintf, __vfwprintf); +weak_alias (_IO_vfwprintf, vfwprintf); +# else +strong_alias (_IO_vfprintf, vfprintf); +libc_hidden_def (vfprintf) +INTDEF(_IO_vfprintf) +# endif +# else +# if defined __ELF__ || defined __GNU_LIBRARY__ +# include +# ifdef weak_alias +# ifdef COMPILE_WPRINTF +weak_alias (_IO_vfwprintf, vfwprintf); +# else +weak_alias (_IO_vfprintf, vfprintf); +# endif +# endif +# endif +# endif +#endif diff --git a/src/kernel/libroot/posix/glibc/stdio-common/vfscanf.c b/src/kernel/libroot/posix/glibc/stdio-common/vfscanf.c new file mode 100644 index 0000000000..93d909958d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/vfscanf.c @@ -0,0 +1,2456 @@ +/* Copyright (C) 1991-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +# define HAVE_LONGLONG +# define LONGLONG long long +#else +# define LONGLONG long +#endif + +/* Determine whether we have to handle `long long' at all. */ +#if LONG_MAX == LONG_LONG_MAX +# define need_longlong 0 +#else +# define need_longlong 1 +#endif + +/* Determine whether we have to handle `long'. */ +#if INT_MAX == LONG_MAX +# define need_long 0 +#else +# define need_long 1 +#endif + +/* Those are flags in the conversion format. */ +#define LONG 0x001 /* l: long or double */ +#define LONGDBL 0x002 /* L: long long or long double */ +#define SHORT 0x004 /* h: short */ +#define SUPPRESS 0x008 /* *: suppress assignment */ +#define POINTER 0x010 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x020 /* do not skip blanks */ +#define WIDTH 0x040 /* width was given */ +#define GROUP 0x080 /* ': group numbers */ +#define MALLOC 0x100 /* a: malloc strings */ +#define CHAR 0x200 /* hh: char */ +#define I18N 0x400 /* I: use locale's digits */ + + +#ifdef USE_IN_LIBIO +# include +# include + +# undef va_list +# define va_list _IO_va_list + +# ifdef COMPILE_WSCANF +# define ungetc(c, s) ((void) (c == WEOF \ + || (--read_in, \ + INTUSE(_IO_sputbackwc) (s, c)))) +# define ungetc_not_eof(c, s) ((void) (--read_in, \ + INTUSE(_IO_sputbackwc) (s, c))) +# define inchar() (c == WEOF ? ((errno = inchar_errno), WEOF) \ + : ((c = _IO_getwc_unlocked (s)), \ + (void) (c != WEOF \ + ? ++read_in \ + : (size_t) (inchar_errno = errno)), c)) + +# define MEMCPY(d, s, n) __wmemcpy (d, s, n) +# define ISSPACE(Ch) iswspace (Ch) +# define ISDIGIT(Ch) iswdigit (Ch) +# define ISXDIGIT(Ch) iswxdigit (Ch) +# define TOLOWER(Ch) towlower (Ch) +# define ORIENT if (_IO_fwide (s, 1) != 1) return WEOF +# define __strtoll_internal __wcstoll_internal +# define __strtoull_internal __wcstoull_internal +# define __strtol_internal __wcstol_internal +# define __strtoul_internal __wcstoul_internal +# define __strtold_internal __wcstold_internal +# define __strtod_internal __wcstod_internal +# define __strtof_internal __wcstof_internal + +# define L_(Str) L##Str +# define CHAR_T wchar_t +# define UCHAR_T unsigned int +# define WINT_T wint_t +# undef EOF +# define EOF WEOF +# else +# define ungetc(c, s) ((void) ((int) c == EOF \ + || (--read_in, \ + INTUSE(_IO_sputbackc) (s, (unsigned char) c)))) +# define ungetc_not_eof(c, s) ((void) (--read_in, \ + INTUSE(_IO_sputbackc) (s, (unsigned char) c))) +# define inchar() (c == EOF ? ((errno = inchar_errno), EOF) \ + : ((c = _IO_getc_unlocked (s)), \ + (void) (c != EOF \ + ? ++read_in \ + : (size_t) (inchar_errno = errno)), c)) +# define MEMCPY(d, s, n) memcpy (d, s, n) +# define ISSPACE(Ch) isspace (Ch) +# define ISDIGIT(Ch) isdigit (Ch) +# define ISXDIGIT(Ch) isxdigit (Ch) +# define TOLOWER(Ch) tolower (Ch) +# define ORIENT if (s->_vtable_offset == 0 \ + && _IO_fwide (s, -1) != -1) \ + return EOF + +# define L_(Str) Str +# define CHAR_T char +# define UCHAR_T unsigned char +# define WINT_T int +# endif + +# define encode_error() do { \ + if (errp != NULL) *errp |= 4; \ + _IO_funlockfile (s); \ + __libc_cleanup_end (0); \ + __set_errno (EILSEQ); \ + return done; \ + } while (0) +# define conv_error() do { \ + if (errp != NULL) *errp |= 2; \ + _IO_funlockfile (s); \ + __libc_cleanup_end (0); \ + return done; \ + } while (0) +# define input_error() do { \ + _IO_funlockfile (s); \ + if (errp != NULL) *errp |= 1; \ + __libc_cleanup_end (0); \ + return done ?: EOF; \ + } while (0) +# define memory_error() do { \ + _IO_funlockfile (s); \ + __set_errno (ENOMEM); \ + __libc_cleanup_end (0); \ + return EOF; \ + } while (0) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + CHECK_FILE (s, EOF); \ + if (s->_flags & _IO_NO_READS) \ + { \ + __set_errno (EBADF); \ + return EOF; \ + } \ + else if (format == NULL) \ + { \ + MAYBE_SET_EINVAL; \ + return EOF; \ + } \ + } while (0) +# define LOCK_STREAM(S) \ + __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, (S)); \ + _IO_flockfile (S) +# define UNLOCK_STREAM(S) \ + _IO_funlockfile (S); \ + __libc_cleanup_region_end (0) +#else +# define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s)) +# define ungetc_not_eof(c, s) (--read_in, (ungetc) (c, s)) +# define inchar() (c == EOF ? EOF \ + : ((c = getc (s)), (void) (c != EOF && ++read_in), c)) +# define MEMCPY(d, s, n) memcpy (d, s, n) +# define ISSPACE(Ch) isspace (Ch) +# define ISDIGIT(Ch) isdigit (Ch) +# define ISXDIGIT(Ch) isxdigit (Ch) +# define TOLOWER(Ch) tolower (Ch) + +# define L_(Str) Str +# define CHAR_T char +# define UCHAR_T unsigned char +# define WINT_T int + +# define encode_error() do { \ + funlockfile (s); \ + __set_errno (EILSEQ); \ + return done; \ + } while (0) +# define conv_error() do { \ + funlockfile (s); \ + return done; \ + } while (0) +# define input_error() do { \ + funlockfile (s); \ + return done ?: EOF; \ + } while (0) +# define memory_error() do { \ + funlockfile (s); \ + __set_errno (ENOMEM); \ + return EOF; \ + } while (0) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + if (!__validfp (s) || !s->__mode.__read) \ + { \ + __set_errno (EBADF); \ + return EOF; \ + } \ + else if (format == NULL) \ + { \ + __set_errno (EINVAL); \ + return EOF; \ + } \ + } while (0) +#if 1 + /* XXX For now !!! */ +# define flockfile(S) /* nothing */ +# define funlockfile(S) /* nothing */ +# define LOCK_STREAM(S) +# define UNLOCK_STREAM(S) +#else +# define LOCK_STREAM(S) \ + __libc_cleanup_region_start (&__funlockfile, (S)); \ + __flockfile (S) +# define UNLOCK_STREAM(S) \ + __funlockfile (S); \ + __libc_cleanup_region_end (0) +#endif +#endif + + +/* Read formatted input from S according to the format string + FORMAT, using the argument list in ARG. + Return the number of assignments made, or -1 for an input error. */ +#ifdef USE_IN_LIBIO +# ifdef COMPILE_WSCANF +int +_IO_vfwscanf (s, format, argptr, errp) + _IO_FILE *s; + const wchar_t *format; + _IO_va_list argptr; + int *errp; +# else +int +_IO_vfscanf (s, format, argptr, errp) + _IO_FILE *s; + const char *format; + _IO_va_list argptr; + int *errp; +# endif +#else +int +__vfscanf (FILE *s, const char *format, va_list argptr) +#endif +{ + va_list arg; + register const CHAR_T *f = format; + register UCHAR_T fc; /* Current character of the format. */ + register WINT_T done = 0; /* Assignments done. */ + register size_t read_in = 0; /* Chars read in. */ + register WINT_T c = 0; /* Last char read. */ + register int width; /* Maximum field width. */ + register int flags; /* Modifiers for current format element. */ + + /* Errno of last failed inchar call. */ + int inchar_errno = 0; + /* Status for reading F-P nums. */ + char got_dot, got_e, negative; + /* If a [...] is a [^...]. */ + CHAR_T not_in; +#define exp_char not_in + /* Base for integral numbers. */ + int base; + /* Signedness for integral numbers. */ + int number_signed; +#define is_hexa number_signed + /* Decimal point character. */ +#ifdef COMPILE_WSCANF + wchar_t decimal; +#else + const char *decimal; +#endif + /* The thousands character of the current locale. */ +#ifdef COMPILE_WSCANF + wchar_t thousands; +#else + const char *thousands; +#endif + /* State for the conversions. */ + mbstate_t state; + /* Integral holding variables. */ + union + { + long long int q; + unsigned long long int uq; + long int l; + unsigned long int ul; + } num; + /* Character-buffer pointer. */ + char *str = NULL; + wchar_t *wstr = NULL; + char **strptr = NULL; + ssize_t strsize = 0; + /* We must not react on white spaces immediately because they can + possibly be matched even if in the input stream no character is + available anymore. */ + int skip_space = 0; + /* Nonzero if we are reading a pointer. */ + int read_pointer; + /* Workspace. */ + CHAR_T *tw; /* Temporary pointer. */ + CHAR_T *wp = NULL; /* Workspace. */ + size_t wpmax = 0; /* Maximal size of workspace. */ + size_t wpsize; /* Currently used bytes in workspace. */ +#define ADDW(Ch) \ + do \ + { \ + if (wpsize == wpmax) \ + { \ + CHAR_T *old = wp; \ + wpmax = (UCHAR_MAX + 1 > 2 * wpmax ? UCHAR_MAX + 1 : 2 * wpmax); \ + wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t)); \ + if (old != NULL) \ + MEMCPY (wp, old, wpsize); \ + } \ + wp[wpsize++] = (Ch); \ + } \ + while (0) + +#ifdef __va_copy + __va_copy (arg, argptr); +#else + arg = (va_list) argptr; +#endif + +#ifdef ORIENT + ORIENT; +#endif + + ARGCHECK (s, format); + + /* Figure out the decimal point character. */ +#ifdef COMPILE_WSCANF + decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); +#else + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); +#endif + /* Figure out the thousands separator character. */ +#ifdef COMPILE_WSCANF + thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); +#else + thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); + if (*thousands == '\0') + thousands = NULL; +#endif + + /* Lock the stream. */ + LOCK_STREAM (s); + + +#ifndef COMPILE_WSCANF + /* From now on we use `state' to convert the format string. */ + memset (&state, '\0', sizeof (state)); +#endif + + /* Run through the format string. */ + while (*f != '\0') + { + unsigned int argpos; + /* Extract the next argument, which is of type TYPE. + For a %N$... spec, this is the Nth argument from the beginning; + otherwise it is the next argument after the state now in ARG. */ +#ifdef __va_copy +# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ + ({ unsigned int pos = argpos; \ + va_list arg; \ + __va_copy (arg, argptr); \ + while (--pos > 0) \ + (void) va_arg (arg, void *); \ + va_arg (arg, type); \ + })) +#else +# if 0 + /* XXX Possible optimization. */ +# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ + ({ va_list arg = (va_list) argptr; \ + arg = (va_list) ((char *) arg \ + + (argpos - 1) \ + * __va_rounded_size (void *)); \ + va_arg (arg, type); \ + })) +# else +# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ + ({ unsigned int pos = argpos; \ + va_list arg = (va_list) argptr; \ + while (--pos > 0) \ + (void) va_arg (arg, void *); \ + va_arg (arg, type); \ + })) +# endif +#endif + +#ifndef COMPILE_WSCANF + if (!isascii ((unsigned char) *f)) + { + /* Non-ASCII, may be a multibyte. */ + int len = __mbrlen (f, strlen (f), &state); + if (len > 0) + { + do + { + c = inchar (); + if (c == EOF) + input_error (); + else if (c != (unsigned char) *f++) + { + ungetc_not_eof (c, s); + conv_error (); + } + } + while (--len > 0); + continue; + } + } +#endif + + fc = *f++; + if (fc != '%') + { + /* Remember to skip spaces. */ + if (ISSPACE (fc)) + { + skip_space = 1; + continue; + } + + /* Read a character. */ + c = inchar (); + + /* Characters other than format specs must just match. */ + if (c == EOF) + input_error (); + + /* We saw white space char as the last character in the format + string. Now it's time to skip all leading white space. */ + if (skip_space) + { + while (ISSPACE (c)) + if (inchar () == EOF && errno == EINTR) + conv_error (); + skip_space = 0; + } + + if (c != fc) + { + ungetc (c, s); + conv_error (); + } + + continue; + } + + /* This is the start of the conversion string. */ + flags = 0; + + /* Not yet decided whether we read a pointer or not. */ + read_pointer = 0; + + /* Initialize state of modifiers. */ + argpos = 0; + + /* Prepare temporary buffer. */ + wpsize = 0; + + /* Check for a positional parameter specification. */ + if (ISDIGIT ((UCHAR_T) *f)) + { + argpos = (UCHAR_T) *f++ - L_('0'); + while (ISDIGIT ((UCHAR_T) *f)) + argpos = argpos * 10 + ((UCHAR_T) *f++ - L_('0')); + if (*f == L_('$')) + ++f; + else + { + /* Oops; that was actually the field width. */ + width = argpos; + flags |= WIDTH; + argpos = 0; + goto got_width; + } + } + + /* Check for the assignment-suppressing, the number grouping flag, + and the signal to use the locale's digit representation. */ + while (*f == L_('*') || *f == L_('\'') || *f == L_('I')) + switch (*f++) + { + case L_('*'): + flags |= SUPPRESS; + break; + case L_('\''): + flags |= GROUP; + break; + case L_('I'): + flags |= I18N; + break; + } + + /* We have seen width. */ + if (ISDIGIT ((UCHAR_T) *f)) + flags |= WIDTH; + + /* Find the maximum field width. */ + width = 0; + while (ISDIGIT ((UCHAR_T) *f)) + { + width *= 10; + width += (UCHAR_T) *f++ - L_('0'); + } + got_width: + if (width == 0) + width = -1; + + /* Check for type modifiers. */ + switch (*f++) + { + case L_('h'): + /* ints are short ints or chars. */ + if (*f == L_('h')) + { + ++f; + flags |= CHAR; + } + else + flags |= SHORT; + break; + case L_('l'): + if (*f == L_('l')) + { + /* A double `l' is equivalent to an `L'. */ + ++f; + flags |= LONGDBL | LONG; + } + else + /* ints are long ints. */ + flags |= LONG; + break; + case L_('q'): + case L_('L'): + /* doubles are long doubles, and ints are long long ints. */ + flags |= LONGDBL | LONG; + break; + case L_('a'): + /* The `a' is used as a flag only if followed by `s', `S' or + `['. */ + if (*f != L_('s') && *f != L_('S') && *f != L_('[')) + { + --f; + break; + } + /* String conversions (%s, %[) take a `char **' + arg and fill it in with a malloc'd pointer. */ + flags |= MALLOC; + break; + case L_('z'): + if (need_longlong && sizeof (size_t) > sizeof (unsigned long int)) + flags |= LONGDBL; + else if (sizeof (size_t) > sizeof (unsigned int)) + flags |= LONG; + break; + case L_('j'): + if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int)) + flags |= LONGDBL; + else if (sizeof (uintmax_t) > sizeof (unsigned int)) + flags |= LONG; + break; + case L_('t'): + if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int)) + flags |= LONGDBL; + else if (sizeof (ptrdiff_t) > sizeof (int)) + flags |= LONG; + break; + default: + /* Not a recognized modifier. Backup. */ + --f; + break; + } + + /* End of the format string? */ + if (*f == L_('\0')) + conv_error (); + + /* Find the conversion specifier. */ + fc = *f++; + if (skip_space || (fc != L_('[') && fc != L_('c') + && fc != L_('C') && fc != L_('n'))) + { + /* Eat whitespace. */ + int save_errno = errno; + errno = 0; + do + if (inchar () == EOF && errno == EINTR) + input_error (); + while (ISSPACE (c)); + errno = save_errno; + ungetc (c, s); + skip_space = 0; + } + + switch (fc) + { + case L_('%'): /* Must match a literal '%'. */ + c = inchar (); + if (c == EOF) + input_error (); + if (c != fc) + { + ungetc_not_eof (c, s); + conv_error (); + } + break; + + case L_('n'): /* Answer number of assignments done. */ + /* Corrigendum 1 to ISO C 1990 describes the allowed flags + with the 'n' conversion specifier. */ + if (!(flags & SUPPRESS)) + { + /* Don't count the read-ahead. */ + if (need_longlong && (flags & LONGDBL)) + *ARG (long long int *) = read_in; + else if (need_long && (flags & LONG)) + *ARG (long int *) = read_in; + else if (flags & SHORT) + *ARG (short int *) = read_in; + else if (!(flags & CHAR)) + *ARG (int *) = read_in; + else + *ARG (char *) = read_in; + +#ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1 + /* We have a severe problem here. The ISO C standard + contradicts itself in explaining the effect of the %n + format in `scanf'. While in ISO C:1990 and the ISO C + Amendement 1:1995 the result is described as + + Execution of a %n directive does not effect the + assignment count returned at the completion of + execution of the f(w)scanf function. + + in ISO C Corrigendum 1:1994 the following was added: + + Subclause 7.9.6.2 + Add the following fourth example: + In: + #include + int d1, d2, n1, n2, i; + i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2); + the value 123 is assigned to d1 and the value3 to n1. + Because %n can never get an input failure the value + of 3 is also assigned to n2. The value of d2 is not + affected. The value 3 is assigned to i. + + We go for now with the historically correct code from ISO C, + i.e., we don't count the %n assignments. When it ever + should proof to be wrong just remove the #ifdef above. */ + ++done; +#endif + } + break; + + case L_('c'): /* Match characters. */ + if ((flags & LONG) == 0) + { + if (!(flags & SUPPRESS)) + { + str = ARG (char *); + if (str == NULL) + conv_error (); + } + + c = inchar (); + if (c == EOF) + input_error (); + + if (width == -1) + width = 1; + +#ifdef COMPILE_WSCANF + /* We have to convert the wide character(s) into multibyte + characters and store the result. */ + memset (&state, '\0', sizeof (state)); + + do + { + size_t n; + + n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state); + if (n == (size_t) -1) + /* No valid wide character. */ + input_error (); + + /* Increment the output pointer. Even if we don't + write anything. */ + str += n; + } + while (--width > 0 && inchar () != EOF); +#else + if (!(flags & SUPPRESS)) + { + do + *str++ = c; + while (--width > 0 && inchar () != EOF); + } + else + while (--width > 0 && inchar () != EOF); +#endif + + if (!(flags & SUPPRESS)) + ++done; + + break; + } + /* FALLTHROUGH */ + case L_('C'): + if (!(flags & SUPPRESS)) + { + wstr = ARG (wchar_t *); + if (wstr == NULL) + conv_error (); + } + + c = inchar (); + if (c == EOF) + input_error (); + +#ifdef COMPILE_WSCANF + /* Just store the incoming wide characters. */ + if (!(flags & SUPPRESS)) + { + do + *wstr++ = c; + while (--width > 0 && inchar () != EOF); + } + else + while (--width > 0 && inchar () != EOF); +#else + { + /* We have to convert the multibyte input sequence to wide + characters. */ + char buf[1]; + mbstate_t cstate; + + memset (&cstate, '\0', sizeof (cstate)); + + do + { + /* This is what we present the mbrtowc function first. */ + buf[0] = c; + + while (1) + { + size_t n; + + n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL, + buf, 1, &cstate); + + if (n == (size_t) -2) + { + /* Possibly correct character, just not enough + input. */ + if (inchar () == EOF) + encode_error (); + + buf[0] = c; + continue; + } + + if (n != 1) + encode_error (); + + /* We have a match. */ + break; + } + + /* Advance the result pointer. */ + ++wstr; + } + while (--width > 0 && inchar () != EOF); + } +#endif + + if (!(flags & SUPPRESS)) + ++done; + + break; + + case L_('s'): /* Read a string. */ + if (!(flags & LONG)) + { +#define STRING_ARG(Str, Type) \ + do if (!(flags & SUPPRESS)) \ + { \ + if (flags & MALLOC) \ + { \ + /* The string is to be stored in a malloc'd buffer. */ \ + strptr = ARG (char **); \ + if (strptr == NULL) \ + conv_error (); \ + /* Allocate an initial buffer. */ \ + strsize = 100; \ + *strptr = (char *) malloc (strsize * sizeof (Type)); \ + Str = (Type *) *strptr; \ + } \ + else \ + Str = ARG (Type *); \ + if (Str == NULL) \ + conv_error (); \ + } while (0) + STRING_ARG (str, char); + + c = inchar (); + if (c == EOF) + input_error (); + +#ifdef COMPILE_WSCANF + memset (&state, '\0', sizeof (state)); +#endif + + do + { + if (ISSPACE (c)) + { + ungetc_not_eof (c, s); + break; + } + +#ifdef COMPILE_WSCANF + /* This is quite complicated. We have to convert the + wide characters into multibyte characters and then + store them. */ + { + size_t n; + + if (!(flags & SUPPRESS) && (flags & MALLOC) + && str + MB_CUR_MAX >= *strptr + strsize) + { + /* We have to enlarge the buffer if the `a' flag + was given. */ + size_t strleng = str - *strptr; + char *newstr; + + newstr = (char *) realloc (*strptr, strsize * 2); + if (newstr == NULL) + { + /* Can't allocate that much. Last-ditch + effort. */ + newstr = (char *) realloc (*strptr, + strleng + MB_CUR_MAX); + if (newstr == NULL) + { + /* We lose. Oh well. Terminate the + string and stop converting, + so at least we don't skip any input. */ + ((char *) (*strptr))[strleng] = '\0'; + ++done; + conv_error (); + } + else + { + *strptr = newstr; + str = newstr + strleng; + strsize = strleng + MB_CUR_MAX; + } + } + else + { + *strptr = newstr; + str = newstr + strleng; + strsize *= 2; + } + } + + n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, + &state); + if (n == (size_t) -1) + encode_error (); + + assert (n <= MB_CUR_MAX); + str += n; + } +#else + /* This is easy. */ + if (!(flags & SUPPRESS)) + { + *str++ = c; + if ((flags & MALLOC) + && (char *) str == *strptr + strsize) + { + /* Enlarge the buffer. */ + str = (char *) realloc (*strptr, 2 * strsize); + if (str == NULL) + { + /* Can't allocate that much. Last-ditch + effort. */ + str = (char *) realloc (*strptr, strsize + 1); + if (str == NULL) + { + /* We lose. Oh well. Terminate the + string and stop converting, + so at least we don't skip any input. */ + ((char *) (*strptr))[strsize - 1] = '\0'; + ++done; + conv_error (); + } + else + { + *strptr = (char *) str; + str += strsize; + ++strsize; + } + } + else + { + *strptr = (char *) str; + str += strsize; + strsize *= 2; + } + } + } +#endif + } + while ((width <= 0 || --width > 0) && inchar () != EOF); + + if (!(flags & SUPPRESS)) + { +#ifdef COMPILE_WSCANF + /* We have to emit the code to get into the initial + state. */ + char buf[MB_LEN_MAX]; + size_t n = __wcrtomb (buf, L'\0', &state); + if (n > 0 && (flags & MALLOC) + && str + n >= *strptr + strsize) + { + /* Enlarge the buffer. */ + size_t strleng = str - *strptr; + char *newstr; + + newstr = (char *) realloc (*strptr, strleng + n + 1); + if (newstr == NULL) + { + /* We lose. Oh well. Terminate the string + and stop converting, so at least we don't + skip any input. */ + ((char *) (*strptr))[strleng] = '\0'; + ++done; + conv_error (); + } + else + { + *strptr = newstr; + str = newstr + strleng; + strsize = strleng + n + 1; + } + } + + str = __mempcpy (str, buf, n); +#endif + *str++ = '\0'; + + if ((flags & MALLOC) && str - *strptr != strsize) + { + char *cp = (char *) realloc (*strptr, str - *strptr); + if (cp != NULL) + *strptr = cp; + } + + ++done; + } + break; + } + /* FALLTHROUGH */ + + case L_('S'): + { +#ifndef COMPILE_WSCANF + mbstate_t cstate; +#endif + + /* Wide character string. */ + STRING_ARG (wstr, wchar_t); + + c = inchar (); + if (c == EOF) + input_error (); + +#ifndef COMPILE_WSCANF + memset (&cstate, '\0', sizeof (cstate)); +#endif + + do + { + if (ISSPACE (c)) + { + ungetc_not_eof (c, s); + break; + } + +#ifdef COMPILE_WSCANF + /* This is easy. */ + if (!(flags & SUPPRESS)) + { + *wstr++ = c; + if ((flags & MALLOC) + && wstr == (wchar_t *) *strptr + strsize) + { + /* Enlarge the buffer. */ + wstr = (wchar_t *) realloc (*strptr, + (2 * strsize) + * sizeof (wchar_t)); + if (wstr == NULL) + { + /* Can't allocate that much. Last-ditch + effort. */ + wstr = (wchar_t *) realloc (*strptr, + (strsize + 1) + * sizeof (wchar_t)); + if (wstr == NULL) + { + /* We lose. Oh well. Terminate the string + and stop converting, so at least we don't + skip any input. */ + ((wchar_t *) (*strptr))[strsize - 1] = L'\0'; + ++done; + conv_error (); + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + ++strsize; + } + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + strsize *= 2; + } + } + } +#else + { + char buf[1]; + + buf[0] = c; + + while (1) + { + size_t n; + + n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL, + buf, 1, &cstate); + + if (n == (size_t) -2) + { + /* Possibly correct character, just not enough + input. */ + if (inchar () == EOF) + encode_error (); + + buf[0] = c; + continue; + } + + if (n != 1) + encode_error (); + + /* We have a match. */ + ++wstr; + break; + } + + if (!(flags & SUPPRESS) && (flags & MALLOC) + && wstr == (wchar_t *) *strptr + strsize) + { + /* Enlarge the buffer. */ + wstr = (wchar_t *) realloc (*strptr, + (2 * strsize + * sizeof (wchar_t))); + if (wstr == NULL) + { + /* Can't allocate that much. Last-ditch effort. */ + wstr = (wchar_t *) realloc (*strptr, + ((strsize + 1) + * sizeof (wchar_t))); + if (wstr == NULL) + { + /* We lose. Oh well. Terminate the + string and stop converting, so at + least we don't skip any input. */ + ((wchar_t *) (*strptr))[strsize - 1] = L'\0'; + ++done; + conv_error (); + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + ++strsize; + } + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + strsize *= 2; + } + } + } +#endif + } + while ((width <= 0 || --width > 0) && inchar () != EOF); + + if (!(flags & SUPPRESS)) + { + *wstr++ = L'\0'; + + if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize) + { + wchar_t *cp = (wchar_t *) realloc (*strptr, + ((wstr + - (wchar_t *) *strptr) + * sizeof(wchar_t))); + if (cp != NULL) + *strptr = (char *) cp; + } + + ++done; + } + } + break; + + case L_('x'): /* Hexadecimal integer. */ + case L_('X'): /* Ditto. */ + base = 16; + number_signed = 0; + goto number; + + case L_('o'): /* Octal integer. */ + base = 8; + number_signed = 0; + goto number; + + case L_('u'): /* Unsigned decimal integer. */ + base = 10; + number_signed = 0; + goto number; + + case L_('d'): /* Signed decimal integer. */ + base = 10; + number_signed = 1; + goto number; + + case L_('i'): /* Generic number. */ + base = 0; + number_signed = 1; + + number: + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == L_('-') || c == L_('+')) + { + ADDW (c); + if (width > 0) + --width; + c = inchar (); + } + + /* Look for a leading indication of base. */ + if (width != 0 && c == L_('0')) + { + if (width > 0) + --width; + + ADDW (c); + c = inchar (); + + if (width != 0 && TOLOWER (c) == L_('x')) + { + if (base == 0) + base = 16; + if (base == 16) + { + if (width > 0) + --width; + c = inchar (); + } + } + else if (base == 0) + base = 8; + } + + if (base == 0) + base = 10; + + if (base == 10 && (flags & I18N) != 0) + { + int from_level; + int to_level; + int level; +#ifdef COMPILE_WSCANF + const wchar_t *wcdigits[10]; +#else + const char *mbdigits[10]; +#endif + int n; + + from_level = 0; +#ifdef COMPILE_WSCANF + to_level = _NL_CURRENT_WORD (LC_CTYPE, + _NL_CTYPE_INDIGITS_WC_LEN) - 1; +#else + to_level = _NL_CURRENT_WORD (LC_CTYPE, + _NL_CTYPE_INDIGITS_MB_LEN) - 1; +#endif + + /* Read the number into workspace. */ + while (c != EOF && width != 0) + { + /* In this round we get the pointer to the digit strings + and also perform the first round of comparisons. */ + for (n = 0; n < 10; ++n) + { + /* Get the string for the digits with value N. */ +#ifdef COMPILE_WSCANF + wcdigits[n] = (const wchar_t *) + _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n); + wcdigits[n] += from_level; + + if (c == *wcdigits[n]) + { + to_level = from_level; + break; + } + + /* Advance the pointer to the next string. */ + ++wcdigits[n]; +#else + const char *cmpp; + int avail = width > 0 ? width : INT_MAX; + + mbdigits[n] = _NL_CURRENT (LC_CTYPE, + _NL_CTYPE_INDIGITS0_MB + n); + + for (level = 0; level < from_level; level++) + mbdigits[n] = strchr (mbdigits[n], '\0') + 1; + + cmpp = mbdigits[n]; + while ((unsigned char) *cmpp == c && avail > 0) + { + if (*++cmpp == '\0') + break; + else + { + if ((c = inchar ()) == EOF) + break; + --avail; + } + } + + if (*cmpp == '\0') + { + if (width > 0) + width = avail; + to_level = from_level; + break; + } + + /* We are pushing all read characters back. */ + if (cmpp > mbdigits[n]) + { + ungetc (c, s); + while (--cmpp > mbdigits[n]) + ungetc_not_eof ((unsigned char) *cmpp, s); + c = (unsigned char) *cmpp; + } + + /* Advance the pointer to the next string. */ + mbdigits[n] = strchr (mbdigits[n], '\0') + 1; +#endif + } + + if (n == 10) + { + /* Have not yet found the digit. */ + for (level = from_level + 1; level <= to_level; ++level) + { + /* Search all ten digits of this level. */ + for (n = 0; n < 10; ++n) + { +#ifdef COMPILE_WSCANF + if (c == *wcdigits[n]) + break; + + /* Advance the pointer to the next string. */ + ++wcdigits[n]; +#else + const char *cmpp; + int avail = width > 0 ? width : INT_MAX; + + cmpp = mbdigits[n]; + while ((unsigned char) *cmpp == c && avail > 0) + { + if (*++cmpp == '\0') + break; + else + { + if ((c = inchar ()) == EOF) + break; + --avail; + } + } + + if (*cmpp == '\0') + { + if (width > 0) + width = avail; + break; + } + + /* We are pushing all read characters back. */ + if (cmpp > mbdigits[n]) + { + ungetc (c, s); + while (--cmpp > mbdigits[n]) + ungetc_not_eof ((unsigned char) *cmpp, s); + c = (unsigned char) *cmpp; + } + + /* Advance the pointer to the next string. */ + mbdigits[n] = strchr (mbdigits[n], '\0') + 1; +#endif + } + + if (n < 10) + { + /* Found it. */ + from_level = level; + to_level = level; + break; + } + } + } + + if (n < 10) + c = L_('0') + n; + else if ((flags & GROUP) +#ifdef COMPILE_WSCANF + && thousands != L'\0' +#else + && thousands != NULL +#endif + ) + { + /* Try matching against the thousands separator. */ +#ifdef COMPILE_WSCANF + if (c != thousands) + break; +#else + const char *cmpp = thousands; + int avail = width > 0 ? width : INT_MAX; + + while ((unsigned char) *cmpp == c && avail > 0) + { + ADDW (c); + if (*++cmpp == '\0') + break; + else + { + if ((c = inchar ()) == EOF) + break; + --avail; + } + } + + if (*cmpp != '\0') + { + /* We are pushing all read characters back. */ + if (cmpp > thousands) + { + wpsize -= cmpp - thousands; + ungetc (c, s); + while (--cmpp > thousands) + ungetc_not_eof ((unsigned char) *cmpp, s); + c = (unsigned char) *cmpp; + } + break; + } + + if (width > 0) + width = avail; + + /* The last thousands character will be added back by + the ADDW below. */ + --wpsize; +#endif + } + else + break; + + ADDW (c); + if (width > 0) + --width; + + c = inchar (); + } + } + else + /* Read the number into workspace. */ + while (c != EOF && width != 0) + { + if (base == 16) + { + if (!ISXDIGIT (c)) + break; + } + else if (!ISDIGIT (c) || c - L_('0') >= base) + { + if (base == 10 && (flags & GROUP) +#ifdef COMPILE_WSCANF + && thousands != L'\0' +#else + && thousands != NULL +#endif + ) + { + /* Try matching against the thousands separator. */ +#ifdef COMPILE_WSCANF + if (c != thousands) + break; +#else + const char *cmpp = thousands; + int avail = width > 0 ? width : INT_MAX; + + while ((unsigned char) *cmpp == c && avail > 0) + { + ADDW (c); + if (*++cmpp == '\0') + break; + else + { + if ((c = inchar ()) == EOF) + break; + --avail; + } + } + + if (*cmpp != '\0') + { + /* We are pushing all read characters back. */ + if (cmpp > thousands) + { + wpsize -= cmpp - thousands; + ungetc (c, s); + while (--cmpp > thousands) + ungetc_not_eof ((unsigned char) *cmpp, s); + c = (unsigned char) *cmpp; + } + break; + } + + if (width > 0) + width = avail; + + /* The last thousands character will be added back by + the ADDW below. */ + --wpsize; +#endif + } + else + break; + } + ADDW (c); + if (width > 0) + --width; + + c = inchar (); + } + + if (wpsize == 0 + || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-')))) + { + /* There was no number. If we are supposed to read a pointer + we must recognize "(nil)" as well. */ + if (wpsize == 0 && read_pointer && (width < 0 || width >= 0) + && c == '(' + && TOLOWER (inchar ()) == L_('n') + && TOLOWER (inchar ()) == L_('i') + && TOLOWER (inchar ()) == L_('l') + && inchar () == L_(')')) + /* We must produce the value of a NULL pointer. A single + '0' digit is enough. */ + ADDW (L_('0')); + else + { + /* The last read character is not part of the number + anymore. */ + ungetc (c, s); + + conv_error (); + } + } + else + /* The just read character is not part of the number anymore. */ + ungetc (c, s); + + /* Convert the number. */ + ADDW (L_('\0')); + if (need_longlong && (flags & LONGDBL)) + { + if (number_signed) + num.q = __strtoll_internal (wp, &tw, base, flags & GROUP); + else + num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP); + } + else + { + if (number_signed) + num.l = __strtol_internal (wp, &tw, base, flags & GROUP); + else + num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP); + } + if (wp == tw) + conv_error (); + + if (!(flags & SUPPRESS)) + { + if (! number_signed) + { + if (need_longlong && (flags & LONGDBL)) + *ARG (unsigned LONGLONG int *) = num.uq; + else if (need_long && (flags & LONG)) + *ARG (unsigned long int *) = num.ul; + else if (flags & SHORT) + *ARG (unsigned short int *) + = (unsigned short int) num.ul; + else if (!(flags & CHAR)) + *ARG (unsigned int *) = (unsigned int) num.ul; + else + *ARG (unsigned char *) = (unsigned char) num.ul; + } + else + { + if (need_longlong && (flags & LONGDBL)) + *ARG (LONGLONG int *) = num.q; + else if (need_long && (flags & LONG)) + *ARG (long int *) = num.l; + else if (flags & SHORT) + *ARG (short int *) = (short int) num.l; + else if (!(flags & CHAR)) + *ARG (int *) = (int) num.l; + else + *ARG (signed char *) = (signed char) num.ul; + } + ++done; + } + break; + + case L_('e'): /* Floating-point numbers. */ + case L_('E'): + case L_('f'): + case L_('F'): + case L_('g'): + case L_('G'): + case L_('a'): + case L_('A'): + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == L_('-') || c == L_('+')) + { + negative = c == L_('-'); + if (width == 0 || inchar () == EOF) + /* EOF is only an input error before we read any chars. */ + conv_error (); + if (! ISDIGIT (c) && TOLOWER (c) != L_('i') + && TOLOWER (c) != L_('n')) + { +#ifdef COMPILE_WSCANF + if (c != decimal) + { + /* This is no valid number. */ + ungetc (c, s); + conv_error (); + } +#else + /* Match against the decimal point. At this point + we are taking advantage of the fact that we can + push more than one character back. This is + (almost) never necessary since the decimal point + string hopefully never contains more than one + byte. */ + const char *cmpp = decimal; + int avail = width > 0 ? width : INT_MAX; + + while ((unsigned char) *cmpp == c && avail > 0) + if (*++cmpp == '\0') + break; + else + { + if (inchar () == EOF) + break; + --avail; + } + + if (*cmpp != '\0') + { + /* This is no valid number. */ + while (1) + { + ungetc (c, s); + if (cmpp == decimal) + break; + c = (unsigned char) *--cmpp; + } + + conv_error (); + } + if (width > 0) + width = avail; +#endif + } + if (width > 0) + --width; + } + else + negative = 0; + + /* Take care for the special arguments "nan" and "inf". */ + if (TOLOWER (c) == L_('n')) + { + /* Maybe "nan". */ + ADDW (c); + if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + /* It is "nan". */ + goto scan_float; + } + else if (TOLOWER (c) == L_('i')) + { + /* Maybe "inf" or "infinity". */ + ADDW (c); + if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + /* It is as least "inf". */ + if (width != 0 && inchar () != EOF) + { + if (TOLOWER (c) == L_('i')) + { + if (width > 0) + --width; + /* Now we have to read the rest as well. */ + ADDW (c); + if (width == 0 || inchar () == EOF + || TOLOWER (c) != L_('n')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + if (width == 0 || inchar () == EOF + || TOLOWER (c) != L_('i')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + if (width == 0 || inchar () == EOF + || TOLOWER (c) != L_('t')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + if (width == 0 || inchar () == EOF + || TOLOWER (c) != L_('y')) + conv_error (); + if (width > 0) + --width; + ADDW (c); + } + else + /* Never mind. */ + ungetc (c, s); + } + goto scan_float; + } + + is_hexa = 0; + exp_char = L_('e'); + if (width != 0 && c == L_('0')) + { + ADDW (c); + c = inchar (); + if (width > 0) + --width; + if (width != 0 && TOLOWER (c) == L_('x')) + { + /* It is a number in hexadecimal format. */ + ADDW (c); + + is_hexa = 1; + exp_char = L_('p'); + + /* Grouping is not allowed. */ + flags &= ~GROUP; + c = inchar (); + if (width > 0) + --width; + } + } + + got_dot = got_e = 0; + do + { + if (ISDIGIT (c)) + ADDW (c); + else if (!got_e && is_hexa && ISXDIGIT (c)) + ADDW (c); + else if (got_e && wp[wpsize - 1] == exp_char + && (c == L_('-') || c == L_('+'))) + ADDW (c); + else if (wpsize > 0 && !got_e && TOLOWER (c) == exp_char) + { + ADDW (exp_char); + got_e = got_dot = 1; + } + else + { +#ifdef COMPILE_WSCANF + if (! got_dot && c == decimal) + { + ADDW (c); + got_dot = 1; + } + else if (thousands != L'\0' && ! got_dot && c == thousands) + ADDW (c); + else + { + /* The last read character is not part of the number + anymore. */ + ungetc (c, s); + break; + } +#else + const char *cmpp = decimal; + int avail = width > 0 ? width : INT_MAX; + + if (! got_dot) + { + while ((unsigned char) *cmpp == c && avail > 0) + if (*++cmpp == '\0') + break; + else + { + if (inchar () == EOF) + break; + --avail; + } + } + + if (*cmpp == '\0') + { + /* Add all the characters. */ + for (cmpp = decimal; *cmpp != '\0'; ++cmpp) + ADDW ((unsigned char) *cmpp); + if (width > 0) + width = avail; + got_dot = 1; + } + else + { + /* Figure out whether it is a thousands separator. + There is one problem: we possibly read more than + one character. We cannot push them back but since + we know that parts of the `decimal' string matched, + we can compare against it. */ + const char *cmp2p = thousands; + + if (thousands != NULL && ! got_dot) + { + while (cmp2p < cmpp + && *cmp2p == decimal[cmp2p - thousands]) + ++cmp2p; + if (cmp2p == cmpp) + { + while ((unsigned char) *cmp2p == c && avail > 0) + if (*++cmp2p == '\0') + break; + else + { + if (inchar () == EOF) + break; + --avail; + } + } + } + + if (cmp2p != NULL && *cmp2p == '\0') + { + /* Add all the characters. */ + for (cmpp = thousands; *cmpp != '\0'; ++cmpp) + ADDW ((unsigned char) *cmpp); + if (width > 0) + width = avail; + } + else + { + /* The last read character is not part of the number + anymore. */ + ungetc (c, s); + break; + } + } +#endif + } + if (width > 0) + --width; + } + while (width != 0 && inchar () != EOF); + + /* Have we read any character? If we try to read a number + in hexadecimal notation and we have read only the `0x' + prefix or no exponent this is an error. */ + if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e))) + conv_error (); + + scan_float: + /* Convert the number. */ + ADDW (L_('\0')); + if (flags & LONGDBL) + { + long double d = __strtold_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (long double *) = negative ? -d : d; + } + else if (flags & LONG) + { + double d = __strtod_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (double *) = negative ? -d : d; + } + else + { + float d = __strtof_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (float *) = negative ? -d : d; + } + + if (tw == wp) + conv_error (); + + if (!(flags & SUPPRESS)) + ++done; + break; + + case L_('['): /* Character class. */ + if (flags & LONG) + STRING_ARG (wstr, wchar_t); + else + STRING_ARG (str, char); + + if (*f == L_('^')) + { + ++f; + not_in = 1; + } + else + not_in = 0; + + if (width < 0) + /* There is no width given so there is also no limit on the + number of characters we read. Therefore we set width to + a very high value to make the algorithm easier. */ + width = INT_MAX; + +#ifdef COMPILE_WSCANF + /* Find the beginning and the end of the scanlist. We are not + creating a lookup table since it would have to be too large. + Instead we search each time through the string. This is not + a constant lookup time but who uses this feature deserves to + be punished. */ + tw = (wchar_t *) f; /* Marks the beginning. */ + + if (*f == L']') + ++f; + + while ((fc = *f++) != L'\0' && fc != L']'); + + if (fc == L'\0') + conv_error (); + wp = (wchar_t *) f - 1; +#else + /* Fill WP with byte flags indexed by character. + We will use this flag map for matching input characters. */ + if (wpmax < UCHAR_MAX + 1) + { + wpmax = UCHAR_MAX + 1; + wp = (char *) alloca (wpmax); + } + memset (wp, '\0', UCHAR_MAX + 1); + + fc = *f; + if (fc == ']' || fc == '-') + { + /* If ] or - appears before any char in the set, it is not + the terminator or separator, but the first char in the + set. */ + wp[fc] = 1; + ++f; + } + + while ((fc = *f++) != '\0' && fc != ']') + if (fc == '-' && *f != '\0' && *f != ']' + && (unsigned char) f[-2] <= (unsigned char) *f) + { + /* Add all characters from the one before the '-' + up to (but not including) the next format char. */ + for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc) + wp[fc] = 1; + } + else + /* Add the character to the flag map. */ + wp[fc] = 1; + + if (fc == '\0') + conv_error(); +#endif + + if (flags & LONG) + { + size_t now = read_in; +#ifdef COMPILE_WSCANF + if (inchar () == WEOF) + input_error (); + + do + { + wchar_t *runp; + + /* Test whether it's in the scanlist. */ + runp = tw; + while (runp < wp) + { + if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp + && runp != tw + && (unsigned int) runp[-1] <= (unsigned int) runp[1]) + { + /* Match against all characters in between the + first and last character of the sequence. */ + wchar_t wc; + + for (wc = runp[-1] + 1; wc <= runp[1]; ++wc) + if (wc == c) + break; + + if (wc <= runp[1] && !not_in) + break; + if (wc <= runp[1] && not_in) + { + /* The current character is not in the + scanset. */ + ungetc (c, s); + goto out; + } + + runp += 2; + } + else + { + if (*runp == c && !not_in) + break; + if (*runp == c && not_in) + { + ungetc (c, s); + goto out; + } + + ++runp; + } + } + + if (runp == wp && !not_in) + { + ungetc (c, s); + goto out; + } + + if (!(flags & SUPPRESS)) + { + *wstr++ = c; + + if ((flags & MALLOC) + && wstr == (wchar_t *) *strptr + strsize) + { + /* Enlarge the buffer. */ + wstr = (wchar_t *) realloc (*strptr, + (2 * strsize) + * sizeof (wchar_t)); + if (wstr == NULL) + { + /* Can't allocate that much. Last-ditch + effort. */ + wstr = (wchar_t *) + realloc (*strptr, (strsize + 1) + * sizeof (wchar_t)); + if (wstr == NULL) + { + /* We lose. Oh well. Terminate the string + and stop converting, so at least we don't + skip any input. */ + ((wchar_t *) (*strptr))[strsize - 1] = L'\0'; + ++done; + conv_error (); + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + ++strsize; + } + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + strsize *= 2; + } + } + } + } + while (--width > 0 && inchar () != WEOF); + out: +#else + char buf[MB_LEN_MAX]; + size_t cnt = 0; + mbstate_t cstate; + + if (inchar () == EOF) + input_error (); + + memset (&cstate, '\0', sizeof (cstate)); + + do + { + if (wp[c] == not_in) + { + ungetc_not_eof (c, s); + break; + } + + /* This is easy. */ + if (!(flags & SUPPRESS)) + { + size_t n; + + /* Convert it into a wide character. */ + buf[0] = c; + n = __mbrtowc (wstr, buf, 1, &cstate); + + if (n == (size_t) -2) + { + /* Possibly correct character, just not enough + input. */ + ++cnt; + assert (cnt < MB_CUR_MAX); + continue; + } + cnt = 0; + + ++wstr; + if ((flags & MALLOC) + && wstr == (wchar_t *) *strptr + strsize) + { + /* Enlarge the buffer. */ + wstr = (wchar_t *) realloc (*strptr, + (2 * strsize + * sizeof (wchar_t))); + if (wstr == NULL) + { + /* Can't allocate that much. Last-ditch + effort. */ + wstr = (wchar_t *) + realloc (*strptr, ((strsize + 1) + * sizeof (wchar_t))); + if (wstr == NULL) + { + /* We lose. Oh well. Terminate the + string and stop converting, + so at least we don't skip any input. */ + ((wchar_t *) (*strptr))[strsize - 1] = L'\0'; + ++done; + conv_error (); + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + ++strsize; + } + } + else + { + *strptr = (char *) wstr; + wstr += strsize; + strsize *= 2; + } + } + } + + if (--width <= 0) + break; + } + while (inchar () != EOF); + + if (cnt != 0) + /* We stopped in the middle of recognizing another + character. That's a problem. */ + encode_error (); +#endif + + if (now == read_in) + /* We haven't succesfully read any character. */ + conv_error (); + + if (!(flags & SUPPRESS)) + { + *wstr++ = L'\0'; + + if ((flags & MALLOC) + && wstr - (wchar_t *) *strptr != strsize) + { + wchar_t *cp = (wchar_t *) + realloc (*strptr, ((wstr - (wchar_t *) *strptr) + * sizeof(wchar_t))); + if (cp != NULL) + *strptr = (char *) cp; + } + + ++done; + } + } + else + { + size_t now = read_in; + + if (inchar () == EOF) + input_error (); + +#ifdef COMPILE_WSCANF + + memset (&state, '\0', sizeof (state)); + + do + { + wchar_t *runp; + size_t n; + + /* Test whether it's in the scanlist. */ + runp = tw; + while (runp < wp) + { + if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp + && runp != tw + && (unsigned int) runp[-1] <= (unsigned int) runp[1]) + { + /* Match against all characters in between the + first and last character of the sequence. */ + wchar_t wc; + + for (wc = runp[-1] + 1; wc <= runp[1]; ++wc) + if (wc == c) + break; + + if (wc <= runp[1] && !not_in) + break; + if (wc <= runp[1] && not_in) + { + /* The current character is not in the + scanset. */ + ungetc (c, s); + goto out2; + } + + runp += 2; + } + else + { + if (*runp == c && !not_in) + break; + if (*runp == c && not_in) + { + ungetc (c, s); + goto out2; + } + + ++runp; + } + } + + if (runp == wp && !not_in) + { + ungetc (c, s); + goto out2; + } + + if (!(flags & SUPPRESS)) + { + if ((flags & MALLOC) + && str + MB_CUR_MAX >= *strptr + strsize) + { + /* Enlarge the buffer. */ + size_t strleng = str - *strptr; + char *newstr; + + newstr = (char *) realloc (*strptr, 2 * strsize); + if (newstr == NULL) + { + /* Can't allocate that much. Last-ditch + effort. */ + newstr = (char *) realloc (*strptr, + strleng + MB_CUR_MAX); + if (newstr == NULL) + { + /* We lose. Oh well. Terminate the string + and stop converting, so at least we don't + skip any input. */ + ((char *) (*strptr))[strleng] = '\0'; + ++done; + conv_error (); + } + else + { + *strptr = newstr; + str = newstr + strleng; + strsize = strleng + MB_CUR_MAX; + } + } + else + { + *strptr = newstr; + str = newstr + strleng; + strsize *= 2; + } + } + } + + n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state); + if (n == (size_t) -1) + encode_error (); + + assert (n <= MB_CUR_MAX); + str += n; + } + while (--width > 0 && inchar () != WEOF); + out2: +#else + do + { + if (wp[c] == not_in) + { + ungetc_not_eof (c, s); + break; + } + + /* This is easy. */ + if (!(flags & SUPPRESS)) + { + *str++ = c; + if ((flags & MALLOC) + && (char *) str == *strptr + strsize) + { + /* Enlarge the buffer. */ + str = (char *) realloc (*strptr, 2 * strsize); + if (str == NULL) + { + /* Can't allocate that much. Last-ditch + effort. */ + str = (char *) realloc (*strptr, strsize + 1); + if (str == NULL) + { + /* We lose. Oh well. Terminate the + string and stop converting, + so at least we don't skip any input. */ + ((char *) (*strptr))[strsize - 1] = '\0'; + ++done; + conv_error (); + } + else + { + *strptr = (char *) str; + str += strsize; + ++strsize; + } + } + else + { + *strptr = (char *) str; + str += strsize; + strsize *= 2; + } + } + } + } + while (--width > 0 && inchar () != EOF); +#endif + + if (now == read_in) + /* We haven't succesfully read any character. */ + conv_error (); + + if (!(flags & SUPPRESS)) + { +#ifdef COMPILE_WSCANF + /* We have to emit the code to get into the initial + state. */ + char buf[MB_LEN_MAX]; + size_t n = __wcrtomb (buf, L'\0', &state); + if (n > 0 && (flags & MALLOC) + && str + n >= *strptr + strsize) + { + /* Enlarge the buffer. */ + size_t strleng = str - *strptr; + char *newstr; + + newstr = (char *) realloc (*strptr, strleng + n + 1); + if (newstr == NULL) + { + /* We lose. Oh well. Terminate the string + and stop converting, so at least we don't + skip any input. */ + ((char *) (*strptr))[strleng] = '\0'; + ++done; + conv_error (); + } + else + { + *strptr = newstr; + str = newstr + strleng; + strsize = strleng + n + 1; + } + } + + str = __mempcpy (str, buf, n); +#endif + *str++ = '\0'; + + if ((flags & MALLOC) && str - *strptr != strsize) + { + char *cp = (char *) realloc (*strptr, str - *strptr); + if (cp != NULL) + *strptr = cp; + } + + ++done; + } + } + break; + + case L_('p'): /* Generic pointer. */ + base = 16; + /* A PTR must be the same size as a `long int'. */ + flags &= ~(SHORT|LONGDBL); + if (need_long) + flags |= LONG; + number_signed = 0; + read_pointer = 1; + goto number; + + default: + /* If this is an unknown format character punt. */ + conv_error (); + } + } + + /* The last thing we saw int the format string was a white space. + Consume the last white spaces. */ + if (skip_space) + { + do + c = inchar (); + while (ISSPACE (c)); + ungetc (c, s); + } + + /* Unlock stream. */ + UNLOCK_STREAM (s); + + return done; +} + +#ifdef USE_IN_LIBIO +# ifdef COMPILE_WSCANF +int +__vfwscanf (FILE *s, const wchar_t *format, va_list argptr) +{ + return _IO_vfwscanf (s, format, argptr, NULL); +} +# else +int +__vfscanf (FILE *s, const char *format, va_list argptr) +{ + return INTUSE(_IO_vfscanf) (s, format, argptr, NULL); +} +libc_hidden_def (__vfscanf) +# endif +#endif + +#ifdef COMPILE_WSCANF +weak_alias (__vfwscanf, vfwscanf) +#else +weak_alias (__vfscanf, vfscanf) +INTDEF(_IO_vfscanf) +#endif diff --git a/src/kernel/libroot/posix/glibc/stdio-common/vfwprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/vfwprintf.c new file mode 100644 index 0000000000..2c3cd06fad --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/vfwprintf.c @@ -0,0 +1,3 @@ +#include +#define COMPILE_WPRINTF 1 +#include "vfprintf.c" diff --git a/src/kernel/libroot/posix/glibc/stdio-common/vfwscanf.c b/src/kernel/libroot/posix/glibc/stdio-common/vfwscanf.c new file mode 100644 index 0000000000..26b1a66608 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/vfwscanf.c @@ -0,0 +1,2 @@ +#define COMPILE_WSCANF 1 +#include "vfscanf.c" diff --git a/src/kernel/libroot/posix/glibc/stdio-common/vprintf.c b/src/kernel/libroot/posix/glibc/stdio-common/vprintf.c new file mode 100644 index 0000000000..a8c4a53cd8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdio-common/vprintf.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1993, 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#undef __OPTIMIZE__ /* Avoid inline `vprintf' function. */ +#include + +#undef vprintf + +/* Write formatted output to stdout according to the + format string FORMAT, using the argument list in ARG. */ +int +vprintf (format, arg) + const char *format; + __gnuc_va_list arg; +{ + return vfprintf (stdout, format, arg); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/Makefile b/src/kernel/libroot/posix/glibc/stdlib/Makefile new file mode 100644 index 0000000000..4d471c911b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/Makefile @@ -0,0 +1,119 @@ +# Copyright (C) 1991-1999, 2000, 2001, 2002 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +# +# Makefile for stdlib routines +# +subdir := stdlib + +headers := stdlib.h alloca.h monetary.h fmtmsg.h ucontext.h sys/ucontext.h \ + inttypes.h stdint.h bits/wordsize.h bits/wchar.h \ + errno.h sys/errno.h bits/errno.h + +routines := \ + atof atoi atol atoll \ + abort \ + bsearch qsort msort \ + getenv putenv setenv secure-getenv \ + exit on_exit atexit cxa_atexit cxa_finalize old_atexit \ + abs labs llabs \ + div ldiv lldiv \ + mblen mbstowcs mbtowc wcstombs wctomb \ + random random_r rand rand_r \ + drand48 erand48 lrand48 nrand48 mrand48 jrand48 \ + srand48 seed48 lcong48 \ + drand48_r erand48_r lrand48_r nrand48_r mrand48_r jrand48_r \ + srand48_r seed48_r lcong48_r \ + drand48-iter \ + strtol strtoul strtoll strtoull \ + strtol_l strtoul_l strtoll_l strtoull_l \ + strtof strtod strtold \ + strtof_l strtod_l strtold_l \ + system canonicalize \ + a64l l64a \ + rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \ + strtoimax strtoumax wcstoimax wcstoumax \ + getcontext setcontext makecontext swapcontext + +# These routines will be omitted from the libc shared object. +# Instead the static object files will be included in a special archive +# linked against when the shared library will be used. +static-only-routines = atexit + +distribute := exit.h grouping.h abort-instr.h isomac.c tst-fmtmsg.sh \ + allocalim.h +test-srcs := tst-fmtmsg +tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ + test-canon test-canon2 tst-strtoll tst-environ \ + tst-xpg-basename tst-random tst-bsearch tst-limits \ + tst-rand48 bug-strtod tst-setcontext test-a64l tst-qsort \ + tst-system + + +# Several mpn functions from GNU MP are used by the strtod function. +mpn-routines := inlines add_n addmul_1 cmp divmod_1 divrem udiv_qrnnd \ + lshift rshift mod_1 mul mul_1 mul_n sub_n submul_1 +mpn-headers = longlong.h gmp.h gmp-impl.h gmp-mparam.h asm-syntax.h + +routines := $(strip $(routines) $(mpn-routines)) \ + dbl2mpn ldbl2mpn \ + mpn2flt mpn2dbl mpn2ldbl +aux := fpioconst mp_clz_tab +distribute := $(distribute) $(mpn-headers) gen-mpn-copy fpioconst.h + +generated += isomac isomac.out + +CFLAGS-bsearch.c = $(exceptions) +CFLAGS-msort.c = $(exceptions) +CFLAGS-qsort.c = $(exceptions) + +include ../Makeconfig + +ifneq (,$(filter %REENTRANT, $(defines))) +CFLAGS-strfmon.c = -D_IO_MTSAFE_IO +CFLAGS-strfmon_l.c = -D_IO_MTSAFE_IO +endif + +ifeq (yes,$(have-protected)) +CFLAGS-atexit.c = -DHAVE_DOT_HIDDEN +endif + +include ../Rules + +# Testdir has to be named stdlib and needs to be writable +test-canon-ARGS = --test-dir=${common-objpfx}stdlib + +tst-strtod-ENV = LOCPATH=$(common-objpfx)localedata + +# Run a test on the header files we use. +tests: $(objpfx)isomac.out + +ifeq (no,$(cross-compiling)) +tests: $(objpfx)tst-fmtmsg.out +endif + +$(objpfx)isomac.out: $(objpfx)isomac + $(dir $<)$(notdir $<) '$(CC)' \ + '-I../include -I.. $(+sysdep-includes) $(sysincludes)' > $<.out + +isomac-CFLAGS = -O +$(objpfx)isomac: isomac.c + $(native-compile) + +$(objpfx)tst-fmtmsg.out: tst-fmtmsg.sh $(objpfx)tst-fmtmsg + $(SHELL) -e $< $(common-objpfx) '$(run-program-prefix)' $(common-objpfx)stdlib/ diff --git a/src/kernel/libroot/posix/glibc/stdlib/Versions b/src/kernel/libroot/posix/glibc/stdlib/Versions new file mode 100644 index 0000000000..fc1e5a1004 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/Versions @@ -0,0 +1,105 @@ +libc { + GLIBC_2.0 { + # functions with required interface outside normal name space + __xpg_basename; + + # functions used in inline functions or macros + __strto*_internal; + + # functions used in other libraries + __secure_getenv; + + # a* + a64l; abort; abs; atexit; atof; atoi; atol; atoll; + + # b* + bsearch; + + # c* + canonicalize_file_name; clearenv; + + # d* + div; drand48; drand48_r; + + # e* + erand48; erand48_r; exit; + + # g* + getenv; getsubopt; + + # i* + initstate; initstate_r; + + # l* + l64a; labs; lcong48; lcong48_r; ldiv; llabs; lldiv; lrand48; lrand48_r; + + # m* + mblen; mbrlen; mbrtowc; mbsinit; mbsnrtowcs; mbsrtowcs; mbstowcs; + mbtowc; mcheck; mcount; mrand48; mrand48_r; + + # n* + nrand48; nrand48_r; + + # o* + on_exit; + + # p* + putenv; + + # q* + qsort; + + # r* + rand; rand_r; random; random_r; realpath; rpmatch; + + # s* + seed48; seed48_r; setcontext; setenv; setstate; setstate_r; srand; srand48; + srand48_r; srandom; srandom_r; step; strfmon; strtod; strtof; strtol; + strtold; strtoll; strtoq; strtoul; strtoull; strtouq; system; + + # u* + unsetenv; + + # w* + wcstombs; wctomb; + } + GLIBC_2.1 { + # a* + addseverity; + + # f* + fmtmsg; + + # g* + getcontext; + + # m* + makecontext; + + # s* + strtoimax; strtoumax; swapcontext; + } + GLIBC_2.1.1 { + # _* + _Exit; + + # i* + imaxabs; imaxdiv; + } + GLIBC_2.1.3 { + # used by new G++ ABI + __cxa_atexit; __cxa_finalize; + } + GLIBC_2.3 { + # Silent change in SUS. + realpath; + } + GLIBC_PRIVATE { + # functions which have an additional interface since they are + # are cancelable. + __libc_system; + + # functions used in other libraries. + __on_exit; + } +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/a64l.c b/src/kernel/libroot/posix/glibc/stdlib/a64l.c new file mode 100644 index 0000000000..23faf2744f --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/a64l.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define TABLE_BASE 0x2e +#define TABLE_SIZE 0x4d + +#define XX ((char)0x40) + + +static const char a64l_table[TABLE_SIZE] = +{ + /* 0x2e */ 0, 1, + /* 0x30 */ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, XX, XX, XX, XX, XX, XX, + /* 0x40 */ XX, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + /* 0x50 */ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, XX, XX, XX, XX, XX, + /* 0x60 */ XX, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 0x70 */ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 +}; + + +long int +a64l (string) + const char *string; +{ + const char *ptr = string; + unsigned long int result = 0ul; + const char *end = ptr + 6; + int shift = 0; + + do + { + unsigned index; + unsigned value; + + index = *ptr - TABLE_BASE; + if ((unsigned int) index >= TABLE_SIZE) + break; + value = (int) a64l_table[index]; + if (value == (int) XX) + break; + ++ptr; + result |= value << shift; + shift += 6; + } + while (ptr != end); + + return (long int) result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/abs.c b/src/kernel/libroot/posix/glibc/stdlib/abs.c new file mode 100644 index 0000000000..7a6ad36a1a --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/abs.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef abs + +/* Return the absolute value of I. */ +int +abs (int i) +{ + return i < 0 ? -i : i; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/alloca.h b/src/kernel/libroot/posix/glibc/stdlib/alloca.h new file mode 100644 index 0000000000..0dd291f1b2 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/alloca.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1992, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ALLOCA_H +#define _ALLOCA_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +/* Remove any previous definitions. */ +#undef alloca + +/* Allocate a block that will be freed when the calling function exits. */ +extern void *alloca (size_t __size) __THROW; + +#ifdef __GNUC__ +# define alloca(size) __builtin_alloca (size) +#endif /* GCC. */ + +__END_DECLS + +#endif /* alloca.h */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/atexit.c b/src/kernel/libroot/posix/glibc/stdlib/atexit.c new file mode 100644 index 0000000000..024381dd43 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/atexit.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991, 1996, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "exit.h" + + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + + +/* Register FUNC to be executed by `exit'. */ +int +atexit (void (*func) (void)) +{ + return __cxa_atexit ((void (*) (void *)) func, NULL, + &__dso_handle == NULL ? NULL : __dso_handle); +} + +/* Hide the symbol so that no definition but the one locally in the + executable or DSO is used. */ +#ifdef HAVE_DOT_HIDDEN +asm (".hidden\tatexit"); +#endif diff --git a/src/kernel/libroot/posix/glibc/stdlib/atof.c b/src/kernel/libroot/posix/glibc/stdlib/atof.c new file mode 100644 index 0000000000..2ce3483ef2 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/atof.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef atof + + +/* Convert a string to a double. */ +double +atof (const char *nptr) +{ + return strtod (nptr, (char **) NULL); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/atoi.c b/src/kernel/libroot/posix/glibc/stdlib/atoi.c new file mode 100644 index 0000000000..217287586e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/atoi.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef atoi + + +/* Convert a string to an int. */ +int +atoi (const char *nptr) +{ + return (int) strtol (nptr, (char **) NULL, 10); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/atol.c b/src/kernel/libroot/posix/glibc/stdlib/atol.c new file mode 100644 index 0000000000..ec77f44cb8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/atol.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef atol + + +/* Convert a string to a long int. */ +long int +atol (const char *nptr) +{ + return strtol (nptr, (char **) NULL, 10); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/atoll.c b/src/kernel/libroot/posix/glibc/stdlib/atoll.c new file mode 100644 index 0000000000..f2fdd1abeb --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/atoll.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef atoll + + +/* Convert a string to a long long int. */ +long long int +atoll (const char *nptr) +{ + return strtoll (nptr, (char **) NULL, 10); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/bsearch.c b/src/kernel/libroot/posix/glibc/stdlib/bsearch.c new file mode 100644 index 0000000000..1bc6c4ba43 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/bsearch.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1991,92,97,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Perform a binary search for KEY in BASE which has NMEMB elements + of SIZE bytes each. The comparisons are done by (*COMPAR)(). */ +void * +bsearch (const void *key, const void *base, size_t nmemb, size_t size, + int (*compar) (const void *, const void *)) +{ + size_t l, u, idx; + const void *p; + int comparison; + + l = 0; + u = nmemb; + while (l < u) + { + idx = (l + u) / 2; + p = (void *) (((const char *) base) + (idx * size)); + comparison = (*compar) (key, p); + if (comparison < 0) + u = idx; + else if (comparison > 0) + l = idx + 1; + else + return (void *) p; + } + + return NULL; +} +libc_hidden_def (bsearch) diff --git a/src/kernel/libroot/posix/glibc/stdlib/canonicalize.c b/src/kernel/libroot/posix/glibc/stdlib/canonicalize.c new file mode 100644 index 0000000000..5c55c5dbd1 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/canonicalize.c @@ -0,0 +1,240 @@ +/* Return the canonical absolute name of a given file. + Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Return the canonical absolute name of file NAME. A canonical name + does not contain any `.', `..' components nor any repeated path + separators ('/') or symlinks. All path components must exist. If + RESOLVED is null, the result is malloc'd; otherwise, if the + canonical name is PATH_MAX chars or more, returns null with `errno' + set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, + returns the name in RESOLVED. If the name cannot be resolved and + RESOLVED is non-NULL, it contains the path of the first component + that cannot be resolved. If the path can be resolved, RESOLVED + holds the same value as the value returned. */ + +char * +__realpath (const char *name, char *resolved) +{ + char *rpath, *dest, *extra_buf = NULL; + const char *start, *end, *rpath_limit; + long int path_max; + int num_links = 0; + + if (name == NULL) + { + /* As per Single Unix Specification V2 we must return an error if + either parameter is a null pointer. We extend this to allow + the RESOLVED parameter to be NULL in case the we are expected to + allocate the room for the return value. */ + __set_errno (EINVAL); + return NULL; + } + + if (name[0] == '\0') + { + /* As per Single Unix Specification V2 we must return an error if + the name argument points to an empty string. */ + __set_errno (ENOENT); + return NULL; + } + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = pathconf (name, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 1024; +#endif + + if (resolved == NULL) + { + rpath = malloc (path_max); + if (rpath == NULL) + return NULL; + } + else + rpath = resolved; + rpath_limit = rpath + path_max; + + if (name[0] != '/') + { + if (!__getcwd (rpath, path_max)) + { + rpath[0] = '\0'; + goto error; + } + dest = strchr (rpath, '\0'); + } + else + { + rpath[0] = '/'; + dest = rpath + 1; + } + + for (start = end = name; *start; start = end) + { + struct stat64 st; + int n; + + /* Skip sequence of multiple path-separators. */ + while (*start == '/') + ++start; + + /* Find end of path component. */ + for (end = start; *end && *end != '/'; ++end) + /* Nothing. */; + + if (end - start == 0) + break; + else if (end - start == 1 && start[0] == '.') + /* nothing */; + else if (end - start == 2 && start[0] == '.' && start[1] == '.') + { + /* Back up to previous component, ignore if at root already. */ + if (dest > rpath + 1) + while ((--dest)[-1] != '/'); + } + else + { + size_t new_size; + + if (dest[-1] != '/') + *dest++ = '/'; + + if (dest + (end - start) >= rpath_limit) + { + ptrdiff_t dest_offset = dest - rpath; + char *new_rpath; + + if (resolved) + { + __set_errno (ENAMETOOLONG); + if (dest > rpath + 1) + dest--; + *dest = '\0'; + goto error; + } + new_size = rpath_limit - rpath; + if (end - start + 1 > path_max) + new_size += end - start + 1; + else + new_size += path_max; + new_rpath = (char *) realloc (rpath, new_size); + if (new_rpath == NULL) + goto error; + rpath = new_rpath; + rpath_limit = rpath + new_size; + + dest = rpath + dest_offset; + } + + dest = __mempcpy (dest, start, end - start); + *dest = '\0'; + + if (__lxstat64 (_STAT_VER, rpath, &st) < 0) + goto error; + + if (S_ISLNK (st.st_mode)) + { + char *buf = __alloca (path_max); + size_t len; + + if (++num_links > MAXSYMLINKS) + { + __set_errno (ELOOP); + goto error; + } + + n = __readlink (rpath, buf, path_max); + if (n < 0) + goto error; + buf[n] = '\0'; + + if (!extra_buf) + extra_buf = __alloca (path_max); + + len = strlen (end); + if ((long int) (n + len) >= path_max) + { + __set_errno (ENAMETOOLONG); + goto error; + } + + /* Careful here, end may be a pointer into extra_buf... */ + memmove (&extra_buf[n], end, len + 1); + name = end = memcpy (extra_buf, buf, n); + + if (buf[0] == '/') + dest = rpath + 1; /* It's an absolute symlink */ + else + /* Back up to previous component, ignore if at root already: */ + if (dest > rpath + 1) + while ((--dest)[-1] != '/'); + } + } + } + if (dest > rpath + 1 && dest[-1] == '/') + --dest; + *dest = '\0'; + + return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath; + +error: + if (resolved) + strcpy (resolved, rpath); + else + free (rpath); + return NULL; +} +versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); + + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3) +char * +__old_realpath (const char *name, char *resolved) +{ + if (resolved == NULL) + { + __set_errno (EINVAL); + return NULL; + } + + return __realpath (name, resolved); +} +compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0); +#endif + + +char * +__canonicalize_file_name (const char *name) +{ + return __realpath (name, NULL); +} +weak_alias (__canonicalize_file_name, canonicalize_file_name) diff --git a/src/kernel/libroot/posix/glibc/stdlib/cxa_atexit.c b/src/kernel/libroot/posix/glibc/stdlib/cxa_atexit.c new file mode 100644 index 0000000000..a3d4c5037d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/cxa_atexit.c @@ -0,0 +1,96 @@ +/* Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "exit.h" + +#undef __cxa_atexit + +/* Register a function to be called by exit or when a shared library + is unloaded. This function is only called from code generated by + the C++ compiler. */ +int +__cxa_atexit (void (*func) (void *), void *arg, void *d) +{ + struct exit_function *new = __new_exitfn (); + + if (new == NULL) + return -1; + + new->flavor = ef_cxa; + new->func.cxa.fn = (void (*) (void *, int)) func; + new->func.cxa.arg = arg; + new->func.cxa.dso_handle = d; + return 0; +} +INTDEF(__cxa_atexit) + + +/* We change global data, so we need locking. */ +__libc_lock_define_initialized (static, lock) + + +static struct exit_function_list initial; +struct exit_function_list *__exit_funcs = &initial; + +struct exit_function * +__new_exitfn (void) +{ + struct exit_function_list *l; + size_t i = 0; + + __libc_lock_lock (lock); + + for (l = __exit_funcs; l != NULL; l = l->next) + { + for (i = 0; i < l->idx; ++i) + if (l->fns[i].flavor == ef_free) + break; + if (i < l->idx) + break; + + if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) + { + i = l->idx++; + break; + } + } + + if (l == NULL) + { + l = (struct exit_function_list *) + malloc (sizeof (struct exit_function_list)); + if (l != NULL) + { + l->next = __exit_funcs; + __exit_funcs = l; + + l->idx = 1; + i = 0; + } + } + + /* Mark entry as used, but we don't know the flavor now. */ + if (l != NULL) + l->fns[i].flavor = ef_us; + + __libc_lock_unlock (lock); + + return l == NULL ? NULL : &l->fns[i]; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/cxa_finalize.c b/src/kernel/libroot/posix/glibc/stdlib/cxa_finalize.c new file mode 100644 index 0000000000..16f50286e1 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/cxa_finalize.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "exit.h" +#include + +/* If D is non-NULL, call all functions registered with `__cxa_atexit' + with the same dso handle. Otherwise, if D is NULL, do nothing. */ +void +__cxa_finalize (void *d) +{ + struct exit_function_list *funcs; + + for (funcs = __exit_funcs; funcs; funcs = funcs->next) + { + struct exit_function *f; + + for (f = &funcs->fns[funcs->idx - 1]; f >= &funcs->fns[0]; --f) + if ((d == NULL || d == f->func.cxa.dso_handle) + /* We don't want to run this cleanup more than once. */ + && compare_and_swap (&f->flavor, ef_cxa, ef_free)) + (*f->func.cxa.fn) (f->func.cxa.arg, 0); + } + + /* Remove the registered fork handlers. */ +#ifdef UNREGISTER_ATFORK + UNREGISTER_ATFORK (d); +#endif +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/drand48-iter.c b/src/kernel/libroot/posix/glibc/stdlib/drand48-iter.c new file mode 100644 index 0000000000..06fb876598 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/drand48-iter.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* Global state for non-reentrant functions. */ +struct drand48_data __libc_drand48_data; + + +int +__drand48_iterate (xsubi, buffer) + unsigned short int xsubi[3]; + struct drand48_data *buffer; +{ + uint64_t X; + uint64_t result; + + /* Initialize buffer, if not yet done. */ + if (__builtin_expect (!buffer->__init, 0)) + { + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + } + + /* Do the real work. We choose a data type which contains at least + 48 bits. Because we compute the modulus it does not care how + many bits really are computed. */ + + X = (uint64_t) xsubi[2] << 32 | (uint32_t) xsubi[1] << 16 | xsubi[0]; + + result = X * buffer->__a + buffer->__c; + + xsubi[0] = result & 0xffff; + xsubi[1] = (result >> 16) & 0xffff; + xsubi[2] = (result >> 32) & 0xffff; + + return 0; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/drand48.c b/src/kernel/libroot/posix/glibc/stdlib/drand48.c new file mode 100644 index 0000000000..06b586f812 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/drand48.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +double +drand48 () +{ + double result; + + (void) __erand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/drand48_r.c b/src/kernel/libroot/posix/glibc/stdlib/drand48_r.c new file mode 100644 index 0000000000..99a2495cd2 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/drand48_r.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +drand48_r (buffer, result) + struct drand48_data *buffer; + double *result; +{ + return __erand48_r (buffer->__x, buffer, result); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/erand48.c b/src/kernel/libroot/posix/glibc/stdlib/erand48.c new file mode 100644 index 0000000000..7ed4e4cab6 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/erand48.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +double +erand48 (xsubi) + unsigned short int xsubi[3]; +{ + double result; + + (void) __erand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/erand48_r.c b/src/kernel/libroot/posix/glibc/stdlib/erand48_r.c new file mode 100644 index 0000000000..48b24e34ee --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/erand48_r.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1995, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int +__erand48_r (xsubi, buffer, result) + unsigned short int xsubi[3]; + struct drand48_data *buffer; + double *result; +{ + union ieee754_double temp; + + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Construct a positive double with the 48 random bits distributed over + its fractional part so the resulting FP number is [0.0,1.0). */ + + temp.ieee.negative = 0; + temp.ieee.exponent = IEEE754_DOUBLE_BIAS; + temp.ieee.mantissa0 = (xsubi[2] << 4) | (xsubi[1] >> 12); + temp.ieee.mantissa1 = ((xsubi[1] & 0xfff) << 20) | (xsubi[0] << 4); + + /* Please note the lower 4 bits of mantissa1 are always 0. */ + *result = temp.d - 1.0; + + return 0; +} +weak_alias (__erand48_r, erand48_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/errno.h b/src/kernel/libroot/posix/glibc/stdlib/errno.h new file mode 100644 index 0000000000..f33b0c921c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/errno.h @@ -0,0 +1,73 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.5 Errors + */ + +#ifndef _ERRNO_H + +/* The includer defined __need_Emath if he wants only the definitions + of EDOM and ERANGE, and not everything else. */ +#ifndef __need_Emath +# define _ERRNO_H 1 +# include +#endif + +__BEGIN_DECLS + +/* Get the error number constants from the system-specific file. + This file will test __need_Emath and _ERRNO_H. */ +#include +#undef __need_Emath + +#ifdef _ERRNO_H + +/* Declare the `errno' variable, unless it's defined as a macro by + bits/errno.h. This is the case in GNU, where it is a per-thread + variable. This redeclaration using the macro still works, but it + will be a function declaration without a prototype and may trigger + a -Wstrict-prototypes warning. */ +#ifndef errno +extern int errno; +#endif + +#ifdef __USE_GNU + +/* The full and simple forms of the name with which the program was + invoked. These variables are set up automatically at startup based on + the value of ARGV[0] (this works only if you use GNU ld). */ +extern char *program_invocation_name, *program_invocation_short_name; +#endif /* __USE_GNU */ +#endif /* _ERRNO_H */ + +__END_DECLS + +#endif /* _ERRNO_H */ + +/* The Hurd defines `error_t' as an enumerated type so + that printing `error_t' values in the debugger shows the names. We + might need this definition sometimes even if this file was included + before. */ +#if defined __USE_GNU || defined __need_error_t +# ifndef __error_t_defined +typedef int error_t; +# define __error_t_defined 1 +# endif +# undef __need_error_t +#endif diff --git a/src/kernel/libroot/posix/glibc/stdlib/exit.c b/src/kernel/libroot/posix/glibc/stdlib/exit.c new file mode 100644 index 0000000000..ac247a1233 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/exit.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1991,95,96,97,99,2001,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "exit.h" + +#ifdef HAVE_GNU_LD +#include "set-hooks.h" +DEFINE_HOOK (__libc_atexit, (void)) +#endif + + +/* Call all functions registered with `atexit' and `on_exit', + in the reverse of the order in which they were registered + perform stdio cleanup, and terminate program execution with STATUS. */ +void +exit (int status) +{ + /* We do it this way to handle recursive calls to exit () made by + the functions registered with `atexit' and `on_exit'. We call + everyone on the list and use the status value in the last + exit (). */ + while (__exit_funcs != NULL) + { + struct exit_function_list *old; + + while (__exit_funcs->idx > 0) + { + const struct exit_function *const f = + &__exit_funcs->fns[--__exit_funcs->idx]; + switch (f->flavor) + { + case ef_free: + case ef_us: + break; + case ef_on: + (*f->func.on.fn) (status, f->func.on.arg); + break; + case ef_at: + (*f->func.at) (); + break; + case ef_cxa: + (*f->func.cxa.fn) (f->func.cxa.arg, status); + break; + } + } + + old = __exit_funcs; + __exit_funcs = __exit_funcs->next; + if (__exit_funcs != NULL) + /* Don't free the last element in the chain, this is the statically + allocate element. */ + free (old); + } + +#ifdef HAVE_GNU_LD + RUN_HOOK (__libc_atexit, ()); +#else + { + extern void _cleanup (void); + _cleanup (); + } +#endif + + _exit (status); +} +libc_hidden_def (exit) diff --git a/src/kernel/libroot/posix/glibc/stdlib/exit.h b/src/kernel/libroot/posix/glibc/stdlib/exit.h new file mode 100644 index 0000000000..055506f04e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/exit.h @@ -0,0 +1,63 @@ +/* Copyright (C) 1991,1996,1997,1999,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _EXIT_H +#define _EXIT_H 1 + + +enum +{ + ef_free, /* `ef_free' MUST be zero! */ + ef_us, + ef_on, + ef_at, + ef_cxa +}; + +struct exit_function + { + /* `flavour' should be of type of the `enum' above but since we need + this element in an atomic operation we have to use `long int'. */ + long int flavor; + union + { + void (*at) (void); + struct + { + void (*fn) (int status, void *arg); + void *arg; + } on; + struct + { + void (*fn) (void *arg, int status); + void *arg; + void *dso_handle; + } cxa; + } func; + }; +struct exit_function_list + { + struct exit_function_list *next; + size_t idx; + struct exit_function fns[32]; + }; +extern struct exit_function_list *__exit_funcs attribute_hidden; + +extern struct exit_function *__new_exitfn (void); + +#endif /* exit.h */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/fmtmsg.c b/src/kernel/libroot/posix/glibc/stdlib/fmtmsg.c new file mode 100644 index 0000000000..37c641c7ef --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/fmtmsg.c @@ -0,0 +1,408 @@ +/* Copyright (C) 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#endif + + +/* We have global data, protect the modification. */ +__libc_lock_define_initialized (static, lock) + + +enum +{ + label_mask = 0x01, + severity_mask = 0x02, + text_mask = 0x04, + action_mask = 0x08, + tag_mask = 0x10, + all_mask = label_mask | severity_mask | text_mask | action_mask | tag_mask +}; + +static const struct +{ + size_t len; + /* Adjust the size if new elements are added. */ + const char name[12]; +} keywords[] = + { + { 5, "label" }, + { 8, "severity" }, + { 4, "text" }, + { 6, "action"}, + { 3, "tag" } + }; +#define NKEYWORDS (sizeof( keywords) / sizeof (keywords[0])) + + +struct severity_info +{ + int severity; + const char *string; + struct severity_info *next; +}; + + +/* List of known severities. */ +static const struct severity_info nosev = +{ + MM_NOSEV, "", NULL +}; +static const struct severity_info haltsev = +{ + MM_HALT, "HALT", (struct severity_info *) &nosev +}; +static const struct severity_info errorsev = +{ + MM_ERROR, "ERROR", (struct severity_info *) &haltsev +}; +static const struct severity_info warningsev = +{ + MM_WARNING, "WARNING", (struct severity_info *) &errorsev +}; +static const struct severity_info infosev = +{ + MM_INFO, "INFO", (struct severity_info *) &warningsev +}; + +/* Start of the list. */ +static struct severity_info *severity_list = (struct severity_info *) &infosev; + +/* Mask of values we will print. */ +static int print; + +/* Prototypes for local functions. */ +static void init (void); +static int internal_addseverity (int severity, const char *string) + internal_function; + + +int +fmtmsg (long int classification, const char *label, int severity, + const char *text, const char *action, const char *tag) +{ + __libc_once_define (static, once); + int result = MM_OK; + struct severity_info *severity_rec; + + /* make sure everything is initialized. */ + __libc_once (once, init); + + /* Start the real work. First check whether the input is ok. */ + if (label != MM_NULLLBL) + { + /* Must be two fields, separated by a colon. */ + const char *cp = strchr (label, ':'); + if (cp == NULL) + return MM_NOTOK; + + /* The first field must not contain more then 10 bytes. */ + if (cp - label > 10 + /* The second field must not have more then 14 bytes. */ + || strlen (cp + 1) > 14) + return MM_NOTOK; + } + + for (severity_rec = severity_list; severity_rec != NULL; + severity_rec = severity_rec->next) + if (severity == severity_rec->severity) + /* Bingo. */ + break; + + /* If we don't know anything about the severity level return an error. */ + if (severity_rec == NULL) + return MM_NOTOK; + + + /* Now we can print. */ + if (classification & MM_PRINT) + { + int do_label = (print & label_mask) && label != MM_NULLLBL; + int do_severity = (print & severity_mask) && severity != MM_NULLSEV; + int do_text = (print & text_mask) && text != MM_NULLTXT; + int do_action = (print & action_mask) && action != MM_NULLACT; + int do_tag = (print & tag_mask) && tag != MM_NULLTAG; + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + { + if (__fwprintf (stderr, L"%s%s%s%s%s%s%s%s%s%s\n", + do_label ? label : "", + do_label + && (do_severity | do_text | do_action | do_tag) + ? ": " : "", + do_severity ? severity_rec->string : "", + do_severity && (do_text | do_action | do_tag) + ? ": " : "", + do_text ? text : "", + do_text && (do_action | do_tag) ? "\n" : "", + do_action ? "TO FIX: " : "", + do_action ? action : "", + do_action && do_tag ? " " : "", + do_tag ? tag : "") < 0) + /* Oh, oh. An error occurred during the output. */ + result = MM_NOMSG; + } + else +#endif + if (fprintf (stderr, "%s%s%s%s%s%s%s%s%s%s\n", + do_label ? label : "", + do_label && (do_severity | do_text | do_action | do_tag) + ? ": " : "", + do_severity ? severity_rec->string : "", + do_severity && (do_text | do_action | do_tag) ? ": " : "", + do_text ? text : "", + do_text && (do_action | do_tag) ? "\n" : "", + do_action ? "TO FIX: " : "", + do_action ? action : "", + do_action && do_tag ? " " : "", + do_tag ? tag : "") < 0) + /* Oh, oh. An error occurred during the output. */ + result = MM_NOMSG; + } + + if (classification & MM_CONSOLE) + { + int do_label = label != MM_NULLLBL; + int do_severity = severity != MM_NULLSEV; + int do_text = text != MM_NULLTXT; + int do_action = action != MM_NULLACT; + int do_tag = tag != MM_NULLTAG; + + syslog (LOG_ERR, "%s%s%s%s%s%s%s%s%s%s\n", + do_label ? label : "", + do_label && (do_severity | do_text | do_action | do_tag) + ? ": " : "", + do_severity ? severity_rec->string : "", + do_severity && (do_text | do_action | do_tag) ? ": " : "", + do_text ? text : "", + do_text && (do_action | do_tag) ? "\n" : "", + do_action ? "TO FIX: " : "", + do_action ? action : "", + do_action && do_tag ? " " : "", + do_tag ? tag : ""); + } + + return result; +} + + +/* Initialize from environment variable content. */ +static void +init (void) +{ + const char *msgverb_var = getenv ("MSGVERB"); + const char *sevlevel_var = getenv ("SEV_LEVEL"); + + if (msgverb_var != NULL && msgverb_var[0] != '\0') + { + /* Using this extra variable allows us to work without locking. */ + do + { + size_t cnt; + + for (cnt = 0; cnt < NKEYWORDS; ++cnt) + if (memcmp (msgverb_var, + keywords[cnt].name, keywords[cnt].len) == 0 + && (msgverb_var[keywords[cnt].len] == ':' + || msgverb_var[keywords[cnt].len] == '\0')) + break; + + if (cnt < NKEYWORDS) + { + print |= 1 << cnt; + + msgverb_var += keywords[cnt].len; + if (msgverb_var[0] == ':') + ++msgverb_var; + } + else + { + /* We found an illegal keyword in the environment + variable. The specifications say that we print all + fields. */ + print = all_mask; + break; + } + } + while (msgverb_var[0] != '\0'); + } + else + print = all_mask; + + + if (sevlevel_var != NULL) + { + __libc_lock_lock (lock); + + while (sevlevel_var[0] != '\0') + { + const char *end = __strchrnul (sevlevel_var, ':'); + int level; + + /* First field: keyword. This is not used here but it must be + present. */ + while (sevlevel_var < end) + if (*sevlevel_var++ == ',') + break; + + if (sevlevel_var < end) + { + /* Second field: severity level, a number. */ + char *cp; + + level = strtol (sevlevel_var, &cp, 0); + if (cp != sevlevel_var && cp < end && *cp++ == ',' + && level > MM_INFO) + { + const char *new_string; + + new_string = __strndup (cp, end - cp); + + if (new_string != NULL + && (internal_addseverity (level, new_string) + != MM_OK)) + free ((char *) new_string); + } + } + + sevlevel_var = end + (*end == ':' ? 1 : 0); + } + } +} + + +/* Add the new entry to the list. */ +static int +internal_function +internal_addseverity (int severity, const char *string) +{ + struct severity_info *runp, *lastp; + int result = MM_OK; + + /* First see if there is already a record for the severity level. */ + for (runp = severity_list, lastp = NULL; runp != NULL; runp = runp-> next) + if (runp->severity == severity) + break; + else + lastp = runp; + + if (runp != NULL) + { + /* Release old string. */ + free ((char *) runp->string); + + if (string != NULL) + /* Change the string. */ + runp->string = string; + else + { + /* Remove the severity class. */ + if (lastp == NULL) + severity_list = runp->next; + else + lastp->next = runp->next; + + free (runp); + } + } + else if (string != NULL) + { + runp = malloc (sizeof (*runp)); + if (runp == NULL) + result = MM_NOTOK; + else + { + runp->severity = severity; + runp->next = severity_list; + runp->string = string; + severity_list = runp; + } + } + else + /* We tried to remove a non-existing severity class. */ + result = MM_NOTOK; + + return result; +} + + +/* Add new severity level or remove old one. */ +int +addseverity (int severity, const char *string) +{ + int result; + const char *new_string; + + /* Prevent illegal SEVERITY values. */ + if (severity <= MM_INFO) + return MM_NOTOK; + + if (string == NULL) + /* We want to remove the severity class. */ + new_string = NULL; + else + { + new_string = __strdup (string); + + if (new_string == NULL) + /* Allocation failed or illegal value. */ + return MM_NOTOK; + } + + /* Protect the global data. */ + __libc_lock_lock (lock); + + /* Do the real work. */ + result = internal_addseverity (severity, string); + + if (result != MM_OK) + /* Free the allocated string. */ + free ((char *) new_string); + + /* Release the lock. */ + __libc_lock_unlock (lock); + + return result; +} + + +libc_freeres_fn (free_mem) +{ + struct severity_info *runp = severity_list; + + while (runp != NULL) + if (runp->severity > MM_INFO) + { + /* This is data we have to release. */ + struct severity_info *here = runp; + free ((char *) runp->string); + runp = runp->next; + free (here); + } + else + runp = runp->next; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/fmtmsg.h b/src/kernel/libroot/posix/glibc/stdlib/fmtmsg.h new file mode 100644 index 0000000000..cd9bdeaffd --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/fmtmsg.h @@ -0,0 +1,106 @@ +/* Message display handling. + Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __FMTMSG_H +#define __FMTMSG_H 1 + +#include + + +__BEGIN_DECLS + +/* Values to control `fmtmsg' function. */ +enum +{ + MM_HARD = 0x001, /* Source of the condition is hardware. */ +#define MM_HARD MM_HARD + MM_SOFT = 0x002, /* Source of the condition is software. */ +#define MM_SOFT MM_SOFT + MM_FIRM = 0x004, /* Source of the condition is firmware. */ +#define MM_FIRM MM_FIRM + MM_APPL = 0x008, /* Condition detected by application. */ +#define MM_APPL MM_APPL + MM_UTIL = 0x010, /* Condition detected by utility. */ +#define MM_UTIL MM_UTIL + MM_OPSYS = 0x020, /* Condition detected by operating system. */ +#define MM_OPSYS MM_OPSYS + MM_RECOVER = 0x040, /* Recoverable error. */ +#define MM_RECOVER MM_RECOVER + MM_NRECOV = 0x080, /* Non-recoverable error. */ +#define MM_NRECOV MM_NRECOV + MM_PRINT = 0x100, /* Display message in standard error. */ +#define MM_PRINT MM_PRINT + MM_CONSOLE = 0x200 /* Display message on system console. */ +#define MM_CONSOLE MM_CONSOLE +}; + +/* Values to be for SEVERITY parameter of `fmtmsg'. */ +enum +{ + MM_NOSEV = 0, /* No severity level provided for the message. */ +#define MM_NOSEV MM_NOSEV + MM_HALT, /* Error causing application to halt. */ +#define MM_HALT MM_HALT + MM_ERROR, /* Application has encountered a non-fatal fault. */ +#define MM_ERROR MM_ERROR + MM_WARNING, /* Application has detected unusual non-error + condition. */ +#define MM_WARNING MM_WARNING + MM_INFO /* Informative message. */ +#define MM_INFO MM_INFO +}; + + +/* Macros which can be used as null values for the arguments of `fmtmsg'. */ +#define MM_NULLLBL ((char *) 0) +#define MM_NULLSEV 0 +#define MM_NULLMC ((long int) 0) +#define MM_NULLTXT ((char *) 0) +#define MM_NULLACT ((char *) 0) +#define MM_NULLTAG ((char *) 0) + + +/* Possible return values of `fmtmsg'. */ +enum +{ + MM_NOTOK = -1, +#define MM_NOTOK MM_NOTOK + MM_OK = 0, +#define MM_OK MM_OK + MM_NOMSG = 1, +#define MM_NOMSG MM_NOMSG + MM_NOCON = 4 +#define MM_NOCON MM_NOCON +}; + + +/* Print message with given CLASSIFICATION, LABEL, SEVERITY, TEXT, ACTION + and TAG to console or standard error. */ +extern int fmtmsg (long int __classification, __const char *__label, + int __severity, __const char *__text, + __const char *__action, __const char *__tag) __THROW; + +#ifdef __USE_SVID +/* Add or remove severity level. */ +extern int addseverity (int __severity, __const char *__string) __THROW; +#endif + +__END_DECLS + +#endif /* fmtmsg.h */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/fpioconst.c b/src/kernel/libroot/posix/glibc/stdlib/fpioconst.c new file mode 100644 index 0000000000..931386db06 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/fpioconst.c @@ -0,0 +1,462 @@ +/* Table of MP integer constants 10^(2^i), used for floating point <-> decimal. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fpioconst.h" +#include /* This defines BITS_PER_MP_LIMB. */ + +/* First page : 32-bit limbs + Second page : 64-bit limbs + Last page : table of pointers + */ + +#if BITS_PER_MP_LIMB == 32 + +/* Table with constants of 10^(2^i), i=0..12 for 32-bit limbs. */ + +const mp_limb_t __tens[] = +{ +#define TENS_P0_IDX 0 +#define TENS_P0_SIZE 3 + [TENS_P0_IDX] = 0x00000000, 0x00000000, 0x0000000a, + +#define TENS_P1_IDX (TENS_P0_IDX + TENS_P0_SIZE) +#define TENS_P1_SIZE 3 + [TENS_P1_IDX] = 0x00000000, 0x00000000, 0x00000064, + +#define TENS_P2_IDX (TENS_P1_IDX + TENS_P1_SIZE) +#define TENS_P2_SIZE 3 + [TENS_P2_IDX] = 0x00000000, 0x00000000, 0x00002710, + +#define TENS_P3_IDX (TENS_P2_IDX + TENS_P2_SIZE) +#define TENS_P3_SIZE 3 + [TENS_P3_IDX] = 0x00000000, 0x00000000, 0x05f5e100, + +#define TENS_P4_IDX (TENS_P3_IDX + TENS_P3_SIZE) +#define TENS_P4_SIZE 4 + [TENS_P4_IDX] = 0x00000000, 0x00000000, 0x6fc10000, 0x002386f2, + +#define TENS_P5_IDX (TENS_P4_IDX + TENS_P4_SIZE) +#define TENS_P5_SIZE 6 + [TENS_P5_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x85acef81, 0x2d6d415b, + 0x000004ee, + +#define TENS_P6_IDX (TENS_P5_IDX + TENS_P5_SIZE) +#define TENS_P6_SIZE 9 + [TENS_P6_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xbf6a1f01, + 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x00184f03, + +#define TENS_P7_IDX (TENS_P6_IDX + TENS_P6_SIZE) +#define TENS_P7_SIZE 16 + [TENS_P7_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x2e953e01, 0x03df9909, 0x0f1538fd, 0x2374e42f, 0xd3cff5ec, + 0xc404dc08, 0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x0000024e, + +#define TENS_P8_IDX (TENS_P7_IDX + TENS_P7_SIZE) +#define TENS_P8_SIZE 29 + [TENS_P8_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x982e7c01, + 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, + 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, + 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x000553f7, + +#ifndef __NO_LONG_DOUBLE_MATH +# define TENS_P9_IDX (TENS_P8_IDX + TENS_P8_SIZE) +# define TENS_P9_SIZE 56 + [TENS_P9_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xfc6cf801, 0x77f27267, 0x8f9546dc, 0x5d96976f, 0xb83a8a97, + 0xc31e1ad9, 0x46c40513, 0x94e65747, 0xc88976c1, 0x4475b579, 0x28f8733b, + 0xaa1da1bf, 0x703ed321, 0x1e25cfea, 0xb21a2f22, 0xbc51fb2e, 0x96e14f5d, + 0xbfa3edac, 0x329c57ae, 0xe7fc7153, 0xc3fc0695, 0x85a91924, 0xf95f635e, + 0xb2908ee0, 0x93abade4, 0x1366732a, 0x9449775c, 0x69be5b0e, 0x7343afac, + 0xb099bc81, 0x45a71d46, 0xa2699748, 0x8cb07303, 0x8a0b1f13, 0x8cab8a97, + 0xc1d238d9, 0x633415d4, 0x0000001c, + +# define TENS_P10_IDX (TENS_P9_IDX + TENS_P9_SIZE) +# define TENS_P10_SIZE 109 + [TENS_P10_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2919f001, + 0xf55b2b72, 0x6e7c215b, 0x1ec29f86, 0x991c4e87, 0x15c51a88, 0x140ac535, + 0x4c7d1e1a, 0xcc2cd819, 0x0ed1440e, 0x896634ee, 0x7de16cfb, 0x1e43f61f, + 0x9fce837d, 0x231d2b9c, 0x233e55c7, 0x65dc60d7, 0xf451218b, 0x1c5cd134, + 0xc9635986, 0x922bbb9f, 0xa7e89431, 0x9f9f2a07, 0x62be695a, 0x8e1042c4, + 0x045b7a74, 0x1abe1de3, 0x8ad822a5, 0xba34c411, 0xd814b505, 0xbf3fdeb3, + 0x8fc51a16, 0xb1b896bc, 0xf56deeec, 0x31fb6bfd, 0xb6f4654b, 0x101a3616, + 0x6b7595fb, 0xdc1a47fe, 0x80d98089, 0x80bda5a5, 0x9a202882, 0x31eb0f66, + 0xfc8f1f90, 0x976a3310, 0xe26a7b7e, 0xdf68368a, 0x3ce3a0b8, 0x8e4262ce, + 0x75a351a2, 0x6cb0b6c9, 0x44597583, 0x31b5653f, 0xc356e38a, 0x35faaba6, + 0x0190fba0, 0x9fc4ed52, 0x88bc491b, 0x1640114a, 0x005b8041, 0xf4f3235e, + 0x1e8d4649, 0x36a8de06, 0x73c55349, 0xa7e6bd2a, 0xc1a6970c, 0x47187094, + 0xd2db49ef, 0x926c3f5b, 0xae6209d4, 0x2d433949, 0x34f4a3c6, 0xd4305d94, + 0xd9d61a05, 0x00000325, + +# define TENS_P11_IDX (TENS_P10_IDX + TENS_P10_SIZE) +# define TENS_P11_SIZE 215 + [TENS_P11_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x1333e001, 0xe3096865, 0xb27d4d3f, 0x49e28dcf, 0xec2e4721, + 0xee87e354, 0xb6067584, 0x368b8abb, 0xa5e5a191, 0x2ed56d55, 0xfd827773, + 0xea50d142, 0x51b78db2, 0x98342c9e, 0xc850dabc, 0x866ed6f1, 0x19342c12, + 0x92794987, 0xd2f869c2, 0x66912e4a, 0x71c7fd8f, 0x57a7842d, 0x235552eb, + 0xfb7fedcc, 0xf3861ce0, 0x38209ce1, 0x9713b449, 0x34c10134, 0x8c6c54de, + 0xa7a8289c, 0x2dbb6643, 0xe3cb64f3, 0x8074ff01, 0xe3892ee9, 0x10c17f94, + 0xa8f16f92, 0xa8281ed6, 0x967abbb3, 0x5a151440, 0x9952fbed, 0x13b41e44, + 0xafe609c3, 0xa2bca416, 0xf111821f, 0xfb1264b4, 0x91bac974, 0xd6c7d6ab, + 0x8e48ff35, 0x4419bd43, 0xc4a65665, 0x685e5510, 0x33554c36, 0xab498697, + 0x0dbd21fe, 0x3cfe491d, 0x982da466, 0xcbea4ca7, 0x9e110c7b, 0x79c56b8a, + 0x5fc5a047, 0x84d80e2e, 0x1aa9f444, 0x730f203c, 0x6a57b1ab, 0xd752f7a6, + 0x87a7dc62, 0x944545ff, 0x40660460, 0x77c1a42f, 0xc9ac375d, 0xe866d7ef, + 0x744695f0, 0x81428c85, 0xa1fc6b96, 0xd7917c7b, 0x7bf03c19, 0x5b33eb41, + 0x5715f791, 0x8f6cae5f, 0xdb0708fd, 0xb125ac8e, 0x785ce6b7, 0x56c6815b, + 0x6f46eadb, 0x4eeebeee, 0x195355d8, 0xa244de3c, 0x9d7389c0, 0x53761abd, + 0xcf99d019, 0xde9ec24b, 0x0d76ce39, 0x70beb181, 0x2e55ecee, 0xd5f86079, + 0xf56d9d4b, 0xfb8886fb, 0x13ef5a83, 0x408f43c5, 0x3f3389a4, 0xfad37943, + 0x58ccf45c, 0xf82df846, 0x415c7f3e, 0x2915e818, 0x8b3d5cf4, 0x6a445f27, + 0xf8dbb57a, 0xca8f0070, 0x8ad803ec, 0xb2e87c34, 0x038f9245, 0xbedd8a6c, + 0xc7c9dee0, 0x0eac7d56, 0x2ad3fa14, 0xe0de0840, 0xf775677c, 0xf1bd0ad5, + 0x92be221e, 0x87fa1fb9, 0xce9d04a4, 0xd2c36fa9, 0x3f6f7024, 0xb028af62, + 0x907855ee, 0xd83e49d6, 0x4efac5dc, 0xe7151aab, 0x77cd8c6b, 0x0a753b7d, + 0x0af908b4, 0x8c983623, 0xe50f3027, 0x94222771, 0x1d08e2d6, 0xf7e928e6, + 0xf2ee5ca6, 0x1b61b93c, 0x11eb962b, 0x9648b21c, 0xce2bcba1, 0x34f77154, + 0x7bbebe30, 0xe526a319, 0x8ce329ac, 0xde4a74d2, 0xb5dc53d5, 0x0009e8b3, + +# define TENS_P12_IDX (TENS_P11_IDX + TENS_P11_SIZE) +# define TENS_P12_SIZE 428 + [TENS_P12_IDX] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2a67c001, + 0xd4724e8d, 0x8efe7ae7, 0xf89a1e90, 0xef084117, 0x54e05154, 0x13b1bb51, + 0x506be829, 0xfb29b172, 0xe599574e, 0xf0da6146, 0x806c0ed3, 0xb86ae5be, + 0x45155e93, 0xc0591cc2, 0x7e1e7c34, 0x7c4823da, 0x1d1f4cce, 0x9b8ba1e8, + 0xd6bfdf75, 0xe341be10, 0xc2dfae78, 0x016b67b2, 0x0f237f1a, 0x3dbeabcd, + 0xaf6a2574, 0xcab3e6d7, 0x142e0e80, 0x61959127, 0x2c234811, 0x87009701, + 0xcb4bf982, 0xf8169c84, 0x88052f8c, 0x68dde6d4, 0xbc131761, 0xff0b0905, + 0x54ab9c41, 0x7613b224, 0x1a1c304e, 0x3bfe167b, 0x441c2d47, 0x4f6cea9c, + 0x78f06181, 0xeb659fb8, 0x30c7ae41, 0x947e0d0e, 0xa1ebcad7, 0xd97d9556, + 0x2130504d, 0x1a8309cb, 0xf2acd507, 0x3f8ec72a, 0xfd82373a, 0x95a842bc, + 0x280f4d32, 0xf3618ac0, 0x811a4f04, 0x6dc3a5b4, 0xd3967a1b, 0x15b8c898, + 0xdcfe388f, 0x454eb2a0, 0x8738b909, 0x10c4e996, 0x2bd9cc11, 0x3297cd0c, + 0x655fec30, 0xae0725b1, 0xf4090ee8, 0x037d19ee, 0x398c6fed, 0x3b9af26b, + 0xc994a450, 0xb5341743, 0x75a697b2, 0xac50b9c1, 0x3ccb5b92, 0xffe06205, + 0xa8329761, 0xdfea5242, 0xeb83cadb, 0xe79dadf7, 0x3c20ee69, 0x1e0a6817, + 0x7021b97a, 0x743074fa, 0x176ca776, 0x77fb8af6, 0xeca19beb, 0x92baf1de, + 0xaf63b712, 0xde35c88b, 0xa4eb8f8c, 0xe137d5e9, 0x40b464a0, 0x87d1cde8, + 0x42923bbd, 0xcd8f62ff, 0x2e2690f3, 0x095edc16, 0x59c89f1b, 0x1fa8fd5d, + 0x5138753d, 0x390a2b29, 0x80152f18, 0x2dd8d925, 0xf984d83e, 0x7a872e74, + 0xc19e1faf, 0xed4d542d, 0xecf9b5d0, 0x9462ea75, 0xc53c0adf, 0x0caea134, + 0x37a2d439, 0xc8fa2e8a, 0x2181327e, 0x6e7bb827, 0x2d240820, 0x50be10e0, + 0x5893d4b8, 0xab312bb9, 0x1f2b2322, 0x440b3f25, 0xbf627ede, 0x72dac789, + 0xb608b895, 0x78787e2a, 0x86deb3f0, 0x6fee7aab, 0xbb9373f4, 0x27ecf57b, + 0xf7d8b57e, 0xfca26a9f, 0x3d04e8d2, 0xc9df13cb, 0x3172826a, 0xcd9e8d7c, + 0xa8fcd8e0, 0xb2c39497, 0x307641d9, 0x1cc939c1, 0x2608c4cf, 0xb6d1c7bf, + 0x3d326a7e, 0xeeaf19e6, 0x8e13e25f, 0xee63302b, 0x2dfe6d97, 0x25971d58, + 0xe41d3cc4, 0x0a80627c, 0xab8db59a, 0x9eea37c8, 0xe90afb77, 0x90ca19cf, + 0x9ee3352c, 0x3613c850, 0xfe78d682, 0x788f6e50, 0x5b060904, 0xb71bd1a4, + 0x3fecb534, 0xb32c450c, 0x20c33857, 0xa6e9cfda, 0x0239f4ce, 0x48497187, + 0xa19adb95, 0xb492ed8a, 0x95aca6a8, 0x4dcd6cd9, 0xcf1b2350, 0xfbe8b12a, + 0x1a67778c, 0x38eb3acc, 0xc32da383, 0xfb126ab1, 0xa03f40a8, 0xed5bf546, + 0xe9ce4724, 0x4c4a74fd, 0x73a130d8, 0xd9960e2d, 0xa2ebd6c1, 0x94ab6feb, + 0x6f233b7c, 0x49126080, 0x8e7b9a73, 0x4b8c9091, 0xd298f999, 0x35e836b5, + 0xa96ddeff, 0x96119b31, 0x6b0dd9bc, 0xc6cc3f8d, 0x282566fb, 0x72b882e7, + 0xd6769f3b, 0xa674343d, 0x00fc509b, 0xdcbf7789, 0xd6266a3f, 0xae9641fd, + 0x4e89541b, 0x11953407, 0x53400d03, 0x8e0dd75a, 0xe5b53345, 0x108f19ad, + 0x108b89bc, 0x41a4c954, 0xe03b2b63, 0x437b3d7f, 0x97aced8e, 0xcbd66670, + 0x2c5508c2, 0x650ebc69, 0x5c4f2ef0, 0x904ff6bf, 0x9985a2df, 0x9faddd9e, + 0x5ed8d239, 0x25585832, 0xe3e51cb9, 0x0ff4f1d4, 0x56c02d9a, 0x8c4ef804, + 0xc1a08a13, 0x13fd01c8, 0xe6d27671, 0xa7c234f4, 0x9d0176cc, 0xd0d73df2, + 0x4d8bfa89, 0x544f10cd, 0x2b17e0b2, 0xb70a5c7d, 0xfd86fe49, 0xdf373f41, + 0x214495bb, 0x84e857fd, 0x00d313d5, 0x0496fcbe, 0xa4ba4744, 0xe8cac982, + 0xaec29e6e, 0x87ec7038, 0x7000a519, 0xaeee333b, 0xff66e42c, 0x8afd6b25, + 0x03b4f63b, 0xbd7991dc, 0x5ab8d9c7, 0x2ed4684e, 0x48741a6c, 0xaf06940d, + 0x2fdc6349, 0xb03d7ecd, 0xe974996f, 0xac7867f9, 0x52ec8721, 0xbcdd9d4a, + 0x8edd2d00, 0x3557de06, 0x41c759f8, 0x3956d4b9, 0xa75409f2, 0x123cd8a1, + 0xb6100fab, 0x3e7b21e2, 0x2e8d623b, 0x92959da2, 0xbca35f77, 0x200c03a5, + 0x35fcb457, 0x1bb6c6e4, 0xf74eb928, 0x3d5d0b54, 0x87cc1d21, 0x4964046f, + 0x18ae4240, 0xd868b275, 0x8bd2b496, 0x1c5563f4, 0xc234d8f5, 0xf868e970, + 0xf9151fff, 0xae7be4a2, 0x271133ee, 0xbb0fd922, 0x25254932, 0xa60a9fc0, + 0x104bcd64, 0x30290145, 0x00000062 +#endif /* !__NO_LONG_DOUBLE_MATH */ +}; + +#elif BITS_PER_MP_LIMB == 64 + +/* Table with constants of 10^(2^i), i=0..12 for 64-bit limbs. */ + +const mp_limb_t __tens[] = +{ +#define TENS_P0_IDX 0 +#define TENS_P0_SIZE 2 + [TENS_P0_IDX] = 0x0000000000000000ull, 0x000000000000000aull, + +#define TENS_P1_IDX (TENS_P0_IDX + TENS_P0_SIZE) +#define TENS_P1_SIZE 2 + [TENS_P1_IDX] = 0x0000000000000000ull, 0x0000000000000064ull, + +#define TENS_P2_IDX (TENS_P1_IDX + TENS_P1_SIZE) +#define TENS_P2_SIZE 2 + [TENS_P2_IDX] = 0x0000000000000000ull, 0x0000000000002710ull, + +#define TENS_P3_IDX (TENS_P2_IDX + TENS_P2_SIZE) +#define TENS_P3_SIZE 2 + [TENS_P3_IDX] = 0x0000000000000000ull, 0x0000000005f5e100ull, + +#define TENS_P4_IDX (TENS_P3_IDX + TENS_P3_SIZE) +#define TENS_P4_SIZE 2 + [TENS_P4_IDX] = 0x0000000000000000ull, 0x002386f26fc10000ull, + +#define TENS_P5_IDX (TENS_P4_IDX + TENS_P4_SIZE) +#define TENS_P5_SIZE 3 + [TENS_P5_IDX] = 0x0000000000000000ull, 0x85acef8100000000ull, + 0x000004ee2d6d415bull, + +#define TENS_P6_IDX (TENS_P5_IDX + TENS_P5_SIZE) +#define TENS_P6_SIZE 5 + [TENS_P6_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, + 0x6e38ed64bf6a1f01ull, 0xe93ff9f4daa797edull, 0x0000000000184f03ull, + +#define TENS_P7_IDX (TENS_P6_IDX + TENS_P6_SIZE) +#define TENS_P7_SIZE 8 + [TENS_P7_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x03df99092e953e01ull, 0x2374e42f0f1538fdull, + 0xc404dc08d3cff5ecull, 0xa6337f19bccdb0daull, 0x0000024ee91f2603ull, + +#define TENS_P8_IDX (TENS_P7_IDX + TENS_P7_SIZE) +#define TENS_P8_SIZE 15 + [TENS_P8_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0xbed3875b982e7c01ull, 0x12152f87d8d99f72ull, 0xcf4a6e706bde50c6ull, + 0x26b2716ed595d80full, 0x1d153624adc666b0ull, 0x63ff540e3c42d35aull, + 0x65f9ef17cc5573c0ull, 0x80dcc7f755bc28f2ull, 0x5fdcefcef46eeddcull, + 0x00000000000553f7ull, +#ifndef __NO_LONG_DOUBLE_MATH +# define TENS_P9_IDX (TENS_P8_IDX + TENS_P8_SIZE) +# define TENS_P9_SIZE 28 + [TENS_P9_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x77f27267fc6cf801ull, 0x5d96976f8f9546dcull, + 0xc31e1ad9b83a8a97ull, 0x94e6574746c40513ull, 0x4475b579c88976c1ull, + 0xaa1da1bf28f8733bull, 0x1e25cfea703ed321ull, 0xbc51fb2eb21a2f22ull, + 0xbfa3edac96e14f5dull, 0xe7fc7153329c57aeull, 0x85a91924c3fc0695ull, + 0xb2908ee0f95f635eull, 0x1366732a93abade4ull, 0x69be5b0e9449775cull, + 0xb099bc817343afacull, 0xa269974845a71d46ull, 0x8a0b1f138cb07303ull, + 0xc1d238d98cab8a97ull, 0x0000001c633415d4ull, + +# define TENS_P10_IDX (TENS_P9_IDX + TENS_P9_SIZE) +# define TENS_P10_SIZE 55 + [TENS_P10_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0xf55b2b722919f001ull, 0x1ec29f866e7c215bull, 0x15c51a88991c4e87ull, + 0x4c7d1e1a140ac535ull, 0x0ed1440ecc2cd819ull, 0x7de16cfb896634eeull, + 0x9fce837d1e43f61full, 0x233e55c7231d2b9cull, 0xf451218b65dc60d7ull, + 0xc96359861c5cd134ull, 0xa7e89431922bbb9full, 0x62be695a9f9f2a07ull, + 0x045b7a748e1042c4ull, 0x8ad822a51abe1de3ull, 0xd814b505ba34c411ull, + 0x8fc51a16bf3fdeb3ull, 0xf56deeecb1b896bcull, 0xb6f4654b31fb6bfdull, + 0x6b7595fb101a3616ull, 0x80d98089dc1a47feull, 0x9a20288280bda5a5ull, + 0xfc8f1f9031eb0f66ull, 0xe26a7b7e976a3310ull, 0x3ce3a0b8df68368aull, + 0x75a351a28e4262ceull, 0x445975836cb0b6c9ull, 0xc356e38a31b5653full, + 0x0190fba035faaba6ull, 0x88bc491b9fc4ed52ull, 0x005b80411640114aull, + 0x1e8d4649f4f3235eull, 0x73c5534936a8de06ull, 0xc1a6970ca7e6bd2aull, + 0xd2db49ef47187094ull, 0xae6209d4926c3f5bull, 0x34f4a3c62d433949ull, + 0xd9d61a05d4305d94ull, 0x0000000000000325ull, + +# define TENS_P11_IDX (TENS_P10_IDX + TENS_P10_SIZE) +# define TENS_P11_SIZE 108 + [TENS_P11_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0xe30968651333e001ull, 0x49e28dcfb27d4d3full, + 0xee87e354ec2e4721ull, 0x368b8abbb6067584ull, 0x2ed56d55a5e5a191ull, + 0xea50d142fd827773ull, 0x98342c9e51b78db2ull, 0x866ed6f1c850dabcull, + 0x9279498719342c12ull, 0x66912e4ad2f869c2ull, 0x57a7842d71c7fd8full, + 0xfb7fedcc235552ebull, 0x38209ce1f3861ce0ull, 0x34c101349713b449ull, + 0xa7a8289c8c6c54deull, 0xe3cb64f32dbb6643ull, 0xe3892ee98074ff01ull, + 0xa8f16f9210c17f94ull, 0x967abbb3a8281ed6ull, 0x9952fbed5a151440ull, + 0xafe609c313b41e44ull, 0xf111821fa2bca416ull, 0x91bac974fb1264b4ull, + 0x8e48ff35d6c7d6abull, 0xc4a656654419bd43ull, 0x33554c36685e5510ull, + 0x0dbd21feab498697ull, 0x982da4663cfe491dull, 0x9e110c7bcbea4ca7ull, + 0x5fc5a04779c56b8aull, 0x1aa9f44484d80e2eull, 0x6a57b1ab730f203cull, + 0x87a7dc62d752f7a6ull, 0x40660460944545ffull, 0xc9ac375d77c1a42full, + 0x744695f0e866d7efull, 0xa1fc6b9681428c85ull, 0x7bf03c19d7917c7bull, + 0x5715f7915b33eb41ull, 0xdb0708fd8f6cae5full, 0x785ce6b7b125ac8eull, + 0x6f46eadb56c6815bull, 0x195355d84eeebeeeull, 0x9d7389c0a244de3cull, + 0xcf99d01953761abdull, 0x0d76ce39de9ec24bull, 0x2e55ecee70beb181ull, + 0xf56d9d4bd5f86079ull, 0x13ef5a83fb8886fbull, 0x3f3389a4408f43c5ull, + 0x58ccf45cfad37943ull, 0x415c7f3ef82df846ull, 0x8b3d5cf42915e818ull, + 0xf8dbb57a6a445f27ull, 0x8ad803ecca8f0070ull, 0x038f9245b2e87c34ull, + 0xc7c9dee0bedd8a6cull, 0x2ad3fa140eac7d56ull, 0xf775677ce0de0840ull, + 0x92be221ef1bd0ad5ull, 0xce9d04a487fa1fb9ull, 0x3f6f7024d2c36fa9ull, + 0x907855eeb028af62ull, 0x4efac5dcd83e49d6ull, 0x77cd8c6be7151aabull, + 0x0af908b40a753b7dull, 0xe50f30278c983623ull, 0x1d08e2d694222771ull, + 0xf2ee5ca6f7e928e6ull, 0x11eb962b1b61b93cull, 0xce2bcba19648b21cull, + 0x7bbebe3034f77154ull, 0x8ce329ace526a319ull, 0xb5dc53d5de4a74d2ull, + 0x000000000009e8b3ull, + +# define TENS_P12_IDX (TENS_P11_IDX + TENS_P11_SIZE) +# define TENS_P12_SIZE 214 + [TENS_P12_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, + 0xd4724e8d2a67c001ull, 0xf89a1e908efe7ae7ull, 0x54e05154ef084117ull, + 0x506be82913b1bb51ull, 0xe599574efb29b172ull, 0x806c0ed3f0da6146ull, + 0x45155e93b86ae5beull, 0x7e1e7c34c0591cc2ull, 0x1d1f4cce7c4823daull, + 0xd6bfdf759b8ba1e8ull, 0xc2dfae78e341be10ull, 0x0f237f1a016b67b2ull, + 0xaf6a25743dbeabcdull, 0x142e0e80cab3e6d7ull, 0x2c23481161959127ull, + 0xcb4bf98287009701ull, 0x88052f8cf8169c84ull, 0xbc13176168dde6d4ull, + 0x54ab9c41ff0b0905ull, 0x1a1c304e7613b224ull, 0x441c2d473bfe167bull, + 0x78f061814f6cea9cull, 0x30c7ae41eb659fb8ull, 0xa1ebcad7947e0d0eull, + 0x2130504dd97d9556ull, 0xf2acd5071a8309cbull, 0xfd82373a3f8ec72aull, + 0x280f4d3295a842bcull, 0x811a4f04f3618ac0ull, 0xd3967a1b6dc3a5b4ull, + 0xdcfe388f15b8c898ull, 0x8738b909454eb2a0ull, 0x2bd9cc1110c4e996ull, + 0x655fec303297cd0cull, 0xf4090ee8ae0725b1ull, 0x398c6fed037d19eeull, + 0xc994a4503b9af26bull, 0x75a697b2b5341743ull, 0x3ccb5b92ac50b9c1ull, + 0xa8329761ffe06205ull, 0xeb83cadbdfea5242ull, 0x3c20ee69e79dadf7ull, + 0x7021b97a1e0a6817ull, 0x176ca776743074faull, 0xeca19beb77fb8af6ull, + 0xaf63b71292baf1deull, 0xa4eb8f8cde35c88bull, 0x40b464a0e137d5e9ull, + 0x42923bbd87d1cde8ull, 0x2e2690f3cd8f62ffull, 0x59c89f1b095edc16ull, + 0x5138753d1fa8fd5dull, 0x80152f18390a2b29ull, 0xf984d83e2dd8d925ull, + 0xc19e1faf7a872e74ull, 0xecf9b5d0ed4d542dull, 0xc53c0adf9462ea75ull, + 0x37a2d4390caea134ull, 0x2181327ec8fa2e8aull, 0x2d2408206e7bb827ull, + 0x5893d4b850be10e0ull, 0x1f2b2322ab312bb9ull, 0xbf627ede440b3f25ull, + 0xb608b89572dac789ull, 0x86deb3f078787e2aull, 0xbb9373f46fee7aabull, + 0xf7d8b57e27ecf57bull, 0x3d04e8d2fca26a9full, 0x3172826ac9df13cbull, + 0xa8fcd8e0cd9e8d7cull, 0x307641d9b2c39497ull, 0x2608c4cf1cc939c1ull, + 0x3d326a7eb6d1c7bfull, 0x8e13e25feeaf19e6ull, 0x2dfe6d97ee63302bull, + 0xe41d3cc425971d58ull, 0xab8db59a0a80627cull, 0xe90afb779eea37c8ull, + 0x9ee3352c90ca19cfull, 0xfe78d6823613c850ull, 0x5b060904788f6e50ull, + 0x3fecb534b71bd1a4ull, 0x20c33857b32c450cull, 0x0239f4cea6e9cfdaull, + 0xa19adb9548497187ull, 0x95aca6a8b492ed8aull, 0xcf1b23504dcd6cd9ull, + 0x1a67778cfbe8b12aull, 0xc32da38338eb3accull, 0xa03f40a8fb126ab1ull, + 0xe9ce4724ed5bf546ull, 0x73a130d84c4a74fdull, 0xa2ebd6c1d9960e2dull, + 0x6f233b7c94ab6febull, 0x8e7b9a7349126080ull, 0xd298f9994b8c9091ull, + 0xa96ddeff35e836b5ull, 0x6b0dd9bc96119b31ull, 0x282566fbc6cc3f8dull, + 0xd6769f3b72b882e7ull, 0x00fc509ba674343dull, 0xd6266a3fdcbf7789ull, + 0x4e89541bae9641fdull, 0x53400d0311953407ull, 0xe5b533458e0dd75aull, + 0x108b89bc108f19adull, 0xe03b2b6341a4c954ull, 0x97aced8e437b3d7full, + 0x2c5508c2cbd66670ull, 0x5c4f2ef0650ebc69ull, 0x9985a2df904ff6bfull, + 0x5ed8d2399faddd9eull, 0xe3e51cb925585832ull, 0x56c02d9a0ff4f1d4ull, + 0xc1a08a138c4ef804ull, 0xe6d2767113fd01c8ull, 0x9d0176cca7c234f4ull, + 0x4d8bfa89d0d73df2ull, 0x2b17e0b2544f10cdull, 0xfd86fe49b70a5c7dull, + 0x214495bbdf373f41ull, 0x00d313d584e857fdull, 0xa4ba47440496fcbeull, + 0xaec29e6ee8cac982ull, 0x7000a51987ec7038ull, 0xff66e42caeee333bull, + 0x03b4f63b8afd6b25ull, 0x5ab8d9c7bd7991dcull, 0x48741a6c2ed4684eull, + 0x2fdc6349af06940dull, 0xe974996fb03d7ecdull, 0x52ec8721ac7867f9ull, + 0x8edd2d00bcdd9d4aull, 0x41c759f83557de06ull, 0xa75409f23956d4b9ull, + 0xb6100fab123cd8a1ull, 0x2e8d623b3e7b21e2ull, 0xbca35f7792959da2ull, + 0x35fcb457200c03a5ull, 0xf74eb9281bb6c6e4ull, 0x87cc1d213d5d0b54ull, + 0x18ae42404964046full, 0x8bd2b496d868b275ull, 0xc234d8f51c5563f4ull, + 0xf9151ffff868e970ull, 0x271133eeae7be4a2ull, 0x25254932bb0fd922ull, + 0x104bcd64a60a9fc0ull, 0x0000006230290145ull +#endif +}; + +#else +# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for" +#endif + +/* Each of array variable above defines one mpn integer which is a power of 10. + This table points to those variables, indexed by the exponent. */ + +const struct mp_power _fpioconst_pow10[LDBL_MAX_10_EXP_LOG + 1] = +{ + { TENS_P0_IDX, TENS_P0_SIZE, 4, }, + { TENS_P1_IDX, TENS_P1_SIZE, 7, 4 }, + { TENS_P2_IDX, TENS_P2_SIZE, 14, 10 }, + { TENS_P3_IDX, TENS_P3_SIZE, 27, 24 }, + { TENS_P4_IDX, TENS_P4_SIZE, 54, 50 }, + { TENS_P5_IDX, TENS_P5_SIZE, 107, 103 }, + { TENS_P6_IDX, TENS_P6_SIZE, 213, 210 }, + { TENS_P7_IDX, TENS_P7_SIZE, 426, 422 }, + { TENS_P8_IDX, TENS_P8_SIZE, 851, 848 }, +#ifndef __NO_LONG_DOUBLE_MATH + { TENS_P9_IDX, TENS_P9_SIZE, 1701, 1698 }, + { TENS_P10_IDX, TENS_P10_SIZE, 3402, 3399 }, + { TENS_P11_IDX, TENS_P11_SIZE, 6804, 6800 }, + { TENS_P12_IDX, TENS_P12_SIZE, 13607, 13604 } +#endif +}; + +#if LAST_POW10 > _LAST_POW10 +# error "Need to expand 10^(2^i) table for i up to" LAST_POW10 +#endif diff --git a/src/kernel/libroot/posix/glibc/stdlib/fpioconst.h b/src/kernel/libroot/posix/glibc/stdlib/fpioconst.h new file mode 100644 index 0000000000..c7f87ba5a8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/fpioconst.h @@ -0,0 +1,69 @@ +/* Header file for constants used in floating point <-> decimal conversions. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPIOCONST_H +#define _FPIOCONST_H + +#include +#include +#include + + +/* These values are used by __printf_fp, where they are noncritical (if the + value is not large enough, it will just be slower); and by + strtof/strtod/strtold, where it is critical (it's used for overflow + detection). + + XXX These should be defined in . For the time being, we have the + IEEE754 values here. */ + +#ifndef __NO_LONG_DOUBLE_MATH +# define LDBL_MAX_10_EXP_LOG 12 /* = floor(log_2(LDBL_MAX_10_EXP)) */ +#else +# define LDBL_MAX_10_EXP_LOG 8 /* = floor(log_2(LDBL_MAX_10_EXP)) */ +#endif +#define DBL_MAX_10_EXP_LOG 8 /* = floor(log_2(DBL_MAX_10_EXP)) */ +#define FLT_MAX_10_EXP_LOG 5 /* = floor(log_2(FLT_MAX_10_EXP)) */ + + +/* The array with the number representation. */ +extern const mp_limb_t __tens[] attribute_hidden; + +/* Table of powers of ten. This is used by __printf_fp and by + strtof/strtod/strtold. */ +struct mp_power + { + size_t arrayoff; /* Offset in `__tens'. */ + mp_size_t arraysize; /* Size of the array. */ + int p_expo; /* Exponent of the number 10^(2^i). */ + int m_expo; /* Exponent of the number 10^-(2^i-1). */ + }; +extern const struct mp_power _fpioconst_pow10[LDBL_MAX_10_EXP_LOG + 1] + attribute_hidden; + +/* The constants in the array `_fpioconst_pow10' have an offset. */ +#if BITS_PER_MP_LIMB == 32 +# define _FPIO_CONST_OFFSET 2 +#else +# define _FPIO_CONST_OFFSET 1 +#endif + + +#endif /* fpioconst.h */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/gen-mpn-copy b/src/kernel/libroot/posix/glibc/stdlib/gen-mpn-copy new file mode 100644 index 0000000000..01656ae54d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/gen-mpn-copy @@ -0,0 +1,35 @@ +#!/bin/sh + +translations=' +sparc64 sparc/sparc64 +sparc32/v8 sparc/sparc8 +sparc32 sparc +x86/pentium i386/i586 +x86 i386 +m68k/mc68000 m68k/m68000 +m68k/mc68020 m68k/m68020 +m88k/mc88100 m88k/m88100 +m88k/mc88110 m88k/m88110 +mips3 mips/mips3 +mips2 mips +hppa/hppa1_1 hppa/hppa1.1 +alpha/ev5 alpha/alphaev5 +power rs6000 +am29000 a29k +' + +set $translations +while [ $# -ge 2 ]; do + gmp=$1 glibc=$2 + shift; shift + echo 'mpn-found-1 := $(filter $(gmp-srcdir)/mpn/'$gmp'/%,$(mpn-found)) +mpn-copy-1 := $(patsubst $(gmp-srcdir)/mpn/'$gmp'/%,$(sysdep_dir)/'$glibc\ +'/%,$(mpn-found-1)) +mpn-found := $(filter-out $(mpn-found-1),$(mpn-found)) +mpn-copy-sysdep := $(mpn-copy-sysdep) $(mpn-copy-1) +$(mpn-copy-1): $(sysdep_dir)/'$glibc'/%: \ + $(ignore gmp2glibc.sed) $(gmp-srcdir)/mpn/'$gmp'/% + $(gmp2glibc)' +done + +exit 0 diff --git a/src/kernel/libroot/posix/glibc/stdlib/getsubopt.c b/src/kernel/libroot/posix/glibc/stdlib/getsubopt.c new file mode 100644 index 0000000000..aac756d34c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/getsubopt.c @@ -0,0 +1,75 @@ +/* Parse comma separate list into words. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Parse comma separated suboption from *OPTIONP and match against + strings in TOKENS. If found return index and set *VALUEP to + optional value introduced by an equal sign. If the suboption is + not part of TOKENS return in *VALUEP beginning of unknown + suboption. On exit *OPTIONP is set to the beginning of the next + token or at the terminating NUL character. */ +int +getsubopt (optionp, tokens, valuep) + char **optionp; + char *const *tokens; + char **valuep; +{ + char *endp, *vstart; + int cnt; + + if (**optionp == '\0') + return -1; + + /* Find end of next token. */ + endp = __strchrnul (*optionp, ','); + + /* Find start of value. */ + vstart = memchr (*optionp, '=', endp - *optionp); + if (vstart == NULL) + vstart = endp; + + /* Try to match the characters between *OPTIONP and VSTART against + one of the TOKENS. */ + for (cnt = 0; tokens[cnt] != NULL; ++cnt) + if (memcmp (*optionp, tokens[cnt], vstart - *optionp) == 0 + && tokens[cnt][vstart - *optionp] == '\0') + { + /* We found the current option in TOKENS. */ + *valuep = vstart != endp ? vstart + 1 : NULL; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return cnt; + } + + /* The current suboption does not match any option. */ + *valuep = *optionp; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return -1; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/gmp-impl.h b/src/kernel/libroot/posix/glibc/stdlib/gmp-impl.h new file mode 100644 index 0000000000..85e419d36f --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/gmp-impl.h @@ -0,0 +1,372 @@ +/* Include file for internal GNU MP types and definitions. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* When using gcc, make sure to use its builtin alloca. */ +#if ! defined (alloca) && defined (__GNUC__) +#define alloca __builtin_alloca +#define HAVE_ALLOCA +#endif + +/* When using cc, do whatever necessary to allow use of alloca. For many + machines, this means including alloca.h. IBM's compilers need a #pragma + in "each module that needs to use alloca". */ +#if ! defined (alloca) +/* We need lots of variants for MIPS, to cover all versions and perversions + of OSes for MIPS. */ +#if defined (__mips) || defined (MIPSEL) || defined (MIPSEB) \ + || defined (_MIPSEL) || defined (_MIPSEB) || defined (__sgi) \ + || defined (__alpha) || defined (__sparc) || defined (sparc) \ + || defined (__ksr__) +#include +#define HAVE_ALLOCA +#endif +#if defined (_IBMR2) +#pragma alloca +#define HAVE_ALLOCA +#endif +#if defined (__DECC) +#define alloca(x) __ALLOCA(x) +#define HAVE_ALLOCA +#endif +#endif + +#if ! defined (HAVE_ALLOCA) || USE_STACK_ALLOC +#include "stack-alloc.h" +#else +#define TMP_DECL(m) +#define TMP_ALLOC(x) alloca(x) +#define TMP_MARK(m) +#define TMP_FREE(m) +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#if ! defined (__GNUC__) +#define inline /* Empty */ +#endif + +#define ABS(x) (x >= 0 ? x : -x) +#ifndef MIN +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#endif +#ifndef MAX +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#endif + +/* Field access macros. */ +#define SIZ(x) ((x)->_mp_size) +#define ABSIZ(x) ABS (SIZ (x)) +#define PTR(x) ((x)->_mp_d) +#define EXP(x) ((x)->_mp_exp) +#define PREC(x) ((x)->_mp_prec) +#define ALLOC(x) ((x)->_mp_alloc) + +#include "gmp-mparam.h" +/* #include "longlong.h" */ + +#if defined (__STDC__) || defined (__cplusplus) +void *malloc (size_t); +void *realloc (void *, size_t); +void free (void *); + +extern void * (*_mp_allocate_func) (size_t); +extern void * (*_mp_reallocate_func) (void *, size_t, size_t); +extern void (*_mp_free_func) (void *, size_t); + +void *_mp_default_allocate (size_t); +void *_mp_default_reallocate (void *, size_t, size_t); +void _mp_default_free (void *, size_t); + +#else + +#define const /* Empty */ +#define signed /* Empty */ + +void *malloc (); +void *realloc (); +void free (); + +extern void * (*_mp_allocate_func) (); +extern void * (*_mp_reallocate_func) (); +extern void (*_mp_free_func) (); + +void *_mp_default_allocate (); +void *_mp_default_reallocate (); +void _mp_default_free (); +#endif + +/* Copy NLIMBS *limbs* from SRC to DST. */ +#define MPN_COPY_INCR(DST, SRC, NLIMBS) \ + do { \ + mp_size_t __i; \ + for (__i = 0; __i < (NLIMBS); __i++) \ + (DST)[__i] = (SRC)[__i]; \ + } while (0) +#define MPN_COPY_DECR(DST, SRC, NLIMBS) \ + do { \ + mp_size_t __i; \ + for (__i = (NLIMBS) - 1; __i >= 0; __i--) \ + (DST)[__i] = (SRC)[__i]; \ + } while (0) +#define MPN_COPY MPN_COPY_INCR + +/* Zero NLIMBS *limbs* AT DST. */ +#define MPN_ZERO(DST, NLIMBS) \ + do { \ + mp_size_t __i; \ + for (__i = 0; __i < (NLIMBS); __i++) \ + (DST)[__i] = 0; \ + } while (0) + +#define MPN_NORMALIZE(DST, NLIMBS) \ + do { \ + while (NLIMBS > 0) \ + { \ + if ((DST)[(NLIMBS) - 1] != 0) \ + break; \ + NLIMBS--; \ + } \ + } while (0) +#define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS) \ + do { \ + while (1) \ + { \ + if ((DST)[(NLIMBS) - 1] != 0) \ + break; \ + NLIMBS--; \ + } \ + } while (0) + +/* Initialize the MP_INT X with space for NLIMBS limbs. + X should be a temporary variable, and it will be automatically + cleared out when the running function returns. + We use __x here to make it possible to accept both mpz_ptr and mpz_t + arguments. */ +#define MPZ_TMP_INIT(X, NLIMBS) \ + do { \ + mpz_ptr __x = (X); \ + __x->_mp_alloc = (NLIMBS); \ + __x->_mp_d = (mp_ptr) TMP_ALLOC ((NLIMBS) * BYTES_PER_MP_LIMB); \ + } while (0) + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + impn_mul_n_basecase (prodp, up, vp, size); \ + else \ + impn_mul_n (prodp, up, vp, size, tspace); \ + } while (0); +#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + impn_sqr_n_basecase (prodp, up, size); \ + else \ + impn_sqr_n (prodp, up, size, tspace); \ + } while (0); + +/* Structure for conversion between internal binary format and + strings in base 2..36. */ +struct bases +{ + /* Number of digits in the conversion base that always fits in an mp_limb_t. + For example, for base 10 on a machine where a mp_limb_t has 32 bits this + is 9, since 10**9 is the largest number that fits into a mp_limb_t. */ + int chars_per_limb; + + /* log(2)/log(conversion_base) */ + float chars_per_bit_exactly; + + /* base**chars_per_limb, i.e. the biggest number that fits a word, built by + factors of base. Exception: For 2, 4, 8, etc, big_base is log2(base), + i.e. the number of bits used to represent each digit in the base. */ + mp_limb_t big_base; + + /* A BITS_PER_MP_LIMB bit approximation to 1/big_base, represented as a + fixed-point number. Instead of dividing by big_base an application can + choose to multiply by big_base_inverted. */ + mp_limb_t big_base_inverted; +}; + +extern const struct bases __mp_bases[]; +extern mp_size_t __gmp_default_fp_limb_precision; + +/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest + limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). + If this would yield overflow, DI should be the largest possible number + (i.e., only ones). For correct operation, the most significant bit of D + has to be set. Put the quotient in Q and the remainder in R. */ +#define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ + do { \ + mp_limb_t _q, _ql, _r; \ + mp_limb_t _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**BITS_PER_MP_LIMB too small */\ + umul_ppmm (_xh, _xl, _q, (d)); \ + sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ + if (_xh != 0) \ + { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q += 1; \ + if (_xh != 0) \ + { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q += 1; \ + } \ + } \ + if (_r >= (d)) \ + { \ + _r -= (d); \ + _q += 1; \ + } \ + (r) = _r; \ + (q) = _q; \ + } while (0) +/* Like udiv_qrnnd_preinv, but for for any value D. DNORM is D shifted left + so that its most significant bit is set. LGUP is ceil(log2(D)). */ +#define udiv_qrnnd_preinv2gen(q, r, nh, nl, d, di, dnorm, lgup) \ + do { \ + mp_limb_t n2, n10, n1, nadj, q1; \ + mp_limb_t _xh, _xl; \ + n2 = ((nh) << (BITS_PER_MP_LIMB - (lgup))) + ((nl) >> 1 >> (l - 1));\ + n10 = (nl) << (BITS_PER_MP_LIMB - (lgup)); \ + n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1)); \ + nadj = n10 + (n1 & (dnorm)); \ + umul_ppmm (_xh, _xl, di, n2 - n1); \ + add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj); \ + q1 = ~(n2 + _xh); \ + umul_ppmm (_xh, _xl, q1, d); \ + add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl); \ + _xh -= (d); \ + (r) = _xl + ((d) & _xh); \ + (q) = _xh - q1; \ + } while (0) +/* Exactly like udiv_qrnnd_preinv, but branch-free. It is not clear which + version to use. */ +#define udiv_qrnnd_preinv2norm(q, r, nh, nl, d, di) \ + do { \ + mp_limb_t n2, n10, n1, nadj, q1; \ + mp_limb_t _xh, _xl; \ + n2 = (nh); \ + n10 = (nl); \ + n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1)); \ + nadj = n10 + (n1 & (d)); \ + umul_ppmm (_xh, _xl, di, n2 - n1); \ + add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj); \ + q1 = ~(n2 + _xh); \ + umul_ppmm (_xh, _xl, q1, d); \ + add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl); \ + _xh -= (d); \ + (r) = _xl + ((d) & _xh); \ + (q) = _xh - q1; \ + } while (0) + +#if defined (__GNUC__) +/* Define stuff for longlong.h. */ +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else +typedef unsigned char UQItype; +typedef long SItype; +typedef unsigned long USItype; +#endif + +typedef mp_limb_t UWtype; +typedef unsigned int UHWtype; +#define W_TYPE_SIZE BITS_PER_MP_LIMB + +/* Internal mpn calls */ +#define impn_mul_n_basecase __MPN(impn_mul_n_basecase) +#define impn_mul_n __MPN(impn_mul_n) +#define impn_sqr_n_basecase __MPN(impn_sqr_n_basecase) +#define impn_sqr_n __MPN(impn_sqr_n) + +#ifndef _PROTO +#if defined (__STDC__) || defined (__cplusplus) +#define _PROTO(x) x +#else +#define _PROTO(x) () +#endif +#endif + +/* Prototypes for internal mpn calls. */ +extern void impn_mul_n_basecase _PROTO ((mp_ptr prodp, mp_srcptr up, + mp_srcptr vp, mp_size_t size)); +extern void impn_mul_n _PROTO ((mp_ptr prodp, mp_srcptr up, mp_srcptr vp, + mp_size_t size, mp_ptr tspace)); +extern void impn_sqr_n_basecase _PROTO ((mp_ptr prodp, mp_srcptr up, + mp_size_t size)); +extern void impn_sqr_n _PROTO ((mp_ptr prodp, mp_srcptr up, mp_size_t size, + mp_ptr tspace)); + + + +#ifndef IEEE_DOUBLE_BIG_ENDIAN +#define IEEE_DOUBLE_BIG_ENDIAN 1 +#endif + +#ifndef IEEE_DOUBLE_MIXED_ENDIAN +#define IEEE_DOUBLE_MIXED_ENDIAN 0 +#endif + +#if IEEE_DOUBLE_MIXED_ENDIAN +union ieee_double_extract +{ + struct + { + unsigned int manh:20; + unsigned int exp:11; + unsigned int sig:1; + unsigned int manl:32; + } s; + double d; +}; +#else +#if IEEE_DOUBLE_BIG_ENDIAN +union ieee_double_extract +{ + struct + { + unsigned int sig:1; + unsigned int exp:11; + unsigned int manh:20; + unsigned int manl:32; + } s; + double d; +}; +#else +union ieee_double_extract +{ + struct + { + unsigned int manl:32; + unsigned int manh:20; + unsigned int exp:11; + unsigned int sig:1; + } s; + double d; +}; +#endif +#endif diff --git a/src/kernel/libroot/posix/glibc/stdlib/gmp.h b/src/kernel/libroot/posix/glibc/stdlib/gmp.h new file mode 100644 index 0000000000..0ecc6d1024 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/gmp.h @@ -0,0 +1,622 @@ +/* gmp.h -- Definitions for GNU multiple precision functions. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#ifndef __GMP_H__ + +#ifndef __GNU_MP__ +#define __GNU_MP__ 2 +#define __need_size_t +#include +#undef __need_size_t + +#if defined (__STDC__) || defined (__cplusplus) +#define __gmp_const const +#else +#define __gmp_const +#endif + +#if defined (__GNUC__) +#define __gmp_inline __inline__ +#else +#define __gmp_inline +#endif + +#ifndef _EXTERN_INLINE +#ifdef __GNUC__ +#define _EXTERN_INLINE extern __inline__ +#else +#define _EXTERN_INLINE static +#endif +#endif + +#ifdef _SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif + +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; +typedef long int mp_size_t; +typedef long int mp_exp_t; + +#ifndef __MP_SMALL__ +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + int _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#else +typedef struct +{ + short int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + short int _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#endif +#endif /* __GNU_MP__ */ + +/* User-visible types. */ +typedef __mpz_struct MP_INT; +typedef __mpz_struct mpz_t[1]; + +/* Structure for rational numbers. Zero is represented as 0/any, i.e. + the denominator is ignored. Negative numbers have the sign in + the numerator. */ +typedef struct +{ + __mpz_struct _mp_num; + __mpz_struct _mp_den; +#if 0 + int _mp_num_alloc; /* Number of limbs allocated + for the numerator. */ + int _mp_num_size; /* The absolute value of this field is the + length of the numerator; the sign is the + sign of the entire rational number. */ + mp_ptr _mp_num; /* Pointer to the numerator limbs. */ + int _mp_den_alloc; /* Number of limbs allocated + for the denominator. */ + int _mp_den_size; /* Length of the denominator. (This field + should always be positive.) */ + mp_ptr _mp_den; /* Pointer to the denominator limbs. */ +#endif +} __mpq_struct; + +typedef __mpq_struct MP_RAT; +typedef __mpq_struct mpq_t[1]; + +typedef struct +{ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to + by the `d' field contains `prec' + 1 + limbs. */ + int _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpf_struct; + +/* typedef __mpf_struct MP_FLOAT; */ +typedef __mpf_struct mpf_t[1]; + +/* Types for function declarations in gmp files. */ +/* ??? Should not pollute user name space with these ??? */ +typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef __mpf_struct *mpf_ptr; +typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; + +#ifndef _PROTO +#if defined (__STDC__) || defined (__cplusplus) +#define _PROTO(x) x +#else +#define _PROTO(x) () +#endif +#endif + +#ifndef __MPN +#if defined (__STDC__) || defined (__cplusplus) +#define __MPN(x) __mpn_##x +#else +#define __MPN(x) __mpn_/**/x +#endif +#endif + +#if defined (FILE) || defined (_STDIO_H_) || defined (__STDIO_H__) || defined (H_STDIO) +#define _GMP_H_HAVE_FILE 1 +#endif + +void mp_set_memory_functions _PROTO ((void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t))); +extern const int mp_bits_per_limb; + +/**************** Integer (i.e. Z) routines. ****************/ + +#if defined (__cplusplus) +extern "C" { +#endif +void *_mpz_realloc _PROTO ((mpz_ptr, mp_size_t)); + +void mpz_abs _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_add _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_add_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_and _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_array_init _PROTO ((mpz_ptr, mp_size_t, mp_size_t)); +void mpz_cdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_cdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_cdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_cdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_cdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_cdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_cdiv_ui _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_clear _PROTO ((mpz_ptr)); +void mpz_clrbit _PROTO ((mpz_ptr, unsigned long int)); +int mpz_cmp _PROTO ((mpz_srcptr, mpz_srcptr)); +int mpz_cmp_si _PROTO ((mpz_srcptr, signed long int)); +int mpz_cmp_ui _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_com _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_divexact _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_fac_ui _PROTO ((mpz_ptr, unsigned long int)); +void mpz_fdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_fdiv_q_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_fdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_fdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_fdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_fdiv_r_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_ui _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_gcd _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_gcd_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_gcdext _PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +/* signed */ long int mpz_get_si _PROTO ((mpz_srcptr)); +char *mpz_get_str _PROTO ((char *, int, mpz_srcptr)); +unsigned long int mpz_get_ui _PROTO ((mpz_srcptr)); +mp_limb_t mpz_getlimbn _PROTO ((mpz_srcptr, mp_size_t)); +unsigned long int mpz_hamdist _PROTO ((mpz_srcptr, mpz_srcptr)); +void mpz_init _PROTO ((mpz_ptr)); +#ifdef _GMP_H_HAVE_FILE +size_t mpz_inp_binary _PROTO ((mpz_ptr, FILE *)); +size_t mpz_inp_raw _PROTO ((mpz_ptr, FILE *)); +size_t mpz_inp_str _PROTO ((mpz_ptr, FILE *, int)); +#endif +void mpz_init_set _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_init_set_d _PROTO ((mpz_ptr, double)); +void mpz_init_set_si _PROTO ((mpz_ptr, signed long int)); +int mpz_init_set_str _PROTO ((mpz_ptr, const char *, int)); +void mpz_init_set_ui _PROTO ((mpz_ptr, unsigned long int)); +int mpz_invert _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_ior _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +int mpz_jacobi _PROTO ((mpz_srcptr, mpz_srcptr)); +int mpz_legendre _PROTO ((mpz_srcptr, mpz_srcptr)); +void mpz_mod _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_mul _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_mul_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_mul_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_neg _PROTO ((mpz_ptr, mpz_srcptr)); +#ifdef _GMP_H_HAVE_FILE +size_t mpz_out_binary _PROTO ((FILE *, mpz_srcptr)); +size_t mpz_out_raw _PROTO ((FILE *, mpz_srcptr)); +size_t mpz_out_str _PROTO ((FILE *, int, mpz_srcptr)); +#endif +int mpz_perfect_square_p _PROTO ((mpz_srcptr)); +unsigned long int mpz_popcount _PROTO ((mpz_srcptr)); +void mpz_pow_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_powm _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); +void mpz_powm_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); +int mpz_probab_prime_p _PROTO ((mpz_srcptr, int)); +void mpz_random _PROTO ((mpz_ptr, mp_size_t)); +void mpz_random2 _PROTO ((mpz_ptr, mp_size_t)); +unsigned long int mpz_scan0 _PROTO ((mpz_srcptr, unsigned long int)); +unsigned long int mpz_scan1 _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_set _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_set_d _PROTO ((mpz_ptr, double)); +void mpz_set_si _PROTO ((mpz_ptr, signed long int)); +int mpz_set_str _PROTO ((mpz_ptr, const char *, int)); +void mpz_set_ui _PROTO ((mpz_ptr, unsigned long int)); +void mpz_setbit _PROTO ((mpz_ptr, unsigned long int)); +size_t mpz_size _PROTO ((mpz_srcptr)); +size_t mpz_sizeinbase _PROTO ((mpz_srcptr, int)); +void mpz_sqrt _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_sqrtrem _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); +void mpz_sub _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_sub_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_tdiv_q_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_tdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_tdiv_r_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_ui_pow_ui _PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +/**************** Rational (i.e. Q) routines. ****************/ + +void mpq_init _PROTO ((mpq_ptr)); +void mpq_clear _PROTO ((mpq_ptr)); +void mpq_set _PROTO ((mpq_ptr, mpq_srcptr)); +void mpq_set_ui _PROTO ((mpq_ptr, unsigned long int, unsigned long int)); +void mpq_set_si _PROTO ((mpq_ptr, signed long int, unsigned long int)); +void mpq_add _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_sub _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_mul _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_div _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_neg _PROTO ((mpq_ptr, mpq_srcptr)); +int mpq_cmp _PROTO ((mpq_srcptr, mpq_srcptr)); +int mpq_cmp_ui _PROTO ((mpq_srcptr, unsigned long int, unsigned long int)); +void mpq_inv _PROTO ((mpq_ptr, mpq_srcptr)); +void mpq_set_num _PROTO ((mpq_ptr, mpz_srcptr)); +void mpq_set_den _PROTO ((mpq_ptr, mpz_srcptr)); +void mpq_get_num _PROTO ((mpz_ptr, mpq_srcptr)); +void mpq_get_den _PROTO ((mpz_ptr, mpq_srcptr)); +double mpq_get_d _PROTO ((mpq_srcptr)); +void mpq_canonicalize _PROTO ((mpq_ptr)); + +/**************** Float (i.e. F) routines. ****************/ + +void mpf_abs _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_add _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_add_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_clear _PROTO ((mpf_ptr)); +int mpf_cmp _PROTO ((mpf_srcptr, mpf_srcptr)); +int mpf_cmp_si _PROTO ((mpf_srcptr, signed long int)); +int mpf_cmp_ui _PROTO ((mpf_srcptr, unsigned long int)); +void mpf_div _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_div_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_div_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_dump _PROTO ((mpf_srcptr)); +int mpf_eq _PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)); +unsigned long int mpf_get_prec _PROTO ((mpf_srcptr)); +char *mpf_get_str _PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); +void mpf_init _PROTO ((mpf_ptr)); +void mpf_init2 _PROTO ((mpf_ptr, unsigned long int)); +#ifdef _GMP_H_HAVE_FILE +size_t mpf_inp_str _PROTO ((mpf_ptr, FILE *, int)); +#endif +void mpf_init_set _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_init_set_d _PROTO ((mpf_ptr, double)); +void mpf_init_set_si _PROTO ((mpf_ptr, signed long int)); +int mpf_init_set_str _PROTO ((mpf_ptr, char *, int)); +void mpf_init_set_ui _PROTO ((mpf_ptr, unsigned long int)); +void mpf_mul _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_mul_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_mul_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_neg _PROTO ((mpf_ptr, mpf_srcptr)); +#ifdef _GMP_H_HAVE_FILE +size_t mpf_out_str _PROTO ((FILE *, int, size_t, mpf_srcptr)); +#endif +void mpf_random2 _PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); +void mpf_reldiff _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_set _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_set_d _PROTO ((mpf_ptr, double)); +void mpf_set_default_prec _PROTO ((unsigned long int)); +void mpf_set_prec _PROTO ((mpf_ptr, unsigned long int)); +void mpf_set_prec_raw _PROTO ((mpf_ptr, unsigned long int)); +void mpf_set_si _PROTO ((mpf_ptr, signed long int)); +int mpf_set_str _PROTO ((mpf_ptr, const char *, int)); +void mpf_set_ui _PROTO ((mpf_ptr, unsigned long int)); +size_t mpf_size _PROTO ((mpf_srcptr)); +void mpf_sqrt _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_sqrt_ui _PROTO ((mpf_ptr, unsigned long int)); +void mpf_sub _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_sub_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_ui_div _PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +void mpf_ui_sub _PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +#if defined (__cplusplus) +} +#endif +/************ Low level positive-integer (i.e. N) routines. ************/ + +/* This is ugly, but we need to make usr calls reach the prefixed function. */ +#define mpn_add __MPN(add) +#define mpn_add_1 __MPN(add_1) +#define mpn_add_n __MPN(add_n) +#define mpn_addmul_1 __MPN(addmul_1) +#define mpn_bdivmod __MPN(bdivmod) +#define mpn_cmp __MPN(cmp) +#define mpn_divmod_1 __MPN(divmod_1) +#define mpn_divrem __MPN(divrem) +#define mpn_divrem_1 __MPN(divrem_1) +#define mpn_dump __MPN(dump) +#define mpn_gcd __MPN(gcd) +#define mpn_gcd_1 __MPN(gcd_1) +#define mpn_gcdext __MPN(gcdext) +#define mpn_get_str __MPN(get_str) +#define mpn_hamdist __MPN(hamdist) +#define mpn_lshift __MPN(lshift) +#define mpn_mod_1 __MPN(mod_1) +#define mpn_mul __MPN(mul) +#define mpn_mul_1 __MPN(mul_1) +#define mpn_mul_n __MPN(mul_n) +#define mpn_perfect_square_p __MPN(perfect_square_p) +#define mpn_popcount __MPN(popcount) +#define mpn_preinv_mod_1 __MPN(preinv_mod_1) +#define mpn_random2 __MPN(random2) +#define mpn_rshift __MPN(rshift) +#define mpn_scan0 __MPN(scan0) +#define mpn_scan1 __MPN(scan1) +#define mpn_set_str __MPN(set_str) +#define mpn_sqrtrem __MPN(sqrtrem) +#define mpn_sub __MPN(sub) +#define mpn_sub_1 __MPN(sub_1) +#define mpn_sub_n __MPN(sub_n) +#define mpn_submul_1 __MPN(submul_1) +#define mpn_udiv_w_sdiv __MPN(udiv_w_sdiv) + +#if defined (__cplusplus) +extern "C" { +#endif +mp_limb_t mpn_add _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +mp_limb_t mpn_add_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_add_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_addmul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_bdivmod _PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); +int mpn_cmp _PROTO ((mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_divmod_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_divrem _PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); +mp_limb_t mpn_divrem_1 _PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); +void mpn_dump _PROTO ((mp_srcptr, mp_size_t)); +mp_size_t mpn_gcd _PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +mp_limb_t mpn_gcd_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t)); +mp_size_t mpn_gcdext _PROTO ((mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +size_t mpn_get_str _PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); +unsigned long int mpn_hamdist _PROTO ((mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_lshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +mp_limb_t mpn_mod_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_mul _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +mp_limb_t mpn_mul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +void mpn_mul_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +int mpn_perfect_square_p _PROTO ((mp_srcptr, mp_size_t)); +unsigned long int mpn_popcount _PROTO ((mp_srcptr, mp_size_t)); +mp_limb_t mpn_preinv_mod_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)); +void mpn_random2 _PROTO ((mp_ptr, mp_size_t)); +mp_limb_t mpn_rshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +unsigned long int mpn_scan0 _PROTO ((mp_srcptr, unsigned long int)); +unsigned long int mpn_scan1 _PROTO ((mp_srcptr, unsigned long int)); +mp_size_t mpn_set_str _PROTO ((mp_ptr, const unsigned char *, size_t, int)); +mp_size_t mpn_sqrtrem _PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_sub _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +mp_limb_t mpn_sub_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_sub_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_submul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +#if defined (__cplusplus) +} +#endif + +#if defined (__GNUC__) || defined (_FORCE_INLINES) +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_add_1 (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_limb_t s2_limb) +#else +mpn_add_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_limb_t s2_limb; +#endif +{ + register mp_limb_t x; + + x = *s1_ptr++; + s2_limb = x + s2_limb; + *res_ptr++ = s2_limb; + if (s2_limb < x) + { + while (--s1_size != 0) + { + x = *s1_ptr++ + 1; + *res_ptr++ = x; + if (x != 0) + goto fin; + } + + return 1; + } + + fin: + if (res_ptr != s1_ptr) + { + mp_size_t i; + for (i = 0; i < s1_size - 1; i++) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_add (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_srcptr s2_ptr, + register mp_size_t s2_size) +#else +mpn_add (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_srcptr s2_ptr; + register mp_size_t s2_size; +#endif +{ + mp_limb_t cy_limb = 0; + + if (s2_size != 0) + cy_limb = mpn_add_n (res_ptr, s1_ptr, s2_ptr, s2_size); + + if (s1_size - s2_size != 0) + cy_limb = mpn_add_1 (res_ptr + s2_size, + s1_ptr + s2_size, + s1_size - s2_size, + cy_limb); + return cy_limb; +} + +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_sub_1 (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_limb_t s2_limb) +#else +mpn_sub_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_limb_t s2_limb; +#endif +{ + register mp_limb_t x; + + x = *s1_ptr++; + s2_limb = x - s2_limb; + *res_ptr++ = s2_limb; + if (s2_limb > x) + { + while (--s1_size != 0) + { + x = *s1_ptr++; + *res_ptr++ = x - 1; + if (x != 0) + goto fin; + } + + return 1; + } + + fin: + if (res_ptr != s1_ptr) + { + mp_size_t i; + for (i = 0; i < s1_size - 1; i++) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_sub (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_srcptr s2_ptr, + register mp_size_t s2_size) +#else +mpn_sub (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_srcptr s2_ptr; + register mp_size_t s2_size; +#endif +{ + mp_limb_t cy_limb = 0; + + if (s2_size != 0) + cy_limb = mpn_sub_n (res_ptr, s1_ptr, s2_ptr, s2_size); + + if (s1_size - s2_size != 0) + cy_limb = mpn_sub_1 (res_ptr + s2_size, + s1_ptr + s2_size, + s1_size - s2_size, + cy_limb); + return cy_limb; +} +#endif /* __GNUC__ */ + +/* Allow faster testing for negative, zero, and positive. */ +#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) +#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) +#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) + +/* Allow direct user access to numerator and denominator of a mpq_t object. */ +#define mpq_numref(Q) (&((Q)->_mp_num)) +#define mpq_denref(Q) (&((Q)->_mp_den)) + +/* When using GCC, optimize certain common comparisons. */ +#if defined (__GNUC__) +#define mpz_cmp_ui(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 \ + ? mpz_sgn (Z) : mpz_cmp_ui (Z,UI)) +#define mpz_cmp_si(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 ? mpz_sgn (Z) \ + : __builtin_constant_p (UI) && (UI) > 0 ? mpz_cmp_ui (Z,UI) \ + : mpz_cmp_si (Z,UI)) +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 \ + ? mpq_sgn (Q) : mpq_cmp_ui (Q,NUI,DUI)) +#endif + +#define mpn_divmod(qp,np,nsize,dp,dsize) mpn_divrem (qp,0,np,nsize,dp,dsize) +#if 0 +#define mpn_divmod_1(qp,np,nsize,dlimb) mpn_divrem_1 (qp,0,np,nsize,dlimb) +#endif + +/* Compatibility with GMP 1. */ +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdivmod_ui(q,r,n,d) \ + ((r == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) +#define mpz_mmod_ui(r,n,d) \ + ((r == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) + +/* Useful synonyms, but not quite compatible with GMP 1. */ +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_mod_ui mpz_fdiv_r_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp + +#define __GNU_MP_VERSION 2 +#define __GNU_MP_VERSION_MINOR 0 +#define __GMP_H__ +#endif /* __GMP_H__ */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/grouping.h b/src/kernel/libroot/posix/glibc/stdlib/grouping.h new file mode 100644 index 0000000000..830304d2f1 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/grouping.h @@ -0,0 +1,186 @@ +/* Internal header for proving correct grouping in strings of numbers. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifndef MAX +#define MAX(a,b) ({ typeof(a) _a = (a); typeof(b) _b = (b); \ + _a > _b ? _a : _b; }) +#endif + +/* Find the maximum prefix of the string between BEGIN and END which + satisfies the grouping rules. It is assumed that at least one digit + follows BEGIN directly. */ + +static inline const STRING_TYPE * +correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end, +#ifdef USE_WIDE_CHAR + wchar_t thousands, +#else + const char *thousands, +#endif + const char *grouping) +{ +#ifndef USE_WIDE_CHAR + size_t thousands_len; + int cnt; +#endif + + if (grouping == NULL) + return end; + +#ifndef USE_WIDE_CHAR + thousands_len = strlen (thousands); +#endif + + while (end > begin) + { + const STRING_TYPE *cp = end - 1; + const char *gp = grouping; + + /* Check first group. */ + while (cp >= begin) + { +#ifdef USE_WIDE_CHAR + if (*cp == thousands) + break; +#else + if (cp[thousands_len - 1] == *thousands) + { + for (cnt = 1; thousands[cnt] != '\0'; ++cnt) + if (thousands[cnt] != cp[thousands_len - 1 - cnt]) + break; + if (thousands[cnt] == '\0') + break; + } +#endif + --cp; + } + + /* We allow the representation to contain no grouping at all even if + the locale specifies we can have grouping. */ + if (cp < begin) + return end; + + if (end - cp == (int) *gp + 1) + { + /* This group matches the specification. */ + + const STRING_TYPE *new_end; + + if (cp < begin) + /* There is just one complete group. We are done. */ + return end; + + /* CP points to a thousands separator character. The preceding + remainder of the string from BEGIN to NEW_END is the part we + will consider if there is a grouping error in this trailing + portion from CP to END. */ + new_end = cp - 1; + + /* Loop while the grouping is correct. */ + while (1) + { + /* Get the next grouping rule. */ + ++gp; + if (*gp == 0) + /* If end is reached use last rule. */ + --gp; + + /* Skip the thousands separator. */ + --cp; + + if (*gp == CHAR_MAX +#if CHAR_MIN < 0 + || *gp < 0 +#endif + ) + { + /* No more thousands separators are allowed to follow. */ + while (cp >= begin) + { +#ifdef USE_WIDE_CHAR + if (*cp == thousands) + break; +#else + for (cnt = 0; thousands[cnt] != '\0'; ++cnt) + if (thousands[cnt] != cp[thousands_len - cnt - 1]) + break; + if (thousands[cnt] == '\0') + break; +#endif + --cp; + } + + if (cp < begin) + /* OK, only digits followed. */ + return end; + } + else + { + /* Check the next group. */ + const STRING_TYPE *group_end = cp; + + while (cp >= begin) + { +#ifdef USE_WIDE_CHAR + if (*cp == thousands) + break; +#else + for (cnt = 0; thousands[cnt] != '\0'; ++cnt) + if (thousands[cnt] != cp[thousands_len - cnt - 1]) + break; + if (thousands[cnt] == '\0') + break; +#endif + --cp; + } + + if (cp < begin && group_end - cp <= (int) *gp) + /* Final group is correct. */ + return end; + + if (cp < begin || group_end - cp != (int) *gp) + /* Incorrect group. Punt. */ + break; + } + } + + /* The trailing portion of the string starting at NEW_END + contains a grouping error. So we will look for a correctly + grouped number in the preceding portion instead. */ + end = new_end; + } + else + { + /* Even the first group was wrong; determine maximum shift. */ + if (end - cp > (int) *gp + 1) + end = cp + (int) *gp + 1; + else if (cp < begin) + /* This number does not fill the first group, but is correct. */ + return end; + else + /* CP points to a thousands separator character. */ + end = cp; + } + } + + return MAX (begin, end); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/isomac.c b/src/kernel/libroot/posix/glibc/stdlib/isomac.c new file mode 100644 index 0000000000..c0b9ad1db2 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/isomac.c @@ -0,0 +1,445 @@ +/* Check system header files for ISO 9899:1990 (ISO C) compliance. + Copyright (C) 1996,97,98,99,2001,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jens Schweikhardt , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is a simple minded program that tries to find illegal macro + definitions in system header files. Illegal macro definitions are + those not from the implementation namespace (i.e. not starting with + an underscore) or not matching any identifier mandated by The + Standard. Some common macro names are considered okay, e.g. all those + beginning with E (which may be defined in ) or ending in + _MAX. See the arrays prefix[] and suffix[] below for details. + + In a compliant implementation no other macros can be defined, because + you could write strictly conforming programs that may fail to compile + due to syntax errors: suppose defines PIPE_BUF, then the + conforming + + #include + #include <- or where the bogus macro is defined + #include + #define STR(x) #x + #define XSTR(x) STR(x) + int main (void) + { + int PIPE_BUF = 0; + assert (strcmp ("PIPE_BUF", XSTR (PIPE_BUF)) == 0); + return 0; + } + + is expected to compile and meet the assertion. If it does not, your + compiler compiles some other language than Standard C. + + REQUIREMENTS: + This program calls gcc to get the list of defined macros. If you + don't have gcc you're probably out of luck unless your compiler or + preprocessor has something similar to gcc's -dM option. Tune + PRINT_MACROS in this case. This program assumes headers are found + under /usr/include and that there is a writable /tmp directory. + Tune SYSTEM_INCLUDE if your system differs. + #define BROKEN_SYSTEM if system(NULL) bombs -- one more violation + of ISO C, by the way. + + OUTPUT: + Each header file name is printed, followed by illegal macro names + and their definition. For the above example, you would see + ... + /usr/include/stdio.h + #define PIPE_BUF 5120 + ... + If your implementation does not yet incorporate Amendment 1 you + will see messages about iso646.h, wctype.h and wchar.h not being + found. */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include +#include +#include + +#define HEADER_MAX 256 + +static const char *macrofile; + +/* ISO C header names including Amendment 1 (without ".h" suffix). */ +static char *header[] = +{ + "assert", "ctype", "errno", "float", "iso646", "limits", "locale", + "math", "setjmp", "signal", "stdarg", "stddef", "stdio", "stdlib", + "string", "time", "wchar", "wctype" +}; + +/* Macros with these prefixes are considered okay. */ +static char *prefix[] = +{ + "_", "E", "is", "str", "mem", "SIG", "FLT_", "DBL_", "LDBL_", + "LC_", "wmem", "wcs" +}; + +/* Macros with these suffixes are considered okay. Will not work for + parametrized macros with arguments. */ +static char *suffix[] = +{ + "_MAX", "_MIN" +}; + +/* These macros are considered okay. In fact, these are just more prefixes. */ +static char *macros[] = +{ + "BUFSIZ", "CHAR_BIT", "CHAR_MAX", "CHAR_MIN", "CLOCKS_PER_SEC", + "DBL_DIG", "DBL_EPSILON", "DBL_MANT_DIG", "DBL_MAX", + "DBL_MAX_10_EXP", "DBL_MAX_EXP", "DBL_MIN", "DBL_MIN_10_EXP", + "DBL_MIN_EXP", "EDOM", "EILSEQ", "EOF", "ERANGE", "EXIT_FAILURE", + "EXIT_SUCCESS", "FILENAME_MAX", "FLT_DIG", "FLT_EPSILON", + "FLT_MANT_DIG", "FLT_MAX", "FLT_MAX_10_EXP", "FLT_MAX_EXP", + "FLT_MIN", "FLT_MIN_10_EXP", "FLT_MIN_EXP", "FLT_RADIX", + "FLT_ROUNDS", "FOPEN_MAX", "HUGE_VAL", "INT_MAX", "INT_MIN", + "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC", + "LC_TIME", "LDBL_DIG", "LDBL_EPSILON", "LDBL_MANT_DIG", "LDBL_MAX", + "LDBL_MAX_10_EXP", "LDBL_MAX_EXP", "LDBL_MIN", "LDBL_MIN_10_EXP", + "LDBL_MIN_EXP", "LONG_MAX", "LONG_MIN", "L_tmpnam", "MB_CUR_MAX", + "MB_LEN_MAX", "NDEBUG", "NULL", "RAND_MAX", "SCHAR_MAX", + "SCHAR_MIN", "SEEK_CUR", "SEEK_END", "SEEK_SET", "SHRT_MAX", + "SHRT_MIN", "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", + "SIGTERM", "SIG_DFL", "SIG_ERR", "SIG_IGN", "TMP_MAX", "UCHAR_MAX", + "UINT_MAX", "ULONG_MAX", "USHRT_MAX", "WCHAR_MAX", "WCHAR_MIN", + "WEOF", "_IOFBF", "_IOLBF", "_IONBF", "abort", "abs", "acos", + "acosf", "acosl", "and", "and_eq", "asctime", "asin", "asinf", + "asinl", "assert", "atan", "atan2", "atan2f", "atan2l", "atanf", + "atanl", "atexit", "atof", "atoi", "atol", "bitand", "bitor", + "bsearch", "btowc", "calloc", "ceil", "ceilf", "ceill", "clearerr", + "clock", "clock_t", "compl", "cos", "cosf", "cosh", "coshf", + "coshl", "cosl", "ctime", "difftime", "div", "div_t", "errno", + "exit", "exp", "expf", "expl", "fabs", "fabsf", "fabsl", "fclose", + "feof", "ferror", "fflush", "fgetc", "fgetpos", "fgets", "fgetwc", + "fgetws", "floor", "floorf", "floorl", "fmod", "fmodf", "fmodl", + "fopen", "fprintf", "fputc", "fputs", "fputwc", "fputws", "fread", + "free", "freopen", "frexp", "frexpf", "frexpl", "fscanf", "fseek", + "fsetpos", "ftell", "fwide", "fwprintf", "fwrite", "fwscanf", + "getc", "getchar", "getenv", "gets", "getwc", "getwchar", "gmtime", + "isalnum", "isalpha", "iscntrl", "isdigit", "isgraph", "islower", + "isprint", "ispunct", "isspace", "isupper", "iswalnum", "iswalpha", + "iswcntrl", "iswctype", "iswdigit", "iswgraph", "iswlower", + "iswprint", "iswpunct", "iswspace", "iswupper", "iswxdigit", + "isxdigit", "labs", "ldexp", "ldexpf", "ldexpl", "ldiv", "ldiv_t", + "localeconv", "localtime", "log", "log10", "log10f", "log10l", + "logf", "logl", "longjmp", "malloc", "mblen", "mbrlen", "mbrtowc", + "mbsinit", "mbsrtowcs", "mbstate_t", "mbstowcs", "mbtowc", "memchr", + "memcmp", "memcpy", "memmove", "memset", "mktime", "modf", "modff", + "modfl", "not", "not_eq", "offsetof", "or", "or_eq", "perror", + "pow", "powf", "powl", "printf", "ptrdiff_t", "putc", "putchar", + "puts", "putwc", "putwchar", "qsort", "raise", "rand", "realloc", + "remove", "rename", "rewind", "scanf", "setbuf", "setjmp", + "setlocale", "setvbuf", "sig_atomic_t", "signal", "sin", "sinf", + "sinh", "sinhf", "sinhl", "sinl", "size_t", "sprintf", "sqrt", + "sqrtf", "sqrtl", "srand", "sscanf", "stderr", "stdin", "stdout", + "strcat", "strchr", "strcmp", "strcoll", "strcpy", "strcspn", + "strerror", "strftime", "strlen", "strncat", "strncmp", "strncpy", + "strpbrk", "strrchr", "strspn", "strstr", "strtod", "strtok", + "strtol", "strtoul", "strxfrm", "swprintf", "swscanf", "system", + "tan", "tanf", "tanh", "tanhf", "tanhl", "tanl", "time", "time_t", + "tmpfile", "tmpnam", "tolower", "toupper", "towctrans", "towlower", + "towupper", "ungetc", "ungetwc", "va_arg", "va_copy", "va_end", "va_start", + "vfprintf", "vfwprintf", "vprintf", "vsprintf", "vswprintf", + "vwprintf", "wchar_t", "wcrtomb", "wcscat", "wcschr", "wcscmp", + "wcscoll", "wcscpy", "wcscspn", "wcsftime", "wcslen", "wcsncat", + "wcsncmp", "wcsncpy", "wcspbrk", "wcsrchr", "wcsrtombs", "wcsspn", + "wcsstr", "wcstod", "wcstok", "wcstol", "wcstombs", "wcstoul", + "wcsxfrm", "wctob", "wctomb", "wctrans", "wctrans_t", "wctype", + "wctype_t", "wint_t", "wmemchr", "wmemcmp", "wmemcpy", "wmemmove", + "wmemset", "wprintf", "wscanf", "xor", "xor_eq" +}; + +#define NUMBER_OF_HEADERS (sizeof header / sizeof *header) +#define NUMBER_OF_PREFIXES (sizeof prefix / sizeof *prefix) +#define NUMBER_OF_SUFFIXES (sizeof suffix / sizeof *suffix) +#define NUMBER_OF_MACROS (sizeof macros / sizeof *macros) + + +/* Format string to build command to invoke compiler. */ +static const char fmt[] = "\ +echo \"#include <%s>\" |\ +%s -E -dM -ansi -pedantic %s -D_LIBC -D_ISOMAC -DNOT_IN_libc -I. \ +-isystem `%s --print-prog-name=include` - 2> /dev/null > %s"; + + +/* The compiler we use (given on the command line). */ +char *CC; +/* The -I parameters for CC to find all headers. */ +char *INC; + +static char *xstrndup (const char *, size_t); +static const char **get_null_defines (void); +static int check_header (const char *, const char **); + +int +main (int argc, char *argv[]) +{ + int h; + int result = 0; + const char **ignore_list; + + CC = argc > 1 ? argv[1] : "gcc"; + INC = argc > 2 ? argv[2] : ""; + + if (system (NULL) == 0) + { + puts ("Sorry, no command processor."); + return EXIT_FAILURE; + } + + /* First get list of symbols which are defined by the compiler. */ + ignore_list = get_null_defines (); + + fputs ("Tested files:\n", stdout); + + for (h = 0; h < NUMBER_OF_HEADERS; ++h) + { + char file_name[HEADER_MAX]; + sprintf (file_name, "%s.h", header[h]); + result |= check_header (file_name, ignore_list); + } + + /* The test suite should return errors but for now this is not + practical. Give a warning and ask the user to correct the bugs. */ + return result; +} + + +static char * +xstrndup (const char *s, size_t n) +{ + size_t len = n; + char *new = malloc (len + 1); + + if (new == NULL) + return NULL; + + new[len] = '\0'; + return memcpy (new, s, len); +} + + +static const char ** +get_null_defines (void) +{ + char line[BUFSIZ], *command; + char **result = NULL; + size_t result_len = 0; + size_t result_max = 0; + FILE *input; + int first = 1; + + macrofile = tmpnam (NULL); + + command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC) + + strlen (INC) + strlen (macrofile)); + + if (command == NULL) + { + puts ("No more memory."); + exit (1); + } + + sprintf (command, fmt, "/dev/null", CC, INC, CC, macrofile); + + if (system (command)) + { + puts ("system() returned nonzero"); + return NULL; + } + free (command); + input = fopen (macrofile, "r"); + + if (input == NULL) + { + printf ("Could not read %s: ", macrofile); + perror (NULL); + return NULL; + } + + while (fgets (line, sizeof line, input) != NULL) + { + int i, okay = 0; + size_t endmac; + char *start, *end; + if (strlen (line) < 9 || line[7] != ' ') + { /* "#define A" */ + printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n", + line); + continue; + } + if (line[8] == '_') + /* It's a safe identifier. */ + continue; + if (result_len == result_max) + { + result_max += 10; + result = realloc (result, result_max * sizeof (char **)); + if (result == NULL) + { + puts ("No more memory."); + exit (1); + } + } + start = &line[8]; + for (end = start + 1; !isspace (*end) && *end != '\0'; ++end) + ; + result[result_len] = xstrndup (start, end - start); + + if (strcmp (result[result_len], "NOT_IN_libc") != 0) + { + if (first) + { + fputs ("The following identifiers will be ignored since the compiler defines them\nby default:\n", stdout); + first = 0; + } + puts (result[result_len]); + } + ++result_len; + } + if (result_len == result_max) + { + result_max += 1; + result = realloc (result, result_max * sizeof (char **)); + if (result == NULL) + { + puts ("No more memory."); + exit (1); + } + } + result[result_len] = NULL; + fclose (input); + remove (macrofile); + + return (const char **) result; +} + + +static int +check_header (const char *file_name, const char **except) +{ + char line[BUFSIZ], *command; + FILE *input; + int result = 0; + + command = malloc (sizeof fmt + strlen (file_name) + 2 * strlen (CC) + + strlen (INC) + strlen (macrofile)); + + if (command == NULL) + { + puts ("No more memory."); + exit (1); + } + + puts (file_name); + sprintf (command, fmt, file_name, CC, INC, CC, macrofile); + + if (system (command)) + { + puts ("system() returned nonzero"); + result = 1; + } + free (command); + input = fopen (macrofile, "r"); + + if (input == NULL) + { + printf ("Could not read %s: ", macrofile); + perror (NULL); + return 1; + } + + while (fgets (line, sizeof line, input) != NULL) + { + int i, okay = 0; + size_t endmac; + const char **cpp; + if (strlen (line) < 9 || line[7] != ' ') + { /* "#define A" */ + printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n", + line); + result = 1; + continue; + } + for (i = 0; i < NUMBER_OF_PREFIXES; ++i) + { + if (!strncmp (line+8, prefix[i], strlen (prefix[i]))) { + ++okay; + break; + } + } + if (okay) + continue; + for (i = 0; i < NUMBER_OF_MACROS; ++i) + { + if (!strncmp (line + 8, macros[i], strlen (macros[i]))) + { + ++okay; + break; + } + } + if (okay) + continue; + /* Find next char after the macro identifier; this can be either + a space or an open parenthesis. */ + endmac = strcspn (line + 8, " ("); + if (line[8+endmac] == '\0') + { + printf ("malformed input, expected '#define MACRO VALUE'\n" + "got '%s'\n", line); + result = 1; + continue; + } + for (i = 0; i < NUMBER_OF_SUFFIXES; ++i) + { + size_t len = strlen (suffix[i]); + if (!strncmp (line + 8 + endmac - len, suffix[i], len)) + { + ++okay; + break; + } + } + if (okay) + continue; + if (except != NULL) + for (cpp = except; *cpp != NULL; ++cpp) + { + size_t len = strlen (*cpp); + if (!strncmp (line + 8, *cpp, len) && isspace (line[8 + len])) + { + ++okay; + break; + } + } + if (!okay) + { + fputs (line, stdout); + result = 2; + } + } + fclose (input); + remove (macrofile); + + return result; +} + +/* EOF */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/jrand48.c b/src/kernel/libroot/posix/glibc/stdlib/jrand48.c new file mode 100644 index 0000000000..81fa8241ef --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/jrand48.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +long int +jrand48 (xsubi) + unsigned short int xsubi[3]; +{ + long int result; + + (void) __jrand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/jrand48_r.c b/src/kernel/libroot/posix/glibc/stdlib/jrand48_r.c new file mode 100644 index 0000000000..2383ae129e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/jrand48_r.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +__jrand48_r (xsubi, buffer, result) + unsigned short int xsubi[3]; + struct drand48_data *buffer; + long int *result; +{ + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Store the result. */ + *result = ((xsubi[2] << 16) | xsubi[1]) & 0xffffffffl; + + return 0; +} +weak_alias (__jrand48_r, jrand48_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/l64a.c b/src/kernel/libroot/posix/glibc/stdlib/l64a.c new file mode 100644 index 0000000000..f3a249fedf --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/l64a.c @@ -0,0 +1,58 @@ +/* Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Conversion table. */ +static const char conv_table[64] = +{ + '.', '/', '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' +}; + +char * +l64a (n) + long int n; +{ + unsigned long int m = (unsigned long int) n; + static char result[7]; + int cnt; + + /* The standard says that only 32 bits are used. */ + m &= 0xffffffff; + + if (m == 0ul) + /* The value for N == 0 is defined to be the empty string. */ + return (char *) ""; + + for (cnt = 0; m > 0ul; ++cnt) + { + result[cnt] = conv_table[m & 0x3f]; + m >>= 6; + } + result[cnt] = '\0'; + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/lcong48.c b/src/kernel/libroot/posix/glibc/stdlib/lcong48.c new file mode 100644 index 0000000000..075494a888 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/lcong48.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +void +lcong48 (param) + unsigned short int param[7]; +{ + (void) __lcong48_r (param, &__libc_drand48_data); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/lcong48_r.c b/src/kernel/libroot/posix/glibc/stdlib/lcong48_r.c new file mode 100644 index 0000000000..a9584a5a8c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/lcong48_r.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +int +__lcong48_r (param, buffer) + unsigned short int param[7]; + struct drand48_data *buffer; +{ + /* Store the given values. */ + memcpy (buffer->__x, ¶m[0], sizeof (buffer->__x)); + buffer->__a = ((uint64_t) param[5] << 32 | (uint32_t) param[4] << 16 + | param[3]); + buffer->__c = param[6]; + buffer->__init = 1; + + return 0; +} +weak_alias (__lcong48_r, lcong48_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/longlong.h b/src/kernel/libroot/posix/glibc/stdlib/longlong.h new file mode 100644 index 0000000000..cd1e30ed2e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/longlong.h @@ -0,0 +1,1333 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000 + Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + UQItype -- Unsigned 8 bit type. + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +#ifndef W_TYPE_SIZE +#define W_TYPE_SIZE 32 +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first nonzero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! + (E.g. WE32100, IBM360.) */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#ifdef __alpha_cix__ +#define count_leading_zeros(COUNT,X) \ + __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X)) +#define count_trailing_zeros(COUNT,X) \ + __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X)) +#define COUNT_LEADING_ZEROS_0 64 +#else +extern const UQItype __clz_tab[]; +#define count_leading_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ + __a = __clz_tab[__t ^ 0xff] - 1; \ + __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ + (COUNT) = 64 - (__clz_tab[__t] + __a*8); \ + } while (0) +#define count_trailing_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ + __t = ~__t & -~__t; \ + __a = ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ + __a <<= 3; \ + __t &= -__t; \ + __a += ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + (COUNT) = __a; \ + } while (0) +#endif /* __alpha_cix__ */ +#endif /* __alpha */ + +#if defined (__arc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +/* Call libgcc routine. */ +#define umul_ppmm(w1, w0, u, v) \ +do { \ + DWunion __w; \ + __w.ll = __umulsidi3 (u, v); \ + w1 = __w.s.high; \ + w0 = __w.s.low; \ +} while (0) +#define __umulsidi3 __umulsidi3 +UDItype __umulsidi3 (USItype, USItype); +#endif + +#if defined (__arm__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rI" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rI" ((USItype) (bl))) +#define umul_ppmm(xh, xl, a, b) \ +{register USItype __t0, __t1, __t2; \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + " mov %2, %5, lsr #16\n" \ + " mov %0, %6, lsr #16\n" \ + " bic %3, %5, %2, lsl #16\n" \ + " bic %4, %6, %0, lsl #16\n" \ + " mul %1, %3, %4\n" \ + " mul %4, %2, %4\n" \ + " mul %3, %0, %3\n" \ + " mul %0, %2, %0\n" \ + " adds %3, %4, %3\n" \ + " addcs %0, %0, #65536\n" \ + " adds %1, %1, %3, lsl #16\n" \ + " adc %0, %0, %3, lsr #16" \ + : "=&r" ((USItype) (xh)), \ + "=r" ((USItype) (xl)), \ + "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ + : "r" ((USItype) (a)), \ + "r" ((USItype) (b)));} +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#endif /* __arm__ */ + +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "%rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + union \ + { \ + UDItype __f; \ + struct {USItype __w1, __w0;} __w1w0; \ + } __t; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=x" (__t.__f) \ + : "x" ((USItype) (u)), \ + "x" ((USItype) (v))); \ + (w1) = __t.__w1w0.__w1; \ + (w0) = __t.__w1w0.__w0; \ + } while (0) +#define UMUL_TIME 8 +#else +#define UMUL_TIME 30 +#endif +#define UDIV_TIME 40 +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0\n" \ +" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\ +" ldo 16(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\ +" ldo 8(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\ +" ldo 4(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\ +" ldo 2(%0),%0 ; Yes. Perform add.\n" \ +" extru %1,30,1,%1 ; Extract bit 1.\n" \ +" sub %0,%1,%0 ; Subtract it.\n" \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif + +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1\n\tadcl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "rm" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("divl %4" \ + : "=a" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "rm" ((USItype) (dv))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#endif /* 80x86 */ + +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + __w; }) +#endif /* __i960__ */ + +#if defined (__M32R__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\taddx %%5,%1\n\taddx %%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\tsubx %5,%1\n\tsubx %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#endif /* __M32R__ */ + +#if defined (__mc68000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) + +/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r. */ +#if defined (__mc68020__) || defined(mc68020) \ + || defined(__mc68030__) || defined(mc68030) \ + || defined(__mc68040__) || defined(mc68040) \ + || defined(__mcpu32__) || defined(mcpu32) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "dmi" ((USItype) (v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) + +#else /* not mc68020 */ +#if !defined(__mcf5200__) +/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("| Inlined umul_ppmm\n" \ + " move%.l %2,%/d0\n" \ + " move%.l %3,%/d1\n" \ + " move%.l %/d0,%/d2\n" \ + " swap %/d0\n" \ + " move%.l %/d1,%/d3\n" \ + " swap %/d1\n" \ + " move%.w %/d2,%/d4\n" \ + " mulu %/d3,%/d4\n" \ + " mulu %/d1,%/d2\n" \ + " mulu %/d0,%/d3\n" \ + " mulu %/d0,%/d1\n" \ + " move%.l %/d4,%/d0\n" \ + " eor%.w %/d0,%/d0\n" \ + " swap %/d0\n" \ + " add%.l %/d0,%/d2\n" \ + " add%.l %/d3,%/d2\n" \ + " jcc 1f\n" \ + " add%.l %#65536,%/d1\n" \ + "1: swap %/d2\n" \ + " moveq %#0,%/d0\n" \ + " move%.w %/d2,%/d0\n" \ + " move%.w %/d4,%/d2\n" \ + " move%.l %/d2,%1\n" \ + " add%.l %/d1,%/d0\n" \ + " move%.l %/d0,%0" \ + : "=g" ((USItype) (xh)), \ + "=g" ((USItype) (xl)) \ + : "g" ((USItype) (a)), \ + "g" ((USItype) (b)) \ + : "d0", "d1", "d2", "d3", "d4") +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mcf5200 */ +#endif /* not mc68020 */ + +/* The '020, '030, '040 and '060 have bitfield insns. */ +#if defined (__mc68020__) || defined(mc68020) \ + || defined(__mc68030__) || defined(mc68030) \ + || defined(__mc68040__) || defined(mc68040) \ + || defined(__mc68060__) || defined(mc68060) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype) (count)) \ + : "od" ((USItype) (x)), "n" (0)) +#endif +#endif /* mc68000 */ + +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__mc88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mulu.d %0,%1,%2" \ + : "=r" (__xx.__ll) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __q; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q) \ + : "r" (__xx.__ll), \ + "r" ((USItype) (d))); \ + (r) = (n0) - __q * (d); (q) = __q; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __mc88110__ */ +#endif /* __m88000__ */ + +#if defined (__mips__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype) (w0)), \ + "=h" ((USItype) (w1)) \ + : "d" ((USItype) (u)), \ + "d" ((USItype) (v))) +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype) (d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { \ + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + +/* FIXME: We should test _IBMR2 here when we add assembly support for the + system vendor compilers. + FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good + enough, since that hits ARM and m68k too. */ +#if (defined (_ARCH_PPC) /* AIX */ \ + || defined (_ARCH_PWR) /* AIX */ \ + || defined (_ARCH_COM) /* AIX */ \ + || defined (__powerpc__) /* gcc */ \ + || defined (__POWERPC__) /* BEOS */ \ + || defined (__ppc__) /* Darwin */ \ + || defined (PPC) /* GNU/Linux, SysV */ \ + ) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \ + || defined (__ppc__) || defined (PPC) || defined (__vxworks__) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#elif defined (_ARCH_PWR) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d)) +#define UDIV_TIME 100 +#endif +#endif /* 32-bit POWER architecture variants. */ + +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ + +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5\n\tae %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n\tse %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2\n" \ +" mts r10,%2\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" cas %0,r2,r0\n" \ +" mfs r10,%1" \ + : "=r" ((USItype) (ph)), \ + "=r" ((USItype) (pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + (count) += 16; \ + } \ + } while (0) +#endif + +#if defined (__sh2__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32 +#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v) +#define count_leading_zeros(count, x) \ + do \ + { \ + UDItype x_ = (USItype)(x); \ + SItype c_; \ + \ + __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_)); \ + (count) = c_ - 31; \ + } \ + while (0) +#define COUNT_LEADING_ZEROS_0 32 +#endif + +#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__n1)), \ + "r" ((USItype) (__n0)), \ + "r" ((USItype) (__d))) +#else +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \ +" tst %%g0\n" \ +" divscc %3,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%0\n" \ +" rd %%y,%1\n" \ +" bl,a 1f\n" \ +" add %1,%4,%1\n" \ +"1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype) (q)), \ + "=r" ((USItype) (r)) \ + : "r" ((USItype) (n1)), \ + "r" ((USItype) (n0)), \ + "rI" ((USItype) (d)) \ + : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + do { \ + __asm__ ("scan %1,1,%0" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + } while (0) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#else +/* SPARC without integer multiplication and divide instructions. + (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm\n" \ +" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\ +" sra %3,31,%%o5 ! Don't move this insn\n" \ +" and %2,%%o5,%%o5 ! Don't move this insn\n" \ +" andcc %%g0,0,%%g1 ! Don't move this insn\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,0,%%g1\n" \ +" add %%g1,%%o5,%0\n" \ +" rd %%y,%1" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "%rI" ((USItype) (u)), \ + "r" ((USItype) (v)) \ + : "g1", "o5" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +/* It's quite necessary to add this much assembler for the sparc. + The default udiv_qrnnd (in C) is more than 10 times slower! */ +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" mov 32,%%g1\n" \ +" subcc %1,%2,%%g0\n" \ +"1: bcs 5f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +" addx %1,%1,%1 ! so this can't give carry\n" \ +" subcc %%g1,1,%%g1\n" \ +"2: bne 1b\n" \ +" subcc %1,%2,%%g0\n" \ +" bcs 3f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" b 3f\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +"4: sub %1,%2,%1\n" \ +"5: addxcc %1,%1,%1\n" \ +" bcc 2b\n" \ +" subcc %%g1,1,%%g1\n" \ +"! Got carry from n. Subtract next step to cancel this carry.\n" \ +" bne 4b\n" \ +" addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n" \ +" sub %1,%2,%1\n" \ +"3: xnor %0,0,%0\n" \ +" ! End of inline udiv_qrnnd" \ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__d)), \ + "1" ((USItype) (__n1)), \ + "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +#endif /* sparc32 */ + +#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \ + && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\t" \ + "add %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "add %0, 1, %0\n" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "%rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\t" \ + "sub %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "sub %0, 1, %0\n\t" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define umul_ppmm(wh, wl, u, v) \ + do { \ + UDItype tmp1, tmp2, tmp3, tmp4; \ + __asm__ __volatile__ ( \ + "srl %7,0,%3\n\t" \ + "mulx %3,%6,%1\n\t" \ + "srlx %6,32,%2\n\t" \ + "mulx %2,%3,%4\n\t" \ + "sllx %4,32,%5\n\t" \ + "srl %6,0,%3\n\t" \ + "sub %1,%5,%5\n\t" \ + "srlx %5,32,%5\n\t" \ + "addcc %4,%5,%4\n\t" \ + "srlx %7,32,%5\n\t" \ + "mulx %3,%5,%3\n\t" \ + "mulx %2,%5,%5\n\t" \ + "sethi %%hi(0x80000000),%2\n\t" \ + "addcc %4,%3,%4\n\t" \ + "srlx %4,32,%4\n\t" \ + "add %2,%2,%2\n\t" \ + "movcc %%xcc,%%g0,%2\n\t" \ + "addcc %5,%4,%5\n\t" \ + "sllx %3,32,%3\n\t" \ + "add %1,%3,%1\n\t" \ + "add %5,%2,%0" \ + : "=r" ((UDItype)(wh)), \ + "=&r" ((UDItype)(wl)), \ + "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \ + : "r" ((UDItype)(u)), \ + "r" ((UDItype)(v)) \ + __CLOBBER_CC); \ + } while (0) +#define UMUL_TIME 96 +#define UDIV_TIME 230 +#endif /* sparc64 */ + +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union { \ + UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=r" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; \ + (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({DWunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0; \ + UWtype __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + USItype __r; \ + (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern const UQItype __clz_tab[]; +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype)1<<2*__BITS4) \ + ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/src/kernel/libroot/posix/glibc/stdlib/lrand48.c b/src/kernel/libroot/posix/glibc/stdlib/lrand48.c new file mode 100644 index 0000000000..a76d77365c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/lrand48.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +long int +lrand48 () +{ + long int result; + + (void) __nrand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/lrand48_r.c b/src/kernel/libroot/posix/glibc/stdlib/lrand48_r.c new file mode 100644 index 0000000000..a3aa48fcda --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/lrand48_r.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995,97,98,2001,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +lrand48_r (buffer, result) + struct drand48_data *buffer; + long int *result; +{ + /* Be generous for the arguments, detect some errors. */ + if (buffer == NULL) + return -1; + + return __nrand48_r (buffer->__x, buffer, result); +} +libc_hidden_def (lrand48_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/mblen.c b/src/kernel/libroot/posix/glibc/stdlib/mblen.c new file mode 100644 index 0000000000..3cd9cf6909 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/mblen.c @@ -0,0 +1,69 @@ +/* Copyright (C) 1991,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Internal state. */ +static mbstate_t state; + +/* Return the length of the multibyte character (if there is one) + at S which is no longer than N characters. + The ISO C standard says that the `mblen' function must not change + the state of the `mbtowc' function. */ +int +mblen (const char *s, size_t n) +{ + int result; + + /* If S is NULL the function has to return null or not null + depending on the encoding having a state depending encoding or + not. */ + if (s == NULL) + { + const struct gconv_fcts *fcts; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Reset the state. */ + memset (&state, '\0', sizeof state); + + result = fcts->towc->__stateful; + } + else if (*s == '\0') + /* According to the ISO C 89 standard this is the expected behaviour. */ + result = 0; + else + { + memset (&state, '\0', sizeof state); + + result = __mbrtowc (NULL, s, n, &state); + + /* The `mbrtowc' functions tell us more than we need. Fold the -1 + and -2 result into -1. */ + if (result < 0) + result = -1; + } + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/mbstowcs.c b/src/kernel/libroot/posix/glibc/stdlib/mbstowcs.c new file mode 100644 index 0000000000..bc5714647f --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/mbstowcs.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* Convert the string of multibyte characters in S to `wchar_t's in + PWCS, writing no more than N. Return the number written, + or (size_t) -1 if an invalid multibyte character is encountered. + + Attention: this function should NEVER be intentionally used. + The interface is completely stupid. The state is shared between + all conversion functions. You should use instead the restartable + version `mbsrtowcs'. */ +size_t +mbstowcs (wchar_t *pwcs, const char *s, size_t n) +{ + mbstate_t state; + + memset (&state, '\0', sizeof state); + /* Return how many we wrote (or maybe an error). */ + return __mbsrtowcs (pwcs, &s, n, &state); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/mbtowc.c b/src/kernel/libroot/posix/glibc/stdlib/mbtowc.c new file mode 100644 index 0000000000..744b2b6c0b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/mbtowc.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1991, 1992, 1995-1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Common state for all non-restartable conversion functions. */ +mbstate_t __no_r_state attribute_hidden; + +/* Convert the multibyte character at S, which is no longer + than N characters, to its `wchar_t' representation, placing + this n *PWC and returning its length. + + Attention: this function should NEVER be intentionally used. + The interface is completely stupid. The state is shared between + all conversion functions. You should use instead the restartable + version `mbrtowc'. */ +int +mbtowc (wchar_t *pwc, const char *s, size_t n) +{ + int result; + + /* If S is NULL the function has to return null or not null + depending on the encoding having a state depending encoding or + not. */ + if (s == NULL) + { + const struct gconv_fcts *fcts; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* This is an extension in the Unix standard which does not directly + violate ISO C. */ + memset (&__no_r_state, '\0', sizeof __no_r_state); + + result = fcts->towc->__stateful; + } + else if (*s == '\0') + { + if (pwc != NULL) + *pwc = L'\0'; + result = 0; + } + else + { + result = __mbrtowc (pwc, s, n, &__no_r_state); + + /* The `mbrtowc' functions tell us more than we need. Fold the -1 + and -2 result into -1. */ + if (result < 0) + result = -1; + } + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/monetary.h b/src/kernel/libroot/posix/glibc/stdlib/monetary.h new file mode 100644 index 0000000000..4c8a4cd3d4 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/monetary.h @@ -0,0 +1,55 @@ +/* Header file for monetary value formatting functions. + Copyright (C) 1996,97,98,99,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MONETARY_H +#define _MONETARY_H 1 + +#include + +/* Get needed types. */ +#define __need_size_t +#include +#include + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + + +__BEGIN_DECLS + +/* Formatting a monetary value according to the current locale. */ +extern ssize_t strfmon (char *__restrict __s, size_t __maxsize, + __const char *__restrict __format, ...) + __THROW __attribute_format_strfmon__ (3, 4); + +#ifdef __USE_GNU +# include + +/* Formatting a monetary value according to the current locale. */ +extern ssize_t strfmon_l (char *__restrict __s, size_t __maxsize, + __locale_t loc, + __const char *__restrict __format, ...) + __THROW __attribute_format_strfmon__ (4, 5); +#endif + +__END_DECLS + +#endif /* monetary.h */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/mrand48.c b/src/kernel/libroot/posix/glibc/stdlib/mrand48.c new file mode 100644 index 0000000000..cb60191110 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/mrand48.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +long int +mrand48 () +{ + long int result; + + (void) __jrand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/mrand48_r.c b/src/kernel/libroot/posix/glibc/stdlib/mrand48_r.c new file mode 100644 index 0000000000..d47bc3732d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/mrand48_r.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +mrand48_r (buffer, result) + struct drand48_data *buffer; + long int *result; +{ + /* Be generous for the arguments, detect some errors. */ + if (buffer == NULL) + return -1; + + return __jrand48_r (buffer->__x, buffer, result); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/msort.c b/src/kernel/libroot/posix/glibc/stdlib/msort.c new file mode 100644 index 0000000000..45d6a99b83 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/msort.c @@ -0,0 +1,156 @@ +/* An alternative to qsort, with an identical interface. + This file is part of the GNU C Library. + Copyright (C) 1992,95-97,99,2000,01,02 Free Software Foundation, Inc. + Written by Mike Haertel, September 1988. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +static void msort_with_tmp (void *b, size_t n, size_t s, + __compar_fn_t cmp, char *t); + +static void +msort_with_tmp (void *b, size_t n, size_t s, __compar_fn_t cmp, + char *t) +{ + char *tmp; + char *b1, *b2; + size_t n1, n2; + + if (n <= 1) + return; + + n1 = n / 2; + n2 = n - n1; + b1 = b; + b2 = (char *) b + (n1 * s); + + msort_with_tmp (b1, n1, s, cmp, t); + msort_with_tmp (b2, n2, s, cmp, t); + + tmp = t; + + if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0) + /* We are operating on aligned words. Use direct word stores. */ + while (n1 > 0 && n2 > 0) + { + if ((*cmp) (b1, b2) <= 0) + { + --n1; + *((op_t *) tmp)++ = *((op_t *) b1)++; + } + else + { + --n2; + *((op_t *) tmp)++ = *((op_t *) b2)++; + } + } + else + while (n1 > 0 && n2 > 0) + { + if ((*cmp) (b1, b2) <= 0) + { + tmp = (char *) __mempcpy (tmp, b1, s); + b1 += s; + --n1; + } + else + { + tmp = (char *) __mempcpy (tmp, b2, s); + b2 += s; + --n2; + } + } + if (n1 > 0) + memcpy (tmp, b1, n1 * s); + memcpy (b, t, (n - n2) * s); +} + +void +qsort (void *b, size_t n, size_t s, __compar_fn_t cmp) +{ + const size_t size = n * s; + + if (size < 1024) + { + void *buf = __alloca (size); + + /* The temporary array is small, so put it on the stack. */ + msort_with_tmp (b, n, s, cmp, buf); + } + else + { + /* We should avoid allocating too much memory since this might + have to be backed up by swap space. */ + static long int phys_pages; + static int pagesize; + + if (phys_pages == 0) + { + phys_pages = __sysconf (_SC_PHYS_PAGES); + + if (phys_pages == -1) + /* Error while determining the memory size. So let's + assume there is enough memory. Otherwise the + implementer should provide a complete implementation of + the `sysconf' function. */ + phys_pages = (long int) (~0ul >> 1); + + /* The following determines that we will never use more than + a quarter of the physical memory. */ + phys_pages /= 4; + + pagesize = __sysconf (_SC_PAGESIZE); + } + + /* Just a comment here. We cannot compute + phys_pages * pagesize + and compare the needed amount of memory against this value. + The problem is that some systems might have more physical + memory then can be represented with a `size_t' value (when + measured in bytes. */ + + /* If the memory requirements are too high don't allocate memory. */ + if (size / pagesize > (size_t) phys_pages) + _quicksort (b, n, s, cmp); + else + { + /* It's somewhat large, so malloc it. */ + int save = errno; + char *tmp = malloc (size); + if (tmp == NULL) + { + /* Couldn't get space, so use the slower algorithm + that doesn't need a temporary array. */ + __set_errno (save); + _quicksort (b, n, s, cmp); + } + else + { + __set_errno (save); + msort_with_tmp (b, n, s, cmp, tmp); + free (tmp); + } + } + } +} +libc_hidden_def (qsort) diff --git a/src/kernel/libroot/posix/glibc/stdlib/nrand48.c b/src/kernel/libroot/posix/glibc/stdlib/nrand48.c new file mode 100644 index 0000000000..0c6b2707b8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/nrand48.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +long int +nrand48 (xsubi) + unsigned short int xsubi[3]; +{ + long int result; + + (void) __nrand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/nrand48_r.c b/src/kernel/libroot/posix/glibc/stdlib/nrand48_r.c new file mode 100644 index 0000000000..dbc50bb397 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/nrand48_r.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +__nrand48_r (xsubi, buffer, result) + unsigned short int xsubi[3]; + struct drand48_data *buffer; + long int *result; +{ + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Store the result. */ + if (sizeof (unsigned short int) == 2) + *result = xsubi[2] << 15 | xsubi[1] >> 1; + else + *result = xsubi[2] >> 1; + + return 0; +} +weak_alias (__nrand48_r, nrand48_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/old_atexit.c b/src/kernel/libroot/posix/glibc/stdlib/old_atexit.c new file mode 100644 index 0000000000..45f330bec8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/old_atexit.c @@ -0,0 +1,8 @@ +#include + +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2_2) +# define atexit __dyn_atexit +# include "atexit.c" +# undef atexit +compat_symbol (libc, __dyn_atexit, atexit, GLIBC_2_0); +#endif diff --git a/src/kernel/libroot/posix/glibc/stdlib/on_exit.c b/src/kernel/libroot/posix/glibc/stdlib/on_exit.c new file mode 100644 index 0000000000..d98fbb3a86 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/on_exit.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "exit.h" + +/* Register a function to be called by exit. */ +int +__on_exit (void (*func) (int status, void *arg), void *arg) +{ + struct exit_function *new = __new_exitfn (); + + if (new == NULL) + return -1; + + new->flavor = ef_on; + new->func.on.fn = func; + new->func.on.arg = arg; + return 0; +} +weak_alias (__on_exit, on_exit) diff --git a/src/kernel/libroot/posix/glibc/stdlib/qsort.c b/src/kernel/libroot/posix/glibc/stdlib/qsort.c new file mode 100644 index 0000000000..1ac268bec9 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/qsort.c @@ -0,0 +1,248 @@ +/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Douglas C. Schmidt (schmidt@ics.uci.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* If you consider tuning this algorithm, you should consult first: + Engineering a sort function; Jon Bentley and M. Douglas McIlroy; + Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */ + +#include +#include +#include +#include + +/* Byte-wise swap two items of size SIZE. */ +#define SWAP(a, b, size) \ + do \ + { \ + register size_t __size = (size); \ + register char *__a = (a), *__b = (b); \ + do \ + { \ + char __tmp = *__a; \ + *__a++ = *__b; \ + *__b++ = __tmp; \ + } while (--__size > 0); \ + } while (0) + +/* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sun 4/260. */ +#define MAX_THRESH 4 + +/* Stack node declarations used to store unfulfilled partition obligations. */ +typedef struct + { + char *lo; + char *hi; + } stack_node; + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +/* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type size_t, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(size_t). */ +#define STACK_SIZE (CHAR_BIT * sizeof(size_t)) +#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top)) +#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi))) +#define STACK_NOT_EMPTY (stack < top) + + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + +void +_quicksort (void *const pbase, size_t total_elems, size_t size, + __compar_fn_t cmp) +{ + register char *base_ptr = (char *) pbase; + + const size_t max_thresh = MAX_THRESH * size; + + if (total_elems == 0) + /* Avoid lossage with unsigned arithmetic below. */ + return; + + if (total_elems > MAX_THRESH) + { + char *lo = base_ptr; + char *hi = &lo[size * (total_elems - 1)]; + stack_node stack[STACK_SIZE]; + stack_node *top = stack + 1; + + while (STACK_NOT_EMPTY) + { + char *left_ptr; + char *right_ptr; + + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR in + the while loops. */ + + char *mid = lo + size * ((hi - lo) / size >> 1); + + if ((*cmp) ((void *) mid, (void *) lo) < 0) + SWAP (mid, lo, size); + if ((*cmp) ((void *) hi, (void *) mid) < 0) + SWAP (mid, hi, size); + else + goto jump_over; + if ((*cmp) ((void *) mid, (void *) lo) < 0) + SWAP (mid, lo, size); + jump_over:; + + left_ptr = lo + size; + right_ptr = hi - size; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do + { + while ((*cmp) ((void *) left_ptr, (void *) mid) < 0) + left_ptr += size; + + while ((*cmp) ((void *) mid, (void *) right_ptr) < 0) + right_ptr -= size; + + if (left_ptr < right_ptr) + { + SWAP (left_ptr, right_ptr, size); + if (mid == left_ptr) + mid = right_ptr; + else if (mid == right_ptr) + mid = left_ptr; + left_ptr += size; + right_ptr -= size; + } + else if (left_ptr == right_ptr) + { + left_ptr += size; + right_ptr -= size; + break; + } + } + while (left_ptr <= right_ptr); + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if ((size_t) (right_ptr - lo) <= max_thresh) + { + if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore both small partitions. */ + POP (lo, hi); + else + /* Ignore small left partition. */ + lo = left_ptr; + } + else if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore small right partition. */ + hi = right_ptr; + else if ((right_ptr - lo) > (hi - left_ptr)) + { + /* Push larger left partition indices. */ + PUSH (lo, right_ptr); + lo = left_ptr; + } + else + { + /* Push larger right partition indices. */ + PUSH (left_ptr, hi); + hi = right_ptr; + } + } + } + + /* Once the BASE_PTR array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE_PTR points to the beginning + of the array to sort, and END_PTR points at the very last element in + the array (*not* one beyond it!). */ + +#define min(x, y) ((x) < (y) ? (x) : (y)) + + { + char *const end_ptr = &base_ptr[size * (total_elems - 1)]; + char *tmp_ptr = base_ptr; + char *thresh = min(end_ptr, base_ptr + max_thresh); + register char *run_ptr; + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size) + if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0) + tmp_ptr = run_ptr; + + if (tmp_ptr != base_ptr) + SWAP (tmp_ptr, base_ptr, size); + + /* Insertion sort, running from left-hand-side up to right-hand-side. */ + + run_ptr = base_ptr + size; + while ((run_ptr += size) <= end_ptr) + { + tmp_ptr = run_ptr - size; + while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0) + tmp_ptr -= size; + + tmp_ptr += size; + if (tmp_ptr != run_ptr) + { + char *trav; + + trav = run_ptr + size; + while (--trav >= run_ptr) + { + char c = *trav; + char *hi, *lo; + + for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo) + *hi = *lo; + *hi = c; + } + } + } + } +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/rand.c b/src/kernel/libroot/posix/glibc/stdlib/rand.c new file mode 100644 index 0000000000..d8458da970 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/rand.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef rand + + +/* Return a random integer between 0 and RAND_MAX. */ +int +rand () +{ + return (int) __random (); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/rand_r.c b/src/kernel/libroot/posix/glibc/stdlib/rand_r.c new file mode 100644 index 0000000000..3d49c92de6 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/rand_r.c @@ -0,0 +1,49 @@ +/* Reentrant random function frm POSIX.1c. + Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* This algorithm is mentioned in the ISO C standard, here extended + for 32 bits. */ +int +rand_r (unsigned int *seed) +{ + unsigned int next = *seed; + int result; + + next *= 1103515245; + next += 12345; + result = (unsigned int) (next / 65536) % 2048; + + next *= 1103515245; + next += 12345; + result <<= 10; + result ^= (unsigned int) (next / 65536) % 1024; + + next *= 1103515245; + next += 12345; + result <<= 10; + result ^= (unsigned int) (next / 65536) % 1024; + + *seed = next; + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/random.c b/src/kernel/libroot/posix/glibc/stdlib/random.c new file mode 100644 index 0000000000..8a32ee7103 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/random.c @@ -0,0 +1,305 @@ +/* Copyright (C) 1995 Free Software Foundation + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * Rewritten to use reentrant functions by Ulrich Drepper, 1995. + */ + +/* + Copyright (C) 1983 Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE.*/ + +#include +#include +#include +#include + + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initialized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* For each of the currently supported random number generators, we have a + break value on the amount of state information (you need at least this many + bytes of state info to support this random number generator), a degree for + the polynomial (actually a trinomial) that the R.N.G. is based on, and + separation between the two lower order coefficients of the trinomial. */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + + +/* Initially, everything is set up as if from: + initstate(1, randtbl, 128); + Note that this initialization takes advantage of the fact that srandom + advances the front and rear pointers 10*rand_deg times, and hence the + rear pointer which starts at 0 will also end up at zero; thus the zeroth + element of the state information, which contains info about the current + position of the rear pointer is just + (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ + +static int32_t randtbl[DEG_3 + 1] = + { + TYPE_3, + + -1726662223, 379960547, 1735697613, 1040273694, 1313901226, + 1627687941, -179304937, -2073333483, 1780058412, -1989503057, + -615974602, 344556628, 939512070, -1249116260, 1507946756, + -812545463, 154635395, 1388815473, -1926676823, 525320961, + -1009028674, 968117788, -123449607, 1284210865, 435012392, + -2017506339, -911064859, -370259173, 1132637927, 1398500161, + -205601318, + }; + + +static struct random_data unsafe_state = + { +/* FPTR and RPTR are two pointers into the state info, a front and a rear + pointer. These two pointers are always rand_sep places aparts, as they + cycle through the state information. (Yes, this does mean we could get + away with just one pointer, but the code for random is more efficient + this way). The pointers are left positioned as they would be from the call: + initstate(1, randtbl, 128); + (The position of the rear pointer, rptr, is really 0 (as explained above + in the initialization of randtbl) because the state table pointer is set + to point to randtbl[1] (as explained below).) */ + + .fptr = &randtbl[SEP_3 + 1], + .rptr = &randtbl[1], + +/* The following things are the pointer to the state information table, + the type of the current generator, the degree of the current polynomial + being used, and the separation between the two pointers. + Note that for efficiency of random, we remember the first location of + the state information, not the zeroth. Hence it is valid to access + state[-1], which is used to store the type of the R.N.G. + Also, we remember the last location, since this is more efficient than + indexing every time to find the address of the last element to see if + the front and rear pointers have wrapped. */ + + .state = &randtbl[1], + + .rand_type = TYPE_3, + .rand_deg = DEG_3, + .rand_sep = SEP_3, + + .end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])] +}; + +/* POSIX.1c requires that there is mutual exclusion for the `rand' and + `srand' functions to prevent concurrent calls from modifying common + data. */ +__libc_lock_define_initialized (static, lock) + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ +void +__srandom (x) + unsigned int x; +{ + __libc_lock_lock (lock); + (void) __srandom_r (x, &unsafe_state); + __libc_lock_unlock (lock); +} + +weak_alias (__srandom, srandom) +weak_alias (__srandom, srand) + +/* Initialize the state information in the given array of N bytes for + future random number generation. Based on the number of bytes we + are given, and the break values for the different R.N.G.'s, we choose + the best (largest) one we can and set things up for it. srandom is + then called to initialize the state information. Note that on return + from srandom, we set state[-1] to be the type multiplexed with the current + value of the rear pointer; this is so successive calls to initstate won't + lose this information and will be able to restart with setstate. + Note: The first thing we do is save the current state, if any, just like + setstate so that it doesn't matter when initstate is called. + Returns a pointer to the old state. */ +char * +__initstate (seed, arg_state, n) + unsigned int seed; + char *arg_state; + size_t n; +{ + int32_t *ostate; + + __libc_lock_lock (lock); + + ostate = &unsafe_state.state[-1]; + + __initstate_r (seed, arg_state, n, &unsafe_state); + + __libc_lock_unlock (lock); + + return (char *) ostate; +} + +weak_alias (__initstate, initstate) + +/* Restore the state from the given state array. + Note: It is important that we also remember the locations of the pointers + in the current state information, and restore the locations of the pointers + from the old state information. This is done by multiplexing the pointer + location into the zeroth word of the state information. Note that due + to the order in which things are done, it is OK to call setstate with the + same state as the current state + Returns a pointer to the old state information. */ +char * +__setstate (arg_state) + char *arg_state; +{ + int32_t *ostate; + + __libc_lock_lock (lock); + + ostate = &unsafe_state.state[-1]; + + if (__setstate_r (arg_state, &unsafe_state) < 0) + ostate = NULL; + + __libc_lock_unlock (lock); + + return (char *) ostate; +} + +weak_alias (__setstate, setstate) + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all the other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +long int +__random () +{ + int32_t retval; + + __libc_lock_lock (lock); + + (void) __random_r (&unsafe_state, &retval); + + __libc_lock_unlock (lock); + + return retval; +} + +weak_alias (__random, random) diff --git a/src/kernel/libroot/posix/glibc/stdlib/random_r.c b/src/kernel/libroot/posix/glibc/stdlib/random_r.c new file mode 100644 index 0000000000..09677e6077 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/random_r.c @@ -0,0 +1,407 @@ +/* + Copyright (C) 1995 Free Software Foundation + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + Copyright (C) 1983 Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE.*/ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * Rewritten to be reentrant by Ulrich Drepper, 1995 + */ + +#include +#include +#include +#include + + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initialized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* For each of the currently supported random number generators, we have a + break value on the amount of state information (you need at least this many + bytes of state info to support this random number generator), a degree for + the polynomial (actually a trinomial) that the R.N.G. is based on, and + separation between the two lower order coefficients of the trinomial. */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + +struct random_poly_info +{ + int seps[MAX_TYPES]; + int degrees[MAX_TYPES]; +}; + +static const struct random_poly_info random_poly_info = +{ + { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }, + { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 } +}; + + + + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ +int +__srandom_r (seed, buf) + unsigned int seed; + struct random_data *buf; +{ + int type; + int32_t *state; + long int i; + long int word; + int32_t *dst; + int kc; + + if (buf == NULL) + goto fail; + type = buf->rand_type; + if ((unsigned int) type >= MAX_TYPES) + goto fail; + + state = buf->state; + /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ + if (seed == 0) + seed = 1; + state[0] = seed; + if (type == TYPE_0) + goto done; + + dst = state; + word = seed; + kc = buf->rand_deg; + for (i = 1; i < kc; ++i) + { + /* This does: + state[i] = (16807 * state[i - 1]) % 2147483647; + but avoids overflowing 31 bits. */ + long int hi = word / 127773; + long int lo = word % 127773; + word = 16807 * lo - 2836 * hi; + if (word < 0) + word += 2147483647; + *++dst = word; + } + + buf->fptr = &state[buf->rand_sep]; + buf->rptr = &state[0]; + kc *= 10; + while (--kc >= 0) + { + int32_t discard; + (void) __random_r (buf, &discard); + } + + done: + return 0; + + fail: + return -1; +} + +weak_alias (__srandom_r, srandom_r) + +/* Initialize the state information in the given array of N bytes for + future random number generation. Based on the number of bytes we + are given, and the break values for the different R.N.G.'s, we choose + the best (largest) one we can and set things up for it. srandom is + then called to initialize the state information. Note that on return + from srandom, we set state[-1] to be the type multiplexed with the current + value of the rear pointer; this is so successive calls to initstate won't + lose this information and will be able to restart with setstate. + Note: The first thing we do is save the current state, if any, just like + setstate so that it doesn't matter when initstate is called. + Returns a pointer to the old state. */ +int +__initstate_r (seed, arg_state, n, buf) + unsigned int seed; + char *arg_state; + size_t n; + struct random_data *buf; +{ + int type; + int degree; + int separation; + int32_t *state; + + if (buf == NULL) + goto fail; + + if (n >= BREAK_3) + type = n < BREAK_4 ? TYPE_3 : TYPE_4; + else if (n < BREAK_1) + { + if (n < BREAK_0) + { + __set_errno (EINVAL); + goto fail; + } + type = TYPE_0; + } + else + type = n < BREAK_2 ? TYPE_1 : TYPE_2; + + degree = random_poly_info.degrees[type]; + separation = random_poly_info.seps[type]; + + buf->rand_type = type; + buf->rand_sep = separation; + buf->rand_deg = degree; + state = &((int32_t *) arg_state)[1]; /* First location. */ + /* Must set END_PTR before srandom. */ + buf->end_ptr = &state[degree]; + + buf->state = state; + + __srandom_r (seed, buf); + + state[-1] = TYPE_0; + if (type != TYPE_0) + state[-1] = (buf->rptr - state) * MAX_TYPES + type; + + return 0; + + fail: + __set_errno (EINVAL); + return -1; +} + +weak_alias (__initstate_r, initstate_r) + +/* Restore the state from the given state array. + Note: It is important that we also remember the locations of the pointers + in the current state information, and restore the locations of the pointers + from the old state information. This is done by multiplexing the pointer + location into the zeroth word of the state information. Note that due + to the order in which things are done, it is OK to call setstate with the + same state as the current state + Returns a pointer to the old state information. */ +int +__setstate_r (arg_state, buf) + char *arg_state; + struct random_data *buf; +{ + int32_t *new_state = 1 + (int32_t *) arg_state; + int type; + int old_type; + int32_t *old_state; + int degree; + int separation; + + if (arg_state == NULL || buf == NULL) + goto fail; + + old_type = buf->rand_type; + old_state = buf->state; + if (old_type == TYPE_0) + old_state[-1] = TYPE_0; + else + old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; + + type = new_state[-1] % MAX_TYPES; + if (type < TYPE_0 || type > TYPE_4) + goto fail; + + buf->rand_deg = degree = random_poly_info.degrees[type]; + buf->rand_sep = separation = random_poly_info.seps[type]; + buf->rand_type = type; + + if (type != TYPE_0) + { + int rear = new_state[-1] / MAX_TYPES; + buf->rptr = &new_state[rear]; + buf->fptr = &new_state[(rear + separation) % degree]; + } + buf->state = new_state; + /* Set end_ptr too. */ + buf->end_ptr = &new_state[degree]; + + return 0; + + fail: + __set_errno (EINVAL); + return -1; +} + +weak_alias (__setstate_r, setstate_r) + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all the other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +int +__random_r (buf, result) + struct random_data *buf; + int32_t *result; +{ + int32_t *state; + + if (buf == NULL || result == NULL) + goto fail; + + state = buf->state; + + if (buf->rand_type == TYPE_0) + { + int32_t val = state[0]; + val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; + state[0] = val; + *result = val; + } + else + { + int32_t *fptr = buf->fptr; + int32_t *rptr = buf->rptr; + int32_t *end_ptr = buf->end_ptr; + int32_t val; + + val = *fptr += *rptr; + /* Chucking least random bit. */ + *result = (val >> 1) & 0x7fffffff; + ++fptr; + if (fptr >= end_ptr) + { + fptr = state; + ++rptr; + } + else + { + ++rptr; + if (rptr >= end_ptr) + rptr = state; + } + buf->fptr = fptr; + buf->rptr = rptr; + } + return 0; + + fail: + __set_errno (EINVAL); + return -1; +} + +weak_alias (__random_r, random_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/rpmatch.c b/src/kernel/libroot/posix/glibc/stdlib/rpmatch.c new file mode 100644 index 0000000000..f3cc520f8b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/rpmatch.c @@ -0,0 +1,64 @@ +/* Determine whether string value is affirmation or negative response + according to current locale's data. + This file is part of the GNU C Library. + Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int +rpmatch (response) + const char *response; +{ + /* Match against one of the response patterns, compiling the pattern + first if necessary. */ + auto inline int try (const int tag, const int match, const int nomatch, + const char **lastp, regex_t *re); + + inline int try (const int tag, const int match, const int nomatch, + const char **lastp, regex_t *re) + { + const char *pattern = nl_langinfo (tag); + if (pattern != *lastp) + { + /* The pattern has changed. */ + if (*lastp) + { + /* Free the old compiled pattern. */ + __regfree (re); + *lastp = NULL; + } + /* Compile the pattern and cache it for future runs. */ + if (__regcomp (re, pattern, REG_EXTENDED) != 0) + return -1; + *lastp = pattern; + } + + /* Try the pattern. */ + return __regexec (re, response, 0, NULL, 0) == 0 ? match : nomatch; + } + + /* We cache the response patterns and compiled regexps here. */ + static const char *yesexpr, *noexpr; + static regex_t yesre, nore; + + return (try (YESEXPR, 1, 0, &yesexpr, &yesre) ?: + try (NOEXPR, 0, -1, &noexpr, &nore)); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/secure-getenv.c b/src/kernel/libroot/posix/glibc/stdlib/secure-getenv.c new file mode 100644 index 0000000000..75a781b3d0 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/secure-getenv.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991, 1992, 1994, 1996, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Some programs and especially the libc itself have to be careful + what values to accept from the environment. This special version + checks for SUID or SGID first before doing any work. */ +char * +__secure_getenv (name) + const char *name; +{ + return __libc_enable_secure ? NULL : getenv (name); +} +libc_hidden_def (__secure_getenv) diff --git a/src/kernel/libroot/posix/glibc/stdlib/seed48.c b/src/kernel/libroot/posix/glibc/stdlib/seed48.c new file mode 100644 index 0000000000..7b23d2fba9 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/seed48.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +unsigned short int * +seed48 (seed16v) + unsigned short int seed16v[3]; +{ + (void) __seed48_r (seed16v, &__libc_drand48_data); + + return __libc_drand48_data.__old_x; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/seed48_r.c b/src/kernel/libroot/posix/glibc/stdlib/seed48_r.c new file mode 100644 index 0000000000..4644ff2440 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/seed48_r.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +__seed48_r (seed16v, buffer) + unsigned short int seed16v[3]; + struct drand48_data *buffer; +{ + /* Save old value at a private place to be used as return value. */ + memcpy (buffer->__old_x, buffer->__x, sizeof (buffer->__x)); + + /* Install new state. */ + buffer->__x[2] = seed16v[2]; + buffer->__x[1] = seed16v[1]; + buffer->__x[0] = seed16v[0]; + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + + return 0; +} +weak_alias (__seed48_r, seed48_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/srand48.c b/src/kernel/libroot/posix/glibc/stdlib/srand48.c new file mode 100644 index 0000000000..c8ea919877 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/srand48.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +void +srand48 (seedval) + long seedval; +{ + (void) __srand48_r (seedval, &__libc_drand48_data); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/srand48_r.c b/src/kernel/libroot/posix/glibc/stdlib/srand48_r.c new file mode 100644 index 0000000000..17be9b41e8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/srand48_r.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +__srand48_r (seedval, buffer) + long int seedval; + struct drand48_data *buffer; +{ + /* The standards say we only have 32 bits. */ + if (sizeof (long int) > 4) + seedval &= 0xffffffffl; + + buffer->__x[2] = seedval >> 16; + buffer->__x[1] = seedval & 0xffffl; + buffer->__x[0] = 0x330e; + + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + + return 0; +} +weak_alias (__srand48_r, srand48_r) diff --git a/src/kernel/libroot/posix/glibc/stdlib/stdlib.h b/src/kernel/libroot/posix/glibc/stdlib/stdlib.h new file mode 100644 index 0000000000..275f34a83b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/stdlib.h @@ -0,0 +1,919 @@ +/* Copyright (C) 1991-99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.20 General utilities + */ + +#ifndef _STDLIB_H + +#include + +/* Get size_t, wchar_t and NULL from . */ +#define __need_size_t +#ifndef __need_malloc_and_calloc +# define __need_wchar_t +# define __need_NULL +#endif +#include +#include + +__BEGIN_DECLS + +#ifndef __need_malloc_and_calloc +#define _STDLIB_H 1 + +#if defined __USE_XOPEN && !defined _SYS_WAIT_H +/* XPG requires a few symbols from being defined. */ +# include +# include + +# ifdef __USE_BSD + +/* Lots of hair to allow traditional BSD use of `union wait' + as well as POSIX.1 use of `int' for the status word. */ + +# if defined __GNUC__ && !defined __cplusplus +# define __WAIT_INT(status) \ + (__extension__ ({ union { __typeof(status) __in; int __i; } __u; \ + __u.__in = (status); __u.__i; })) +# else +# define __WAIT_INT(status) (*(int *) &(status)) +# endif + +/* This is the type of the argument to `wait'. The funky union + causes redeclarations with ether `int *' or `union wait *' to be + allowed without complaint. __WAIT_STATUS_DEFN is the type used in + the actual function definitions. */ + +# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus +# define __WAIT_STATUS void * +# define __WAIT_STATUS_DEFN void * +# else +/* This works in GCC 2.6.1 and later. */ +typedef union + { + union wait *__uptr; + int *__iptr; + } __WAIT_STATUS __attribute__ ((__transparent_union__)); +# define __WAIT_STATUS_DEFN int * +# endif + +# else /* Don't use BSD. */ + +# define __WAIT_INT(status) (status) +# define __WAIT_STATUS int * +# define __WAIT_STATUS_DEFN int * + +# endif /* Use BSD. */ + +/* Define the macros also would define this way. */ +# define WEXITSTATUS(status) __WEXITSTATUS(__WAIT_INT(status)) +# define WTERMSIG(status) __WTERMSIG(__WAIT_INT(status)) +# define WSTOPSIG(status) __WSTOPSIG(__WAIT_INT(status)) +# define WIFEXITED(status) __WIFEXITED(__WAIT_INT(status)) +# define WIFSIGNALED(status) __WIFSIGNALED(__WAIT_INT(status)) +# define WIFSTOPPED(status) __WIFSTOPPED(__WAIT_INT(status)) +#endif /* X/Open and not included. */ + +__BEGIN_NAMESPACE_STD +/* Returned by `div'. */ +typedef struct + { + int quot; /* Quotient. */ + int rem; /* Remainder. */ + } div_t; + +/* Returned by `ldiv'. */ +#ifndef __ldiv_t_defined +typedef struct + { + long int quot; /* Quotient. */ + long int rem; /* Remainder. */ + } ldiv_t; +# define __ldiv_t_defined 1 +#endif +__END_NAMESPACE_STD + +#if defined __USE_ISOC99 && !defined __lldiv_t_defined +__BEGIN_NAMESPACE_C99 +/* Returned by `lldiv'. */ +__extension__ typedef struct + { + long long int quot; /* Quotient. */ + long long int rem; /* Remainder. */ + } lldiv_t; +# define __lldiv_t_defined 1 +__END_NAMESPACE_C99 +#endif + + +/* The largest number rand will return (same as INT_MAX). */ +#define RAND_MAX 2147483647 + + +/* We define these the same for all machines. + Changes from this to the outside world should be done in `_exit'. */ +#define EXIT_FAILURE 1 /* Failing exit status. */ +#define EXIT_SUCCESS 0 /* Successful exit status. */ + + +/* Maximum length of a multibyte character in the current locale. */ +#define MB_CUR_MAX (__ctype_get_mb_cur_max ()) +extern size_t __ctype_get_mb_cur_max (void) __THROW; + + +__BEGIN_NAMESPACE_STD +/* Convert a string to a floating-point number. */ +extern double atof (__const char *__nptr) __THROW __attribute_pure__; +/* Convert a string to an integer. */ +extern int atoi (__const char *__nptr) __THROW __attribute_pure__; +/* Convert a string to a long integer. */ +extern long int atol (__const char *__nptr) __THROW __attribute_pure__; +__END_NAMESPACE_STD + +#if defined __USE_ISOC99 || (defined __GLIBC_HAVE_LONG_LONG && defined __USE_MISC) +__BEGIN_NAMESPACE_C99 +/* Convert a string to a long long integer. */ +__extension__ extern long long int atoll (__const char *__nptr) + __THROW __attribute_pure__; +__END_NAMESPACE_C99 +#endif + +__BEGIN_NAMESPACE_STD +/* Convert a string to a floating-point number. */ +extern double strtod (__const char *__restrict __nptr, + char **__restrict __endptr) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Likewise for `float' and `long double' sizes of floating-point numbers. */ +extern float strtof (__const char *__restrict __nptr, + char **__restrict __endptr) __THROW; + +extern long double strtold (__const char *__restrict __nptr, + char **__restrict __endptr) __THROW; +__END_NAMESPACE_C99 +#endif + +__BEGIN_NAMESPACE_STD +/* Convert a string to a long integer. */ +extern long int strtol (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) __THROW; +/* Convert a string to an unsigned long integer. */ +extern unsigned long int strtoul (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW; +__END_NAMESPACE_C99 + +#if defined __GLIBC_HAVE_LONG_LONG && defined __USE_BSD +/* Convert a string to a quadword integer. */ +__extension__ +extern long long int strtoq (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) __THROW; +/* Convert a string to an unsigned quadword integer. */ +__extension__ +extern unsigned long long int strtouq (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW; +#endif /* GCC and use BSD. */ + +#if defined __USE_ISOC99 || (defined __GLIBC_HAVE_LONG_LONG && defined __USE_MISC) +__BEGIN_NAMESPACE_C99 +/* Convert a string to a quadword integer. */ +__extension__ +extern long long int strtoll (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) __THROW; +/* Convert a string to an unsigned quadword integer. */ +__extension__ +extern unsigned long long int strtoull (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW; +__END_NAMESPACE_C99 +#endif /* ISO C99 or GCC and use MISC. */ + + +#ifdef __USE_GNU +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* Special versions of the functions above which take the locale to + use as an additional parameter. */ +extern long int strtol_l (__const char *__restrict __nptr, + char **__restrict __endptr, int __base, + __locale_t __loc) __THROW; + +extern unsigned long int strtoul_l (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, __locale_t __loc) __THROW; + +__extension__ +extern long long int strtoll_l (__const char *__restrict __nptr, + char **__restrict __endptr, int __base, + __locale_t __loc) __THROW; + +__extension__ +extern unsigned long long int strtoull_l (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, __locale_t __loc) + __THROW; + +extern double strtod_l (__const char *__restrict __nptr, + char **__restrict __endptr, __locale_t __loc) + __THROW; + +extern float strtof_l (__const char *__restrict __nptr, + char **__restrict __endptr, __locale_t __loc) __THROW; + +extern long double strtold_l (__const char *__restrict __nptr, + char **__restrict __endptr, + __locale_t __loc) __THROW; +#endif /* GNU */ + + +/* The internal entry points for `strtoX' take an extra flag argument + saying whether or not to parse locale-dependent number grouping. */ + +extern double __strtod_internal (__const char *__restrict __nptr, + char **__restrict __endptr, int __group) + __THROW; +extern float __strtof_internal (__const char *__restrict __nptr, + char **__restrict __endptr, int __group) + __THROW; +extern long double __strtold_internal (__const char *__restrict __nptr, + char **__restrict __endptr, + int __group) __THROW; +#ifndef __strtol_internal_defined +extern long int __strtol_internal (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, int __group) __THROW; +# define __strtol_internal_defined 1 +#endif +#ifndef __strtoul_internal_defined +extern unsigned long int __strtoul_internal (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, int __group) __THROW; +# define __strtoul_internal_defined 1 +#endif +#if defined __GNUC__ || defined __USE_ISOC99 +# ifndef __strtoll_internal_defined +__extension__ +extern long long int __strtoll_internal (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, int __group) __THROW; +# define __strtoll_internal_defined 1 +# endif +# ifndef __strtoull_internal_defined +__extension__ +extern unsigned long long int __strtoull_internal (__const char * + __restrict __nptr, + char **__restrict __endptr, + int __base, int __group) + __THROW; +# define __strtoull_internal_defined 1 +# endif +#endif /* GCC */ + +#ifdef __USE_EXTERN_INLINES +/* Define inline functions which call the internal entry points. */ + +__BEGIN_NAMESPACE_STD +extern __inline double +strtod (__const char *__restrict __nptr, char **__restrict __endptr) __THROW +{ + return __strtod_internal (__nptr, __endptr, 0); +} +extern __inline long int +strtol (__const char *__restrict __nptr, char **__restrict __endptr, + int __base) __THROW +{ + return __strtol_internal (__nptr, __endptr, __base, 0); +} +extern __inline unsigned long int +strtoul (__const char *__restrict __nptr, char **__restrict __endptr, + int __base) __THROW +{ + return __strtoul_internal (__nptr, __endptr, __base, 0); +} +__END_NAMESPACE_STD + +# ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +extern __inline float +strtof (__const char *__restrict __nptr, char **__restrict __endptr) __THROW +{ + return __strtof_internal (__nptr, __endptr, 0); +} +extern __inline long double +strtold (__const char *__restrict __nptr, char **__restrict __endptr) __THROW +{ + return __strtold_internal (__nptr, __endptr, 0); +} +__END_NAMESPACE_C99 +# endif + +# ifdef __USE_BSD +__extension__ extern __inline long long int +strtoq (__const char *__restrict __nptr, char **__restrict __endptr, + int __base) __THROW +{ + return __strtoll_internal (__nptr, __endptr, __base, 0); +} +__extension__ extern __inline unsigned long long int +strtouq (__const char *__restrict __nptr, char **__restrict __endptr, + int __base) __THROW +{ + return __strtoull_internal (__nptr, __endptr, __base, 0); +} +# endif + +# if defined __USE_MISC || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +__extension__ extern __inline long long int +strtoll (__const char *__restrict __nptr, char **__restrict __endptr, + int __base) __THROW +{ + return __strtoll_internal (__nptr, __endptr, __base, 0); +} +__extension__ extern __inline unsigned long long int +strtoull (__const char * __restrict __nptr, char **__restrict __endptr, + int __base) __THROW +{ + return __strtoull_internal (__nptr, __endptr, __base, 0); +} +__END_NAMESPACE_C99 +# endif + +__BEGIN_NAMESPACE_STD +extern __inline double +atof (__const char *__nptr) __THROW +{ + return strtod (__nptr, (char **) NULL); +} +extern __inline int +atoi (__const char *__nptr) __THROW +{ + return (int) strtol (__nptr, (char **) NULL, 10); +} +extern __inline long int +atol (__const char *__nptr) __THROW +{ + return strtol (__nptr, (char **) NULL, 10); +} +__END_NAMESPACE_STD + +# if defined __USE_MISC || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +__extension__ extern __inline long long int +atoll (__const char *__nptr) __THROW +{ + return strtoll (__nptr, (char **) NULL, 10); +} +__END_NAMESPACE_C99 +# endif +#endif /* Optimizing and Inlining. */ + + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +/* Convert N to base 64 using the digits "./0-9A-Za-z", least-significant + digit first. Returns a pointer to static storage overwritten by the + next call. */ +extern char *l64a (long int __n) __THROW; + +/* Read a number from a string S in base 64 as above. */ +extern long int a64l (__const char *__s) __THROW __attribute_pure__; + +#endif /* Use SVID || extended X/Open. */ + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED || defined __USE_BSD +# include /* we need int32_t... */ + +/* These are the functions that actually do things. The `random', `srandom', + `initstate' and `setstate' functions are those from BSD Unices. + The `rand' and `srand' functions are required by the ANSI standard. + We provide both interfaces to the same random number generator. */ +/* Return a random long integer between 0 and RAND_MAX inclusive. */ +extern long int random (void) __THROW; + +/* Seed the random number generator with the given number. */ +extern void srandom (unsigned int __seed) __THROW; + +/* Initialize the random number generator to use state buffer STATEBUF, + of length STATELEN, and seed it with SEED. Optimal lengths are 8, 16, + 32, 64, 128 and 256, the bigger the better; values less than 8 will + cause an error and values greater than 256 will be rounded down. */ +extern char *initstate (unsigned int __seed, char *__statebuf, + size_t __statelen) __THROW; + +/* Switch the random number generator to state buffer STATEBUF, + which should have been previously initialized by `initstate'. */ +extern char *setstate (char *__statebuf) __THROW; + + +# ifdef __USE_MISC +/* Reentrant versions of the `random' family of functions. + These functions all use the following data structure to contain + state, rather than global state variables. */ + +struct random_data + { + int32_t *fptr; /* Front pointer. */ + int32_t *rptr; /* Rear pointer. */ + int32_t *state; /* Array of state values. */ + int rand_type; /* Type of random number generator. */ + int rand_deg; /* Degree of random number generator. */ + int rand_sep; /* Distance between front and rear. */ + int32_t *end_ptr; /* Pointer behind state table. */ + }; + +extern int random_r (struct random_data *__restrict __buf, + int32_t *__restrict __result) __THROW; + +extern int srandom_r (unsigned int __seed, struct random_data *__buf) __THROW; + +extern int initstate_r (unsigned int __seed, char *__restrict __statebuf, + size_t __statelen, + struct random_data *__restrict __buf) __THROW; + +extern int setstate_r (char *__restrict __statebuf, + struct random_data *__restrict __buf) __THROW; +# endif /* Use misc. */ +#endif /* Use SVID || extended X/Open || BSD. */ + + +__BEGIN_NAMESPACE_STD +/* Return a random integer between 0 and RAND_MAX inclusive. */ +extern int rand (void) __THROW; +/* Seed the random number generator with the given number. */ +extern void srand (unsigned int __seed) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_POSIX +/* Reentrant interface according to POSIX.1. */ +extern int rand_r (unsigned int *__seed) __THROW; +#endif + + +#if defined __USE_SVID || defined __USE_XOPEN +/* System V style 48-bit random number generator functions. */ + +/* Return non-negative, double-precision floating-point value in [0.0,1.0). */ +extern double drand48 (void) __THROW; +extern double erand48 (unsigned short int __xsubi[3]) __THROW; + +/* Return non-negative, long integer in [0,2^31). */ +extern long int lrand48 (void) __THROW; +extern long int nrand48 (unsigned short int __xsubi[3]) __THROW; + +/* Return signed, long integers in [-2^31,2^31). */ +extern long int mrand48 (void) __THROW; +extern long int jrand48 (unsigned short int __xsubi[3]) __THROW; + +/* Seed random number generator. */ +extern void srand48 (long int __seedval) __THROW; +extern unsigned short int *seed48 (unsigned short int __seed16v[3]) __THROW; +extern void lcong48 (unsigned short int __param[7]) __THROW; + +# ifdef __USE_MISC +/* Data structure for communication with thread safe versions. This + type is to be regarded as opaque. It's only exported because users + have to allocate objects of this type. */ +struct drand48_data + { + unsigned short int __x[3]; /* Current state. */ + unsigned short int __old_x[3]; /* Old state. */ + unsigned short int __c; /* Additive const. in congruential formula. */ + unsigned short int __init; /* Flag for initializing. */ + unsigned long long int __a; /* Factor in congruential formula. */ + }; + +/* Return non-negative, double-precision floating-point value in [0.0,1.0). */ +extern int drand48_r (struct drand48_data *__restrict __buffer, + double *__restrict __result) __THROW; +extern int erand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + double *__restrict __result) __THROW; + +/* Return non-negative, long integer in [0,2^31). */ +extern int lrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) __THROW; +extern int nrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) __THROW; + +/* Return signed, long integers in [-2^31,2^31). */ +extern int mrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) __THROW; +extern int jrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) __THROW; + +/* Seed random number generator. */ +extern int srand48_r (long int __seedval, struct drand48_data *__buffer) + __THROW; + +extern int seed48_r (unsigned short int __seed16v[3], + struct drand48_data *__buffer) __THROW; + +extern int lcong48_r (unsigned short int __param[7], + struct drand48_data *__buffer) __THROW; +# endif /* Use misc. */ +#endif /* Use SVID or X/Open. */ + +#endif /* don't just need malloc and calloc */ + +#ifndef __malloc_and_calloc_defined +# define __malloc_and_calloc_defined +__BEGIN_NAMESPACE_STD +/* Allocate SIZE bytes of memory. */ +extern void *malloc (size_t __size) __THROW __attribute_malloc__; +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern void *calloc (size_t __nmemb, size_t __size) + __THROW __attribute_malloc__; +__END_NAMESPACE_STD +#endif + +#ifndef __need_malloc_and_calloc +__BEGIN_NAMESPACE_STD +/* Re-allocate the previously allocated block + in PTR, making the new block SIZE bytes long. */ +extern void *realloc (void *__ptr, size_t __size) __THROW __attribute_malloc__; +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free (void *__ptr) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Free a block. An alias for `free'. (Sun Unices). */ +extern void cfree (void *__ptr) __THROW; +#endif /* Use misc. */ + +#if defined __USE_GNU || defined __USE_BSD || defined __USE_MISC +# include +#endif /* Use GNU, BSD, or misc. */ + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Allocate SIZE bytes on a page boundary. The storage cannot be freed. */ +extern void *valloc (size_t __size) __THROW __attribute_malloc__; +#endif + +#ifdef __USE_XOPEN2K +/* Allocate memory of SIZE bytes with an alignment of ALIGNMENT. */ +extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size) + __THROW __attribute_malloc__; +#endif + +__BEGIN_NAMESPACE_STD +/* Abort execution and generate a core-dump. */ +extern void abort (void) __THROW __attribute__ ((__noreturn__)); + + +/* Register a function to be called when `exit' is called. */ +extern int atexit (void (*__func) (void)) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Register a function to be called with the status + given to `exit' and the given argument. */ +extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg) + __THROW; +#endif + +__BEGIN_NAMESPACE_STD +/* Call all functions registered with `atexit' and `on_exit', + in the reverse of the order in which they were registered + perform stdio cleanup, and terminate program execution with STATUS. */ +extern void exit (int __status) __THROW __attribute__ ((__noreturn__)); +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Terminate the program with STATUS without calling any of the + functions registered with `atexit' or `on_exit'. */ +extern void _Exit (int __status) __THROW __attribute__ ((__noreturn__)); +__END_NAMESPACE_C99 +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the value of envariable NAME, or NULL if it doesn't exist. */ +extern char *getenv (__const char *__name) __THROW; +__END_NAMESPACE_STD + +/* This function is similar to the above but returns NULL if the + programs is running with SUID or SGID enabled. */ +extern char *__secure_getenv (__const char *__name) __THROW; + +#if defined __USE_SVID || defined __USE_XOPEN +/* The SVID says this is in , but this seems a better place. */ +/* Put STRING, which is of the form "NAME=VALUE", in the environment. + If there is no `=', remove NAME from the environment. */ +extern int putenv (char *__string) __THROW; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN2K +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. */ +extern int setenv (__const char *__name, __const char *__value, int __replace) + __THROW; + +/* Remove the variable NAME from the environment. */ +extern int unsetenv (__const char *__name) __THROW; +#endif + +#ifdef __USE_MISC +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +extern int clearenv (void) __THROW; +#endif + + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique file name. */ +extern char *mktemp (char *__template) __THROW; + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Returns a file descriptor open on the file for reading and writing, + or -1 if it cannot create a uniquely-named file. */ +# ifndef __USE_FILE_OFFSET64 +extern int mkstemp (char *__template) __THROW; +# else +# ifdef __REDIRECT +extern int __REDIRECT (mkstemp, (char *__template) __THROW, mkstemp64); +# else +# define mkstemp mkstemp64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int mkstemp64 (char *__template) __THROW; +# endif +#endif + +#ifdef __USE_BSD +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +extern char *mkdtemp (char *__template) __THROW; +#endif + + +__BEGIN_NAMESPACE_STD +/* Execute the given line as a shell command. */ +extern int system (__const char *__command) __THROW; +__END_NAMESPACE_STD + + +#ifdef __USE_GNU +/* Return a malloc'd string containing the canonical absolute name of the + named file. The last file name component need not exist, and may be a + symlink to a nonexistent file. */ +extern char *canonicalize_file_name (__const char *__name) __THROW; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Return the canonical absolute name of file NAME. The last file name + component need not exist, and may be a symlink to a nonexistent file. + If RESOLVED is null, the result is malloc'd; otherwise, if the canonical + name is PATH_MAX chars or more, returns null with `errno' set to + ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, returns the + name in RESOLVED. */ +extern char *realpath (__const char *__restrict __name, + char *__restrict __resolved) __THROW; +#endif + + +/* Shorthand for type of comparison functions. */ +#ifndef __COMPAR_FN_T +# define __COMPAR_FN_T +typedef int (*__compar_fn_t) (__const void *, __const void *); + +# ifdef __USE_GNU +typedef __compar_fn_t comparison_fn_t; +# endif +#endif + +__BEGIN_NAMESPACE_STD +/* Do a binary search for KEY in BASE, which consists of NMEMB elements + of SIZE bytes each, using COMPAR to perform the comparisons. */ +extern void *bsearch (__const void *__key, __const void *__base, + size_t __nmemb, size_t __size, __compar_fn_t __compar); + +/* Sort NMEMB elements of BASE, of SIZE bytes each, + using COMPAR to perform the comparisons. */ +extern void qsort (void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar); + + +/* Return the absolute value of X. */ +extern int abs (int __x) __THROW __attribute__ ((__const__)); +extern long int labs (long int __x) __THROW __attribute__ ((__const__)); +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__extension__ extern long long int llabs (long long int __x) + __THROW __attribute__ ((__const__)); +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the `div_t', `ldiv_t' or `lldiv_t' representation + of the value of NUMER over DENOM. */ +/* GCC may have built-ins for these someday. */ +extern div_t div (int __numer, int __denom) + __THROW __attribute__ ((__const__)); +extern ldiv_t ldiv (long int __numer, long int __denom) + __THROW __attribute__ ((__const__)); +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +__extension__ extern lldiv_t lldiv (long long int __numer, + long long int __denom) + __THROW __attribute__ ((__const__)); +__END_NAMESPACE_C99 +#endif + + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +/* Convert floating point numbers to strings. The returned values are + valid only until another call to the same function. */ + +/* Convert VALUE to a string with NDIGIT digits and return a pointer to + this. Set *DECPT with the position of the decimal character and *SIGN + with the sign of the number. */ +extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __THROW; + +/* Convert VALUE to a string rounded to NDIGIT decimal digits. Set *DECPT + with the position of the decimal character and *SIGN with the sign of + the number. */ +extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __THROW; + +/* If possible convert VALUE to a string with NDIGIT significant digits. + Otherwise use exponential representation. The resulting string will + be written to BUF. */ +extern char *gcvt (double __value, int __ndigit, char *__buf) __THROW; + + +# ifdef __USE_MISC +/* Long double versions of above functions. */ +extern char *qecvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) __THROW; +extern char *qfcvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) __THROW; +extern char *qgcvt (long double __value, int __ndigit, char *__buf) __THROW; + + +/* Reentrant version of the functions above which provide their own + buffers. */ +extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __THROW; +extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __THROW; + +extern int qecvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) __THROW; +extern int qfcvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) __THROW; +# endif /* misc */ +#endif /* use MISC || use X/Open Unix */ + + +__BEGIN_NAMESPACE_STD +/* Return the length of the multibyte character + in S, which is no longer than N. */ +extern int mblen (__const char *__s, size_t __n) __THROW; +/* Return the length of the given multibyte character, + putting its `wchar_t' representation in *PWC. */ +extern int mbtowc (wchar_t *__restrict __pwc, + __const char *__restrict __s, size_t __n) __THROW; +/* Put the multibyte character represented + by WCHAR in S, returning its length. */ +extern int wctomb (char *__s, wchar_t __wchar) __THROW; + + +/* Convert a multibyte string to a wide char string. */ +extern size_t mbstowcs (wchar_t *__restrict __pwcs, + __const char *__restrict __s, size_t __n) __THROW; +/* Convert a wide char string to multibyte string. */ +extern size_t wcstombs (char *__restrict __s, + __const wchar_t *__restrict __pwcs, size_t __n) + __THROW; +__END_NAMESPACE_STD + + +#ifdef __USE_SVID +/* Determine whether the string value of RESPONSE matches the affirmation + or negative response expression as specified by the LC_MESSAGES category + in the program's current locale. Returns 1 if affirmative, 0 if + negative, and -1 if not matching. */ +extern int rpmatch (__const char *__response) __THROW; +#endif + + +#ifdef __USE_XOPEN_EXTENDED +/* Parse comma separated suboption from *OPTIONP and match against + strings in TOKENS. If found return index and set *VALUEP to + optional value introduced by an equal sign. If the suboption is + not part of TOKENS return in *VALUEP beginning of unknown + suboption. On exit *OPTIONP is set to the beginning of the next + token or at the terminating NUL character. */ +extern int getsubopt (char **__restrict __optionp, + char *__const *__restrict __tokens, + char **__restrict __valuep) __THROW; +#endif + + +#ifdef __USE_XOPEN +/* Setup DES tables according KEY. */ +extern void setkey (__const char *__key) __THROW; +#endif + + +/* X/Open pseudo terminal handling. */ + +#ifdef __USE_XOPEN2K +/* Return a master pseudo-terminal handle. */ +extern int posix_openpt (int __oflag) __THROW; +#endif + +#ifdef __USE_XOPEN +/* The next four functions all take a master pseudo-tty fd and + perform an operation on the associated slave: */ + +/* Chown the slave to the calling user. */ +extern int grantpt (int __fd) __THROW; + +/* Release an internal lock so the slave can be opened. + Call after grantpt(). */ +extern int unlockpt (int __fd) __THROW; + +/* Return the pathname of the pseudo terminal slave assoicated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ +extern char *ptsname (int __fd) __THROW; +#endif + +#ifdef __USE_GNU +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ +extern int ptsname_r (int __fd, char *__buf, size_t __buflen) __THROW; + +/* Open a master pseudo terminal and return its file descriptor. */ +extern int getpt (void) __THROW; +#endif + +#ifdef __USE_BSD +/* Put the 1 minute, 5 minute and 15 minute load averages into the first + NELEM elements of LOADAVG. Return the number written (never more than + three, but may be less than NELEM), or -1 if an error occurred. */ +extern int getloadavg (double __loadavg[], int __nelem) __THROW; +#endif + +#endif /* don't just need malloc and calloc */ +#undef __need_malloc_and_calloc + +__END_DECLS + +#endif /* stdlib.h */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/strfmon.c b/src/kernel/libroot/posix/glibc/stdlib/strfmon.c new file mode 100644 index 0000000000..e7183ec843 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/strfmon.c @@ -0,0 +1,657 @@ +/* Formatting a monetary value according to the current locale. + Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper + and Jochen Hein , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include "../libio/libioP.h" +# include "../libio/strfile.h" +#endif +#include +#include +#include +#include +#include "../locale/localeinfo.h" + + +#define out_char(Ch) \ + do { \ + if (dest >= s + maxsize - 1) \ + { \ + __set_errno (E2BIG); \ + va_end (ap); \ + return -1; \ + } \ + *dest++ = (Ch); \ + } while (0) + +#define out_string(String) \ + do { \ + const char *_s = (String); \ + while (*_s) \ + out_char (*_s++); \ + } while (0) + +#define out_nstring(String, N) \ + do { \ + int _n = (N); \ + const char *_s = (String); \ + while (_n-- > 0) \ + out_char (*_s++); \ + } while (0) + +#define to_digit(Ch) ((Ch) - '0') + + +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +#endif + +extern int __printf_fp (FILE *, const struct printf_info *, + const void *const *); +libc_hidden_proto (__printf_fp) +/* This function determines the number of digit groups in the output. + The definition is in printf_fp.c. */ +extern unsigned int __guess_grouping (unsigned int intdig_max, + const char *grouping, wchar_t sepchar); + + +/* We have to overcome some problems with this implementation. On the + one hand the strfmon() function is specified in XPG4 and of course + it has to follow this. But on the other hand POSIX.2 specifies + some information in the LC_MONETARY category which should be used, + too. Some of the information contradicts the information which can + be specified in format string. */ +#ifndef USE_IN_EXTENDED_LOCALE_MODEL +ssize_t +strfmon (char *s, size_t maxsize, const char *format, ...) +#else +ssize_t +__strfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format, ...) +#endif +{ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL + struct locale_data *current = loc->__locales[LC_MONETARY]; +#endif +#ifdef USE_IN_LIBIO + _IO_strfile f; +# ifdef _IO_MTSAFE_IO + _IO_lock_t lock; +# endif +#else + FILE f; +#endif + struct printf_info info; + va_list ap; /* Scan through the varargs. */ + char *dest; /* Pointer so copy the output. */ + const char *fmt; /* Pointer that walks through format. */ + + va_start (ap, format); + + dest = s; + fmt = format; + + /* Loop through the format-string. */ + while (*fmt != '\0') + { + /* The floating-point value to output. */ + union + { + double dbl; + __long_double_t ldbl; + } + fpnum; + int print_curr_symbol; + int left_prec; + int left_pad; + int right_prec; + int group; + char pad; + int is_long_double; + int p_sign_posn; + int n_sign_posn; + int sign_posn; + int other_sign_posn; + int left; + int is_negative; + int sep_by_space; + int other_sep_by_space; + int cs_precedes; + int other_cs_precedes; + const char *sign_string; + const char *other_sign_string; + int done; + const char *currency_symbol; + size_t currency_symbol_len; + int width; + char *startp; + const void *ptr; + char space_char; + + /* Process all character which do not introduce a format + specification. */ + if (*fmt != '%') + { + out_char (*fmt++); + continue; + } + + /* "%%" means a single '%' character. */ + if (fmt[1] == '%') + { + out_char (*++fmt); + ++fmt; + continue; + } + + /* Defaults for formatting. */ + print_curr_symbol = 1; /* Print the currency symbol. */ + left_prec = -1; /* No left precision specified. */ + right_prec = -1; /* No right precision specified. */ + group = 1; /* Print digits grouped. */ + pad = ' '; /* Fill character is . */ + is_long_double = 0; /* Double argument by default. */ + p_sign_posn = -1; /* This indicates whether the */ + n_sign_posn = -1; /* '(' flag is given. */ + width = -1; /* No width specified so far. */ + left = 0; /* Right justified by default. */ + + /* Parse group characters. */ + while (1) + { + switch (*++fmt) + { + case '=': /* Set fill character. */ + pad = *++fmt; + if (pad == '\0') + { + /* Premature EOS. */ + __set_errno (EINVAL); + va_end (ap); + return -1; + } + continue; + case '^': /* Don't group digits. */ + group = 0; + continue; + case '+': /* Use +/- for sign of number. */ + if (n_sign_posn != -1) + { + __set_errno (EINVAL); + va_end (ap); + return -1; + } + p_sign_posn = *_NL_CURRENT (LC_MONETARY, P_SIGN_POSN); + n_sign_posn = *_NL_CURRENT (LC_MONETARY, N_SIGN_POSN); + continue; + case '(': /* Use ( ) for negative sign. */ + if (n_sign_posn != -1) + { + __set_errno (EINVAL); + va_end (ap); + return -1; + } + p_sign_posn = 0; + n_sign_posn = 0; + continue; + case '!': /* Don't print the currency symbol. */ + print_curr_symbol = 0; + continue; + case '-': /* Print left justified. */ + left = 1; + continue; + default: + /* Will stop the loop. */; + } + break; + } + + /* If not specified by the format string now find the values for + the format specification. */ + if (p_sign_posn == -1) + p_sign_posn = *_NL_CURRENT (LC_MONETARY, P_SIGN_POSN); + if (n_sign_posn == -1) + n_sign_posn = *_NL_CURRENT (LC_MONETARY, N_SIGN_POSN); + + if (isdigit (*fmt)) + { + /* Parse field width. */ + width = to_digit (*fmt); + + while (isdigit (*++fmt)) + { + width *= 10; + width += to_digit (*fmt); + } + + /* If we don't have enough room for the demanded width we + can stop now and return an error. */ + if (dest + width >= s + maxsize) + { + __set_errno (E2BIG); + va_end (ap); + return -1; + } + } + + /* Recognize left precision. */ + if (*fmt == '#') + { + if (!isdigit (*++fmt)) + { + __set_errno (EINVAL); + va_end (ap); + return -1; + } + left_prec = to_digit (*fmt); + + while (isdigit (*++fmt)) + { + left_prec *= 10; + left_prec += to_digit (*fmt); + } + } + + /* Recognize right precision. */ + if (*fmt == '.') + { + if (!isdigit (*++fmt)) + { + __set_errno (EINVAL); + va_end (ap); + return -1; + } + right_prec = to_digit (*fmt); + + while (isdigit (*++fmt)) + { + right_prec *= 10; + right_prec += to_digit (*fmt); + } + } + + /* Handle modifier. This is an extension. */ + if (*fmt == 'L') + { + ++fmt; + is_long_double = 1; + } + + /* Handle format specifier. */ + switch (*fmt++) + { + case 'i': /* Use international currency symbol. */ + currency_symbol = _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL); + currency_symbol_len = 3; + space_char = currency_symbol[3]; + if (right_prec == -1) + { + if (*_NL_CURRENT (LC_MONETARY, INT_FRAC_DIGITS) == CHAR_MAX) + right_prec = 2; + else + right_prec = *_NL_CURRENT (LC_MONETARY, INT_FRAC_DIGITS); + } + break; + case 'n': /* Use national currency symbol. */ + currency_symbol = _NL_CURRENT (LC_MONETARY, CURRENCY_SYMBOL); + currency_symbol_len = strlen (currency_symbol); + space_char = ' '; + if (right_prec == -1) + { + if (*_NL_CURRENT (LC_MONETARY, FRAC_DIGITS) == CHAR_MAX) + right_prec = 2; + else + right_prec = *_NL_CURRENT (LC_MONETARY, FRAC_DIGITS); + } + break; + default: /* Any unrecognized format is an error. */ + __set_errno (EINVAL); + va_end (ap); + return -1; + } + + /* If we have to print the digits grouped determine how many + extra characters this means. */ + if (group && left_prec != -1) + left_prec += __guess_grouping (left_prec, + _NL_CURRENT (LC_MONETARY, MON_GROUPING), + *_NL_CURRENT (LC_MONETARY, + MON_THOUSANDS_SEP)); + + /* Now it's time to get the value. */ + if (is_long_double == 1) + { + fpnum.ldbl = va_arg (ap, long double); + is_negative = fpnum.ldbl < 0; + if (is_negative) + fpnum.ldbl = -fpnum.ldbl; + } + else + { + fpnum.dbl = va_arg (ap, double); + is_negative = fpnum.dbl < 0; + if (is_negative) + fpnum.dbl = -fpnum.dbl; + } + + /* We now know the sign of the value and can determine the format. */ + if (is_negative) + { + sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN); + /* If the locale does not specify a character for the + negative sign we use a '-'. */ + if (*sign_string == '\0') + sign_string = (const char *) "-"; + cs_precedes = *_NL_CURRENT (LC_MONETARY, N_CS_PRECEDES); + sep_by_space = *_NL_CURRENT (LC_MONETARY, N_SEP_BY_SPACE); + sign_posn = n_sign_posn; + + other_sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN); + other_cs_precedes = *_NL_CURRENT (LC_MONETARY, P_CS_PRECEDES); + other_sep_by_space = *_NL_CURRENT (LC_MONETARY, P_SEP_BY_SPACE); + other_sign_posn = p_sign_posn; + } + else + { + sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN); + cs_precedes = *_NL_CURRENT (LC_MONETARY, P_CS_PRECEDES); + sep_by_space = *_NL_CURRENT (LC_MONETARY, P_SEP_BY_SPACE); + sign_posn = p_sign_posn; + + other_sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN); + if (*other_sign_string == '\0') + other_sign_string = (const char *) "-"; + other_cs_precedes = *_NL_CURRENT (LC_MONETARY, N_CS_PRECEDES); + other_sep_by_space = *_NL_CURRENT (LC_MONETARY, N_SEP_BY_SPACE); + other_sign_posn = n_sign_posn; + } + + /* Set default values for unspecified information. */ + if (cs_precedes != 0) + cs_precedes = 1; + if (other_cs_precedes != 0) + other_cs_precedes = 1; + if (sep_by_space == CHAR_MAX) + sep_by_space = 0; + if (other_sep_by_space == CHAR_MAX) + other_sep_by_space = 0; + if (sign_posn == CHAR_MAX) + sign_posn = 1; + if (other_sign_posn == CHAR_MAX) + other_sign_posn = 1; + + /* Check for degenerate cases */ + if (sep_by_space == 2) + { + if (sign_posn == 0 || + (sign_posn == 1 && !cs_precedes) || + (sign_posn == 2 && cs_precedes)) + /* sign and symbol are not adjacent, so no separator */ + sep_by_space = 0; + } + if (other_sep_by_space == 2) + { + if (other_sign_posn == 0 || + (other_sign_posn == 1 && !other_cs_precedes) || + (other_sign_posn == 2 && other_cs_precedes)) + /* sign and symbol are not adjacent, so no separator */ + other_sep_by_space = 0; + } + + /* Set the left precision and padding needed for alignment */ + if (left_prec == -1) + { + left_prec = 0; + left_pad = 0; + } + else + { + /* Set left_pad to number of spaces needed to align positive + and negative formats */ + + int left_bytes = 0; + int other_left_bytes = 0; + + /* Work out number of bytes for currency string and separator + preceding the value */ + if (cs_precedes) + { + left_bytes += currency_symbol_len; + if (sep_by_space != 0) + ++left_bytes; + } + + if (other_cs_precedes) + { + other_left_bytes += currency_symbol_len; + if (other_sep_by_space != 0) + ++other_left_bytes; + } + + /* Work out number of bytes for the sign (or left parenthesis) + preceding the value */ + if (sign_posn == 0 && is_negative) + ++left_bytes; + else if (sign_posn == 1) + left_bytes += strlen (sign_string); + else if (cs_precedes && (sign_posn == 3 || sign_posn == 4)) + left_bytes += strlen (sign_string); + + if (other_sign_posn == 0 && !is_negative) + ++other_left_bytes; + else if (other_sign_posn == 1) + other_left_bytes += strlen (other_sign_string); + else if (other_cs_precedes && + (other_sign_posn == 3 || other_sign_posn == 4)) + other_left_bytes += strlen (other_sign_string); + + /* Compare the number of bytes preceding the value for + each format, and set the padding accordingly */ + if (other_left_bytes > left_bytes) + left_pad = other_left_bytes - left_bytes; + else + left_pad = 0; + } + + /* Perhaps we'll someday make these things configurable so + better start using symbolic names now. */ +#define left_paren '(' +#define right_paren ')' + + startp = dest; /* Remember start so we can compute length. */ + + while (left_pad-- > 0) + out_char (' '); + + if (sign_posn == 0 && is_negative) + out_char (left_paren); + + if (cs_precedes) + { + if (sign_posn != 0 && sign_posn != 2 && sign_posn != 4 + && sign_posn != 5) + { + out_string (sign_string); + if (sep_by_space == 2) + out_char (' '); + } + + if (print_curr_symbol) + { + out_string (currency_symbol); + + if (sign_posn == 4) + { + if (sep_by_space == 2) + out_char (space_char); + out_string (sign_string); + if (sep_by_space == 1) + /* POSIX.2 and SUS are not clear on this case, but C99 + says a space follows the adjacent-symbol-and-sign */ + out_char (' '); + } + else + if (sep_by_space == 1) + out_char (space_char); + } + } + else + if (sign_posn != 0 && sign_posn != 2 && sign_posn != 3 + && sign_posn != 4 && sign_posn != 5) + out_string (sign_string); + + /* Print the number. */ +#ifdef USE_IN_LIBIO +# ifdef _IO_MTSAFE_IO + f._sbf._f._lock = &lock; +# endif + INTUSE(_IO_init) ((_IO_FILE *) &f, 0); + _IO_JUMPS ((struct _IO_FILE_plus *) &f) = &_IO_str_jumps; + INTUSE(_IO_str_init_static) ((_IO_strfile *) &f, dest, + (s + maxsize) - dest, dest); +#else + memset ((void *) &f, 0, sizeof (f)); + f.__magic = _IOMAGIC; + f.__mode.__write = 1; + /* The buffer size is one less than MAXLEN + so we have space for the null terminator. */ + f.__bufp = f.__buffer = (char *) dest; + f.__bufsize = (s + maxsize) - dest; + f.__put_limit = f.__buffer + f.__bufsize; + f.__get_limit = f.__buffer; + /* After the buffer is full (MAXLEN characters have been written), + any more characters written will go to the bit bucket. */ + f.__room_funcs = __default_room_functions; + f.__io_funcs.__write = NULL; + f.__seen = 1; +#endif + /* We clear the last available byte so we can find out whether + the numeric representation is too long. */ + s[maxsize - 1] = '\0'; + + info.prec = right_prec; + info.width = left_prec + (right_prec ? (right_prec + 1) : 0); + info.spec = 'f'; + info.is_long_double = is_long_double; + info.is_short = 0; + info.is_long = 0; + info.alt = 0; + info.space = 0; + info.left = left; + info.showsign = 0; + info.group = group; + info.pad = pad; + info.extra = 1; /* This means use values from LC_MONETARY. */ + info.wide = 0; + + ptr = &fpnum; + done = __printf_fp ((FILE *) &f, &info, &ptr); + if (done < 0) + { + va_end (ap); + return -1; + } + + if (s[maxsize - 1] != '\0') + { + __set_errno (E2BIG); + return -1; + } + + dest += done; + + if (!cs_precedes) + { + if (sign_posn == 3) + { + if (sep_by_space == 1) + out_char (' '); + out_string (sign_string); + } + + if (print_curr_symbol) + { + if ((sign_posn == 3 && sep_by_space == 2) + || (sign_posn == 4 && sep_by_space == 1) + || (sign_posn == 2 && sep_by_space == 1) + || (sign_posn == 1 && sep_by_space == 1) + || (sign_posn == 0 && sep_by_space == 1)) + out_char (space_char); + out_nstring (currency_symbol, currency_symbol_len); + if (sign_posn == 4) + { + if (sep_by_space == 2) + out_char (' '); + out_string (sign_string); + } + } + } + + if (sign_posn == 2) + { + if (sep_by_space == 2) + out_char (' '); + out_string (sign_string); + } + + if (sign_posn == 0 && is_negative) + out_char (right_paren); + + /* Now test whether the output width is filled. */ + if (dest - startp < width) + { + if (left) + /* We simply have to fill using spaces. */ + do + out_char (' '); + while (dest - startp < width); + else + { + int dist = width - (dest - startp); + char *cp; + for (cp = dest - 1; cp >= startp; --cp) + cp[dist] = cp[0]; + + dest += dist; + + do + startp[--dist] = ' '; + while (dist > 0); + } + } + } + + /* Terminate the string. */ + *dest = '\0'; + + va_end (ap); + + return dest - s; +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/strfmon_l.c b/src/kernel/libroot/posix/glibc/stdlib/strfmon_l.c new file mode 100644 index 0000000000..b0c82a337e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/strfmon_l.c @@ -0,0 +1,24 @@ +/* Formatting a monetary value according to the given locale. + Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 +#include + +weak_alias (__strfmon_l, strfmon_l) diff --git a/src/kernel/libroot/posix/glibc/stdlib/strtod.c b/src/kernel/libroot/posix/glibc/stdlib/strtod.c new file mode 100644 index 0000000000..820307a0ec --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/strtod.c @@ -0,0 +1,1583 @@ +/* Read decimal floating point numbers. + This file is part of the GNU C Library. + Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Configuration part. These macros are defined by `strtold.c', + `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the + `long double' and `float' versions of the reader. */ +#ifndef FLOAT +# define FLOAT double +# define FLT DBL +# ifdef USE_WIDE_CHAR +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __wcstod_l +# else +# define STRTOF wcstod +# endif +# else +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __strtod_l +# else +# define STRTOF strtod +# endif +# endif +# define MPN2FLOAT __mpn_construct_double +# define FLOAT_HUGE_VAL HUGE_VAL +# define SET_MANTISSA(flt, mant) \ + do { union ieee754_double u; \ + u.d = (flt); \ + if ((mant & 0xfffffffffffffULL) == 0) \ + mant = 0x8000000000000ULL; \ + u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ + u.ieee.mantissa1 = (mant) & 0xffffffff; \ + (flt) = u.d; \ + } while (0) +#endif +/* End of configuration part. */ + +#include +#include +#include +#include +#include "../locale/localeinfo.h" +#include +#include +#include +#include + +/* The gmp headers need some configuration frobs. */ +#define HAVE_ALLOCA 1 + +/* Include gmp-mparam.h first, such that definitions of _SHORT_LIMB + and _LONG_LONG_LIMB in it can take effect into gmp.h. */ +#include +#include +#include +#include +#include "fpioconst.h" + +#define NDEBUG 1 +#include + + +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_DECL __locale_t loc; +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_DECL +#endif + +#if defined _LIBC || defined HAVE_WCHAR_H +# include +#endif + +#ifdef USE_WIDE_CHAR +# include +# define STRING_TYPE wchar_t +# define CHAR_TYPE wint_t +# define L_(Ch) L##Ch +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __iswspace_l ((Ch), loc) +# define ISDIGIT(Ch) __iswdigit_l ((Ch), loc) +# define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc) +# define TOLOWER(Ch) __towlower_l ((Ch), loc) +# define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc) +# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) +# else +# define ISSPACE(Ch) iswspace (Ch) +# define ISDIGIT(Ch) iswdigit (Ch) +# define ISXDIGIT(Ch) iswxdigit (Ch) +# define TOLOWER(Ch) towlower (Ch) +# define STRNCASECMP(S1, S2, N) __wcsncasecmp ((S1), (S2), (N)) +# define STRTOULL(S, E, B) __wcstoull_internal ((S), (E), (B), 0) +# endif +#else +# define STRING_TYPE char +# define CHAR_TYPE char +# define L_(Ch) Ch +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __isspace_l ((Ch), loc) +# define ISDIGIT(Ch) __isdigit_l ((Ch), loc) +# define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc) +# define TOLOWER(Ch) __tolower_l ((Ch), loc) +# define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc) +# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) +# else +# define ISSPACE(Ch) isspace (Ch) +# define ISDIGIT(Ch) isdigit (Ch) +# define ISXDIGIT(Ch) isxdigit (Ch) +# define TOLOWER(Ch) tolower (Ch) +# define STRNCASECMP(S1, S2, N) __strncasecmp ((S1), (S2), (N)) +# define STRTOULL(S, E, B) __strtoull_internal ((S), (E), 0, (B)) +# endif +#endif + + +/* Constants we need from float.h; select the set for the FLOAT precision. */ +#define MANT_DIG PASTE(FLT,_MANT_DIG) +#define DIG PASTE(FLT,_DIG) +#define MAX_EXP PASTE(FLT,_MAX_EXP) +#define MIN_EXP PASTE(FLT,_MIN_EXP) +#define MAX_10_EXP PASTE(FLT,_MAX_10_EXP) +#define MIN_10_EXP PASTE(FLT,_MIN_10_EXP) + +/* Extra macros required to get FLT expanded before the pasting. */ +#define PASTE(a,b) PASTE1(a,b) +#define PASTE1(a,b) a##b + +/* Function to construct a floating point number from an MP integer + containing the fraction bits, a base 2 exponent, and a sign flag. */ +extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative); + +/* Definitions according to limb size used. */ +#if BITS_PER_MP_LIMB == 32 +# define MAX_DIG_PER_LIMB 9 +# define MAX_FAC_PER_LIMB 1000000000UL +#elif BITS_PER_MP_LIMB == 64 +# define MAX_DIG_PER_LIMB 19 +# define MAX_FAC_PER_LIMB 10000000000000000000ULL +#else +# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for" +#endif + + +/* Local data structure. */ +static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] = +{ 0, 10, 100, + 1000, 10000, 100000L, + 1000000L, 10000000L, 100000000L, + 1000000000L +#if BITS_PER_MP_LIMB > 32 + , 10000000000ULL, 100000000000ULL, + 1000000000000ULL, 10000000000000ULL, 100000000000000ULL, + 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL, + 1000000000000000000ULL, 10000000000000000000ULL +#endif +#if BITS_PER_MP_LIMB > 64 + #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB +#endif +}; + +#ifndef howmany +#define howmany(x,y) (((x)+((y)-1))/(y)) +#endif +#define SWAP(x, y) ({ typeof(x) _tmp = x; x = y; y = _tmp; }) + +#define NDIG (MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG) +#define HEXNDIG ((MAX_EXP - MIN_EXP + 7) / 8 + 2 * MANT_DIG) +#define RETURN_LIMB_SIZE howmany (MANT_DIG, BITS_PER_MP_LIMB) + +#define RETURN(val,end) \ + do { if (endptr != NULL) *endptr = (STRING_TYPE *) (end); \ + return val; } while (0) + +/* Maximum size necessary for mpn integers to hold floating point numbers. */ +#define MPNSIZE (howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \ + + 2) +/* Declare an mpn integer variable that big. */ +#define MPN_VAR(name) mp_limb_t name[MPNSIZE]; mp_size_t name##size +/* Copy an mpn integer value. */ +#define MPN_ASSIGN(dst, src) \ + memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t)) + + +/* Return a floating point number of the needed type according to the given + multi-precision number after possible rounding. */ +static inline FLOAT +round_and_return (mp_limb_t *retval, int exponent, int negative, + mp_limb_t round_limb, mp_size_t round_bit, int more_bits) +{ + if (exponent < MIN_EXP - 1) + { + mp_size_t shift = MIN_EXP - 1 - exponent; + + if (shift > MANT_DIG) + { + __set_errno (EDOM); + return 0.0; + } + + more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0; + if (shift == MANT_DIG) + /* This is a special case to handle the very seldom case where + the mantissa will be empty after the shift. */ + { + int i; + + round_limb = retval[RETURN_LIMB_SIZE - 1]; + round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB; + for (i = 0; i < RETURN_LIMB_SIZE; ++i) + more_bits |= retval[i] != 0; + MPN_ZERO (retval, RETURN_LIMB_SIZE); + } + else if (shift >= BITS_PER_MP_LIMB) + { + int i; + + round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB]; + round_bit = (shift - 1) % BITS_PER_MP_LIMB; + for (i = 0; i < (shift - 1) / BITS_PER_MP_LIMB; ++i) + more_bits |= retval[i] != 0; + more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) + != 0); + + (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB], + RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB), + shift % BITS_PER_MP_LIMB); + MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)], + shift / BITS_PER_MP_LIMB); + } + else if (shift > 0) + { + round_limb = retval[0]; + round_bit = shift - 1; + (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift); + } + /* This is a hook for the m68k long double format, where the + exponent bias is the same for normalized and denormalized + numbers. */ +#ifndef DENORM_EXP +# define DENORM_EXP (MIN_EXP - 2) +#endif + exponent = DENORM_EXP; + } + + if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0 + && (more_bits || (retval[0] & 1) != 0 + || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0)) + { + mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1); + + if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) || + ((MANT_DIG % BITS_PER_MP_LIMB) != 0 && + (retval[RETURN_LIMB_SIZE - 1] + & (((mp_limb_t) 1) << (MANT_DIG % BITS_PER_MP_LIMB))) != 0)) + { + ++exponent; + (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1); + retval[RETURN_LIMB_SIZE - 1] + |= ((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB); + } + else if (exponent == DENORM_EXP + && (retval[RETURN_LIMB_SIZE - 1] + & (((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB))) + != 0) + /* The number was denormalized but now normalized. */ + exponent = MIN_EXP - 1; + } + + if (exponent > MAX_EXP) + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + + return MPN2FLOAT (retval, exponent, negative); +} + + +/* Read a multi-precision integer starting at STR with exactly DIGCNT digits + into N. Return the size of the number limbs in NSIZE at the first + character od the string that is not part of the integer as the function + value. If the EXPONENT is small enough to be taken as an additional + factor for the resulting number (see code) multiply by it. */ +static inline const STRING_TYPE * +str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize, + int *exponent +#ifndef USE_WIDE_CHAR + , const char *decimal, size_t decimal_len, const char *thousands +#endif + + ) +{ + /* Number of digits for actual limb. */ + int cnt = 0; + mp_limb_t low = 0; + mp_limb_t start; + + *nsize = 0; + assert (digcnt > 0); + do + { + if (cnt == MAX_DIG_PER_LIMB) + { + if (*nsize == 0) + { + n[0] = low; + *nsize = 1; + } + else + { + mp_limb_t cy; + cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB); + cy += __mpn_add_1 (n, n, *nsize, low); + if (cy != 0) + { + n[*nsize] = cy; + ++(*nsize); + } + } + cnt = 0; + low = 0; + } + + /* There might be thousands separators or radix characters in + the string. But these all can be ignored because we know the + format of the number is correct and we have an exact number + of characters to read. */ +#ifdef USE_WIDE_CHAR + if (*str < L'0' || *str > L'9') + ++str; +#else + if (*str < '0' || *str > '9') + { + int inner = 0; + if (thousands != NULL && *str == *thousands + && ({ for (inner = 1; thousands[inner] != '\0'; ++inner) + if (thousands[inner] != str[inner]) + break; + thousands[inner] == '\0'; })) + str += inner; + else + str += decimal_len; + } +#endif + low = low * 10 + *str++ - L_('0'); + ++cnt; + } + while (--digcnt > 0); + + if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB) + { + low *= _tens_in_limb[*exponent]; + start = _tens_in_limb[cnt + *exponent]; + *exponent = 0; + } + else + start = _tens_in_limb[cnt]; + + if (*nsize == 0) + { + n[0] = low; + *nsize = 1; + } + else + { + mp_limb_t cy; + cy = __mpn_mul_1 (n, n, *nsize, start); + cy += __mpn_add_1 (n, n, *nsize, low); + if (cy != 0) + n[(*nsize)++] = cy; + } + + return str; +} + + +/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits + with the COUNT most significant bits of LIMB. + + Tege doesn't like this function so I have to write it here myself. :) + --drepper */ +static inline void +__mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count, + mp_limb_t limb) +{ + if (count == BITS_PER_MP_LIMB) + { + /* Optimize the case of shifting by exactly a word: + just copy words, with no actual bit-shifting. */ + mp_size_t i; + for (i = size - 1; i > 0; --i) + ptr[i] = ptr[i - 1]; + ptr[0] = limb; + } + else + { + (void) __mpn_lshift (ptr, ptr, size, count); + ptr[0] |= limb >> (BITS_PER_MP_LIMB - count); + } +} + + +#define INTERNAL(x) INTERNAL1(x) +#define INTERNAL1(x) __##x##_internal + +/* This file defines a function to check for correct grouping. */ +#include "grouping.h" + + +/* Return a floating point number with the value of the given string NPTR. + Set *ENDPTR to the character after the last used one. If the number is + smaller than the smallest representable number, set `errno' to ERANGE and + return 0.0. If the number is too big to be represented, set `errno' to + ERANGE and return HUGE_VAL with the appropriate sign. */ +FLOAT +INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM) + const STRING_TYPE *nptr; + STRING_TYPE **endptr; + int group; + LOCALE_PARAM_DECL +{ + int negative; /* The sign of the number. */ + MPN_VAR (num); /* MP representation of the number. */ + int exponent; /* Exponent of the number. */ + + /* Numbers starting `0X' or `0x' have to be processed with base 16. */ + int base = 10; + + /* When we have to compute fractional digits we form a fraction with a + second multi-precision number (and we sometimes need a second for + temporary results). */ + MPN_VAR (den); + + /* Representation for the return value. */ + mp_limb_t retval[RETURN_LIMB_SIZE]; + /* Number of bits currently in result value. */ + int bits; + + /* Running pointer after the last character processed in the string. */ + const STRING_TYPE *cp, *tp; + /* Start of significant part of the number. */ + const STRING_TYPE *startp, *start_of_digits; + /* Points at the character following the integer and fractional digits. */ + const STRING_TYPE *expp; + /* Total number of digit and number of digits in integer part. */ + int dig_no, int_no, lead_zero; + /* Contains the last character read. */ + CHAR_TYPE c; + +/* We should get wint_t from , but not all GCC versions define it + there. So define it ourselves if it remains undefined. */ +#ifndef _WINT_T + typedef unsigned int wint_t; +#endif + /* The radix character of the current locale. */ +#ifdef USE_WIDE_CHAR + wchar_t decimal; +#else + const char *decimal; + size_t decimal_len; +#endif + /* The thousands character of the current locale. */ +#ifdef USE_WIDE_CHAR + wchar_t thousands = L'\0'; +#else + const char *thousands = NULL; +#endif + /* The numeric grouping specification of the current locale, + in the format described in . */ + const char *grouping; + /* Used in several places. */ + int cnt; + +#ifdef USE_IN_EXTENDED_LOCALE_MODEL + struct locale_data *current = loc->__locales[LC_NUMERIC]; +#endif + + if (group) + { + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + if (*grouping <= 0 || *grouping == CHAR_MAX) + grouping = NULL; + else + { + /* Figure out the thousands separator character. */ +#ifdef USE_WIDE_CHAR + thousands = _NL_CURRENT_WORD (LC_NUMERIC, + _NL_NUMERIC_THOUSANDS_SEP_WC); + if (thousands == L'\0') + grouping = NULL; +#else + thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); + if (*thousands == '\0') + { + thousands = NULL; + grouping = NULL; + } +#endif + } + } + else + grouping = NULL; + + /* Find the locale's decimal point character. */ +#ifdef USE_WIDE_CHAR + decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); + assert (decimal != L'\0'); +# define decimal_len 1 +#else + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); + decimal_len = strlen (decimal); + assert (decimal_len > 0); +#endif + + /* Prepare number representation. */ + exponent = 0; + negative = 0; + bits = 0; + + /* Parse string to get maximal legal prefix. We need the number of + characters of the integer part, the fractional part and the exponent. */ + cp = nptr - 1; + /* Ignore leading white space. */ + do + c = *++cp; + while (ISSPACE (c)); + + /* Get sign of the result. */ + if (c == L_('-')) + { + negative = 1; + c = *++cp; + } + else if (c == L_('+')) + c = *++cp; + + /* Return 0.0 if no legal string is found. + No character is used even if a sign was found. */ +#ifdef USE_WIDE_CHAR + if (c == (wint_t) decimal + && (wint_t) cp[1] >= L'0' && (wint_t) cp[1] <= L'9') + { + /* We accept it. This funny construct is here only to indent + the code directly. */ + } +#else + for (cnt = 0; decimal[cnt] != '\0'; ++cnt) + if (cp[cnt] != decimal[cnt]) + break; + if (decimal[cnt] == '\0' && cp[1] >= '0' && cp[1] <= '9') + { + /* We accept it. This funny construct is here only to indent + the code directly. */ + } +#endif + else if (c < L_('0') || c > L_('9')) + { + /* Check for `INF' or `INFINITY'. */ + if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0) + { + /* Return +/- infinity. */ + if (endptr != NULL) + *endptr = (STRING_TYPE *) + (cp + (STRNCASECMP (cp + 3, L_("inity"), 5) == 0 + ? 8 : 3)); + + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + } + + if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0) + { + /* Return NaN. */ + FLOAT retval = NAN; + + cp += 3; + + /* Match `(n-char-sequence-digit)'. */ + if (*cp == L_('(')) + { + const STRING_TYPE *startp = cp; + do + ++cp; + while ((*cp >= L_('0') && *cp <= L_('9')) + || (TOLOWER (*cp) >= L_('a') && TOLOWER (*cp) <= L_('z')) + || *cp == L_('_')); + + if (*cp != L_(')')) + /* The closing brace is missing. Only match the NAN + part. */ + cp = startp; + else + { + /* This is a system-dependent way to specify the + bitmask used for the NaN. We expect it to be + a number which is put in the mantissa of the + number. */ + STRING_TYPE *endp; + unsigned long long int mant; + + mant = STRTOULL (startp + 1, &endp, 0); + if (endp == cp) + SET_MANTISSA (retval, mant); + } + } + + if (endptr != NULL) + *endptr = (STRING_TYPE *) cp; + + return retval; + } + + /* It is really a text we do not recognize. */ + RETURN (0.0, nptr); + } + + /* First look whether we are faced with a hexadecimal number. */ + if (c == L_('0') && TOLOWER (cp[1]) == L_('x')) + { + /* Okay, it is a hexa-decimal number. Remember this and skip + the characters. BTW: hexadecimal numbers must not be + grouped. */ + base = 16; + cp += 2; + c = *cp; + grouping = NULL; + } + + /* Record the start of the digits, in case we will check their grouping. */ + start_of_digits = startp = cp; + + /* Ignore leading zeroes. This helps us to avoid useless computations. */ +#ifdef USE_WIDE_CHAR + while (c == L'0' || ((wint_t) thousands != L'\0' && c == (wint_t) thousands)) + c = *++cp; +#else + if (thousands == NULL) + while (c == '0') + c = *++cp; + else + { + /* We also have the multibyte thousands string. */ + while (1) + { + if (c != '0') + { + for (cnt = 0; thousands[cnt] != '\0'; ++cnt) + if (c != thousands[cnt]) + break; + if (thousands[cnt] != '\0') + break; + } + c = *++cp; + } + } +#endif + + /* If no other digit but a '0' is found the result is 0.0. + Return current read pointer. */ + if ((c < L_('0') || c > L_('9')) + && (base == 16 && (c < (CHAR_TYPE) TOLOWER (L_('a')) + || c > (CHAR_TYPE) TOLOWER (L_('f')))) +#ifdef USE_WIDE_CHAR + && c != (wint_t) decimal +#else + && ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt) + if (decimal[cnt] != cp[cnt]) + break; + decimal[cnt] != '\0'; }) +#endif + && (base == 16 && (cp == start_of_digits + || (CHAR_TYPE) TOLOWER (c) != L_('p'))) + && (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e'))) + { + tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); + /* If TP is at the start of the digits, there was no correctly + grouped prefix of the string; so no number found. */ + RETURN (0.0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp); + } + + /* Remember first significant digit and read following characters until the + decimal point, exponent character or any non-FP number character. */ + startp = cp; + dig_no = 0; + while (1) + { + if ((c >= L_('0') && c <= L_('9')) + || (base == 16 && (wint_t) TOLOWER (c) >= L_('a') + && (wint_t) TOLOWER (c) <= L_('f'))) + ++dig_no; + else + { +#ifdef USE_WIDE_CHAR + if ((wint_t) thousands == L'\0' || c != (wint_t) thousands) + /* Not a digit or separator: end of the integer part. */ + break; +#else + if (thousands == NULL) + break; + else + { + for (cnt = 0; thousands[cnt] != '\0'; ++cnt) + if (thousands[cnt] != cp[cnt]) + break; + if (thousands[cnt] != '\0') + break; + } +#endif + } + c = *++cp; + } + + if (grouping && dig_no > 0) + { + /* Check the grouping of the digits. */ + tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); + if (cp != tp) + { + /* Less than the entire string was correctly grouped. */ + + if (tp == start_of_digits) + /* No valid group of numbers at all: no valid number. */ + RETURN (0.0, nptr); + + if (tp < startp) + /* The number is validly grouped, but consists + only of zeroes. The whole value is zero. */ + RETURN (0.0, tp); + + /* Recompute DIG_NO so we won't read more digits than + are properly grouped. */ + cp = tp; + dig_no = 0; + for (tp = startp; tp < cp; ++tp) + if (*tp >= L_('0') && *tp <= L_('9')) + ++dig_no; + + int_no = dig_no; + lead_zero = 0; + + goto number_parsed; + } + } + + /* We have the number digits in the integer part. Whether these are all or + any is really a fractional digit will be decided later. */ + int_no = dig_no; + lead_zero = int_no == 0 ? -1 : 0; + + /* Read the fractional digits. A special case are the 'american style' + numbers like `16.' i.e. with decimal but without trailing digits. */ + if ( +#ifdef USE_WIDE_CHAR + c == (wint_t) decimal +#else + ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt) + if (decimal[cnt] != cp[cnt]) + break; + decimal[cnt] == '\0'; }) +#endif + ) + { + cp += decimal_len; + c = *cp; + while ((c >= L_('0') && c <= L_('9')) || + (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f'))) + { + if (c != L_('0') && lead_zero == -1) + lead_zero = dig_no - int_no; + ++dig_no; + c = *++cp; + } + } + + /* Remember start of exponent (if any). */ + expp = cp; + + /* Read exponent. */ + if ((base == 16 && TOLOWER (c) == L_('p')) + || (base != 16 && TOLOWER (c) == L_('e'))) + { + int exp_negative = 0; + + c = *++cp; + if (c == L_('-')) + { + exp_negative = 1; + c = *++cp; + } + else if (c == L_('+')) + c = *++cp; + + if (c >= L_('0') && c <= L_('9')) + { + int exp_limit; + + /* Get the exponent limit. */ + if (base == 16) + exp_limit = (exp_negative ? + -MIN_EXP + MANT_DIG + 4 * int_no : + MAX_EXP - 4 * int_no + lead_zero); + else + exp_limit = (exp_negative ? + -MIN_10_EXP + MANT_DIG + int_no : + MAX_10_EXP - int_no + lead_zero); + + do + { + exponent *= 10; + + if (exponent > exp_limit) + /* The exponent is too large/small to represent a valid + number. */ + { + FLOAT result; + + /* We have to take care for special situation: a joker + might have written "0.0e100000" which is in fact + zero. */ + if (lead_zero == -1) + result = negative ? -0.0 : 0.0; + else + { + /* Overflow or underflow. */ + __set_errno (ERANGE); + result = (exp_negative ? 0.0 : + negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL); + } + + /* Accept all following digits as part of the exponent. */ + do + ++cp; + while (*cp >= L_('0') && *cp <= L_('9')); + + RETURN (result, cp); + /* NOTREACHED */ + } + + exponent += c - L_('0'); + c = *++cp; + } + while (c >= L_('0') && c <= L_('9')); + + if (exp_negative) + exponent = -exponent; + } + else + cp = expp; + } + + /* We don't want to have to work with trailing zeroes after the radix. */ + if (dig_no > int_no) + { + while (expp[-1] == L_('0')) + { + --expp; + --dig_no; + } + assert (dig_no >= int_no); + } + + if (dig_no == int_no && dig_no > 0 && exponent < 0) + do + { + while (expp[-1] < L_('0') || expp[-1] > L_('9')) + --expp; + + if (expp[-1] != L_('0')) + break; + + --expp; + --dig_no; + --int_no; + ++exponent; + } + while (dig_no > 0 && exponent < 0); + + number_parsed: + + /* The whole string is parsed. Store the address of the next character. */ + if (endptr) + *endptr = (STRING_TYPE *) cp; + + if (dig_no == 0) + return negative ? -0.0 : 0.0; + + if (lead_zero) + { + /* Find the decimal point */ +#ifdef USE_WIDE_CHAR + while (*startp != decimal) + ++startp; +#else + while (1) + { + if (*startp == decimal[0]) + { + for (cnt = 1; decimal[cnt] != '\0'; ++cnt) + if (decimal[cnt] != startp[cnt]) + break; + if (decimal[cnt] == '\0') + break; + } + ++startp; + } +#endif + startp += lead_zero + decimal_len; + exponent -= base == 16 ? 4 * lead_zero : lead_zero; + dig_no -= lead_zero; + } + + /* If the BASE is 16 we can use a simpler algorithm. */ + if (base == 16) + { + static const int nbits[16] = { 0, 1, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4 }; + int idx = (MANT_DIG - 1) / BITS_PER_MP_LIMB; + int pos = (MANT_DIG - 1) % BITS_PER_MP_LIMB; + mp_limb_t val; + + while (!ISXDIGIT (*startp)) + ++startp; + while (*startp == L_('0')) + ++startp; + if (ISDIGIT (*startp)) + val = *startp++ - L_('0'); + else + val = 10 + TOLOWER (*startp++) - L_('a'); + bits = nbits[val]; + /* We cannot have a leading zero. */ + assert (bits != 0); + + if (pos + 1 >= 4 || pos + 1 >= bits) + { + /* We don't have to care for wrapping. This is the normal + case so we add the first clause in the `if' expression as + an optimization. It is a compile-time constant and so does + not cost anything. */ + retval[idx] = val << (pos - bits + 1); + pos -= bits; + } + else + { + retval[idx--] = val >> (bits - pos - 1); + retval[idx] = val << (BITS_PER_MP_LIMB - (bits - pos - 1)); + pos = BITS_PER_MP_LIMB - 1 - (bits - pos - 1); + } + + /* Adjust the exponent for the bits we are shifting in. */ + exponent += bits - 1 + (int_no - 1) * 4; + + while (--dig_no > 0 && idx >= 0) + { + if (!ISXDIGIT (*startp)) + startp += decimal_len; + if (ISDIGIT (*startp)) + val = *startp++ - L_('0'); + else + val = 10 + TOLOWER (*startp++) - L_('a'); + + if (pos + 1 >= 4) + { + retval[idx] |= val << (pos - 4 + 1); + pos -= 4; + } + else + { + retval[idx--] |= val >> (4 - pos - 1); + val <<= BITS_PER_MP_LIMB - (4 - pos - 1); + if (idx < 0) + return round_and_return (retval, exponent, negative, val, + BITS_PER_MP_LIMB - 1, dig_no > 0); + + retval[idx] = val; + pos = BITS_PER_MP_LIMB - 1 - (4 - pos - 1); + } + } + + /* We ran out of digits. */ + MPN_ZERO (retval, idx); + + return round_and_return (retval, exponent, negative, 0, 0, 0); + } + + /* Now we have the number of digits in total and the integer digits as well + as the exponent and its sign. We can decide whether the read digits are + really integer digits or belong to the fractional part; i.e. we normalize + 123e-2 to 1.23. */ + { + register int incr = (exponent < 0 ? MAX (-int_no, exponent) + : MIN (dig_no - int_no, exponent)); + int_no += incr; + exponent -= incr; + } + + if (int_no + exponent > MAX_10_EXP + 1) + { + __set_errno (ERANGE); + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + } + + if (exponent < MIN_10_EXP - (DIG + 1)) + { + __set_errno (ERANGE); + return 0.0; + } + + if (int_no > 0) + { + /* Read the integer part as a multi-precision number to NUM. */ + startp = str_to_mpn (startp, int_no, num, &numsize, &exponent +#ifndef USE_WIDE_CHAR + , decimal, decimal_len, thousands +#endif + ); + + if (exponent > 0) + { + /* We now multiply the gained number by the given power of ten. */ + mp_limb_t *psrc = num; + mp_limb_t *pdest = den; + int expbit = 1; + const struct mp_power *ttab = &_fpioconst_pow10[0]; + + do + { + if ((exponent & expbit) != 0) + { + size_t size = ttab->arraysize - _FPIO_CONST_OFFSET; + mp_limb_t cy; + exponent ^= expbit; + + /* FIXME: not the whole multiplication has to be + done. If we have the needed number of bits we + only need the information whether more non-zero + bits follow. */ + if (numsize >= ttab->arraysize - _FPIO_CONST_OFFSET) + cy = __mpn_mul (pdest, psrc, numsize, + &__tens[ttab->arrayoff + + _FPIO_CONST_OFFSET], + size); + else + cy = __mpn_mul (pdest, &__tens[ttab->arrayoff + + _FPIO_CONST_OFFSET], + size, psrc, numsize); + numsize += size; + if (cy == 0) + --numsize; + (void) SWAP (psrc, pdest); + } + expbit <<= 1; + ++ttab; + } + while (exponent != 0); + + if (psrc == den) + memcpy (num, den, numsize * sizeof (mp_limb_t)); + } + + /* Determine how many bits of the result we already have. */ + count_leading_zeros (bits, num[numsize - 1]); + bits = numsize * BITS_PER_MP_LIMB - bits; + + /* Now we know the exponent of the number in base two. + Check it against the maximum possible exponent. */ + if (bits > MAX_EXP) + { + __set_errno (ERANGE); + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + } + + /* We have already the first BITS bits of the result. Together with + the information whether more non-zero bits follow this is enough + to determine the result. */ + if (bits > MANT_DIG) + { + int i; + const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB; + const mp_size_t least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB; + const mp_size_t round_idx = least_bit == 0 ? least_idx - 1 + : least_idx; + const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1 + : least_bit - 1; + + if (least_bit == 0) + memcpy (retval, &num[least_idx], + RETURN_LIMB_SIZE * sizeof (mp_limb_t)); + else + { + for (i = least_idx; i < numsize - 1; ++i) + retval[i - least_idx] = (num[i] >> least_bit) + | (num[i + 1] + << (BITS_PER_MP_LIMB - least_bit)); + if (i - least_idx < RETURN_LIMB_SIZE) + retval[RETURN_LIMB_SIZE - 1] = num[i] >> least_bit; + } + + /* Check whether any limb beside the ones in RETVAL are non-zero. */ + for (i = 0; num[i] == 0; ++i) + ; + + return round_and_return (retval, bits - 1, negative, + num[round_idx], round_bit, + int_no < dig_no || i < round_idx); + /* NOTREACHED */ + } + else if (dig_no == int_no) + { + const mp_size_t target_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB; + const mp_size_t is_bit = (bits - 1) % BITS_PER_MP_LIMB; + + if (target_bit == is_bit) + { + memcpy (&retval[RETURN_LIMB_SIZE - numsize], num, + numsize * sizeof (mp_limb_t)); + /* FIXME: the following loop can be avoided if we assume a + maximal MANT_DIG value. */ + MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize); + } + else if (target_bit > is_bit) + { + (void) __mpn_lshift (&retval[RETURN_LIMB_SIZE - numsize], + num, numsize, target_bit - is_bit); + /* FIXME: the following loop can be avoided if we assume a + maximal MANT_DIG value. */ + MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize); + } + else + { + mp_limb_t cy; + assert (numsize < RETURN_LIMB_SIZE); + + cy = __mpn_rshift (&retval[RETURN_LIMB_SIZE - numsize], + num, numsize, is_bit - target_bit); + retval[RETURN_LIMB_SIZE - numsize - 1] = cy; + /* FIXME: the following loop can be avoided if we assume a + maximal MANT_DIG value. */ + MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize - 1); + } + + return round_and_return (retval, bits - 1, negative, 0, 0, 0); + /* NOTREACHED */ + } + + /* Store the bits we already have. */ + memcpy (retval, num, numsize * sizeof (mp_limb_t)); +#if RETURN_LIMB_SIZE > 1 + if (numsize < RETURN_LIMB_SIZE) + retval[numsize] = 0; +#endif + } + + /* We have to compute at least some of the fractional digits. */ + { + /* We construct a fraction and the result of the division gives us + the needed digits. The denominator is 1.0 multiplied by the + exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and + 123e-6 gives 123 / 1000000. */ + + int expbit; + int neg_exp; + int more_bits; + mp_limb_t cy; + mp_limb_t *psrc = den; + mp_limb_t *pdest = num; + const struct mp_power *ttab = &_fpioconst_pow10[0]; + + assert (dig_no > int_no && exponent <= 0); + + + /* For the fractional part we need not process too many digits. One + decimal digits gives us log_2(10) ~ 3.32 bits. If we now compute + ceil(BITS / 3) =: N + digits we should have enough bits for the result. The remaining + decimal digits give us the information that more bits are following. + This can be used while rounding. (Two added as a safety margin.) */ + if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2) + { + dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2; + more_bits = 1; + } + else + more_bits = 0; + + neg_exp = dig_no - int_no - exponent; + + /* Construct the denominator. */ + densize = 0; + expbit = 1; + do + { + if ((neg_exp & expbit) != 0) + { + mp_limb_t cy; + neg_exp ^= expbit; + + if (densize == 0) + { + densize = ttab->arraysize - _FPIO_CONST_OFFSET; + memcpy (psrc, &__tens[ttab->arrayoff + _FPIO_CONST_OFFSET], + densize * sizeof (mp_limb_t)); + } + else + { + cy = __mpn_mul (pdest, &__tens[ttab->arrayoff + + _FPIO_CONST_OFFSET], + ttab->arraysize - _FPIO_CONST_OFFSET, + psrc, densize); + densize += ttab->arraysize - _FPIO_CONST_OFFSET; + if (cy == 0) + --densize; + (void) SWAP (psrc, pdest); + } + } + expbit <<= 1; + ++ttab; + } + while (neg_exp != 0); + + if (psrc == num) + memcpy (den, num, densize * sizeof (mp_limb_t)); + + /* Read the fractional digits from the string. */ + (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent +#ifndef USE_WIDE_CHAR + , decimal, decimal_len, thousands +#endif + ); + + /* We now have to shift both numbers so that the highest bit in the + denominator is set. In the same process we copy the numerator to + a high place in the array so that the division constructs the wanted + digits. This is done by a "quasi fix point" number representation. + + num: ddddddddddd . 0000000000000000000000 + |--- m ---| + den: ddddddddddd n >= m + |--- n ---| + */ + + count_leading_zeros (cnt, den[densize - 1]); + + if (cnt > 0) + { + /* Don't call `mpn_shift' with a count of zero since the specification + does not allow this. */ + (void) __mpn_lshift (den, den, densize, cnt); + cy = __mpn_lshift (num, num, numsize, cnt); + if (cy != 0) + num[numsize++] = cy; + } + + /* Now we are ready for the division. But it is not necessary to + do a full multi-precision division because we only need a small + number of bits for the result. So we do not use __mpn_divmod + here but instead do the division here by hand and stop whenever + the needed number of bits is reached. The code itself comes + from the GNU MP Library by Torbj\"orn Granlund. */ + + exponent = bits; + + switch (densize) + { + case 1: + { + mp_limb_t d, n, quot; + int used = 0; + + n = num[0]; + d = den[0]; + assert (numsize == 1 && n < d); + + do + { + udiv_qrnnd (quot, n, n, 0, d); + +#define got_limb \ + if (bits == 0) \ + { \ + register int cnt; \ + if (quot == 0) \ + cnt = BITS_PER_MP_LIMB; \ + else \ + count_leading_zeros (cnt, quot); \ + exponent -= cnt; \ + if (BITS_PER_MP_LIMB - cnt > MANT_DIG) \ + { \ + used = MANT_DIG + cnt; \ + retval[0] = quot >> (BITS_PER_MP_LIMB - used); \ + bits = MANT_DIG + 1; \ + } \ + else \ + { \ + /* Note that we only clear the second element. */ \ + /* The conditional is determined at compile time. */ \ + if (RETURN_LIMB_SIZE > 1) \ + retval[1] = 0; \ + retval[0] = quot; \ + bits = -cnt; \ + } \ + } \ + else if (bits + BITS_PER_MP_LIMB <= MANT_DIG) \ + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB, \ + quot); \ + else \ + { \ + used = MANT_DIG - bits; \ + if (used > 0) \ + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot); \ + } \ + bits += BITS_PER_MP_LIMB + + got_limb; + } + while (bits <= MANT_DIG); + + return round_and_return (retval, exponent - 1, negative, + quot, BITS_PER_MP_LIMB - 1 - used, + more_bits || n != 0); + } + case 2: + { + mp_limb_t d0, d1, n0, n1; + mp_limb_t quot = 0; + int used = 0; + + d0 = den[0]; + d1 = den[1]; + + if (numsize < densize) + { + if (num[0] >= d1) + { + /* The numerator of the number occupies fewer bits than + the denominator but the one limb is bigger than the + high limb of the numerator. */ + n1 = 0; + n0 = num[0]; + } + else + { + if (bits <= 0) + exponent -= BITS_PER_MP_LIMB; + else + { + if (bits + BITS_PER_MP_LIMB <= MANT_DIG) + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, + BITS_PER_MP_LIMB, 0); + else + { + used = MANT_DIG - bits; + if (used > 0) + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0); + } + bits += BITS_PER_MP_LIMB; + } + n1 = num[0]; + n0 = 0; + } + } + else + { + n1 = num[1]; + n0 = num[0]; + } + + while (bits <= MANT_DIG) + { + mp_limb_t r; + + if (n1 == d1) + { + /* QUOT should be either 111..111 or 111..110. We need + special treatment of this rare case as normal division + would give overflow. */ + quot = ~(mp_limb_t) 0; + + r = n0 + d1; + if (r < d1) /* Carry in the addition? */ + { + add_ssaaaa (n1, n0, r - d0, 0, 0, d0); + goto have_quot; + } + n1 = d0 - (d0 != 0); + n0 = -d0; + } + else + { + udiv_qrnnd (quot, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, quot); + } + + q_test: + if (n1 > r || (n1 == r && n0 > 0)) + { + /* The estimated QUOT was too large. */ + --quot; + + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if (r >= d1) /* If not carry, test QUOT again. */ + goto q_test; + } + sub_ddmmss (n1, n0, r, 0, n1, n0); + + have_quot: + got_limb; + } + + return round_and_return (retval, exponent - 1, negative, + quot, BITS_PER_MP_LIMB - 1 - used, + more_bits || n1 != 0 || n0 != 0); + } + default: + { + int i; + mp_limb_t cy, dX, d1, n0, n1; + mp_limb_t quot = 0; + int used = 0; + + dX = den[densize - 1]; + d1 = den[densize - 2]; + + /* The division does not work if the upper limb of the two-limb + numerator is greater than the denominator. */ + if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0) + num[numsize++] = 0; + + if (numsize < densize) + { + mp_size_t empty = densize - numsize; + + if (bits <= 0) + { + register int i; + for (i = numsize; i > 0; --i) + num[i + empty] = num[i - 1]; + MPN_ZERO (num, empty + 1); + exponent -= empty * BITS_PER_MP_LIMB; + } + else + { + if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG) + { + /* We make a difference here because the compiler + cannot optimize the `else' case that good and + this reflects all currently used FLOAT types + and GMP implementations. */ + register int i; +#if RETURN_LIMB_SIZE <= 2 + assert (empty == 1); + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, + BITS_PER_MP_LIMB, 0); +#else + for (i = RETURN_LIMB_SIZE; i > empty; --i) + retval[i] = retval[i - empty]; +#endif + for (i = numsize; i > 0; --i) + num[i + empty] = num[i - 1]; + MPN_ZERO (num, empty + 1); + } + else + { + used = MANT_DIG - bits; + if (used >= BITS_PER_MP_LIMB) + { + register int i; + (void) __mpn_lshift (&retval[used + / BITS_PER_MP_LIMB], + retval, RETURN_LIMB_SIZE, + used % BITS_PER_MP_LIMB); + for (i = used / BITS_PER_MP_LIMB; i >= 0; --i) + retval[i] = 0; + } + else if (used > 0) + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0); + } + bits += empty * BITS_PER_MP_LIMB; + } + } + else + { + int i; + assert (numsize == densize); + for (i = numsize; i > 0; --i) + num[i] = num[i - 1]; + } + + den[densize] = 0; + n0 = num[densize]; + + while (bits <= MANT_DIG) + { + if (n0 == dX) + /* This might over-estimate QUOT, but it's probably not + worth the extra code here to find out. */ + quot = ~(mp_limb_t) 0; + else + { + mp_limb_t r; + + udiv_qrnnd (quot, r, n0, num[densize - 1], dX); + umul_ppmm (n1, n0, d1, quot); + + while (n1 > r || (n1 == r && n0 > num[densize - 2])) + { + --quot; + r += dX; + if (r < dX) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + after the calculation of QUOT. Taking advantage of this, we + could make this loop make two iterations less. */ + + cy = __mpn_submul_1 (num, den, densize + 1, quot); + + if (num[densize] != cy) + { + cy = __mpn_add_n (num, num, den, densize); + assert (cy != 0); + --quot; + } + n0 = num[densize] = num[densize - 1]; + for (i = densize - 1; i > 0; --i) + num[i] = num[i - 1]; + + got_limb; + } + + for (i = densize; num[i] == 0 && i >= 0; --i) + ; + return round_and_return (retval, exponent - 1, negative, + quot, BITS_PER_MP_LIMB - 1 - used, + more_bits || i >= 0); + } + } + } + + /* NOTREACHED */ +} +#if defined _LIBC \ + && !(defined USE_IN_EXTENDED_LOCALE_MODEL && defined USE_WIDE_CHAR) +libc_hidden_def (INTERNAL (STRTOF)) +#endif + +/* External user entry point. */ + +FLOAT +#ifdef weak_function +weak_function +#endif +STRTOF (nptr, endptr LOCALE_PARAM) + const STRING_TYPE *nptr; + STRING_TYPE **endptr; + LOCALE_PARAM_DECL +{ + return INTERNAL (STRTOF) (nptr, endptr, 0 LOCALE_PARAM); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/strtod_l.c b/src/kernel/libroot/posix/glibc/stdlib/strtod_l.c new file mode 100644 index 0000000000..e8449050d3 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/strtod_l.c @@ -0,0 +1,31 @@ +/* Convert string representing a number to float value, using given locale. + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 + +#include + +extern double ____strtod_l_internal (const char *, char **, int, __locale_t); +extern unsigned long long int ____strtoull_l_internal (const char *, char **, + int, int, __locale_t); + +#include + +weak_alias (__strtod_l, strtod_l) diff --git a/src/kernel/libroot/posix/glibc/stdlib/strtof.c b/src/kernel/libroot/posix/glibc/stdlib/strtof.c new file mode 100644 index 0000000000..9d070279f8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/strtof.c @@ -0,0 +1,22 @@ +/* The actual implementation for all floating point sizes is in strtod.c. + These macros tell it to produce the `float' version, `strtof'. */ + +#define FLOAT float +#define FLT FLT +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __strtof_l +#else +# define STRTOF strtof +#endif +#define MPN2FLOAT __mpn_construct_float +#define FLOAT_HUGE_VAL HUGE_VALF +#define SET_MANTISSA(flt, mant) \ + do { union ieee754_float u; \ + u.f = (flt); \ + if ((mant & 0x7fffff) == 0) \ + mant = 0x400000; \ + u.ieee.mantissa = (mant) & 0x7fffff; \ + (flt) = u.f; \ + } while (0) + +#include "strtod.c" diff --git a/src/kernel/libroot/posix/glibc/stdlib/strtof_l.c b/src/kernel/libroot/posix/glibc/stdlib/strtof_l.c new file mode 100644 index 0000000000..1187ffc73b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/strtof_l.c @@ -0,0 +1,31 @@ +/* Convert string representing a number to float value, using given locale. + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 + +#include + +extern float ____strtof_l_internal (const char *, char **, int, __locale_t); +extern unsigned long long int ____strtoull_l_internal (const char *, char **, + int, int, __locale_t); + +#include + +weak_alias (__strtof_l, strtof_l) diff --git a/src/kernel/libroot/posix/glibc/stdlib/strtold_l.c b/src/kernel/libroot/posix/glibc/stdlib/strtold_l.c new file mode 100644 index 0000000000..c3a4e79390 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/strtold_l.c @@ -0,0 +1,53 @@ +/* Convert string representing a number to float value, using given locale. + Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifndef __NO_LONG_DOUBLE_MATH + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 + +extern long double ____strtold_l_internal (const char *, char **, int, + __locale_t); +extern unsigned long long int ____strtoull_l_internal (const char *, char **, + int, int, __locale_t); + +# include + +#else +/* There is no `long double' type, use the `double' implementations. */ +extern double ____strtod_l_internal (const char *, char **, int, + __locale_t); +long double +____strtold_l_internal (const char *nptr, char **endptr, int group, + __locale_t loc) +{ + return ____strtod_l_internal (nptr, endptr, group, loc); +} + +long double +__strtold_l (const char *nptr, char **endptr, __locale_t loc) +{ + return ____strtod_l_internal (nptr, endptr, 0, loc); +} +#endif + +weak_alias (__strtold_l, strtold_l) diff --git a/src/kernel/libroot/posix/glibc/stdlib/sys/errno.h b/src/kernel/libroot/posix/glibc/stdlib/sys/errno.h new file mode 100644 index 0000000000..339f4fc10c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/sys/errno.h @@ -0,0 +1 @@ +#include diff --git a/src/kernel/libroot/posix/glibc/stdlib/ucontext.h b/src/kernel/libroot/posix/glibc/stdlib/ucontext.h new file mode 100644 index 0000000000..ee6f594f07 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/ucontext.h @@ -0,0 +1,53 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V ABI compliant user-level context switching support. */ + +#ifndef _UCONTEXT_H +#define _UCONTEXT_H 1 + +#include + +/* Get machine dependent definition of data structures. */ +#include + +__BEGIN_DECLS + +/* Get user context and store it in variable pointed to by UCP. */ +extern int getcontext (ucontext_t *__ucp) __THROW; + +/* Set user context from information of variable pointed to by UCP. */ +extern int setcontext (__const ucontext_t *__ucp) __THROW; + +/* Save current context in context variable pointed to by OUCP and set + context from variable pointed to by UCP. */ +extern int swapcontext (ucontext_t *__restrict __oucp, + __const ucontext_t *__restrict __ucp) __THROW; + +/* Manipulate user context UCP to continue with calling functions FUNC + and the ARGC-1 parameters following ARGC when the context is used + the next time in `setcontext' or `swapcontext'. + + We cannot say anything about the parameters FUNC takes; `void' + is as good as any other choice. */ +extern void makecontext (ucontext_t *__ucp, void (*__func) (void), + int __argc, ...) __THROW; + +__END_DECLS + +#endif /* ucontext.h */ diff --git a/src/kernel/libroot/posix/glibc/stdlib/wcstombs.c b/src/kernel/libroot/posix/glibc/stdlib/wcstombs.c new file mode 100644 index 0000000000..e25b6b30fb --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/wcstombs.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991,1992,1995,1996,1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* Convert the `wchar_t' string in PWCS to a multibyte character string + in S, writing no more than N characters. Return the number of bytes + written, or (size_t) -1 if an invalid `wchar_t' was found. */ +size_t +wcstombs (char *s, const wchar_t *pwcs, size_t n) +{ + mbstate_t state; + + memset (&state, '\0', sizeof state); + + /* Return how many we wrote (or maybe an error). */ + return __wcsrtombs (s, &pwcs, n, &state); +} diff --git a/src/kernel/libroot/posix/glibc/stdlib/wctomb.c b/src/kernel/libroot/posix/glibc/stdlib/wctomb.c new file mode 100644 index 0000000000..49872f5c6b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/wctomb.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1991, 1992, 1995-1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +extern mbstate_t __no_r_state attribute_hidden; /* Defined in mbtowc.c. */ + +/* Convert WCHAR into its multibyte character representation, + putting this in S and returning its length. + + Attention: this function should NEVER be intentionally used. + The interface is completely stupid. The state is shared between + all conversion functions. You should use instead the restartable + version `wcrtomb'. */ +int +wctomb (char *s, wchar_t wchar) +{ + /* If S is NULL the function has to return null or not null + depending on the encoding having a state depending encoding or + not. */ + if (s == NULL) + { + const struct gconv_fcts *fcts; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* This is an extension in the Unix standard which does not directly + violate ISO C. */ + memset (&__no_r_state, '\0', sizeof __no_r_state); + + return fcts->tomb->__stateful; + } + + return __wcrtomb (s, wchar, &__no_r_state); +} +libc_hidden_def (wctomb) diff --git a/src/kernel/libroot/posix/glibc/stdlib/xpg_basename.c b/src/kernel/libroot/posix/glibc/stdlib/xpg_basename.c new file mode 100644 index 0000000000..cc1a1ab8e5 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/stdlib/xpg_basename.c @@ -0,0 +1,72 @@ +/* Return basename of given pathname according to the weird XPG specification. + Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +char * +__xpg_basename (char *filename) +{ + char *p; + + if (filename == NULL || filename[0] == '\0') + /* We return a pointer to a static string containing ".". */ + p = (char *) "."; + else + { + p = strrchr (filename, '/'); + + if (p == NULL) + /* There is no slash in the filename. Return the whole string. */ + p = filename; + else + { + if (p[1] == '\0') + { + /* We must remove trailing '/'. */ + while (p > filename && p[-1] == '/') + --p; + + /* Now we can be in two situations: + a) the string only contains '/' characters, so we return + '/' + b) p points past the last component, but we have to remove + the trailing slash. */ + if (p > filename) + { + *p-- = '\0'; + while (p > filename && p[-1] != '/') + --p; + } + else + /* The last slash we already found is the right position + to return. */ + while (p[1] != '\0') + ++p; + } + else + /* Go to the first character of the name. */ + ++p; + } + } + + return p; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/Depend b/src/kernel/libroot/posix/glibc/wcsmbs/Depend new file mode 100644 index 0000000000..f3e1156a4e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/Depend @@ -0,0 +1 @@ +localedata diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/Makefile b/src/kernel/libroot/posix/glibc/wcsmbs/Makefile new file mode 100644 index 0000000000..882084db1e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/Makefile @@ -0,0 +1,68 @@ +# Copyright (C) 1995-2000, 2002 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +# +# Sub-makefile for wcsmbs portion of the library. +# +subdir := wcsmbs + +headers := wchar.h +distribute := wcwidth.h wcsmbsload.h + +routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ + wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \ + wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \ + btowc wctob mbsinit \ + mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \ + mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \ + wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \ + wcstol_l wcstoul_l wcstoll_l wcstoull_l \ + wcstod_l wcstold_l wcstof_l \ + wcscoll wcsxfrm \ + wcwidth wcswidth \ + wcscoll_l wcsxfrm_l \ + wcscasecmp wcsncase wcscasecmp_l wcsncase_l \ + wcsmbsload mbsrtowcs_l + +tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \ + tst-wcrtomb + +include ../Rules + +CFLAGS-wcwidth.c = -I../wctype +CFLAGS-wcswidth.c = -I../wctype + +strtox-CFLAGS = -I../include -I../stdlib +CFLAGS-wcstol.c = $(strtox-CFLAGS) +CFLAGS-wcstoul.c = $(strtox-CFLAGS) +CFLAGS-wcstoll.c = $(strtox-CFLAGS) +CFLAGS-wcstoull.c = $(strtox-CFLAGS) +CFLAGS-wcstod.c = $(strtox-CFLAGS) +CFLAGS-wcstold.c = $(strtox-CFLAGS) +CFLAGS-wcstof.c = $(strtox-CFLAGS) +CFLAGS-wcstol_l.c = $(strtox-CFLAGS) +CFLAGS-wcstoul_l.c = $(strtox-CFLAGS) +CFLAGS-wcstoll_l.c = $(strtox-CFLAGS) +CFLAGS-wcstoull_l.c = $(strtox-CFLAGS) +CFLAGS-wcstod_l.c = $(strtox-CFLAGS) +CFLAGS-wcstold_l.c = $(strtox-CFLAGS) +CFLAGS-wcstof_l.c = $(strtox-CFLAGS) + +tst-btowc-ENV = LOCPATH=$(common-objpfx)localedata +tst-mbrtowc-ENV = LOCPATH=$(common-objpfx)localedata +tst-wcrtomb-ENV = LOCPATH=$(common-objpfx)localedata diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/Versions b/src/kernel/libroot/posix/glibc/wcsmbs/Versions new file mode 100644 index 0000000000..6f2e72eb2a --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/Versions @@ -0,0 +1,27 @@ +libc { + GLIBC_2.0 { + # functions used in inline functions or macros + __wcsto*_internal; __mbrlen; __mbrtowc; + + # b* + btowc; + + # w* + wcpcpy; wcpncpy; wcrtomb; wcscat; wcschr; wcscmp; wcscoll; + wcscpy; wcscspn; wcsdup; wcslen; wcsncat; wcsncmp; + wcsncpy; wcsnrtombs; wcspbrk; wcsrchr; wcsrtombs; wcsspn; wcsstr; + wcstod; wcstof; wcstok; wcstol; wcstold; wcstoq; wcstoul; + wcstouq; wcswidth; wcsxfrm; wctob; + + wmemchr; wmemcmp; wmemcpy; wmemmove; wmemset; + } + GLIBC_2.1 { + # w* + wcscasecmp; wcsncasecmp; wcsnlen; wcstoll; + wcstoimax; wcstoumax; wcstoull; wcswcs; wmemrtombs; wmemrtowcs; + } + GLIBC_2.2 { + # w* + wcschrnul; wmempcpy; + } +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/btowc.c b/src/kernel/libroot/posix/glibc/wcsmbs/btowc.c new file mode 100644 index 0000000000..1ba0221403 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/btowc.c @@ -0,0 +1,87 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + +wint_t +__btowc (c) + int c; +{ + const struct gconv_fcts *fcts; + + /* If the parameter does not fit into one byte or it is the EOF value + we can give the answer now. */ + if (c < SCHAR_MIN || c > UCHAR_MAX || c == EOF) + return WEOF; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + if (__builtin_expect (fcts->towc_nsteps == 1, 1) + && __builtin_expect (fcts->towc->__btowc_fct != NULL, 1)) + { + /* Use the shortcut function. */ + return DL_CALL_FCT (fcts->towc->__btowc_fct, + (fcts->towc, (unsigned char) c)); + } + else + { + /* Fall back to the slow but generic method. */ + wchar_t result; + struct __gconv_step_data data; + unsigned char inbuf[1]; + const unsigned char *inptr = inbuf; + size_t dummy; + int status; + + /* Tell where we want the result. */ + data.__outbuf = (unsigned char *) &result; + data.__outbufend = data.__outbuf + sizeof (wchar_t); + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = &data.__state; + data.__trans = NULL; + + /* Make sure we start in the initial state. */ + memset (&data.__state, '\0', sizeof (mbstate_t)); + + /* Create the input string. */ + inbuf[0] = c; + + status = DL_CALL_FCT (fcts->towc->__fct, + (fcts->towc, &data, &inptr, inptr + 1, + NULL, &dummy, 0, 1)); + + if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT + && status != __GCONV_EMPTY_INPUT) + /* The conversion failed. */ + result = WEOF; + + return result; + } +} +weak_alias (__btowc, btowc) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/mbrlen.c b/src/kernel/libroot/posix/glibc/wcsmbs/mbrlen.c new file mode 100644 index 0000000000..a173ea0f20 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/mbrlen.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* The mbrlen function has an internal shift state which gets used if + the PS parameter is NULL. */ +static mbstate_t internal; + + +size_t +__mbrlen (s, n, ps) + const char *s; + size_t n; + mbstate_t *ps; +{ + return __mbrtowc (NULL, s, n, ps ?: &internal); +} +libc_hidden_def (__mbrlen) +weak_alias (__mbrlen, mbrlen) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/mbrtowc.c b/src/kernel/libroot/posix/glibc/wcsmbs/mbrtowc.c new file mode 100644 index 0000000000..de79e10e5d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/mbrtowc.c @@ -0,0 +1,110 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + +#ifndef EILSEQ +# define EILSEQ EINVAL +#endif + +/* This is the private state used if PS is NULL. */ +static mbstate_t state; + +size_t +__mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ + wchar_t buf[1]; + struct __gconv_step_data data; + int status; + size_t result; + size_t dummy; + const unsigned char *inbuf; + char *outbuf = (char *) (pwc ?: buf); + const struct gconv_fcts *fcts; + + /* Set information for this step. */ + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = ps ?: &state; + data.__trans = NULL; + + /* A first special case is if S is NULL. This means put PS in the + initial state. */ + if (s == NULL) + { + outbuf = (char *) buf; + s = ""; + n = 1; + } + + /* Tell where we want the result. */ + data.__outbuf = outbuf; + data.__outbufend = outbuf + sizeof (wchar_t); + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Do a normal conversion. */ + inbuf = (const unsigned char *) s; + status = DL_CALL_FCT (fcts->towc->__fct, + (fcts->towc, &data, &inbuf, inbuf + n, + NULL, &dummy, 0, 1)); + + /* There must not be any problems with the conversion but illegal input + characters. The output buffer must be large enough, otherwise the + definition of MB_CUR_MAX is not correct. All the other possible + errors also must not happen. */ + assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_ILLEGAL_INPUT + || status == __GCONV_INCOMPLETE_INPUT + || status == __GCONV_FULL_OUTPUT); + + if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_FULL_OUTPUT) + { + if (data.__outbuf != (unsigned char *) outbuf + && *(wchar_t *) outbuf == L'\0') + { + /* The converted character is the NUL character. */ + assert (__mbsinit (data.__statep)); + result = 0; + } + else + result = inbuf - (const unsigned char *) s; + } + else if (status == __GCONV_INCOMPLETE_INPUT) + result = (size_t) -2; + else + { + result = (size_t) -1; + __set_errno (EILSEQ); + } + + return result; +} +libc_hidden_def (__mbrtowc) +weak_alias (__mbrtowc, mbrtowc) +libc_hidden_weak (mbrtowc) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/mbsinit.c b/src/kernel/libroot/posix/glibc/wcsmbs/mbsinit.c new file mode 100644 index 0000000000..5d740c85fc --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/mbsinit.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* In GNU libc the conversion functions only can convert between the + fixed wide character representation and the multibyte + representation of the same character set. Since we use ISO 10646 + in UCS4 encoding for wide characters the best solution for + multibyte characters is the UTF8 encoding. I.e., the only state + information is a counter of the processed bytes so far and the + value collected so far. Especially, we don't have different shift + states. */ +int +__mbsinit (ps) + const mbstate_t *ps; +{ + return ps == NULL || ps->__count == 0; +} +weak_alias (__mbsinit, mbsinit) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/mbsnrtowcs.c b/src/kernel/libroot/posix/glibc/wcsmbs/mbsnrtowcs.c new file mode 100644 index 0000000000..9ac06fe6c2 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/mbsnrtowcs.c @@ -0,0 +1,140 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include + +#ifndef EILSEQ +# define EILSEQ EINVAL +#endif + + +/* This is the private state used if PS is NULL. */ +static mbstate_t state; + +/* This is a non-standard function but it is very useful in the + implementation of stdio because we have to deal with unterminated + buffers. At most NMC bytes will be converted. */ +size_t +__mbsnrtowcs (dst, src, nmc, len, ps) + wchar_t *dst; + const char **src; + size_t nmc; + size_t len; + mbstate_t *ps; +{ + const unsigned char *srcend; + struct __gconv_step_data data; + size_t result; + int status; + struct __gconv_step *towc; + size_t dummy; + const struct gconv_fcts *fcts; + + /* Tell where we want the result. */ + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = ps ?: &state; + data.__trans = NULL; + + if (nmc == 0) + return 0; + srcend = *src + __strnlen (*src, nmc - 1) + 1; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Get the structure with the function pointers. */ + towc = fcts->towc; + + /* We have to handle DST == NULL special. */ + if (dst == NULL) + { + wchar_t buf[64]; /* Just an arbitrary size. */ + const unsigned char *inbuf = *src; + + result = 0; + data.__outbufend = (unsigned char *) buf + sizeof (buf); + do + { + data.__outbuf = (unsigned char *) buf; + + status = DL_CALL_FCT (towc->__fct, + (towc, &data, &inbuf, srcend, NULL, + &dummy, 0, 1)); + + result += (wchar_t *) data.__outbuf - buf; + } + while (status == __GCONV_FULL_OUTPUT); + + if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + && ((wchar_t *) data.__outbuf)[-1] == L'\0') + /* Don't count the NUL character in. */ + --result; + } + else + { + /* This code is based on the safe assumption that all internal + multi-byte encodings use the NUL byte only to mark the end + of the string. */ + data.__outbuf = (unsigned char *) dst; + data.__outbufend = data.__outbuf + len * sizeof (wchar_t); + + status = DL_CALL_FCT (towc->__fct, + (towc, &data, (const unsigned char **) src, srcend, + NULL, &dummy, 0, 1)); + + result = (wchar_t *) data.__outbuf - dst; + + /* We have to determine whether the last character converted + is the NUL character. */ + if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + && (assert (result > 0), + ((wchar_t *) dst)[result - 1] == L'\0')) + { + assert (__mbsinit (data.__statep)); + *src = NULL; + --result; + } + } + + /* There must not be any problems with the conversion but illegal input + characters. */ + assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_ILLEGAL_INPUT + || status == __GCONV_INCOMPLETE_INPUT + || status == __GCONV_FULL_OUTPUT); + + if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT + && status != __GCONV_EMPTY_INPUT && status != __GCONV_INCOMPLETE_INPUT) + { + result = (size_t) -1; + __set_errno (EILSEQ); + } + + return result; +} +weak_alias (__mbsnrtowcs, mbsnrtowcs) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs.c b/src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs.c new file mode 100644 index 0000000000..602dd5e64c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs.c @@ -0,0 +1,167 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef EILSEQ +# define EILSEQ EINVAL +#endif + + +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +size_t +attribute_hidden +__mbsrtowcs_l (dst, src, len, ps, l) + wchar_t *dst; + const char **src; + size_t len; + mbstate_t *ps; + __locale_t l; +#else +/* This is the private state used if PS is NULL. */ +static mbstate_t state; + +size_t +__mbsrtowcs (dst, src, len, ps) + wchar_t *dst; + const char **src; + size_t len; + mbstate_t *ps; +#endif +{ + struct __gconv_step_data data; + size_t result; + int status; + struct __gconv_step *towc; + size_t non_reversible; + const struct gconv_fcts *fcts; + + /* Tell where we want the result. */ + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; +#ifdef USE_IN_EXTENDED_LOCALE_MODEL + data.__statep = ps; +#else + data.__statep = ps ?: &state; +#endif + data.__trans = NULL; + + /* Get the conversion functions. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL + fcts = get_gconv_fcts (l->__locales[LC_CTYPE]); +#else + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); +#endif + + /* Get the structure with the function pointers. */ + towc = fcts->towc; + + /* We have to handle DST == NULL special. */ + if (dst == NULL) + { + mbstate_t temp_state; + wchar_t buf[64]; /* Just an arbitrary size. */ + const unsigned char *inbuf = (const unsigned char *) *src; + const unsigned char *srcend = inbuf + strlen (inbuf) + 1; + + temp_state = *data.__statep; + data.__statep = &temp_state; + + result = 0; + data.__outbufend = (char *) buf + sizeof (buf); + do + { + data.__outbuf = (char *) buf; + + status = DL_CALL_FCT (towc->__fct, + (towc, &data, &inbuf, srcend, NULL, + &non_reversible, 0, 1)); + + result += (wchar_t *) data.__outbuf - buf; + } + while (status == __GCONV_FULL_OUTPUT); + + if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + { + /* There better should be a NUL wide char at the end. */ + assert (((wchar_t *) data.__outbuf)[-1] == L'\0'); + /* Don't count the NUL character in. */ + --result; + } + } + else + { + /* This code is based on the safe assumption that all internal + multi-byte encodings use the NUL byte only to mark the end + of the string. */ + const unsigned char *srcend; + + srcend = (const unsigned char *) (*src + + __strnlen (*src, len * MB_CUR_MAX) + + 1); + + data.__outbuf = (unsigned char *) dst; + data.__outbufend = data.__outbuf + len * sizeof (wchar_t); + + status = DL_CALL_FCT (towc->__fct, + (towc, &data, (const unsigned char **) src, srcend, + NULL, &non_reversible, 0, 1)); + + result = (wchar_t *) data.__outbuf - dst; + + /* We have to determine whether the last character converted + is the NUL character. */ + if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + && ((wchar_t *) dst)[result - 1] == L'\0') + { + assert (result > 0); + assert (__mbsinit (data.__statep)); + *src = NULL; + --result; + } + } + + /* There must not be any problems with the conversion but illegal input + characters. */ + assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_ILLEGAL_INPUT + || status == __GCONV_INCOMPLETE_INPUT + || status == __GCONV_FULL_OUTPUT); + + if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT + && status != __GCONV_EMPTY_INPUT && status != __GCONV_INCOMPLETE_INPUT) + { + result = (size_t) -1; + __set_errno (EILSEQ); + } + + return result; +} +#ifndef USE_IN_EXTENDED_LOCALE_MODEL +weak_alias (__mbsrtowcs, mbsrtowcs) +#endif diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs_l.c new file mode 100644 index 0000000000..0890803b59 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/mbsrtowcs_l.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "wcsmbsload.h" + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 +#include "mbsrtowcs.c" diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wchar.h b/src/kernel/libroot/posix/glibc/wcsmbs/wchar.h new file mode 100644 index 0000000000..74a8fc1f0b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wchar.h @@ -0,0 +1,741 @@ +/* Copyright (C) 1995-99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.24 + * Extended multibyte and wide character utilities + */ + +#ifndef _WCHAR_H + +#ifndef __need_mbstate_t +# define _WCHAR_H 1 +# include +#endif + +#ifdef _WCHAR_H +/* Get FILE definition. */ +# define __need___FILE +# ifdef __USE_UNIX98 +# define __need_FILE +# endif +# include +/* Get va_list definition. */ +# define __need___va_list +# include + +/* Get size_t, wchar_t, wint_t and NULL from . */ +# define __need_size_t +# define __need_wchar_t +# define __need_NULL +#endif +#define __need_wint_t +#include + +#include + +/* We try to get wint_t from , but not all GCC versions define it + there. So define it ourselves if it remains undefined. */ +#ifndef _WINT_T +/* Integral type unchanged by default argument promotions that can + hold any value corresponding to members of the extended character + set, as well as at least one value that does not correspond to any + member of the extended character set. */ +# define _WINT_T +typedef unsigned int wint_t; +#else +# ifdef __USE_GNU +__USING_NAMESPACE_STD(wint_t) +# endif +#endif + + +#ifndef __mbstate_t_defined +# define __mbstate_t_defined 1 +/* Conversion state information. */ +typedef struct +{ + int __count; + union + { + wint_t __wch; + char __wchb[4]; + } __value; /* Value so far. */ +} __mbstate_t; +#endif +#undef __need_mbstate_t + + +/* The rest of the file is only used if used if __need_mbstate_t is not + defined. */ +#ifdef _WCHAR_H + +__BEGIN_NAMESPACE_C99 +/* Public type. */ +//typedef __mbstate_t mbstate_t; +__END_NAMESPACE_C99 +#ifdef __USE_GNU +__USING_NAMESPACE_C99(mbstate_t) +#endif + +#ifndef WCHAR_MIN +/* These constants might also be defined in . */ +# define WCHAR_MIN __WCHAR_MIN +# define WCHAR_MAX __WCHAR_MAX +#endif + +#ifndef WEOF +# define WEOF (0xffffffffu) +#endif + +/* For XPG4 compliance we have to define the stuff from here + as well. */ +#if defined __USE_XOPEN && !defined __USE_UNIX98 +# include +#endif + + +__BEGIN_DECLS + +__BEGIN_NAMESPACE_STD +/* This incomplete type is defined in but needed here because + of `wcsftime'. */ +struct tm; +/* XXX We have to clean this up at some point. Since tm is in the std + namespace but wcsftime is in __c99 the type wouldn't be found + without inserting it in the global namespace. */ +__USING_NAMESPACE_STD(tm) +__END_NAMESPACE_STD + + +__BEGIN_NAMESPACE_C99 +/* Copy SRC to DEST. */ +extern wchar_t *wcscpy (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src) __THROW; +/* Copy no more than N wide-characters of SRC to DEST. */ +extern wchar_t *wcsncpy (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, size_t __n) + __THROW; + +/* Append SRC onto DEST. */ +extern wchar_t *wcscat (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src) __THROW; +/* Append no more than N wide-characters of SRC onto DEST. */ +extern wchar_t *wcsncat (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, size_t __n) + __THROW; + +/* Compare S1 and S2. */ +extern int wcscmp (__const wchar_t *__s1, __const wchar_t *__s2) + __THROW __attribute_pure__; +/* Compare N wide-characters of S1 and S2. */ +extern int wcsncmp (__const wchar_t *__s1, __const wchar_t *__s2, size_t __n) + __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* Compare S1 and S2, ignoring case. */ +extern int wcscasecmp (__const wchar_t *__s1, __const wchar_t *__s2) __THROW; + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +extern int wcsncasecmp (__const wchar_t *__s1, __const wchar_t *__s2, + size_t __n) __THROW; + +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ +# include + +extern int wcscasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2, + __locale_t __loc) __THROW; + +extern int wcsncasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2, + size_t __n, __locale_t __loc) __THROW; +#endif + +__BEGIN_NAMESPACE_C99 +/* Compare S1 and S2, both interpreted as appropriate to the + LC_COLLATE category of the current locale. */ +extern int wcscoll (__const wchar_t *__s1, __const wchar_t *__s2) __THROW; +/* Transform S2 into array pointed to by S1 such that if wcscmp is + applied to two transformed strings the result is the as applying + `wcscoll' to the original strings. */ +extern size_t wcsxfrm (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) __THROW; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ + +/* Compare S1 and S2, both interpreted as appropriate to the + LC_COLLATE category of the given locale. */ +extern int wcscoll_l (__const wchar_t *__s1, __const wchar_t *__s2, + __locale_t __loc) __THROW; + +/* Transform S2 into array pointed to by S1 such that if wcscmp is + applied to two transformed strings the result is the as applying + `wcscoll' to the original strings. */ +extern size_t wcsxfrm_l (wchar_t *__s1, __const wchar_t *__s2, + size_t __n, __locale_t __loc) __THROW; + +/* Duplicate S, returning an identical malloc'd string. */ +extern wchar_t *wcsdup (__const wchar_t *__s) __THROW __attribute_malloc__; +#endif + +__BEGIN_NAMESPACE_C99 +/* Find the first occurrence of WC in WCS. */ +extern wchar_t *wcschr (__const wchar_t *__wcs, wchar_t __wc) + __THROW __attribute_pure__; +/* Find the last occurrence of WC in WCS. */ +extern wchar_t *wcsrchr (__const wchar_t *__wcs, wchar_t __wc) + __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* This function is similar to `wcschr'. But it returns a pointer to + the closing NUL wide character in case C is not found in S. */ +extern wchar_t *wcschrnul (__const wchar_t *__s, wchar_t __wc) + __THROW __attribute_pure__; +#endif + +__BEGIN_NAMESPACE_C99 +/* Return the length of the initial segmet of WCS which + consists entirely of wide characters not in REJECT. */ +extern size_t wcscspn (__const wchar_t *__wcs, __const wchar_t *__reject) + __THROW __attribute_pure__; +/* Return the length of the initial segmet of WCS which + consists entirely of wide characters in ACCEPT. */ +extern size_t wcsspn (__const wchar_t *__wcs, __const wchar_t *__accept) + __THROW __attribute_pure__; +/* Find the first occurrence in WCS of any character in ACCEPT. */ +extern wchar_t *wcspbrk (__const wchar_t *__wcs, __const wchar_t *__accept) + __THROW __attribute_pure__; +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +extern wchar_t *wcsstr (__const wchar_t *__haystack, __const wchar_t *__needle) + __THROW __attribute_pure__; + +/* Divide WCS into tokens separated by characters in DELIM. */ +extern wchar_t *wcstok (wchar_t *__restrict __s, + __const wchar_t *__restrict __delim, + wchar_t **__restrict __ptr) __THROW; + +/* Return the number of wide characters in S. */ +extern size_t wcslen (__const wchar_t *__s) __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_XOPEN +/* Another name for `wcsstr' from XPG4. */ +extern wchar_t *wcswcs (__const wchar_t *__haystack, __const wchar_t *__needle) + __THROW __attribute_pure__; +#endif + +#ifdef __USE_GNU +/* Return the number of wide characters in S, but at most MAXLEN. */ +extern size_t wcsnlen (__const wchar_t *__s, size_t __maxlen) + __THROW __attribute_pure__; +#endif + + +__BEGIN_NAMESPACE_C99 +/* Search N wide characters of S for C. */ +extern wchar_t *wmemchr (__const wchar_t *__s, wchar_t __c, size_t __n) + __THROW __attribute_pure__; + +/* Compare N wide characters of S1 and S2. */ +extern int wmemcmp (__const wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) + __THROW __attribute_pure__; + +/* Copy N wide characters of SRC to DEST. */ +extern wchar_t *wmemcpy (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) __THROW; + +/* Copy N wide characters of SRC to DEST, guaranteeing + correct behavior for overlapping strings. */ +extern wchar_t *wmemmove (wchar_t *__s1, __const wchar_t *__s2, size_t __n) + __THROW; + +/* Set N wide characters of S to C. */ +extern wchar_t *wmemset (wchar_t *__s, wchar_t __c, size_t __n) __THROW; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* Copy N wide characters of SRC to DEST and return pointer to following + wide character. */ +extern wchar_t *wmempcpy (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) + __THROW; +#endif + + +__BEGIN_NAMESPACE_C99 +/* Determine whether C constitutes a valid (one-byte) multibyte + character. */ +extern wint_t btowc (int __c) __THROW; + +/* Determine whether C corresponds to a member of the extended + character set whose multibyte representation is a single byte. */ +extern int wctob (wint_t __c) __THROW; + +/* Determine whether PS points to an object representing the initial + state. */ +extern int mbsinit (__const mbstate_t *__ps) __THROW __attribute_pure__; + +/* Write wide character representation of multibyte character pointed + to by S to PWC. */ +extern size_t mbrtowc (wchar_t *__restrict __pwc, + __const char *__restrict __s, size_t __n, + mbstate_t *__p) __THROW; + +/* Write multibyte representation of wide character WC to S. */ +extern size_t wcrtomb (char *__restrict __s, wchar_t __wc, + mbstate_t *__restrict __ps) __THROW; + +/* Return number of bytes in multibyte character pointed to by S. */ +extern size_t __mbrlen (__const char *__restrict __s, size_t __n, + mbstate_t *__restrict __ps) __THROW; +extern size_t mbrlen (__const char *__restrict __s, size_t __n, + mbstate_t *__restrict __ps) __THROW; +__END_NAMESPACE_C99 + +#ifdef __USE_EXTERN_INLINES +/* Define inline function as optimization. */ +extern __inline size_t mbrlen (__const char *__restrict __s, size_t __n, + mbstate_t *__restrict __ps) __THROW +{ return (__ps != NULL + ? mbrtowc (NULL, __s, __n, __ps) : __mbrlen (__s, __n, NULL)); } +#endif + +__BEGIN_NAMESPACE_C99 +/* Write wide character representation of multibyte character string + SRC to DST. */ +extern size_t mbsrtowcs (wchar_t *__restrict __dst, + __const char **__restrict __src, size_t __len, + mbstate_t *__restrict __ps) __THROW; + +/* Write multibyte character representation of wide character string + SRC to DST. */ +extern size_t wcsrtombs (char *__restrict __dst, + __const wchar_t **__restrict __src, size_t __len, + mbstate_t *__restrict __ps) __THROW; +__END_NAMESPACE_C99 + + +#ifdef __USE_GNU +/* Write wide character representation of at most NMC bytes of the + multibyte character string SRC to DST. */ +extern size_t mbsnrtowcs (wchar_t *__restrict __dst, + __const char **__restrict __src, size_t __nmc, + size_t __len, mbstate_t *__restrict __ps) __THROW; + +/* Write multibyte character representation of at most NWC characters + from the wide character string SRC to DST. */ +extern size_t wcsnrtombs (char *__restrict __dst, + __const wchar_t **__restrict __src, + size_t __nwc, size_t __len, + mbstate_t *__restrict __ps) __THROW; +#endif /* use GNU */ + + +/* The following functions are extensions found in X/Open CAE. */ +#ifdef __USE_XOPEN +/* Determine number of column positions required for C. */ +extern int wcwidth (wchar_t __c) __THROW; + +/* Determine number of column positions required for first N wide + characters (or fewer if S ends before this) in S. */ +extern int wcswidth (__const wchar_t *__s, size_t __n) __THROW; +#endif /* Use X/Open. */ + + +__BEGIN_NAMESPACE_C99 +/* Convert initial portion of the wide string NPTR to `double' + representation. */ +extern double wcstod (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; + +#ifdef __USE_ISOC99 +/* Likewise for `float' and `long double' sizes of floating-point numbers. */ +extern float wcstof (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; +extern long double wcstold (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; +#endif /* C99 */ + + +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +extern long int wcstol (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long int' + representation. */ +extern unsigned long int wcstoul (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +#if defined __USE_ISOC99 || (defined __GNUC__ && defined __USE_GNU) +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +__extension__ +extern long long int wcstoll (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long long int' + representation. */ +__extension__ +extern unsigned long long int wcstoull (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW; +#endif /* ISO C99 or GCC and GNU. */ +__END_NAMESPACE_C99 + +#if defined __GNUC__ && defined __USE_GNU +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +__extension__ +extern long long int wcstoq (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long long int' + representation. */ +__extension__ +extern unsigned long long int wcstouq (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW; +#endif /* GCC and use GNU. */ + +#ifdef __USE_GNU +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* Special versions of the functions above which take the locale to + use as an additional parameter. */ +extern long int wcstol_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base, + __locale_t __loc) __THROW; + +extern unsigned long int wcstoul_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) __THROW; + +__extension__ +extern long long int wcstoll_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) __THROW; + +__extension__ +extern unsigned long long int wcstoull_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) + __THROW; + +extern double wcstod_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, __locale_t __loc) + __THROW; + +extern float wcstof_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, __locale_t __loc) + __THROW; + +extern long double wcstold_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + __locale_t __loc) __THROW; +#endif /* GNU */ + + +/* The internal entry points for `wcstoX' take an extra flag argument + saying whether or not to parse locale-dependent number grouping. */ +extern double __wcstod_internal (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __group) + __THROW; +extern float __wcstof_internal (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __group) + __THROW; +extern long double __wcstold_internal (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __group) __THROW; + +#ifndef __wcstol_internal_defined +extern long int __wcstol_internal (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, int __group) __THROW; +# define __wcstol_internal_defined 1 +#endif +#ifndef __wcstoul_internal_defined +extern unsigned long int __wcstoul_internal (__const wchar_t *__restrict __npt, + wchar_t **__restrict __endptr, + int __base, int __group) __THROW; +# define __wcstoul_internal_defined 1 +#endif +#ifndef __wcstoll_internal_defined +__extension__ +extern long long int __wcstoll_internal (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, int __group) __THROW; +# define __wcstoll_internal_defined 1 +#endif +#ifndef __wcstoull_internal_defined +__extension__ +extern unsigned long long int __wcstoull_internal (__const wchar_t * + __restrict __nptr, + wchar_t ** + __restrict __endptr, + int __base, + int __group) __THROW; +# define __wcstoull_internal_defined 1 +#endif + + +#if defined __OPTIMIZE__ && __GNUC__ >= 2 +/* Define inline functions which call the internal entry points. */ +__BEGIN_NAMESPACE_C99 + +extern __inline double wcstod (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW +{ return __wcstod_internal (__nptr, __endptr, 0); } +extern __inline long int wcstol (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW +{ return __wcstol_internal (__nptr, __endptr, __base, 0); } +extern __inline unsigned long int wcstoul (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW +{ return __wcstoul_internal (__nptr, __endptr, __base, 0); } +__END_NAMESPACE_C99 + +# ifdef __USE_GNU +extern __inline float wcstof (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW +{ return __wcstof_internal (__nptr, __endptr, 0); } +extern __inline long double wcstold (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW +{ return __wcstold_internal (__nptr, __endptr, 0); } + + +__extension__ +extern __inline long long int wcstoq (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW +{ return __wcstoll_internal (__nptr, __endptr, __base, 0); } +__extension__ +extern __inline unsigned long long int wcstouq (__const wchar_t * + __restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW +{ return __wcstoull_internal (__nptr, __endptr, __base, 0); } +# endif /* Use GNU. */ +#endif /* Optimizing GCC >=2. */ + + +#ifdef __USE_GNU +/* Copy SRC to DEST, returning the address of the terminating L'\0' in + DEST. */ +extern wchar_t *wcpcpy (wchar_t *__dest, __const wchar_t *__src) __THROW; + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +extern wchar_t *wcpncpy (wchar_t *__dest, __const wchar_t *__src, size_t __n) + __THROW; +#endif /* use GNU */ + + +/* Wide character I/O functions. */ +#if defined __USE_ISOC99 || defined __USE_UNIX98 +__BEGIN_NAMESPACE_C99 + +/* Select orientation for stream. */ +extern int fwide (__FILE *__fp, int __mode) __THROW; + + +/* Write formatted output to STREAM. */ +extern int fwprintf (__FILE *__restrict __stream, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wprintf__, 2, 3))) */; +/* Write formatted output to stdout. */ +extern int wprintf (__const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wprintf__, 1, 2))) */; +/* Write formatted output of at most N characters to S. */ +extern int swprintf (wchar_t *__restrict __s, size_t __n, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 4))) */; + +/* Write formatted output to S from argument list ARG. */ +extern int vfwprintf (__FILE *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wprintf__, 2, 0))) */; +/* Write formatted output to stdout from argument list ARG. */ +extern int vwprintf (__const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wprintf__, 1, 0))) */; +/* Write formatted output of at most N character to S from argument + list ARG. */ +extern int vswprintf (wchar_t *__restrict __s, size_t __n, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */; + + +/* Read formatted input from STREAM. */ +extern int fwscanf (__FILE *__restrict __stream, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */; +/* Read formatted input from stdin. */ +extern int wscanf (__const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wscanf__, 1, 2))) */; +/* Read formatted input from S. */ +extern int swscanf (__const wchar_t *__restrict __s, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */; + +__END_NAMESPACE_C99 +#endif /* Use ISO C99 and Unix98. */ + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 + +/* Read formatted input from S into argument list ARG. */ +extern int vfwscanf (__FILE *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */; +/* Read formatted input from stdin into argument list ARG. */ +extern int vwscanf (__const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wscanf__, 1, 0))) */; +/* Read formatted input from S into argument list ARG. */ +extern int vswscanf (__const wchar_t *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */; + +__END_NAMESPACE_C99 +#endif /* Use ISO C99. */ + + +__BEGIN_NAMESPACE_C99 +/* Read a character from STREAM. */ +extern wint_t fgetwc (__FILE *__stream) __THROW; +extern wint_t getwc (__FILE *__stream) __THROW; + +/* Read a character from stdin. */ +extern wint_t getwchar (void) __THROW; + + +/* Write a character to STREAM. */ +extern wint_t fputwc (wchar_t __wc, __FILE *__stream) __THROW; +extern wint_t putwc (wchar_t __wc, __FILE *__stream) __THROW; + +/* Write a character to stdout. */ +extern wint_t putwchar (wchar_t __wc) __THROW; + + +/* Get a newline-terminated wide character string of finite length + from STREAM. */ +extern wchar_t *fgetws (wchar_t *__restrict __ws, int __n, + __FILE *__restrict __stream) __THROW; + +/* Write a string to STREAM. */ +extern int fputws (__const wchar_t *__restrict __ws, + __FILE *__restrict __stream) __THROW; + + +/* Push a character back onto the input buffer of STREAM. */ +extern wint_t ungetwc (wint_t __wc, __FILE *__stream) __THROW; +__END_NAMESPACE_C99 + + +#ifdef __USE_GNU +/* These are defined to be equivalent to the `char' functions defined + in POSIX.1:1996. */ +extern wint_t getwc_unlocked (__FILE *__stream) __THROW; +extern wint_t getwchar_unlocked (void) __THROW; + +/* This is the wide character version of a GNU extension. */ +extern wint_t fgetwc_unlocked (__FILE *__stream) __THROW; + +/* Faster version when locking is not necessary. */ +extern wint_t fputwc_unlocked (wchar_t __wc, __FILE *__stream) __THROW; + +/* These are defined to be equivalent to the `char' functions defined + in POSIX.1:1996. */ +extern wint_t putwc_unlocked (wchar_t __wc, __FILE *__stream) __THROW; +extern wint_t putwchar_unlocked (wchar_t __wc) __THROW; + + +/* This function does the same as `fgetws' but does not lock the stream. */ +extern wchar_t *fgetws_unlocked (wchar_t *__restrict __ws, int __n, + __FILE *__restrict __stream) __THROW; + +/* This function does the same as `fputws' but does not lock the stream. */ +extern int fputws_unlocked (__const wchar_t *__restrict __ws, + __FILE *__restrict __stream) __THROW; +#endif + + +__BEGIN_NAMESPACE_C99 +/* Format TP into S according to FORMAT. + Write no more than MAXSIZE wide characters and return the number + of wide characters written, or 0 if it would exceed MAXSIZE. */ +extern size_t wcsftime (wchar_t *__restrict __s, size_t __maxsize, + __const wchar_t *__restrict __format, + __const struct tm *__restrict __tp) __THROW; +__END_NAMESPACE_C99 + +# ifdef __USE_GNU +# include + +/* Similar to `wcsftime' but takes the information from + the provided locale and not the global locale. */ +extern size_t wcsftime_l (wchar_t *__restrict __s, size_t __maxsize, + __const wchar_t *__restrict __format, + __const struct tm *__restrict __tp, + __locale_t __loc) __THROW; +# endif + +/* The X/Open standard demands that most of the functions defined in + the header must also appear here. This is probably + because some X/Open members wrote their implementation before the + ISO C standard was published and introduced the better solution. + We have to provide these definitions for compliance reasons but we + do this nonsense only if really necessary. */ +#if defined __USE_UNIX98 && !defined __USE_GNU +# define __need_iswxxx +# include +#endif + +__END_DECLS + +#endif /* _WCHAR_H defined */ + +#endif /* wchar.h */ diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcpcpy.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcpcpy.c new file mode 100644 index 0000000000..6c17bf1756 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcpcpy.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define __need_ptrdiff_t +#include + + +/* Copy SRC to DEST, returning the address of the terminating L'\0' in + DEST. */ +wchar_t * +__wcpcpy (dest, src) + wchar_t *dest; + const wchar_t *src; +{ + wchar_t *wcp = (wchar_t *) dest - 1; + wint_t c; + const ptrdiff_t off = src - dest + 1; + + do + { + c = wcp[off]; + *++wcp = c; + } + while (c != L'\0'); + + return wcp; +} + +weak_alias (__wcpcpy, wcpcpy) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcpncpy.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcpncpy.c new file mode 100644 index 0000000000..59b7301ca8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcpncpy.c @@ -0,0 +1,89 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Copy no more than N wide-characters of SRC to DEST, returning the + address of the last character written into DEST. */ +wchar_t * +__wcpncpy (dest, src, n) + wchar_t *dest; + const wchar_t *src; + size_t n; +{ + wint_t c; + wchar_t *const s = dest; + + --dest; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *src++; + *++dest = c; + if (c == L'\0') + break; + c = *src++; + *++dest = c; + if (c == L'\0') + break; + c = *src++; + *++dest = c; + if (c == L'\0') + break; + c = *src++; + *++dest = c; + if (c == L'\0') + break; + if (--n4 == 0) + goto last_chars; + } + n = n - (dest - s) - 1; + if (n == 0) + return dest; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return dest; + + do + { + c = *src++; + *++dest = c; + if (--n == 0) + return dest; + } + while (c != L'\0'); + + zero_fill: + do + *++dest = L'\0'; + while (--n > 0); + + return dest; +} + +weak_alias (__wcpncpy, wcpncpy) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcrtomb.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcrtomb.c new file mode 100644 index 0000000000..38144796f8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcrtomb.c @@ -0,0 +1,112 @@ +/* Copyright (C) 1996,1997,1998,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include + +#ifndef EILSEQ +# define EILSEQ EINVAL +#endif + + +/* This is the private state used if PS is NULL. */ +static mbstate_t state; + +size_t +__wcrtomb (char *s, wchar_t wc, mbstate_t *ps) +{ + char buf[MB_CUR_MAX]; + struct __gconv_step_data data; + int status; + size_t result; + size_t dummy; + const struct gconv_fcts *fcts; + + /* Set information for this step. */ + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = ps ?: &state; + data.__trans = NULL; + + /* A first special case is if S is NULL. This means put PS in the + initial state. */ + if (s == NULL) + { + s = buf; + wc = L'\0'; + } + + /* Tell where we want to have the result. */ + data.__outbuf = s; + data.__outbufend = s + MB_CUR_MAX; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* If WC is the NUL character we write into the output buffer the byte + sequence necessary for PS to get into the initial state, followed + by a NUL byte. */ + if (wc == L'\0') + { + status = DL_CALL_FCT (fcts->tomb->__fct, + (fcts->tomb, &data, NULL, NULL, + NULL, &dummy, 1, 1)); + + if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + *data.__outbuf++ = '\0'; + } + else + { + /* Do a normal conversion. */ + const unsigned char *inbuf = (const unsigned char *) &wc; + + status = DL_CALL_FCT (fcts->tomb->__fct, + (fcts->tomb, &data, &inbuf, + inbuf + sizeof (wchar_t), NULL, &dummy, 0, 1)); + } + + /* There must not be any problems with the conversion but illegal input + characters. The output buffer must be large enough, otherwise the + definition of MB_CUR_MAX is not correct. All the other possible + errors also must not happen. */ + assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_ILLEGAL_INPUT + || status == __GCONV_INCOMPLETE_INPUT + || status == __GCONV_FULL_OUTPUT); + + if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_FULL_OUTPUT) + result = data.__outbuf - (unsigned char *) s; + else + { + result = (size_t) -1; + __set_errno (EILSEQ); + } + + return result; +} +weak_alias (__wcrtomb, wcrtomb) +libc_hidden_weak (wcrtomb) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp.c new file mode 100644 index 0000000000..d9fbecf629 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#ifndef weak_alias +# define __wcscasecmp wcscasecmp +# define TOLOWER(Ch) towlower (Ch) +#else +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define __wcscasecmp __wcscasecmp_l +# define TOLOWER(Ch) __towlower_l ((Ch), loc) +# else +# define TOLOWER(Ch) towlower (Ch) +# endif +#endif + +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_DECL __locale_t loc; +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_DECL +#endif + +/* Compare S1 and S2, ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less than, + equal to or greater than S2. */ +int +__wcscasecmp (s1, s2 LOCALE_PARAM) + const wchar_t *s1; + const wchar_t *s2; + LOCALE_PARAM_DECL +{ + wint_t c1, c2; + + if (s1 == s2) + return 0; + + do + { + c1 = TOLOWER (*s1++); + c2 = TOLOWER (*s2++); + if (c1 == L'\0') + break; + } + while (c1 == c2); + + return c1 - c2; +} +#ifndef __wcscasecmp +weak_alias (__wcscasecmp, wcscasecmp) +#endif diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp_l.c new file mode 100644 index 0000000000..a278e5b00f --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscasecmp_l.c @@ -0,0 +1,24 @@ +/* Copyright (C) 1997,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 +#include + +libc_hidden_def (__wcscasecmp_l) +weak_alias (__wcscasecmp_l, wcscasecmp_l) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscat.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscat.c new file mode 100644 index 0000000000..6985a3103d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscat.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1995, 1996, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Append SRC on the end of DEST. */ +wchar_t * +__wcscat (dest, src) + wchar_t *dest; + const wchar_t *src; +{ + register wchar_t *s1 = dest; + register const wchar_t *s2 = src; + wchar_t c; + + /* Find the end of the string. */ + do + c = *s1++; + while (c != L'\0'); + + /* Make S1 point before the next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + s1 -= 2; + + do + { + c = *s2++; + *++s1 = c; + } + while (c != L'\0'); + + return dest; +} +weak_alias (__wcscat, wcscat) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcschr.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcschr.c new file mode 100644 index 0000000000..15b55d4543 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcschr.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Find the first occurrence of WC in WCS. */ +wchar_t * +wcschr (wcs, wc) + register const wchar_t *wcs; + register const wchar_t wc; +{ + do + if (*wcs == wc) + return (wchar_t *) wcs; + while (*wcs++ != L'\0'); + + return NULL; +} +libc_hidden_def (wcschr) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcschrnul.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcschrnul.c new file mode 100644 index 0000000000..9b61651f9e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcschrnul.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Find the first occurrence of WC in WCS. */ +wchar_t * +__wcschrnul (wcs, wc) + register const wchar_t *wcs; + register const wchar_t wc; +{ + while (*wcs != L'\0') + if (*wcs == wc) + break; + else + ++wcs; + + return (wchar_t *) wcs; +} +weak_alias (__wcschrnul, wcschrnul) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscmp.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscmp.c new file mode 100644 index 0000000000..8241c67f9b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscmp.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Compare S1 and S2, returning less than, equal to or + greater than zero if S1 is lexicographically less than, + equal to or greater than S2. */ +int +wcscmp (s1, s2) + const wchar_t *s1; + const wchar_t *s2; +{ + wint_t c1, c2; + + do + { + c1 = (wint_t) *s1++; + c2 = (wint_t) *s2++; + if (c1 == L'\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} +libc_hidden_def (wcscmp) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscoll.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscoll.c new file mode 100644 index 0000000000..40bd584e8b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscoll.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "../locale/coll-lookup.h" + +#define STRING_TYPE wchar_t +#define USTRING_TYPE wint_t +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRCOLL __wcscoll_l +#else +# define STRCOLL __wcscoll +#endif +#define STRCMP wcscmp +#define STRLEN __wcslen +#define WEIGHT_H "../locale/weightwc.h" +#define SUFFIX WC +#define L(arg) L##arg +#define WIDE_CHAR_VERSION 1 + +#include "../string/strcoll.c" + +#ifndef USE_IN_EXTENDED_LOCALE_MODEL +weak_alias (__wcscoll, wcscoll) +libc_hidden_weak (wcscoll) +#endif diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscoll_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscoll_l.c new file mode 100644 index 0000000000..20007b29c9 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscoll_l.c @@ -0,0 +1,23 @@ +/* Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 +#include + +weak_alias (__wcscoll_l, wcscoll_l) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscpy.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscpy.c new file mode 100644 index 0000000000..2e52a6c46f --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscpy.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Copy SRC to DEST. */ +wchar_t * +wcscpy (dest, src) + wchar_t *dest; + const wchar_t *src; +{ + wint_t c; + wchar_t *wcp; + + if (__alignof__ (wchar_t) >= sizeof (wchar_t)) + { + const ptrdiff_t off = dest - src - 1; + + wcp = (wchar_t *) src; + + do + { + c = *wcp++; + wcp[off] = c; + } + while (c != L'\0'); + } + else + { + wcp = dest; + + do + { + c = *src++; + *wcp++ = c; + } + while (c != L'\0'); + } + + return dest; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcscspn.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcscspn.c new file mode 100644 index 0000000000..8ad4d9dc95 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcscspn.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Return the length of the maximum initial segment + of WCS which contains only wide-characters not in REJECT. */ +size_t +wcscspn (wcs, reject) + const wchar_t *wcs; + const wchar_t *reject; +{ + register size_t count = 0; + + while (*wcs != L'\0') + if (wcschr (reject, *wcs++) == NULL) + ++count; + else + return count; + + return count; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsdup.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsdup.c new file mode 100644 index 0000000000..185836cb4a --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsdup.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* Duplicate S, returning an identical malloc'd string. */ +wchar_t * +wcsdup (s) + const wchar_t *s; +{ + size_t len = (__wcslen (s) + 1) * sizeof (wchar_t); + void *new = malloc (len); + + if (new == NULL) + return NULL; + + return (wchar_t *) memcpy (new, (void *) s, len); +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcslen.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcslen.c new file mode 100644 index 0000000000..1bced4bc98 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcslen.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Return length of string S. */ +size_t +__wcslen (s) + const wchar_t *s; +{ + size_t len = 0; + + while (s[len] != L'\0') + { + if (s[++len] == L'\0') + return len; + if (s[++len] == L'\0') + return len; + if (s[++len] == L'\0') + return len; + ++len; + } + + return len; +} +weak_alias (__wcslen, wcslen) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbs-tst1.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbs-tst1.c new file mode 100644 index 0000000000..1816d54eb6 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbs-tst1.c @@ -0,0 +1,59 @@ +/* Based on a test program by Won Kyu Park . */ + +#include +#include +#include +#include +#include +#include + +int +main (void) +{ + int test = 0; + int idx = 0; + char buf[100], *pchar; + wchar_t tmp[10]; + wchar_t tmp1[] = { L'W', L'o', L'r', L'l', L'd', L'\0' }; + char str[] = "Hello"; + int result = 0; + + pchar = setlocale (LC_ALL, ""); + printf ("locale : %s\n",pchar); + printf ("MB_CUR_MAX %Zd\n", MB_CUR_MAX); + + puts ("---- test 1 ------"); + test = mbstowcs (tmp, str, (strlen (str) + 1) * sizeof (char)); + printf ("size of string by mbstowcs %d\n", test); + if (test != strlen (str)) + result = 1; + idx += wctomb (&buf[0], tmp[0]); + idx += wctomb (&buf[idx], tmp[1]); + buf[idx] = 0; + printf ("orig string %s\n", str); + printf ("string by wctomb %s\n", buf); + printf ("string by %%C %C", tmp[0]); + if (tmp[0] != L'H') + result = 1; + printf ("%C\n", tmp[1]); + if (tmp[1] != L'e') + result = 1; + printf ("string by %%S %S\n", tmp); + if (wcscmp (tmp, L"Hello") != 0) + result = 1; + puts ("---- test 2 ------"); + printf ("wchar string %S\n", tmp1); + printf ("wchar %C\n", tmp1[0]); + test = wcstombs (buf, tmp1, (wcslen (tmp1) + 1) * sizeof (wchar_t)); + printf ("size of string by wcstombs %d\n", test); + if (test != wcslen (tmp1)) + result = 1; + test = wcslen (tmp1); + printf ("size of string by wcslen %d\n", test); + printf ("char %s\n", buf); + if (strcmp (buf, "World") != 0) + result = 1; + puts ("------------------"); + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.c new file mode 100644 index 0000000000..2fea6c38b3 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.c @@ -0,0 +1,269 @@ +/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* These are the descriptions for the default conversion functions. */ +static struct __gconv_step to_wc = +{ + .__shlib_handle = NULL, + .__modname = NULL, + .__counter = INT_MAX, + .__from_name = (char *) "ANSI_X3.4-1968//TRANSLIT", + .__to_name = (char *) "INTERNAL", + .__fct = __gconv_transform_ascii_internal, + .__btowc_fct = __gconv_btwoc_ascii, + .__init_fct = NULL, + .__end_fct = NULL, + .__min_needed_from = 1, + .__max_needed_from = 1, + .__min_needed_to = 4, + .__max_needed_to = 4, + .__stateful = 0, + .__data = NULL +}; + +static struct __gconv_step to_mb = +{ + .__shlib_handle = NULL, + .__modname = NULL, + .__counter = INT_MAX, + .__from_name = (char *) "INTERNAL", + .__to_name = (char *) "ANSI_X3.4-1968//TRANSLIT", + .__fct = __gconv_transform_internal_ascii, + .__btowc_fct = NULL, + .__init_fct = NULL, + .__end_fct = NULL, + .__min_needed_from = 4, + .__max_needed_from = 4, + .__min_needed_to = 1, + .__max_needed_to = 1, + .__stateful = 0, + .__data = NULL +}; + + +/* For the default locale we only have to handle ANSI_X3.4-1968. */ +const struct gconv_fcts __wcsmbs_gconv_fcts_c = +{ + .towc = &to_wc, + .towc_nsteps = 1, + .tomb = &to_mb, + .tomb_nsteps = 1 +}; + + +struct __gconv_step * +attribute_hidden +__wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp) +{ + size_t nsteps; + struct __gconv_step *result; +#if 0 + size_t nstateful; + size_t cnt; +#endif + + if (__gconv_find_transform (to, from, &result, &nsteps, 0) != __GCONV_OK) + /* Loading the conversion step is not possible. */ + return NULL; + + /* Maybe it is someday necessary to allow more than one step. + Currently this is not the case since the conversions handled here + are from and to INTERNAL and there always is a converted for + that. It the directly following code is enabled the libio + functions will have to allocate appropriate __gconv_step_data + elements instead of only one. */ +#if 0 + /* Count the number of stateful conversions. Since we will only + have one 'mbstate_t' object available we can only deal with one + stateful conversion. */ + nstateful = 0; + for (cnt = 0; cnt < nsteps; ++cnt) + if (result[cnt].__stateful) + ++nstateful; + if (nstateful > 1) +#else + if (nsteps > 1) +#endif + { + /* We cannot handle this case. */ + __gconv_close_transform (result, nsteps); + result = NULL; + } + else + *nstepsp = nsteps; + + return result; +} + + +/* Extract from the given locale name the character set portion. Since + only the XPG form of the name includes this information we don't have + to take care for the CEN form. */ +#define extract_charset_name(str) \ + ({ \ + const char *cp = str; \ + char *result = NULL; \ + \ + cp += strcspn (cp, "@.+,"); \ + if (*cp == '.') \ + { \ + const char *endp = ++cp; \ + while (*endp != '\0' && *endp != '@') \ + ++endp; \ + if (endp != cp) \ + result = strndupa (cp, endp - cp); \ + } \ + result; \ + }) + + +/* Some of the functions here must not be used while setlocale is called. */ +__libc_lock_define (extern, __libc_setlocale_lock attribute_hidden) + +/* Load conversion functions for the currently selected locale. */ +void +internal_function +__wcsmbs_load_conv (struct locale_data *new_category) +{ + /* Acquire the lock. */ + __libc_lock_lock (__libc_setlocale_lock); + + /* We should repeat the test since while we waited some other thread + might have run this function. */ + if (__builtin_expect (new_category->private.ctype == NULL, 1)) + { + /* We must find the real functions. */ + const char *charset_name; + const char *complete_name; + struct gconv_fcts *new_fcts; + int use_translit; + + /* Allocate the gconv_fcts structure. */ + new_fcts = malloc (sizeof *new_fcts); + if (new_fcts == NULL) + goto failed; + + /* Get name of charset of the locale. */ + charset_name = new_category->values[_NL_ITEM_INDEX(CODESET)].string; + + /* Does the user want transliteration? */ + use_translit = new_category->use_translit; + + /* Normalize the name and add the slashes necessary for a + complete lookup. */ + complete_name = norm_add_slashes (charset_name, + use_translit ? "TRANSLIT" : NULL); + + /* It is not necessary to use transliteration in this direction + since the internal character set is supposed to be able to + represent all others. */ + new_fcts->towc = __wcsmbs_getfct ("INTERNAL", complete_name, + &new_fcts->towc_nsteps); + new_fcts->tomb = (new_fcts->towc != NULL + ? __wcsmbs_getfct (complete_name, "INTERNAL", + &new_fcts->tomb_nsteps) + : NULL); + + /* If any of the conversion functions is not available we don't + use any since this would mean we cannot convert back and + forth.*/ + if (new_fcts->tomb == NULL) + { + if (new_fcts->towc != NULL) + __gconv_close_transform (new_fcts->towc, new_fcts->towc_nsteps); + + free (new_fcts); + + failed: + new_category->private.ctype = &__wcsmbs_gconv_fcts_c; + } + else + { + new_category->private.ctype = new_fcts; + new_category->private.cleanup = &_nl_cleanup_ctype; + } + } + + __libc_lock_unlock (__libc_setlocale_lock); +} + + +/* Clone the current conversion function set. */ +void +internal_function +__wcsmbs_clone_conv (struct gconv_fcts *copy) +{ + const struct gconv_fcts *orig; + + orig = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Copy the data. */ + *copy = *orig; + + /* Now increment the usage counters. + Note: This assumes copy->towc_nsteps == 1 and copy->tomb_nsteps == 1. */ + if (copy->towc->__shlib_handle != NULL) + ++copy->towc->__counter; + if (copy->tomb->__shlib_handle != NULL) + ++copy->tomb->__counter; +} + + +/* Get converters for named charset. */ +int +internal_function +__wcsmbs_named_conv (struct gconv_fcts *copy, const char *name) +{ + copy->towc = __wcsmbs_getfct ("INTERNAL", name, ©->towc_nsteps); + if (copy->towc != NULL) + { + copy->tomb = __wcsmbs_getfct (name, "INTERNAL", ©->tomb_nsteps); + if (copy->tomb == NULL) + __gconv_close_transform (copy->towc, copy->towc_nsteps); + } + + return copy->towc == NULL || copy->tomb == NULL ? 1 : 0; +} + +void internal_function +_nl_cleanup_ctype (struct locale_data *locale) +{ + const struct gconv_fcts *const data = locale->private.ctype; + if (data != NULL) + { + locale->private.ctype = NULL; + locale->private.cleanup = NULL; + + /* Free the old conversions. */ + __gconv_close_transform (data->tomb, data->tomb_nsteps); + __gconv_close_transform (data->towc, data->towc_nsteps); + free ((char *) data); + } +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.h b/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.h new file mode 100644 index 0000000000..12cd75cdb4 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.h @@ -0,0 +1,81 @@ +/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _WCSMBSLOAD_H +#define _WCSMBSLOAD_H 1 + +#include +#include +#include + + +/* Contains pointers to the used functions in the `gconv' modules. */ +struct gconv_fcts + { + struct __gconv_step *towc; + size_t towc_nsteps; + struct __gconv_step *tomb; + size_t tomb_nsteps; + }; + +/* Set of currently active conversion functions. */ +extern const struct gconv_fcts __wcsmbs_gconv_fcts_c attribute_hidden; + +/* Load conversion functions for the currently selected locale. */ +extern void __wcsmbs_load_conv (struct locale_data *new_category) + internal_function; + +/* Clone the current `__wcsmbs_load_conv' value. */ +extern void __wcsmbs_clone_conv (struct gconv_fcts *copy) + internal_function; + +/* Find the conversion functions for converting to and from NAME. */ +extern int __wcsmbs_named_conv (struct gconv_fcts *copy, const char *name) + internal_function; + +/* Function used for the `private.cleanup' hook. */ +extern void _nl_cleanup_ctype (struct locale_data *) + internal_function attribute_hidden; + + +#include + + +/* Load the function implementation if necessary. */ +extern struct __gconv_step *__wcsmbs_getfct (const char *to, const char *from, + size_t *nstepsp) + attribute_hidden; + +extern const struct locale_data _nl_C_LC_CTYPE attribute_hidden; + +/* Check whether the LC_CTYPE locale changed since the last call. + Update the pointers appropriately. */ +static inline const struct gconv_fcts * +get_gconv_fcts (struct locale_data *data) +{ + if (__builtin_expect (data->private.u.ctype == NULL, 0)) + { + if (__builtin_expect (data == &_nl_C_LC_CTYPE, 0)) + return &__wcsmbs_gconv_fcts_c; + __wcsmbs_load_conv (data); + } + return data->private.u.ctype; +} + +#endif /* wcsmbsload.h */ diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsncase.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncase.c new file mode 100644 index 0000000000..5056e9c1cb --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncase.c @@ -0,0 +1,76 @@ +/* Compare at most N wide characters of two strings without taking care + for the case. + Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#ifndef weak_alias +# define __wcsncasecmp wcsncasecmp +# define TOLOWER(Ch) towlower (Ch) +#else +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define __wcsncasecmp __wcsncasecmp_l +# define TOLOWER(Ch) __towlower_l ((Ch), loc) +# else +# define TOLOWER(Ch) towlower (Ch) +# endif +#endif + +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_DECL __locale_t loc; +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_DECL +#endif + +/* Compare no more than N wide characters of S1 and S2, + ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less + than, equal to or greater than S2. */ +int +__wcsncasecmp (s1, s2, n LOCALE_PARAM) + const wchar_t *s1; + const wchar_t *s2; + size_t n; + LOCALE_PARAM_DECL +{ + wint_t c1, c2; + + if (s1 == s2 || n == 0) + return 0; + + do + { + c1 = (wint_t) TOLOWER (*s1++); + c2 = (wint_t) TOLOWER (*s2++); + if (c1 == L'\0' || c1 != c2) + return c1 - c2; + } while (--n > 0); + + return c1 - c2; +} +#ifndef __wcsncasecmp +weak_alias (__wcsncasecmp, wcsncasecmp) +#endif diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsncase_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncase_l.c new file mode 100644 index 0000000000..45a26e53a8 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncase_l.c @@ -0,0 +1,24 @@ +/* Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 +#include + +libc_hidden_def (__wcsncasecmp_l) +weak_alias (__wcsncasecmp_l, wcsncasecmp_l) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsncat.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncat.c new file mode 100644 index 0000000000..8ff149e883 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncat.c @@ -0,0 +1,80 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Append no more than N wide-character of SRC onto DEST. */ +wchar_t * +wcsncat (dest, src, n) + wchar_t *dest; + const wchar_t *src; + size_t n; +{ + wchar_t c; + wchar_t * const s = dest; + + /* Find the end of DEST. */ + do + c = *dest++; + while (c != L'\0'); + + /* Make DEST point before next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + dest -= 2; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + n--; + } + + if (c != L'\0') + *++dest = L'\0'; + + return s; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsncmp.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncmp.c new file mode 100644 index 0000000000..9bf7a91f38 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncmp.c @@ -0,0 +1,71 @@ +/* Copyright (C) 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Compare no more than N characters of S1 and S2, + returning less than, equal to or greater than zero + if S1 is lexicographically less than, equal to or + greater than S2. */ +int +wcsncmp (s1, s2, n) + const wchar_t *s1; + const wchar_t *s2; + size_t n; +{ + wint_t c1 = L'\0'; + wint_t c2 = L'\0'; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (wint_t) *s1++; + c2 = (wint_t) *s2++; + if (c1 == L'\0' || c1 != c2) + return c1 - c2; + c1 = (wint_t) *s1++; + c2 = (wint_t) *s2++; + if (c1 == L'\0' || c1 != c2) + return c1 - c2; + c1 = (wint_t) *s1++; + c2 = (wint_t) *s2++; + if (c1 == L'\0' || c1 != c2) + return c1 - c2; + c1 = (wint_t) *s1++; + c2 = (wint_t) *s2++; + if (c1 == L'\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + c1 = (wint_t) *s1++; + c2 = (wint_t) *s2++; + if (c1 == L'\0' || c1 != c2) + return c1 - c2; + n--; + } + + return c1 - c2; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsncpy.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncpy.c new file mode 100644 index 0000000000..8469d94d79 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsncpy.c @@ -0,0 +1,86 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Copy no more than N wide-characters of SRC to DEST. */ +wchar_t * +wcsncpy (dest, src, n) + wchar_t *dest; + const wchar_t *src; + size_t n; +{ + wint_t c; + wchar_t *const s = dest; + + --dest; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *src++; + *++dest = c; + if (c == L'\0') + break; + c = *src++; + *++dest = c; + if (c == L'\0') + break; + c = *src++; + *++dest = c; + if (c == L'\0') + break; + c = *src++; + *++dest = c; + if (c == L'\0') + break; + if (--n4 == 0) + goto last_chars; + } + n = n - (dest - s) - 1; + if (n == 0) + return s; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return s; + + do + { + c = *src++; + *++dest = c; + if (--n == 0) + return s; + } + while (c != L'\0'); + + zero_fill: + do + *++dest = L'\0'; + while (--n > 0); + + return s; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsnlen.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsnlen.c new file mode 100644 index 0000000000..3cfbccad91 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsnlen.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Copy SRC to DEST. */ +size_t +__wcsnlen (s, maxlen) + const wchar_t *s; + size_t maxlen; +{ + size_t len = 0; + + while (s[len] != L'\0' && maxlen > 0) + { + if (s[++len] == L'\0' || --maxlen == 0) + return len; + if (s[++len] == L'\0' || --maxlen == 0) + return len; + if (s[++len] == L'\0' || --maxlen == 0) + return len; + ++len; + --maxlen; + } + + return len; +} +weak_alias (__wcsnlen, wcsnlen) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsnrtombs.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsnrtombs.c new file mode 100644 index 0000000000..bb2ca1d08b --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsnrtombs.c @@ -0,0 +1,146 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + +#ifndef EILSEQ +# define EILSEQ EINVAL +#endif + + +/* This is the private state used if PS is NULL. */ +static mbstate_t state; + +/* This is a non-standard function but it is very useful in the + implementation of stdio because we have to deal with unterminated + buffers. At most NWC wide character will be converted. */ +size_t +__wcsnrtombs (dst, src, nwc, len, ps) + char *dst; + const wchar_t **src; + size_t nwc; + size_t len; + mbstate_t *ps; +{ + struct __gconv_step_data data; + const wchar_t *srcend; + int status; + size_t result; + struct __gconv_step *tomb; + const struct gconv_fcts *fcts; + + /* Tell where we want the result. */ + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = ps ?: &state; + data.__trans = NULL; + + if (nwc == 0) + return 0; + srcend = *src + __wcsnlen (*src, nwc - 1) + 1; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Get the structure with the function pointers. */ + tomb = fcts->tomb; + + /* We have to handle DST == NULL special. */ + if (dst == NULL) + { + unsigned char buf[256]; /* Just an arbitrary value. */ + const wchar_t *inbuf = *src; + size_t dummy; + + result = 0; + data.__outbufend = buf + sizeof (buf); + + do + { + data.__outbuf = buf; + + status = DL_CALL_FCT (tomb->__fct, + (tomb, &data, (const unsigned char **) &inbuf, + (const unsigned char *) srcend, NULL, + &dummy, 0, 1)); + + /* Count the number of bytes. */ + result += data.__outbuf - buf; + } + while (status == __GCONV_FULL_OUTPUT); + + if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + && data.__outbuf[-1] == '\0') + /* Don't count the NUL character in. */ + --result; + } + else + { + /* This code is based on the safe assumption that all internal + multi-byte encodings use the NUL byte only to mark the end + of the string. */ + size_t dummy; + + data.__outbuf = dst; + data.__outbufend = dst + len; + + status = DL_CALL_FCT (tomb->__fct, + (tomb, &data, (const unsigned char **) src, + (const unsigned char *) srcend, NULL, + &dummy, 0, 1)); + + /* Count the number of bytes. */ + result = data.__outbuf - (unsigned char *) dst; + + /* We have to determine whether the last character converted + is the NUL character. */ + if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + && data.__outbuf[-1] == '\0') + { + assert (data.__outbuf != (unsigned char *) dst); + assert (__mbsinit (data.__statep)); + *src = NULL; + --result; + } + } + + /* There must not be any problems with the conversion but illegal input + characters. */ + assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_ILLEGAL_INPUT + || status == __GCONV_INCOMPLETE_INPUT + || status == __GCONV_FULL_OUTPUT); + + if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT + && status != __GCONV_EMPTY_INPUT) + { + result = (size_t) -1; + __set_errno (EILSEQ); + } + + return result; +} +weak_alias (__wcsnrtombs, wcsnrtombs) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcspbrk.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcspbrk.c new file mode 100644 index 0000000000..9dd09551fd --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcspbrk.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Find the first occurrence in WCS of any wide-character in ACCEPT. */ +wchar_t * +wcspbrk (wcs, accept) + register const wchar_t *wcs; + register const wchar_t *accept; +{ + while (*wcs != L'\0') + if (wcschr (accept, *wcs) == NULL) + ++wcs; + else + return (wchar_t *) wcs; + + return NULL; +} +libc_hidden_def (wcspbrk) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsrchr.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsrchr.c new file mode 100644 index 0000000000..5f4b4781cd --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsrchr.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Find the last occurrence of WC in WCS. */ +wchar_t * +wcsrchr (wcs, wc) + register const wchar_t *wcs; + register const wchar_t wc; +{ + const wchar_t *retval = NULL; + + do + if (*wcs == wc) + retval = wcs; + while (*wcs++ != L'\0'); + + return (wchar_t *) retval; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsrtombs.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsrtombs.c new file mode 100644 index 0000000000..dda115dfd3 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsrtombs.c @@ -0,0 +1,147 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include + +#ifndef EILSEQ +# define EILSEQ EINVAL +#endif + + +/* This is the private state used if PS is NULL. */ +static mbstate_t state; + +size_t +__wcsrtombs (dst, src, len, ps) + char *dst; + const wchar_t **src; + size_t len; + mbstate_t *ps; +{ + struct __gconv_step_data data; + int status; + size_t result; + struct __gconv_step *tomb; + const struct gconv_fcts *fcts; + + /* Tell where we want the result. */ + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = ps ?: &state; + data.__trans = NULL; + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Get the structure with the function pointers. */ + tomb = fcts->tomb; + + /* We have to handle DST == NULL special. */ + if (dst == NULL) + { + mbstate_t temp_state; + unsigned char buf[256]; /* Just an arbitrary value. */ + const wchar_t *srcend = *src + __wcslen (*src) + 1; + const wchar_t *inbuf = *src; + size_t dummy; + + temp_state = *data.__statep; + data.__statep = &temp_state; + + result = 0; + data.__outbufend = buf + sizeof (buf); + + do + { + data.__outbuf = buf; + + status = DL_CALL_FCT (tomb->__fct, + (tomb, &data, (const unsigned char **) &inbuf, + (const unsigned char *) srcend, NULL, + &dummy, 0, 1)); + + /* Count the number of bytes. */ + result += data.__outbuf - buf; + } + while (status == __GCONV_FULL_OUTPUT); + + if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + { + /* There better should be a NUL byte at the end. */ + assert (data.__outbuf[-1] == '\0'); + /* Don't count the NUL character in. */ + --result; + } + } + else + { + /* This code is based on the safe assumption that all internal + multi-byte encodings use the NUL byte only to mark the end + of the string. */ + const wchar_t *srcend = *src + __wcsnlen (*src, len) + 1; + size_t dummy; + + data.__outbuf = dst; + data.__outbufend = dst + len; + + status = DL_CALL_FCT (tomb->__fct, + (tomb, &data, (const unsigned char **) src, + (const unsigned char *) srcend, NULL, + &dummy, 0, 1)); + + /* Count the number of bytes. */ + result = data.__outbuf - (unsigned char *) dst; + + /* We have to determine whether the last character converted + is the NUL character. */ + if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT) + && data.__outbuf[-1] == '\0') + { + assert (data.__outbuf != (unsigned char *) dst); + assert (__mbsinit (data.__statep)); + *src = NULL; + --result; + } + } + + /* There must not be any problems with the conversion but illegal input + characters. */ + assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT + || status == __GCONV_ILLEGAL_INPUT + || status == __GCONV_INCOMPLETE_INPUT + || status == __GCONV_FULL_OUTPUT); + + if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT + && status != __GCONV_EMPTY_INPUT) + { + result = (size_t) -1; + __set_errno (EILSEQ); + } + + return result; +} +weak_alias (__wcsrtombs, wcsrtombs) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsspn.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsspn.c new file mode 100644 index 0000000000..83e2026369 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsspn.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Return the length of the maximum initial segment + of WCS which contains only wide-characters in ACCEPT. */ +size_t +wcsspn (wcs, accept) + const wchar_t *wcs; + const wchar_t *accept; +{ + register const wchar_t *p; + register const wchar_t *a; + register size_t count = 0; + + for (p = wcs; *p != L'\0'; ++p) + { + for (a = accept; *a != L'\0'; ++a) + if (*p == *a) + break; + if (*a == L'\0') + return count; + else + ++count; + } + + return count; +} +libc_hidden_def (wcsspn) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsstr.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsstr.c new file mode 100644 index 0000000000..f785c15218 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsstr.c @@ -0,0 +1,100 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * The original strstr() file contains the following comment: + * + * My personal strstr() implementation that beats most other algorithms. + * Until someone tells me otherwise, I assume that this is the + * fastest implementation of strstr() in C. + * I deliberately chose not to comment it. You should have at least + * as much fun trying to understand it, as I had to write it :-). + * + * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */ + +#include + +wchar_t * +wcsstr (haystack, needle) + const wchar_t *haystack; + const wchar_t *needle; +{ + register wchar_t b, c; + + if ((b = *needle) != L'\0') + { + haystack--; /* possible ANSI violation */ + do + if ((c = *++haystack) == L'\0') + goto ret0; + while (c != b); + + if (!(c = *++needle)) + goto foundneedle; + ++needle; + goto jin; + + for (;;) + { + register wchar_t a; + register const wchar_t *rhaystack, *rneedle; + + do + { + if (!(a = *++haystack)) + goto ret0; + if (a == b) + break; + if ((a = *++haystack) == L'\0') + goto ret0; +shloop: ; + } + while (a != b); + +jin: if (!(a = *++haystack)) + goto ret0; + + if (a != c) + goto shloop; + + if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle))) + do + { + if (a == L'\0') + goto foundneedle; + if (*++rhaystack != (a = *++needle)) + break; + if (a == L'\0') + goto foundneedle; + } + while (*++rhaystack == (a = *++needle)); + + needle = rneedle; /* took the register-poor approach */ + + if (a == L'\0') + break; + } + } +foundneedle: + return (wchar_t*) haystack; +ret0: + return NULL; +} +/* This alias is for backward compatibility with drafts of the ISO C + standard. Unfortunately the Unix(TM) standard requires this name. */ +weak_alias (wcsstr, wcswcs) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcstod.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcstod.c new file mode 100644 index 0000000000..5a39091c25 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcstod.c @@ -0,0 +1,25 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* The actual implementation for all floating point sizes is in strtod.c. */ + +#define USE_WIDE_CHAR 1 + +#include diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcstod_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcstod_l.c new file mode 100644 index 0000000000..87f3a8f7bc --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcstod_l.c @@ -0,0 +1,35 @@ +/* Convert string representing a number to integer value, using given locale. + Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_wchar_t +#include +#include + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 + +extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int, + __locale_t); +extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, + wchar_t **, int, int, + __locale_t); + +#include + +weak_alias (__wcstod_l, wcstod_l) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcstof.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcstof.c new file mode 100644 index 0000000000..02f91ef904 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcstof.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* The actual implementation for all floating point sizes is in strtod.c. + These macros tell it to produce the `float' version, `wcstof'. */ + +#define FLOAT float +#define FLT FLT +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __wcstof_l +#else +# define STRTOF wcstof +#endif +#define MPN2FLOAT __mpn_construct_float +#define FLOAT_HUGE_VAL HUGE_VALF +#define USE_WIDE_CHAR 1 +#define SET_MANTISSA(flt, mant) \ + do { union ieee754_float u; \ + u.f = (flt); \ + if ((mant & 0x7fffff) == 0) \ + mant = 0x400000; \ + u.ieee.mantissa = (mant) & 0x7fffff; \ + (flt) = u.f; \ + } while (0) + +#include diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcstof_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcstof_l.c new file mode 100644 index 0000000000..542961e1fe --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcstof_l.c @@ -0,0 +1,35 @@ +/* Convert string representing a number to integer value, using given locale. + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_wchar_t +#include +#include + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 + +extern float ____wcstof_l_internal (const wchar_t *, wchar_t **, int, + __locale_t); +extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, + wchar_t **, int, int, + __locale_t); + +#include + +weak_alias (__wcstof_l, wcstof_l) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcstok.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcstok.c new file mode 100644 index 0000000000..ab8c73fc81 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcstok.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Parse WCS into tokens separated by characters in DELIM. If WCS is + NULL, the last string wcstok() was called with is used. */ +wchar_t * +wcstok (wcs, delim, save_ptr) + wchar_t *wcs; + const wchar_t *delim; + wchar_t **save_ptr; +{ + wchar_t *result; + + if (wcs == NULL) + { + if (*save_ptr == NULL) + { + __set_errno (EINVAL); + return NULL; + } + else + wcs = *save_ptr; + } + + /* Scan leading delimiters. */ + wcs += wcsspn (wcs, delim); + if (*wcs == L'\0') + { + *save_ptr = NULL; + return NULL; + } + + /* Find the end of the token. */ + result = wcs; + wcs = wcspbrk (result, delim); + if (wcs == NULL) + /* This token finishes the string. */ + *save_ptr = NULL; + else + { + /* Terminate the token and make *SAVE_PTR point past it. */ + *wcs = L'\0'; + *save_ptr = wcs + 1; + } + return result; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcstold.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcstold.c new file mode 100644 index 0000000000..5c58aa69e6 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcstold.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifndef __NO_LONG_DOUBLE_MATH +/* The actual implementation for all floating point sizes is in strtod.c. + These macros tell it to produce the `long double' version, `wcstold'. */ + +# define FLOAT long double +# define FLT LDBL +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __wcstold_l +# else +# define STRTOF wcstold +# endif +# define MPN2FLOAT __mpn_construct_long_double +# define FLOAT_HUGE_VAL HUGE_VALL +# define USE_WIDE_CHAR 1 +# define SET_MANTISSA(flt, mant) \ + do { union ieee854_long_double u; \ + u.d = (flt); \ + if ((mant & 0x7fffffffffffffffULL) == 0) \ + mant = 0x4000000000000000ULL; \ + u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000; \ + u.ieee.mantissa1 = (mant) & 0xffffffff; \ + (flt) = u.d; \ + } while (0) + +# include +#else +/* There is no `long double' type, use the `double' implementations. */ +long double +__wcstold_internal (const wchar_t *nptr, wchar_t **endptr, int group) +{ + return __wcstod_internal (nptr, endptr, group); +} +libc_hidden_def (__wcstold_internal) + +long double +wcstold (const wchar_t *nptr, wchar_t **endptr) +{ + return __wcstod_internal (nptr, endptr, 0); +} +#endif diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcstold_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcstold_l.c new file mode 100644 index 0000000000..91a92124cf --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcstold_l.c @@ -0,0 +1,56 @@ +/* Convert string representing a number to integer value, using given locale. + Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_wchar_t +#include +#include +#include +#include + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 + +#ifndef __NO_LONG_DOUBLE_MATH + +extern long double ____wcstold_l_internal (const wchar_t *, wchar_t **, int, + __locale_t); +extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, + wchar_t **, int, int, + __locale_t); + +# include +#else +/* There is no `long double' type, use the `double' implementations. */ +extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int, + __locale_t); +long double +____wcstold_l_internal (const wchar_t *nptr, wchar_t **endptr, int group, + __locale_t loc) +{ + return ____wcstod_l_internal (nptr, endptr, group, loc); +} + +long double +__wcstold_l (const wchar_t *nptr, wchar_t **endptr, __locale_t loc) +{ + return ____wcstod_l_internal (nptr, endptr, 0, loc); +} +#endif + +weak_alias (__wcstold_l, wcstold_l) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcswidth.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcswidth.c new file mode 100644 index 0000000000..72c0d98c4e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcswidth.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "wcwidth.h" + +/* Determine number of column positions required for first N wide + characters (or fewer if S ends before this) in S. */ +int +wcswidth (const wchar_t *s, size_t n) +{ + int result = 0; + + while (n-- > 0 && *s != L'\0') + { + int now = internal_wcwidth (*s); + if (now == -1) + return -1; + result += now; + ++s; + } + + return result; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm.c new file mode 100644 index 0000000000..10f3d72673 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "../locale/coll-lookup.h" + +#define STRING_TYPE wchar_t +#define USTRING_TYPE wint_t +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRXFRM __wcsxfrm_l +#else +# define STRXFRM wcsxfrm +#endif +#define STRCMP wcscmp +#define STRLEN __wcslen +#define STPNCPY __wcpncpy +#define WEIGHT_H "../locale/weightwc.h" +#define SUFFIX WC +#define L(arg) L##arg +#define WIDE_CHAR_VERSION 1 + +#include "../string/strxfrm.c" diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm_l.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm_l.c new file mode 100644 index 0000000000..13046237a9 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcsxfrm_l.c @@ -0,0 +1,23 @@ +/* Copyright (C) 1996,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_IN_EXTENDED_LOCALE_MODEL 1 +#include + +weak_alias (__wcsxfrm_l, wcsxfrm_l) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wctob.c b/src/kernel/libroot/posix/glibc/wcsmbs/wctob.c new file mode 100644 index 0000000000..d053b9a28f --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wctob.c @@ -0,0 +1,74 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +int +wctob (c) + wint_t c; +{ + char buf[MB_LEN_MAX]; + struct __gconv_step_data data; + wchar_t inbuf[1]; + wchar_t *inptr = inbuf; + size_t dummy; + int status; + const struct gconv_fcts *fcts; + + if (c == WEOF) + return EOF; + + /* Tell where we want the result. */ + data.__outbuf = buf; + data.__outbufend = buf + MB_LEN_MAX; + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = &data.__state; + data.__trans = NULL; + + /* Make sure we start in the initial state. */ + memset (&data.__state, '\0', sizeof (mbstate_t)); + + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Create the input string. */ + inbuf[0] = c; + + status = DL_CALL_FCT (fcts->tomb->__fct, + (fcts->tomb, &data, + (const unsigned char **) &inptr, + (const unsigned char *) &inbuf[1], + NULL, &dummy, 0, 1)); + + /* The conversion failed or the output is too long. */ + if ((status != __GCONV_OK && status != __GCONV_FULL_OUTPUT + && status != __GCONV_EMPTY_INPUT) + || data.__outbuf != (unsigned char *) (buf + 1)) + return EOF; + + return (unsigned char) buf[0]; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.c b/src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.c new file mode 100644 index 0000000000..82dd0201df --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1996, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "wcwidth.h" + +/* Determine number of column positions required for CH. */ +int +wcwidth (wchar_t ch) +{ + return internal_wcwidth (ch); +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.h b/src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.h new file mode 100644 index 0000000000..c24dee9126 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wcwidth.h @@ -0,0 +1,40 @@ +/* Internal header containing implementation of wcwidth() function. + Copyright (C) 1996,1997,1999,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "../wctype/wchar-lookup.h" +#include "../locale/localeinfo.h" + +/* Table containing width information. */ +extern const char *__ctype32_width attribute_hidden; + +static __inline int +internal_wcwidth (wchar_t wc) +{ + unsigned char res; + + /* The tables have been prepared in such a way that + 1. wc == L'\0' yields res = 0, + 2. !iswprint (wc) implies res = '\xff'. */ + res = wcwidth_table_lookup (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_WIDTH), wc); + + return res == (unsigned char) '\xff' ? -1 : (int) res; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wmemchr.c b/src/kernel/libroot/posix/glibc/wcsmbs/wmemchr.c new file mode 100644 index 0000000000..da93e965b2 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wmemchr.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1996,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +wchar_t * +wmemchr (s, c, n) + register const wchar_t *s; + register wchar_t c; + register size_t n; +{ + /* For performance reasons unfold the loop four times. */ + while (n >= 4) + { + if (s[0] == c) + return (wchar_t *) s; + if (s[1] == c) + return (wchar_t *) &s[1]; + if (s[2] == c) + return (wchar_t *) &s[2]; + if (s[3] == c) + return (wchar_t *) &s[3]; + s += 4; + n -= 4; + } + + if (n > 0) + { + if (*s == c) + return (wchar_t *) s; + ++s; + --n; + } + if (n > 0) + { + if (*s == c) + return (wchar_t *) s; + ++s; + --n; + } + if (n > 0) + if (*s == c) + return (wchar_t *) s; + + return NULL; +} +libc_hidden_def (wmemchr) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wmemcmp.c b/src/kernel/libroot/posix/glibc/wcsmbs/wmemcmp.c new file mode 100644 index 0000000000..c6a321b89d --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wmemcmp.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int +wmemcmp (s1, s2, n) + const wchar_t *s1; + const wchar_t *s2; + size_t n; +{ + register wint_t c1; + register wint_t c2; + + while (n >= 4) + { + c1 = (wint_t) s1[0]; + c2 = (wint_t) s2[0]; + if (c1 - c2 != 0) + return c1 - c2; + c1 = (wint_t) s1[1]; + c2 = (wint_t) s2[1]; + if (c1 - c2 != 0) + return c1 - c2; + c1 = (wint_t) s1[2]; + c2 = (wint_t) s2[2]; + if (c1 - c2 != 0) + return c1 - c2; + c1 = (wint_t) s1[3]; + c2 = (wint_t) s2[3]; + if (c1 - c2 != 0) + return c1 - c2; + s1 += 4; + s2 += 4; + n -= 4; + } + + if (n > 0) + { + c1 = (wint_t) s1[0]; + c2 = (wint_t) s2[0]; + if (c1 - c2 != 0) + return c1 - c2; + ++s1; + ++s2; + --n; + } + if (n > 0) + { + c1 = (wint_t) s1[0]; + c2 = (wint_t) s2[0]; + if (c1 - c2 != 0) + return c1 - c2; + ++s1; + ++s2; + --n; + } + if (n > 0) + { + c1 = (wint_t) s1[0]; + c2 = (wint_t) s2[0]; + if (c1 - c2 != 0) + return c1 - c2; + } + + return 0; +} diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wmemcpy.c b/src/kernel/libroot/posix/glibc/wcsmbs/wmemcpy.c new file mode 100644 index 0000000000..f962d3023c --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wmemcpy.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +wchar_t * +__wmemcpy (s1, s2, n) + wchar_t *s1; + const wchar_t *s2; + size_t n; +{ + return (wchar_t *) memcpy ((char *) s1, (char *) s2, n * sizeof (wchar_t)); +} +weak_alias (__wmemcpy, wmemcpy) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wmemmove.c b/src/kernel/libroot/posix/glibc/wcsmbs/wmemmove.c new file mode 100644 index 0000000000..20aceccb85 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wmemmove.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +wchar_t * +__wmemmove (s1, s2, n) + wchar_t *s1; + const wchar_t *s2; + size_t n; +{ + return (wchar_t *) memmove ((char *) s1, (char *) s2, n * sizeof (wchar_t)); +} +weak_alias (__wmemmove, wmemmove) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wmempcpy.c b/src/kernel/libroot/posix/glibc/wcsmbs/wmempcpy.c new file mode 100644 index 0000000000..f97f324635 --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wmempcpy.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +wchar_t * +__wmempcpy (s1, s2, n) + wchar_t *s1; + const wchar_t *s2; + size_t n; +{ + return (wchar_t *) __mempcpy ((char *) s1, (char *) s2, + n * sizeof (wchar_t)); +} +weak_alias (__wmempcpy, wmempcpy) diff --git a/src/kernel/libroot/posix/glibc/wcsmbs/wmemset.c b/src/kernel/libroot/posix/glibc/wcsmbs/wmemset.c new file mode 100644 index 0000000000..ae69f1fd0e --- /dev/null +++ b/src/kernel/libroot/posix/glibc/wcsmbs/wmemset.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1996,97,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +wchar_t * +wmemset (s, c, n) + wchar_t *s; + wchar_t c; + size_t n; +{ + register wchar_t *wp = s; + + while (n >= 4) + { + wp[0] = c; + wp[1] = c; + wp[2] = c; + wp[3] = c; + wp += 4; + n -= 4; + } + + if (n > 0) + { + wp[0] = c; + + if (n > 1) + { + wp[1] = c; + + if (n > 2) + wp[2] = c; + } + } + + return s; +} +libc_hidden_def (wmemset)