OSDN Git Service

Enable WCHAR support for C/POSIX stub locales.
authorManuel Novoa III <mjn3@codepoet.org>
Wed, 3 Jul 2002 17:24:17 +0000 (17:24 -0000)
committerManuel Novoa III <mjn3@codepoet.org>
Wed, 3 Jul 2002 17:24:17 +0000 (17:24 -0000)
Implemented unformatted wide i/o functions. (ungetwc still needs testing)
Fix a few bugs in wchar.c.
Modifications for bcc/elks support.

20 files changed:
Rules.mak
include/printf.h
include/stdlib.h
libc/misc/assert/__assert.c
libc/misc/locale/locale.c
libc/misc/time/time.c
libc/misc/wchar/Makefile
libc/misc/wchar/wchar.c
libc/misc/wchar/wstdio.c [new file with mode: 0644]
libc/misc/wctype/wctype.c
libc/stdio/Makefile
libc/stdio/old_vfprintf.c
libc/stdio/printf.c
libc/stdio/scanf.c
libc/stdio/stdio.c
libc/stdlib/stdlib.c
libc/string/Makefile
libc/string/wstring.c
libc/sysdeps/linux/common/bits/uClibc_locale.h
libc/sysdeps/linux/common/bits/uClibc_stdio.h

index e35f9f7..cc93523 100644 (file)
--- a/Rules.mak
+++ b/Rules.mak
@@ -125,11 +125,6 @@ ifeq ($(strip $(INCLUDE_THREADS)),true)
     CFLAGS  += -D_LIBC_REENTRANT
 endif
 
-# Locale support is required for wide char support.
-ifneq ($(strip $(HAS_LOCALE)),true)
-    HAS_WCHAR:=false
-endif
-
 # TARGET_PREFIX is the directory under which which the uClibc runtime
 # environment will be installed and used on the target system.   The 
 # result will look something like the following:
index 8b0a66c..96e4afa 100644 (file)
@@ -154,7 +154,7 @@ struct printf_info
    The function should return the number of characters written,
    or -1 for errors.  */
 
-typedef int printf_function (FILE *__stream,
+typedef int (*printf_function) (FILE *__stream,
                             __const struct printf_info *__info,
                             __const void *__const *__args);
 
index 1920e41..235045f 100644 (file)
@@ -109,6 +109,7 @@ typedef struct
 # define __ldiv_t_defined      1
 #endif
 
+#ifdef __UCLIBC_HAS_LONG_LONG__
 #if defined __USE_ISOC99 && !defined __lldiv_t_defined
 /* Returned by `lldiv'.  */
 __extension__ typedef struct
@@ -118,6 +119,7 @@ __extension__ typedef struct
   } lldiv_t;
 # define __lldiv_t_defined     1
 #endif
+#endif /* __UCLIBC_HAS_LONG_LONG__ */
 
 
 /* The largest number rand will return (same as INT_MAX).  */
@@ -136,19 +138,24 @@ __extension__ typedef struct
 extern size_t _stdlib_mb_cur_max (void) __THROW;
 #endif
 
+#ifdef __UCLIBC_HAS_FLOATS__
 /* Convert a string to a floating-point number.  */
 extern double atof (__const char *__nptr) __THROW __attribute_pure__;
+#endif /* __UCLIBC_HAS_FLOATS__ */
 /* 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__;
 
+#ifdef __UCLIBC_HAS_LONG_LONG__
 #if defined __USE_ISOC99 || (defined __GNUC__ && defined __USE_MISC)
 /* Convert a string to a long long integer.  */
 __extension__ extern long long int atoll (__const char *__nptr)
      __THROW __attribute_pure__;
 #endif
+#endif /* __UCLIBC_HAS_LONG_LONG__ */
 
+#ifdef __UCLIBC_HAS_FLOATS__
 /* Convert a string to a floating-point number.  */
 extern double strtod (__const char *__restrict __nptr,
                      char **__restrict __endptr) __THROW;
@@ -161,6 +168,7 @@ extern float strtof (__const char *__restrict __nptr,
 extern long double strtold (__const char *__restrict __nptr,
                            char **__restrict __endptr) __THROW;
 #endif
+#endif /* __UCLIBC_HAS_FLOATS__ */
 
 /* Convert a string to a long integer.  */
 extern long int strtol (__const char *__restrict __nptr,
@@ -170,6 +178,7 @@ extern unsigned long int strtoul (__const char *__restrict __nptr,
                                  char **__restrict __endptr, int __base)
      __THROW;
 
+#ifdef __UCLIBC_HAS_LONG_LONG__
 #if defined __GNUC__ && defined __USE_BSD
 /* Convert a string to a quadword integer.  */
 __extension__
@@ -195,6 +204,7 @@ extern unsigned long long int strtoull (__const char *__restrict __nptr,
                                        char **__restrict __endptr, int __base)
      __THROW;
 #endif /* ISO C99 or GCC and use MISC.  */
+#endif /* __UCLIBC_HAS_LONG_LONG__ */
 
 
 #if 0
@@ -251,6 +261,7 @@ extern long double __strtold_l (__const char *__restrict __nptr,
 /* The internal entry points for `strtoX' take an extra flag argument
    saying whether or not to parse locale-dependent number grouping.  */
 
+#ifdef __UCLIBC_HAS_FLOATS__
 extern double __strtod_internal (__const char *__restrict __nptr,
                                 char **__restrict __endptr, int __group)
      __THROW;
@@ -260,6 +271,7 @@ extern float __strtof_internal (__const char *__restrict __nptr,
 extern long double __strtold_internal (__const char *__restrict __nptr,
                                       char **__restrict __endptr,
                                       int __group) __THROW;
+#endif /* __UCLIBC_HAS_FLOATS__ */
 #ifndef __strtol_internal_defined
 extern long int __strtol_internal (__const char *__restrict __nptr,
                                   char **__restrict __endptr,
@@ -272,6 +284,7 @@ extern unsigned long int __strtoul_internal (__const char *__restrict __nptr,
                                             int __base, int __group) __THROW;
 # define __strtoul_internal_defined    1
 #endif
+#ifdef __UCLIBC_HAS_LONG_LONG__
 #if defined __GNUC__ || defined __USE_ISOC99
 # ifndef __strtoll_internal_defined
 __extension__
@@ -290,6 +303,7 @@ extern unsigned long long int __strtoull_internal (__const char *
 #  define __strtoull_internal_defined  1
 # endif
 #endif /* GCC */
+#endif /* __UCLIBC_HAS_LONG_LONG__ */
 
 #ifdef __USE_EXTERN_INLINES
 /* Define inline functions which call the internal entry points.  */
@@ -460,9 +474,11 @@ extern int rand_r (unsigned int *__seed) __THROW;
 #if defined __USE_SVID || defined __USE_XOPEN
 /* System V style 48-bit random number generator functions.  */
 
+#ifdef __UCLIBC_HAS_FLOATS__
 /* 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;
+#endif /* __UCLIBC_HAS_FLOATS__ */
 
 /* Return non-negative, long integer in [0,2^31).  */
 extern long int lrand48 (void) __THROW;
@@ -487,15 +503,19 @@ struct drand48_data
     unsigned short int __old_x[3]; /* Old state.  */
     unsigned short int __c;    /* Additive const. in congruential formula.  */
     unsigned short int __init; /* Flag for initializing.  */
+#ifdef __UCLIBC_HAS_LONG_LONG__
     unsigned long long int __a;        /* Factor in congruential formula.  */
+#endif /* __UCLIBC_HAS_LONG_LONG__ */
   };
 
+#ifdef __UCLIBC_HAS_FLOATS__
 /* 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;
+#endif /* __UCLIBC_HAS_FLOATS__ */
 
 /* Return non-negative, long integer in [0,2^31).  */
 extern int lrand48_r (struct drand48_data *__restrict __buffer,
@@ -707,10 +727,12 @@ extern void qsort (void *__base, size_t __nmemb, size_t __size,
 /* Return the absolute value of X.  */
 extern int abs (int __x) __THROW __attribute__ ((__const__));
 extern long int labs (long int __x) __THROW __attribute__ ((__const__));
+#ifdef __UCLIBC_HAS_LONG_LONG__
 #ifdef __USE_ISOC99
 __extension__ extern long long int llabs (long long int __x)
      __THROW __attribute__ ((__const__));
 #endif
+#endif /* #ifdef __UCLIBC_HAS_LONG_LONG__ */
 
 
 /* Return the `div_t', `ldiv_t' or `lldiv_t' representation
@@ -720,13 +742,16 @@ extern div_t div (int __numer, int __denom)
      __THROW __attribute__ ((__const__));
 extern ldiv_t ldiv (long int __numer, long int __denom)
      __THROW __attribute__ ((__const__));
+#ifdef __UCLIBC_HAS_LONG_LONG__
 #ifdef __USE_ISOC99
 __extension__ extern lldiv_t lldiv (long long int __numer,
                                    long long int __denom)
      __THROW __attribute__ ((__const__));
 #endif
+#endif /* __UCLIBC_HAS_LONG_LONG__ */
 
 
+#ifdef __UCLIBC_HAS_FLOATS__
 #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.  */
@@ -775,6 +800,7 @@ extern int qfcvt_r (long double __value, int __ndigit,
                    char *__restrict __buf, size_t __len) __THROW;
 # endif        /* misc */
 #endif /* use MISC || use X/Open Unix */
+#endif /* __UCLIBC_HAS_FLOATS__ */
 
 #ifdef __UCLIBC_HAS_WCHAR__
 /* Return the length of the multibyte character
index fba9dc7..db5f9a7 100644 (file)
@@ -28,7 +28,7 @@
 #undef assert
 
 void __assert(const char *assertion, const char * filename,
-                         int linenumber, const char * function)
+                         int linenumber, register const char * function)
 {
        char buf[__BUFLEN_INT10TOSTR];
 
index fd52782..689257b 100644 (file)
 #include <stdint.h>
 #include <assert.h>
 
-#ifdef __LOCALE_C_ONLY
-
-#ifdef __WCHAR_ENABLED
-#error wide char support requires full locale support
-#endif
-
-#else  /* __LOCALE_C_ONLY */
+#ifndef __LOCALE_C_ONLY
 
 #define CUR_LOCALE_SPEC                        (__global_locale.cur_locale)
 #undef CODESET_LIST
@@ -496,14 +490,15 @@ void _locale_set(const unsigned char *p)
  *   ctype, numeric, monetary, time, collate, messages, all
  */
 
+#define C_LC_ALL 6
 
 /* Combine the data to avoid size penalty for seperate char arrays when
  * compiler aligns objects.  The original code is left in as documentation. */
 #define cat_start nl_data
-#define C_locale_data nl_data + LC_ALL + 1 + 78
+#define C_locale_data (nl_data + C_LC_ALL + 1 + 78)
 
-static const unsigned char nl_data[LC_ALL + 1 + 78 + 300] = {
-/*  static const unsigned char cat_start[LC_ALL + 1] = { */
+static const unsigned char nl_data[C_LC_ALL + 1 + 78 + 300] = {
+/*  static const unsigned char cat_start[C_LC_ALL + 1] = { */
        '\x00', '\x01', '\x04', '\x1a', '\x4c', '\x4c', '\x4e', 
 /*  }; */
 /*  static const unsigned char item_offset[78] = { */
@@ -564,10 +559,10 @@ char *nl_langinfo(nl_item item)
        unsigned int c;
        unsigned int i;
 
-       if ((c = _NL_ITEM_CATEGORY(item)) < LC_ALL) {
+       if ((c = _NL_ITEM_CATEGORY(item)) < C_LC_ALL) {
                if ((i = cat_start[c] + _NL_ITEM_INDEX(item)) < cat_start[c+1]) {
 /*                     return (char *) C_locale_data + item_offset[i] + (i & 64); */
-                       return (char *) C_locale_data + nl_data[LC_ALL+1+i] + (i & 64);
+                       return (char *) C_locale_data + nl_data[C_LC_ALL+1+i] + (i & 64);
                }
        }
        return (char *) cat_start;      /* Conveniently, this is the empty string. */
index 409be32..e7e3b84 100644 (file)
 #endif
 
 /* TODO - This stuff belongs in some include/bits/ file. */
-#ifndef __BCC__
 #undef CLK_TCK
 #if (TARGET_ARCH == alpha) || (TARGET_ARCH == ia64)
 #define CLK_TCK     1024
 #else
 #define CLK_TCK     100
 #endif
-#endif
 
 /* The era code is currently unfinished. */
 /*  #define ENABLE_ERA_CODE */
@@ -1855,9 +1853,8 @@ time_t _time_mktime(struct tm *timeptr, int store_on_success)
        }
 
 #ifdef __BCC__
-       /* TODO - check */
        d = p[5] - 1;
-       days = -719163L + d*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]);
+       days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]);
        secs = p[0] + 60*( p[1] + 60*((long)(p[2])) )
                + _time_tzinfo[timeptr->tm_isdst > 0].gmt_offset;
        if (secs < 0) {
index 23a1e9b..ddd701a 100644 (file)
 TOPDIR=../../../
 include $(TOPDIR)Rules.mak
 
-MSRC=  wchar.c
-MOBJ=  btowc.o wctob.o mbsinit.o mbrlen.o mbrtowc.o wcrtomb.o mbsrtowcs.o \
-       wcsrtombs.o _wchar_utf8sntowcs.o _wchar_wcstoutf8s.o \
+MSRC1=  wchar.c
+MOBJ1=  btowc.o wctob.o mbsinit.o mbrlen.o mbrtowc.o wcrtomb.o mbsrtowcs.o \
+       wcsrtombs.o _wchar_utf8sntowcs.o _wchar_wcsntoutf8s.o \
        __mbsnrtowcs.o __wcsnrtombs.o
 
-OBJS=$(MOBJ)
+MSRC2=  wstdio.c
+MOBJ2=  fwide.o \
+       fgetwc.o getwchar.o fgetws.o \
+       fputwc.o putwchar.o fputws.o \
+       ungetwc.o
+# getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias)
+# putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias)
+
+# wcwidth wcswidth
+# wcstod wcstof wcstold
+# wcstol wcstoul wcstoq wcstouq wcstoll wcstoull
+# fwprintf wprintf swprintf vfwprintf vwprintf vswprintf
+# fwscanf  wscanf  swscanf  vfwscanf  vwscanf  vswscanf
+# wcsftime
+
+OBJS=$(MOBJ1) $(MOBJ2)
 
 all: $(OBJS) $(LIBC)
 
@@ -38,7 +53,11 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
        $(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(MOBJ): $(MSRC)
+$(MOBJ1): $(MSRC1)
+       $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+       $(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(MOBJ2): $(MSRC2)
        $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
        $(STRIPTOOL) -x -R .note -R .comment $*.o
 
index f2d9f4a..9f08f33 100644 (file)
  * an issue for uClibc, but may be for ELKS.  I'm currently not sure
  * if I'll use 16-bit, 32-bit, or configureable wchars in ELKS.
  *
+ * July 1, 2002
+ *
+ * Fixed _wchar_utf8sntowcs() for the max number of wchars == 0 case.
+ * Fixed nul-char bug in btowc(), and another in __mbsnrtowcs() for 8-bit
+ *    locales.
+ * Enabled building of a C/POSIX-locale-only version, so full locale support
+ *    no longer needs to be enabled.
+ *
  * Manuel
  */
 
 #include <locale.h>
 #include <wchar.h>
 
+#ifdef __UCLIBC_HAS_LOCALE__
 #define ENCODING (__global_locale.encoding)
+#warning implement __CTYPE_HAS_UTF_8_LOCALES!
+#define __CTYPE_HAS_UTF_8_LOCALES
+#else
+#define ENCODING (__ctype_encoding_7_bit)
+#undef __CTYPE_HAS_8_BIT_LOCALES
+#undef __CTYPE_HAS_UTF_8_LOCALES
+#undef L__wchar_utf8sntowcs
+#undef L__wchar_wcsntoutf8s
+#endif
 
 #if WCHAR_MAX > 0xffffU
 #define UTF_8_MAX_LEN 6
@@ -76,9 +94,6 @@
 
 /*  #define KUHN */
 
-#warning implement __CTYPE_HAS_UTF_8_LOCALES!
-#define __CTYPE_HAS_UTF_8_LOCALES
-
 /* Implementation-specific work functions. */
 
 extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
@@ -103,6 +118,8 @@ extern size_t __wcsnrtombs(char *__restrict dst,
 
 wint_t btowc(int c)
 {
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+
        wchar_t wc;
        unsigned char buf[1];
        mbstate_t mbstate;
@@ -110,11 +127,19 @@ wint_t btowc(int c)
        if (c != EOF) {
                *buf = (unsigned char) c;
                mbstate.mask = 0;               /* Initialize the mbstate. */
-               if (mbrtowc(&wc, buf, 1, &mbstate) == 1) {
+               if (mbrtowc(&wc, buf, 1, &mbstate) <= 1) {
                        return wc;
                }
        }
        return WEOF;
+
+#else  /*  __CTYPE_HAS_8_BIT_LOCALES */
+
+       /* If we don't have 8-bit locale support, then this is trivial since
+        * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */
+       return (((unsigned int)c) < 0x80) ? c : WEOF;
+
+#endif /*  __CTYPE_HAS_8_BIT_LOCALES */
 }
 
 #endif
@@ -125,9 +150,22 @@ wint_t btowc(int c)
 
 int wctob(wint_t c)
 {
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+
        unsigned char buf[MB_LEN_MAX];
 
        return (wcrtomb(buf, c, NULL) == 1) ? *buf : EOF;
+
+#else  /*  __CTYPE_HAS_8_BIT_LOCALES */
+
+       /* If we don't have 8-bit locale support, then this is trivial since
+        * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */
+       
+       /* TODO: need unsigned version of wint_t... */
+/*     return (((unsigned int)c) < 0x80) ? c : WEOF; */
+       return ((c >= 0) && (c < 0x80)) ? c : EOF;
+
+#endif /*  __CTYPE_HAS_8_BIT_LOCALES */
 }
 
 #endif
@@ -144,6 +182,9 @@ int mbsinit(const mbstate_t *ps)
 #ifdef L_mbrlen
 
 size_t mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps)
+        __attribute__ ((__weak__, __alias__("__mbrlen")));
+
+size_t __mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps)
 {
        static mbstate_t mbstate;       /* Rely on bss 0-init. */
 
@@ -183,7 +224,7 @@ size_t mbrtowc(wchar_t *__restrict pwc, const char *__restrict s,
        /* Need to do this here since mbsrtowcs doesn't allow incompletes. */
        if (ENCODING == __ctype_encoding_utf8) {
                r = _wchar_utf8sntowcs(pwc, 1, &p, n, ps, 1);
-               return (r == 1) ? (p-s) : r;
+               return (r == 1) ? (p-s) : r; /* Need to return 0 if nul char. */
        }
 #endif
 
@@ -289,10 +330,13 @@ size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
                wn = SIZE_MAX;
                incr = 0;
        }
-#warning fix _wchar_utf8sntowcs to allow wn == 0!
-       assert(wn > 0);                         /* TODO: fix this!! */
 
-       count = wn;
+       /* This is really here only to support the glibc extension function
+        * __mbsnrtowcs which apparently returns 0 if wn == 0 without any
+        * check on the validity of the mbstate. */
+       if (!(count = wn)) {
+               return 0;
+       }
 
        if ((mask = (__uwchar_t) ps->mask) != 0) { /* A continuation... */
 #ifdef DECODER
@@ -420,7 +464,7 @@ size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
 
 #endif
 /**********************************************************************/
-#ifdef L__wchar_wcstoutf8s
+#ifdef L__wchar_wcsntoutf8s
 
 size_t _wchar_wcsntoutf8s(char *__restrict s, size_t n,
                                                  const wchar_t **__restrict src, size_t wn)
@@ -568,13 +612,13 @@ size_t __mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src,
                                if (!wc) {
                                        goto BAD;
                                }
-                       } else if (!wc) {
+                       }
+                       if (!(*dst = wc)) {
                                s = NULL;
                                break;
                        }
-                       ++s;
-                       *dst = wc;
                        dst += incr;
+                       ++s;
                        --count;
                }
                if (dst != wcbuf) {
@@ -633,7 +677,7 @@ size_t __wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src,
        if (ENCODING == __ctype_encoding_utf8) {
                return _wchar_wcsntoutf8s(dst, len, src, NWC);
        }
-#endif
+#endif /* __CTYPE_HAS_UTF_8_LOCALES */
 
        incr = 1;
        if (!dst) {
@@ -676,12 +720,12 @@ size_t __wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src,
 /*  #define __WCHAR_REPLACEMENT_CHAR '?' */
 #ifdef __WCHAR_REPLACEMENT_CHAR
                                *dst = (unsigned char) ( u ? u : __WCHAR_REPLACEMENT_CHAR );
-#else
+#else  /* __WCHAR_REPLACEMENT_CHAR */
                                if (!u) {
                                        goto BAD;
                                }
                                *dst = (unsigned char) u;
-#endif
+#endif /* __WCHAR_REPLACEMENT_CHAR */
                        }
                        ++s;
                        dst += incr;
@@ -692,7 +736,7 @@ size_t __wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src,
                }
                return len - count;
        }
-#endif
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
 
        assert(ENCODING == __ctype_encoding_7_bit);
 
diff --git a/libc/misc/wchar/wstdio.c b/libc/misc/wchar/wstdio.c
new file mode 100644 (file)
index 0000000..79cf1df
--- /dev/null
@@ -0,0 +1,542 @@
+
+/*
+ * ANSI/ISO C99 says
+
+ 9 Although both text and binary wide­oriented streams are conceptually sequences of wide
+ characters, the external file associated with a wide­oriented stream is a sequence of
+ multibyte characters, generalized as follows:
+ --- Multibyte encodings within files may contain embedded null bytes (unlike multibyte
+ encodings valid for use internal to the program).
+ --- A file need not begin nor end in the initial shift state. 225)
+
+ * How do we deal with this?
+
+ * Should auto_wr_transition init the mbstate object?
+*/
+
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <wchar.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
+
+#ifndef __STDIO_THREADSAFE
+
+#ifdef __BCC__
+#define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
+asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
+RETURNTYPE NAME PARAMS
+#else
+#define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
+strong_alias(NAME,NAME##_unlocked) \
+RETURNTYPE NAME PARAMS
+#endif
+
+#define UNLOCKED(RETURNTYPE,NAME,PARAMS,ARGS) \
+       UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,stream)
+
+#ifdef __BCC__
+#define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
+asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
+void NAME PARAMS
+#else
+#define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
+strong_alias(NAME,NAME##_unlocked) \
+void NAME PARAMS
+#endif
+
+#define __STDIO_THREADLOCK_OPENLIST
+#define __STDIO_THREADUNLOCK_OPENLIST
+
+#else  /* __STDIO_THREADSAFE */
+
+#include <pthread.h>
+
+#define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
+RETURNTYPE NAME PARAMS \
+{ \
+       RETURNTYPE retval; \
+       __STDIO_THREADLOCK(STREAM); \
+       retval = NAME##_unlocked ARGS ; \
+       __STDIO_THREADUNLOCK(STREAM); \
+       return retval; \
+} \
+RETURNTYPE NAME##_unlocked PARAMS
+
+#define UNLOCKED(RETURNTYPE,NAME,PARAMS,ARGS) \
+       UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,stream)
+
+#define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
+void NAME PARAMS \
+{ \
+       __STDIO_THREADLOCK(stream); \
+       NAME##_unlocked ARGS ; \
+       __STDIO_THREADUNLOCK(stream); \
+} \
+void NAME##_unlocked PARAMS
+
+#define __STDIO_THREADLOCK_OPENLIST \
+       pthread_mutex_lock(&_stdio_openlist_lock)
+
+#define __STDIO_THREADUNLOCK_OPENLIST \
+       pthread_mutex_unlock(&_stdio_openlist_lock)
+
+#define __STDIO_THREADTRYLOCK_OPENLIST \
+       pthread_mutex_trylock(&_stdio_openlist_lock)
+
+#endif /* __STDIO_THREADSAFE */
+
+#ifndef __STDIO_BUFFERS
+#error stdio buffers are currently required for wide i/o
+#endif
+
+/**********************************************************************/
+#ifdef L_fwide
+
+/* TODO: According to SUSv3 should return EBADF if invalid stream. */
+
+int fwide(register FILE *stream, int mode)
+{
+       __STDIO_THREADLOCK(stream);
+
+       if (mode && !(stream->modeflags & (__FLAG_WIDE|__FLAG_NARROW))) {
+               stream->modeflags |= ((mode > 0) ? __FLAG_WIDE : __FLAG_NARROW);
+       }
+
+       mode = (stream->modeflags & __FLAG_WIDE)
+               - (stream->modeflags & __FLAG_NARROW);
+
+       __STDIO_THREADUNLOCK(stream);
+
+       return mode;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fgetwc
+
+static void munge_stream(register FILE *stream, unsigned char *buf)
+{
+#ifdef __STDIO_GETC_MACRO
+       stream->bufgetc =
+#endif
+#ifdef __STDIO_PUTC_MACRO
+       stream->bufputc =
+#endif
+       stream->bufpos = stream->bufread = stream->bufend = stream->bufstart = buf;
+}
+
+UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
+{
+       wint_t wi;
+       wchar_t wc[1];
+       int n;
+       size_t r;
+       unsigned char c[1];
+       unsigned char sbuf[1];
+       unsigned char ungot_width;      /* Support ftell after wscanf ungetwc. */
+
+       wi = WEOF;                                      /* Prepare for failure. */
+
+       if (stream->modeflags & __FLAG_NARROW) {
+               stream->modeflags |= __FLAG_ERROR;
+               __set_errno(EBADF);
+               goto DONE;
+       }
+       stream->modeflags |= __FLAG_WIDE;
+
+       if (stream->modeflags & __MASK_UNGOT) {/* Any ungetwc()s? */
+               assert( (stream->modeflags & (__FLAG_READING|__FLAG_ERROR))
+                               == __FLAG_READING);
+               wi = stream->ungot[(--stream->modeflags) & __MASK_UNGOT];
+               stream->ungot[1] = 0;
+               goto DONE;
+       }
+
+       if (!stream->bufstart) {        /* Ugh... stream isn't buffered! */
+               /* Munge the stream temporarily to use a 1-byte buffer. */
+               munge_stream(stream, sbuf);
+               ++stream->bufend;
+       }
+
+       ungot_width = 0;
+
+ LOOP:
+       if ((n = stream->bufread - stream->bufpos) == 0) {
+               goto FILL_BUFFER;
+       }
+
+       r = mbrtowc(wc, stream->bufpos, n, &stream->state);
+       if (((ssize_t) r) >= 0) {       /* Single byte... */
+               if (r == 0) {                   /* Nul wide char... means 0 byte for us so */
+                       ++r;                            /* increment r and handle below as single. */
+               }
+               stream->bufpos += r;
+               stream->ungot_width[0] = ungot_width + r;
+               wi = *wc;
+               goto DONE;
+       }
+
+       if (r == ((size_t) -2)) {
+               /* Potentially valid but incomplete and no more buffered. */
+               stream->bufpos += n;    /* Update bufpos for stream. */
+               ungot_width += n;
+       FILL_BUFFER:
+               if (_stdio_fread(c, (size_t) 1, stream) > 0) {
+                       assert(stream->bufpos == stream->bufstart + 1);
+                       *--stream->bufpos = *c; /* Insert byte into buffer. */
+                       goto LOOP;
+               }
+               if (!__FERROR(stream)) { /* EOF with no error. */
+                       if (!stream->state.mask) {      /* No partially complete wchar. */
+                               goto DONE;
+                       }
+                       /* EOF but partially complete wchar. */
+                       /* TODO: should EILSEQ be set? */
+                       __set_errno(EILSEQ);
+               }
+       }
+
+       /* If we reach here, either r == ((size_t)-1) and mbrtowc set errno
+        * to EILSEQ, or r == ((size_t)-2) and stream is in an error state
+        * or at EOF with a partially complete wchar.  Make sure stream's
+        * error indicator is set. */
+       stream->modeflags |= __FLAG_ERROR;
+
+ DONE:
+       if (stream->bufstart == sbuf) { /* Need to un-munge the stream. */
+               munge_stream(stream, NULL);
+       }
+
+       return wi;
+}
+
+strong_alias(fgetwc_unlocked,getwc_unlocked);
+strong_alias(fgetwc,getwc);
+
+#endif
+/**********************************************************************/
+#ifdef L_getwchar
+
+UNLOCKED_STREAM(wint_t,getwchar,(void),(),stdin)
+{
+       register FILE *stream = stdin; /* This helps bcc optimize. */
+
+       return fgetwc_unlocked(stream);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fgetws
+
+UNLOCKED(wchar_t *,fgetws,(wchar_t *__restrict ws, int n,
+                                                  FILE *__restrict stream),(ws, n, stream))
+{
+       register wchar_t *p = ws;
+       wint_t wi;
+
+       while ((n > 1)
+                  && ((wi = fgetwc_unlocked(stream)) != WEOF)
+                  && ((*p++ = wi) != '\n')
+                  ) {
+               --n;
+       }
+       if (p == ws) {
+               /* TODO -- should we set errno? */
+/*             if (n <= 0) { */
+/*                     errno = EINVAL; */
+/*             } */
+               return NULL;
+       }
+       *p = 0;
+       return ws;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fputwc
+
+UNLOCKED(wint_t,fputwc,(wchar_t wc, FILE *stream),(wc, stream))
+{
+#if 0
+       size_t r;
+       char buf[MB_LEN_MAX];
+
+       if (stream->modeflags & __FLAG_NARROW) {
+               stream->modeflags |= __FLAG_ERROR;
+               __set_errno(EBADF);
+               return WEOF;
+       }
+       stream->modeflags |= __FLAG_WIDE;
+
+       /* TODO:
+        * If stream is in reading state with bad mbstate object, what to do?
+        * Should we check the state first?  Should we check error indicator?
+        * Should we check reading or even read-only?
+        */
+       /* It looks like the only ANSI/ISO C99 - blessed way of manipulating
+        * the stream's mbstate object is through fgetpos/fsetpos. */
+       r = wcrtomb(buf, wc, &stream->state);
+
+       return (r != ((size_t) -1) && (r == _stdio_fwrite(buf, r, stream)))
+               ? wc : WEOF;
+
+#elif 0
+
+       /* this is broken if wc == 0 !!! */
+       wchar_t wbuf[2];
+
+       wbuf[0] = wc;
+       wbuf[1] = 0;
+
+       return (fputws_unlocked(wbuf, stream) > 0) ? wc : WEOF;
+
+#else
+
+       size_t n;
+       char buf[MB_LEN_MAX];
+
+       if (stream->modeflags & __FLAG_NARROW) {
+               stream->modeflags |= __FLAG_ERROR;
+               __set_errno(EBADF);
+               return WEOF;
+       }
+       stream->modeflags |= __FLAG_WIDE;
+
+       return (((n = wcrtomb(buf, wc, &stream->state)) != ((size_t)-1)) /* EILSEQ */
+                       && (_stdio_fwrite(buf, n, stream) != n))/* Didn't write everything. */
+               ? wc : WEOF;
+
+#endif
+}
+
+strong_alias(fputwc_unlocked,putwc_unlocked);
+strong_alias(fputwc,putwc);
+
+#endif
+/**********************************************************************/
+#ifdef L_putwchar
+
+UNLOCKED_STREAM(wint_t,putwchar,(wchar_t wc),(wc),stdout)
+{
+       register FILE *stream = stdout; /* This helps bcc optimize. */
+
+       return fputwc_unlocked(wc, stream);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fputws
+
+UNLOCKED(int,fputws,(const wchar_t *__restrict ws,
+                                        register FILE *__restrict stream),(ws, stream))
+{
+#if 1
+       size_t n;
+       char buf[64];
+
+       if (stream->modeflags & __FLAG_NARROW) {
+               stream->modeflags |= __FLAG_ERROR;
+               __set_errno(EBADF);
+               return -1;
+       }
+       stream->modeflags |= __FLAG_WIDE;
+
+       while ((n = wcsrtombs(buf, &ws, sizeof(buf), &stream->state)) != 0) {
+               /* Wasn't an empty wide string. */
+               if ((n == ((size_t) -1))/* Encoding error! */
+                        || (_stdio_fwrite(buf, n, stream) != n)/* Didn't write everything. */
+                        ) {
+                       return -1;
+               }
+               if (!ws) {                              /* Done? */
+                       break;
+               }
+       }
+
+       return 1;
+
+
+
+
+#elif 1
+       int result;
+       size_t n;
+       size_t len;
+       register char *s;
+       unsigned char *bufend;
+       char sbuf[MB_LEN_MAX];
+
+       if (stream->modeflags & __FLAG_NARROW) {
+       RETURN_BADF:
+               stream->modeflags |= __FLAG_ERROR;
+               __set_errno(EBADF);
+               return -1;
+       }
+       stream->modeflags |= __FLAG_WIDE;
+
+       /* Note: What follows is setup grabbed from _stdio_fwrite and modified
+        * slightly.  Since this is a wide stream, we can ignore bufgetc and
+        * bufputc if present.  They always == bufstart.
+        * It is unfortunate that we need to duplicate so much code here, but
+        * we need to do the stream setup before starting the wc->mb conversion. */
+
+       if ((stream->modeflags & __FLAG_READONLY)
+#ifndef __STDIO_AUTO_RW_TRANSITION
+       /* ANSI/ISO requires either at EOF or currently not reading. */
+               || ((stream->modeflags & (__FLAG_READING|__FLAG_EOF))
+                       == __FLAG_READING)
+#endif /* __STDIO_AUTO_RW_TRANSITION */
+               ) {
+               /* TODO: This is for posix behavior if readonly.  To save space, we
+                * use this errno for write attempt while reading, as no errno is
+                * specified by posix for this case, even though the restriction is
+                * mentioned in fopen(). */
+               goto RETURN_BADF;
+       }
+
+#ifdef __STDIO_AUTO_RW_TRANSITION
+       /* If reading, deal with ungots and read-buffered chars. */
+       if (stream->modeflags & __FLAG_READING) {
+               if (((stream->bufpos < stream->bufread)
+                        || (stream->modeflags & __MASK_UNGOT))
+                       /* If appending, we might as well seek to end to save a seek. */
+                       /* TODO: set EOF in fseek when appropriate? */
+                       && fseek(stream, 0L, 
+                                        ((stream->modeflags & __FLAG_APPEND)
+                                         ? SEEK_END : SEEK_CUR))
+                       ) {
+                       /* Note: This differs from glibc's apparent behavior of
+                          not setting the error flag and discarding the buffered
+                          read data. */
+                       stream->modeflags |= __FLAG_ERROR; /* fseek may not set this. */
+                       return -1;                      /* Fail if we need to fseek but can't. */
+               }
+               /* Always reset even if fseek called (saves a test). */
+               stream->bufpos = stream->bufread = stream->bufstart;
+               stream->modeflags &= ~__FLAG_READING;
+       }
+#endif
+
+       /* Ok, the boilerplate from _stdio_fwrite is done.  */
+
+       if (stream->bufpos > stream->bufstart) { /* Pending writes.. */
+               /* This is a performance penalty, but it simplifies the code below.
+                * If this is removed, the buffer sharing and while loop condition
+                * need to be modified below (at least).  We at least save a little
+                * on the overhead by calling _stdio_fwrite directly instead of
+                * fflush_unlocked. */
+               if (_stdio_fwrite(NULL, 0, stream) > 0) {/* fflush incomplete! */
+                       return -1;
+               }
+       }
+
+       stream->modeflags |= __FLAG_WRITING; /* Ensure Writing flag is set. */
+
+       /* Next, we "steal" the stream's buffer and do the wc->mb conversion
+        * straight into it.  This will cause the equivalent of an fflush
+        * for each string write.  :-( */
+       
+       bufend = NULL;
+       s = stream->bufstart;
+
+       if ((len = stream->bufend - stream->bufstart) < MB_LEN_MAX) {
+               /* Stream is unbuffered or buffer is too small, so deactivate. */
+               bufend = stream->bufend;
+               stream->bufend = stream->bufstart;
+               s = sbuf;
+               len = MB_LEN_MAX;
+       }
+
+       result = 1;                                     /* Assume success. */
+       while (ws && (n = wcsrtombs(s, &ws, len, &stream->state)) != 0) {
+               if ((n == ((size_t) -1)) /* Encoding error! */
+                        /* TODO - maybe call write directly?  but what about custom streams? */
+                        || (_stdio_fwrite(s, n, stream) != n)/* Didn't write everything. */
+                        ) {
+                       result = -1;
+                       break;
+               }
+       }
+
+       if (bufend) {                           /* If deactivated stream buffer, renable it. */
+               stream->bufend = bufend;
+       }
+
+       return result;
+
+#else  /* slow, dumb version */
+       while (*ws) {
+               if (fputwc_unlocked(*ws, stream) == WEOF) {
+                       return -1;
+               }
+               ++ws;
+       }
+       return 1;
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_ungetwc
+/*
+ * Note: This is the application-callable ungetwc.  If wscanf calls this, it
+ * should also set stream->ungot[1] to 0 if this is the only ungot.
+ */
+
+/* Reentrant. */
+
+wint_t ungetwc(wint_t c, register FILE *stream)
+{
+       __STDIO_THREADLOCK(stream);
+
+       __stdio_validate_FILE(stream); /* debugging only */
+
+       if (stream->modeflags & __FLAG_NARROW) {
+               stream->modeflags |= __FLAG_ERROR;
+               c = WEOF;
+               goto DONE;
+       }
+       stream->modeflags |= __FLAG_WIDE;
+
+       /* If can't read or there's been an error, or c == EOF, or ungot slots
+        * already filled, then return EOF */
+       if ((stream->modeflags
+                & (__MASK_UNGOT2|__FLAG_WRITEONLY
+#ifndef __STDIO_AUTO_RW_TRANSITION
+                       |__FLAG_WRITING         /* Note: technically no, but yes in spirit */
+#endif /* __STDIO_AUTO_RW_TRANSITION */
+                       ))
+               || ((stream->modeflags & __MASK_UNGOT1) && (stream->ungot[1]))
+               || (c == WEOF) ) {
+               c = WEOF;
+               goto DONE;;
+       }
+
+/*  ungot_width */
+
+#ifdef __STDIO_BUFFERS
+                                                               /* TODO: shouldn't allow writing??? */
+       if (stream->modeflags & __FLAG_WRITING) {
+               fflush_unlocked(stream); /* Commit any write-buffered chars. */
+       }
+#endif /* __STDIO_BUFFERS */
+
+       /* Clear EOF and WRITING flags, and set READING FLAG */
+       stream->modeflags &= ~(__FLAG_EOF|__FLAG_WRITING);
+       stream->modeflags |= __FLAG_READING;
+       stream->ungot[1] = 1;           /* Flag as app ungetc call; wscanf fixes up. */
+       stream->ungot[(stream->modeflags++) & __MASK_UNGOT] = c;
+
+       __stdio_validate_FILE(stream); /* debugging only */
+
+ DONE:
+       __STDIO_THREADUNLOCK(stream);
+
+       return c;
+}
+
+#endif
+/**********************************************************************/
index 39ed2cf..802e979 100644 (file)
@@ -34,6 +34,7 @@
 #include <string.h>
 #include <errno.h>
 #include <locale.h>
+#include <ctype.h>
 
 /* We know wide char support is enabled.  We wouldn't be here otherwise. */
 
@@ -41,7 +42,9 @@
  * towctrans function. */
 /*  #define SMALL_UPLOW */
 
+#ifndef __LOCALE_C_ONLY
 #define __WCTYPE_WITH_LOCALE
+#endif
 
 /**********************************************************************/
 
@@ -292,6 +295,10 @@ wctype_t wctype(const char *property)
 /**********************************************************************/
 #ifdef L_iswctype
 
+#warning duh... replace the range-based classification with table lookup!
+
+#ifdef __WCTYPE_WITH_LOCALE
+
 #warning TODO: need to fix locale ctype table lookup stuff
 #if 0
 extern const char ctype_range[];
@@ -346,6 +353,102 @@ int iswctype(wint_t wc, wctype_t desc)
        return 0;
 }
 
+#else
+
+static const unsigned char WCctype[] = {
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_space_blank     << 4),
+       __CTYPE_cntrl_space_nonblank | (__CTYPE_cntrl_space_nonblank  << 4),
+       __CTYPE_cntrl_space_nonblank | (__CTYPE_cntrl_space_nonblank  << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_cntrl_nonspace       | (__CTYPE_cntrl_nonspace        << 4),
+       __CTYPE_print_space_blank    | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_digit                | (__CTYPE_digit                 << 4),
+       __CTYPE_digit                | (__CTYPE_digit                 << 4),
+       __CTYPE_digit                | (__CTYPE_digit                 << 4),
+       __CTYPE_digit                | (__CTYPE_digit                 << 4),
+       __CTYPE_digit                | (__CTYPE_digit                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_alpha_upper           << 4),
+       __CTYPE_alpha_upper          | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_alpha_lower           << 4),
+       __CTYPE_alpha_lower          | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_punct                 << 4),
+       __CTYPE_punct                | (__CTYPE_cntrl_nonspace        << 4),
+};
+
+static const char ctype_range[] = {
+       __CTYPE_RANGES
+};
+
+int iswctype(wint_t wc, wctype_t desc)
+{
+       unsigned char d = __CTYPE_unclassified;
+
+       if (((__uwchar_t) wc) <= 0x7f) {
+               if (desc < _CTYPE_iswxdigit) {
+                       d = WCctype[wc >> 1];
+                       d = (wc & 1) ? (d >> 4) : (d & 0xf);
+
+                       return ( ((unsigned char)(d - ctype_range[2*desc]))
+                                        <= ctype_range[2*desc + 1] )
+                               && ((desc != _CTYPE_iswblank) || (d & 1));
+               }
+
+               if (desc == _CTYPE_iswxdigit) {
+                       return __C_isxdigit(((char) wc));
+               }
+       }
+       return 0;
+}
+
+#endif
+
 #endif
 /**********************************************************************/
 #ifdef L_towctrans
@@ -446,10 +549,26 @@ wint_t towctrans(wint_t wc, wctrans_t desc)
 
 #endif
 
-#else
+#else  /* __WCTYPE_WITH_LOCALE */
 
+/* Minimal support for C/POSIX locale. */
 
-#endif
+wint_t towctrans(wint_t wc, wctrans_t desc)
+{
+       if (((unsigned int)(desc - _CTYPE_tolower))
+               <= (_CTYPE_toupper - _CTYPE_tolower)
+               ) {
+               /* Transliteration is either tolower or toupper. */
+               if (((__uwchar_t) wc) <= 0x7f) {
+                       return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc);
+               }
+       } else {
+               __set_errno(EINVAL);    /* Invalid transliteration. */
+       }
+       return wc;
+}
+
+#endif /* __WCTYPE_WITH_LOCALE */
 
 #endif
 /**********************************************************************/
index 0145b94..011f3a7 100644 (file)
@@ -57,7 +57,8 @@ MOBJ = fclose.o fflush.o fopen.o freopen.o perror.o remove.o \
        __fsetlocking.o flockfile.o ftrylockfile.o funlockfile.o \
        _stdio_fopen.o _stdio_fread.o _stdio_fwrite.o _stdio_adjpos.o \
        _stdio_lseek.o _stdio_init.o \
-       _stdio_fsfopen.o _stdio_fdout.o _uintmaxtostr.o _stdio_strerror_r.o
+       _stdio_fsfopen.o _stdio_fdout.o _uintmaxtostr.o _stdio_strerror_r.o \
+       getdelim.o getline.o ctermid.o
 
 # ifeq ($(DOLFS),true)
 #      MOBJ += fopen64.o freopen64.o ftello64.o fseeko64.o fsetpos64.o fgetpos64.o
@@ -83,8 +84,7 @@ endif
 MSRC3=scanf.c
 MOBJ3=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o
 
-CSRC=popen.c getdelim.c getline.c tmpfile.c tmpnam.c \
-     tmpnam_r.c tempnam.c ctermid.c
+CSRC=popen.c tmpfile.c tmpnam.c tmpnam_r.c tempnam.c
 ifeq ($(USE_OLD_VFPRINTF),true)
        CSRC += old_vfprintf.c
 endif
index 036c97c..945f59a 100644 (file)
 
 /*  #define __isdigit(c) (((unsigned int)(c - '0')) < 10) */
 
+#if defined(__UCLIBC_HAS_FLOATS__)
 extern size_t _dtostr(FILE * fp, long double x, struct printf_info *info);
+#endif
 
 
 enum {
@@ -179,7 +181,7 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
                         va_list ap)
 {
        int i, cnt, lval, len;
-       char *p;
+       register char *p;
        const char *fmt0;
        int preci, width;
 #define upcase i
@@ -325,7 +327,7 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
                                        p = _uintmaxtostr((tmp + sizeof(tmp) - 1),
                                                                          ((lval>1) /* TODO -- longlong/long/int/short/char */
                                                                           ? va_arg(ap, uintmax_t)
-                                                                          : (uintmax_t) ((long long) /* sign-extend! */
+                                                                          : (uintmax_t) ((intmax_t) /* sign-extend! */
                                                                                                        va_arg(ap, long))),
                                                                          -radix, upcase);
 
index 2fac4c9..fc6dd87 100644 (file)
 #define __PA_FLAG_INTMASK \
        (__PA_FLAG_CHAR|PA_FLAG_SHORT|__PA_FLAG_INT|PA_FLAG_LONG|PA_FLAG_LONG_LONG)
 
-extern printf_function *_custom_printf_handler[MAX_USER_SPEC];
+extern printf_function _custom_printf_handler[MAX_USER_SPEC];
 extern printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC];
 extern char *_custom_printf_spec;
 
@@ -177,13 +177,13 @@ enum {
  */
 
 /* TODO -- Fix the table below to take into account stdint.h. */
-#ifndef LLONG_MAX
-#error fix QUAL_CHARS for no long long!  Affects 'L', 'j', 'q', 'll'.
-#else
-#if LLONG_MAX != INTMAX_MAX
-#error fix QUAL_CHARS intmax_t entry 'j'!
-#endif
-#endif
+/*  #ifndef LLONG_MAX */
+/*  #error fix QUAL_CHARS for no long long!  Affects 'L', 'j', 'q', 'll'. */
+/*  #else */
+/*  #if LLONG_MAX != INTMAX_MAX */
+/*  #error fix QUAL_CHARS intmax_t entry 'j'! */
+/*  #endif */
+/*  #endif */
 
 #ifdef PDS
 #error PDS already defined!
@@ -191,6 +191,9 @@ enum {
 #ifdef SS
 #error SS already defined!
 #endif
+#ifdef IMS
+#error IMS already defined!
+#endif
 
 #if PTRDIFF_MAX == INT_MAX
 #define PDS            0
@@ -212,11 +215,21 @@ enum {
 #error fix QUAL_CHARS size_t entries 'z', 'Z'!
 #endif
 
+#if INTMAX_MAX == INT_MAX
+#define IMS            0
+#elif INTMAX_MAX == LONG_MAX
+#define IMS            4
+#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX)
+#define IMS            8
+#else
+#error fix QUAL_CHARS ptrdiff_t entry 't'!
+#endif
+
 #define QUAL_CHARS             { \
        /* j:(u)intmax_t z:(s)size_t  t:ptrdiff_t  \0:int */ \
        /* q:long_long  Z:(s)size_t */ \
        'h',   'l',  'L',  'j',  'z',  't',  'q', 'Z',  0, \
-        2,     4,    8,    8,   SS,  PDS,    8,  SS,   0, /* TODO -- fix!!! */\
+        2,     4,    8,  IMS,   SS,  PDS,    8,  SS,   0, /* TODO -- fix!!! */\
      1,     8 \
 }
 
@@ -311,7 +324,7 @@ extern int _ppfs_parsespec(ppfs_t *ppfs); /* parses specifier */
  */
 
 size_t parse_printf_format(register const char *template,
-                                                  size_t n, int *argtypes)
+                                                  size_t n, register int *argtypes)
 {
        ppfs_t ppfs;
        size_t i;
@@ -1021,7 +1034,7 @@ int register_printf_function(int spec, printf_function handler,
 /**********************************************************************/
 #ifdef L__do_one_spec
 
-printf_function *_custom_printf_handler[MAX_USER_SPEC];
+printf_function _custom_printf_handler[MAX_USER_SPEC];
 
 extern void _store_inttype(void *dest, int desttype, uintmax_t val);
 extern uintmax_t _load_inttype(int desttype, const void *src, int uflag);
@@ -1263,6 +1276,7 @@ int _do_one_spec(FILE * __restrict stream, register ppfs_t *ppfs, int *count)
 #endif
 /**********************************************************************/
 #ifdef L_vsnprintf
+
 #ifdef __STDIO_BUFFERS
 int vsnprintf(char *__restrict buf, size_t size,
                          const char * __restrict format, va_list arg)
@@ -1273,7 +1287,7 @@ int vsnprintf(char *__restrict buf, size_t size,
 #ifdef __STDIO_GETC_MACRO
        f.bufgetc =
 #endif
-       f.bufrpos = f.bufwpos = f.bufstart = buf;
+       f.bufpos = f.bufread = f.bufstart = buf;
 
        if (size > SIZE_MAX - (size_t) buf) {
                size = SIZE_MAX - (size_t) buf;
@@ -1294,16 +1308,20 @@ int vsnprintf(char *__restrict buf, size_t size,
        f.filedes = -2;                         /* for debugging */
        f.modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
 
+#ifdef __STDIO_MBSTATE
+       __INIT_MBSTATE(&(f.state));
+#endif /* __STDIO_MBSTATE */
+
 #ifdef __STDIO_THREADSAFE
        __stdio_init_mutex(&f.lock);
 #endif
 
        rv = vfprintf(&f, format, arg);
        if (size) {
-               if (f.bufwpos == f.bufend) {
-                       --f.bufwpos;
+               if (f.bufpos == f.bufend) {
+                       --f.bufpos;
                }
-               *f.bufwpos = 0;
+               *f.bufpos = 0;
        }
        return rv;
 }
@@ -1319,10 +1337,11 @@ typedef struct {
 
 #define COOKIE ((__snpf_cookie *) cookie)
 
-static ssize_t snpf_write(void *cookie, const char *buf, size_t bufsize)
+static ssize_t snpf_write(register void *cookie, const char *buf,
+                                                 size_t bufsize)
 {
        size_t count;
-       char *p;
+       register char *p;
 
        /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */
 
@@ -1368,6 +1387,10 @@ int vsnprintf(char *__restrict buf, size_t size,
        f.filedes = -1;                         /* For debugging. */
        f.modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
 
+#ifdef __STDIO_MBSTATE
+       __INIT_MBSTATE(&(f.state));
+#endif /* __STDIO_MBSTATE */
+
 #ifdef __STDIO_THREADSAFE
        __stdio_init_mutex(&f.lock);
 #endif
@@ -1384,6 +1407,7 @@ int vsnprintf(char *__restrict buf, size_t size,
 #endif
 /**********************************************************************/
 #ifdef L_vdprintf
+
 int vdprintf(int filedes, const char * __restrict format, va_list arg)
 {
        FILE f;
@@ -1394,7 +1418,7 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg)
 #ifdef __STDIO_GETC_MACRO
        f.bufgetc =
 #endif
-       f.bufrpos = f.bufwpos = f.bufstart = buf;
+       f.bufpos = f.bufread = f.bufstart = buf;
 #ifdef __STDIO_PUTC_MACRO
        f.bufputc = 
 #endif
@@ -1410,6 +1434,10 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg)
        f.filedes = filedes;
        f.modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
 
+#ifdef __STDIO_MBSTATE
+       __INIT_MBSTATE(&(f.state));
+#endif /* __STDIO_MBSTATE */
+
 #ifdef __STDIO_THREADSAFE
        __stdio_init_mutex(&f.lock);
 #endif
@@ -1418,6 +1446,7 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg)
 
        return fflush(&f) ? -1 : rv;
 }
+
 #endif
 /**********************************************************************/
 #ifdef L_vasprintf
@@ -1486,6 +1515,7 @@ int vsprintf(char *__restrict buf, const char * __restrict format,
 #endif
 /**********************************************************************/
 #ifdef L_fprintf
+
 int fprintf(FILE * __restrict stream, const char * __restrict format, ...)
 {
        va_list arg;
@@ -1497,6 +1527,7 @@ int fprintf(FILE * __restrict stream, const char * __restrict format, ...)
 
        return rv;
 }
+
 #endif
 /**********************************************************************/
 #ifdef L_snprintf
@@ -1521,6 +1552,7 @@ int snprintf(char *__restrict buf, size_t size,
 #endif
 /**********************************************************************/
 #ifdef L_dprintf
+
 int dprintf(int filedes, const char * __restrict format, ...)
 {
        va_list arg;
@@ -1532,6 +1564,7 @@ int dprintf(int filedes, const char * __restrict format, ...)
 
        return rv;
 }
+
 #endif
 /**********************************************************************/
 #ifdef L_asprintf
@@ -2059,7 +2092,8 @@ void _store_inttype(register void *dest, int desttype, uintmax_t val)
 /**********************************************************************/
 #ifdef L__load_inttype
 
-extern uintmax_t _load_inttype(int desttype, const void *src, int uflag)
+extern uintmax_t _load_inttype(int desttype, register const void *src,
+                                                          int uflag)
 {
        if (uflag >= 0) {                       /* unsigned */
 #if LONG_MAX != INT_MAX
index 7506268..6d7a84e 100644 (file)
  * implementation doesn't for the "100ergs" case mentioned above.
  */
 
+#define _ISOC99_SOURCE                 /* for LLONG_MAX primarily... */
 #define _GNU_SOURCE
-#include <features.h>
-#if defined(__UCLIBC__) && !defined(__USE_ISOC99)
-#define __USE_ISOC99
-#endif
-
 #define _STDIO_UTILITY
 #include <stdio.h>
 #include <stdlib.h>
@@ -124,9 +120,13 @@ int vsscanf(__const char *sp, __const char *fmt, va_list ap)
 
        string->filedes = -2;           /* for debugging */
        string->modeflags = (__FLAG_NARROW|__FLAG_READONLY);
-       string->bufstart = string->bufrpos = (unsigned char *) ((void *) sp);
+       string->bufstart = string->bufpos = (unsigned char *) ((void *) sp);
        string->bufgetc = (char *) ((unsigned) -1);
 
+#ifdef __STDIO_MBSTATE
+       __INIT_MBSTATE(&(string->state));
+#endif /* __STDIO_MBSTATE */
+
 #ifdef __STDIO_THREADSAFE
        __stdio_init_mutex(&string->lock);
 #endif
@@ -172,9 +172,11 @@ static int valid_digit(char c, char base)
 extern unsigned long
 _stdlib_strto_l(register const char * __restrict str,
                                char ** __restrict endptr, int base, int sflag);
+#ifdef LLONG_MAX
 extern unsigned long long
 _stdlib_strto_ll(register const char * __restrict str,
                                 char ** __restrict endptr, int base, int sflag);
+#endif
 
 struct scan_cookie {
        FILE *fp;
@@ -205,7 +207,8 @@ static const char spec[]  = "%n[csoupxXid";
 /* radix[i] <-> spec[i+5]     o   u   p   x   X  i   d */
 static const char radix[] = { 8, 10, 16, 16, 16, 0, 10 };
 
-static void init_scan_cookie(struct scan_cookie *sc, FILE *fp)
+static void init_scan_cookie(register struct scan_cookie *sc,
+                                                        register FILE *fp)
 {
        sc->fp = fp;
        sc->nread = 0;
@@ -216,7 +219,7 @@ static void init_scan_cookie(struct scan_cookie *sc, FILE *fp)
 
 /* TODO -- what about literal '\0' chars in a file??? */
 
-static int scan_getc_nw(struct scan_cookie *sc)
+static int scan_getc_nw(register struct scan_cookie *sc)
 {
        if (sc->ungot_flag == 0) {
                sc->ungot_char = getc(sc->fp);
@@ -230,7 +233,7 @@ static int scan_getc_nw(struct scan_cookie *sc)
        return sc->ungot_char;
 }
 
-static int scan_getc(struct scan_cookie *sc)
+static int scan_getc(register struct scan_cookie *sc)
 {
        if (sc->ungot_flag == 0) {
                sc->ungot_char = getc(sc->fp);
@@ -247,7 +250,7 @@ static int scan_getc(struct scan_cookie *sc)
        return sc->ungot_char;
 }
 
-static void scan_ungetc(struct scan_cookie *sc)
+static void scan_ungetc(register struct scan_cookie *sc)
 {
        if (sc->ungot_flag != 0) {
                assert(sc->width < 0);
@@ -262,7 +265,7 @@ static void scan_ungetc(struct scan_cookie *sc)
        }
 }
 
-static void kill_scan_cookie(struct scan_cookie *sc)
+static void kill_scan_cookie(register struct scan_cookie *sc)
 {
        if (sc->ungot_flag) {
                ungetc(sc->ungot_char,sc->fp);
@@ -273,10 +276,7 @@ static void kill_scan_cookie(struct scan_cookie *sc)
        }
 }
 
-int vfscanf(fp, format, ap)
-FILE *fp;
-const char *format;
-va_list ap;
+int vfscanf(FILE *fp, const char *format, va_list ap)
 {
 #ifdef __UCLIBC_HAS_LONG_LONG__
 #define STRTO_L_(s,e,b,sf) _stdlib_strto_ll(s,e,b,sf)
@@ -294,9 +294,9 @@ va_list ap;
 #endif
        UV_TYPE uv;
        struct scan_cookie sc;
-       unsigned const char *fmt;
+       register unsigned const char *fmt;
        const char *p;
-       unsigned char *b;
+       register unsigned char *b;
        void *vp;
        int cc, i, cnt;
        signed char lval;
@@ -523,7 +523,7 @@ va_list ap;
                                                                *((unsigned int *)vp) = (unsigned int)uv;
                                                                break;
 #endif
-                                                       case -1:
+                                                       case (signed char)(-1):
                                                                if (usflag) {
                                                                        if (uv > USHRT_MAX) {
                                                                                uv = USHRT_MAX;
@@ -535,7 +535,7 @@ va_list ap;
                                                                }
                                                                *((unsigned short *)vp) = (unsigned short)uv;
                                                                break;
-                                                       case -2:
+                                                       case (signed char)(-2):
                                                                if (usflag) {
                                                                        if (uv > UCHAR_MAX) {
                                                                                uv = UCHAR_MAX;
index c847316..a56eff7 100644 (file)
  *
  *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
 
+/* Before we include anything, convert L_ctermid to L_ctermid_function
+ * and undef L_ctermid if defined.  This is necessary as L_ctermid is
+ * a SUSv3 standard macro defined in stdio.h. */
+#ifdef L_ctermid
+#define L_ctermid_function
+#undef L_ctermid
+#endif
+
 #define _ISOC99_SOURCE                 /* for ULLONG primarily... */
 #define _GNU_SOURCE
 #define _STDIO_UTILITY                 /* for _stdio_fdout and _uintmaxtostr. */
 
 /**********************************************************************/
 
-/* TODO -- make this the default except for bcc with it's broken preproc? */
-#ifdef __UCLIBC__
-#define _stdin stdin
-#define _stdout stdout
-#define _stderr stderr
-#endif /* __UCLIBC__ */
-
-/**********************************************************************/
-
 #ifndef __STDIO_THREADSAFE
 
+#ifdef __BCC__
+#define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
+asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
+RETURNTYPE NAME PARAMS
+#else
 #define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
 strong_alias(NAME,NAME##_unlocked) \
 RETURNTYPE NAME PARAMS
+#endif
 
 #define UNLOCKED(RETURNTYPE,NAME,PARAMS,ARGS) \
        UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,stream)
 
+#ifdef __BCC__
+#define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
+asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
+void NAME PARAMS
+#else
 #define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
 strong_alias(NAME,NAME##_unlocked) \
 void NAME PARAMS
+#endif
 
 #define __STDIO_THREADLOCK_OPENLIST
 #define __STDIO_THREADUNLOCK_OPENLIST
@@ -175,6 +186,14 @@ void NAME##_unlocked PARAMS
 #define __STDIO_FILE_INIT_CUSTOM_STREAM(stream)
 #endif
 
+#ifdef __STDIO_MBSTATE
+#define __STDIO_FILE_INIT_MBSTATE \
+       { 0, 0 },
+#else
+#define __STDIO_FILE_INIT_MBSTATE
+#endif
+
+
 #ifdef __STDIO_THREADSAFE
 #define __STDIO_FILE_INIT_THREADSAFE \
        0, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
@@ -191,21 +210,10 @@ void NAME##_unlocked PARAMS
        __STDIO_FILE_INIT_BUFGETC((buf)) \
        __STDIO_FILE_INIT_BUFPUTC((buf)) \
        __STDIO_FILE_INIT_CUSTOM_STREAM(stream) \
+       __STDIO_FILE_INIT_MBSTATE \
        __STDIO_FILE_INIT_THREADSAFE \
 } /* TODO: mbstate and builtin buf */
 
-#ifdef __STDIO_MBSTATE_DATA
-extern void _init_mbstate(mbstate_t *dest);
-
-#define __COMMA_CLEAN_MBSTATE        , 0
-#define __COPY_MBSTATE(dest,src)  memcpy(dest, src, sizeof(mbstate_t))
-#define __INIT_MBSTATE(dest) _init_mbstate(dest)
-#else
-#define __COMMA_CLEAN_MBSTATE
-#define __COPY_MBSTATE(dest,src)
-#define __INIT_MBSTATE(dest)
-#endif
-
 #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
 
 /* TODO -- what does glibc do for undefined funcs?  errno set? */
@@ -237,7 +245,7 @@ extern void _init_mbstate(mbstate_t *dest);
 
 /* SUSv2 Legacy function -- need not be reentrant. */
 
-int getw (register FILE *stream)
+int getw(FILE *stream)
 {
        int aw[1];
 
@@ -259,7 +267,7 @@ int getw (register FILE *stream)
 
 /* SUSv2 Legacy function -- need not be reentrant. */
 
-int putw (int w, register FILE *stream)
+int putw(int w, FILE *stream)
 {
        int aw[1];
 
@@ -322,6 +330,30 @@ FILE *fopen64(const char * __restrict filename, const char * __restrict mode)
 
 #endif
 /**********************************************************************/
+#ifdef L_ctermid_function
+
+/* Not required to be reentrant. */
+
+char *ctermid(register char *s)
+{
+       static char sbuf[L_ctermid];
+
+#ifdef __BCC__
+       /* Currently elks doesn't support /dev/tty. */
+       if (!s) {
+               s = sbuf;
+       }
+       *s = 0;
+
+       return s;
+#else
+       /* glibc always returns /dev/tty for linux. */
+       return strcpy((s ? s : sbuf), "/dev/tty");
+#endif
+}
+
+#endif
+/**********************************************************************/
 /* BSD functions */
 /**********************************************************************/
 #ifdef L_setbuffer
@@ -413,7 +445,7 @@ typedef struct {
 
 #define COOKIE ((__fmo_cookie *) cookie)
 
-static ssize_t fmo_read(void *cookie, register char *buf, size_t bufsize)
+static ssize_t fmo_read(register void *cookie, char *buf, size_t bufsize)
 {
        size_t count = COOKIE->len - COOKIE->pos;
 
@@ -442,7 +474,7 @@ static ssize_t fmo_read(void *cookie, register char *buf, size_t bufsize)
        return bufsize;
 }
 
-static ssize_t fmo_write(void *cookie, register const char *buf, size_t bufsize)
+static ssize_t fmo_write(register void *cookie, const char *buf, size_t bufsize)
 {
        size_t count;
 
@@ -499,7 +531,7 @@ static ssize_t fmo_write(void *cookie, register const char *buf, size_t bufsize)
 }
 
 /* glibc doesn't allow seeking, but it has in-buffer seeks... we don't. */
-static int fmo_seek(void *cookie, __offmax_t *pos, int whence)
+static int fmo_seek(register void *cookie, __offmax_t *pos, int whence)
 {
        __offmax_t p = *pos;
 
@@ -522,7 +554,7 @@ static int fmo_seek(void *cookie, __offmax_t *pos, int whence)
        return 0;
 }
 
-static int fmo_close(void *cookie)
+static int fmo_close(register void *cookie)
 {
        if (COOKIE->dynbuf) {
                free(COOKIE->buf);
@@ -545,7 +577,7 @@ static const cookie_io_functions_t _fmo_io_funcs = {
 FILE *fmemopen(void *s, size_t len, const char *modes)
 {
        FILE *fp;
-       __fmo_cookie *cookie;
+       register __fmo_cookie *cookie;
        size_t i;
 
        if ((cookie = malloc(sizeof(__fmo_cookie))) != NULL) {
@@ -614,9 +646,9 @@ typedef struct {
 /*  { */
 /*  } */
 
-static ssize_t oms_write(void *cookie, const char *buf, size_t bufsize)
+static ssize_t oms_write(register void *cookie, const char *buf, size_t bufsize)
 {
-       char *newbuf;
+       register char *newbuf;
        size_t count;
 
        /* Note: we already know bufsize < SSIZE_MAX... */
@@ -649,10 +681,10 @@ static ssize_t oms_write(void *cookie, const char *buf, size_t bufsize)
        return bufsize;
 }
 
-static int oms_seek(void *cookie, __offmax_t *pos, int whence)
+static int oms_seek(register void *cookie, __offmax_t *pos, int whence)
 {
        __offmax_t p = *pos;
-       char *buf;
+       register char *buf;
        size_t leastlen;
 
        /* Note: fseek already checks that whence is legal, so don't check here
@@ -713,8 +745,8 @@ static const cookie_io_functions_t _oms_io_funcs = {
 
 FILE *open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc)
 {
-       __oms_cookie *cookie;
-       FILE *fp;
+       register __oms_cookie *cookie;
+       register FILE *fp;
 
        if ((cookie = malloc(sizeof(__oms_cookie))) != NULL) {
                if ((cookie->buf = malloc(cookie->len = BUFSIZ)) == NULL) {
@@ -767,8 +799,8 @@ FILE *open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc)
 
 #ifndef __BCC__
 
-FILE *fopencookie (void * __restrict cookie, const char * __restrict mode,
-                                       cookie_io_functions_t io_functions)
+FILE *fopencookie(void * __restrict cookie, const char * __restrict mode,
+                                 cookie_io_functions_t io_functions)
 {
        FILE *stream;
        int fd;
@@ -804,10 +836,10 @@ FILE *fopencookie (void * __restrict cookie, const char * __restrict mode,
  * instead.
  */
 
-FILE *_fopencookie (void * __restrict cookie, const char * __restrict mode,
-                                       cookie_io_functions_t *io_functions)
+FILE *_fopencookie(void * __restrict cookie, const char * __restrict mode,
+                                  register cookie_io_functions_t *io_functions)
 {
-       FILE *stream;
+       register FILE *stream;
 
        if ((stream = _stdio_fopen("/dev/null", mode, NULL, -1)) != NULL) {
                int fd = stream->filedes;
@@ -929,7 +961,7 @@ void __fpurge(register FILE * __restrict stream)
 #ifdef __STDIO_GETC_MACRO
        stream->bufgetc =                       /* Must disable getc. */
 #endif
-       stream->bufwpos = stream->bufrpos = stream->bufstart; /* Reset pointers. */
+       stream->bufpos = stream->bufread = stream->bufstart; /* Reset pointers. */
 #endif /* __STDIO_BUFFERS */
        /* Reset r/w flags and clear ungots. */
        stream->modeflags &= ~(__FLAG_READING|__FLAG_WRITING|__MASK_UNGOT);
@@ -942,19 +974,22 @@ void __fpurge(register FILE * __restrict stream)
 /* Not reentrant. */
 
 #ifdef __STDIO_WIDE
-#warning TODO  -- implement __fpending for wide streams! */
-#else  /* __STDIO_WIDE */
+#warning unlike the glibc version, this __fpending returns bytes in buffer for wide streams too!
+
+link_warning(__fpending, "This version of __fpending returns bytes remaining in buffer for both narrow and wide streams.  glibc's version returns wide chars in buffer for the wide stream case.")
+
+#endif  /* __STDIO_WIDE */
+
 size_t __fpending(register FILE * __restrict stream)
 {
 #ifdef __STDIO_BUFFERS
        /* TODO -- should we check this?  should we set errno?  just assert? */
        return (stream->modeflags & (__FLAG_READING|__FLAG_READONLY))
-               ? 0 : (stream->bufwpos - stream->bufstart);
+               ? 0 : (stream->bufpos - stream->bufstart);
 #else  /* __STDIO_BUFFERS */
        return 0;
 #endif /* __STDIO_BUFFERS */
 }
-#endif /* __STDIO_WIDE */
 
 #endif
 /**********************************************************************/
@@ -1039,6 +1074,64 @@ void funlockfile(FILE *stream)
 
 #endif
 /**********************************************************************/
+#ifdef L_getline
+
+ssize_t getline(char **__restrict lineptr, size_t *__restrict n,
+                               FILE *__restrict stream)
+{
+       return __getdelim(lineptr, n, '\n', stream);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getdelim
+
+weak_alias(__getdelim,getdelim);
+
+#define GETDELIM_GROWBY                64
+
+ssize_t __getdelim(char **__restrict lineptr, size_t *__restrict n,
+                                  int delimiter, register FILE *__restrict stream)
+{
+       register char *buf;
+       size_t pos;
+       int c;
+
+       if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */
+               __set_errno(EINVAL);    /* though I think we should assert here */
+               return -1;                              /* if anything. */
+       }
+
+       if (!(buf = *lineptr)) {        /* If passed NULL for buffer, */
+               *n = 0;                                 /* ignore value passed and treat size as 0. */
+       }
+       pos = 1;                        /* Make sure we have space for terminating nul. */
+
+       __STDIO_THREADLOCK(stream);
+
+       do {
+               if (pos >= *n) {
+                       if (!(buf = realloc(buf, *n + GETDELIM_GROWBY))) {
+                               __set_errno(ENOMEM); /* Emulate old uClibc implementation. */
+                               break;
+                       }
+                       *n += GETDELIM_GROWBY;
+                       *lineptr = buf;
+               }
+       } while (((c = getc(stream)) != EOF) && ((buf[pos++ - 1] = c) != delimiter));
+
+       __STDIO_THREADUNLOCK(stream);
+
+       if (--pos) {
+               buf[pos] = 0;
+               return pos;
+       }
+
+       return -1;              /* Either initial realloc failed or first read was EOF. */
+}
+
+#endif
+/**********************************************************************/
 /* my extension functions */
 /**********************************************************************/
 #ifdef L__stdio_fsfopen
@@ -1079,11 +1172,9 @@ FILE *_stdio_fsfopen(const char * __restrict filename,
  * then the file position is treated as unknown.
  */
 
-
 /* Internal function -- not reentrant. */
 
-int _stdio_adjpos(register FILE * __restrict stream,
-                                       register __offmax_t *pos)
+int _stdio_adjpos(register FILE * __restrict stream, register __offmax_t *pos)
 {
        __offmax_t r;
        int cor = stream->modeflags & __MASK_UNGOT;     /* handle ungots */
@@ -1092,18 +1183,18 @@ int _stdio_adjpos(register FILE * __restrict stream,
        /* Assumed narrow stream so correct if wide. */
        if (cor && (stream->modeflags & __FLAG_WIDE)) {
                cor = cor - 1 + stream->ungot_width[0];
-               if ((stream->ungot_width[0] == 0) /* don't know byte count or */
-                       || ((stream->modeflags & __MASK_UNGOT) > 1)) { /* app case */
-                       return -1;
+               if (((stream->modeflags & __MASK_UNGOT) > 1) || stream->ungot[1]) {
+                       return -1; /* App did ungetwc, so position is indeterminate. */
                }
+               assert(stream->ungot_width[0] > 0);
        }
 #endif /* __STDIO_WIDE */
 #ifdef __STDIO_BUFFERS
        if (stream->modeflags & __FLAG_WRITING) {
-               cor -= (stream->bufwpos - stream->bufstart); /* pending writes */
+               cor -= (stream->bufpos - stream->bufstart); /* pending writes */
        }
        if (stream->modeflags & __FLAG_READING) {
-               cor += (stream->bufwpos - stream->bufrpos); /* extra's read */
+               cor += (stream->bufread - stream->bufpos); /* extra's read */
        }
 #endif /* __STDIO_BUFFERS */
 
@@ -1122,7 +1213,7 @@ int _stdio_adjpos(register FILE * __restrict stream,
 
 /* Internal function -- not reentrant. */
 
-int _stdio_lseek(FILE *stream, __offmax_t *pos, int whence)
+int _stdio_lseek(register FILE *stream, register __offmax_t *pos, int whence)
 {
        __offmax_t res;
 
@@ -1152,7 +1243,7 @@ int _stdio_lseek(FILE *stream, __offmax_t *pos, int whence)
 
 /* Unlike write, it's ok for read to return fewer than bufsize, since
  * we may not need all of them. */
-static ssize_t _stdio_READ(FILE *stream, void *buf, size_t bufsize)
+static ssize_t _stdio_READ(register FILE *stream, unsigned char *buf, size_t bufsize)
 {
        ssize_t rv;
 
@@ -1192,8 +1283,7 @@ static ssize_t _stdio_READ(FILE *stream, void *buf, size_t bufsize)
 
 /* Internal function -- not reentrant. */
 
-size_t _stdio_fread(unsigned char *buffer, size_t bytes,
-                                         register FILE *stream)
+size_t _stdio_fread(unsigned char *buffer, size_t bytes, register FILE *stream)
 {
        __stdio_validate_FILE(stream); /* debugging only */
 
@@ -1233,12 +1323,15 @@ size_t _stdio_fread(unsigned char *buffer, size_t bytes,
        if (stream->modeflags & __MASK_BUFMODE) {
                /* If the stream is readable and not fully buffered, we must first
                 * flush all line buffered output streams.  Do this before the
-                * error check as this may be a read/write line-buffered stream. */
-               fflush((FILE *) &_stdio_openlist); /* Uses an implementation hack!!! */
+                * error check as this may be a read/write line-buffered stream.
+                * Note: Uses an implementation-specific hack!!! */
+               fflush_unlocked((FILE *) &_stdio_openlist);
        }
 
 #ifdef __STDIO_AUTO_RW_TRANSITION
-       if ((stream->modeflags & __FLAG_WRITING) && (fflush(stream) == EOF)) {
+       if ((stream->modeflags & __FLAG_WRITING)
+               && (fflush_unlocked(stream) == EOF)
+               ) {
                return 0;                               /* Fail if we need to fflush but can't. */
        }
 #endif /* __STDIO_AUTO_RW_TRANSITION */
@@ -1260,23 +1353,23 @@ size_t _stdio_fread(unsigned char *buffer, size_t bytes,
 
                /* Now get any other needed chars from the buffer or the file. */
        FROM_BUF:
-               while (bytes && (stream->bufrpos < stream->bufwpos)) {
+               while (bytes && (stream->bufpos < stream->bufread)) {
                        --bytes;
-                       *p++ = *stream->bufrpos++;
+                       *p++ = *stream->bufpos++;
                }
 
                if (bytes > 0) {
                        ssize_t len;
 
                        /* The buffer is exhausted, but we still need chars.  */
-                       stream->bufrpos = stream->bufwpos = stream->bufstart;
+                       stream->bufpos = stream->bufread = stream->bufstart;
 
-                       if (bytes <= stream->bufend - stream->bufwpos) {
+                       if (bytes <= stream->bufend - stream->bufread) {
                                /* We have sufficient space in the buffer. */
-                               len = _stdio_READ(stream, stream->bufwpos,
-                                                                 stream->bufend - stream->bufwpos);
+                               len = _stdio_READ(stream, stream->bufread,
+                                                                 stream->bufend - stream->bufread);
                                if (len > 0) {
-                                       stream->bufwpos += len;
+                                       stream->bufread += len;
                                        goto FROM_BUF;
                                }
                        } else {
@@ -1293,7 +1386,7 @@ size_t _stdio_fread(unsigned char *buffer, size_t bytes,
 
 #ifdef __STDIO_GETC_MACRO
                if (!(stream->modeflags & (__FLAG_WIDE|__MASK_UNGOT|__MASK_BUFMODE))) {
-                       stream->bufgetc = stream->bufwpos; /* Enable getc macro. */
+                       stream->bufgetc = stream->bufread; /* Enable getc macro. */
                }
 #endif
 
@@ -1377,7 +1470,8 @@ size_t _stdio_fread(unsigned char *buffer, size_t bytes,
  *deals correctly with bufsize > SSIZE_MAX... not much on an issue on linux
  * but definitly could be on Elks.  Also on Elks, always loops for EINTR..
  * Returns number of bytes written, so a short write indicates an error */
-static size_t _stdio_WRITE(FILE *stream, const void *buf, size_t bufsize)
+static size_t _stdio_WRITE(register FILE *stream,
+                                                  register const unsigned char *buf, size_t bufsize)
 {
        size_t todo;
        ssize_t rv, stodo;
@@ -1412,7 +1506,7 @@ static size_t _stdio_WRITE(FILE *stream, const void *buf, size_t bufsize)
 /* Internal function -- not reentrant. */
 
 size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
-                                          register FILE *stream)
+                                        register FILE *stream)
 {
 #ifdef __STDIO_BUFFERS
        register const unsigned char *p;
@@ -1438,7 +1532,7 @@ size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
 #ifdef __STDIO_AUTO_RW_TRANSITION
        /* If reading, deal with ungots and read-buffered chars. */
        if (stream->modeflags & __FLAG_READING) {
-               if (((stream->bufrpos < stream->bufwpos)
+               if (((stream->bufpos < stream->bufread)
                         || (stream->modeflags & __MASK_UNGOT))
                        /* If appending, we might as well seek to end to save a seek. */
                        /* TODO: set EOF in fseek when appropriate? */
@@ -1456,7 +1550,7 @@ size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
 #ifdef __STDIO_GETC_MACRO
                stream->bufgetc =
 #endif /* __STDIO_GETC_MACRO */
-               stream->bufrpos = stream->bufwpos = stream->bufstart;
+               stream->bufpos = stream->bufread = stream->bufstart;
        }
 #endif
 
@@ -1475,7 +1569,7 @@ size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
                if (!buffer) {                          /* fflush the stream */
                FFLUSH:
                        {
-                               size_t count = stream->bufwpos - stream->bufstart;
+                               size_t count = stream->bufpos - stream->bufstart;
                                p = stream->bufstart;
 
                                if (stream->filedes == -2) { /* TODO -- document this hack! */
@@ -1489,22 +1583,22 @@ size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
                                        count -= rv;
                                }
                        
-                               stream->bufwpos = stream->bufstart;
+                               stream->bufpos = stream->bufstart;
                                while (count) {
-                                       *stream->bufwpos++ = *p++;
+                                       *stream->bufpos++ = *p++;
                                        --count;
                                }
 
                                if (!buffer) {  /* fflush case... */
                                        __stdio_validate_FILE(stream); /* debugging only */
-                                       return stream->bufwpos - stream->bufstart;
+                                       return stream->bufpos - stream->bufstart;
                                }
                        }
                }
 
 #if 1
                /* TODO: If the stream is buffered, we may be able to omit. */
-               if ((stream->bufwpos == stream->bufstart) /* buf empty */
+               if ((stream->bufpos == stream->bufstart) /* buf empty */
                        && (stream->bufend - stream->bufstart <= bytes) /* fills */
                        && (stream->filedes != -2)) { /* not strinf fake file */
                        /* so want to do a direct write of supplied buffer */
@@ -1517,7 +1611,7 @@ size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
 #endif
                /* otherwise buffer not empty and/or data fits */
                {
-                       size_t count = stream->bufend - stream->bufwpos;
+                       size_t count = stream->bufend - stream->bufpos;
                        p = buffer;
 
                        if (count > bytes) {
@@ -1526,7 +1620,7 @@ size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
                        bytes -= count;
 
                        while (count) {
-                               *stream->bufwpos++ = *buffer++;
+                               *stream->bufpos++ = *buffer++;
                                --count;
                        }
 
@@ -1615,10 +1709,12 @@ void __stdio_validate_FILE(FILE *stream)
        __STDIO_THREADLOCK(stream);
 
 #ifdef __STDIO_BUFFERS
-       assert(stream->bufstart <= stream->bufrpos);
-       assert(stream->bufrpos <= stream->bufwpos);
-       assert(stream->bufwpos <= stream->bufend);
-       assert(stream->bufwpos <= stream->bufend);
+       assert(stream->bufstart <= stream->bufread);
+       if (stream->modeflags & (__FLAG_READING)) {
+               assert(stream->bufpos <= stream->bufread);
+       }
+       assert(stream->bufread <= stream->bufend);
+       assert(stream->bufpos <= stream->bufend);
        if ((stream->modeflags & __MASK_BUFMODE) == __FLAG_NBF) {
                assert(stream->bufstart == stream->bufend);
        }
@@ -1637,7 +1733,7 @@ void __stdio_validate_FILE(FILE *stream)
 #endif
 #ifdef __STDIO_GETC_MACRO
        assert(stream->bufstart <= stream->bufgetc);
-       assert(stream->bufgetc <= stream->bufwpos);
+       assert(stream->bufgetc <= stream->bufread);
        if (stream->bufstart < stream->bufgetc) {
                assert(stream->modeflags & (__FLAG_READING));
                assert(!(stream->modeflags
@@ -1693,9 +1789,9 @@ static FILE _stdio_streams[] = {
                                                         2, 0, 0, 0 )
 };
 
-FILE *_stdin = _stdio_streams + 0;
-FILE *_stdout = _stdio_streams + 1;
-FILE *_stderr = _stdio_streams + 2;
+FILE *stdin = _stdio_streams + 0;
+FILE *stdout = _stdio_streams + 1;
+FILE *stderr = _stdio_streams + 2;
 
 #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
 
@@ -1725,7 +1821,7 @@ void __stdio_init_mutex(pthread_mutex_t *m)
 void _stdio_term(void)
 {
 #if defined(__STDIO_GLIBC_CUSTOM_STREAMS) || defined(__STDIO_THREADSAFE)
-       FILE *ptr;
+       register FILE *ptr;
 #endif
 
        /* TODO: if called via a signal handler for a signal mid _stdio_fwrite,
@@ -1746,7 +1842,7 @@ void _stdio_term(void)
        /* TODO -- set an alarm and flush each file "by hand"? to avoid blocking? */
 
        /* Now flush all streams. */
-       fflush(NULL);
+       fflush_unlocked(NULL);
 #endif /* __STDIO_BUFFERS */
 
        /* Next close all custom streams in case of any special cleanup, but
@@ -1765,7 +1861,7 @@ void _stdio_term(void)
                        /* TODO: "unbuffer" files like glibc does?  Inconsistent with
                         * custom stream handling above, but that's necessary to deal
                         * with special user-defined close behavior. */
-                       stream->bufwpos = stream->bufrpos = stream->bufend
+                       stream->bufpos = stream->bufread = stream->bufend
 #ifdef __STDIO_GETC_MACRO
                                = stream->bufgetc
 #endif
@@ -1867,8 +1963,8 @@ int fclose(register FILE *stream)
 
 #ifdef __STDIO_BUFFERS
        if (stream->modeflags & __FLAG_WRITING) {
-               rv = fflush(stream);    /* Write any pending buffered chars. */
-       }                                                       /* Also disables putc macro if used. */
+               rv = fflush_unlocked(stream); /* Write any pending buffered chars. */
+       }                                                                 /* Also disables putc macro if used. */
 
 #ifdef __STDIO_GETC_MACRO
        /* Not necessary after fflush, but always do this to reduce size. */
@@ -2097,8 +2193,8 @@ FILE *fopen(const char * __restrict filename, const char * __restrict mode)
 /* Internal function -- reentrant (locks open file list) */
 
 FILE *_stdio_fopen(const char * __restrict filename,
-                                        register const char * __restrict mode,
-                                        register FILE * __restrict stream, int filedes)
+                                  register const char * __restrict mode,
+                                  register FILE * __restrict stream, int filedes)
 {
        __mode_t open_mode;
 
@@ -2230,7 +2326,7 @@ FILE *_stdio_fopen(const char * __restrict filename,
 #ifdef __STDIO_PUTC_MACRO
        stream->bufputc =
 #endif
-       stream->bufwpos = stream->bufrpos = stream->bufstart;
+       stream->bufpos = stream->bufread = stream->bufstart;
 #endif /* __STDIO_BUFFERS */
 
 #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
@@ -2241,6 +2337,10 @@ FILE *_stdio_fopen(const char * __restrict filename,
        stream->gcs.close = _cs_close;
 #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
 
+#ifdef __STDIO_MBSTATE
+       __INIT_MBSTATE(&(stream->state));
+#endif /* __STDIO_MBSTATE */
+
 #ifdef __STDIO_THREADSAFE
        __stdio_init_mutex(&stream->lock);
 #endif /* __STDIO_THREADSAFE */
@@ -2282,7 +2382,7 @@ FILE *freopen(const char * __restrict filename, const char * __restrict mode,
         * TODO: Apparently linux allows setting append mode.  Implement?
         */
        unsigned short dynmode;
-       FILE *fp;
+       register FILE *fp;
 
        __STDIO_THREADLOCK(stream);
 
@@ -2290,7 +2390,7 @@ FILE *freopen(const char * __restrict filename, const char * __restrict mode,
        /* This also removes the stream for the open file list. */
        dynmode = 
 #ifdef __STDIO_BUFFERS
-               //              __MASK_BUFMODE |                /* TODO: check */
+               /*              __MASK_BUFMODE | */             /* TODO: check */
 #endif /* __STDIO_BUFFERS */
                (stream->modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
 
@@ -2310,12 +2410,12 @@ FILE *freopen(const char * __restrict filename, const char * __restrict mode,
 
 /* Reentrant. */
 
-/* TODO -- is it collecting the common work (40 bytes) into a function? */
+/* TODO -- is it worth collecting the common work (40 bytes) in a function? */
 FILE *freopen64(const char * __restrict filename, const char * __restrict mode,
                                register FILE * __restrict stream)
 {
        unsigned short dynmode;
-       FILE *fp;
+       register FILE *fp;
 
        __STDIO_THREADLOCK(stream);
 
@@ -2323,7 +2423,7 @@ FILE *freopen64(const char * __restrict filename, const char * __restrict mode,
        /* This also removes the stream for the open file list. */
        dynmode = 
 #ifdef __STDIO_BUFFERS
-               //              __MASK_BUFMODE |                /* TODO: check */
+               /*              __MASK_BUFMODE | */             /* TODO: check */
 #endif /* __STDIO_BUFFERS */
                (stream->modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
 
@@ -2448,7 +2548,7 @@ int setvbuf(register FILE * __restrict stream, register char * __restrict buf,
 #ifdef __STDIO_PUTC_MACRO
                stream->bufputc =
 #endif
-               stream->bufwpos = stream->bufrpos = stream->bufstart = buf;
+               stream->bufpos = stream->bufread = stream->bufstart = buf;
                stream->bufend = buf + size;
        }
 
@@ -2603,9 +2703,9 @@ UNLOCKED(int,getc,(register FILE *stream),(stream))
 
 /* Reentrancy handled by UNLOCKED() macro. */
 
-UNLOCKED_STREAM(int,getchar,(void),(),_stdin)
+UNLOCKED_STREAM(int,getchar,(void),(),stdin)
 {
-       register FILE *stream = _stdin; /* This helps bcc optimize. */
+       register FILE *stream = stdin; /* This helps bcc optimize. */
 
        return __GETC(stream);
 }
@@ -2620,7 +2720,7 @@ link_warning(gets, "the 'gets' function is dangerous and should not be used.")
 
 char *gets(char *s)                            /* WARNING!!! UNSAFE FUNCTION!!! */
 {
-       register FILE *stream = _stdin; /* This helps bcc optimize. */
+       register FILE *stream = stdin;  /* This helps bcc optimize. */
        register char *p = s;
        int c;
 
@@ -2628,7 +2728,7 @@ char *gets(char *s)                               /* WARNING!!! UNSAFE FUNCTION!!! */
 
        /* Note: don't worry about performance here... this shouldn't be used!
         * Therefore, force actual function call. */
-       while (((c = (*getc)(stream)) != EOF) && ((*p = c) != '\n')) {
+       while (((c = (getc_unlocked)(stream)) != EOF) && ((*p = c) != '\n')) {
                ++p;
        }
        if ((c == EOF) || (s == p)) {
@@ -2661,9 +2761,9 @@ UNLOCKED(int,putc,(int c, register FILE *stream),(c,stream))
 
 /* Reentrancy handled by UNLOCKED() macro. */
 
-UNLOCKED_STREAM(int,putchar,(int c),(c),_stdout)
+UNLOCKED_STREAM(int,putchar,(int c),(c),stdout)
 {
-       register FILE *stream = _stdout; /* This helps bcc optimize. */
+       register FILE *stream = stdout; /* This helps bcc optimize. */
 
        return __PUTC(c, stream);
 }
@@ -2676,17 +2776,17 @@ UNLOCKED_STREAM(int,putchar,(int c),(c),_stdout)
 
 int puts(register const char *s)
 {
-       register FILE *stream = _stdout; /* This helps bcc optimize. */
+       register FILE *stream = stdout; /* This helps bcc optimize. */
        int n;
 
        __STDIO_THREADLOCK(stream);
 
-       n = fputs(s,stream) + 1;
+       n = fputs_unlocked(s,stream) + 1;
        if (
 #if 1
-               fputc('\n',stream)
+               fputc_unlocked('\n',stream)
 #else
-               fputs("\n",stream)
+               fputs_unlocked("\n",stream)
 #endif
                == EOF) {
                n = EOF;
@@ -2739,7 +2839,7 @@ int ungetc(int c, register FILE *stream)
 #ifdef __STDIO_BUFFERS
                                                                /* TODO: shouldn't allow writing??? */
        if (stream->modeflags & __FLAG_WRITING) {
-               fflush(stream);                 /* Commit any write-buffered chars. */
+               fflush_unlocked(stream); /* Commit any write-buffered chars. */
        }
 #endif /* __STDIO_BUFFERS */
 
@@ -2838,21 +2938,22 @@ UNLOCKED(size_t,fwrite,
 
 int fgetpos64(FILE * __restrict stream, register fpos64_t * __restrict pos)
 {
+#ifdef __STDIO_MBSTATE
        int retval;
 
        __STDIO_THREADLOCK(stream);
 
        retval = ((pos != NULL) && ((pos->__pos = ftello64(stream)) >= 0))
-               ? (
-#ifdef __STDIO_MBSTATE_DATA
-                  __COPY_MBSTATE(&(pos->__mbstate), &(stream->mbstate)),
-#endif /* __STDIO_MBSTATE_DATA */
-                  0)
+               ? (__COPY_MBSTATE(&(pos->__mbstate), &(stream->state)), 0)
                : (__set_errno(EINVAL), -1);
 
        __STDIO_THREADUNLOCK(stream);
 
        return retval;
+#else
+       return ((pos != NULL) && ((pos->__pos = ftello64(stream)) >= 0))
+               ? 0 : (__set_errno(EINVAL), -1);
+#endif
 }
 
 #ifndef L_fgetpos64
@@ -2864,7 +2965,7 @@ int fgetpos64(FILE * __restrict stream, register fpos64_t * __restrict pos)
 #endif
 /**********************************************************************/
 #ifdef L_fseek
-strong_alias(fseek, fseeko);
+strong_alias(fseek,fseeko);
 #endif
 
 #if defined(L_fseek) && defined(__STDIO_LARGE_FILES)
@@ -2907,7 +3008,7 @@ int fseeko64(register FILE *stream, __off64_t offset, int whence)
        if (
 #ifdef __STDIO_BUFFERS
                /* First commit any pending buffered writes. */
-               ((stream->modeflags & __FLAG_WRITING) && fflush(stream)) ||
+               ((stream->modeflags & __FLAG_WRITING) && fflush_unlocked(stream)) ||
 #endif /* __STDIO_BUFFERS */
                ((whence == SEEK_CUR) && (_stdio_adjpos(stream, pos) < 0))
                || (_stdio_lseek(stream, pos, whence) < 0)
@@ -2921,16 +3022,16 @@ int fseeko64(register FILE *stream, __off64_t offset, int whence)
 #ifdef __STDIO_GETC_MACRO
        stream->bufgetc =                       /* Must disable getc. */
 #endif
-       stream->bufwpos = stream->bufrpos = stream->bufstart;
+       stream->bufpos = stream->bufread = stream->bufstart;
 #endif /* __STDIO_BUFFERS */
 
        stream->modeflags &=
                ~(__FLAG_READING|__FLAG_WRITING|__FLAG_EOF|__MASK_UNGOT);
 
-#ifdef __STDIO_MBSTATE_DATA
+#ifdef __STDIO_MBSTATE
        /* TODO: don't clear state if don't move? */
-       __INIT_MBSTATE(&(stream->mbstate));
-#endif /* __STDIO_MBSTATE_DATA */
+       __INIT_MBSTATE(&(stream->state));
+#endif /* __STDIO_MBSTATE */
        __stdio_validate_FILE(stream); /* debugging only */
 
        retval = 0;
@@ -2968,18 +3069,23 @@ int fsetpos64(FILE *stream, register const fpos64_t *pos)
                __set_errno(EINVAL);
                return EOF;
        }
-#ifdef __STDIO_MBSTATE_DATA
-#error unimplemented and non-reentrant besides!
+#ifdef __STDIO_MBSTATE
        {
                int retval;
+
+               __STDIO_THREADLOCK(stream);
+
                if ((retval = fseeko64(stream, pos->__pos, SEEK_SET)) == 0) {
-                       __COPY_MBSTATE(&(stream->mbstate), &(pos->__mbstate));
+                       __COPY_MBSTATE(&(stream->state), &(pos->__mbstate));
                }
+
+               __STDIO_THREADUNLOCK(stream);
+
                return retval;
        }
-#else  /* __STDIO_MBSTATE_DATA */
+#else  /* __STDIO_MBSTATE */
        return fseeko64(stream, pos->__pos, SEEK_SET);
-#endif /* __STDIO_MBSTATE_DATA */
+#endif /* __STDIO_MBSTATE */
 }
 
 #ifndef L_fsetpos64
@@ -2991,7 +3097,7 @@ int fsetpos64(FILE *stream, register const fpos64_t *pos)
 #endif
 /**********************************************************************/
 #ifdef L_ftell
-strong_alias(ftell, ftello);
+strong_alias(ftell,ftello);
 #endif
 
 #if defined(L_ftell) && defined(__STDIO_LARGE_FILES)
@@ -3042,6 +3148,10 @@ void rewind(register FILE *stream)
 
        __CLEARERR(stream);                     /* Clear errors first and then seek */
        fseek(stream, 0L, SEEK_SET); /* in case there is an error seeking. */
+#ifdef __STDIO_MBSTATE
+       /* TODO: Is it correct to re-init the stream's state?  I think so... */
+       __INIT_MBSTATE(&(stream->state));
+#endif /* __STDIO_MBSTATE */
 
        __STDIO_THREADUNLOCK(stream);
 }
@@ -3103,11 +3213,11 @@ void perror(register const char *s)
 
 #if 1
 #ifdef __STDIO_PRINTF_M_SPEC
-       fprintf(_stderr, "%s%s%m\n", s, sep); /* Use the gnu %m feature. */
+       fprintf(stderr, "%s%s%m\n", s, sep); /* Use the gnu %m feature. */
 #else
        {
                char buf[64];
-               fprintf(_stderr, "%s%s%s\n", s, sep,
+               fprintf(stderr, "%s%s%s\n", s, sep,
                                _stdio_strerror_r(errno, buf, sizeof(buf)));
        }
 #endif
@@ -3135,7 +3245,7 @@ void perror(register const char *s)
 void _stdio_fdout(int fd, ...)
 {
        va_list arg;
-       const char *p;
+       register const char *p;
 
        va_start(arg, fd);
        while ((p = va_arg(arg, const char *)) != NULL) {
@@ -3154,8 +3264,8 @@ void _stdio_fdout(int fd, ...)
 #define INTERNAL_DIV_MOD
 #endif
 
-char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval,
-                                        int base, __UIM_CASE alphacase)
+char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
+                                       int base, __UIM_CASE alphacase)
 {
     int negative;
     unsigned int digit;
@@ -3231,7 +3341,7 @@ char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval,
 
 static const char unknown[] = "Unknown error";
 
-char *_stdio_strerror_r(int err, char *buf, size_t buflen)
+char *_stdio_strerror_r(int err, register char *buf, size_t buflen)
 {
        int errsave;
 
index 4c9e8f0..689fdeb 100644 (file)
@@ -638,7 +638,17 @@ void ssort (void  *base,
 #define UTF_8_MAX_LEN 3
 #endif
 
+#ifdef __UCLIBC_HAS_LOCALE__
 #define ENCODING (__global_locale.encoding)
+#warning implement __CTYPE_HAS_UTF_8_LOCALES!
+#define __CTYPE_HAS_UTF_8_LOCALES
+#else
+#define ENCODING (__ctype_encoding_7_bit)
+#undef __CTYPE_HAS_8_BIT_LOCALES
+#undef __CTYPE_HAS_UTF_8_LOCALES
+#undef L__wchar_utf8sntowcs
+#undef L__wchar_wcsntoutf8s
+#endif
 
 #endif
 
@@ -647,16 +657,20 @@ void ssort (void  *base,
 
 size_t _stdlib_mb_cur_max(void)
 {
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
        return __global_locale.mb_cur_max;
+#else
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+#warning need to change this when/if transliteration is implemented
+#endif
+       return 1;
+#endif
 }
 
 #endif
 /**********************************************************************/
 #ifdef L_mblen
 
-#warning implement __CTYPE_HAS_UTF_8_LOCALES!
-#define __CTYPE_HAS_UTF_8_LOCALES
-
 int mblen(register const char *s, size_t n)
 {
        static mbstate_t state;
@@ -683,9 +697,6 @@ int mblen(register const char *s, size_t n)
 /**********************************************************************/
 #ifdef L_mbtowc
 
-#warning implement __CTYPE_HAS_UTF_8_LOCALES!
-#define __CTYPE_HAS_UTF_8_LOCALES
-
 int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
 {
        static mbstate_t state;
@@ -712,9 +723,6 @@ int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
 /**********************************************************************/
 #ifdef L_wctomb
 
-#warning implement __CTYPE_HAS_UTF_8_LOCALES!
-#define __CTYPE_HAS_UTF_8_LOCALES
-
 /* Note: We completely ignore state in all currently supported conversions. */
 
 int wctomb(register char *__restrict s, wchar_t swc)
index 2cd1334..f19782c 100644 (file)
@@ -38,6 +38,8 @@ MOBJW2= wcscasecmp.o wcscat.o wcschrnul.o wcschr.o wcscmp.o wcscpy.o wcscspn.o \
        wcsnlen.o wcspbrk.o wcsrchr.o wcsspn.o wcsstr.o wcstok.o wmemchr.o \
        wmemcmp.o wmemcpy.o wmemmove.o wmempcpy.o wmemset.o
 
+# wcscoll wcsxfrm wcpcpy wcpncpy
+
 MSRC1=strsignal.c
 MOBJ1=strsignal.o psignal.o
 
index 4c619ad..59300f1 100644 (file)
@@ -293,7 +293,7 @@ int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n)
 
 #ifndef L_wcscmp
 #warning implement strcoll and remove weak alias (or enable for C locale only)
-weak_alias(strcmp, strcoll);
+weak_alias(strcmp,strcoll);
 #endif
 
 int Wstrcmp(register const Wchar *s1, register const Wchar *s2)
index 2a35d38..a9cd39f 100644 (file)
 #define __LC_ALL                       6
 
 /**********************************************************************/
-#if defined(_LIBC) && !defined(__LOCALE_C_ONLY)
-
-#include <stddef.h>
-#include <stdint.h>
-#include <bits/uClibc_locale_data.h>
+#ifdef _LIBC
 
 /* TODO: This really needs to be somewhere else... */
 #include <limits.h>
@@ -89,6 +85,14 @@ typedef uintmax_t                    __uwchar_t;
 #error Can not determine an appropriate type for __uwchar_t!
 #endif
 
+#endif
+
+/**********************************************************************/
+#if defined(_LIBC) && !defined(__LOCALE_C_ONLY)
+
+#include <stddef.h>
+#include <stdint.h>
+#include <bits/uClibc_locale_data.h>
 
 
 extern void _locale_set(const unsigned char *p);
index 1a559bd..16a7da8 100644 (file)
 #define __STDIO_LARGE_FILES
 #endif /* __UCLIBC_HAVE_LFS__ */
 
+#ifdef __UCLIBC_HAS_WCHAR__
+#define __STDIO_WIDE
+#endif
+
 /* Make sure defines related to large files are consistent. */
 #ifdef _LIBC
 
 /* These are the stdio configuration options.  Keep them here until
    uClibc's configuration process gets reworked. */
 
-/*  #define __STDIO_WIDE */
 #ifdef __STDIO_WIDE
-typedef int __wchar_t;                 /* TODO: temporary, as not currently uClibc */
+#define __need_wchar_t
+#include <stddef.h>
+/* Note: we don't really need mbstate for 8-bit locales.  We do for UTF-8.
+ * For now, always use it. */
+#define __STDIO_MBSTATE
+#define __need_mbstate_t
+#include <wchar.h>
 #endif
 
 #define __STDIO_BUFFERS
@@ -163,13 +172,19 @@ typedef int __wchar_t;                    /* TODO: temporary, as not currently uClibc */
 
 typedef struct {
        __off_t __pos;
-/*    __mbstate_t __state; */
+#ifdef __STDIO_MBSTATE
+  __mbstate_t __mbstate;
+#endif
 } __stdio_fpos_t;
 
+#ifdef __STDIO_LARGE_FILES
 typedef struct {
        __off64_t __pos;
-/*    __mbstate_t __state; */
+#ifdef __STDIO_MBSTATE
+  __mbstate_t __mbstate;
+#endif
 } __stdio_fpos64_t;
+#endif
 
 
 /**********************************************************************/
@@ -229,8 +244,9 @@ 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];
-       __wchar_t ungot[2];
+       wchar_t ungot[2];
 #else  /* __STDIO_WIDE */
        unsigned char ungot[2];
 #endif /* __STDIO_WIDE */
@@ -241,8 +257,8 @@ struct __stdio_file_struct {
 #ifdef __STDIO_BUFFERS
        unsigned char *bufstart;        /* pointer to buffer */
        unsigned char *bufend;          /* pointer to 1 past end of buffer */
-       unsigned char *bufwpos;         /* pointer to 1 past last buffered */
-       unsigned char *bufrpos;         /* pointer to next readable buffered */
+       unsigned char *bufpos;
+       unsigned char *bufread;         /* pointer to 1 past last buffered read char. */
 #ifdef __STDIO_GETC_MACRO
        unsigned char *bufgetc;         /* 1 past last readable by getc */
 #endif /* __STDIO_GETC_MACRO */
@@ -254,6 +270,9 @@ struct __stdio_file_struct {
        void *cookie;
        _IO_cookie_io_functions_t gcs;
 #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
+#ifdef __STDIO_MBSTATE
+       __mbstate_t state;
+#endif
 #ifdef __STDIO_THREADSAFE
        int user_locking;
        pthread_mutex_t lock;
@@ -302,6 +321,16 @@ extern int _cs_close(void *cookie);
 
 /**********************************************************************/
 
+#ifdef __STDIO_MBSTATE
+#define __COPY_MBSTATE(dest,src)  ((dest)->mask = (src)->mask, (dest)->wc = (src)->wc)
+#define __INIT_MBSTATE(dest) ((dest)->mask = 0)
+#else
+#define __COPY_MBSTATE(dest,src)
+#define __INIT_MBSTATE(dest)
+#endif
+
+/**********************************************************************/
+
 /* TODO -- thread safety issues */
 #define __CLEARERR(stream) \
        ((stream)->modeflags &= ~(__FLAG_EOF|__FLAG_ERROR), (void)0)
@@ -323,16 +352,16 @@ extern int _cs_close(void *cookie);
  */
 
 #ifdef __STDIO_GETC_MACRO
-#define __GETC(stream)         ( ((stream)->bufrpos < (stream)->bufgetc) \
-                                                       ? (*(stream)->bufrpos++) \
+#define __GETC(stream)         ( ((stream)->bufpos < (stream)->bufgetc) \
+                                                       ? (*(stream)->bufpos++) \
                                                        : fgetc_unlocked(stream) )
 #else  /* __STDIO_GETC_MACRO */
 #define __GETC(stream)         fgetc_unlocked(stream)
 #endif /* __STDIO_GETC_MACRO */
 
 #ifdef __STDIO_PUTC_MACRO
-#define __PUTC(c, stream)      ( ((stream)->bufwpos < (stream)->bufputc) \
-                                                       ? (*(stream)->bufwpos++) = (c) \
+#define __PUTC(c, stream)      ( ((stream)->bufpos < (stream)->bufputc) \
+                                                       ? (*(stream)->bufpos++) = (c) \
                                                        : fputc_unlocked((c),(stream)) )
 #else  /* __STDIO_PUTC_MACRO */
 #define __PUTC(c, stream)      fputc_unlocked(c, stream);
@@ -488,7 +517,9 @@ extern char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval,
 
 /* TODO: note done above..  typedef struct __stdio_file_struct _UC_FILE; */
 typedef __stdio_fpos_t         _UC_fpos_t;
+#ifdef __STDIO_LARGE_FILES
 typedef __stdio_fpos64_t       _UC_fpos64_t;
+#endif
 
 #define _UC_IOFBF              _STDIO_IOFBF /* Fully buffered.  */
 #define _UC_IOLBF              _STDIO_IOLBF /* Line buffered.  */