Tue Dec 5 02:27:32 1995 Ulrich Drepper <drepper@gnu.ai.mit.edu>

* libio/Makefile [routines]: Remove iofscanf, add iopopen, pclose.

	* libio/iofscanf.c: Remove file.

	* libio/iogetdelim.c (_IO_getdelim): Correct stupid bug at string
        termination.

	* libio/iopopen.c: New file from GNU libio.

	* libio/memstream.c: Fixed bug in fclose handling.  Instead of
	providing a close callback we need a finish callback.

	* libio/pclose.c: New file.  Derived from popen.c in GNU libio.

	* posix/gnu/types.h: Fixed typo.

	* stdio-common/errnobug.c: fputs returns EOF in error case.  Do
	not test for != 0.

	* stdio-common/printf-parse.h (parse_one_spec): Do not force
	padding with ' ' if precision is given.  Fix by HJ Lu.

	* stdio-common/printf_fp.c: Fix comment.

	* stdio-common/tfformat.c, stdio-common/tiformat.c,
	stdio-common/tstdiomisc.c: New files from GNU libio test suite.

	* stdio-common/tstgetln.c: Provide ssize_t type when testing
	libio.

	* stdio-common/vfprintf.c (outchar): Use PUTC instead of putc.
	(vfprintf): Cleasr args_type array before using it.
	When printing 0 as an integer with precision 0 nothing must be
	written for the number.
	Based on patch by HJ Lu.

	* stdio-common/vfscanf.c: Remove fixed input buffer.  Now we
        have a dynamically extended buffer.

	* stdlib/strtod.c: Merge with version in Linux libc.  This fixes
        some bugs with handling of very small numbers and has different
        solution for formaer patches.

	* sysdeps/i386/i586/add_n.S, sysdeps/i386/i586/sub_n.S: Rename
        macros r1 and r2 to t1, and t2 resp.  This is necessary because
        glibc headers also define r1.
Tue Dec  5 02:27:32 1995  Ulrich Drepper  <drepper@gnu.ai.mit.edu>

	* libio/Makefile [routines]: Remove iofscanf, add iopopen, pclose.

	* libio/iofscanf.c: Remove file.

	* libio/iogetdelim.c (_IO_getdelim): Correct stupid bug at string
        termination.

	* libio/iopopen.c: New file from GNU libio.

	* libio/memstream.c: Fixed bug in fclose handling.  Instead of
	providing a close callback we need a finish callback.

	* libio/pclose.c: New file.  Derived from popen.c in GNU libio.

	* posix/gnu/types.h: Fixed typo.

	* stdio-common/errnobug.c: fputs returns EOF in error case.  Do
	not test for != 0.

	* stdio-common/printf-parse.h (parse_one_spec): Do not force
	padding with ' ' if precision is given.  Fix by HJ Lu.

	* stdio-common/printf_fp.c: Fix comment.

	* stdio-common/tfformat.c, stdio-common/tiformat.c,
	stdio-common/tstdiomisc.c: New files from GNU libio test suite.

	* stdio-common/tstgetln.c: Provide ssize_t type when testing
	libio.

	* stdio-common/vfprintf.c (outchar): Use PUTC instead of putc.
	(vfprintf): Cleasr args_type array before using it.
	When printing 0 as an integer with precision 0 nothing must be
	written for the number.
	Based on patch by HJ Lu.

	* stdio-common/vfscanf.c: Remove fixed input buffer.  Now we
        have a dynamically extended buffer.

	* stdlib/strtod.c: Merge with version in Linux libc.  This fixes
        some bugs with handling of very small numbers and has different
        solution for formaer patches.

	* sysdeps/i386/i586/add_n.S, sysdeps/i386/i586/sub_n.S: Rename
        macros r1 and r2 to t1, and t2 resp.  This is necessary because
        glibc headers also define r1.
This commit is contained in:
Roland McGrath 1995-12-05 03:35:55 +00:00
parent b5a08c5aca
commit 77a58cad3f
16 changed files with 318 additions and 250 deletions

View File

@ -1,3 +1,52 @@
Tue Dec 5 02:27:32 1995 Ulrich Drepper <drepper@gnu.ai.mit.edu>
* libio/Makefile [routines]: Remove iofscanf, add iopopen, pclose.
* libio/iofscanf.c: Remove file.
* libio/iogetdelim.c (_IO_getdelim): Correct stupid bug at string
termination.
* libio/iopopen.c: New file from GNU libio.
* libio/memstream.c: Fixed bug in fclose handling. Instead of
providing a close callback we need a finish callback.
* libio/pclose.c: New file. Derived from popen.c in GNU libio.
* posix/gnu/types.h: Fixed typo.
* stdio-common/errnobug.c: fputs returns EOF in error case. Do
not test for != 0.
* stdio-common/printf-parse.h (parse_one_spec): Do not force
padding with ' ' if precision is given. Fix by HJ Lu.
* stdio-common/printf_fp.c: Fix comment.
* stdio-common/tfformat.c, stdio-common/tiformat.c,
stdio-common/tstdiomisc.c: New files from GNU libio test suite.
* stdio-common/tstgetln.c: Provide ssize_t type when testing
libio.
* stdio-common/vfprintf.c (outchar): Use PUTC instead of putc.
(vfprintf): Cleasr args_type array before using it.
When printing 0 as an integer with precision 0 nothing must be
written for the number.
Based on patch by HJ Lu.
* stdio-common/vfscanf.c: Remove fixed input buffer. Now we
have a dynamically extended buffer.
* stdlib/strtod.c: Merge with version in Linux libc. This fixes
some bugs with handling of very small numbers and has different
solution for formaer patches.
* sysdeps/i386/i586/add_n.S, sysdeps/i386/i586/sub_n.S: Rename
macros r1 and r2 to t1, and t2 resp. This is necessary because
glibc headers also define r1.
Mon Dec 4 12:10:28 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> Mon Dec 4 12:10:28 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* stdlib/gen-mpn-copy (translations): Updated for new layout in * stdlib/gen-mpn-copy (translations): Updated for new layout in

View File

@ -25,14 +25,14 @@ headers := stdio.h libio.h
routines := \ routines := \
filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \ filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \
iofopncook iofprintf iofputs iofread iofscanf iofsetpos ioftell \ iofopncook iofprintf iofputs iofread iofsetpos ioftell \
iofwrite iogetdelim iogetline iogets iopadn ioprims ioputs \ iofwrite iogetdelim iogetline iogets iopadn iopopen ioprims ioputs \
ioseekoff ioseekpos iosetbuffer iosetvbuf iosprintf ioungetc \ ioseekoff ioseekpos iosetbuffer iosetvbuf iosprintf ioungetc \
iovsprintf iovsscanf \ iovsprintf iovsscanf \
\ \
clearerr feof ferror fgetc fileno fputc freopen fseek getc getchar \ clearerr feof ferror fgetc fileno fputc freopen fseek getc getchar \
memstream putc putchar rewind setbuf setlinebuf vasprintf vdprintf \ memstream pclose putc putchar rewind setbuf setlinebuf vasprintf \
vscanf vsnprintf \ vdprintf vscanf vsnprintf \
\ \
libc_fatal libc_fatal

View File

@ -1,50 +0,0 @@
/*
Copyright (C) 1993, 1995 Free Software Foundation
This file is part of the GNU IO Library. This library is free
software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this library; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, if you link this library with files
compiled with a GNU compiler to produce an executable, this does not cause
the resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
#include "libioP.h"
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
int
_IO_fscanf
#ifdef __STDC__
(_IO_FILE *fp, const char* format, ...)
#else
(fp, format, va_alist) _IO_FILE *fp; char *format; va_dcl
#endif
{
int ret;
va_list args;
CHECK_FILE (fp, EOF);
_IO_va_start (args, format);
ret = _IO_vfscanf (fp, format, args, NULL);
va_end (args);
return ret;
}
weak_alias (_IO_fscanf, fscanf)

View File

@ -79,11 +79,11 @@ _IO_getdelim (lineptr, n, delimiter, fp)
t = (char *) memchr ((void *) fp->_IO_read_ptr, delimiter, len); t = (char *) memchr ((void *) fp->_IO_read_ptr, delimiter, len);
if (t != NULL) if (t != NULL)
len = (t - fp->_IO_read_ptr) + 1; len = (t - fp->_IO_read_ptr) + 1;
/* make enough space for len+1 (for final NUL) bytes. */ /* Make enough space for len+1 (for final NUL) bytes. */
needed = cur_len + len + 1; needed = cur_len + len + 1;
if (needed > *n) if (needed > *n)
{ {
if (t == NULL && needed < 2 * *n) if (needed < 2 * *n)
needed = 2 * *n; /* Be generous. */ needed = 2 * *n; /* Be generous. */
*n = needed; *n = needed;
*lineptr = (char *) realloc (*lineptr, needed); *lineptr = (char *) realloc (*lineptr, needed);
@ -97,7 +97,7 @@ _IO_getdelim (lineptr, n, delimiter, fp)
break; break;
len = fp->_IO_read_end - fp->_IO_read_ptr; len = fp->_IO_read_end - fp->_IO_read_ptr;
} }
lineptr[cur_len] = '\0'; (*lineptr)[cur_len] = '\0';
return cur_len; return cur_len;
} }

View File

@ -30,13 +30,13 @@ struct _IO_FILE_memstream
static int _IO_mem_sync __P ((_IO_FILE* fp)); static int _IO_mem_sync __P ((_IO_FILE* fp));
static int _IO_mem_close __P ((_IO_FILE* fp)); static void _IO_mem_finish __P ((_IO_FILE* fp));
static const struct _IO_jump_t _IO_mem_jumps = static const struct _IO_jump_t _IO_mem_jumps =
{ {
JUMP_INIT_DUMMY, JUMP_INIT_DUMMY,
JUMP_INIT (finish, _IO_str_finish), JUMP_INIT (finish, _IO_mem_finish),
JUMP_INIT (overflow, _IO_str_overflow), JUMP_INIT (overflow, _IO_str_overflow),
JUMP_INIT (underflow, _IO_str_underflow), JUMP_INIT (underflow, _IO_str_underflow),
JUMP_INIT (uflow, _IO_default_uflow), JUMP_INIT (uflow, _IO_default_uflow),
@ -51,7 +51,7 @@ static const struct _IO_jump_t _IO_mem_jumps =
JUMP_INIT (read, _IO_default_read), JUMP_INIT (read, _IO_default_read),
JUMP_INIT (write, _IO_default_write), JUMP_INIT (write, _IO_default_write),
JUMP_INIT (seek, _IO_default_seek), JUMP_INIT (seek, _IO_default_seek),
JUMP_INIT (close, _IO_mem_close), JUMP_INIT (close, _IO_default_close),
JUMP_INIT (stat, _IO_default_stat) JUMP_INIT (stat, _IO_default_stat)
}; };
@ -79,6 +79,9 @@ open_memstream (bufloc, sizeloc)
fp->_sf._s._allocate_buffer = (_IO_alloc_type) malloc; fp->_sf._s._allocate_buffer = (_IO_alloc_type) malloc;
fp->_sf._s._free_buffer = (_IO_free_type) free; fp->_sf._s._free_buffer = (_IO_free_type) free;
fp->bufloc = bufloc;
fp->sizeloc = sizeloc;
return &fp->_sf._f; return &fp->_sf._f;
} }
@ -102,28 +105,28 @@ _IO_mem_sync (fp)
else else
*fp->_IO_write_ptr = '\0'; *fp->_IO_write_ptr = '\0';
*mp->bufloc = fp->_IO_buf_base; *mp->bufloc = fp->_IO_write_base;
*mp->sizeloc = _IO_blen (fp); *mp->sizeloc = fp->_IO_write_ptr - fp->_IO_write_base;
return 0; return 0;
} }
static int _IO_mem_close (fp) static void
_IO_mem_finish (fp)
_IO_FILE* fp; _IO_FILE* fp;
{ {
struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp; struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
int res;
res = _IO_default_close (fp); *mp->bufloc = (char *) realloc (fp->_IO_write_base,
if (res < 0) fp->_IO_write_ptr - fp->_IO_write_base + 1);
return res; if (*mp->bufloc != NULL)
{
(*mp->bufloc)[fp->_IO_write_ptr - fp->_IO_write_base] = '\0';
*mp->sizeloc = fp->_IO_write_ptr - fp->_IO_write_base;
}
*mp->bufloc = (char *) realloc (fp->_IO_buf_base, _IO_blen (fp) + 1); fp->_IO_buf_base = NULL;
if (*mp->bufloc == NULL)
return -1;
(*mp->bufloc)[_IO_blen (fp)] = '\0';
*mp->sizeloc = _IO_blen (fp);
return 0; _IO_default_finish (fp);
} }

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. /* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -13,7 +13,7 @@ Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave, not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */ Cambridge, MA 02139, USA. */
#ifndef _GNU_TYPES_H #ifndef _GNU_TYPES_H

View File

@ -39,7 +39,8 @@ distribute := _itoa.h printf-parse.h
tests := tst-printf tstscanf test_rdwr test-popen tstgetln test-fseek \ tests := tst-printf tstscanf test_rdwr test-popen tstgetln test-fseek \
temptest tst-fileno test-fwrite \ temptest tst-fileno test-fwrite \
xbug errnobug \ xbug errnobug \
bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug1 bug2 bug3 bug4 bug5 bug6 bug7 \
tfformat tiformat tstdiomisc
include ../Rules include ../Rules

View File

@ -1,5 +1,5 @@
/* Regression test for reported old bug that errno is clobbered /* Regression test for reported old bug that errno is clobbered
by the first successful output to a stream on an unseekable object. by the first successful output to a stream on an unseekable object.
Copyright (C) 1995 Free Software Foundation, Inc. Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -43,7 +43,7 @@ main (void)
} }
errno = 0; errno = 0;
if (fputs ("fnord", f)) if (fputs ("fnord", f) == EOF)
{ {
perror ("fputs"); perror ("fputs");
return 1; return 1;

View File

@ -32,7 +32,7 @@ Cambridge, MA 02139, USA. */
struct printf_spec struct printf_spec
{ {
/* Information parsed from the format spec. */ /* Information parsed from the format spec. */
struct printf_info info; struct printf_info info;
/* Pointers into the format string for the end of this format /* Pointers into the format string for the end of this format
@ -260,10 +260,6 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
else else
/* "%.?" is treated like "%.0?". */ /* "%.?" is treated like "%.0?". */
spec->info.prec = 0; spec->info.prec = 0;
/* If there was a precision specified, ignore the 0 flag and always
pad with spaces. */
spec->info.pad = ' ';
} }
/* Check for type modifiers. */ /* Check for type modifiers. */
@ -364,7 +360,7 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
break; break;
} }
if (spec->data_arg == -1 && spec->ndata_args > 0) if (spec->data_arg == -1 && spec->ndata_args > 0)
{ {
/* There are args consumed, but no positional spec. /* There are args consumed, but no positional spec.
Use the next sequential arg position. */ Use the next sequential arg position. */

View File

@ -345,7 +345,7 @@ __printf_fp (fp, info, args)
scalesize = 0; scalesize = 0;
if (exponent > 2) if (exponent > 2)
{ {
/* |FP| >= 1.0. */ /* |FP| >= 8.0. */
int scaleexpo = 0; int scaleexpo = 0;
int explog = LDBL_MAX_10_EXP_LOG; int explog = LDBL_MAX_10_EXP_LOG;
int exp10 = 0; int exp10 = 0;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1992 Free Software Foundation, Inc. /* Copyright (C) 1992, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -19,6 +19,10 @@ Cambridge, MA 02139, USA. */
#include <ansidecl.h> #include <ansidecl.h>
#include <stdio.h> #include <stdio.h>
#ifdef USE_IN_LIBIO
# define ssize_t _IO_ssize_t
#endif
int int
DEFUN_VOID(main) DEFUN_VOID(main)
{ {

View File

@ -96,7 +96,7 @@ ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
do \ do \
{ \ { \
register const int outc = (x); \ register const int outc = (x); \
if (putc (outc, s) == EOF) \ if (PUTC (outc, s) == EOF) \
return -1; \ return -1; \
else \ else \
++done; \ ++done; \
@ -230,11 +230,12 @@ vfprintf (s, format, ap)
/* Allocate memory for the argument descriptions. */ /* Allocate memory for the argument descriptions. */
args_type = alloca (nargs * sizeof (int)); args_type = alloca (nargs * sizeof (int));
memset (args_type, 0, nargs * sizeof (int));
args_value = alloca (nargs * sizeof (union printf_arg)); args_value = alloca (nargs * sizeof (union printf_arg));
/* XXX Could do sanity check here: /* XXX Could do sanity check here: If any element in ARGS_TYPE is
Initialize args_type elts to zero. still zero after this loop, format is invalid. For now we simply
If any is still zero after this loop, format is invalid. */ use 0 as the value. */
/* Fill in the types of all the arguments. */ /* Fill in the types of all the arguments. */
for (cnt = 0; cnt < nspecs; ++cnt) for (cnt = 0; cnt < nspecs; ++cnt)
@ -287,6 +288,8 @@ vfprintf (s, format, ap)
default: default:
if ((args_type[cnt] & PA_FLAG_PTR) != 0) if ((args_type[cnt] & PA_FLAG_PTR) != 0)
args_value[cnt].pa_pointer = va_arg (ap, void *); args_value[cnt].pa_pointer = va_arg (ap, void *);
else
args_value[cnt].pa_long_double = 0.0;
break; break;
} }
@ -420,15 +423,27 @@ vfprintf (s, format, ap)
char *const workend = &work[sizeof(work) - 1]; char *const workend = &work[sizeof(work) - 1];
register char *w; register char *w;
/* Supply a default precision if none was given. */
if (specs[cnt].info.prec == -1) if (specs[cnt].info.prec == -1)
specs[cnt].info.prec = 1; /* Supply a default precision if none was given. */
specs[cnt].info.prec = 1;
else
/* We have to take care for the '0' flag. If a
precision is given it must be ignored. */
specs[cnt].info.pad = ' ';
/* Put the number in WORK. */ /* If the precision is 0 and the number is 0 nothing has
w = _itoa (num, workend + 1, base, specs[cnt].info.spec == 'X'); to be written for the number. */
w -= 1; if (specs[cnt].info.prec == 0 && num == 0)
if (specs[cnt].info.group && grouping) w = workend;
w = group_number (w, workend, grouping, thousands_sep); else
{
/* Put the number in WORK. */
w = _itoa (num, workend + 1, base,
specs[cnt].info.spec == 'X');
w -= 1;
if (specs[cnt].info.group && grouping)
w = group_number (w, workend, grouping, thousands_sep);
}
specs[cnt].info.width -= workend - w; specs[cnt].info.width -= workend - w;
specs[cnt].info.prec -= workend - w; specs[cnt].info.prec -= workend - w;
@ -618,8 +633,18 @@ vfprintf (s, format, ap)
} }
#ifdef USE_IN_LIBIO #ifdef USE_IN_LIBIO
#undef vfprintf # undef vfprintf
# ifdef strong_alias
/* This is for glibc. */
strong_alias (_IO_vfprintf, vfprintf) strong_alias (_IO_vfprintf, vfprintf)
# else
# if defined __ELF__ || defined __GNU_LIBRARY__
# include <gnu-stabs.h>
# ifdef weak_alias
weak_alias (_IO_vfprintf, vfprintf);
# endif
# endif
# endif
#endif #endif

View File

@ -132,6 +132,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
int base; int base;
/* Signedness for integral numbers. */ /* Signedness for integral numbers. */
int number_signed; int number_signed;
/* Decimal point character. */
wchar_t decimal;
/* Integral holding variables. */ /* Integral holding variables. */
union union
{ {
@ -144,9 +146,24 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
register char *str, **strptr; register char *str, **strptr;
size_t strsize; size_t strsize;
/* Workspace. */ /* Workspace. */
char work[200]; char *tw; /* Temporary pointer. */
char *w; /* Pointer into WORK. */ char *wp = NULL; /* Workspace. */
wchar_t decimal; /* Decimal point character. */ size_t wpsize = 0; /* Currently used bytes in workspace. */
size_t wpmax = 0; /* Maximal size of workspace. */
#define ADDW(Ch) \
do \
{ \
if (wpsize == wpmax) \
{ \
char *old = wp; \
wpmax = 200 > 2 * wpmax ? 200 : 2 * wpmax; \
wp = (char *) alloca (wpmax); \
if (wpsize > 0) \
memcpy (wp, old, wpsize); \
} \
wp[wpsize++] = (Ch); \
} \
while (0)
ARGCHECK (s, format); ARGCHECK (s, format);
@ -338,7 +355,6 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
conv_error (); conv_error ();
/* Find the conversion specifier. */ /* Find the conversion specifier. */
w = work;
fc = *f++; fc = *f++;
if (fc != '[' && fc != 'c' && fc != 'n') if (fc != '[' && fc != 'c' && fc != 'n')
/* Eat whitespace. */ /* Eat whitespace. */
@ -490,7 +506,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
/* Check for a sign. */ /* Check for a sign. */
if (c == '-' || c == '+') if (c == '-' || c == '+')
{ {
*w++ = c; ADDW (c);
if (width > 0) if (width > 0)
--width; --width;
(void) inchar (); (void) inchar ();
@ -501,7 +517,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
{ {
if (width > 0) if (width > 0)
--width; --width;
*w++ = '0'; ADDW ('0');
(void) inchar (); (void) inchar ();
@ -523,40 +539,40 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
if (base == 0) if (base == 0)
base = 10; base = 10;
/* Read the number into WORK. */ /* Read the number into workspace. */
do do
{ {
if (base == 16 ? !isxdigit (c) : if (base == 16 ? !isxdigit (c) :
(!isdigit (c) || c - '0' >= base)) (!isdigit (c) || c - '0' >= base))
break; break;
*w++ = c; ADDW (c);
if (width > 0) if (width > 0)
--width; --width;
} }
while (inchar () != EOF && width != 0); while (inchar () != EOF && width != 0);
if (w == work || if (wpsize == 0 ||
(w - work == 1 && (work[0] == '+' || work[0] == '-'))) (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
/* There was no number. */ /* There was no number. */
conv_error (); conv_error ();
/* Convert the number. */ /* Convert the number. */
*w = '\0'; ADDW ('\0');
if (is_longlong) if (is_longlong)
{ {
if (number_signed) if (number_signed)
num.q = __strtoq_internal (work, &w, base, group_flag); num.q = __strtoq_internal (wp, &tw, base, group_flag);
else else
num.uq = __strtouq_internal (work, &w, base, group_flag); num.uq = __strtouq_internal (wp, &tw, base, group_flag);
} }
else else
{ {
if (number_signed) if (number_signed)
num.l = __strtol_internal (work, &w, base, group_flag); num.l = __strtol_internal (wp, &tw, base, group_flag);
else else
num.ul = __strtoul_internal (work, &w, base, group_flag); num.ul = __strtoul_internal (wp, &tw, base, group_flag);
} }
if (w == work) if (wp == tw)
conv_error (); conv_error ();
if (do_assign) if (do_assign)
@ -599,7 +615,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
/* Check for a sign. */ /* Check for a sign. */
if (c == '-' || c == '+') if (c == '-' || c == '+')
{ {
*w++ = c; ADDW (c);
if (inchar () == EOF) if (inchar () == EOF)
/* EOF is only an input error before we read any chars. */ /* EOF is only an input error before we read any chars. */
conv_error (); conv_error ();
@ -611,17 +627,18 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
do do
{ {
if (isdigit (c)) if (isdigit (c))
*w++ = c; ADDW (c);
else if (got_e && w[-1] == 'e' && (c == '-' || c == '+')) else if (got_e && wp[wpsize - 1] == 'e'
*w++ = c; && (c == '-' || c == '+'))
ADDW (c);
else if (!got_e && tolower (c) == 'e') else if (!got_e && tolower (c) == 'e')
{ {
*w++ = 'e'; ADDW ('e');
got_e = got_dot = 1; got_e = got_dot = 1;
} }
else if (c == decimal && !got_dot) else if (c == decimal && !got_dot)
{ {
*w++ = c; ADDW (c);
got_dot = 1; got_dot = 1;
} }
else else
@ -630,33 +647,34 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
--width; --width;
} while (inchar () != EOF && width != 0); } while (inchar () != EOF && width != 0);
if (w == work) if (wpsize == 0)
conv_error(); conv_error();
if (w[-1] == '-' || w[-1] == '+' || w[-1] == 'e') if (wp[wpsize - 1] == '-' || wp[wpsize - 1] == '+'
|| wp[wpsize - 1] == 'e')
conv_error (); conv_error ();
/* Convert the number. */ /* Convert the number. */
*w = '\0'; ADDW ('\0');
if (is_long_double) if (is_long_double)
{ {
long double d = __strtold_internal (work, &w, group_flag); long double d = __strtold_internal (wp, &tw, group_flag);
if (do_assign && w != work) if (do_assign && tw != wp)
*ARG (long double *) = d; *ARG (long double *) = d;
} }
else if (is_long) else if (is_long)
{ {
double d = __strtod_internal (work, &w, group_flag); double d = __strtod_internal (wp, &tw, group_flag);
if (do_assign && w != work) if (do_assign && tw != wp)
*ARG (double *) = d; *ARG (double *) = d;
} }
else else
{ {
float d = __strtof_internal (work, &w, group_flag); float d = __strtof_internal (wp, &tw, group_flag);
if (do_assign && w != work) if (do_assign && tw != wp)
*ARG (float *) = d; *ARG (float *) = d;
} }
if (w == work) if (tw == wp)
conv_error (); conv_error ();
if (do_assign) if (do_assign)
@ -680,23 +698,23 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
while ((fc = *f++) != '\0' && fc != ']') while ((fc = *f++) != '\0' && fc != ']')
{ {
if (fc == '-' && *f != '\0' && *f != ']' && if (fc == '-' && *f != '\0' && *f != ']' &&
w > work && w[-1] <= *f) wpsize > 0 && wp[wpsize - 1] <= *f)
/* Add all characters from the one before the '-' /* Add all characters from the one before the '-'
up to (but not including) the next format char. */ up to (but not including) the next format char. */
for (fc = w[-1] + 1; fc < *f; ++fc) for (fc = wp[wpsize - 1] + 1; fc < *f; ++fc)
*w++ = fc; ADDW (fc);
else else
/* Add the character to the list. */ /* Add the character to the list. */
*w++ = fc; ADDW (fc);
} }
if (fc == '\0') if (fc == '\0')
conv_error(); conv_error();
*w = '\0'; ADDW ('\0');
num.ul = read_in; num.ul = read_in;
do do
{ {
if ((strchr (work, c) == NULL) != not_in) if ((strchr (wp, c) == NULL) != not_in)
break; break;
STRING_ADD_CHAR (c); STRING_ADD_CHAR (c);
if (width > 0) if (width > 0)

View File

@ -359,7 +359,10 @@ INTERNAL (STRTOF) (nptr, endptr, group)
} }
} }
else else
grouping = NULL; {
grouping = NULL;
thousands = L'\0';
}
/* Find the locale's decimal point character. */ /* Find the locale's decimal point character. */
if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT), if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
@ -373,7 +376,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
bits = 0; bits = 0;
/* Parse string to get maximal legal prefix. We need the number of /* Parse string to get maximal legal prefix. We need the number of
characters of the interger part, the fractional part and the exponent. */ characters of the integer part, the fractional part and the exponent. */
cp = nptr - 1; cp = nptr - 1;
/* Ignore leading white space. */ /* Ignore leading white space. */
do do
@ -470,7 +473,8 @@ INTERNAL (STRTOF) (nptr, endptr, group)
int_no = dig_no; int_no = dig_no;
lead_zero = int_no == 0 ? -1 : 0; lead_zero = int_no == 0 ? -1 : 0;
/* Read the fractional digits. */ /* Read the fractional digits. A special case are the 'american style'
numbers like `16.' i.e. with decimal but without trailing digits. */
if (c == decimal) if (c == decimal)
{ {
if (isdigit (cp[1])) if (isdigit (cp[1]))
@ -506,11 +510,18 @@ INTERNAL (STRTOF) (nptr, endptr, group)
if (isdigit (c)) if (isdigit (c))
{ {
int exp_limit;
/* Get the exponent limit. */
exp_limit = exp_negative ?
-MIN_10_EXP + MANT_DIG - int_no :
MAX_10_EXP - int_no + lead_zero;
do do
{ {
if ((!exp_negative && exponent * 10 + int_no > MAX_10_EXP) exponent *= 10;
|| (exp_negative
&& exponent * 10 + int_no > -MIN_10_EXP + MANT_DIG)) if (exponent > exp_limit)
/* The exponent is too large/small to represent a valid /* The exponent is too large/small to represent a valid
number. */ number. */
{ {
@ -530,7 +541,6 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* NOTREACHED */ /* NOTREACHED */
} }
exponent *= 10;
exponent += c - '0'; exponent += c - '0';
c = *++cp; c = *++cp;
} }
@ -563,6 +573,15 @@ INTERNAL (STRTOF) (nptr, endptr, group)
if (dig_no == 0) if (dig_no == 0)
return 0.0; return 0.0;
if (lead_zero)
{
/* Find the decimal point */
while (*startp != decimal) startp++;
startp += lead_zero + 1;
exponent -= lead_zero;
dig_no -= lead_zero;
}
/* Now we have the number of digits in total and the integer digits as well /* Now we have the number of digits in total and the integer digits as well
as the exponent and its sign. We can decide whether the read digits are as the exponent and its sign. We can decide whether the read digits are
really integer digits or belong to the fractional part; i.e. we normalize really integer digits or belong to the fractional part; i.e. we normalize
@ -580,7 +599,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
} }
if (exponent - MAX(0, lead_zero) < MIN_10_EXP - (DIG + 1)) if (exponent < MIN_10_EXP - (DIG + 1))
{ {
errno = ERANGE; errno = ERANGE;
return 0.0; return 0.0;
@ -728,7 +747,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* We construct a fraction and the result of the division gives us /* We construct a fraction and the result of the division gives us
the needed digits. The denominator is 1.0 multiplied by the the needed digits. The denominator is 1.0 multiplied by the
exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and
123e6 gives 123 / 1000000. */ 123e-6 gives 123 / 1000000. */
int expbit; int expbit;
int cnt; int cnt;
@ -748,9 +767,9 @@ INTERNAL (STRTOF) (nptr, endptr, group)
digits we should have enough bits for the result. The remaining digits we should have enough bits for the result. The remaining
decimal digits give us the information that more bits are following. decimal digits give us the information that more bits are following.
This can be used while rounding. (One added as a safety margin.) */ This can be used while rounding. (One added as a safety margin.) */
if (dig_no - int_no - lead_zero > (MANT_DIG - bits + 2) / 3 + 1) if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 1)
{ {
dig_no = int_no + lead_zero + (MANT_DIG - bits + 2) / 3 + 1; dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 1;
more_bits = 1; more_bits = 1;
} }
else else
@ -789,14 +808,6 @@ INTERNAL (STRTOF) (nptr, endptr, group)
if (psrc == num) if (psrc == num)
memcpy (den, num, densize * sizeof (mp_limb)); memcpy (den, num, densize * sizeof (mp_limb));
/* If we have leading zeroes now reduce the number of significant digits
and set the pointer to the first non-0 digit. */
if (lead_zero > 0)
{
startp += lead_zero + 1; /* +1 for radix character */
dig_no -= lead_zero;
}
/* Read the fractional digits from the string. */ /* Read the fractional digits from the string. */
(void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent); (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent);
@ -898,23 +909,34 @@ INTERNAL (STRTOF) (nptr, endptr, group)
if (numsize < densize) if (numsize < densize)
{ {
if (bits <= 0) if (num[0] >= d1)
exponent -= BITS_PER_MP_LIMB; {
/* The nominator of the number occupies fewer bits than
the denominator but the one limb is bigger than the
high limb of the nominator. */
n1 = 0;
n0 = num[0];
}
else else
{ {
if (bits + BITS_PER_MP_LIMB <= MANT_DIG) if (bits <= 0)
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, exponent -= BITS_PER_MP_LIMB;
BITS_PER_MP_LIMB, 0);
else else
{ {
used = MANT_DIG - bits; if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
if (used > 0) __mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0); BITS_PER_MP_LIMB, 0);
else
{
used = MANT_DIG - bits;
if (used > 0)
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
}
bits += BITS_PER_MP_LIMB;
} }
bits += BITS_PER_MP_LIMB; n1 = num[0];
n0 = 0;
} }
n1 = num[0];
n0 = 0;
} }
else else
{ {

View File

@ -27,16 +27,16 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
size (sp + 16) size (sp + 16)
*/ */
#define r1 %eax #include "sysdep.h"
#define r2 %edx #include "asm-syntax.h"
#define t1 %eax
#define t2 %edx
#define src1 %esi #define src1 %esi
#define src2 %ebp #define src2 %ebp
#define dst %edi #define dst %edi
#define x %ebx #define x %ebx
#include "sysdep.h"
#include "asm-syntax.h"
.text .text
ALIGN (3) ALIGN (3)
.globl C_SYMBOL_NAME(__mpn_add_n) .globl C_SYMBOL_NAME(__mpn_add_n)
@ -54,77 +54,77 @@ C_SYMBOL_NAME(__mpn_add_n:)
movl (src2),x movl (src2),x
decl %ecx decl %ecx
movl %ecx,r2 movl %ecx,t2
shrl $3,%ecx shrl $3,%ecx
andl $7,r2 andl $7,t2
testl %ecx,%ecx /* zero carry flag */ testl %ecx,%ecx /* zero carry flag */
jz Lend jz Lend
pushl r2 pushl t2
ALIGN (3) ALIGN (3)
Loop: movl 28(dst),%eax /* fetch destination cache line */ Loop: movl 28(dst),%eax /* fetch destination cache line */
leal 32(dst),dst leal 32(dst),dst
L1: movl (src1),r1 L1: movl (src1),t1
movl 4(src1),r2 movl 4(src1),t2
adcl x,r1 adcl x,t1
movl 4(src2),x movl 4(src2),x
adcl x,r2 adcl x,t2
movl 8(src2),x movl 8(src2),x
movl r1,-32(dst) movl t1,-32(dst)
movl r2,-28(dst) movl t2,-28(dst)
L2: movl 8(src1),r1 L2: movl 8(src1),t1
movl 12(src1),r2 movl 12(src1),t2
adcl x,r1 adcl x,t1
movl 12(src2),x movl 12(src2),x
adcl x,r2 adcl x,t2
movl 16(src2),x movl 16(src2),x
movl r1,-24(dst) movl t1,-24(dst)
movl r2,-20(dst) movl t2,-20(dst)
L3: movl 16(src1),r1 L3: movl 16(src1),t1
movl 20(src1),r2 movl 20(src1),t2
adcl x,r1 adcl x,t1
movl 20(src2),x movl 20(src2),x
adcl x,r2 adcl x,t2
movl 24(src2),x movl 24(src2),x
movl r1,-16(dst) movl t1,-16(dst)
movl r2,-12(dst) movl t2,-12(dst)
L4: movl 24(src1),r1 L4: movl 24(src1),t1
movl 28(src1),r2 movl 28(src1),t2
adcl x,r1 adcl x,t1
movl 28(src2),x movl 28(src2),x
adcl x,r2 adcl x,t2
movl 32(src2),x movl 32(src2),x
movl r1,-8(dst) movl t1,-8(dst)
movl r2,-4(dst) movl t2,-4(dst)
leal 32(src1),src1 leal 32(src1),src1
leal 32(src2),src2 leal 32(src2),src2
decl %ecx decl %ecx
jnz Loop jnz Loop
popl r2 popl t2
Lend: Lend:
decl r2 /* test r2 w/o clobbering carry */ decl t2 /* test t2 w/o clobbering carry */
js Lend2 js Lend2
incl r2 incl t2
Loop2: Loop2:
leal 4(dst),dst leal 4(dst),dst
movl (src1),r1 movl (src1),t1
adcl x,r1 adcl x,t1
movl 4(src2),x movl 4(src2),x
movl r1,-4(dst) movl t1,-4(dst)
leal 4(src1),src1 leal 4(src1),src1
leal 4(src2),src2 leal 4(src2),src2
decl r2 decl t2
jnz Loop2 jnz Loop2
Lend2: Lend2:
movl (src1),r1 movl (src1),t1
adcl x,r1 adcl x,t1
movl r1,(dst) movl t1,(dst)
sbbl %eax,%eax sbbl %eax,%eax
negl %eax negl %eax

View File

@ -27,16 +27,16 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
size (sp + 16) size (sp + 16)
*/ */
#define r1 %eax #include "sysdep.h"
#define r2 %edx #include "asm-syntax.h"
#define t1 %eax
#define t2 %edx
#define src1 %esi #define src1 %esi
#define src2 %ebp #define src2 %ebp
#define dst %edi #define dst %edi
#define x %ebx #define x %ebx
#include "sysdep.h"
#include "asm-syntax.h"
.text .text
ALIGN (3) ALIGN (3)
.globl C_SYMBOL_NAME(__mpn_sub_n) .globl C_SYMBOL_NAME(__mpn_sub_n)
@ -54,77 +54,77 @@ C_SYMBOL_NAME(__mpn_sub_n:)
movl (src2),x movl (src2),x
decl %ecx decl %ecx
movl %ecx,r2 movl %ecx,t2
shrl $3,%ecx shrl $3,%ecx
andl $7,r2 andl $7,t2
testl %ecx,%ecx /* zero carry flag */ testl %ecx,%ecx /* zero carry flag */
jz Lend jz Lend
pushl r2 pushl t2
ALIGN (3) ALIGN (3)
Loop: movl 28(dst),%eax /* fetch destination cache line */ Loop: movl 28(dst),%eax /* fetch destination cache line */
leal 32(dst),dst leal 32(dst),dst
L1: movl (src1),r1 L1: movl (src1),t1
movl 4(src1),r2 movl 4(src1),t2
sbbl x,r1 sbbl x,t1
movl 4(src2),x movl 4(src2),x
sbbl x,r2 sbbl x,t2
movl 8(src2),x movl 8(src2),x
movl r1,-32(dst) movl t1,-32(dst)
movl r2,-28(dst) movl t2,-28(dst)
L2: movl 8(src1),r1 L2: movl 8(src1),t1
movl 12(src1),r2 movl 12(src1),t2
sbbl x,r1 sbbl x,t1
movl 12(src2),x movl 12(src2),x
sbbl x,r2 sbbl x,t2
movl 16(src2),x movl 16(src2),x
movl r1,-24(dst) movl t1,-24(dst)
movl r2,-20(dst) movl t2,-20(dst)
L3: movl 16(src1),r1 L3: movl 16(src1),t1
movl 20(src1),r2 movl 20(src1),t2
sbbl x,r1 sbbl x,t1
movl 20(src2),x movl 20(src2),x
sbbl x,r2 sbbl x,t2
movl 24(src2),x movl 24(src2),x
movl r1,-16(dst) movl t1,-16(dst)
movl r2,-12(dst) movl t2,-12(dst)
L4: movl 24(src1),r1 L4: movl 24(src1),t1
movl 28(src1),r2 movl 28(src1),t2
sbbl x,r1 sbbl x,t1
movl 28(src2),x movl 28(src2),x
sbbl x,r2 sbbl x,t2
movl 32(src2),x movl 32(src2),x
movl r1,-8(dst) movl t1,-8(dst)
movl r2,-4(dst) movl t2,-4(dst)
leal 32(src1),src1 leal 32(src1),src1
leal 32(src2),src2 leal 32(src2),src2
decl %ecx decl %ecx
jnz Loop jnz Loop
popl r2 popl t2
Lend: Lend:
decl r2 /* test r2 w/o clobbering carry */ decl t2 /* test t2 w/o clobbering carry */
js Lend2 js Lend2
incl r2 incl t2
Loop2: Loop2:
leal 4(dst),dst leal 4(dst),dst
movl (src1),r1 movl (src1),t1
sbbl x,r1 sbbl x,t1
movl 4(src2),x movl 4(src2),x
movl r1,-4(dst) movl t1,-4(dst)
leal 4(src1),src1 leal 4(src1),src1
leal 4(src2),src2 leal 4(src2),src2
decl r2 decl t2
jnz Loop2 jnz Loop2
Lend2: Lend2:
movl (src1),r1 movl (src1),t1
sbbl x,r1 sbbl x,t1
movl r1,(dst) movl t1,(dst)
sbbl %eax,%eax sbbl %eax,%eax
negl %eax negl %eax