Explorar el Código

stdio mostly rewritten... passes lots of tests now.
printf now supports long double, plus some bug fixes.

Manuel Novoa III hace 23 años
padre
commit
82dd793fd0
Se han modificado 6 ficheros con 487 adiciones y 421 borrados
  1. 34 19
      include/stdio.h
  2. 11 15
      libc/misc/internals/dtostr.c
  3. 3 3
      libc/stdio/Makefile
  4. 28 29
      libc/stdio/printf.c
  5. 6 6
      libc/stdio/scanf.c
  6. 405 349
      libc/stdio/stdio.c

+ 34 - 19
include/stdio.h

@@ -35,17 +35,17 @@ __BEGIN_DECLS
 struct __stdio_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; /* highest address writable by macro */
+  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 __stdio_file * next;
 
   int fd; /* the file descriptor associated with the stream */
-  int mode;
-
-  struct __stdio_file * next;
 
-  char unbuf[8];	   /* The buffer for 'unbuffered' streams */
+  unsigned char mode;
+  unsigned char ungot;
+  char unbuf[2];	   /* The buffer for 'unbuffered' streams */
 };
 
 typedef struct __stdio_file FILE;
@@ -65,17 +65,13 @@ typedef struct __stdio_file FILE;
 #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 with malloc, can free */
-#define __MODE_FREEFIL	0x08	/* FILE allocated with malloc, can free */
-#define __MODE_READ	0x10	/* Opened in read only */
-#define __MODE_WRITE	0x20	/* Opened in write only */
-#define __MODE_RDWR	0x30	/* Opened in read/write */
-#define __MODE_READING	0x40	/* Buffer has pending read data */
-#define __MODE_WRITING	0x80	/* Buffer has pending write data */
-#define __MODE_EOF	0x100	/* EOF status */
-#define __MODE_ERR	0x200	/* Error status */
-#define __MODE_UNGOT	0x400	/* Buffer has been polluted by ungetc */
+#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 */
 
 /* The possibilities for the third argument to `fseek'.
    These values should not be changed.  */
@@ -157,7 +153,26 @@ extern FILE *fopen __P ((__const char *__restrict __filename,
 extern FILE *freopen __P ((__const char *__restrict __filename,
 			   __const char *__restrict __mode,
 			   FILE *__restrict __stream));
-#define freopen(__file, __mode, __fp) __fopen((__file), -1, (__fp), (__mode))
+
+#ifdef __USE_MISC
+/*
+ * 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 been built with 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!
+ */
+extern FILE *fsfopen __P ((__const char *__restrict __filename,
+			   __const char *__restrict __mode,
+			   FILE *__restrict __stream));
+#endif
+
 
 #ifdef __USE_LARGEFILE64
 extern FILE *fopen64 __P ((__const char *__restrict __filename,
@@ -390,8 +405,8 @@ extern int ferror __P ((FILE *__stream));
 /* Macro versions of the 3 previous functions */
 /* If fp is NULL... */
 #define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR), (void)0)
-#define feof(fp)   	(((fp)->mode&__MODE_EOF) != 0)
-#define ferror(fp)	(((fp)->mode&__MODE_ERR) != 0)
+#define feof(fp)   	((fp)->mode&__MODE_EOF)
+#define ferror(fp)	((fp)->mode&__MODE_ERR)
 
 /* Print a message describing the meaning of the value of errno.  */
 extern void perror __P ((__const char *__s));

+ 11 - 15
libc/misc/internals/dtostr.c

@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2000, 2001 Manuel Novoa III
  *
- * Function:  int __dtostr(FILE * fp, size_t size, double x, 
+ * 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
@@ -32,17 +32,18 @@
 
 /*
  * Configuration for the scaling power table.  Ignoring denormals, you
- * should have 2**EXP_TABLE_SIZE >= MAX_DBL_EXP >= 2**(EXP_TABLE_SIZE-1).
+ * 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       9
+#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.
- * 17 digits suffices to uniquely determine a double on i386.
+ * (20) 17 digits suffices to uniquely determine a (long) double on i386.
  */
-#define MAX_DIGITS          17
+#define MAX_DIGITS          20
 
 /*
  * Set this to the smallest integer type capable of storing a pointer.
@@ -56,11 +57,7 @@
  * caused by the FPU that strtod had.  If it causes problems, call the function
  * and compile zoicheck.c with -ffloat-store.
  */
-#if 1
 #define _zero_or_inf_check(x) ( x == (x/4) )
-#else
-extern int _zero_or_inf_check(double x);
-#endif
 
 /*
  * Fairly portable nan check.  Bitwise for i386 generated larger code.
@@ -103,10 +100,9 @@ enum {
 
 /*
  * Only bother checking if this is too small.
- * Throw in some play for denormals ( roughly O(-324) vs O(-307) on i386 ).
  */
 
-#if (3+DBL_DIG-DBL_MIN_10_EXP)/2 > EXP_TABLE_MAX
+#if LDBL_MAX_10_EXP/2 > EXP_TABLE_MAX
 #error larger EXP_TABLE_SIZE needed
 #endif
 
@@ -147,11 +143,11 @@ static const char *fmts[] = {
 
 /*****************************************************************************/
 
-int __dtostr(FILE * fp, size_t size, double x, 
+int __dtostr(FILE * fp, size_t size, long double x, 
 			 char flag[], int width, int preci, char mode)
 {
-	double exp_table[EXP_TABLE_SIZE];
-	double p10;
+	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;
@@ -290,7 +286,7 @@ int __dtostr(FILE * fp, size_t size, double x,
 	}
 	*++e = 0;					/* ending nul char */
 
-	if ((mode == 'g') && ((o_exp >= -4) && (o_exp < round))) {
+	if ((mode == 'g') && ((o_exp >= -4) && (o_exp <= round))) {
 		mode = 'f';
 	}
 

+ 3 - 3
libc/stdio/Makefile

@@ -36,13 +36,13 @@ endif
 
 MSRC=stdio.c
 MOBJ=_stdio_init.o \
-     _alloc_stdio_buffer.o _free_stdio_buffer.o _free_stdio_stream.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 \
+     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
+     fread.o fwrite.o getchar.o putchar.o _uClibc_fwrite.o _uClibc_fread.o
 
 MSRC2=printf.c
 MOBJ2=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o snprintf.o \

+ 28 - 29
libc/stdio/printf.c

@@ -267,7 +267,7 @@ int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap)
 	 */
 	f.bufwrite = (char *) ((unsigned) -1);
 	f.bufpos = sp;
-	f.mode = _IOFBF | __MODE_WRITE;
+	f.mode = _IOFBF;
 
 	rv = vfnprintf(&f, size, fmt, ap);
 	if (size) {					/* If this is going to a buffer, */
@@ -283,25 +283,17 @@ int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap)
  */
 extern int vdprintf(int fd, const char *fmt, va_list ap)
 {
-#if 0
-	FILE f = {f.unbuf, f.unbuf, f.unbuf, f.unbuf, f.unbuf + sizeof(f.unbuf),
-			  fd, _IONBF | __MODE_WRITE};
-
-	assert(fd >= 0);			/* fd==0 may no longer be stdin */
-
-	return vfnprintf(&f, -1, fmt, ap);
-#else
 	char buf[BUFSIZ];
-	FILE f = {buf, buf, buf, buf, buf + sizeof(buf),
-			  fd, _IOFBF | __MODE_WRITE};
+	FILE f = {buf, 0, buf+sizeof(buf), buf, buf+sizeof(buf), 0, fd, _IOFBF};
 	int rv;
 
-	assert(fd >= 0);			/* fd==0 may no longer be stdin */
-
 	rv = vfnprintf(&f, -1, fmt, ap);
-	fflush(&f);
+
+	if (fflush(&f)) {
+		return -1;
+	}
+
 	return rv;
-#endif
 }
 #endif
 
@@ -311,7 +303,7 @@ 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, double x,
+extern int __dtostr(FILE * fp, size_t size, long double x,
 				  char flag[], int width, int preci, char mode);
 
 enum {
@@ -353,7 +345,7 @@ 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 i, cnt = 0, lval;
+	int i, cnt, lval;
 	char *p;
 	const char *fmt0;
 	int buffer_mode;
@@ -367,7 +359,9 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 #endif
 	char flag[sizeof(spec)];
 
-	/* This speeds things up a bit for unbuffered */
+	cnt = 0;
+
+	/* This speeds things up a bit for line unbuffered */
 	buffer_mode = (op->mode & __MODE_BUF);
 	op->mode &= (~__MODE_BUF);
 
@@ -375,9 +369,6 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 		if (*fmt == '%') {
 			fmt0 = fmt;			/* save our position in case of bad format */
 			++fmt;
-			if (buffer_mode == _IONBF) {
-				fflush(op);
-			}
 			width = -1;			/* min field width */
 			preci = -5;			/* max string width or mininum digits */
 			radix = 10;			/* number base */
@@ -511,7 +502,7 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 					if (flag[FLAG_HASH] && (*p != '0')) { /* non-zero */
 						if (radix == 8) {
 							*--p = '0';	/* add leadding zero */
-						} else { /* either 2 or 16 */
+						} else if (radix != 10) { /* either 2 or 16 */
 							flag[FLAG_PLUS] = '0';
 							*--p = 'b';
 							if (radix == 16) {
@@ -556,6 +547,9 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 						*p = va_arg(ap, int);
 					} else {	/* string */
 						p = va_arg(ap, char *);
+						if (!p) {
+							p = "(null)";
+						}
 					}
 #if WANT_DOUBLE || WANT_DOUBLE_ERROR
 				} else if (p-u_spec < 27) {		/* floating point */
@@ -564,11 +558,15 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 					if (preci < 0) {
 						preci = 6;
 					}
-					cnt += __dtostr(op, max_size, va_arg(ap, double),
+					cnt += __dtostr(op, max_size,
+									(long double) ((lval > 1)
+									 ? va_arg(ap, long double)
+									 : va_arg(ap, double)),
 									flag, width,  preci, *fmt);
 					goto nextfmt;
 #elif WANT_DOUBLE_ERROR
-					(void) va_arg(ap,double); /* carry on */
+					(void) ((lval > 1) ? va_arg(ap, long double)
+							: va_arg(ap, double)); /* carry on */
 					p = (char *) dbl_err;
 #endif /* WANT_DOUBLE */
 				}
@@ -604,7 +602,11 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 						|| (*fmt == 'm')
 #endif
 						) {
-							len = preci;
+							if (len > preci) {
+								len = preci;
+							} else {
+								preci = len;
+							}
 						}
 						preci -= len;
 						if (preci < 0) {
@@ -678,11 +680,8 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap)
 	}
 
 	op->mode |= buffer_mode;
-	if (buffer_mode == _IONBF) {
-		fflush(op);
-	}
 	if (buffer_mode == _IOLBF) {
-		op->bufwrite = op->bufstart;
+		op->bufwrite = op->bufpos;
 	}
 
 	if (ferror(op)) {

+ 6 - 6
libc/stdio/scanf.c

@@ -35,15 +35,15 @@ va_dcl
 #endif
 {
 	FILE string[1] = {
-		{0, (char *) (unsigned) -1, 0, 0, (char *) (unsigned) -1, -1,
-		 _IOFBF | __MODE_READ}
+		{0, (unsigned char *) ((unsigned) -1), 0, 0, (char *) ((unsigned) -1),
+		 0, -1, _IOFBF}
 	};
 
 	va_list ptr;
 	int rv;
 
-	va_start(ptr, fmt);
 	string->bufpos = (unsigned char *) ((void *) sp);
+	va_start(ptr, fmt);
 	rv = vfscanf(string, fmt, ptr);
 	va_end(ptr);
 	return rv;
@@ -83,11 +83,11 @@ va_list ap;
 int vsscanf(__const char *sp, __const char *fmt, va_list ap)
 {
 	FILE string[1] = {
-		{0, (char *) (unsigned) -1, 0, 0, (char *) (unsigned) -1, -1,
-		 _IOFBF | __MODE_READ}
+		{0, (unsigned char *) ((unsigned) -1), 0, 0, (char *) ((unsigned) -1),
+		 0, -1, _IOFBF}
 	};
 
-	string->bufpos = (unsigned char *) ((void *) sp);
+	string->bufpos = (unsigned char *) sp;
 	return vfscanf(string, fmt, ap);
 }
 #endif

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 405 - 349
libc/stdio/stdio.c


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio