Browse Source

Swap in the new stdio code.

Manuel Novoa III 22 years ago
parent
commit
03e039820d

+ 247 - 0
include/printf.h

@@ -0,0 +1,247 @@
+/* Copyright (C) 1991-1993,1995-1999,2000,2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* March 11, 2001         Manuel Novoa III
+ *
+ * Modified as appropriate for my new stdio lib.
+ */
+
+#ifndef	_PRINTF_H
+
+#define	_PRINTF_H	1
+#include <features.h>
+
+__BEGIN_DECLS
+
+#define	__need_FILE
+#include <stdio.h>
+#define	__need_size_t
+#define __need_wchar_t
+#include <stddef.h>
+
+/* WARNING -- This is definitely nonportable... but it seems to work
+ * with gcc, which is currently the only "supported" compiler.
+ * The library code uses bitmasks for space-efficiency (you can't
+ * set/test multiple bitfields in one operation).  Unfortunatly, we
+ * need to support bitfields since that's what glibc uses.  So, we take
+ * advantage of how gcc lays out bitfields to create an appropriate
+ * mapping.  By defining __PRINTF_INFO_NO_BITFIELD we access the
+ * bitfields using bitmasks in a single flag variable.
+ *
+ * WARNING -- This may very well fail if built with -fpack-struct!!!
+ *
+ * TODO -- Add a validation test.
+ * TODO -- Add an option to build in a shim translation function if
+ *         the bitfield<->bitmask mapping fails.
+ */
+/*  #define __PRINTF_INFO_NO_BITFIELD */
+#include <endian.h>
+
+struct printf_info
+{
+  int prec;			/* Precision.  */
+  int width;			/* Width.  */
+#ifdef __STDIO_WIDE				/* TODO: temporary fix for uClibc */
+  wchar_t spec;			/* Format letter.  */
+#else
+  int spec;
+#endif
+#ifndef __PRINTF_INFO_NO_BITFIELD
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  unsigned int space:1;		/* Space flag.  */
+  unsigned int showsign:1;	/* + flag.  */
+  unsigned int extra:1;		/* For special use.  */
+  unsigned int left:1;		/* - flag.  */
+  unsigned int alt:1;		/* # flag.  */
+  unsigned int group:1;		/* ' flag.  */
+  unsigned int i18n:1;		/* I flag.  */
+  unsigned int wide:1;		/* Nonzero for wide character streams.  */
+  unsigned int is_char:1;	/* hh flag.  */
+  unsigned int is_short:1;	/* h flag.  */
+  unsigned int is_long:1;	/* l flag.  */
+  unsigned int is_long_double:1;/* L flag.  */
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+  unsigned int __padding:20;/* non-gnu -- total of 32 bits on 32bit arch */
+  unsigned int is_long_double:1;/* L flag.  */
+  unsigned int is_long:1;	/* l flag.  */
+  unsigned int is_short:1;	/* h flag.  */
+  unsigned int is_char:1;	/* hh flag.  */
+  unsigned int wide:1;		/* Nonzero for wide character streams.  */
+  unsigned int i18n:1;		/* I flag.  */
+  unsigned int group:1;		/* ' flag.  */
+  unsigned int alt:1;		/* # flag.  */
+  unsigned int left:1;		/* - flag.  */
+  unsigned int extra:1;		/* For special use.  */
+  unsigned int showsign:1;	/* + flag.  */
+  unsigned int space:1;		/* Space flag.  */
+
+#else
+#error unsupported byte order!
+#endif
+
+#define PRINT_INFO_FLAG_VAL(INFO_PTR,BITFIELD) (INFO_PTR)->BITFIELD
+#define PRINT_INFO_SET_FLAG(INFO_PTR,BITFIELD) (INFO_PTR)->BITFIELD = 1
+#define PRINT_INFO_CLR_FLAG(INFO_PTR,BITFIELD) (INFO_PTR)->BITFIELD = 0
+#define PRINT_INFO_SET_extra(INFO_PTR,VAL) (INFO_PTR)->extra = (VAL)
+
+#else  /* __PRINTF_INFO_NO_BITFIELD */
+
+  unsigned int _flags;		/* non-gnu */
+#define __PRINT_INFO_FLAG_space					(1<<0)
+#define __PRINT_INFO_FLAG_showsign				(1<<1)
+#define __PRINT_INFO_FLAG_extra					(1<<2)
+#define __PRINT_INFO_FLAG_left					(1<<3)
+#define __PRINT_INFO_FLAG_alt					(1<<4)
+#define __PRINT_INFO_FLAG_group					(1<<5)
+#define __PRINT_INFO_FLAG_i18n					(1<<6)
+#define __PRINT_INFO_FLAG_wide					(1<<7)
+
+#define __PRINT_INFO_FLAG_is_char				(1<<8)
+#define __PRINT_INFO_FLAG_is_short				(1<<9)
+#define __PRINT_INFO_FLAG_is_long				(1<<10)
+#define __PRINT_INFO_FLAG_is_long_double		(1<<11)
+
+#if defined(__STDC__) && __STDC__
+#define PRINT_INFO_FLAG_VAL(INFO_PTR,BITFIELD) \
+	((INFO_PTR)->_flags & __PRINT_INFO_FLAG_##BITFIELD)
+#define PRINT_INFO_SET_FLAG(INFO_PTR,BITFIELD) \
+	((INFO_PTR)->_flags |= __PRINT_INFO_FLAG_##BITFIELD)
+#define PRINT_INFO_CLR_FLAG(INFO_PTR,BITFIELD) \
+	((INFO_PTR)->_flags &= ~__PRINT_INFO_FLAG_##BITFIELD)
+#else
+#define PRINT_INFO_FLAG_VAL(INFO_PTR,BITFIELD) \
+	((INFO_PTR)->_flags & __PRINT_INFO_FLAG_/**/BITFIELD)
+#define PRINT_INFO_SET_FLAG(INFO_PTR,BITFIELD) \
+	((INFO_PTR)->_flags |= __PRINT_INFO_FLAG_/**/BITFIELD)
+#define PRINT_INFO_CLR_FLAG(INFO_PTR,BITFIELD) \
+	((INFO_PTR)->_flags &= ~__PRINT_INFO_FLAG_/**/BITFIELD)
+#endif
+#define PRINT_INFO_SET_extra(INFO_PTR,VAL) \
+	((INFO_PTR)->_flags |= (((INFO_PTR)->_flags & ~1) | ((VAL) & 1)))
+#endif /* __PRINTF_INFO_NO_BITFIELD */
+#ifdef __STDIO_WIDE				/* TODO: temporary fix for uClibc */
+  wchar_t pad;			/* Padding character.  */
+#else
+  int pad;
+#endif
+};
+
+
+/* Type of a printf specifier-handler function.
+   STREAM is the FILE on which to write output.
+   INFO gives information about the format specification.
+   ARGS is a vector of pointers to the argument data;
+   the number of pointers will be the number returned
+   by the associated arginfo function for the same INFO.
+
+   The function should return the number of characters written,
+   or -1 for errors.  */
+
+typedef int printf_function (FILE *__stream,
+			     __const struct printf_info *__info,
+			     __const void *__const *__args);
+
+/* Type of a printf specifier-arginfo function.
+   INFO gives information about the format specification.
+   N, ARGTYPES, and return value are as for parse_printf_format.  */
+
+typedef int printf_arginfo_function (__const struct printf_info *__info,
+				     size_t __n, int *__argtypes);
+
+
+/* Register FUNC to be called to format SPEC specifiers; ARGINFO must be
+   specified to determine how many arguments a SPEC conversion requires and
+   what their types are.  */
+
+extern int register_printf_function (int __spec, printf_function __func,
+				     printf_arginfo_function __arginfo);
+
+
+/* Parse FMT, and fill in N elements of ARGTYPES with the
+   types needed for the conversions FMT specifies.  Returns
+   the number of arguments required by FMT.
+
+   The ARGINFO function registered with a user-defined format is passed a
+   `struct printf_info' describing the format spec being parsed.  A width
+   or precision of INT_MIN means a `*' was used to indicate that the
+   width/precision will come from an arg.  The function should fill in the
+   array it is passed with the types of the arguments it wants, and return
+   the number of arguments it wants.  */
+
+extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n,
+				   int *__restrict __argtypes) __THROW;
+
+
+/* Codes returned by `parse_printf_format' for basic types.
+
+   These values cover all the standard format specifications.
+   Users can add new values after PA_LAST for their own types.  */
+
+/* WARNING -- The above is not entirely true, even for glibc.
+ * As far as the library code is concerned, such args are treated
+ * as 'your type' pointers if qualified by PA_FLAG_PTR.  If they
+ * aren't qualified as pointers, I _think_ glibc just ignores them
+ * and carries on.  I think it should be treated as an error. */
+
+enum
+{				/* C type: */
+  PA_INT,			/* int */
+  PA_CHAR,			/* int, cast to char */
+  PA_WCHAR,			/* wide char */
+  PA_STRING,			/* const char *, a '\0'-terminated string */
+  PA_WSTRING,			/* const wchar_t *, wide character string */
+  PA_POINTER,			/* void * */
+  PA_FLOAT,			/* float */
+  PA_DOUBLE,			/* double */
+  __PA_NOARG,			/* non-glibc -- signals non-arg width or prec */
+  PA_LAST
+};
+
+/* Flag bits that can be set in a type returned by `parse_printf_format'.  */
+/* WARNING -- These differ in value from what glibc uses. */
+#define PA_FLAG_MASK		(0xff00)
+#define __PA_FLAG_CHAR		(0x0100) /* non-gnu -- to deal with hh */
+#define PA_FLAG_SHORT		(0x0200)
+#define PA_FLAG_LONG		(0x0400)
+#define PA_FLAG_LONG_LONG	(0x0800)
+#define PA_FLAG_LONG_DOUBLE	PA_FLAG_LONG_LONG
+#define PA_FLAG_PTR		(0x1000) /* TODO -- make dynamic??? */
+
+#define __PA_INTMASK		(0x0f00) /* non-gnu -- all int flags */
+
+/* Function which can be registered as `printf'-handlers.  */
+
+/* Print floating point value using using abbreviations for the orders
+   of magnitude used for numbers ('k' for kilo, 'm' for mega etc).  If
+   the format specifier is a uppercase character powers of 1000 are
+   used.  Otherwise powers of 1024.  */
+extern int printf_size (FILE *__restrict __fp,
+			__const struct printf_info *__info,
+			__const void *__const *__restrict __args) __THROW;
+
+/* This is the appropriate argument information function for `printf_size'.  */
+extern int printf_size_info (__const struct printf_info *__restrict
+			     __info, size_t __n, int *__restrict __argtypes)
+     __THROW;
+
+
+__END_DECLS
+
+#endif /* printf.h  */

+ 30 - 62
include/stdio.h

@@ -1,4 +1,4 @@
-/* Define ISO C stdio on top of C++ iostreams.
+/*
    Copyright (C) 1991, 1994-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Copyright (C) 1991, 1994-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    This file is part of the GNU C Library.
 
 
@@ -37,32 +37,11 @@ __BEGIN_DECLS
 # define __need_FILE
 # define __need_FILE
 # define __need___FILE
 # define __need___FILE
 #endif /* Don't need FILE.  */
 #endif /* Don't need FILE.  */
-#include <sys/types.h>
 
 
 
 
 #if !defined __FILE_defined && defined __need_FILE
 #if !defined __FILE_defined && defined __need_FILE
 
 
 /* The opaque type of streams.  This is the definition used elsewhere.  */
 /* The opaque type of streams.  This is the definition used elsewhere.  */
-
-/* when you add or change fields here, be sure to change the initialization
- * in stdio_init and fopen */
-
-struct _UC_FILE {
-  unsigned char *bufpos;   /* the next byte to write to or read from */
-  unsigned char *bufread;  /* the end of data returned by last read() */
-  unsigned char *bufwrite; /* 1 + highest address writable by macro */
-  unsigned char *bufstart; /* the start of the buffer */
-  unsigned char *bufend;   /* the end of the buffer; ie the byte after the last
-                              malloc()ed byte */
-  struct _UC_FILE * next;
-
-  int fd; /* the file descriptor associated with the stream */
-
-  unsigned char mode;
-  unsigned char ungot;
-  unsigned char unbuf[2];	   /* The buffer for 'unbuffered' streams */
-};
-
 typedef struct _UC_FILE FILE;
 typedef struct _UC_FILE FILE;
 
 
 # define __FILE_defined	1
 # define __FILE_defined	1
@@ -83,39 +62,33 @@ typedef struct _UC_FILE __FILE;
 #ifdef	_STDIO_H
 #ifdef	_STDIO_H
 #undef _STDIO_USES_IOSTREAM
 #undef _STDIO_USES_IOSTREAM
 
 
+#include <sys/types.h>
+
+#include <bits/uClibc_stdio.h>
+
 /* This define avoids name pollution if we're using GNU stdarg.h */
 /* This define avoids name pollution if we're using GNU stdarg.h */
 # define __need___va_list
 # define __need___va_list
 #include <stdarg.h>
 #include <stdarg.h>
 
 
-
 /* The type of the second argument to `fgetpos' and `fsetpos'.  */
 /* The type of the second argument to `fgetpos' and `fsetpos'.  */
 #ifndef __USE_FILE_OFFSET64
 #ifndef __USE_FILE_OFFSET64
-typedef __off_t fpos_t;
+typedef _UC_fpos_t fpos_t;
 #else
 #else
-typedef __off64_t fpos_t;
+typedef _UC_fpos64_t fpos_t;
 #endif
 #endif
 #ifdef __USE_LARGEFILE64
 #ifdef __USE_LARGEFILE64
-typedef __off64_t fpos64_t;
+typedef _UC_fpos64_t fpos64_t;
 #endif
 #endif
 
 
 /* The possibilities for the third argument to `setvbuf'.  */
 /* The possibilities for the third argument to `setvbuf'.  */
-#define _IOFBF 0 		/* Fully buffered.  */
-#define _IOLBF 1		/* Line buffered.  */
-#define _IONBF 2		/* No buffering.  */
-
-/* Possible states for a file stream -- internal use only */
-#define __MODE_BUF		0x03	/* Modal buffering dependent on isatty */
-#define __MODE_FREEBUF	0x04	/* Buffer allocated by stdio code, can free */
-#define __MODE_FREEFIL	0x08	/* FILE allocated by stdio code, can free */
-#define __MODE_UNGOT	0x10	/* Buffer has been polluted by ungetc */
-#define __MODE_TIED 	0x20	/* FILE is tied with stdin/stdout */
-#define __MODE_EOF		0x40	/* EOF status */
-#define __MODE_ERR		0x80	/* Error status */
+#define _IOFBF _UC_IOFBF 		/* Fully buffered.  */
+#define _IOLBF _UC_IOLBF		/* Line buffered.  */
+#define _IONBF _UC_IONBF		/* No buffering.  */
 
 
 
 
 /* Default buffer size.  */
 /* Default buffer size.  */
 #ifndef BUFSIZ
 #ifndef BUFSIZ
-# define BUFSIZ	    (512)
+# define BUFSIZ _UC_BUFSIZ
 #endif
 #endif
 
 
 
 
@@ -155,10 +128,12 @@ typedef __off64_t fpos64_t;
 extern FILE *stdin;		/* Standard input stream.  */
 extern FILE *stdin;		/* Standard input stream.  */
 extern FILE *stdout;		/* Standard output stream.  */
 extern FILE *stdout;		/* Standard output stream.  */
 extern FILE *stderr;		/* Standard error output stream.  */
 extern FILE *stderr;		/* Standard error output stream.  */
+#ifdef __STDC__
 /* C89/C99 say they're macros.  Make them happy.  */
 /* C89/C99 say they're macros.  Make them happy.  */
 #define stdin stdin
 #define stdin stdin
 #define stdout stdout
 #define stdout stdout
 #define stderr stderr
 #define stderr stderr
+#endif
 
 
 /* Remove file FILENAME.  */
 /* Remove file FILENAME.  */
 extern int remove (__const char *__filename) __THROW;
 extern int remove (__const char *__filename) __THROW;
@@ -212,8 +187,7 @@ extern int fflush (FILE *__stream) __THROW;
 extern int fflush_unlocked (FILE *__stream) __THROW;
 extern int fflush_unlocked (FILE *__stream) __THROW;
 #endif
 #endif
 
 
-#if 0
-/*#ifdef __USE_GNU*/
+#ifdef __USE_GNU
 /* Close all streams.  */
 /* Close all streams.  */
 extern int fcloseall (void) __THROW;
 extern int fcloseall (void) __THROW;
 #endif
 #endif
@@ -254,8 +228,8 @@ extern FILE *freopen64 (__const char *__restrict __filename,
 extern FILE *fdopen (int __fd, __const char *__modes) __THROW;
 extern FILE *fdopen (int __fd, __const char *__modes) __THROW;
 #endif
 #endif
 
 
-#if 0
-/*#ifdef	__USE_GNU*/
+#ifdef	__USE_GNU
+#ifdef __STDIO_GLIBC_CUSTOM_STREAMS
 /* Create a new stream that refers to the given magic cookie,
 /* Create a new stream that refers to the given magic cookie,
    and uses the given functions for input and output.  */
    and uses the given functions for input and output.  */
 extern FILE *fopencookie (void *__restrict __magic_cookie,
 extern FILE *fopencookie (void *__restrict __magic_cookie,
@@ -271,6 +245,7 @@ extern FILE *fmemopen (void *__s, size_t __len, __const char *__modes) __THROW;
 extern FILE *open_memstream (char **__restrict __bufloc,
 extern FILE *open_memstream (char **__restrict __bufloc,
 			     size_t *__restrict __sizeloc) __THROW;
 			     size_t *__restrict __sizeloc) __THROW;
 #endif
 #endif
+#endif
 
 
 
 
 /* If BUF is NULL, make STREAM unbuffered.
 /* If BUF is NULL, make STREAM unbuffered.
@@ -380,9 +355,7 @@ extern int getchar (void) __THROW;
 
 
 /* The C standard explicitly says this is a macro, so we always do the
 /* The C standard explicitly says this is a macro, so we always do the
    optimization for it.  */
    optimization for it.  */
-#define getc(stream)	\
-  (((stream)->bufpos >= (stream)->bufread) ? fgetc(stream):		\
-    (*(stream)->bufpos++))
+#define getc(_fp) __GETC(_fp)
 
 
 #if defined __USE_POSIX || defined __USE_MISC
 #if defined __USE_POSIX || defined __USE_MISC
 /* These are defined in POSIX.1:1996.  */
 /* These are defined in POSIX.1:1996.  */
@@ -405,9 +378,7 @@ extern int putchar (int __c) __THROW;
 
 
 /* The C standard explicitly says this can be a macro,
 /* The C standard explicitly says this can be a macro,
    so we always do the optimization for it.  */
    so we always do the optimization for it.  */
-#define putc(c, stream)	\
-    (((stream)->bufpos >= (stream)->bufwrite) ? fputc((c), (stream))	\
-                          : (unsigned char) (*(stream)->bufpos++ = (c))	)
+#define putc(_ch, _fp) __PUTC(_ch, _fp)
 
 
 #ifdef __USE_MISC
 #ifdef __USE_MISC
 /* Faster version when locking is not necessary.  */
 /* Faster version when locking is not necessary.  */
@@ -434,8 +405,7 @@ extern int putw (int __w, FILE *__stream) __THROW;
 extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
 extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
      __THROW;
      __THROW;
 
 
-#if 0
-/*#ifdef __USE_GNU*/
+#ifdef __USE_GNU
 /* This function does the same as `fgets' but does not lock the stream.  */
 /* This function does the same as `fgets' but does not lock the stream.  */
 extern char *fgets_unlocked (char *__restrict __s, int __n,
 extern char *fgets_unlocked (char *__restrict __s, int __n,
 			     FILE *__restrict __stream) __THROW;
 			     FILE *__restrict __stream) __THROW;
@@ -452,15 +422,15 @@ extern char *gets (char *__s) __THROW;
    NULL), pointing to *N characters of space.  It is realloc'd as
    NULL), pointing to *N characters of space.  It is realloc'd as
    necessary.  Returns the number of characters read (not including the
    necessary.  Returns the number of characters read (not including the
    null terminator), or -1 on error or EOF.  */
    null terminator), or -1 on error or EOF.  */
-extern ssize_t __getdelim (char **__restrict __lineptr,
+extern __ssize_t __getdelim (char **__restrict __lineptr,
 			       size_t *__restrict __n, int __delimiter,
 			       size_t *__restrict __n, int __delimiter,
 			       FILE *__restrict __stream) __THROW;
 			       FILE *__restrict __stream) __THROW;
-extern ssize_t getdelim (char **__restrict __lineptr,
+extern __ssize_t getdelim (char **__restrict __lineptr,
 			     size_t *__restrict __n, int __delimiter,
 			     size_t *__restrict __n, int __delimiter,
 			     FILE *__restrict __stream) __THROW;
 			     FILE *__restrict __stream) __THROW;
 
 
 /* Like `getdelim', but reads up to a newline.  */
 /* Like `getdelim', but reads up to a newline.  */
-extern ssize_t getline (char **__restrict __lineptr,
+extern __ssize_t getline (char **__restrict __lineptr,
 			    size_t *__restrict __n,
 			    size_t *__restrict __n,
 			    FILE *__restrict __stream) __THROW;
 			    FILE *__restrict __stream) __THROW;
 #endif
 #endif
@@ -470,8 +440,7 @@ extern ssize_t getline (char **__restrict __lineptr,
 extern int fputs (__const char *__restrict __s, FILE *__restrict __stream)
 extern int fputs (__const char *__restrict __s, FILE *__restrict __stream)
      __THROW;
      __THROW;
 
 
-#if 0
-/*#ifdef __USE_GNU*/
+#ifdef __USE_GNU
 /* This function does the same as `fputs' but does not lock the stream.  */
 /* This function does the same as `fputs' but does not lock the stream.  */
 extern int fputs_unlocked (__const char *__restrict __s,
 extern int fputs_unlocked (__const char *__restrict __s,
 			   FILE *__restrict __stream) __THROW;
 			   FILE *__restrict __stream) __THROW;
@@ -582,7 +551,7 @@ extern int sys_nerr;
 extern __const char *__const sys_errlist[];
 extern __const char *__const sys_errlist[];
 #endif
 #endif
 #if 0
 #if 0
-/*#ifdef	__USE_GNU*/
+/*  #ifdef	__USE_GNU */
 extern int _sys_nerr;
 extern int _sys_nerr;
 extern __const char *__const _sys_errlist[];
 extern __const char *__const _sys_errlist[];
 #endif
 #endif
@@ -591,8 +560,6 @@ extern __const char *__const _sys_errlist[];
 #ifdef	__USE_POSIX
 #ifdef	__USE_POSIX
 /* Return the system file descriptor for STREAM.  */
 /* Return the system file descriptor for STREAM.  */
 extern int fileno (FILE *__stream) __THROW;
 extern int fileno (FILE *__stream) __THROW;
-/* Only use the macro below if you know fp is a valid FILE for a valid fd. */
-#define __fileno(fp)	((fp)->fd)
 #endif /* Use POSIX.  */
 #endif /* Use POSIX.  */
 
 
 #ifdef __USE_MISC
 #ifdef __USE_MISC
@@ -624,7 +591,7 @@ extern char *cuserid (char *__s) __THROW;
 
 
 
 
 #if 0
 #if 0
-/*#ifdef	__USE_GNU*/
+/*  #ifdef	__USE_GNU */
 struct obstack;			/* See <obstack.h>.  */
 struct obstack;			/* See <obstack.h>.  */
 
 
 /* Write formatted output to an obstack.  */
 /* Write formatted output to an obstack.  */
@@ -636,7 +603,7 @@ extern int obstack_vprintf (struct obstack *__restrict __obstack,
 #endif /* Use GNU.  */
 #endif /* Use GNU.  */
 
 
 
 
-#if defined __USE_POSIX || defined __USE_MISC
+#if (defined __USE_POSIX || defined __USE_MISC) && defined __UCLIBC_HAS_THREADS__
 /* These are defined in POSIX.1:1996.  */
 /* These are defined in POSIX.1:1996.  */
 
 
 /* Acquire ownership of STREAM.  */
 /* Acquire ownership of STREAM.  */
@@ -660,7 +627,8 @@ extern void funlockfile (FILE *__stream) __THROW;
 
 
 /* If we are compiling with optimizing read this file.  It contains
 /* If we are compiling with optimizing read this file.  It contains
    several optimizing inline functions and macros.  */
    several optimizing inline functions and macros.  */
-#ifdef __USE_EXTERN_INLINES
+#if 0
+/*  #ifdef __USE_EXTERN_INLINES */
 # include <bits/stdio.h>
 # include <bits/stdio.h>
 #endif
 #endif
 
 

+ 87 - 0
include/stdio_ext.h

@@ -0,0 +1,87 @@
+/* Functions to access FILE structure internals.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This header contains the same definitions as the header of the same name
+   on Sun's Solaris OS.  */
+
+#ifndef _STDIO_EXT_H
+#define _STDIO_EXT_H	1
+
+#include <stdio.h>
+
+enum
+{
+  /* Query current state of the locking status.  */
+  FSETLOCKING_QUERY = 0,
+#define FSETLOCKING_QUERY	FSETLOCKING_QUERY
+  /* The library protects all uses of the stream functions, except for
+     uses of the *_unlocked functions, by calls equivalent to flockfile().  */
+  FSETLOCKING_INTERNAL,
+#define FSETLOCKING_INTERNAL	FSETLOCKING_INTERNAL
+  /* The user will take care of locking.  */
+  FSETLOCKING_BYCALLER
+#define FSETLOCKING_BYCALLER	FSETLOCKING_BYCALLER
+};
+
+
+__BEGIN_DECLS
+
+/* Return the size of the buffer of FP in bytes currently in use by
+   the given stream.  */
+extern size_t __fbufsize (FILE *__fp);
+
+
+/* Return non-zero value iff the stream FP is opened readonly, or if the
+   last operation on the stream was a read operation.  */
+extern int __freading (FILE *__fp);
+
+/* Return non-zero value iff the stream FP is opened write-only or
+   append-only, or if the last operation on the stream was a write
+   operation.  */
+extern int __fwriting (FILE *__fp);
+
+
+/* Return non-zero value iff stream FP is not opened write-only or
+   append-only.  */
+extern int __freadable (FILE *__fp);
+
+/* Return non-zero value iff stream FP is not opened read-only.  */
+extern int __fwritable (FILE *__fp);
+
+
+/* Return non-zero value iff the stream FP is line-buffered.  */
+extern int __flbf (FILE *__fp);
+
+
+/* Discard all pending buffered I/O on the stream FP.  */
+extern void __fpurge (FILE *__fp);
+
+/* Return amount of output in bytes pending on a stream FP.  */
+extern size_t __fpending (FILE *__fp);
+
+/* Flush all line-buffered files.  */
+extern void _flushlbf (void);
+
+
+/* Set locking status of stream FP to TYPE.  */
+extern int __fsetlocking (FILE *__fp, int __type);
+
+__END_DECLS
+
+#endif	/* stdio_ext.h */

+ 7 - 10
libc/inet/addr.c

@@ -10,10 +10,16 @@
  * are smaller than the previous functions and don't require static buffers.
  * are smaller than the previous functions and don't require static buffers.
  * In the process, removed the reference to strcat and cut object size of
  * In the process, removed the reference to strcat and cut object size of
  * inet_ntoa in half (from 190 bytes down to 94).
  * inet_ntoa in half (from 190 bytes down to 94).
+ *
+ * Manuel Novoa III       Feb 2002
+ *
+ * Changed to use _int10tostr.
  */
  */
 
 
 #define __FORCE_GLIBC
 #define __FORCE_GLIBC
 #include <features.h>
 #include <features.h>
+#define _STDIO_UTILITY			/* For _int10tostr. */
+#include <stdio.h>
 #include <string.h>
 #include <string.h>
 #include <ctype.h>
 #include <ctype.h>
 #include <netinet/in.h>
 #include <netinet/in.h>
@@ -80,15 +86,6 @@ const char *cp;
 
 
 #ifdef L_inet_ntoa
 #ifdef L_inet_ntoa
 
 
-#include <limits.h>
-
-#if (ULONG_MAX >> 32)
-/* We're set up for 32 bit unsigned longs */
-#error need to check size allocation for static buffer 'buf'
-#endif
-
-extern char *__ultostr(char *buf, unsigned long uval, int base, int uppercase);
-
 char *inet_ntoa(in)
 char *inet_ntoa(in)
 struct in_addr in;
 struct in_addr in;
 {
 {
@@ -101,7 +98,7 @@ struct in_addr in;
 	q = 0;
 	q = 0;
 	p = buf + sizeof(buf) - 1;
 	p = buf + sizeof(buf) - 1;
 	for (i=0 ; i < 4 ; i++ ) {
 	for (i=0 ; i < 4 ; i++ ) {
-		p = __ultostr(p, addr & 0xff, 10, 0 ) - 1;
+		p = _int10tostr(p, addr & 0xff) - 1;
 		addr >>= 8;
 		addr >>= 8;
 		if (q) {
 		if (q) {
 			*q = '.';
 			*q = '.';

+ 42 - 39
libc/misc/assert/__assert.c

@@ -1,49 +1,52 @@
-/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
- * This file is part of the Linux-8086 C library and is distributed
- * under the GNU Library General Public License.
- */
-
-/*
- * Manuel Novoa III       Dec 2000
+/*  Copyright (C) 2002     Manuel Novoa III
+ *  An __assert() function compatible with the modified glibc assert.h
+ *  that is used by uClibc.
+ *
+ *  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.
  *
  *
- * Converted to use my new (un)signed long (long) to string routines, which
- * are smaller than the previous functions and don't require static buffers.
+ *  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.
  */
  */
 
 
-#include <unistd.h>
-#include <string.h>
+#define _STDIO_UTILITY	/* For _stdio_fdout and _int10tostr. */
+#include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
-#include <limits.h>
-
-#if (INT_MAX >> 31)
-/* We're set up for 32 bit ints */
-#error need to check size allocation for buffer 'buf'
-#endif
-
-extern char *__ltostr(char *buf, unsigned long uval, int base, int uppercase);
+#include <unistd.h>
 
 
-static void errput(str)
-const char *str;
-{
-	write(2, str, strlen(str));
-}
+/* Get the prototype from assert.h as a double-check. */
+#undef NDEBUG
+#include <assert.h>
+#undef assert
 
 
-void __assert(assertion, filename, linenumber, function)
-const char *assertion;
-const char *filename;
-int linenumber;
-const char *function;
+void __assert(const char *assertion, const char * filename,
+			  int linenumber, const char * function)
 {
 {
-	char buf[12];
+	char buf[__BUFLEN_INT10TOSTR];
 
 
-	errput(filename);
-	errput(":");
-	errput(__ltostr(buf + sizeof(buf) - 1, linenumber, 10, 0));
-	errput(function ? ": " : "");
-	errput(function ? function : "");
-	errput(function ? "() " : "");
-	errput(": Assertion \"");
-	errput(assertion);
-	errput("\" failed.\n");
+	_stdio_fdout(STDERR_FILENO,
+#if 0
+				 program_name,	/* TODO: support program_name like glibc? */
+				 ": ",
+#endif
+				 filename,
+				 ":",
+				 _int10tostr(buf+sizeof(buf)-1, linenumber),
+				 ": ",
+				 /* Function name isn't available with some compilers. */
+				 ((function == NULL) ? "?function?" : function),
+				 ":  Assertion `",
+				 assertion,
+				 "' failed.\n",
+				 NULL
+				 );
 	abort();
 	abort();
 }
 }

+ 1 - 7
libc/misc/internals/Makefile

@@ -24,13 +24,7 @@
 TOPDIR=../../../
 TOPDIR=../../../
 include $(TOPDIR)Rules.mak
 include $(TOPDIR)Rules.mak
 
 
-CSRC=ultostr.c ltostr.c __uClibc_main.c tempname.c errno.c __errno_location.c __h_errno_location.c
-ifeq ($(HAS_FLOATING_POINT),true)
-	CSRC += dtostr.c zoicheck.c
-endif
-ifeq ($(HAS_LONG_LONG),true)
-	CSRC += ulltostr.c lltostr.c 
-endif
+CSRC=__uClibc_main.c tempname.c errno.c __errno_location.c __h_errno_location.c
 
 
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 OBJS=$(COBJS)
 OBJS=$(COBJS)

+ 9 - 9
libc/misc/internals/__uClibc_main.c

@@ -28,13 +28,13 @@ void __uClibc_main(int argc, char **argv, char **envp)
 
 
 #ifdef HAVE_ELF
 #ifdef HAVE_ELF
 weak_alias(__environ, environ);
 weak_alias(__environ, environ);
-extern void weak_function __init_stdio(void);
-extern void weak_function __stdio_flush_buffers(void);
+extern void weak_function _stdio_init(void);
+extern void weak_function _stdio_term(void);
 extern int *weak_const_function __errno_location (void);
 extern int *weak_const_function __errno_location (void);
 extern int *weak_const_function __h_errno_location (void);
 extern int *weak_const_function __h_errno_location (void);
 #else
 #else
-extern void __init_stdio(void);
-extern void __stdio_flush_buffers(void);
+extern void _stdio_init(void);
+extern void _stdio_term(void);
 extern int *__errno_location (void);
 extern int *__errno_location (void);
 extern int *__h_errno_location (void);
 extern int *__h_errno_location (void);
 #endif	
 #endif	
@@ -71,8 +71,8 @@ void __uClibc_main(int argc, char **argv, char **envp)
 	 * Initialize stdio here.  In the static library case, this will
 	 * Initialize stdio here.  In the static library case, this will
 	 * be bypassed if not needed because of the weak alias above.
 	 * be bypassed if not needed because of the weak alias above.
 	 */
 	 */
-	if (__init_stdio)
-	  __init_stdio();
+	if (_stdio_init)
+	  _stdio_init();
 
 
 	/*
 	/*
 	 * Note: It is possible that any initialization done above could
 	 * Note: It is possible that any initialization done above could
@@ -95,7 +95,7 @@ void __uClibc_main(int argc, char **argv, char **envp)
 /*
 /*
  * Define an empty function and use it as a weak alias for the stdio
  * Define an empty function and use it as a weak alias for the stdio
  * initialization routine.  That way we don't pull in all the stdio
  * initialization routine.  That way we don't pull in all the stdio
- * code unless we need to.  Similarly, do the same for __stdio_flush_buffers
+ * code unless we need to.  Similarly, do the same for _stdio_term
  * so as not to include atexit unnecessarily.
  * so as not to include atexit unnecessarily.
  *
  *
  * NOTE!!! This is only true for the _static_ case!!!
  * NOTE!!! This is only true for the _static_ case!!!
@@ -106,7 +106,7 @@ weak_alias(__environ, environ);
 void __uClibc_empty_func(void)
 void __uClibc_empty_func(void)
 {
 {
 }
 }
-weak_alias(__uClibc_empty_func, __init_stdio);
-weak_alias(__uClibc_empty_func, __stdio_flush_buffers);
+weak_alias(__uClibc_empty_func, _stdio_init);
+weak_alias(__uClibc_empty_func, _stdio_term);
 #endif
 #endif
 #endif	
 #endif	

+ 0 - 423
libc/misc/internals/dtostr.c

@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Manuel Novoa III
- *
- * Function:  int __dtostr(FILE * fp, size_t size, long double x, 
- *			               char flag[], int width, int preci, char mode)
- *
- * This was written for uClibc to provide floating point support for
- * the printf functions.  It handles +/- infinity and nan on i386.
- *
- * Notes:
- *
- * At most MAX_DIGITS significant digits are kept.  Any trailing digits
- * are treated as 0 as they are really just the results of rounding noise
- * anyway.  If you want to do better, use an arbitary precision arithmetic
- * package.  ;-)
- *
- * It should also be fairly portable, as not assumptions are made about the
- * bit-layout of doubles.
- *
- * It should be too difficult to convert this to handle long doubles on i386.
- * For information, see the comments below.
- *
- * TODO: 
- *   long double and/or float version?  (note: for float can trim code some).
- *   
- *   Decrease the size.  This is really much bigger than I'd like.
- */
-
-/*****************************************************************************/
-/* Don't change anything that follows unless you know what you're doing.     */
-/*****************************************************************************/
-
-/*
- * Configuration for the scaling power table.  Ignoring denormals, you
- * should have 2**EXP_TABLE_SIZE >= LDBL_MAX_EXP >= 2**(EXP_TABLE_SIZE-1).
- * The minimum for standard C is 6.  For IEEE 8bit doubles, 9 suffices.
- * For long doubles on i386, use 13.
- */
-#define EXP_TABLE_SIZE       13
-
-/* 
- * Set this to the maximum number of digits you want converted.
- * Conversion is done in blocks of DIGITS_PER_BLOCK (9 by default) digits.
- * (20) 17 digits suffices to uniquely determine a (long) double on i386.
- */
-#define MAX_DIGITS          20
-
-/*
- * Set this to the smallest integer type capable of storing a pointer.
- */
-#define INT_OR_PTR int
-
-/*
- * This is really only used to check for infinities.  The macro produces
- * smaller code for i386 and, since this is tested before any floating point
- * calculations, it doesn't appear to suffer from the excess precision problem
- * caused by the FPU that strtod had.  If it causes problems, call the function
- * and compile zoicheck.c with -ffloat-store.
- */
-#define _zero_or_inf_check(x) ( x == (x/4) )
-
-/*
- * Fairly portable nan check.  Bitwise for i386 generated larger code.
- * If you have a better version, comment this out.
- */
-#define isnan(x) (x != x)
-
-/*****************************************************************************/
-/* Don't change anything that follows peroid!!!  ;-)                         */
-/*****************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <float.h>
-#include <limits.h>
-
-extern int fnprintf(FILE * fp, size_t size, const char *fmt, ...);
-
-/* from printf.c -- should really be in an internal header file */
-enum {
-	FLAG_PLUS = 0,
-	FLAG_MINUS_LJUSTIFY,
-	FLAG_HASH,
-	FLAG_0_PAD,
-	FLAG_SPACE,
-};
-
-/*****************************************************************************/
-
-/*
- * Set things up for the scaling power table.
- */
-
-#if EXP_TABLE_SIZE < 6
-#error EXP_TABLE_SIZE should be at least 6 to comply with standards
-#endif
-
-#define EXP_TABLE_MAX      (1U<<(EXP_TABLE_SIZE-1))
-
-/*
- * Only bother checking if this is too small.
- */
-
-#if LDBL_MAX_10_EXP/2 > EXP_TABLE_MAX
-#error larger EXP_TABLE_SIZE needed
-#endif
-
-/*
- * With 32 bit ints, we can get 9 digits per block.
- */
-#define DIGITS_PER_BLOCK     9
-
-#if (INT_MAX >> 30)
-#define DIGIT_BLOCK_TYPE     int
-#define DB_FMT               "%.*d"
-#elif (LONG_MAX >> 30)
-#define DIGIT_BLOCK_TYPE     long
-#define DB_FMT               "%.*ld"
-#else
-#error need at least 32 bit longs
-#endif
-
-/* Are there actually any machines where this might fail? */
-#if 'A' > 'a'
-#error ordering assumption violated : 'A' > 'a'
-#endif
-
-/* Maximum number of calls to fnprintf to output double. */
-#define MAX_CALLS 8
-
-/*****************************************************************************/
-
-#define NUM_DIGIT_BLOCKS   ((MAX_DIGITS+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK)
-
-/* extra space for '-', '.', 'e+###', and nul */
-#define BUF_SIZE  ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK )
-/*****************************************************************************/
-
-static const char *fmts[] = {
-	"%0*d", "%.*s", ".", "inf", "INF", "nan", "NAN", "%*s"
-};
-
-/*****************************************************************************/
-
-int __dtostr(FILE * fp, size_t size, long double x, 
-			 char flag[], int width, int preci, char mode)
-{
-	long double exp_table[EXP_TABLE_SIZE];
-	long double p10;
-	DIGIT_BLOCK_TYPE digit_block; /* int of at least 32 bits */
-	int i, j;
-	int round, o_exp;
-	int exp, exp_neg;
-	char *s;
-	char *e;
-	char buf[BUF_SIZE];
-	INT_OR_PTR pc_fwi[2*MAX_CALLS];
-	INT_OR_PTR *ppc;
-	char exp_buf[8];
-	char drvr[8];
-	char *pdrvr;
-	int npc;
-	int cnt;
-	char sign_str[2];
-	char o_mode;
-
-	/* check that INT_OR_PTR is sufficiently large */
-	assert( sizeof(INT_OR_PTR) == sizeof(char *) );
-
-	*sign_str = flag[FLAG_PLUS];
-	*(sign_str+1) = 0;
-	if (isnan(x)) {				/* nan check */
-		pdrvr = drvr + 1;
-		*pdrvr++ = 5 + (mode < 'a');
-		pc_fwi[2] = 3;
-		flag[FLAG_0_PAD] = 0;
-		goto EXIT_SPECIAL;
-	}
-
-	if (x == 0) {				/* handle 0 now to avoid false positive */
-		exp = -1;
-		goto GENERATE_DIGITS;
-	}
-
-	if (x < 0) {				/* convert negatives to positives */
-		*sign_str = '-';
-		x = -x;
-	}
-
-	if (_zero_or_inf_check(x)) { /* must be inf since zero handled above */
-		pdrvr = drvr + 1;
-		*pdrvr++ = 3 +  + (mode < 'a');
-		pc_fwi[2] = 3;
-		flag[FLAG_0_PAD] = 0;
-		goto EXIT_SPECIAL;
-	}
-
-	/* need to build the scaling table */
-	for (i = 0, p10 = 10 ; i < EXP_TABLE_SIZE ; i++) {
-		exp_table[i] = p10;
-		p10 *= p10;
-	}
-
-	exp_neg = 0;
-	if (x < 1e8) {				/* do we need to scale up or down? */
-		exp_neg = 1;
-	}
-
-	exp = DIGITS_PER_BLOCK - 1;
-
-	i = EXP_TABLE_SIZE;
-	j = EXP_TABLE_MAX;
-	while ( i-- ) {				/* scale x such that 1e8 <= x < 1e9 */
-		if (exp_neg) {
-			if (x * exp_table[i] < 1e9) {
-				x *= exp_table[i];
-				exp -= j;
-			}
-		} else {
-			if (x / exp_table[i] >= 1e8) {
-				x /= exp_table[i];
-				exp += j;
-			}
-		}
-		j >>= 1;
-	}
-	if (x >= 1e9) {				/* handle bad rounding case */
-		x /= 10;
-		++exp;
-	}
-	assert(x < 1e9);
-
- GENERATE_DIGITS:
-	s = buf + 2; /* leave space for '\0' and '0' */
-
-	for (i = 0 ; i < NUM_DIGIT_BLOCKS ; ++i ) {
-		digit_block = (DIGIT_BLOCK_TYPE) x;
-		x = (x - digit_block) * 1e9;
-		s += sprintf(s, DB_FMT, DIGITS_PER_BLOCK, digit_block);
-	}
-
-	/*************************************************************************/
-
-	*exp_buf = 'e';
-	if (mode < 'a') {
-		*exp_buf = 'E';
-		mode += ('a' - 'A');
-	} 
-
-	o_mode = mode;
-
-	round = preci;
-
-	if ((mode == 'g') && (round > 0)){
-		--round;
-	}
-
-	if (mode == 'f') {
-		round += exp;
-	}
-
-	s = buf;
-	*s++ = 0;					/* terminator for rounding and 0-triming */
-	*s = '0';					/* space to round */
-
-	i = 0;
-	e = s + MAX_DIGITS + 1;
-	if (round < MAX_DIGITS) {
-		e = s + round + 2;
-		if (*e >= '5') {
-			i = 1;
-		}
-	}
-
-	do {						/* handle rounding and trim trailing 0s */
-		*--e += i;				/* add the carry */
-	} while ((*e == '0') || (*e > '9'));
-
-	o_exp = exp;
-	if (e <= s) {				/* we carried into extra digit */
-		++o_exp;
-		e = s;					/* needed if all 0s */
-	} else {
-		++s;
-	}
-	*++e = 0;					/* ending nul char */
-
-	if ((mode == 'g') && ((o_exp >= -4) && (o_exp <= round))) {
-		mode = 'f';
-	}
-
-	exp = o_exp;
-	if (mode != 'f') {
-		o_exp = 0;
-	}
-
-	if (o_exp < 0) {
-		*--s = '0';				/* fake the first digit */
-	}
-
-	pdrvr = drvr+1;
-	ppc = pc_fwi+2;
-
-	*pdrvr++ = 0;
-	*ppc++ = 1;
-	*ppc++ = (INT_OR_PTR)(*s++ - '0');
-
-	i = e - s;					/* total digits */
-	if (o_exp >= 0) {
-		if (o_exp >= i) {		/* all digit(s) left of decimal */
-			*pdrvr++ = 1;
-			*ppc++ = i;
-			*ppc++ = (INT_OR_PTR)(s);
-			o_exp -= i;
-			i = 0;
-			if (o_exp>0) {		/* have 0s left of decimal */
-				*pdrvr++ = 0;
-				*ppc++ = o_exp;
-				*ppc++ = 0;
-			}
-		} else if (o_exp > 0) {	/* decimal between digits */
-			*pdrvr++ = 1;
-			*ppc++ = o_exp;
-			*ppc++ = (INT_OR_PTR)(s);
-			s += o_exp;
-			i -= o_exp;
-		}
-		o_exp = -1;
-	}
-
-	if (flag[FLAG_HASH] || (i) || ((o_mode != 'g') && (preci > 0))) {
-		*pdrvr++ = 2;			/* need decimal */
-		*ppc++ = 1;				/* needed for width calc */
-		ppc++;
-	}
-
-	if (++o_exp < 0) {			/* have 0s right of decimal */
-		*pdrvr++ = 0;
-		*ppc++ = -o_exp;
-		*ppc++ = 0;
-	}
-	if (i) {					/* have digit(s) right of decimal */
-		*pdrvr++ = 1;
-		*ppc++ = i;
-		*ppc++ = (INT_OR_PTR)(s);
-	}
-
-	if (o_mode != 'g') {
-		i -= o_exp;
-		if (i < preci) {		/* have 0s right of digits */
-			i = preci - i;
-			*pdrvr++ = 0;
-			*ppc++ = i;
-			*ppc++ = 0;
-		}
-	}
-
-	/* build exponent string */
-	if (mode != 'f') {
-		*pdrvr++ = 1;
-		*ppc++ = sprintf(exp_buf,"%c%+.2d", *exp_buf, exp);
-		*ppc++ = (INT_OR_PTR) exp_buf;
-	}
-
- EXIT_SPECIAL:
-	npc = pdrvr - drvr;
-	ppc = pc_fwi + 2;
-	for (i=1 ; i< npc ; i++) {
-		width -= *(ppc++);
-		ppc++;
-	}
-	i = 0;
-	if (*sign_str) {
-		i = 1;
-	}
-	width -= i;
-	if (width <= 0) {
-		width = 0;
-	} else {
-		if (flag[FLAG_MINUS_LJUSTIFY]) { /* padding on right */
-			++npc;
-			*pdrvr++ = 7;
-			*ppc = width;
-			*++ppc = (INT_OR_PTR)("");
-			width = 0;
-		} else if (flag[FLAG_0_PAD] == '0') { /* 0 padding */
-			pc_fwi[2] += width;
-			width = 0;
-		}
-	}
-	*drvr = 7;
-	ppc = pc_fwi;
-	*ppc++ = width + i;
-	*ppc = (INT_OR_PTR) sign_str;
-
-	pdrvr = drvr;
-	ppc = pc_fwi;
-	cnt = 0;
-	for (i=0 ; i<npc ; i++) {
-#if 1
-		fnprintf(fp, size, fmts[(int)(*pdrvr++)], (INT_OR_PTR)(*(ppc)), 
-				 (INT_OR_PTR)(*(ppc+1)));
-#else
-		j = fnprintf(fp, size, fmts[(int)(*pdrvr++)], (INT_OR_PTR)(*(ppc)), 
-					  (INT_OR_PTR)(*(ppc+1)));
-		assert(j == *ppc);
-#endif
-		if (size > *ppc) {
-			size -= *ppc;
-		}
-		cnt += *ppc;			/* to avoid problems if j == -1 */
-		ppc += 2;
-	}
-
-	return cnt;
-}
-
-
-
-
-
-

+ 0 - 39
libc/misc/internals/lltostr.c

@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2000 Manuel Novoa III
- *
- * Note: buf is a pointer to the END of the buffer passed.
- * Call like this:
- *     char buf[SIZE], *p;
- *     p = __lltostr(buf + sizeof(buf) - 1, ...)
- * For long longs of 64 bits, appropriate buffer sizes are:
- *     base =  2      66  = 1 (possible -) sign + 64 digits + 1 nul
- *     base = 10      21  = 1 (possible -) sign + 19 digits + 1 nul
- *     base = 16      18  = 1 (possible -) sign + 16 hex digits + 1 nul
- */
-
-extern char *__ulltostr(char *buf, unsigned long long uval, int base, 
-						int uppercase);
-
-char *__lltostr(char *buf, long long val, int base, int uppercase)
-{
-	unsigned long long uval;
-	char *pos;
-    int negative;
-
-	negative = 0;
-    if (val < 0) {
-		negative = 1;
-		uval = ((unsigned long long)(-(1+val))) + 1;
-    } else {
-		uval = val;
-	}
-
-
-    pos = __ulltostr(buf, uval, base, uppercase);
-
-    if (pos && negative) {
-		*--pos = '-';
-    }
-
-    return pos;
-}

+ 0 - 39
libc/misc/internals/ltostr.c

@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2000 Manuel Novoa III
- *
- * Note: buf is a pointer to the END of the buffer passed.
- * Call like this:
- *     char buf[SIZE], *p;
- *     p = __ltostr(buf + sizeof(buf) - 1, ...)
- *
- * For longs of 32 bits, appropriate buffer sizes are:
- *     base =  2      34  = 1 (possible -) sign + 32 digits + 1 nul
- *     base = 10      12  = 1 (possible -) sign + 10 digits + 1 nul
- *     base = 16      10  = 1 (possible -) sign + 8 hex digits + 1 nul
- */
-
-extern char *__ultostr(char *buf, unsigned long uval, int base, int uppercase);
-
-char *__ltostr(char *buf, long val, int base, int uppercase)
-{
-	unsigned long uval;
-	char *pos;
-    int negative;
-
-	negative = 0;
-    if (val < 0) {
-		negative = 1;
-		uval = ((unsigned long)(-(1+val))) + 1;
-    } else {
-		uval = val;
-	}
-
-
-    pos = __ultostr(buf, uval, base, uppercase);
-
-    if (pos && negative) {
-		*--pos = '-';
-    }
-
-    return pos;
-}

+ 23 - 14
libc/misc/internals/tempname.c

@@ -16,6 +16,11 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
    Boston, MA 02111-1307, USA.  */
 
 
+/* March 11, 2002       Manuel Novoa III
+ *
+ * Modify code to remove dependency on libgcc long long arith support funcs.
+ */
+
 #include <stddef.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -117,8 +122,11 @@ int __gen_tempname (char *tmpl, int openit)
     char *XXXXXX;
     char *XXXXXX;
     static uint64_t value;
     static uint64_t value;
     struct timeval tv;
     struct timeval tv;
+	uint32_t high, low, rh;
+	unsigned int k;
     int count, fd;
     int count, fd;
     int save_errno = errno;
     int save_errno = errno;
+	int i;
 
 
     len = strlen (tmpl);
     len = strlen (tmpl);
     if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
     if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
@@ -136,20 +144,21 @@ int __gen_tempname (char *tmpl, int openit)
 
 
     for (count = 0; count < TMP_MAX; value += 7777, ++count)
     for (count = 0; count < TMP_MAX; value += 7777, ++count)
     {
     {
-	uint64_t v = value;
-
-	/* Fill in the random bits.  */
-	XXXXXX[0] = letters[v % 62];
-	v /= 62;
-	XXXXXX[1] = letters[v % 62];
-	v /= 62;
-	XXXXXX[2] = letters[v % 62];
-	v /= 62;
-	XXXXXX[3] = letters[v % 62];
-	v /= 62;
-	XXXXXX[4] = letters[v % 62];
-	v /= 62;
-	XXXXXX[5] = letters[v % 62];
+	low = value & UINT32_MAX;
+	high = value >> 32;
+
+	for (i = 0 ; i < 6 ; i++) {
+		rh = high % 62;
+		high /= 62;
+#define L ((UINT32_MAX % 62 + 1) % 62)
+		k = (low % 62) + (L * rh);
+#undef L
+#define H ((UINT32_MAX / 62) + ((UINT32_MAX % 62 + 1) / 62))
+		low = (low / 62) + (H * rh) + (k / 62);
+#undef H
+		k %= 62;
+		XXXXXX[i] = letters[k];
+	}
 
 
 	if (openit)
 	if (openit)
 	{
 	{

+ 0 - 37
libc/misc/internals/ulltostr.c

@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2000 Manuel Novoa III
- *
- * Note: buf is a pointer to the END of the buffer passed.
- * Call like this:
- *     char buf[SIZE], *p;
- *     p = __ulltostr(buf + sizeof(buf) - 1, ...)
- *
- * For long longs of 64 bits, appropriate buffer sizes are:
- *     base =  2      65  = 64 digits + 1 nul
- *     base = 10      20  = 19 digits + 1 nul
- *     base = 16      17  = 16 hex digits + 1 nul
- */
-
-char *__ulltostr(char *buf, unsigned long long uval, int base, int uppercase)
-{
-    int digit;
-
-    if ((base < 2) || (base > 36)) {
-		return 0;
-    }
-
-    *buf = '\0';
-
-    do {
-		digit = uval % base;
-		uval /= base;
-
-		/* note: slightly slower but generates less code */
-		*--buf = '0' + digit;
-		if (digit > 9) {
-			*buf = (uppercase ? 'A' : 'a') + digit - 10;
-		}
-    } while (uval);
-
-    return buf;
-}

+ 0 - 37
libc/misc/internals/ultostr.c

@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2000 Manuel Novoa III
- *
- * Note: buf is a pointer to the END of the buffer passed.
- * Call like this;
- *     char buf[SIZE], *p;
- *     p = __ultostr(buf + sizeof(buf) - 1, ...)
- *
- * For longs of 32 bits, appropriate buffer sizes are:
- *     base =  2      33  = 32 digits + 1 nul
- *     base = 10      11  = 10 digits + 1 nul
- *     base = 16       9  = 8 hex digits + 1 nul
- */
-
-char *__ultostr(char *buf, unsigned long uval, int base, int uppercase)
-{
-    int digit;
-
-    if ((base < 2) || (base > 36)) {
-		return 0;
-    }
-
-    *buf = '\0';
-
-    do {
-		digit = uval % base;
-		uval /= base;
-
-		/* note: slightly slower but generates less code */
-		*--buf = '0' + digit;
-		if (digit > 9) {
-			*buf = (uppercase ? 'A' : 'a') + digit - 10;
-		}
-    } while (uval);
-
-    return buf;
-}

+ 0 - 16
libc/misc/internals/zoicheck.c

@@ -1,16 +0,0 @@
-
-/*
- * Copyright (C) 2000 Manuel Novoa III
- *
- * This is a utility routine for strtod errno support.
- * As the name implies, it checks if a double is either 0 or +/-infinity.
- * Doing this inline doesn't work on i386 because of excess precission
- * stored in the FPU.
- *
- * TODO: Check bitmasks directly?
- */
-
-int _zero_or_inf_check(double x)
-{
-	return ( x == x/4 );
-}

+ 61 - 14
libc/stdio/Makefile

@@ -24,26 +24,73 @@
 TOPDIR=../../
 TOPDIR=../../
 include $(TOPDIR)Rules.mak
 include $(TOPDIR)Rules.mak
 
 
-MSRC=stdio.c
-MOBJ=_stdio_init.o _alloc_stdio_buffer.o _free_stdio_buffer_of_file.o \
-     _free_stdio_stream.o clearerr.o feof.o ferror.o fileno.o setbuffer.o \
-     setvbuf.o setbuf.o setlinebuf.o fclose.o _fopen.o fopen.o freopen.o \
-     fdopen.o fflush.o fsfopen.o fseek.o rewind.o ftell.o fgetpos.o fsetpos.o \
-     fputc.o fgetc.o fgets.o gets.o fputs.o puts.o ungetc.o fread.o fwrite.o \
-     getchar.o putchar.o _uClibc_fwrite.o _uClibc_fread.o fopen64.o getc.o putc.o
-
-MSRC2=printf.c
-MOBJ2=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o snprintf.o \
-     vsnprintf.o asprintf.o vfnprintf.o fnprintf.o vdprintf.o
+# Set to true to use the old vfprintf instead of the new.  The old is roughly
+# C89 compliant, but doesn't deal with qualifiers on %n and doesn't deal with
+# %h correctly or %hh at all on the interger conversions.  But on i386 it is
+# over 1.5k smaller than the new code.  Of course, the new code fixes the
+# above mentioned deficiencies and adds custom specifier support similar to
+# glibc, as well as handling positional args.  This option is here temporarily
+# until the configuration system gets rewritten.  Note also that the old
+# vfprintf code will be rewritten at some point to bring it into at least C89
+# standards compliance.
+
+USE_OLD_VFPRINTF = false
+
+# Note: The *64.o objects are empty when compiled without large file support.
+#       To not build them at all, remove the appropriate line from the MOBJ
+#       definition and uncomment the DOLFS test below.
+
+# Note: Use the libpthreads of: flockfile.o ftrylockfile.o funlockfile.o
+#       Also, maybe move __fsetlocking.o as well?
+
+MSRC = stdio.c
+MOBJ = fclose.o fflush.o fopen.o freopen.o perror.o remove.o \
+	setbuf.o setvbuf.o fgetc.o fgets.o fputc.o fputs.o \
+	getc.o getchar.o gets.o putc.o putchar.o puts.o \
+	ungetc.o fread.o fwrite.o fgetpos.o fseek.o fsetpos.o ftell.o \
+	rewind.o clearerr.o feof.o ferror.o \
+	fileno.o fdopen.o getw.o putw.o setbuffer.o setlinebuf.o fcloseall.o \
+	fopen64.o freopen64.o ftello64.o fseeko64.o fsetpos64.o fgetpos64.o \
+	__fbufsize.o __freading.o __fwriting.o __freadable.o __fwritable.o \
+	__flbf.o __fpurge.o __fpending.o _flushlbf.o \
+	 fopencookie.o fmemopen.o open_memstream.o \
+	__fsetlocking.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
+
+# ifeq ($(DOLFS),true)
+# 	MOBJ += fopen64.o freopen64.o ftello64.o fseeko64.o fsetpos64.o fgetpos64.o
+# endif
+
+MSRC2= printf.c
+MOBJ2=  vsnprintf.o vdprintf.o vasprintf.o vprintf.o vsprintf.o \
+	fprintf.o  snprintf.o  dprintf.o  asprintf.o  printf.o  sprintf.o
+
+ifneq ($(USE_OLD_VFPRINTF),true)
+	MOBJ2 += _ppfs_init.o _ppfs_prepargs.o _ppfs_setargs.o \
+		 _ppfs_parsespec.o _do_one_spec.o vfprintf.o \
+		 _store_inttype.o _load_inttype.o \
+		 register_printf_function.o parse_printf_format.o
+endif
+
+
+
+ifeq ($(HAS_FLOATING_POINT),true)
+	MOBJ2 += _dtostr.o
+endif
 
 
 MSRC3=scanf.c
 MSRC3=scanf.c
 MOBJ3=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o
 MOBJ3=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o
 
 
-CSRC=popen.c perror.c remove.c getdelim.c getline.c tmpfile.c tmpnam.c \
-     tmpnam_r.c tempnam.c ctermid.c getw.c putw.c
+CSRC=popen.c getdelim.c getline.c tmpfile.c tmpnam.c \
+     tmpnam_r.c tempnam.c ctermid.c
+ifeq ($(USE_OLD_VFPRINTF),true)
+	CSRC += old_vfprintf.c
+endif
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 COBJS=$(patsubst %.c,%.o, $(CSRC))
-OBJS=$(MOBJ) $(MOBJ2) $(MOBJ3) $(COBJS)
 
 
+OBJS=$(MOBJ) $(MOBJ2) $(MOBJ3) $(COBJS)
 
 
 all: $(OBJS) $(LIBC)
 all: $(OBJS) $(LIBC)
 
 

+ 0 - 36
libc/stdio/getw.c

@@ -1,36 +0,0 @@
-/* Copyright (C) 1991, 1997, 1998 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <stdio.h>
-
-#ifdef USE_IN_LIBIO
-# include <libio/iolibio.h>
-# define fread(p, m, n, s) _IO_fread (p, m, n, s)
-#endif
-
-/* Read a word (int) from STREAM.  */
-int
-getw (FILE *stream)
-{
-  int w;
-
-  /* Is there a better way?  */
-  if (fread ((void *) &w, sizeof (w), 1, stream) != 1)
-    return EOF;
-  return w;
-}

+ 78 - 298
libc/stdio/printf.c → libc/stdio/old_vfprintf.c

@@ -97,7 +97,6 @@
 
 
 /* These are now set in uClibc_config.h based on Config. */
 /* These are now set in uClibc_config.h based on Config. */
 /*
 /*
-#define __UCLIBC_HAS_LONG_LONG__         1
 #define __UCLIBC_HAS_FLOATS__            1
 #define __UCLIBC_HAS_FLOATS__            1
 */
 */
 
 
@@ -109,7 +108,6 @@
  *      to the base code size of 1163 on i386.
  *      to the base code size of 1163 on i386.
  */
  */
 
 
-#define WANT_LONG_LONG_ERROR   0
 #define WANT_FLOAT_ERROR      0
 #define WANT_FLOAT_ERROR      0
 
 
 /*
 /*
@@ -123,200 +121,29 @@
 
 
 /**************************************************************************/
 /**************************************************************************/
 
 
-#include <sys/types.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
+#define _GNU_SOURCE				/* for strnlen */
+#define _STDIO_UTILITY
+#include <stdio.h>
+#include <stdarg.h>
 #include <limits.h>
 #include <limits.h>
-#include <assert.h>
-
-#if WANT_GNU_ERRNO
+#include <string.h>
 #include <errno.h>
 #include <errno.h>
-#endif
 
 
-#ifdef __STDC__
-#include <stdarg.h>
-#define va_strt      va_start
-#else
-#include <varargs.h>
-#define va_strt(p,i) va_start(p)
-#endif
+#define __PRINTF_INFO_NO_BITFIELD
+#include <printf.h>
 
 
-#include "stdio.h"
+#ifdef __STDIO_THREADSAFE
+#include <pthread.h>
+#endif /* __STDIO_THREADSAFE */
 
 
-extern int vfnprintf(FILE * op, size_t max_size,
-					 register __const char *fmt, register va_list ap);
+/*  #undef __UCLIBC_HAS_FLOATS__ */
+/*  #undef WANT_FLOAT_ERROR */
+/*  #define WANT_FLOAT_ERROR      1 */
 
 
-#ifdef L_printf
-int printf(const char *fmt, ...)
-{
-	va_list ptr;
-	int rv;
+#define __isdigit(c) (((unsigned int)(c - '0')) < 10)
 
 
-	va_strt(ptr, fmt);
-	rv = vfnprintf(stdout, -1, fmt, ptr);
-	va_end(ptr);
-	return rv;
-}
-#endif
+extern size_t _dtostr(FILE * fp, long double x, struct printf_info *info);
 
 
-#ifdef L_asprintf
-int asprintf(char **app, const char *fmt, ...)
-{
-	va_list ptr;
-	int rv;
-	char *p;
-
-	/*
-	 * First iteration - find out size of buffer required and allocate it.
-	 */
-	va_strt(ptr, fmt);
-	rv = vsnprintf(NULL, 0, fmt, ptr);
-	va_end(ptr);
-
-	p = malloc(++rv);			/* allocate the buffer */
-	*app = p;
-	if (!p) {
-		return -1;
-	}
-
-	/*
-	 * Second iteration - actually produce output.
-	 */
-	va_strt(ptr, fmt);
-	rv = vsnprintf(p, rv, fmt, ptr);
-	va_end(ptr);
-
-	return rv;
-}
-#endif
-
-#ifdef L_sprintf
-int sprintf(char *sp, const char *fmt, ...)
-{
-	va_list ptr;
-	int rv;
-
-	va_strt(ptr, fmt);
-	rv = vsnprintf(sp, -1, fmt, ptr);
-	va_end(ptr);
-	return rv;
-}
-#endif
-
-
-#ifdef L_snprintf
-int snprintf(char *sp, size_t size, const char *fmt, ...)
-{
-	va_list ptr;
-	int rv;
-
-	va_strt(ptr, fmt);
-	rv = vsnprintf(sp, size, fmt, ptr);
-	va_end(ptr);
-	return rv;
-}
-#endif
-
-#ifdef L_fprintf
-int fprintf(FILE * fp, const char *fmt, ...)
-{
-	va_list ptr;
-	int rv;
-
-	va_strt(ptr, fmt);
-	rv = vfnprintf(fp, -1, fmt, ptr);
-	va_end(ptr);
-	return rv;
-}
-#endif
-
-#ifdef L_fnprintf
-int fnprintf(FILE * fp, size_t size, const char *fmt, ...)
-{
-	va_list ptr;
-	int rv;
-
-	va_strt(ptr, fmt);
-	rv = vfnprintf(fp, size, fmt, ptr);
-	va_end(ptr);
-	return rv;
-}
-#endif
-
-#ifdef L_vprintf
-int vprintf(const char *fmt, va_list ap)
-{
-	return vfprintf(stdout, fmt, ap);
-}
-#endif
-
-#ifdef L_vfprintf
-
-int vfprintf(FILE * op, register __const char *fmt, register va_list ap)
-{
-	return vfnprintf(op, -1, fmt, ap);
-}
-
-#endif
-
-#ifdef L_vsprintf
-int vsprintf(char *sp, __const char *fmt, va_list ap)
-{
-	return vsnprintf(sp, -1, fmt, ap);
-}
-#endif
-
-#ifdef L_vsnprintf
-int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap)
-{
-	int rv;
-	FILE f;
-
-	/*
-	 * As we're only using the putc macro in vfnprintf, we don't need to
-	 * initialize all FILE f's fields.
-	 */
-	f.bufwrite = (char *) ((unsigned) -1);
-	f.bufpos = sp;
-	f.mode = _IOFBF;
-
-	rv = vfnprintf(&f, size, fmt, ap);
-	if (size) {					/* If this is going to a buffer, */
-		*(f.bufpos) = 0;		/* don't forget to nul-terminate. */
-	}
-	return rv;
-}
-#endif
-
-#ifdef L_vdprintf
-/*
- * Note: If fd has an associated buffered FILE, bad things happen.
- */
-extern int vdprintf(int fd, const char *fmt, va_list ap)
-{
-	char buf[BUFSIZ];
-	FILE f = {buf, 0, buf+sizeof(buf), buf, buf+sizeof(buf), 0, fd, _IOFBF};
-	int rv;
-
-	rv = vfnprintf(&f, -1, fmt, ap);
-
-	if (fflush(&f)) {
-		return -1;
-	}
-
-	return rv;
-}
-#endif
-
-#ifdef L_vfnprintf
-
-extern char *__ultostr(char *buf, unsigned long uval, int base, int uppercase);
-extern char *__ltostr(char *buf, long val, int base, int uppercase);
-extern char *__ulltostr(char *buf, unsigned long long uval, int base, int uppercase);
-extern char *__lltostr(char *buf, long long val, int base, int uppercase);
-extern int __dtostr(FILE * fp, size_t size, long double x,
-				  char flag[], int width, int preci, char mode);
 
 
 enum {
 enum {
 	FLAG_PLUS = 0,
 	FLAG_PLUS = 0,
@@ -329,15 +156,7 @@ enum {
 /* layout                   01234  */
 /* layout                   01234  */
 static const char spec[] = "+-#0 ";
 static const char spec[] = "+-#0 ";
 
 
-#if defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR
 static const char qual[] = "hlLq";
 static const char qual[] = "hlLq";
-#else
-static const char qual[] = "hl";
-#endif
-
-#if !defined(__UCLIBC_HAS_LONG_LONG__) && WANT_LONG_LONG_ERROR
-static const char ll_err[] = "<LONG-LONG>";
-#endif
 
 
 #if !defined(__UCLIBC_HAS_FLOATS__) && WANT_FLOAT_ERROR
 #if !defined(__UCLIBC_HAS_FLOATS__) && WANT_FLOAT_ERROR
 static const char dbl_err[] = "<DOUBLE>";
 static const char dbl_err[] = "<DOUBLE>";
@@ -355,27 +174,21 @@ static const char u_spec[] = "%nbopxXudics";
 /* u_radix[i] <-> u_spec[i+2] for unsigned entries only */
 /* u_radix[i] <-> u_spec[i+2] for unsigned entries only */
 static const char u_radix[] = "\x02\x08\x10\x10\x10\x0a";
 static const char u_radix[] = "\x02\x08\x10\x10\x10\x0a";
 
 
-int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
+int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
+			 va_list ap)
 {
 {
 	int i, cnt, lval, len;
 	int i, cnt, lval, len;
 	char *p;
 	char *p;
 	const char *fmt0;
 	const char *fmt0;
-	int buffer_mode;
 	int preci, width;
 	int preci, width;
 #define upcase i
 #define upcase i
 	int radix, dpoint /*, upcase*/;
 	int radix, dpoint /*, upcase*/;
-#if defined(__UCLIBC_HAS_LONG_LONG__)
-	char tmp[65];
-#else
-	char tmp[33];
-#endif
+	char tmp[65];				/* TODO - determing needed size from headers */
 	char flag[sizeof(spec)];
 	char flag[sizeof(spec)];
 
 
-	cnt = 0;
+	__STDIO_THREADLOCK(op);
 
 
-	/* This speeds things up a bit for line unbuffered */
-	buffer_mode = (op->mode & __MODE_BUF);
-	op->mode &= (~__MODE_BUF);
+	cnt = 0;
 
 
 	while (*fmt) {
 	while (*fmt) {
 		if (*fmt == '%') {
 		if (*fmt == '%') {
@@ -391,8 +204,6 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 			lval = 1;			/* sizeof(int) == sizeof(long) */
 			lval = 1;			/* sizeof(int) == sizeof(long) */
 #endif
 #endif
 
 
-			tmp[1] = 0;			/* set things up for %c -- better done here */
-
 			/* init flags */
 			/* init flags */
 			for (p =(char *) spec ; *p ; p++) {
 			for (p =(char *) spec ; *p ; p++) {
 				flag[p-spec] = '\0';
 				flag[p-spec] = '\0';
@@ -446,13 +257,11 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 			for (p = (char *) qual ; *p ; p++) {
 			for (p = (char *) qual ; *p ; p++) {
 				if (*p == *fmt) {
 				if (*p == *fmt) {
 					lval = p - qual;
 					lval = p - qual;
-					++fmt;
-#if defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR
+					++fmt;		/* TODO - hh */
 					if ((*p == 'l') && (*fmt == *p)) {
 					if ((*p == 'l') && (*fmt == *p)) {
 						++lval;
 						++lval;
 						++fmt;
 						++fmt;
 					}
 					}
-#endif /* defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR */
 				}
 				}
 			}
 			}
 
 
@@ -477,40 +286,20 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 				}
 				}
 				if (p-u_spec < 8) { /* unsigned conversion */
 				if (p-u_spec < 8) { /* unsigned conversion */
 					radix = u_radix[p-u_spec-2];
 					radix = u_radix[p-u_spec-2];
-					upcase = ((int)'x') - *p;
+					upcase = ((*p == 'x') ? __UIM_LOWER : __UIM_UPPER);
 					if (*p == 'p') {
 					if (*p == 'p') {
 						lval = (sizeof(char *) == sizeof(long));
 						lval = (sizeof(char *) == sizeof(long));
-						upcase = 0;
+						upcase = __UIM_LOWER;
 						flag[FLAG_HASH] = 'p';
 						flag[FLAG_HASH] = 'p';
 					}
 					}
-#if defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR
-					if (lval >= 2) {
-#if defined(__UCLIBC_HAS_LONG_LONG__)
-						p = __ulltostr(tmp + sizeof(tmp) - 1,
-									   va_arg(ap, unsigned long long),
-									   radix, upcase);
-#else
-						(void) va_arg(ap, unsigned long long);	/* cary on */
-						p = (char *) ll_err;
-#endif /* defined(__UCLIBC_HAS_LONG_LONG__) */
-					} else {
-#endif /* defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR */
-#if UINT_MAX != ULONG_MAX
-						/* sizeof(unsigned int) != sizeof(unsigned long) */
-						p = __ultostr(tmp + sizeof(tmp) - 1, (unsigned long)
-									  ((lval)
-									   ? va_arg(ap, unsigned long)
-									   : va_arg(ap, unsigned int)),
-									  radix, upcase);
-#else
-						/* sizeof(unsigned int) == sizeof(unsigned long) */
-						p = __ultostr(tmp + sizeof(tmp) - 1, (unsigned long)
-									  va_arg(ap, unsigned long),
+
+					p = _uintmaxtostr((tmp + sizeof(tmp) - 1),
+									  ((lval>1) /* TODO -- longlong/long/int/short/char */
+									   ? va_arg(ap, uintmax_t)
+									   : (uintmax_t)
+									   va_arg(ap, unsigned long)),
 									  radix, upcase);
 									  radix, upcase);
-#endif
-#if defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR
-					}
-#endif /* defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR */
+
 					flag[FLAG_PLUS] = '\0';	/* meaningless for unsigned */
 					flag[FLAG_PLUS] = '\0';	/* meaningless for unsigned */
 					if (*p != '0') { /* non-zero */
 					if (*p != '0') { /* non-zero */
 						if (flag[FLAG_HASH]) {
 						if (flag[FLAG_HASH]) {
@@ -531,31 +320,14 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 						p = "(nil)";
 						p = "(nil)";
 					}
 					}
 				} else if (p-u_spec < 10) { /* signed conversion */
 				} else if (p-u_spec < 10) { /* signed conversion */
-#if defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR
-					if (lval >= 2) {
-#if defined(__UCLIBC_HAS_LONG_LONG__)
-						p = __lltostr(tmp + sizeof(tmp) - 1,
-									  va_arg(ap, long long), 10, 0);
-#else
-						(void) va_arg(ap, long long); /* carry on */
-						p = (char *) ll_err;
-#endif /* defined(__UCLIBC_HAS_LONG_LONG__) */
-					} else {
-#endif /* defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR */
-#if INT_MAX != LONG_MAX
-						/* sizeof(int) != sizeof(long) */
-						p = __ltostr(tmp + sizeof(tmp) - 1, (long)
-									 ((lval)
-									  ? va_arg(ap, long)
-									  : va_arg(ap, int)), 10, 0);
-#else
-						/* sizeof(int) == sizeof(long) */
-						p = __ltostr(tmp + sizeof(tmp) - 1, (long)
-									 va_arg(ap, long), 10, 0);
-#endif
-#if defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR
-					}
-#endif /* defined(__UCLIBC_HAS_LONG_LONG__) || WANT_LONG_LONG_ERROR */
+
+ 					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! */
+													va_arg(ap, long))),
+									  -radix, upcase);
+
 				} else if (p-u_spec < 12) {	/* character or string */
 				} else if (p-u_spec < 12) {	/* character or string */
 					flag[FLAG_PLUS] = '\0';
 					flag[FLAG_PLUS] = '\0';
 					flag[FLAG_0_PAD] = ' ';
 					flag[FLAG_0_PAD] = ' ';
@@ -569,21 +341,44 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 						p = va_arg(ap, char *);
 						p = va_arg(ap, char *);
 						if (!p) {
 						if (!p) {
 							p = "(null)";
 							p = "(null)";
+							preci = 6;
+						} else {
+							if (preci < 0) {
+								preci = INT_MAX;
+							}
 						}
 						}
+						len = strnlen(p, preci);
+						goto print_len_set;
 					}
 					}
 #if defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR
 #if defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR
 				} else if (p-u_spec < 27) {		/* floating point */
 				} else if (p-u_spec < 27) {		/* floating point */
 #endif /* defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR */
 #endif /* defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR */
 #if defined(__UCLIBC_HAS_FLOATS__)
 #if defined(__UCLIBC_HAS_FLOATS__)
+					struct printf_info info;
 					if (preci < 0) {
 					if (preci < 0) {
 						preci = 6;
 						preci = 6;
 					}
 					}
-					cnt += __dtostr(op, 
-									(max_size > cnt ? max_size - cnt : 0),
-									(long double) ((lval > 1)
-									 ? va_arg(ap, long double)
-									 : va_arg(ap, double)),
-									flag, width,  preci, *fmt);
+					info.width = width;
+					info.prec = preci;
+					info.spec = *fmt;
+					info.pad = flag[FLAG_0_PAD];
+					info._flags = 0;
+					if (flag[FLAG_PLUS] == '+') {
+						PRINT_INFO_SET_FLAG(&info,showsign);
+					} else if (flag[FLAG_PLUS] == ' ') {
+						PRINT_INFO_SET_FLAG(&info,space);
+					}
+					if (flag[FLAG_HASH]) {
+						PRINT_INFO_SET_FLAG(&info,alt);
+					}
+					if (flag[FLAG_MINUS_LJUSTIFY]) {
+						PRINT_INFO_SET_FLAG(&info,left);
+					}
+					cnt += _dtostr(op, 
+								   ((lval > 1)
+									? va_arg(ap, long double)
+									: (long double) va_arg(ap, double)),
+								   &info);
 					goto nextfmt;
 					goto nextfmt;
 #elif WANT_FLOAT_ERROR
 #elif WANT_FLOAT_ERROR
 					(void) ((lval > 1) ? va_arg(ap, long double)
 					(void) ((lval > 1) ? va_arg(ap, long double)
@@ -597,7 +392,8 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 #endif
 #endif
 				{				/* this used to be printfield */
 				{				/* this used to be printfield */
 					/* cheaper than strlen call */
 					/* cheaper than strlen call */
-					for ( len = 0 ; p[len] ; len++ ) { }
+/*  					for ( len = 0 ; p[len] ; len++ ) { } */
+					len = strnlen(p, SIZE_MAX);
 				print_len_set:
 				print_len_set:
 					if ((*p == '-')
 					if ((*p == '-')
 #if WANT_GNU_ERRNO
 #if WANT_GNU_ERRNO
@@ -671,13 +467,8 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 							ch = *p++; /* main field */
 							ch = *p++; /* main field */
 							--len;
 							--len;
 						}
 						}
-
-						if (++cnt < max_size) {
-							putc(ch, op);
-						}
-						if ((ch == '\n') && (buffer_mode == _IOLBF)) {
-							fflush(op);
-						}
+						++cnt;
+						putc(ch, op);
 					}
 					}
 				}
 				}
 				goto nextfmt;
 				goto nextfmt;
@@ -686,28 +477,17 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 			fmt = fmt0;	/* this was an illegal format */
 			fmt = fmt0;	/* this was an illegal format */
 		}
 		}
 
 
-		charout:
-		if (++cnt < max_size) {
-			putc(*fmt, op);	/* normal char out */
-		}
-		if ((*fmt == '\n') && (buffer_mode == _IOLBF)) {
-			fflush(op);
-		}
+	charout:
+		++cnt;
+		putc(*fmt, op);	/* normal char out */
 
 
 	nextfmt:
 	nextfmt:
 		++fmt;
 		++fmt;
 	}
 	}
 
 
-	op->mode |= buffer_mode;
-	if (buffer_mode == _IOLBF) {
-		op->bufwrite = op->bufpos;
-	}
+	i = (__FERROR(op)) ? -1 : cnt;
 
 
-	if (ferror(op)) {
-		cnt = -1;
-	}
-	return (cnt);
-}
-
-#endif
+	__STDIO_THREADLOCK(op);
 
 
+	return i;
+}

+ 0 - 27
libc/stdio/perror.c

@@ -1,27 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-/*
- * Manuel Novoa III           Feb 2001
- *
- * Replaced old version that did write(2,...)'s with a version using
- * stream functions.  If the program is calling perror, it's a safe
- * bet that printf and friends are used as well.  It is also possible
- * that the calling program could buffer stderr, or reassign it.
- * Also, the old version did not conform the standards when the 
- * passed char * was either NULL or pointed to an empty string.
- */
-
-void perror(__const char *str)
-{
-	static const char perror_str[] = ": ";
-	const char *sep;
-
-	sep = perror_str;
-	if (!(str && *str)) {		/* Caller did not supply a prefix message */
-		sep += 2;				/* or passed an empty string. */
-		str = sep;
-	}
-	fprintf(stderr, "%s%s%s\n", str, sep, strerror(errno));
-}

+ 0 - 34
libc/stdio/putw.c

@@ -1,34 +0,0 @@
-/* Copyright (C) 1991, 1997, 1998 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <stdio.h>
-
-#ifdef USE_IN_LIBIO
-# include <libio/iolibio.h>
-# define fwrite(p, n, m, s) _IO_fwrite (p, n, m, s)
-#endif
-
-/* Write the word (int) W to STREAM.  */
-int
-putw (int w, FILE *stream)
-{
-  /* Is there a better way?  */
-  if (fwrite ((const void *) &w, sizeof (w), 1, stream) < 1)
-    return EOF;
-  return 0;
-}

+ 0 - 23
libc/stdio/remove.c

@@ -1,23 +0,0 @@
-/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
- * This file is part of the Linux-8086 C library and is distributed
- * under the GNU Library General Public License.
- */
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <errno.h>
-
-int remove(src)
-__const char *src;
-{
-	extern int errno;
-	int er = errno;
-	int rv = unlink(src);
-
-	if (rv < 0 && errno == EISDIR)
-		rv = rmdir(src);
-	if (rv >= 0)
-		__set_errno(er);
-	return rv;
-}
-

+ 60 - 23
libc/stdio/scanf.c

@@ -31,14 +31,24 @@
  * implementation doesn't for the "100ergs" case mentioned above.
  * implementation doesn't for the "100ergs" case mentioned above.
  */
  */
 
 
-#include <stdlib.h>
-#include <unistd.h>
+#define _GNU_SOURCE
+#include <features.h>
+#if defined(__UCLIBC__) && !defined(__USE_ISOC99)
 #define __USE_ISOC99
 #define __USE_ISOC99
+#endif
+
+#define _STDIO_UTILITY
 #include <stdio.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
 #include <ctype.h>
 #include <ctype.h>
 #include <string.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdarg.h>
 
 
+#ifdef __STDIO_THREADSAFE
+#include <pthread.h>
+#endif /* __STDIO_THREADSAFE */
+
 #ifdef L_scanf
 #ifdef L_scanf
 #ifdef __STDC__
 #ifdef __STDC__
 int scanf(const char *fmt, ...)
 int scanf(const char *fmt, ...)
@@ -59,29 +69,22 @@ va_dcl
 #endif
 #endif
 
 
 #ifdef L_sscanf
 #ifdef L_sscanf
-#ifdef __STDC__
-int sscanf(const char *sp, const char *fmt, ...)
+#if !defined(__STDIO_BUFFERS) && !defined(__STDIO_GLIBC_CUSTOM_STREAMS)
+#warning skipping sscanf since no buffering and no custom streams!
 #else
 #else
-int sscanf(sp, fmt, va_alist)
-__const char *sp;
-__const char *fmt;
-va_dcl
-#endif
-{
-	FILE string[1] = {
-		{0, (unsigned char *) ((unsigned) -1), 0, 0, (char *) ((unsigned) -1),
-		 0, -1, _IOFBF}
-	};
 
 
+int sscanf(const char *sp, const char *fmt, ...)
+{
 	va_list ptr;
 	va_list ptr;
 	int rv;
 	int rv;
 
 
-	string->bufpos = (unsigned char *) ((void *) sp);
 	va_start(ptr, fmt);
 	va_start(ptr, fmt);
-	rv = vfscanf(string, fmt, ptr);
+	rv = vsscanf(sp, fmt, ptr);
 	va_end(ptr);
 	va_end(ptr);
 	return rv;
 	return rv;
 }
 }
+
+#endif
 #endif
 #endif
 
 
 #ifdef L_fscanf
 #ifdef L_fscanf
@@ -114,16 +117,37 @@ va_list ap;
 #endif
 #endif
 
 
 #ifdef L_vsscanf
 #ifdef L_vsscanf
+#ifdef __STDIO_BUFFERS
 int vsscanf(__const char *sp, __const char *fmt, va_list ap)
 int vsscanf(__const char *sp, __const char *fmt, va_list ap)
 {
 {
-	FILE string[1] = {
-		{0, (unsigned char *) ((unsigned) -1), 0, 0, (char *) ((unsigned) -1),
-		 0, -1, _IOFBF}
-	};
+	FILE string[1];
+
+	string->filedes = -2;		/* for debugging */
+	string->modeflags = (__FLAG_NARROW|__FLAG_READONLY);
+	string->bufstart = string->bufrpos = (unsigned char *) ((void *) sp);
+	string->bufgetc = (char *) ((unsigned) -1);
 
 
-	string->bufpos = (unsigned char *) sp;
 	return vfscanf(string, fmt, ap);
 	return vfscanf(string, fmt, ap);
 }
 }
+#else  /* __STDIO_BUFFERS */
+#ifdef __STDIO_GLIBC_CUSTOM_STREAMS
+int vsscanf(__const char *sp, __const char *fmt, va_list ap)
+{
+	FILE *f;
+	int rv;
+
+	if ((f = fmemopen((char *)sp, strlen(sp), "r")) == NULL) {
+		return -1;
+	}
+	rv = vfscanf(f, fmt, ap);
+	fclose(f);
+
+	return rv;
+}
+#else  /* __STDIO_GLIBC_CUSTOM_STREAMS */
+#warning skipping vsscanf since no buffering and no custom streams!
+#endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
+#endif /* __STDIO_BUFFERS */
 #endif
 #endif
 
 
 #ifdef L_vfscanf
 #ifdef L_vfscanf
@@ -154,6 +178,7 @@ struct scan_cookie {
 	int width_flag;
 	int width_flag;
 	int ungot_char;
 	int ungot_char;
 	int ungot_flag;
 	int ungot_flag;
+	int app_ungot;
 };
 };
 
 
 #ifdef __UCLIBC_HAS_LONG_LONG__
 #ifdef __UCLIBC_HAS_LONG_LONG__
@@ -181,8 +206,11 @@ static void init_scan_cookie(struct scan_cookie *sc, FILE *fp)
 	sc->nread = 0;
 	sc->nread = 0;
 	sc->width_flag = 0;
 	sc->width_flag = 0;
 	sc->ungot_flag = 0;
 	sc->ungot_flag = 0;
+	sc->app_ungot = ((fp->modeflags & __MASK_UNGOT) ? fp->ungot[1] : 0);
 }
 }
 
 
+/* TODO -- what about literal '\0' chars in a file??? */
+
 static int scan_getc_nw(struct scan_cookie *sc)
 static int scan_getc_nw(struct scan_cookie *sc)
 {
 {
 	if (sc->ungot_flag == 0) {
 	if (sc->ungot_flag == 0) {
@@ -233,6 +261,10 @@ static void kill_scan_cookie(struct scan_cookie *sc)
 {
 {
 	if (sc->ungot_flag) {
 	if (sc->ungot_flag) {
 		ungetc(sc->ungot_char,sc->fp);
 		ungetc(sc->ungot_char,sc->fp);
+		/* Deal with distiction between user and scanf ungots. */
+		if (sc->nread == 0) {	/* Only one char was read... app ungot? */
+			sc->fp->ungot[1] = sc->app_ungot; /* restore ungot state. */
+		}
 	}
 	}
 }
 }
 
 
@@ -267,6 +299,8 @@ va_list ap;
 	unsigned char buf[MAX_DIGITS+2];
 	unsigned char buf[MAX_DIGITS+2];
 	unsigned char scanset[UCHAR_MAX + 1];
 	unsigned char scanset[UCHAR_MAX + 1];
 
 
+	__STDIO_THREADLOCK(fp);
+
 	init_scan_cookie(&sc,fp);
 	init_scan_cookie(&sc,fp);
 
 
 	fmt = (unsigned const char *) format;
 	fmt = (unsigned const char *) format;
@@ -547,7 +581,7 @@ va_list ap;
 				goto done;
 				goto done;
 			}
 			}
 			/* Unrecognized specifier! */
 			/* Unrecognized specifier! */
-			goto done;
+			goto RETURN_cnt;
 		} if (isspace(*fmt)) {	/* Consume all whitespace. */
 		} if (isspace(*fmt)) {	/* Consume all whitespace. */
 			while (isspace(scan_getc_nw(&sc)))
 			while (isspace(scan_getc_nw(&sc)))
 				{}
 				{}
@@ -567,9 +601,12 @@ va_list ap;
 	kill_scan_cookie(&sc);
 	kill_scan_cookie(&sc);
 
 
 	if ((sc.ungot_char <= 0) && (cnt == 0) && (*fmt)) {
 	if ((sc.ungot_char <= 0) && (cnt == 0) && (*fmt)) {
-		return (EOF);
+		cnt = EOF;
 	}
 	}
 
 
+ RETURN_cnt:
+	__STDIO_THREADUNLOCK(fp);
+
 	return (cnt);
 	return (cnt);
 }
 }
 
 

+ 0 - 1117
libc/stdio/stdio.c

@@ -1,1117 +0,0 @@
-/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
- * This file is part of the Linux-8086 C library and is distributed
- * under the GNU Library General Public License.
- */
-
-/* This is an implementation of the C standard IO package.
- *
- * Updates:
- * 29-Sep-2000 W. Greathouse    1. fgetc copying beyond end of buffer
- *                              2. stdout needs flushed when input requested on
- *                                 stdin.
- *                              3. bufend was set incorrectly to 4 bytes beyond
- *                                 bufin (sizeof a pointer) instead of BUFSIZ.
- *                                 This resulted in 4 byte buffers for full
- *                                 buffered stdin and stdout and an 8 byte
- *                                 buffer for the unbuffered stderr!
- */
-
-/*
- * Feb 27, 2001            Manuel Novoa III
- *
- * Most of the core functionality has been completely rewritten.
- * A number of functions have been added as well, as mandated by C89.
- *
- * An extension function "fsfopen" has been added:
- *   Open a file using an automatically (stack) or statically allocated FILE.
- *   The FILE * returned behaves just as any other FILE * with respect to the
- *   stdio functions, but be aware of the following:
- *   NOTE: The buffer used for the file is FILE's builtin 2-byte buffer, so
- *         setting a new buffer is probably advisable.
- *   NOTE: This function is primarily intended to be used for stack-allocated
- *         FILEs when uClibc stdio has no dynamic memory support.
- *         For the statically allocated case, it is probably better to increase
- *         the value of FIXED_STREAMS in stdio.c.
- *   WARNING: If allocated on the stack, make sure you call fclose before the
- *            stack memory is reclaimed!
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <malloc.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-#include <limits.h>
-
-extern off_t _uClibc_fwrite(const unsigned char *buf, off_t bytes, FILE *fp);
-extern off_t _uClibc_fread(unsigned char *buf, off_t bytes, FILE *fp);
-
-/* Used internally to actually open files */
-extern FILE *__fopen __P((__const char *__restrict __filename, int __fd,
-	                FILE *__restrict __stream, __const char *__restrict __mode,
-			int extra_modes));
-
-/* Note: This def of READING is ok since 1st ungetc puts in buf. */
-#define READING(fp) (fp->bufstart < fp->bufread)
-#define WRITING(fp) (fp->bufwrite > fp->bufstart)
-
-#define READABLE(fp) (fp->bufread != 0)
-#define WRITEABLE(fp) (fp->bufwrite != 0)
-#define EOF_OR_ERROR(fp) (fp->mode & (__MODE_EOF | __MODE_ERR))
-
-/***********************************************************************/
-/* BUILD TIME OPTIONS                                                  */
-/***********************************************************************/
-/*
- * FIXED_STREAMS must be >= 3 and FIXED_BUFFERS must be >= 2.
- * As a feature, these can be increased, although this is probably
- * only useful if DISABLE_DYNAMIC is set to 1 below.
- */
-
-#define FIXED_STREAMS 3
-#define FIXED_BUFFERS 2
-
-/*
- * As a feature, you can build uClibc with no dynamic allocation done
- * by the stdio package.  Just set DISABLE_DYNAMIC to nonzero.  Note that
- * use of asprintf, getdelim, or getline will pull malloc into the link.
- *
- * Note: You can't trust FOPEN_MAX if DISABLE_DYNAMIC != 0.
- */
-#define DISABLE_DYNAMIC 0
-
-/*
- * As a feature, you can try to allow setvbuf calls after file operations.
- * Setting FLEXIBLE_SETVBUF to nonzero will cause setvbuf to try to fflush
- * any buffered writes or sync the file position for buffered reads.  If it
- * is successful, the buffer change can then take place.
- */
-#define FLEXIBLE_SETVBUF 0
-/***********************************************************************/
-
-#if DISABLE_DYNAMIC != 0
-#undef malloc
-#undef free
-#define malloc(x) 0
-#define free(x)
-#endif
-
-extern FILE *__IO_list;			/* For fflush. */
-extern FILE *_free_file_list;
-extern char _free_buffer_index;
-extern FILE _stdio_streams[FIXED_STREAMS];
-extern unsigned char _fixed_buffers[FIXED_BUFFERS * BUFSIZ];
-
-extern unsigned char *_alloc_stdio_buffer(size_t size);
-extern void _free_stdio_buffer_of_file(FILE *fp);
-extern void _free_stdio_stream(FILE *fp);
-
-#ifdef L__alloc_stdio_buffer
-unsigned char *_alloc_stdio_buffer(size_t size)
-{
-	unsigned char *buf;
-
-	if ((size == BUFSIZ) && (_free_buffer_index < FIXED_BUFFERS)) {
-		buf = _fixed_buffers + ((unsigned int)_free_buffer_index) * BUFSIZ;
-		_free_buffer_index = *buf;
-		return buf;
-	}
-	return malloc(size);
-}
-#endif
-
-#ifdef L__free_stdio_buffer_of_file
-void _free_stdio_buffer_of_file(FILE *fp)
-{
-	unsigned char *buf;
-
-	if (!(fp->mode & __MODE_FREEBUF)) {
-		return;
-	}
-	fp->mode &= ~(__MODE_FREEBUF);
-	buf = fp->bufstart;
-
-	if ((buf >= _fixed_buffers) 
-	 && (buf < _fixed_buffers + (FIXED_BUFFERS * BUFSIZ))) {
-		*buf = _free_buffer_index;
-		_free_buffer_index = (buf - _fixed_buffers)/BUFSIZ;
-		return;
-	}
-	free(buf);
-}
-#endif
-
-#ifdef L__stdio_init
-
-#if FIXED_BUFFERS < 2
-#error FIXED_BUFFERS must be >= 2
-#endif
-
-#if FIXED_BUFFERS >= UCHAR_MAX
-#error FIXED_BUFFERS must be < UCHAR_MAX
-#endif
-
-#define bufin (_fixed_buffers)
-#define bufout (_fixed_buffers + BUFSIZ)
-#define buferr (_stdio_streams[2].unbuf) /* Stderr is unbuffered */
-
-unsigned char _fixed_buffers[FIXED_BUFFERS * BUFSIZ];
-
-#if FIXED_STREAMS < 3
-#error FIXED_STREAMS must be >= 3
-#endif
-
-FILE _stdio_streams[FIXED_STREAMS] = {
-	{bufin, bufin,      0, bufin, bufin + BUFSIZ,
-	 _stdio_streams + 1,
-	 0, _IOFBF | __MODE_FREEFIL | __MODE_FREEBUF | __MODE_TIED },
-	{bufout,    0, bufout, bufout, bufout + BUFSIZ,
-	 _stdio_streams + 2,
-	 1, _IOFBF | __MODE_FREEFIL | __MODE_FREEBUF | __MODE_TIED },
-	{buferr,    0, buferr, buferr, buferr + 1,
-	 NULL,
-	 2, _IONBF | __MODE_FREEFIL }
-};
-
-FILE *stdin = _stdio_streams + 0;
-FILE *stdout = _stdio_streams + 1;
-FILE *stderr = _stdio_streams + 2;
-
-/*
- * Note: the following forces linking of the __init_stdio function if
- * any of the stdio functions are used since they all call fflush directly
- * or indirectly.
- */
-FILE *__IO_list = _stdio_streams;			/* For fflush. */
-
-FILE *_free_file_list = 0;
-char _free_buffer_index = FIXED_BUFFERS;
-
-/*
- * __stdio_flush_buffers is automatically when exiting if stdio is used.
- * See misc/internals/__uClibc_main.c and and stdlib/atexit.c.
- */
-void __stdio_flush_buffers(void)
-{
-    FILE *fp;
-    for (fp = __IO_list; fp; fp = fp->next) {
-	if (WRITEABLE(fp)) {
-	    /* Set the underlying fd to non-block mode to ensure
-	     * that calls to _exit() and abort() will not block */
-	    int opts;
-	    opts = fcntl(fp->fd, F_GETFL);
-	    fcntl(fp->fd, F_SETFL, opts|O_NONBLOCK);
-	    fflush(fp);
-	    fcntl(fp->fd, F_SETFL, opts);
-	}
-    }
-}
-
-/*
- * __init_stdio is automatically by __uClibc_main if stdio is used.
- */
-void __init_stdio(void)
-{
-#if (FIXED_BUFFERS > 2) || (FIXED_STREAMS > 3)
-	int i;
-#endif
-#if FIXED_BUFFERS > 2
-	_free_buffer_index = 2;
-	for ( i = 2 ; i < FIXED_BUFFERS ; i++ ) {
-		_fixed_buffers[i*BUFSIZ] = i;
-	}
-#endif
-#if FIXED_STREAMS > 3
-	_free_file_list = _stdio_streams + 3;
-	for ( i = 3 ; i < FIXED_STREAMS-1 ; i++ ) {
-		_stdio_streams[i].next = _stdio_streams + i + 1;
-	}
-	_stdio_streams[i].next = 0;
-#endif
-
-#if _IOFBF != 0 || _IOLBF != 1
-#error Assumption violated -- values of _IOFBF and/or _IOLBF
-/* This asssumption is also made in _fopen. */
-#endif
-
-	/* stdout uses line buffering when connected to a tty. */
-	_stdio_streams[1].mode |= isatty(1);
-}
-#endif
-
-#ifdef L_fputc
-int fputc(int c, FILE *fp)
-{
-	unsigned char buf[1];
-
-	*buf = (unsigned char) c;
-
-	if (_uClibc_fwrite(buf, 1, fp)) {
-		return (unsigned char) c;
-	}
-	return EOF;
-}
-#endif
-
-#ifdef L_fgetc
-int fgetc(FILE *fp)
-{
-	unsigned char buf[1];
-
-	if (_uClibc_fread(buf, 1, fp)) {
-		return *buf;
-	}
-	return EOF;
-}
-#endif
-
-#ifdef L_fflush
-int fflush(FILE *fp)
-{
-	int rv;
-
-	rv = 0;
-
-	if (fp == NULL) {			/* On NULL flush the lot. */
-		for (fp = __IO_list; fp; fp = fp->next) {
-			if (WRITEABLE(fp) && fflush(fp)) {
-				rv = EOF;
-			}
-		}
-	} else if (WRITING(fp)) {	/* Output buffer contents. */
-		_uClibc_fwrite(NULL, 0, fp);
-		if (fp->mode & __MODE_ERR) {
-			rv = -1;
-		}
-	} else if (!WRITEABLE(fp)) { /* File opened read-only!!! */
-		/*
-		 * According to info, glibc returns an error when the file is opened
-		 * in read-only mode.
-		 * ANSI says behavior in this case is undefined but also says you
-		 * shouldn't flush a stream you were reading from.
-		 */
-		__set_errno(EBADF);			/* Should we set stream error indicator? */
-		rv = -1;
-	}
-
-	return rv;
-}
-#endif
-
-#ifdef L_fgets
-/* Nothing special here ... */
-char *fgets(char *s, int count, FILE *fp)
-{
-	int ch;
-	char *p;
-	
-	p = s;
-	while (count-- > 1) {		/* Guard against count arg == INT_MIN. */
-		ch = getc(fp);
-		if (ch == EOF) {
-			break;
-		}
-		*p++ = ch;
-		if (ch == '\n') {
-			break;
-		}
-	}
-	if (ferror(fp) || (s == p)) {
-		return 0;
-	}
-	*p = 0;
-	return s;
-}
-#endif
-
-#ifdef L_gets
-link_warning (gets, "the `gets' function is dangerous and should not be used.")
-char *gets(char *str) /* This is an UNSAFE function! */
-{
-	/* 
-	 * Strictly speaking, this implementation is incorrect as the number
-	 * of chars gets can read should be unlimited.  However, I can't
-	 * imagine anyone wanting to gets() into a buffer bigger than INT_MAX.
-	 *
-	 * Besides, this function is inherently unsafe and shouldn't be used.
-	 */
-	return fgets(str, INT_MAX, stdin);
-}
-#endif
-
-#ifdef L_fputs
-int fputs(const char *str, FILE *fp)
-{
-	int n;
-
-	n = strlen(str);
-
-	_uClibc_fwrite((const unsigned char *)str, n, fp);
-	if (fp->mode & __MODE_ERR) {
-		n = EOF;
-	}
-	return n;
-}
-#endif
-
-#ifdef L_puts
-int puts(const char *str)
-{
-	int n;
-
-	n = fputs(str, stdout);	/* Let next fputc handle EOF or error. */
-	if (fputc('\n', stdout) == EOF) { /* Don't use putc since we want to */
-		return EOF;				/* fflush stdout if it is line buffered. */
-	}
-	return n + 1;
-}
-#endif
-
-#ifdef L_fread
-/*
- * fread will often be used to read in large chunks of data calling read()
- * directly can be a big win in this case. Beware also fgetc calls this
- * function to fill the buffer.
- */
-size_t fread(buf, size, nelm, fp)
-void *buf;
-size_t size;
-size_t nelm;
-FILE *fp;
-{
-	unsigned char *p;
-	unsigned char *q;
-
-#warning TODO: handle possible overflow of size * nelm
-	p = (unsigned char *) buf;
-	q = p + (size * nelm);
-
-	while ((p < q) && !EOF_OR_ERROR(fp)) {
-		p += _uClibc_fread(p, q - p, fp);
-	}
-	return (p - (unsigned char *) buf)/size;
-}
-#endif
-
-#ifdef L__uClibc_fread
-off_t _uClibc_fread(unsigned char *buf, off_t bytes, FILE *fp)
-{
-	unsigned char *p;
-	off_t len;
-
-	if (!READABLE(fp)) {
-		fp->mode |= __MODE_ERR;
-	} else if (WRITING(fp)) {
-		fflush(fp);
-	} else if (fp->mode & stdout->mode & __MODE_TIED) {
-		fflush(stdout);
-	}
-	if (EOF_OR_ERROR(fp) || (bytes <= 0)) {
-		return 0;
-	}
-
-	p = (unsigned char *) buf;
-
-	if (fp->mode & __MODE_UNGOT) { /* If we had an ungetc'd char, */
-		fp->mode ^= __MODE_UNGOT; /* reset the flag and return it. */
-		*p++ = fp->ungot;
-		--bytes;
-	}
-
- FROM_BUF:
-	len = fp->bufread - fp->bufpos;
-	if (len > bytes) {			/* Enough buffered */
-		len = bytes;
-	}
-	
-	bytes -= len;
-	while (len--) {
-		*p++ = *fp->bufpos++;
-	}
-
-	if (bytes && !EOF_OR_ERROR(fp)) { /* More requested but buffer empty. */
-		if (bytes < fp->bufend - fp->bufstart) {
-			fp->bufpos = fp->bufread = fp->bufstart; /* Reset pointers. */
-			fp->bufread += _uClibc_fread(fp->bufstart,
-										 fp->bufend - fp->bufstart, fp);
-			goto FROM_BUF;
-		}
-
-		len = read(fp->fd, p, (unsigned) bytes);
-		if (len < 0) {
-			fp->mode |= __MODE_ERR;
-		} else {
-			p += len;
-			if (len == 0) {
-				fp->mode |= __MODE_EOF;
-			}
-		}
-	}
-
-	return (p - (unsigned char *)buf);
-
-}
-#endif
-
-#ifdef L_fwrite
-/*
- * Like fread, fwrite will often be used to write out large chunks of
- * data; calling write() directly can be a big win in this case.
- * 
- * But first we check to see if there's space in the buffer.
- */
-size_t fwrite(buf, size, nelm, fp)
-const void *buf;
-size_t size;
-size_t nelm;
-FILE *fp;
-{
-	off_t bytes;
-
-#warning TODO: handle possible overflow for bytes
-	bytes = size * nelm;		/* How many bytes do we want? */
-
-	bytes = _uClibc_fwrite((const unsigned char *)buf, bytes, fp);
-
-	return bytes/size;
-}
-#endif
-
-#ifdef L__uClibc_fwrite
-/*
- * If buf == NULL, fflush.
- * If buf != NULL, (fflush and) write
- * Returns number of chars written from fp buffer _OR_ from buf.
- */
-
-off_t _uClibc_fwrite(const unsigned char *buf, off_t bytes, FILE *fp)
-{
-	unsigned char *p;
-	int rv, had_newline;
-
-	/*
-	 * Fail if stream isn't writable, if we were reading and get an error
-	 * changing over to write mode (ie. can't update stream position),
-	 * or if the stream was already in an error state.
-	 */
-	if (!WRITEABLE(fp)) {		/* Fail if stream isn't writable. */
-		fp->mode |= __MODE_ERR;
-	} else if (READING(fp)) {	/* If read buffer isn't empty, */
-		fseek(fp, 0, SEEK_CUR); /* stop reading and update position. */
-	} else if (READABLE(fp)) {
-		fp->bufread = fp->bufstart;	/* Reset start of read buffer. */
-	}
-	if (EOF_OR_ERROR(fp)) {
-		return 0;
-	}
-
-	p = (unsigned char *)buf;
-	if (p && (fp->bufpos + bytes <= fp->bufend)) { /* Enough buffer space? */
-		had_newline = 0;
-		while (bytes--) {
-			if (*p == '\n') {
-				had_newline = 1;
-			}
-			*fp->bufpos++ = *p++;
-		}
-		if (fp->bufpos < fp->bufend) { /* Buffer is not full. */
-			fp->bufwrite = fp->bufend;
-			if ((fp->mode & __MODE_BUF) == _IOLBF) {
-				fp->bufwrite = fp->bufpos;
-				if (had_newline) {
-					goto FFLUSH;
-				}
-			}
-			goto DONE;
-		}
-	FFLUSH:
-		/* If we get here, either buffer is full or we need to flush anyway. */
-		buf = fp->bufpos - (p - (unsigned char *)buf);
-		p = NULL;
-	}
-	if (!p) {					/* buf == NULL means fflush */
-		p = fp->bufstart;
-		bytes = fp->bufpos - p;
-		fp->bufpos = fp->bufwrite = p;
-	} else if (fp->bufpos > fp->bufstart) {	/* If there are buffered chars, */
-		_uClibc_fwrite(NULL, 0, fp); /* write them. */
-		if (ferror(fp)) {
-			return 0;
-		}
-	}
-
-	while (bytes) {
-		if ((rv = write(fp->fd, p, bytes)) < 0) {
-			rv = 0;
-			break;
-		}
-		p += rv;
-		bytes -= rv;
-	}
-	if (bytes) {
-		fp->mode |= __MODE_ERR;
-	}
-
- DONE:
-	return (p - (unsigned char *)buf);
-}
-#endif
-
-#ifdef L_rewind
-void rewind(fp)
-FILE *fp;
-{
-	clearerr(fp);				/* Clear errors first, then seek in case */
-	fseek(fp, 0, SEEK_SET);		/* there is an error seeking. */
-}
-#endif
-
-#ifdef L_fseek
-int fseek(FILE *fp, long int offset, int ref)
-{
-#if SEEK_SET != 0 || SEEK_CUR != 1 || SEEK_END != 2
-#error Assumption violated -- values of SEEK_SET, SEEK_CUR, SEEK_END
-#endif
-
-	if ((ref < 0) || (ref > 2)) {
-		__set_errno(EINVAL);
-		return -1;
-	}
-
-	if (WRITING(fp)) {
-		fflush(fp);				/* We'll deal with errors below. */
-		/* After fflush, bufpos is at CUR. */
-	} else if (READING(fp)) {
-		if (ref == SEEK_CUR) {
-			/* Correct offset to take into account position in buffer. */
-			offset -= (fp->bufread - fp->bufpos);
-			if (fp->mode & __MODE_UNGOT) { /* If we had an ungetc'd char, */
-				--offset;			/* adjust offset (clear flag below). */
-			}
-		}
-	}
-
-	if ((fp->mode & __MODE_ERR) || 
-		(((ref != SEEK_CUR) || offset) && (lseek(fp->fd, offset, ref) < 0))) {
-		return -1;
-	}
-
-	if (READING(fp)) {
-		fp->bufpos = fp->bufread = fp->bufstart;
-	}
-	fp->mode &=	~(__MODE_EOF | __MODE_UNGOT);
-
-	return 0;
-}
-#endif
-
-#ifdef L_ftell
-long ftell(fp)
-FILE *fp;
-{
-	/* Note: can't do fflush here since it would discard any ungetc's. */
-	off_t pos;
-
-    pos = lseek(fp->fd, 0, SEEK_CUR); /* Get kernels idea of position. */
-	if (pos < 0) {
-		return -1;
-	}
-
-	if (WRITING(fp)) {
-		pos += (fp->bufpos - fp->bufstart);	/* Adjust for buffer position. */
-	} else if (READING(fp)) {
-	    pos -= (fp->bufread - fp->bufpos);	/* Adjust for buffer position. */
-		if (fp->mode & __MODE_UNGOT) {
-			--pos;
-		}
-		if (pos < 0) {			/* ungetcs at start of file? */
-			__set_errno(EIO);
-			pos = -1;
-		}
-	}
-
-	return pos;
-}
-#endif
-
-#ifdef L__fopen
-/*
- * This Fopen is all three of fopen, fdopen and freopen. The macros in
- * stdio.h show the other names.
- */
-static __inline FILE *_alloc_stdio_stream(void)
-{
-	FILE *fp;
-
-	if (_free_file_list) {
-		fp = _free_file_list;
-		_free_file_list = fp->next;
-	} else if (!(fp = malloc(sizeof(FILE)))) {
-		return 0;
-	}
-	fp->mode = __MODE_FREEFIL | _IOFBF;
-	/* Initially set to use builtin buffer of FILE structure. */
-	fp->bufstart = fp->unbuf;
-	fp->bufend = fp->unbuf + sizeof(fp->unbuf);
-	return fp;
-}
-
-FILE *__fopen(fname, fd, fp, mode, extra_modes)
-const char *fname;
-int fd;
-FILE *fp;
-const char *mode;
-int extra_modes;
-{
-	FILE *nfp;
-	unsigned char *p;
-	int open_mode;
-	int cur_mode;
-
-	nfp = fp;
-
-	/* Parse the mode string arg. */
-	switch (*mode++) {
-		case 'r':				/* read */
-			open_mode = O_RDONLY | extra_modes;
-			break;
-		case 'w':				/* write (create or truncate)*/
-			open_mode = (O_WRONLY | O_CREAT | O_TRUNC | extra_modes);
-			break;
-		case 'a':				/* write (create or append) */
-			open_mode = (O_WRONLY | O_CREAT | O_APPEND | extra_modes);
-			break;
-		default:				/* illegal mode */
-			__set_errno(EINVAL);
-			goto _fopen_ERROR;
-	}
-
-	if ((*mode == 'b')) {		/* binary mode (nop for uClibc) */
-		++mode;
-	}
-
-
-#if O_RDONLY != 0 || O_WRONLY != 1 || O_RDWR != 2
-#error Assumption violated concerning open mode constants!
-#endif
-
-	if (*mode == '+') {			/* read-write */
-		++mode;
-		open_mode &= ~(O_RDONLY | O_WRONLY);
-		open_mode |= O_RDWR;
-	}
-
-	while (*mode) {				/* ignore everything else except ... */
-		if (*mode == 'x') {		/* open exclusive -- GNU extension */
-			open_mode |= O_EXCL;
-		}
-		++mode;
-	}
-
-	if (fp == 0) {				/* We need a FILE so allocate it before */
-		if (!(nfp = _alloc_stdio_stream())) {
-			return 0;
-		}
-	}
-
-	if (fname) {				/* Open the file itself */
-		fd = open(fname, open_mode, 0666);
-	} else {					/* fdopen -- check mode is compatible. */
-#if O_ACCMODE != 3 || O_RDONLY != 0 || O_WRONLY != 1 || O_RDWR != 2
-#error Assumption violated - mode constants
-#endif
-		cur_mode = fcntl(fd, F_GETFL);
-		if (cur_mode == -1) {
-			fd = -1;
-		} else if (!(cur_mode & O_RDWR) 
-				   && ((cur_mode ^ open_mode) & O_ACCMODE)) {
-			__set_errno(EINVAL);
-			fd = -1;
-		}
-	}
-
-	if (fd < 0) {				/* Error from open or bad arg passed. */
-	_fopen_ERROR:
-		if (nfp) {
-			_free_stdio_stream(nfp);
-		}
-		return 0;
-	}
-
-	nfp->fd = fd;				/* Set FILE's fd before adding to open list. */
-
-	if (fp == 0) {				/* Not freopen so... */
-		nfp->next = __IO_list;	/* use newly created FILE and */
-		__IO_list = nfp;		/* add it to the list of open files. */
-
-		if ((p = _alloc_stdio_buffer(BUFSIZ)) != 0) {
-			nfp->bufstart = p;
-			nfp->bufend = p + BUFSIZ;
-			nfp->mode |= __MODE_FREEBUF;
-		}
-	}
-
-	/* Ok, file's ready clear the buffer and save important bits */
-	nfp->bufpos = nfp->bufstart;
-	nfp->mode |= isatty(fd);
-	nfp->bufread = nfp->bufwrite = 0;
-	if (!(open_mode & O_WRONLY)) {
-		nfp->bufread = nfp->bufstart;
-	}
-	if (open_mode & (O_WRONLY | O_RDWR)) {
-		nfp->bufwrite = nfp->bufstart;
-	}
-
-	return nfp;
-}
-#endif
-
-#ifdef L_fclose
-int fclose(fp)
-FILE *fp;
-{
-	FILE *prev;
-	FILE *ptr;
-	int rv;
-
-	rv = 0;
-	if (WRITING(fp)) {			/* If there are buffered chars to write... */
-		rv = fflush(fp);		/* write them. */
-	}
-	if (close(fp->fd)) {		/* Need to close even if fflush fails. */
-		rv = EOF;
-	}
-
-	prev = 0;					/* Remove file from open list. */
-	for (ptr = __IO_list; ptr ; ptr = ptr->next) {
-		if (ptr == fp) {
-			if (prev == 0) {
-				__IO_list = fp->next;
-			} else {
-				prev->next = fp->next;
-			}
-			break;
-		}
-		prev = ptr;
-	}
-
-	_free_stdio_stream(fp);		/* Finally free the stream if necessary. */
-
-	return rv;
-}
-#endif
-
-#ifdef L__free_stdio_stream
-/* The following is only called by fclose and _fopen. */
-void _free_stdio_stream(FILE *fp)
-{
-	_free_stdio_buffer_of_file(fp);	/* Free buffer if necessary. */
-
-	if (!(fp->mode & __MODE_FREEFIL)) {
-		return;
-	}
-
-	/* Note: we generally won't bother checking for bad pointers here. */
-	if ((fp >= _stdio_streams) && (fp < _stdio_streams + FIXED_STREAMS)) {
-		assert( (fp - _stdio_streams) % ((_stdio_streams+1) -_stdio_streams)
-				== 0 );
-		fp->next = _free_file_list;
-		_free_file_list = fp;
-		return;
-	}
-	free(fp);
-}
-#endif
-
-#ifdef L_setbuffer
-void setbuffer(FILE *fp, char *buf, size_t size)
-{
-	int mode;
-
-	mode = _IOFBF;
-	if (!buf) {
-		mode = _IONBF;
-	}
-	setvbuf(fp, buf, mode, size);
-}
-#endif
-
-#ifdef L_setvbuf
-int setvbuf(FILE *fp, char *ubuf, int mode, size_t size)
-{
-	unsigned char *buf = ubuf;
-	int allocated_buf_flag;
-
-	if ((mode < 0) || (mode > 2)) {	/* Illegal mode. */
-		return EOF;
-	}
-
-#if FLEXIBLE_SETVBUF
-	/* C89 standard requires no ops before setvbuf, but we can be flexible. */
-	/* NOTE: This will trash any chars ungetc'd!!! */
-	if (fseek(fp, 0, SEEK_CUR)) {
-		return EOF;
-	}
-#endif
-
-	/* Note: If size == 2 we could use FILE's builting buffer as well, but */
-	/* I don't think the benefit is worth the code size increase. */
-	if ((mode == _IONBF) || (size < 1)) {
-		size = 1;				/* size == 1 _REQUIRED_ for _IONBF!!! */
-		buf = fp->unbuf;
-	}
-
-	fp->mode &= ~(__MODE_BUF);	/* Clear current mode */
-	fp->mode |= mode;			/*   and set new one. */
-
-	allocated_buf_flag = 0;
-	if ((!buf) && (size != (fp->bufend - fp->bufstart))) {
-		/* No buffer supplied and requested size different from current. */
-		allocated_buf_flag = __MODE_FREEBUF;
-		if (!(buf = _alloc_stdio_buffer(size))) {
-			return EOF;			/* Keep current buffer. */
-		}
-	}
-
-	if (buf && (buf != fp->bufstart)) { /* Want different buffer. */
-		_free_stdio_buffer_of_file(fp);	/* Free the old buffer. */
-		fp->mode |= allocated_buf_flag;	/* Allocated? or FILE's builtin. */
-		fp->bufstart = buf;
-		fp->bufend = buf + size;
-		fp->bufpos = fp->bufstart;
-		if (READABLE(fp)) {
-			fp->bufread = fp->bufstart;
-		}
-		if (WRITEABLE(fp)) {
-			fp->bufwrite = fp->bufstart;
-		}
-	}
-
-	return 0;
-}
-#endif
-
-#ifdef L_setbuf
-void setbuf(FILE *fp, char *buf)
-{
-	int mode;
-
-	mode = _IOFBF;
-	if (!buf) {
-		mode = _IONBF;
-	}
-	setvbuf(fp, buf, mode, BUFSIZ);
-}
-#endif
-
-#ifdef L_setlinebuf
-void setlinebuf(FILE *fp)
-{
-	setvbuf(fp, NULL, _IOLBF, BUFSIZ);
-}
-#endif
-
-#ifdef L_ungetc
-/* 
- * NOTE: Only one character of pushback is guaranteed, although sometimes
- * it is possible to do more.  You have 1 plus as many characters of pushback
- * as have been read since that last buffer-fill.
- */
-int ungetc(c, fp)
-int c;
-FILE *fp;
-{
-	unsigned char *p;
-
-	/* If can't read or there's been an error, or c == EOF, or ungot slot
-	 * already filled, then return EOF */
-		/*
-		 * This can only happen if an fgetc triggered a read (that filled
-		 * the buffer for case 2 above) and then we ungetc 3 chars.
-		 */
-	if (!READABLE(fp) || (fp->mode & (__MODE_UNGOT | __MODE_ERR))
-		|| (c == EOF) ) {
-		return EOF;
-	}
-
-	if (WRITING(fp)) {			/* Commit any write-buffered chars. */
-		fflush(fp);
-	}
-
-	if (fp->bufpos > fp->bufstart) { /* We have space before bufpos. */
-		p = --fp->bufpos;
-	} else if (fp->bufread == fp->bufpos) { /* Buffer is empty. */
-		p = fp->bufread++;
-	} else {
-		fp->mode |= __MODE_UNGOT;
-		p = &(fp->ungot);
-	}
-	fp->mode &= ~(__MODE_EOF);	/* Clear EOF indicator. */
-
-	if (*p != (unsigned char) c) { /* Don't store if same, because could */
-		*p = (unsigned char) c;	/* be sscanf from a const string!!! */
-	}
-
-	return c;
-}
-#endif
-
-#ifdef L_fopen
-#undef fopen
-FILE *fopen(const char *__restrict filename,
-			const char *__restrict mode)
-{
-	return __fopen(filename, -1, NULL, mode, 0);
-}
-#endif
-
-#ifdef L_freopen
-FILE *freopen(__const char *__restrict filename,
-			  __const char *__restrict mode, FILE *__restrict fp)
-{
-	/* fflush file, close the old fd, and reset modes. */
-	if (WRITING(fp)) {			/* If anything in the write buffer... */
-		fflush(fp);				/* write it. */
-	}
-	close(fp->fd);				/* Close the file. */
-	fp->mode &= (__MODE_FREEFIL | __MODE_FREEBUF); /* Reset the FILE modes. */
-	fp->mode |= _IOFBF;
-
-	return __fopen(filename, -1, fp, mode, 0);
-}
-#endif
-
-#ifdef L_fsfopen
-FILE *fsfopen(__const char *__restrict filename,
-			  __const char *__restrict mode, FILE *__restrict fp)
-{
-	fp->mode = _IOFBF;
-	fp->bufstart = fp->unbuf;
-	fp->bufend = fp->unbuf + sizeof(fp->unbuf);
-
-	return __fopen(filename, -1, fp, mode, 0);
-}
-#endif
-
-#ifdef L_fdopen
-#undef fdopen
-FILE *fdopen(int fd, __const char *mode)
-{
-	return __fopen(NULL, fd, NULL, mode, 0);
-}
-#endif
-
-
-#ifdef L_getc
-#undef getc
-int getc(FILE *stream)
-{
-    return(((stream)->bufpos >= (stream)->bufread)?  fgetc(stream) :
-		(*(stream)->bufpos++));
-}
-#endif
-
-#ifdef L_putc
-#undef putc
-int putc(int c, FILE *stream)
-{
-    return(((stream)->bufpos >= (stream)->bufwrite)?  fputc((c), (stream)) :
-		(unsigned char) (*(stream)->bufpos++ = (c)) );
-}
-#endif
-
-#ifdef L_getchar
-#undef getchar
-int getchar(void)
-{
-	return getc(stdin);
-}
-#endif
-
-#ifdef L_putchar
-#undef putchar
-int putchar(int c)
-{
-	return putc(c, stdout);
-}
-#endif
-
-#ifdef L_clearerr
-#undef clearerr
-void clearerr(FILE *fp)
-{
-	fp->mode &= ~(__MODE_EOF | __MODE_ERR);
-}
-#endif
-
-#ifdef L_feof
-#undef feof
-int feof(FILE *fp)
-{
-  	return fp->mode & __MODE_EOF;
-}
-#endif
-
-#ifdef L_ferror
-#undef ferror
-int ferror(FILE *fp)
-{
-	return fp->mode & __MODE_ERR;
-}
-#endif
-
-#ifdef L_fileno
-int fileno(FILE *fp)
-{
-	return fp->fd;
-}
-#endif
-
-#ifdef L_fgetpos
-int fgetpos(FILE *fp, fpos_t *pos)
-{
-	fpos_t p;
-
-	if (!pos) {					/* NULL pointer. */
-		__set_errno(EINVAL);
-		return -1;
-	}
-
-	if ((p = ftell(fp)) < 0) {	/* ftell failed. */
-		return -1;				/* errno set by ftell. */
-	}
-
-	*pos = p;
-	return 0;
-}
-#endif
-
-#ifdef L_fsetpos
-int fsetpos(FILE *fp, __const fpos_t *pos)
-{
-	if (pos) {					/* Pointer ok. */
-		return fseek(fp, *pos, SEEK_SET);
-	}
-	__set_errno(EINVAL);				/* NULL pointer. */
-	return EOF;
-}
-#endif
-
-#ifdef L_fopen64
-#ifdef __UCLIBC_HAVE_LFS__
-#ifndef O_LARGEFILE
-#define O_LARGEFILE	0100000
-#endif
-FILE *fopen64(const char *__restrict filename,
-			const char *__restrict mode)
-{
-	return __fopen(filename, -1, NULL, mode, O_LARGEFILE);
-}
-#endif /* __UCLIBC_HAVE_LFS__ */
-#endif
-

+ 8 - 5
libc/stdlib/atexit.c

@@ -17,7 +17,7 @@
  *   Changed name of __cleanup to __uClibc_cleanup.
  *   Changed name of __cleanup to __uClibc_cleanup.
  *   Moved declaration of __uClibc_cleanup to __uClibc_main
  *   Moved declaration of __uClibc_cleanup to __uClibc_main
  *      where it is initialized with (possibly weak alias)
  *      where it is initialized with (possibly weak alias)
- *      __stdio_flush_buffers.
+ *      _stdio_term.
  *
  *
  * Jul 2001          Steve Thayer
  * Jul 2001          Steve Thayer
  * 
  * 
@@ -141,7 +141,7 @@ void __exit_handler(int status)
 #endif
 #endif
 
 
 #ifdef L_exit
 #ifdef L_exit
-extern void weak_function __stdio_flush_buffers(void);
+extern void weak_function _stdio_term(void);
 void (*__exit_cleanup) (int) = 0;
 void (*__exit_cleanup) (int) = 0;
 
 
 /*
 /*
@@ -154,9 +154,12 @@ void exit(int rv)
 		__exit_cleanup(rv);
 		__exit_cleanup(rv);
 	}
 	}
 
 
-	/* Clean up everything else */
-	if (__stdio_flush_buffers) 
-	    __stdio_flush_buffers();
+    /* If we are using stdio, try to shut it down.  At the very least,
+	 * this will attempt to commit all buffered writes.  It may also
+	 * unbuffer all writable files, or close them outright.
+	 * Check the stdio routines for details. */
+	if (_stdio_term) 
+	    _stdio_term();
 
 
 	_exit(rv);
 	_exit(rv);
 }
 }

+ 6 - 7
libc/stdlib/ptsname.c

@@ -17,6 +17,8 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
    Boston, MA 02111-1307, USA.  */
 
 
+#define _STDIO_UTILITY			/* For _int10tostr. */
+#include <stdio.h>
 #include <errno.h>
 #include <errno.h>
 #include <paths.h>
 #include <paths.h>
 #include <stdlib.h>
 #include <stdlib.h>
@@ -27,6 +29,7 @@
 #include <termios.h>
 #include <termios.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
+
 #if !defined UNIX98PTY_ONLY
 #if !defined UNIX98PTY_ONLY
 
 
 /* Check if DEV corresponds to a master pseudo terminal device.  */
 /* Check if DEV corresponds to a master pseudo terminal device.  */
@@ -55,8 +58,6 @@ extern const char _ptyname2[];
 /* Directory where we can find the slave pty nodes.  */
 /* Directory where we can find the slave pty nodes.  */
 #define _PATH_DEVPTS "/dev/pts/"
 #define _PATH_DEVPTS "/dev/pts/"
 
 
-extern char *__ultostr(char *buf, unsigned long uval, int base, int uppercase);
-
 /* Store at most BUFLEN characters of the pathname of the slave pseudo
 /* Store at most BUFLEN characters of the pathname of the slave pseudo
    terminal associated with the master FD is open on in BUF.
    terminal associated with the master FD is open on in BUF.
    Return 0 on success, otherwise an error number.  */
    Return 0 on success, otherwise an error number.  */
@@ -86,14 +87,12 @@ int ptsname_r (int fd, char *buf, size_t buflen)
 #ifdef TIOCGPTN
 #ifdef TIOCGPTN
   if (ioctl (fd, TIOCGPTN, &ptyno) == 0)
   if (ioctl (fd, TIOCGPTN, &ptyno) == 0)
     {
     {
-      /* Buffer we use to print the number in.  For a maximum size for
-         `int' of 8 bytes we never need more than 20 digits.  */
-      char numbuf[21];
+      /* Buffer we use to print the number in. */
+      char numbuf[__BUFLEN_INT10TOSTR];
       static const char devpts[] = _PATH_DEVPTS;
       static const char devpts[] = _PATH_DEVPTS;
       char *p;
       char *p;
 
 
-      numbuf[20] = '\0';
-      p = __ultostr (&numbuf[sizeof numbuf - 1], ptyno, 10, 0);
+      p = _int10tostr(&numbuf[sizeof numbuf - 1], ptyno);
 
 
       if (buflen < sizeof devpts + &numbuf[sizeof numbuf - 1] - p)
       if (buflen < sizeof devpts + &numbuf[sizeof numbuf - 1] - p)
 	{
 	{

+ 12 - 14
libc/string/strerror.c

@@ -28,26 +28,25 @@ Cambridge, MA 02139, USA.  */
  *
  *
  * Added the option WANT_ERRORLIST for low-memory applications to omit the
  * Added the option WANT_ERRORLIST for low-memory applications to omit the
  * error message strings and only output the error number.
  * error message strings and only output the error number.
+ *
+ * Manuel Novoa III       Feb 2002
+ *
+ * Change to _int10tostr and fix a bug in end-of-buf arg.
  */
  */
 
 
 #define WANT_ERRORLIST     1
 #define WANT_ERRORLIST     1
 
 
+#define _STDIO_UTILITY			/* For _int10tostr. */
 #include <stdio.h>
 #include <stdio.h>
 #include <string.h>
 #include <string.h>
 #include <errno.h>
 #include <errno.h>
 
 
-#include <limits.h>
-
-#if (INT_MAX >> 31)
-/* We're set up for 32 bit ints */
-#error need to check size allocation for static buffer 'retbuf'
-#endif
-
-extern char *__ltostr(char *buf, long uval, int base, int uppercase);
-
 #if WANT_ERRORLIST
 #if WANT_ERRORLIST
 static char retbuf[48];
 static char retbuf[48];
 #else
 #else
+#if __BUFLEN_INT10TOSTR > 12
+#error currently set up for 32 bit ints max!
+#endif
 static char retbuf[33];			/* 33 is sufficient for 32 bit ints */
 static char retbuf[33];			/* 33 is sufficient for 32 bit ints */
 #endif
 #endif
 static const char unknown_error[] = "Unknown Error: errno"; /* = */
 static const char unknown_error[] = "Unknown Error: errno"; /* = */
@@ -66,9 +65,8 @@ char *strerror(int err)
 	}
 	}
 #endif
 #endif
 
 
-	/* unknown error */
-	pos = __ltostr(retbuf + sizeof(retbuf) + 1, err, 10, 0)
-		- sizeof(unknown_error); /* leave space for the '=' */
+	/* unknown error -- leave space for the '=' */
+	pos = _int10tostr(retbuf+sizeof(retbuf)-1, err)	- sizeof(unknown_error);
 	strcpy(pos, unknown_error);
 	strcpy(pos, unknown_error);
 	*(pos + sizeof(unknown_error) - 1) = '=';
 	*(pos + sizeof(unknown_error) - 1) = '=';
 	return pos;
 	return pos;
@@ -97,8 +95,8 @@ int main(void)
 #endif
 #endif
 
 
 	p = strerror(INT_MIN);
 	p = strerror(INT_MIN);
-	j = strlen(p)+1;
-	if (j > max) {
+	j = retbuf+sizeof(retbuf) - p;
+	if ( > max) {
 	    max = j;
 	    max = j;
 	    printf("strerror.c - Test of INT_MIN: <%s>  %d\n", p, j);
 	    printf("strerror.c - Test of INT_MIN: <%s>  %d\n", p, j);
 	}
 	}

+ 15 - 13
libc/string/strsignal.c

@@ -34,22 +34,23 @@
  *
  *
  * Added the option WANT_SIGLIST for low-memory applications to omit the
  * Added the option WANT_SIGLIST for low-memory applications to omit the
  * signal message strings and only output the signal number.
  * signal message strings and only output the signal number.
+ *
+ * Manuel Novoa III       Feb 2002
+ *
+ * Change to use _int10tostr and fix a bug in end-of-buf arg.
  */
  */
 
 
 #define WANT_SIGLIST       1
 #define WANT_SIGLIST       1
+
+#define _STDIO_UTILITY			/* For _int10tostr. */
+#include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <malloc.h>
 #include <malloc.h>
 #include <signal.h>
 #include <signal.h>
-#include <limits.h>
+#ifndef __USE_GNU
 #define __USE_GNU
 #define __USE_GNU
-#include <string.h>
-
-#if (INT_MAX >> 31)
-/* We're set up for 32 bit ints */
-#error need to check size allocation for static buffer 'retbuf'
 #endif
 #endif
-
-extern char *__ltostr(char *buf, long uval, int base, int uppercase);
+#include <string.h>
 
 
 /********************** Function strsignal ************************************/
 /********************** Function strsignal ************************************/
 #ifdef L_strsignal
 #ifdef L_strsignal
@@ -96,6 +97,10 @@ const char *const sys_siglist[] = {
 
 
 #define NUM_KNOWN_SIGNALS    32
 #define NUM_KNOWN_SIGNALS    32
 
 
+#if __BUFLEN_INT10TOSTR > 12
+#error currently set up for 32 bit ints max!
+#endif
+
 static char retbuf[28];			/* 28 is sufficient for 32 bit ints */
 static char retbuf[28];			/* 28 is sufficient for 32 bit ints */
 static const char unknown_signal[] = "Unknown Signal:";
 static const char unknown_signal[] = "Unknown Signal:";
 
 
@@ -112,8 +117,7 @@ char *strsignal(int sig)
 	}
 	}
 #endif
 #endif
 
 
-	pos = __ltostr(retbuf + sizeof(unknown_signal) + 1, sig, 10, 0)
-		- sizeof(unknown_signal);
+	pos = _int10tostr(retbuf+sizeof(retbuf)-1, sig) - sizeof(unknown_signal);
 	strcpy(pos, unknown_signal);
 	strcpy(pos, unknown_signal);
 	*(pos + sizeof(unknown_signal) - 1) = ' ';
 	*(pos + sizeof(unknown_signal) - 1) = ' ';
 	return pos;
 	return pos;
@@ -123,8 +127,6 @@ char *strsignal(int sig)
 /********************** Function psignal ************************************/
 /********************** Function psignal ************************************/
 #ifdef L_psignal
 #ifdef L_psignal
 
 
-#include <stdio.h>
-
 void psignal(int sig, const char *s)
 void psignal(int sig, const char *s)
 {
 {
 	fprintf(stderr, "%s: %s\n", s, strsignal(sig));
 	fprintf(stderr, "%s: %s\n", s, strsignal(sig));
@@ -161,7 +163,7 @@ int main(void)
 #endif
 #endif
 
 
 	p = strsignal(INT_MIN);
 	p = strsignal(INT_MIN);
-	j = strlen(p)+1;
+	j = retbuf+sizeof(retbuf) - p;
 	if (j > max) max = j;
 	if (j > max) max = j;
 	/*printf("strsignal.c - Test of INT_MIN: <%s>  %d\n", p, j);*/
 	/*printf("strsignal.c - Test of INT_MIN: <%s>  %d\n", p, j);*/
 
 

+ 494 - 0
libc/sysdeps/linux/common/bits/uClibc_stdio.h

@@ -0,0 +1,494 @@
+/*  Copyright (C) 2002     Manuel Novoa III
+ *  Header for my stdio library for linux and (soon) elks.
+ *
+ *  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 _STDIO_H
+#error Always include <stdio.h> rather than <bits/uClibc_stdio.h>
+#endif
+
+/**********************************************************************/
+#ifdef __UCLIBC__
+
+#ifdef __UCLIBC_HAS_THREADS__
+#define __STDIO_THREADSAFE
+#endif
+
+#ifdef __UCLIBC_HAVE_LFS__
+#define __STDIO_LARGE_FILES
+#endif /* __UCLIBC_HAVE_LFS__ */
+
+/* Make sure defines related to large files are consistent. */
+#ifdef _LIBC
+
+#ifdef __UCLIBC_HAVE_LFS__
+#undef __USE_LARGEFILE
+#undef __USE_LARGEFILE64
+#undef __USE_FILE_OFFSET64
+/* if we're actually building uClibc with large file support, only define... */
+#define __USE_LARGEFILE64	1
+#endif /* __UCLIBC_HAVE_LFS__ */
+
+#else  /* not _LIBC */
+
+#ifndef __UCLIBC_HAVE_LFS__
+#if defined(__LARGEFILE64_SOURCE) || defined(__USE_LARGEFILE64) \
+    || defined(__USE_FILE_OFFSET64)
+#error Sorry... uClibc was built without large file support!
+#endif
+#endif /* __UCLIBC_HAVE_LFS__ */
+
+#endif /* _LIBC */
+
+#endif /* __UCLIBC__ */
+/**********************************************************************/
+/* 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 */
+#endif
+
+#define __STDIO_BUFFERS
+#define __STDIO_GETC_MACRO
+#define __STDIO_PUTC_MACRO
+
+/* For uClibc, these are currently handled above. */
+/*  #define __STDIO_LARGE_FILES */
+#define __STDIO_THREADSAFE
+
+/* L mode extension for fopen. */
+#define __STDIO_FOPEN_LARGEFILE_MODE
+
+/* size of builtin buf -- only tested with 0 */
+#define _STDIO_BUILTIN_BUF_SIZE		0
+
+/* TODO - enable features based on __STDIO_GLIBC_FEATURES */
+
+/*  #define __STDIO_GLIBC_FEATURES */
+#define __STDIO_AUTO_RW_TRANSITION
+#define __STDIO_FOPEN_EXCLUSIVE_MODE
+#define __STDIO_PRINTF_M_SPEC
+#define __STDIO_GLIBC_CUSTOM_STREAMS
+
+
+/* ANSI/ISO mandate at least 256. */
+#define _STDIO_BUFSIZ			256
+
+/* 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
+
+/* TODO -- where should this go? */
+#ifndef O_LARGEFILE
+#define O_LARGEFILE	0100000
+#endif
+
+/**********************************************************************/
+
+/* These are consistency checks on the different options */
+
+#ifndef __STDIO_BUFFERS
+#undef __STDIO_GETC_MACRO
+#undef __STDIO_PUTC_MACRO
+#endif
+
+#ifdef __BCC__
+#undef __STDIO_LARGE_FILES
+#endif
+
+#ifndef __STDIO_LARGE_FILES
+#undef __STDIO_FOPEN_LARGEFILE_MODE
+#endif
+
+/**********************************************************************/
+
+#ifdef __STDIO_THREADSAFE
+/* Need this for pthread_mutex_t. */
+#include <bits/pthreadtypes.h>
+
+#define __STDIO_THREADLOCK(STREAM) \
+	if ((STREAM)->user_locking == 0) { \
+		pthread_mutex_lock(&(STREAM)->lock); \
+	}
+
+#define __STDIO_THREADUNLOCK(STREAM) \
+	if ((STREAM)->user_locking == 0) { \
+		pthread_mutex_unlock(&(STREAM)->lock); \
+	}
+
+#define __STDIO_THREADTRYLOCK(STREAM) \
+	if ((STREAM)->user_locking == 0) { \
+		pthread_mutex_trylock(&(STREAM)->lock); \
+	}
+
+#else  /* __STDIO_THREADSAFE */
+
+#define __STDIO_THREADLOCK(STREAM)
+#define __STDIO_THREADUNLOCK(STREAM)
+#define __STDIO_THREADTRYLOCK(STREAM)
+
+#endif /* __STDIO_THREADSAFE */
+
+/* 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_IOFBF 0	/* Fully buffered.  */
+#define _STDIO_IOLBF 1	/* Line buffered.  */
+#define _STDIO_IONBF 2	/* No buffering.  */
+
+typedef struct {
+	__off_t __pos;
+/*    __mbstate_t __state; */
+} __stdio_fpos_t;
+
+typedef struct {
+	__off64_t __pos;
+/*    __mbstate_t __state; */
+} __stdio_fpos64_t;
+
+
+/**********************************************************************/
+#ifdef __STDIO_LARGE_FILES
+typedef __off64_t __offmax_t;	/* TODO -- rename this? */
+#else
+typedef __off_t __offmax_t;		/* TODO -- rename this? */
+#endif
+
+/**********************************************************************/
+
+#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);
+/* 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 struct {
+	__io_read_fn *read;
+	__io_write_fn *write;
+	__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
+ */
+
+#ifdef __UCLIBC__
+#define __stdio_file_struct _UC_FILE
+#endif
+
+struct __stdio_file_struct {
+	unsigned short modeflags;
+	/* There could be a hole here, but modeflags is used most.*/
+#ifdef __STDIO_WIDE
+	unsigned char ungot_width[2];
+	__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 __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 */
+#ifdef __STDIO_GETC_MACRO
+	unsigned char *bufgetc;		/* 1 past last readable by getc */
+#endif /* __STDIO_GETC_MACRO */
+#ifdef __STDIO_PUTC_MACRO
+	unsigned char *bufputc;		/* 1 past last writeable by putc */
+#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_THREADSAFE
+	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];
+#endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */
+};
+
+
+/***********************************************************************/
+
+#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 __FLAG_FBF          0		/* convenience value */
+#define __FLAG_LBF          0x0100
+#define __FLAG_NBF          0x0200
+#define __MASK_BUFMODE      0x0300
+
+#define __FLAG_APPEND       0x0400
+#define __FLAG_WIDE			0x0800
+
+#define __FLAG_READING		0x1000
+#define __FLAG_WRITING		0x2000
+
+#define __FLAG_FREEBUF		0x4000	/* free buffer after use */
+#define __FLAG_LARGEFILE    0x8000
+
+/**********************************************************************/
+
+#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 */
+
+/**********************************************************************/
+
+/* 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)
+
+#define __FEOF_OR_FERROR(stream) \
+	((stream)->modeflags & (__FLAG_EOF|__FLAG_ERROR))
+
+
+/* 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)->bufrpos < (stream)->bufgetc) \
+							? (*(stream)->bufrpos++) \
+							: 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) \
+							: fputc_unlocked((c),(stream)) )
+#else  /* __STDIO_PUTC_MACRO */
+#define __PUTC(c, stream)	fputc_unlocked(c, stream);
+#endif /* __STDIO_PUTC_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
+
+#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
+
+/**********************************************************************
+ * PROTOTYPES OF INTERNAL FUNCTIONS
+ **********************************************************************/
+
+extern FILE *_stdio_openlist;
+
+#ifdef __STDIO_THREADSAFE
+extern pthread_mutex_t _stdio_openlist_lock;
+extern void __stdio_init_mutex(pthread_mutex_t *m);
+#endif
+
+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);
+
+extern FILE *_stdio_fopen(const char * __restrict filename,
+							const char * __restrict mode,
+							FILE * __restrict stream, int filedes);
+
+extern FILE *_stdio_fsfopen(const char * __restrict filename,
+							const char * __restrict mode,
+							register FILE * __restrict stream);
+
+extern void _stdio_init(void);
+extern void _stdio_term(void);
+
+#ifndef NDEBUG
+extern void __stdio_validate_FILE(FILE *stream);
+#else
+#define __stdio_validate_FILE(stream)		((void)0)
+#endif
+
+/**********************************************************************
+ * UTILITY functions
+ **********************************************************************/
+#ifdef _STDIO_UTILITY
+
+#include <features.h>
+#include <limits.h>
+#include <stdint.h>
+
+#if UINTMAX_MAX <= 4294967295UL
+#define __UIM_BUFLEN			12 /* 10 digits + 1 nul + 1 sign */
+#elif UINTMAX_MAX <= 18446744073709551615ULL
+#define __UIM_BUFLEN			22 /* 20 digits + 1 nul + 1 sign */
+#else
+#error unknown number of digits for intmax_t!
+#endif
+
+#ifdef ULLONG_MAX				/* --------------- */
+#if ULLONG_MAX <= 4294967295UL
+#define __UIM_BUFLEN_LLONG		12 /* 10 digits + 1 nul + 1 sign */
+#elif ULLONG_MAX <= 18446744073709551615ULL
+#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 ULONG_MAX <= 4294967295UL
+#define __UIM_BUFLEN_LONG		12 /* 10 digits + 1 nul + 1 sign */
+#elif ULONG_MAX <= 18446744073709551615ULL
+#define __UIM_BUFLEN_LONG		22 /* 20 digits + 1 nul + 1 sign */
+#else
+#error unknown number of digits for long!
+#endif
+
+#if UINT_MAX <= 65536U
+#define __UIM_BUFLEN_INT		7 /* 10 digits + 1 nul + 1 sign */
+#elif UINT_MAX <= 4294967295UL
+#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_LOWER = 'a' - 10,
+	__UIM_UPPER = 'A' - 10,
+} __UIM_CASE;
+
+/* 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, ...);
+
+/* 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 /* _STDIO_UTILITY */
+/**********************************************************************/
+/* uClibc translations */
+/**********************************************************************/
+
+/* TODO: note done above..  typedef struct __stdio_file_struct _UC_FILE; */
+typedef __stdio_fpos_t		_UC_fpos_t;
+typedef __stdio_fpos64_t	_UC_fpos64_t;
+
+#define _UC_IOFBF		_STDIO_IOFBF /* Fully buffered.  */
+#define _UC_IOLBF 		_STDIO_IOLBF /* Line buffered.  */
+#define _UC_IONBF 		_STDIO_IONBF /* No buffering.  */
+
+#define _UC_BUFSIZ		_STDIO_BUFSIZ

+ 10 - 37
libpthread/linuxthreads/lockfile.c

@@ -17,72 +17,45 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
    Boston, MA 02111-1307, USA.  */
 
 
-#include <bits/libc-lock.h>
+/*  #include <bits/libc-lock.h> */
 #include <stdio.h>
 #include <stdio.h>
 #include <pthread.h>
 #include <pthread.h>
 
 
-#ifdef USE_IN_LIBIO
-#include "../libio/libioP.h"
-#endif
-
 void
 void
 __flockfile (FILE *stream)
 __flockfile (FILE *stream)
 {
 {
-#ifdef USE_IN_LIBIO
-  __pthread_mutex_lock (stream->_lock);
-#else
-#endif
+  pthread_mutex_lock(&stream->lock);
 }
 }
-#ifdef USE_IN_LIBIO
-#undef _IO_flockfile
-strong_alias (__flockfile, _IO_flockfile)
-#endif
 weak_alias (__flockfile, flockfile);
 weak_alias (__flockfile, flockfile);
 
 
 
 
 void
 void
 __funlockfile (FILE *stream)
 __funlockfile (FILE *stream)
 {
 {
-#ifdef USE_IN_LIBIO
-  __pthread_mutex_unlock (stream->_lock);
-#else
-#endif
+  pthread_mutex_unlock(&stream->lock);
 }
 }
-#ifdef USE_IN_LIBIO
-#undef _IO_funlockfile
-strong_alias (__funlockfile, _IO_funlockfile)
-#endif
 weak_alias (__funlockfile, funlockfile);
 weak_alias (__funlockfile, funlockfile);
 
 
 
 
 int
 int
 __ftrylockfile (FILE *stream)
 __ftrylockfile (FILE *stream)
 {
 {
-#ifdef USE_IN_LIBIO
-  return __pthread_mutex_trylock (stream->_lock);
-#else
-  return 0;
-#endif
+  return pthread_mutex_trylock(&stream->lock);
 }
 }
-#ifdef USE_IN_LIBIO
-strong_alias (__ftrylockfile, _IO_ftrylockfile)
-#endif
 weak_alias (__ftrylockfile, ftrylockfile);
 weak_alias (__ftrylockfile, ftrylockfile);
 
 
 
 
 void
 void
 __fresetlockfiles (void)
 __fresetlockfiles (void)
 {
 {
-#ifdef USE_IN_LIBIO
-  _IO_FILE *fp;
+  FILE *fp;
   pthread_mutexattr_t attr;
   pthread_mutexattr_t attr;
 
 
-  __pthread_mutexattr_init (&attr);
-  __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+  pthread_mutexattr_init(&attr);
+  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
 
 
-  for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
-    __pthread_mutex_init (fp->_lock, &attr);
+  for (fp = _stdio_openlist; fp != NULL; fp = fp->nextopen)
+    pthread_mutex_init(&fp->lock, &attr);
 
 
-  __pthread_mutexattr_destroy (&attr);
-#endif
+  pthread_mutexattr_destroy(&attr);
 }
 }