[uClibc-cvs] uClibc/libc/sysdeps/linux/common/bits uClibc_uintmaxtostr.h, NONE, 1.1 uClibc_locale.h, 1.12, 1.13 uClibc_stdio.h, 1.15, 1.16

Manuel Novoa III mjn3 at uclibc.org
Wed Feb 11 23:48:52 UTC 2004


Update of /var/cvs/uClibc/libc/sysdeps/linux/common/bits
In directory nail:/tmp/cvs-serv16121/libc/sysdeps/linux/common/bits

Modified Files:
	uClibc_locale.h uClibc_stdio.h 
Added Files:
	uClibc_uintmaxtostr.h 
Log Message:
New stdio core.  Should be more maintainable.  Fixes a couple of bugs.
  Codepaths streamlined.  Improved performance for nonthreaded apps
  when linked with a thread-enabled libc.
Minor iconv bug and some locale/thread related startup issues fixed.
  These showed up in getting a gcj-compiled java helloworld app running.
Removed some old extension functions... _stdio_fdout and _stdio_fsfopen.


--- NEW FILE: uClibc_uintmaxtostr.h ---
/*  Copyright (C) 2003     Manuel Novoa III
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!
 *
 *  This code is currently under development.  Also, I plan to port
 *  it to elks which is a 16-bit environment with a fairly limited
 *  compiler.  Therefore, please refrain from modifying this code
 *  and, instead, pass any bug-fixes, etc. to me.  Thanks.  Manuel
 *
 *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */

#ifndef _UINTMAXTOSTR_H
#define _UINTMAXTOSTR_H 1

#ifdef _FEATURES_H
# ifndef __USE_ISOC99
#  error features was included without defining _ISOC99_SOURCE!
# endif
#else
# ifndef _ISOC99_SOURCE
#  define _ISOC99_SOURCE
# endif
#endif

#include <features.h>
#include <limits.h>
#include <stdint.h>

#if INTMAX_MAX <= 2147483647L
#define __UIM_BUFLEN			12 /* 10 digits + 1 nul + 1 sign */
#elif INTMAX_MAX <= 9223372036854775807LL
#define __UIM_BUFLEN			22 /* 20 digits + 1 nul + 1 sign */
#else
#error unknown number of digits for intmax_t!
#endif

#ifdef LLONG_MAX				/* --------------- */
#if LLONG_MAX <= 2147483647L
#define __UIM_BUFLEN_LLONG		12 /* 10 digits + 1 nul + 1 sign */
#elif LLONG_MAX <= 9223372036854775807LL
#define __UIM_BUFLEN_LLONG		22 /* 20 digits + 1 nul + 1 sign */
#else
#error unknown number of digits for long long!
#endif
#endif /* ULLONG_MAX ----------------------------- */

#if LONG_MAX <= 2147483647L
#define __UIM_BUFLEN_LONG		12 /* 10 digits + 1 nul + 1 sign */
#elif LONG_MAX <= 9223372036854775807LL
#define __UIM_BUFLEN_LONG		22 /* 20 digits + 1 nul + 1 sign */
#else
#error unknown number of digits for long!
#endif

#if INT_MAX <= 32767
#define __UIM_BUFLEN_INT		7 /* 10 digits + 1 nul + 1 sign */
#elif INT_MAX <= 2147483647L
#define __UIM_BUFLEN_INT		12 /* 10 digits + 1 nul + 1 sign */
#else
#error unknown number of digits for int!
#endif

typedef enum {
	__UIM_DECIMAL = 0,
	__UIM_GROUP = ',',			/* Base 10 locale-dependent grouping. */
	__UIM_LOWER = 'a' - 10,
	__UIM_UPPER = 'A' - 10,
} __UIM_CASE;

/* Convert the int val to a string in base abs(base).  val is treated as
 * an unsigned ??? int type if base > 0, and signed if base < 0.  This
 * is an internal function with _no_ error checking done unless assert()s
 * are enabled.
 *
 * Note: bufend is a pointer to the END of the buffer passed.
 * Call like this:
 *     char buf[SIZE], *p;
 *     p = _xltostr(buf + sizeof(buf) - 1, {unsigned int},  10, __UIM_DECIMAL)
 *     p = _xltostr(buf + sizeof(buf) - 1,          {int}, -10, __UIM_DECIMAL)
 *
 * WARNING: If base > 10, case _must_be_ either __UIM_LOWER or __UIM_UPPER
 *          for lower and upper case alphas respectively.
 * WARNING: If val is really a signed type, make sure base is negative!
 *          Otherwise, you could overflow your buffer.
 */
extern char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval,
						   int base, __UIM_CASE alphacase);

/* TODO -- make this either a (possibly inline) function? */
#ifndef __BCC__
#define _int10tostr(bufend, intval) \
	_uintmaxtostr((bufend), (intval), -10, __UIM_DECIMAL)
#else  /* bcc doesn't do prototypes, we need to explicitly cast */
#define _int10tostr(bufend, intval) \
	_uintmaxtostr((bufend), (uintmax_t)(intval), -10, __UIM_DECIMAL)
#endif

#define __BUFLEN_INT10TOSTR		__UIM_BUFLEN_INT

#endif /* _UINTMAXTOSTR_H */

Index: uClibc_locale.h
===================================================================
RCS file: /var/cvs/uClibc/libc/sysdeps/linux/common/bits/uClibc_locale.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- uClibc_locale.h	11 Nov 2003 23:44:13 -0000	1.12
+++ uClibc_locale.h	11 Feb 2004 23:48:48 -0000	1.13
@@ -316,6 +316,7 @@
 
 } __uclibc_locale_t;
 
+extern __uclibc_locale_t __global_locale_data;
 extern struct __uclibc_locale_struct * __global_locale;
 #endif
 

Index: uClibc_stdio.h
===================================================================
RCS file: /var/cvs/uClibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- uClibc_stdio.h	27 Dec 2003 23:30:48 -0000	1.15
+++ uClibc_stdio.h	11 Feb 2004 23:48:48 -0000	1.16
@@ -30,93 +30,50 @@
 #endif
 
 /**********************************************************************/
-#ifdef __UCLIBC__
-
-#ifdef __UCLIBC_HAS_THREADS__
-#define __STDIO_THREADSAFE
-#endif
-
-#ifdef __UCLIBC_HAS_LFS__
-#define __STDIO_LARGE_FILES
-#endif /* __UCLIBC_HAS_LFS__ */
-
-#ifdef __UCLIBC_HAS_WCHAR__
-#define __STDIO_WIDE
-#endif
 
 #define __STDIO_BUFFERS
 /* ANSI/ISO mandate at least 256. */
 #if defined(__UCLIBC_HAS_STDIO_BUFSIZ_NONE__)
 /* Fake this because some apps use stdio.h BUFSIZ. */
-#define _STDIO_BUFSIZ			256
+#define __STDIO_BUFSIZ			256
 #undef __STDIO_BUFFERS
 #elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_256__)
-#define _STDIO_BUFSIZ			256
+#define __STDIO_BUFSIZ			256
 #elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_512__)
-#define _STDIO_BUFSIZ			512
+#define __STDIO_BUFSIZ			512
 #elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_1024__)
-#define _STDIO_BUFSIZ		   1024
+#define __STDIO_BUFSIZ		   1024
 #elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_2048__)
-#define _STDIO_BUFSIZ		   2048
+#define __STDIO_BUFSIZ		   2048
 #elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_4096__)
-#define _STDIO_BUFSIZ		   4096
+#define __STDIO_BUFSIZ		   4096
 #elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_8192__)
-#define _STDIO_BUFSIZ		   8192
+#define __STDIO_BUFSIZ		   8192
 #else
 #error config seems to be out of sync regarding bufsiz options
 #endif
 
-#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
-#define __STDIO_GETC_MACRO
-#endif
-
-#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
-#define __STDIO_PUTC_MACRO
-#endif
-
-#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__
-#define __STDIO_AUTO_RW_TRANSITION
-#endif
-
-#ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__
-#define __STDIO_FOPEN_LARGEFILE_MODE
-#endif
-
-#ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__
-#define __STDIO_FOPEN_EXCLUSIVE_MODE
-#endif
-
-#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__
-#define __STDIO_PRINTF_M_SUPPORT
-#endif
-
-#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
-#define __STDIO_GLIBC_CUSTOM_STREAMS
-#endif
-
 #ifdef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__
-#define _STDIO_BUILTIN_BUF_SIZE		0
+#define __STDIO_BUILTIN_BUF_SIZE		0
 #else  /* __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ */
 #if defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__)
-#define _STDIO_BUILTIN_BUF_SIZE		0
+#define __STDIO_BUILTIN_BUF_SIZE		0
 #elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__)
-#define _STDIO_BUILTIN_BUF_SIZE		4
+#define __STDIO_BUILTIN_BUF_SIZE		4
 #elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__)
-#define _STDIO_BUILTIN_BUF_SIZE		8
+#define __STDIO_BUILTIN_BUF_SIZE		8
 #else
 #error config seems to be out of sync regarding builtin buffer size
 #endif
-#endif /* __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ */
-
-#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__
-#define __STDIO_GLIBC_CUSTOM_PRINTF
 #endif
 
+#if defined(__STDIO_BUFFERS) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) || defined(__UCLIBC_HAS_THREADS__)
+#define __STDIO_HAS_OPENLIST 1
+#else
+#undef __STDIO_HAS_OPENLIST
+#endif
 
-/* Currently unimplemented/untested */
-/* #define __STDIO_FLEXIBLE_SETVBUF */
-
-
+/**********************************************************************/
 /* Make sure defines related to large files are consistent. */
 #ifdef _LIBC
 
@@ -124,62 +81,44 @@
 #undef __USE_LARGEFILE
 #undef __USE_LARGEFILE64
 #undef __USE_FILE_OFFSET64
-/* if we're actually building uClibc with large file support, only define... */
+/* If we're actually building uClibc with large file support, only define... */
 #define __USE_LARGEFILE64	1
 #endif /* __UCLIBC_HAS_LFS__ */
 
 #else  /* not _LIBC */
 
 #ifndef __UCLIBC_HAS_LFS__
-#if defined(__LARGEFILE64_SOURCE) || defined(__USE_LARGEFILE64) \
-    || defined(__USE_FILE_OFFSET64)
+#if defined(__LARGEFILE64_SOURCE) || defined(__USE_LARGEFILE64) || defined(__USE_FILE_OFFSET64)
 #error Sorry... uClibc was built without large file support!
 #endif
 #endif /* __UCLIBC_HAS_LFS__ */
 
 #endif /* _LIBC */
-
-#endif /* __UCLIBC__ */
 /**********************************************************************/
-/* These are the stdio configuration options.  Keep them here until
-   uClibc's configuration process gets reworked. */
+#ifdef __UCLIBC_HAS_WCHAR__
 
-#ifdef __STDIO_WIDE
 #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
-
 
-/* For uClibc, these are currently handled above. */
-/* #define __STDIO_BUFFERS */
-/* #define __STDIO_GETC_MACRO */
-/* #define __STDIO_PUTC_MACRO */
-/* #define __STDIO_LARGE_FILES */
-/* #define __STDIO_THREADSAFE */
-/* ANSI/ISO mandate at least 256. */
-/* #define _STDIO_BUFSIZ			256 */
-/* #define __STDIO_AUTO_RW_TRANSITION */
-/* #define __STDIO_FOPEN_EXCLUSIVE_MODE */
-/* #define __STDIO_PRINTF_M_SPEC */
-/* #define __STDIO_GLIBC_CUSTOM_STREAMS */
-/* L mode extension for fopen. */
-/* #define __STDIO_FOPEN_LARGEFILE_MODE */
-/* size of builtin buf -- only tested with 0 */
-/* #define _STDIO_BUILTIN_BUF_SIZE		0 */
+#endif
+/**********************************************************************/
 /* Currently unimplemented/untested */
 /* #define __STDIO_FLEXIBLE_SETVBUF */
 
-/**********************************************************************/
-/* TODO -- posix or gnu -- belongs in limits.h and >= 9 for sus */
-/* NOTE: for us it is currently _always_ 9 */
-/*#define NL_ARGMAX			9*/
+#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
+#define __STDIO_GETC_MACRO
+#endif
+
+#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
+#define __STDIO_PUTC_MACRO
+#endif
 
-/**********************************************************************/
 
 /* These are consistency checks on the different options */
 
@@ -189,413 +128,408 @@
 #endif
 
 #ifdef __BCC__
-#undef __STDIO_LARGE_FILES
+#undef __UCLIBC_HAS_LFS__
 #endif
 
-#ifndef __STDIO_LARGE_FILES
-#undef __STDIO_FOPEN_LARGEFILE_MODE
+#ifndef __UCLIBC_HAS_LFS__
+#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__
 #endif
 
 /**********************************************************************/
-
-#ifdef __STDIO_THREADSAFE
+#ifdef __UCLIBC_HAS_THREADS__
 /* Need this for pthread_mutex_t. */
 #include <bits/pthreadtypes.h>
 
-#define __STDIO_THREADLOCK(STREAM) \
-	if ((STREAM)->user_locking == 0) { \
-		__pthread_mutex_lock(&(STREAM)->lock); \
-	}
+/* user_locking
+ * 0 : do auto locking/unlocking
+ * 1 : user does locking/unlocking
+ * 2 : initial state prior to thread initialization
+ *     with no auto locking/unlocking
+ *
+ * When threading is initialized, walk the stdio open stream list
+ * and do  "if (user_locking == 2) user_locking = 0;".
+ *
+ * This way, we avoid calling the weak lock/unlock functions.
+ */
 
-#define __STDIO_THREADUNLOCK(STREAM) \
-	if ((STREAM)->user_locking == 0) { \
-		__pthread_mutex_unlock(&(STREAM)->lock); \
+#define __STDIO_AUTO_THREADLOCK_VAR			int __infunc_user_locking
+
+#define __STDIO_AUTO_THREADLOCK(__stream)								\
+	if ((__infunc_user_locking = (__stream)->__user_locking) == 0) {	\
+		__pthread_mutex_lock(&(__stream)->__lock);						\
 	}
 
-#define __STDIO_THREADTRYLOCK(STREAM) \
-	if ((STREAM)->user_locking == 0) { \
-		__pthread_mutex_trylock(&(STREAM)->lock); \
+#define __STDIO_AUTO_THREADUNLOCK(__stream)				\
+	if (__infunc_user_locking == 0) {					\
+		__pthread_mutex_unlock(&(__stream)->__lock);		\
 	}
 
-#define __STDIO_SET_USER_LOCKING(STREAM)   	((STREAM)->user_locking = 1)
+#define __STDIO_SET_USER_LOCKING(__stream)	((__stream)->__user_locking = 1)
 
-#else  /* __STDIO_THREADSAFE */
+#define __STDIO_ALWAYS_THREADLOCK(__stream)	\
+		__pthread_mutex_lock(&(__stream)->__lock)
 
-#define __STDIO_THREADLOCK(STREAM)
-#define __STDIO_THREADUNLOCK(STREAM)
-#define __STDIO_THREADTRYLOCK(STREAM)
+#define __STDIO_ALWAYS_THREADTRYLOCK(__stream)	\
+		__pthread_mutex_trylock(&(__stream)->__lock)
 
-#define __STDIO_SET_USER_LOCKING(STREAM)
+#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \
+		__pthread_mutex_unlock(&(__stream)->__lock)
 
-#endif /* __STDIO_THREADSAFE */
+#else  /* __UCLIBC_HAS_THREADS__ */
 
-/* This file may eventually have two personalities:
-   1) core stuff (similar to glibc's libio.h)
-   2) extern inlines (for glibc's bits/stdio.h)
-   Right now, only (1) is implemented. */
+#define __STDIO_AUTO_THREADLOCK_VAR				((void)0)
 
-#define _STDIO_IOFBF 0	/* Fully buffered.  */
-#define _STDIO_IOLBF 1	/* Line buffered.  */
-#define _STDIO_IONBF 2	/* No buffering.  */
+#define __STDIO_AUTO_THREADLOCK(__stream)		((void)0)
+#define __STDIO_AUTO_THREADUNLOCK(__stream)		((void)0)
+
+#define __STDIO_SET_USER_LOCKING(__stream)		((void)0)
+
+#define __STDIO_ALWAYS_THREADLOCK(__stream)		((void)0)
+#define __STDIO_ALWAYS_THREADTRYLOCK(__stream)	(0)	/* Always succeed. */
+#define __STDIO_ALWAYS_THREADUNLOCK(__stream)	((void)0)
+
+#endif /* __UCLIBC_HAS_THREADS__ */
+/**********************************************************************/
+
+#define __STDIO_IOFBF 0		/* Fully buffered.  */
+#define __STDIO_IOLBF 1		/* Line buffered.  */
+#define __STDIO_IONBF 2		/* No buffering.  */
 
 typedef struct {
 	__off_t __pos;
 #ifdef __STDIO_MBSTATE
 	__mbstate_t __mbstate;
 #endif
-#ifdef __STDIO_WIDE
-	int mblen_pending;
+#ifdef __UCLIBC_HAS_WCHAR__
+	int __mblen_pending;
 #endif
-} __stdio_fpos_t;
+} __STDIO_fpos_t;
 
-#ifdef __STDIO_LARGE_FILES
+#ifdef __UCLIBC_HAS_LFS__
 typedef struct {
 	__off64_t __pos;
 #ifdef __STDIO_MBSTATE
 	__mbstate_t __mbstate;
 #endif
-#ifdef __STDIO_WIDE
-	int mblen_pending;
+#ifdef __UCLIBC_HAS_WCHAR__
+	int __mblen_pending;
 #endif
-} __stdio_fpos64_t;
+} __STDIO_fpos64_t;
 #endif
 
-
 /**********************************************************************/
-#ifdef __STDIO_LARGE_FILES
+#ifdef __UCLIBC_HAS_LFS__
 typedef __off64_t __offmax_t;	/* TODO -- rename this? */
 #else
 typedef __off_t __offmax_t;		/* TODO -- rename this? */
 #endif
 
 /**********************************************************************/
+#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
 
-#ifdef __STDIO_GLIBC_CUSTOM_STREAMS
-
-typedef __ssize_t __io_read_fn(void *cookie,
-							   char *buf, size_t bufsize);
-typedef __ssize_t __io_write_fn(void *cookie,
-								const char *buf, size_t bufsize);
+typedef __ssize_t __io_read_fn(void *__cookie, char *__buf, size_t __bufsize);
+typedef __ssize_t __io_write_fn(void *__cookie,
+								__const char *__buf, size_t __bufsize);
 /* NOTE: GLIBC difference!!! -- fopencookie seek function
  * For glibc, the type of pos is always (__off64_t *) but in our case
  * it is type (__off_t *) when the lib is built without large file support.
  */
-typedef int __io_seek_fn(void *cookie,
-						 __offmax_t *pos, int whence);
-typedef int __io_close_fn(void *cookie);
+typedef int __io_seek_fn(void *__cookie, __offmax_t *__pos, int __whence);
+typedef int __io_close_fn(void *__cookie);
 
 typedef struct {
-	__io_read_fn *read;
+	__io_read_fn  *read;
 	__io_write_fn *write;
-	__io_seek_fn *seek;
+	__io_seek_fn  *seek;
 	__io_close_fn *close;
 } _IO_cookie_io_functions_t;
 
 #if defined(_LIBC) || defined(_GNU_SOURCE)
+
 typedef __io_read_fn cookie_read_function_t;
 typedef __io_write_fn cookie_write_function_t;
 typedef __io_seek_fn cookie_seek_function_t;
 typedef __io_close_fn cookie_close_function_t;
 
 typedef _IO_cookie_io_functions_t cookie_io_functions_t;
-#endif /* _GNU_SOURCE */
 
-#endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
-
-/*
- * ungot scheme:
- * 0 0   none
- * 0 1   one user (unused ungot is 1) or one scanf (unused ungot is 0)
- * 1 0   must be scanf[0] and user[1]
- * 1 1   illegal -- could be used to signal safe for setbuf
- *         but if used, need to fix _stdio_adjpos at least!
- */
+#endif
 
-#ifdef __UCLIBC__
-#define __stdio_file_struct _UC_FILE
 #endif
+/**********************************************************************/
 
-struct __stdio_file_struct {
-	unsigned short modeflags;
+struct __STDIO_FILE_STRUCT {
+	unsigned short __modeflags;
 	/* There could be a hole here, but modeflags is used most.*/
-#ifdef __STDIO_WIDE
-	/* TODO - ungot_width could be combined with ungot.  But what about hole? */
-	unsigned char ungot_width[2]; /* 0 is current (building) char, 1 is scanf */
-	wchar_t ungot[2];
-#else  /* __STDIO_WIDE */
-	unsigned char ungot[2];
-#endif /* __STDIO_WIDE */
-	int filedes;
-#if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
-	struct __stdio_file_struct *nextopen;
-#endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
+#ifdef __UCLIBC_HAS_WCHAR__
+	unsigned char __ungot_width[2]; /* 0: current (building) char; 1: scanf */
+	/* Move the following futher down to avoid problems with getc/putc
+	 * macros breaking shared apps when wchar config support is changed. */
+	/* wchar_t ungot[2]; */
+#else  /* __UCLIBC_HAS_WCHAR__ */
+	unsigned char __ungot[2];
+#endif /* __UCLIBC_HAS_WCHAR__ */
+	int __filedes;
 #ifdef __STDIO_BUFFERS
-	unsigned char *bufstart;	/* pointer to buffer */
-	unsigned char *bufend;		/* pointer to 1 past end of buffer */
-	unsigned char *bufpos;
-	unsigned char *bufread;		/* pointer to 1 past last buffered read char. */
+	unsigned char *__bufstart;	/* pointer to buffer */
+	unsigned char *__bufend;	/* pointer to 1 past end of buffer */
+	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 */
+	unsigned char *__bufgetc_u;	/* 1 past last readable by getc_unlocked */
 #endif /* __STDIO_GETC_MACRO */
 #ifdef __STDIO_PUTC_MACRO
-	unsigned char *bufputc;		/* 1 past last writeable by putc */
+	unsigned char *__bufputc_u;	/* 1 past last writeable by putc_unlocked */
 #endif /* __STDIO_PUTC_MACRO */
+
 #endif /* __STDIO_BUFFERS */
-#ifdef __STDIO_GLIBC_CUSTOM_STREAMS
-	void *cookie;
-	_IO_cookie_io_functions_t gcs;
-#endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
+
+#ifdef __STDIO_HAS_OPENLIST
+	struct __STDIO_FILE_STRUCT *__nextopen;
+#endif
+#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
+	void *__cookie;
+	_IO_cookie_io_functions_t __gcs;
+#endif
+#ifdef __UCLIBC_HAS_WCHAR__
+	wchar_t __ungot[2];
+#endif
 #ifdef __STDIO_MBSTATE
-	__mbstate_t state;
+	__mbstate_t __state;
 #endif
-#ifdef __STDIO_THREADSAFE
-	int user_locking;
-	pthread_mutex_t lock;
+#ifdef __UCLIBC_HAS_XLOCALE__
+	void *__unused;				/* Placeholder for codeset binding. */
+#endif
+#ifdef __UCLIBC_HAS_THREADS__
+	int __user_locking;
+	pthread_mutex_t __lock;
 #endif
 /* Everything after this is unimplemented... and may be trashed. */
 #if __STDIO_BUILTIN_BUF_SIZE > 0
-	unsigned char builtinbuf[__STDIO_BUILTIN_BUF_SIZE];
+	unsigned char __builtinbuf[__STDIO_BUILTIN_BUF_SIZE];
 #endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */
 };
 
 
 /***********************************************************************/
+/* Having ungotten characters implies the stream is reading.
+ * The scheme used here treats the least significant 2 bits of
+ * the stream's modeflags member as follows:
+ *   0 0   Not currently reading.
+ *   0 1   Reading, but no ungetc() or scanf() push back chars.
+ *   1 0   Reading with one ungetc() char (ungot[1] is 1)
+ *         or one scanf() pushed back char (ungot[1] is 0).
+ *   1 1   Reading with both an ungetc() char and a scanf()
+ *         pushed back char.  Note that this must be the result
+ *         of a scanf() push back (in ungot[0]) _followed_ by
+ *         an ungetc() call (in ungot[1]).
+ *
+ * Notes:
+ *   scanf() can NOT use ungetc() to push back characters.
+ *     (See section 7.19.6.2 of the C9X rationale -- WG14/N897.)
+ */
 
-#define __MASK_UNGOT    	(0x0002|0x0001)
-#define __MASK_UNGOT1    	0x0001
-#define __MASK_UNGOT2    	0x0002
-#define __FLAG_EOF			0x0004	/* EOF reached? */
-#define __FLAG_ERROR		0x0008	/* stream in error state? */
-#define __FLAG_WRITEONLY  	0x0010	/* unreadable */
-#define __FLAG_READONLY  	0x0020	/* unwriteable */
-#define __FLAG_FREEFILE		0x0040	/* free FILE struct after use */
-#define __FLAG_NARROW       0x0080
+#define __MASK_READING		0x0003U /* (0x0001 | 0x0002) */
+#define __FLAG_READING		0x0001U
+#define __FLAG_UNGOT    	0x0002U
+#define __FLAG_EOF			0x0004U
+#define __FLAG_ERROR		0x0008U
+#define __FLAG_WRITEONLY  	0x0010U
+#define __FLAG_READONLY  	0x0020U /* (__FLAG_WRITEONLY << 1) */
+#define __FLAG_WRITING		0x0040U
+#define __FLAG_NARROW       0x0080U
 
-#define __FLAG_FBF          0		/* convenience value */
-#define __FLAG_LBF          0x0100
-#define __FLAG_NBF          0x0200
-#define __MASK_BUFMODE      0x0300
+#define __FLAG_FBF          0x0000U /* must be 0 */
+#define __FLAG_LBF          0x0100U
+#define __FLAG_NBF          0x0200U /* (__FLAG_LBF << 1) */
+#define __MASK_BUFMODE      0x0300U /* (__FLAG_LBF|__FLAG_NBF) */
+#define __FLAG_APPEND       0x0400U /* fixed! == O_APPEND for linux */
+#define __FLAG_WIDE			0x0800U
+/* available slot           0x1000U */
+#define __FLAG_FREEFILE		0x2000U
+#define __FLAG_FREEBUF		0x4000U
+#define __FLAG_LARGEFILE    0x8000U /* fixed! == 0_LARGEFILE for linux */
 
-#define __FLAG_APPEND       0x0400
-#define __FLAG_WIDE			0x0800
+/* Note: In no-buffer mode, it would be possible to pack the necessary
+ * flags into one byte.  Since we wouldn't be buffering and there would
+ * be no support for wchar, the only flags we would need would be:
+ *   2 bits : ungot count
+ *   2 bits : eof + error
+ *   2 bits : readonly + writeonly
+ *   1 bit  : freefile
+ *   1 bit  : appending
+ * So, for a very small system (< 128 files) we might have a
+ * 4-byte FILE struct of:
+ *   unsigned char flags;
+ *   signed char filedes;
+ *   unsigned char ungot[2];
+ */
+/**********************************************************************
+ * PROTOTYPES OF INTERNAL FUNCTIONS
+ **********************************************************************/
+#ifdef _LIBC
 
-#define __FLAG_READING		0x1000
-#define __FLAG_WRITING		0x2000
+extern void _stdio_init(void);
+extern void _stdio_term(void);
 
-#define __FLAG_FREEBUF		0x4000	/* free buffer after use */
-#define __FLAG_LARGEFILE    0x8000
+#ifdef __STDIO_HAS_OPENLIST
 
-/**********************************************************************/
+extern struct __STDIO_FILE_STRUCT *_stdio_openlist;
 
-#ifdef __STDIO_GLIBC_CUSTOM_STREAMS
-extern __ssize_t _cs_read(void *cookie, char *buf, size_t bufsize);
-extern __ssize_t _cs_write(void *cookie, const char *buf, size_t bufsize);
-extern int _cs_seek(void *cookie, __offmax_t *pos, int whence);
-extern int _cs_close(void *cookie);
-#endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
+#ifdef __UCLIBC_HAS_THREADS__
+extern pthread_mutex_t _stdio_openlist_lock;
+extern int _stdio_openlist_delflag;
+extern int _stdio_user_locking;
+extern void __stdio_init_mutex(pthread_mutex_t *m);
+#endif
 
+#endif
+
+#endif
 /**********************************************************************/
 
-#ifdef __STDIO_MBSTATE
-#define __COPY_MBSTATE(dest,src)  ((dest)->mask = (src)->mask, (dest)->wc = (src)->wc)
-#define __INIT_MBSTATE(dest) ((dest)->mask = 0)
+#define __CLEARERR_UNLOCKED(__stream) \
+	((void)((__stream)->__modeflags &= ~(__FLAG_EOF|__FLAG_ERROR)))
+#define __FEOF_UNLOCKED(__stream)	((__stream)->__modeflags & __FLAG_EOF)
+#define __FERROR_UNLOCKED(__stream)	((__stream)->__modeflags & __FLAG_ERROR)
+
+#ifdef __UCLIBC_HAS_THREADS__
+# define __CLEARERR(__stream)	(clearerr)(__stream)
+# define __FERROR(__stream)		(ferror)(__stream)
+# define __FEOF(__stream)		(feof)(__stream)
 #else
-#define __COPY_MBSTATE(dest,src)
-#define __INIT_MBSTATE(dest)
+# define __CLEARERR(__stream)	__CLEARERR_UNLOCKED(__stream)
+# define __FERROR(__stream)		__FERROR_UNLOCKED(__stream)
+# define __FEOF(__stream)		__FEOF_UNLOCKED(__stream)
 #endif
 
-/**********************************************************************/
-
-/* TODO -- thread safety issues */
-#define __CLEARERR(stream) \
-	((stream)->modeflags &= ~(__FLAG_EOF|__FLAG_ERROR), (void)0)
-#define __FEOF(stream)		((stream)->modeflags & __FLAG_EOF)
-#define __FERROR(stream)	((stream)->modeflags & __FLAG_ERROR)
+extern int __fgetc_unlocked(FILE *__stream);
+extern int __fputc_unlocked(int __c, FILE *__stream);
 
-#define __FEOF_OR_FERROR(stream) \
-	((stream)->modeflags & (__FLAG_EOF|__FLAG_ERROR))
+/* First define the default definitions.  They overriden below as necessary. */
+#define __FGETC_UNLOCKED(__stream)		(__fgetc_unlocked)((__stream))
+#define __FGETC(__stream)				(fgetc)((__stream))
+#define __GETC_UNLOCKED(__stream)		(__fgetc_unlocked)((__stream))
+#define __GETC(__stream)				(fgetc)((__stream))
 
+#define __FPUTC_UNLOCKED(__c, __stream)	(__fputc_unlocked)((__c),(__stream))
+#define __FPUTC(__c, __stream)			(fputc)((__c),(__stream))
+#define __PUTC_UNLOCKED(__c, __stream)	(__fputc_unlocked)((__c),(__stream))
+#define __PUTC(__c, __stream)			(fputc)((__c),(__stream))
 
-/* TODO: check this
- * If we want to implement the getc and putc macros, we need to take
- * into account wide streams.  So... would need two additional variables
- * if we have wide streams (bufread and bufwrite), and one otherwise
- * (bufwrite).  getc would be effective for FBF streams.  It isn't for
- * LBF streams because other LBF streams need to be flushed.  putc
- * thouch is only effective for FBF streams.  Of course, to support
- * threads, we have to use functions.
- */
 
 #ifdef __STDIO_GETC_MACRO
-#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)->bufpos < (stream)->bufputc) \
-							? (*(stream)->bufpos++) = (c) \
-							: fputc_unlocked((c),(stream)) )
-#else  /* __STDIO_PUTC_MACRO */
-#define __PUTC(c, stream)	fputc_unlocked(c, stream)
-#endif /* __STDIO_PUTC_MACRO */
 
+extern FILE *__stdin;			/* For getchar() macro. */
 
-#if 0
-/* TODO: disabled for now */
-/* Masking macros for the above _are_ allowed by the standard. */
-#define clearerr(stream)	__CLEARERR(stream)
-#define feof(stream)		__FEOF(stream)
-#define ferror(stream)		__FERROR(stream)
-#endif
+# define __GETC_UNLOCKED_MACRO(__stream)					\
+		( ((__stream)->__bufpos < (__stream)->__bufgetc_u)	\
+		  ? (*(__stream)->__bufpos++)						\
+		  : __fgetc_unlocked(__stream) )
 
-#if 0
-/* TODO -- what about custom streams!!! */
-/* Only use the macro below if you know fp is a valid FILE for a valid fd. */
-#define __fileno(fp)	((fp)->filedes)
-#endif
+# if 0
+	/* Classic macro approach.  getc{_unlocked} can have side effects. */
+#  undef  __GETC_UNLOCKED
+#  define __GETC_UNLOCKED(__stream)		__GETC_UNLOCKED_MACRO((__stream))
+#  ifndef __UCLIBC_HAS_THREADS__
+#   undef  __GETC
+#   define __GETC(__stream)				__GETC_UNLOCKED_MACRO((__stream))
+#  endif
 
-/**********************************************************************
- * PROTOTYPES OF INTERNAL FUNCTIONS
- **********************************************************************/
+# else
+	/* Using gcc extension for safety and additional inlining. */
+#  undef  __FGETC_UNLOCKED
+#  define __FGETC_UNLOCKED(__stream)		\
+		(__extension__ ({					\
+			FILE *__S = (__stream);			\
+			__GETC_UNLOCKED_MACRO(__S);		\
+		}) )
 
-extern FILE *_stdio_openlist;
+#  undef  __GETC_UNLOCKED
+#  define __GETC_UNLOCKED(__stream)		__FGETC_UNLOCKED((__stream))
 
-#ifdef __STDIO_THREADSAFE
-extern pthread_mutex_t _stdio_openlist_lock;
-extern void __stdio_init_mutex(pthread_mutex_t *m);
-#endif
+#  ifdef __UCLIBC_HAS_THREADS__
+#   undef  __FGETC
+#   define __FGETC(__stream)				\
+		(__extension__ ({					\
+			FILE *__S = (__stream);			\
+			((__S->__user_locking )			\
+			 ? __GETC_UNLOCKED_MACRO(__S)	\
+			 : (fgetc)(__S));				\
+		}) )
 
-extern int _stdio_adjpos(FILE * __restrict stream, __offmax_t * pos);
-extern int _stdio_lseek(FILE *stream, __offmax_t *pos, int whence);
-/* TODO: beware of signals with _stdio_fwrite!!!! */
-extern size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
-							  FILE *stream);
-extern size_t _stdio_fread(unsigned char *buffer, size_t bytes,
-							 FILE *stream);
+#   undef  __GETC
+#   define __GETC(__stream)				__FGETC((__stream))
 
-extern FILE *_stdio_fopen(const char * __restrict filename,
-							const char * __restrict mode,
-							FILE * __restrict stream, int filedes);
+#  else 
 
-extern FILE *_stdio_fsfopen(const char * __restrict filename,
-							const char * __restrict mode,
-							register FILE * __restrict stream);
+#   undef  __FGETC
+#   define __FGETC(__stream)			__FGETC_UNLOCKED((__stream))
+#   undef  __GETC
+#   define __GETC(__stream)				__FGETC_UNLOCKED((__stream))
 
-extern void _stdio_init(void);
-extern void _stdio_term(void);
+#  endif
+# endif
 
-#ifndef NDEBUG
-extern void __stdio_validate_FILE(FILE *stream);
 #else
-#define __stdio_validate_FILE(stream)		((void)0)
-#endif
-
-#ifdef __STDIO_WIDE
-extern size_t _wstdio_fwrite(const wchar_t *__restrict ws, size_t n,
-							 register FILE *__restrict stream);
-#endif
 
-/**********************************************************************
- * UTILITY functions
- **********************************************************************/
-#ifdef _STDIO_UTILITY
+#endif /* __STDIO_GETC_MACRO */
 
-#include <features.h>
-#include <limits.h>
-#include <stdint.h>
 
-#if INTMAX_MAX <= 2147483647L
-#define __UIM_BUFLEN			12 /* 10 digits + 1 nul + 1 sign */
-#elif INTMAX_MAX <= 9223372036854775807LL
-#define __UIM_BUFLEN			22 /* 20 digits + 1 nul + 1 sign */
-#else
-#error unknown number of digits for intmax_t!
-#endif
+#ifdef __STDIO_PUTC_MACRO
 
-#ifdef LLONG_MAX				/* --------------- */
-#if LLONG_MAX <= 2147483647L
-#define __UIM_BUFLEN_LLONG		12 /* 10 digits + 1 nul + 1 sign */
-#elif LLONG_MAX <= 9223372036854775807LL
-#define __UIM_BUFLEN_LLONG		22 /* 20 digits + 1 nul + 1 sign */
-#else
-#error unknown number of digits for long long!
-#endif
-#endif /* ULLONG_MAX ----------------------------- */
+extern FILE *__stdout;			/* For putchar() macro. */
 
-#if LONG_MAX <= 2147483647L
-#define __UIM_BUFLEN_LONG		12 /* 10 digits + 1 nul + 1 sign */
-#elif LONG_MAX <= 9223372036854775807LL
-#define __UIM_BUFLEN_LONG		22 /* 20 digits + 1 nul + 1 sign */
-#else
-#error unknown number of digits for long!
-#endif
+# define __PUTC_UNLOCKED_MACRO(__c, __stream)						\
+		( ((__stream)->__bufpos < (__stream)->__bufputc_u)	\
+		  ? (*(__stream)->__bufpos++) = (__c)				\
+		  : __fputc_unlocked((__c),(__stream)) )
 
-#if INT_MAX <= 32767
-#define __UIM_BUFLEN_INT		7 /* 10 digits + 1 nul + 1 sign */
-#elif INT_MAX <= 2147483647L
-#define __UIM_BUFLEN_INT		12 /* 10 digits + 1 nul + 1 sign */
-#else
-#error unknown number of digits for int!
-#endif
+# if 0
+	/* Classic macro approach.  putc{_unlocked} can have side effects.*/
+#  undef  __PUTC_UNLOCKED
+#  define __PUTC_UNLOCKED(__c, __stream) \
+									__PUTC_UNLOCKED_MACRO((__c), (__stream))
+#  ifndef __UCLIBC_HAS_THREADS__
+#   undef  __PUTC
+#   define __PUTC(__c, __stream)	__PUTC_UNLOCKED_MACRO((__c), (__stream))
+#  endif
 
-typedef enum {
-	__UIM_DECIMAL = 0,
-	__UIM_GROUP = ',',			/* Base 10 locale-dependent grouping. */
-	__UIM_LOWER = 'a' - 10,
-	__UIM_UPPER = 'A' - 10,
-} __UIM_CASE;
+# else
+	/* Using gcc extension for safety and additional inlining. */
 
-/* Write a NULL-terminated list of "char *" args to file descriptor fd.
- * For an example of usage, see __assert.c.
- */
-extern void _stdio_fdout(int fd, ...);
+#  undef  __FPUTC_UNLOCKED
+#  define __FPUTC_UNLOCKED(__c, __stream)		\
+		(__extension__ ({						\
+			FILE *__S = (__stream);				\
+			__PUTC_UNLOCKED_MACRO((__c),__S);	\
+		}) )
 
-/* Convert the int val to a string in base abs(base).  val is treated as
- * an unsigned ??? int type if base > 0, and signed if base < 0.  This
- * is an internal function with _no_ error checking done unless assert()s
- * are enabled.
- *
- * Note: bufend is a pointer to the END of the buffer passed.
- * Call like this:
- *     char buf[SIZE], *p;
- *     p = _xltostr(buf + sizeof(buf) - 1, {unsigned int},  10, __UIM_DECIMAL)
- *     p = _xltostr(buf + sizeof(buf) - 1,          {int}, -10, __UIM_DECIMAL)
- *
- * WARNING: If base > 10, case _must_be_ either __UIM_LOWER or __UIM_UPPER
- *          for lower and upper case alphas respectively.
- * WARNING: If val is really a signed type, make sure base is negative!
- *          Otherwise, you could overflow your buffer.
- */
-extern char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval,
-						   int base, __UIM_CASE alphacase);
+#  undef  __PUTC_UNLOCKED
+#  define __PUTC_UNLOCKED(__c, __stream)	__FPUTC_UNLOCKED((__c), (__stream))
 
-/* TODO -- make this either a (possibly inline) function? */
-#ifndef __BCC__
-#define _int10tostr(bufend, intval) \
-	_uintmaxtostr((bufend), (intval), -10, __UIM_DECIMAL)
-#else  /* bcc doesn't do prototypes, we need to explicitly cast */
-#define _int10tostr(bufend, intval) \
-	_uintmaxtostr((bufend), (uintmax_t)(intval), -10, __UIM_DECIMAL)
-#endif
+#  ifdef __UCLIBC_HAS_THREADS__
+#   undef  __FPUTC
+#   define __FPUTC(__c, __stream)				\
+		(__extension__ ({						\
+			FILE *__S = (__stream);				\
+			((__S->__user_locking)				\
+			 ? __PUTC_UNLOCKED_MACRO((__c),__S)	\
+			 : (fputc)((__c),__S));				\
+		}) )
 
-#define __BUFLEN_INT10TOSTR		__UIM_BUFLEN_INT
+#   undef  __PUTC
+#   define __PUTC(__c, __stream)		__FPUTC((__c), (__stream))
 
-#endif /* _STDIO_UTILITY */
-/**********************************************************************/
-/* uClibc translations */
-/**********************************************************************/
+#  else
 
-/* 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
+#   undef  __FUTC
+#   define __FPUTC(__c, __stream) 		__FPUTC_UNLOCKED((__c),(__stream))
+#   undef  __PUTC
+#   define __PUTC(__c, __stream) 		__FPUTC_UNLOCKED((__c),(__stream))
 
-#define _UC_IOFBF		_STDIO_IOFBF /* Fully buffered.  */
-#define _UC_IOLBF 		_STDIO_IOLBF /* Line buffered.  */
-#define _UC_IONBF 		_STDIO_IONBF /* No buffering.  */
+#  endif
+# endif
 
-#define _UC_BUFSIZ		_STDIO_BUFSIZ
+#endif /* __STDIO_PUTC_MACRO */




More information about the uClibc-cvs mailing list