summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2003-08-01 20:08:59 +0000
committerManuel Novoa III <mjn3@codepoet.org>2003-08-01 20:08:59 +0000
commit1217289737588e65b088b3535428b27c7287d699 (patch)
tree6a292ac767d219702e26a6a2111737f84a96900c /libc/sysdeps/linux
parent32b76c5ec3c257b7287913d0d1a96e0cbb2e9c6a (diff)
Add a new *scanf implementation, includeing the *wscanf functions.
Should be standards compliant and with several optional features, including support for hexadecimal float notation, locale awareness, glibc-like locale-specific digit grouping with the `'' flag, and positional arg support. I tested it pretty well (finding several bugs in glibc's scanf in the process), but it is brand new so be aware. The *wprintf functions now support floating point output. Also, a couple of bugs were squashed. Finally, %a/%A conversions are now implemented. Implement the glibc xlocale interface for thread-specific locale support. Also add the various *_l(args, locale_t loc_arg) funcs. NOTE!!! setlocale() is NOT threadsafe! NOTE!!! The strto{floating point} conversion functions are now locale aware. The also now support hexadecimal floating point notation. Add the wcsto{floating point} conversion functions. Fix a bug in mktime() related to dst. Note that unlike glibc's mktime, uClibc's version always normalizes the struct tm before attempting to determine the correct dst setting if tm_isdst == -1 on entry. Add a stub version of the libintl functions. (untested) Fixed a known memory leak in setlocale() related to the collation data. Add lots of new config options (which Erik agreed to sort out :-), including finally exposing some of the stripped down stdio configs. Be careful with those though, as they haven't been tested in a long time. (temporary) GOTCHAs... The ctype functions are currently incorrect for 8-bit locales. They will be fixed shortly. The ctype functions are now table-based, resulting in larger staticly linked binaries. I'll be adding an option to use the old approach in the stub locale configuration.
Diffstat (limited to 'libc/sysdeps/linux')
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_ctype.h2
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_fpmax.h132
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_locale.h129
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_stdio.h123
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_touplow.h44
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_uwchar.h56
-rw-r--r--libc/sysdeps/linux/common/bits/xopen_lim.h6
7 files changed, 425 insertions, 67 deletions
diff --git a/libc/sysdeps/linux/common/bits/uClibc_ctype.h b/libc/sysdeps/linux/common/bits/uClibc_ctype.h
index 7ff62e376..294997b74 100644
--- a/libc/sysdeps/linux/common/bits/uClibc_ctype.h
+++ b/libc/sysdeps/linux/common/bits/uClibc_ctype.h
@@ -33,6 +33,8 @@
#ifndef _BITS_CTYPE_H
#define _BITS_CTYPE_H
+#warning uClibc_ctype.h is deprecated
+
/* Taking advantage of the C99 mutual-exclusion guarantees for the various
* (w)ctype classes, including the descriptions of printing and control
* (w)chars, we can place each in one of the following mutually-exlusive
diff --git a/libc/sysdeps/linux/common/bits/uClibc_fpmax.h b/libc/sysdeps/linux/common/bits/uClibc_fpmax.h
new file mode 100644
index 000000000..08d47129c
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/uClibc_fpmax.h
@@ -0,0 +1,132 @@
+/* Copyright (C) 2003 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Define a maximal floating point type, and the associated constants
+ * that are defined for the floating point types in float.h.
+ *
+ * This is to support archs that are missing long double, or even double.
+ */
+
+#ifndef _UCLIBC_FPMAX_H
+#define _UCLIBC_FPMAX_H
+
+#ifndef _ISOC99_SOURCE
+#define _ISOC99_SOURCE 1
+#endif
+
+#include <features.h>
+#include <float.h>
+
+#ifdef __UCLIBC_HAS_FLOATS__
+
+#if defined(LDBL_MANT_DIG)
+
+typedef long double __fpmax_t;
+#define FPMAX_TYPE 3
+
+#define FPMAX_MANT_DIG LDBL_MANT_DIG
+#define FPMAX_DIG LDBL_DIG
+#define FPMAX_EPSILON LDBL_EPSILON
+#define FPMAX_MIN_EXP LDBL_MIN_EXP
+#define FPMAX_MIN LDBL_MIN
+#define FPMAX_MIN_10_EXP LDBL_MIN_10_EXP
+#define FPMAX_MAX_EXP LDBL_MAX_EXP
+#define FPMAX_MAX LDBL_MAX
+#define FPMAX_MAX_10_EXP LDBL_MAX_10_EXP
+
+#elif defined(DBL_MANT_DIG)
+
+typedef double __fpmax_t;
+#define FPMAX_TYPE 2
+
+#define FPMAX_MANT_DIG DBL_MANT_DIG
+#define FPMAX_DIG DBL_DIG
+#define FPMAX_EPSILON DBL_EPSILON
+#define FPMAX_MIN_EXP DBL_MIN_EXP
+#define FPMAX_MIN DBL_MIN
+#define FPMAX_MIN_10_EXP DBL_MIN_10_EXP
+#define FPMAX_MAX_EXP DBL_MAX_EXP
+#define FPMAX_MAX DBL_MAX
+#define FPMAX_MAX_10_EXP DBL_MAX_10_EXP
+
+#elif defined(FLT_MANT_DIG)
+
+typedef float __fpmax_t;
+#define FPMAX_TYPE 1
+
+#define FPMAX_MANT_DIG FLT_MANT_DIG
+#define FPMAX_DIG FLT_DIG
+#define FPMAX_EPSILON FLT_EPSILON
+#define FPMAX_MIN_EXP FLT_MIN_EXP
+#define FPMAX_MIN FLT_MIN
+#define FPMAX_MIN_10_EXP FLT_MIN_10_EXP
+#define FPMAX_MAX_EXP FLT_MAX_EXP
+#define FPMAX_MAX FLT_MAX
+#define FPMAX_MAX_10_EXP FLT_MAX_10_EXP
+
+#else
+#error unable to determine appropriate type for __fpmax_t!
+#endif
+
+#ifndef DECIMAL_DIG
+
+#ifdef L___strtofpmax
+/* Emit warning only once. */
+#warning DECIMAL_DIG is not defined! If you are using gcc, it may not be defining __STDC_VERSION__ as it should.
+#endif
+#if !defined(FLT_RADIX) || (FLT_RADIX != 2)
+#error unable to compensate for missing DECIMAL_DIG!
+#endif
+
+/* ceil (1 + #mantissa * log10 (FLT_RADIX)) */
+#define DECIMAL_DIG (1 + (((FPMAX_MANT_DIG * 100) + 331) / 332))
+
+#endif /* DECIMAL_DIG */
+
+extern __fpmax_t __strtofpmax(const char *str, char **endptr, int exp_adjust);
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+extern __fpmax_t __strtofpmax_l(const char *str, char **endptr, int exp_adjust,
+ __locale_t locale_arg);
+#endif
+
+#ifdef __UCLIBC_HAS_WCHAR__
+extern __fpmax_t __wcstofpmax(const wchar_t *wcs, wchar_t **endptr,
+ int exp_adjust);
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+extern __fpmax_t __wcstofpmax_l(const wchar_t *wcs, wchar_t **endptr,
+ int exp_adjust, __locale_t locale_arg);
+#endif
+#endif /* __UCLIBC_HAS_WCHAR__ */
+
+/* The following checks in an __fpmax_t is either 0 or +/- infinity.
+ *
+ * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
+ *
+ * This only works if __fpmax_t is the actual maximal floating point type used
+ * in intermediate calculations. Otherwise, excess precision in the
+ * intermediate values can cause the test to fail.
+ *
+ * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
+ */
+
+#define __FPMAX_ZERO_OR_INF_CHECK(x) ((x) == ((x)/4) )
+
+#endif /* __UCLIBC_HAS_FLOATS__ */
+
+#endif /* _UCLIBC_FPMAX_H */
diff --git a/libc/sysdeps/linux/common/bits/uClibc_locale.h b/libc/sysdeps/linux/common/bits/uClibc_locale.h
index 4e89188b8..56819ba62 100644
--- a/libc/sysdeps/linux/common/bits/uClibc_locale.h
+++ b/libc/sysdeps/linux/common/bits/uClibc_locale.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Manuel Novoa III
+/* Copyright (C) 2002, 2003 Manuel Novoa III
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -32,18 +32,17 @@
/**********************************************************************/
/* uClibc compatibilty stuff */
-#ifdef __UCLIBC_HAS_WCHAR__
-#define __WCHAR_ENABLED
-#endif
-
-
#ifdef __UCLIBC_HAS_LOCALE__
#undef __LOCALE_C_ONLY
#else /* __UCLIBC_HAS_LOCALE__ */
-#define __LOCALE_C_ONLY
+#define __LOCALE_C_ONLY
+
+#define __XL(N) N
+#define __LOCALE_PARAM
+#define __LOCALE_ARG
#endif /* __UCLIBC_HAS_LOCALE__ */
@@ -63,43 +62,18 @@
#define __LC_ALL 6
/**********************************************************************/
-#if defined(_LIBC) && defined(__WCHAR_ENABLED)
-
-/* TODO: This really needs to be somewhere else... */
-#include <limits.h>
-#include <stdint.h>
-
-#if WCHAR_MIN == 0
-typedef wchar_t __uwchar_t;
-#elif WCHAR_MAX <= USHRT_MAX
-typedef unsigned short __uwchar_t;
-#elif WCHAR_MAX <= UINT_MAX
-typedef unsigned int __uwchar_t;
-#elif WCHAR_MAX <= ULONG_MAX
-typedef unsigned long __uwchar_t;
-#elif defined(ULLONG_MAX) && (WCHAR_MAX <= ULLONG_MAX)
-typedef unsigned long long __uwchar_t;
-#elif WCHAR_MAX <= UINT_MAX
-typedef uintmax_t __uwchar_t;
-#else
-#error Can not determine an appropriate type for __uwchar_t!
-#endif
-
-#endif
-
-/**********************************************************************/
-#if defined(_LIBC) && !defined(__LOCALE_C_ONLY)
+/* #if defined(_LIBC) && !defined(__LOCALE_C_ONLY) */
+#ifndef __LOCALE_C_ONLY
#include <stddef.h>
#include <stdint.h>
-#include <bits/uClibc_locale_data.h>
+#include <bits/uClibc_touplow.h>
+#include <bits/uClibc_locale_data.h>
extern void _locale_set(const unsigned char *p);
extern void _locale_init(void);
-/* TODO: assumes 8-bit chars!!! */
-
enum {
__ctype_encoding_7_bit, /* C/POSIX */
__ctype_encoding_utf8, /* UTF-8 */
@@ -164,6 +138,12 @@ typedef struct {
/* static unsigned char cur_locale[LOCALE_STRING_SIZE]; */
typedef struct {
+#ifdef __UCLIBC_HAS_XLOCALE__
+ const __uint16_t *__ctype_b;
+ const __ctype_touplow_t *__ctype_tolower;
+ const __ctype_touplow_t *__ctype_toupper;
+#endif
+
/* int tables_loaded; */
/* unsigned char lctypes[LOCALE_STRING_SIZE]; */
unsigned char cur_locale[LOCALE_STRING_SIZE];
@@ -185,21 +165,30 @@ typedef struct {
const unsigned char *tbl8ctype;
const unsigned char *idx8uplow;
const unsigned char *tbl8uplow;
-#ifdef __WCHAR_ENABLED
+#ifdef __UCLIBC_HAS_WCHAR__
const unsigned char *idx8c2wc;
const uint16_t *tbl8c2wc; /* char > 0x7f to wide char */
const unsigned char *idx8wc2c;
const unsigned char *tbl8wc2c;
/* translit */
-#endif /* __WCHAR_ENABLED */
+#endif /* __UCLIBC_HAS_WCHAR__ */
#endif /* __CTYPE_HAS_8_BIT_LOCALES */
-#ifdef __WCHAR_ENABLED
+#ifdef __UCLIBC_HAS_WCHAR__
+
+ const uint16_t *code2flag;
+
const unsigned char *tblwctype;
const unsigned char *tblwuplow;
/* const unsigned char *tblwcomb; */
const int16_t *tblwuplow_diff; /* yes... signed */
/* width?? */
-#endif /* __WCHAR_ENABLED */
+
+ wchar_t decimal_point_wc;
+ wchar_t thousands_sep_wc;
+ int decimal_point_len;
+ int thousands_sep_len;
+
+#endif /* __UCLIBC_HAS_WCHAR__ */
/* ctype */
const char *outdigit0_mb;
@@ -313,10 +302,68 @@ typedef struct {
/* collate is at the end */
__collate_t collate;
-} __locale_t;
+} __uclibc_locale_t;
+
+typedef __uclibc_locale_t *__locale_t;
extern __locale_t __global_locale;
+
+extern int __locale_mbrtowc_l(wchar_t *__restrict dst,
+ const char *__restrict src,
+ __locale_t loc );
+
+#ifdef L_setlocale
+/* so we only get the warning once... */
+#warning need thread version of CUR_LOCALE!
+#endif
+/**********************************************************************/
+#ifdef __UCLIBC_HAS_XLOCALE__
+
+extern __locale_t __curlocale_var;
+
+#ifdef __UCLIBC_HAS_THREADS__
+
+extern __locale_t __curlocale(void) __THROW __attribute__ ((__const__));
+extern __locale_t __curlocale_set(__locale_t new);
+#define __UCLIBC_CURLOCALE (__curlocale())
+#define __UCLIBC_CURLOCALE_DATA (*__curlocale())
+
+#else /* __UCLIBC_HAS_THREADS__ */
+
+#define __UCLIBC_CURLOCALE (__curlocale_var)
+#define __UCLIBC_CURLOCALE_DATA (*__curlocale_var)
+
+#endif /* __UCLIBC_HAS_THREADS__ */
+
+#elif defined(__UCLIBC_HAS_LOCALE__)
+
+#define __UCLIBC_CURLOCALE (__global_locale)
+#define __UCLIBC_CURLOCALE_DATA (*__global_locale)
+
+#endif
+/**********************************************************************/
+#if defined(__UCLIBC_HAS_XLOCALE__) && defined(__UCLIBC_DO_XLOCALE)
+
+#define __XL(N) N ## _l
+#define __LOCALE_PARAM , __locale_t locale_arg
+#define __LOCALE_ARG , locale_arg
+#define __LOCALE_PTR locale_arg
+
+#else /* defined(__UCLIBC_HAS_XLOCALE__) && defined(__STDLIB_DO_XLOCALE) */
+
+#define __XL(N) N
+#define __LOCALE_PARAM
+#define __LOCALE_ARG
+#define __LOCALE_PTR __UCLIBC_CURLOCALE
+
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && defined(__STDLIB_DO_XLOCALE) */
+/**********************************************************************/
+
+extern __locale_t __newlocale(int category_mask, const char *locale, __locale_t base)
+ __THROW;
+
#endif /* defined(_LIBC) && !defined(__LOCALE_C_ONLY) */
+/**********************************************************************/
#endif /* _UCLIBC_LOCALE_H */
diff --git a/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/libc/sysdeps/linux/common/bits/uClibc_stdio.h
index 59156eeea..6c0cff7ed 100644
--- a/libc/sysdeps/linux/common/bits/uClibc_stdio.h
+++ b/libc/sysdeps/linux/common/bits/uClibc_stdio.h
@@ -44,6 +44,79 @@
#define __STDIO_WIDE
#endif
+#define __STDIO_BUFFERS
+/* ANSI/ISO mandate at least 256. */
+#if defined(__UCLIBC_HAS_STDIO_BUFSIZ_NONE__)
+/* Fake this because some apps use stdio.h BUFSIZ. */
+#define _STDIO_BUFSIZ 256
+#undef __STDIO_BUFFERS
+#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_256__)
+#define _STDIO_BUFSIZ 256
+#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_512__)
+#define _STDIO_BUFSIZ 512
+#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_1024__)
+#define _STDIO_BUFSIZ 1024
+#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_2048__)
+#define _STDIO_BUFSIZ 2048
+#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_4096__)
+#define _STDIO_BUFSIZ 4096
+#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_8192__)
+#define _STDIO_BUFSIZ 8192
+#else
+#error config seems to be out of sync regarding bufsiz options
+#endif
+
+#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
+#define __STDIO_GETC_MACRO
+#endif
+
+#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
+#define __STDIO_PUTC_MACRO
+#endif
+
+#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__
+#define __STDIO_AUTO_RW_TRANSITION
+#endif
+
+#ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__
+#define __STDIO_FOPEN_LARGEFILE_MODE
+#endif
+
+#ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__
+#define __STDIO_FOPEN_EXCLUSIVE_MODE
+#endif
+
+#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__
+#define __STDIO_PRINTF_M_SUPPORT
+#endif
+
+#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
+#define __STDIO_GLIBC_CUSTOM_STREAMS
+#endif
+
+#ifdef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__
+#define _STDIO_BUILTIN_BUF_SIZE 0
+#else /* __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ */
+#if defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__)
+#define _STDIO_BUILTIN_BUF_SIZE 0
+#elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__)
+#define _STDIO_BUILTIN_BUF_SIZE 4
+#elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__)
+#define _STDIO_BUILTIN_BUF_SIZE 8
+#else
+#error config seems to be out of sync regarding builtin buffer size
+#endif
+#endif /* __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ */
+
+#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__
+#define __STDIO_GLIBC_CUSTOM_PRINTF
+#endif
+
+
+/* Currently unimplemented/untested */
+/* #define __STDIO_FLEXIBLE_SETVBUF */
+
+
/* Make sure defines related to large files are consistent. */
#ifdef _LIBC
@@ -81,32 +154,23 @@
#include <wchar.h>
#endif
-#define __STDIO_BUFFERS
-#define __STDIO_GETC_MACRO
-#define __STDIO_PUTC_MACRO
/* For uClibc, these are currently handled above. */
-/* #define __STDIO_LARGE_FILES */
-/* #define __STDIO_THREADSAFE */
-
+/* #define __STDIO_BUFFERS */
+/* #define __STDIO_GETC_MACRO */
+/* #define __STDIO_PUTC_MACRO */
+/* #define __STDIO_LARGE_FILES */
+/* #define __STDIO_THREADSAFE */
+/* ANSI/ISO mandate at least 256. */
+/* #define _STDIO_BUFSIZ 256 */
+/* #define __STDIO_AUTO_RW_TRANSITION */
+/* #define __STDIO_FOPEN_EXCLUSIVE_MODE */
+/* #define __STDIO_PRINTF_M_SPEC */
+/* #define __STDIO_GLIBC_CUSTOM_STREAMS */
/* L mode extension for fopen. */
-#define __STDIO_FOPEN_LARGEFILE_MODE
-
+/* #define __STDIO_FOPEN_LARGEFILE_MODE */
/* size of builtin buf -- only tested with 0 */
-#define _STDIO_BUILTIN_BUF_SIZE 0
-
-/* TODO - enable features based on __STDIO_GLIBC_FEATURES */
-
-/* #define __STDIO_GLIBC_FEATURES */
-#define __STDIO_AUTO_RW_TRANSITION
-#define __STDIO_FOPEN_EXCLUSIVE_MODE
-#define __STDIO_PRINTF_M_SPEC
-#define __STDIO_GLIBC_CUSTOM_STREAMS
-
-
-/* ANSI/ISO mandate at least 256. */
-#define _STDIO_BUFSIZ 256
-
+/* #define _STDIO_BUILTIN_BUF_SIZE 0 */
/* Currently unimplemented/untested */
/* #define __STDIO_FLEXIBLE_SETVBUF */
@@ -173,7 +237,10 @@
typedef struct {
__off_t __pos;
#ifdef __STDIO_MBSTATE
- __mbstate_t __mbstate;
+ __mbstate_t __mbstate;
+#endif
+#ifdef __STDIO_WIDE
+ int mblen_pending;
#endif
} __stdio_fpos_t;
@@ -181,7 +248,10 @@ typedef struct {
typedef struct {
__off64_t __pos;
#ifdef __STDIO_MBSTATE
- __mbstate_t __mbstate;
+ __mbstate_t __mbstate;
+#endif
+#ifdef __STDIO_WIDE
+ int mblen_pending;
#endif
} __stdio_fpos64_t;
#endif
@@ -234,6 +304,7 @@ typedef _IO_cookie_io_functions_t cookie_io_functions_t;
* 0 1 one user (unused ungot is 1) or one scanf (unused ungot is 0)
* 1 0 must be scanf[0] and user[1]
* 1 1 illegal -- could be used to signal safe for setbuf
+ * but if used, need to fix _stdio_adjpos at least!
*/
#ifdef __UCLIBC__
@@ -244,8 +315,8 @@ struct __stdio_file_struct {
unsigned short modeflags;
/* There could be a hole here, but modeflags is used most.*/
#ifdef __STDIO_WIDE
- /* TOOD - ungot_width could be combined with ungot. But what about hole? */
- unsigned char ungot_width[2];
+ /* TODO - ungot_width could be combined with ungot. But what about hole? */
+ unsigned char ungot_width[2]; /* 0 is current (building) char, 1 is scanf */
wchar_t ungot[2];
#else /* __STDIO_WIDE */
unsigned char ungot[2];
diff --git a/libc/sysdeps/linux/common/bits/uClibc_touplow.h b/libc/sysdeps/linux/common/bits/uClibc_touplow.h
new file mode 100644
index 000000000..75d508546
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/uClibc_touplow.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
+ *
+ * Besides uClibc, I'm using this code in my libc for elks, which is
+ * a 16-bit environment with a fairly limited compiler. It would make
+ * things much easier for me if this file isn't modified unnecessarily.
+ * In particular, please put any new or replacement functions somewhere
+ * else, and modify the makefile to use your version instead.
+ * Thanks. Manuel
+ *
+ * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
+
+#ifndef _UCLIBC_TOUPLOW_H
+#define _UCLIBC_TOUPLOW_H
+
+#include <features.h>
+#include <bits/types.h>
+
+/* glibc uses the equivalent of - typedef __int32_t __ctype_touplow_t; */
+
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+typedef __int16_t __ctype_touplow_t;
+#else /* __UCLIBC_HAS_CTYPE_SIGNED__ */
+typedef unsigned char __ctype_touplow_t;
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__ */
+
+#endif /* _UCLIBC_TOUPLOW_H */
+
diff --git a/libc/sysdeps/linux/common/bits/uClibc_uwchar.h b/libc/sysdeps/linux/common/bits/uClibc_uwchar.h
new file mode 100644
index 000000000..206191276
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/uClibc_uwchar.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2003 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
+ *
+ * Besides uClibc, I'm using this code in my libc for elks, which is
+ * a 16-bit environment with a fairly limited compiler. It would make
+ * things much easier for me if this file isn't modified unnecessarily.
+ * In particular, please put any new or replacement functions somewhere
+ * else, and modify the makefile to use your version instead.
+ * Thanks. Manuel
+ *
+ * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
+
+
+/* Define an internal unsigned int type __uwchar_t just large enough
+ * to hold a wchar_t.
+ */
+
+#ifndef _UCLIBC_UWCHAR_H
+#define _UCLIBC_UWCHAR_H
+
+#include <limits.h>
+#include <stdint.h>
+
+#if WCHAR_MIN == 0
+typedef wchar_t __uwchar_t;
+#elif WCHAR_MAX <= USHRT_MAX
+typedef unsigned short __uwchar_t;
+#elif WCHAR_MAX <= UINT_MAX
+typedef unsigned int __uwchar_t;
+#elif WCHAR_MAX <= ULONG_MAX
+typedef unsigned long __uwchar_t;
+#elif defined(ULLONG_MAX) && (WCHAR_MAX <= ULLONG_MAX)
+typedef unsigned long long __uwchar_t;
+#elif WCHAR_MAX <= UINTMAX_MAX
+typedef uintmax_t __uwchar_t;
+#else
+#error Can not determine an appropriate type for __uwchar_t!
+#endif
+
+#endif /* _UCLIBC_UWCHAR_H */
diff --git a/libc/sysdeps/linux/common/bits/xopen_lim.h b/libc/sysdeps/linux/common/bits/xopen_lim.h
index 90cb54123..c2363ab04 100644
--- a/libc/sysdeps/linux/common/bits/xopen_lim.h
+++ b/libc/sysdeps/linux/common/bits/xopen_lim.h
@@ -68,7 +68,13 @@
/* Maximum value of `digit' in calls to the `printf' and `scanf'
functions. Posix dictates this should be a minimum of 9 */
+#if !defined(__UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__) || (__UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ <= 1)
+#undef NL_ARGMAX
+#elif __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ < 9
#define NL_ARGMAX 9
+#else
+#define NL_ARGMAX __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__
+#endif
/* Maximum number of bytes in a `LANG' name. We have no limit. */
#define NL_LANGMAX _POSIX2_LINE_MAX