From 96aa2d94a2355cdc55c96e808d14a0e7f2ebe77d Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 20 Nov 1995 03:48:11 +0000 Subject: Sat Nov 18 16:46:01 1995 Ulrich Drepper * libio/Makefile, libio/cleanup.c, libio/clearerr.c, libio/feof.c, libio/ferror.c, libio/fgetc.c, libio/filedoalloc.c, libio/fileno.c, libio/fileops.c, libio/fputc.c, libio/freopen.c, libio/fseek.c, libio/genops.c, libio/getc.c, libio/getchar.c, libio/iofclose.c, libio/iofdopen.c, libio/iofflush.c, libio/iofgetpos.c, libio/iofgets.c, libio/iofopen.c, libio/iofprintf.c, libio/iofputs.c, libio/iofread.c, libio/iofscanf.c, libio/iofsetpos.c, libio/ioftell.c, libio/iofwrite.c, libio/iogetdelim.c, libio/iogetline.c, libio/iogets.c, libio/iolibio.h, libio/iopadn.c, libio/ioprims.c, libio/ioputs.c, libio/ioseekoff.c, libio/ioseekpos.c, libio/iosetbuffer.c, libio/iosetvbuf.c, libio/iosprintf.c, libio/ioungetc.c, libio/iovsprintf.c, libio/iovsscanf.c, libio/libio.h, libio/libioP.h, libio/putc.c, libio/putchar.c, libio/rewind.c, libio/setbuf.c, libio/setlinebuf.c, libio/stdfiles.c, libio/stdio.c, libio/stdio.h, libio/strfile.h, libio/strops.c, libio/vasprintf.c, libio/vscanf.c, libio/vsnprintf.c: New files. Slightly modified version from Linux libc. * libio/memstream.c, libio/vdprintf.c: New files for functions not (yet) part of GNU libio. * libio/iofopncook.c: Implementation of `fopencookie', mainly written by Per Bothner. * stdio-common/getline.c: Adapted to libio. * stdio-common/snprintf.c: Adapted to libio. * stdio-common/vfprintf.c: Adapted to libio. * stdio-common/vfscanf.c: Adapted to libio. * sysdeps/posix/tempname.c: Adapted to libio. --- stdio-common/getline.c | 5 ++ stdio-common/printf_fp.c | 14 +-- stdio-common/snprintf.c | 1 + stdio-common/vfprintf.c | 51 +++++------ stdio-common/vfscanf.c | 224 +++++++++++++++++++++++++++++++++++------------ 5 files changed, 205 insertions(+), 90 deletions(-) (limited to 'stdio-common') diff --git a/stdio-common/getline.c b/stdio-common/getline.c index 1a2f975c75..f103979333 100644 --- a/stdio-common/getline.c +++ b/stdio-common/getline.c @@ -22,6 +22,11 @@ Cambridge, MA 02139, USA. */ #undef __getline +#ifdef USE_IN_LIBIO +# define ssize_t _IO_ssize_t +# define __getdelim _IO_getdelim +#endif + /* Like getdelim, but always looks for a newline. */ ssize_t DEFUN(__getline, (lineptr, n, stream), diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index 28d13d61b8..31c009e891 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -269,7 +269,7 @@ __printf_fp (fp, info, args) { fracsize = __mpn_extract_long_double (fp_input, (sizeof (fp_input) / - sizeof (fp_input[0])), + sizeof (fp_input[0])), &exponent, &is_neg, fpnum.ldbl); to_shift = 1 + fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG; @@ -496,7 +496,7 @@ __printf_fp (fp, info, args) /* Now shift the input value to its right place. */ cy = __mpn_lshift (frac, fp_input, fracsize, to_shift); - frac[fracsize++] = cy; + frac[fracsize++] = cy; assert (cy == 1 || (frac[fracsize - 2] == 0 && frac[0] == 0)); expsign = 1; @@ -524,7 +524,7 @@ __printf_fp (fp, info, args) if (cy == 0) --tmpsize; - count_leading_zeros (cnt_h, tmp[tmpsize - 1]); + count_leading_zeros (cnt_h, tmp[tmpsize - 1]); incr = (tmpsize - fracsize) * BITS_PER_MP_LIMB + BITS_PER_MP_LIMB - 1 - cnt_h; @@ -559,7 +559,7 @@ __printf_fp (fp, info, args) && tmp[tmpsize - 2] < topval[0])))) { /* The factor is right. Adapt binary and decimal - exponents. */ + exponents. */ exponent -= incr; exp10 |= 1 << explog; @@ -639,7 +639,7 @@ __printf_fp (fp, info, args) /* Now shift the input value to its right place. */ cy = __mpn_lshift (frac, fp_input, fracsize, (exponent + to_shift)); - frac[fracsize++] = cy; + frac[fracsize++] = cy; exponent = 0; } @@ -714,7 +714,7 @@ __printf_fp (fp, info, args) it is possible that we need two more characters in front of all the other output. */ buffer = alloca (2 + chars_needed); - cp = startp = buffer + 2; /* Let room for rounding. */ + cp = startp = buffer + 2; /* Let room for rounding. */ /* Do the real work: put digits in allocated buffer. */ if (expsign == 0 || type != 'f') @@ -886,7 +886,7 @@ __printf_fp (fp, info, args) } /* Compute number of characters which must be filled with the padding - character. */ + character. */ if (is_neg || info->showsign || info->space) --width; width -= cp - startp; diff --git a/stdio-common/snprintf.c b/stdio-common/snprintf.c index a7a6e722ee..ca0b60aed6 100644 --- a/stdio-common/snprintf.c +++ b/stdio-common/snprintf.c @@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */ #include #ifdef USE_IN_LIBIO +# include # define __vsnprintf _IO_vsnprintf #endif diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index e22403be22..9e855ded56 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -239,11 +239,11 @@ vfprintf (s, format, ap) /* Fill in the types of all the arguments. */ for (cnt = 0; cnt < nspecs; ++cnt) { - /* If the width is determined by an argument this is an int. */ + /* If the width is determined by an argument this is an int. */ if (specs[cnt].width_arg != -1) args_type[specs[cnt].width_arg] = PA_INT; - /* If the precision is determined by an argument this is an int. */ + /* If the precision is determined by an argument this is an int. */ if (specs[cnt].prec_arg != -1) args_type[specs[cnt].prec_arg] = PA_INT; @@ -583,16 +583,16 @@ vfprintf (s, format, ap) case 'n': /* Answer the count of characters written. */ if (specs[cnt].info.is_longlong) - *(long long int *) + *(long long int *) args_value[specs[cnt].data_arg].pa_pointer = done; else if (specs[cnt].info.is_long) - *(long int *) + *(long int *) args_value[specs[cnt].data_arg].pa_pointer = done; else if (!specs[cnt].info.is_short) - *(int *) + *(int *) args_value[specs[cnt].data_arg].pa_pointer = done; else - *(short int *) + *(short int *) args_value[specs[cnt].data_arg].pa_pointer = done; break; @@ -745,23 +745,24 @@ _IO_helper_overflow (s, c) static const struct _IO_jump_t _IO_helper_jumps = { - _IO_helper_overflow, - _IO_default_underflow, - _IO_default_xsputn, - _IO_default_xsgetn, - _IO_default_read, - _IO_default_write, - _IO_default_doallocate, - _IO_default_pbackfail, - _IO_default_setbuf, - _IO_default_sync, - _IO_default_finish, - _IO_default_close, - _IO_default_stat, - _IO_default_seek, - _IO_default_seekoff, - _IO_default_seekpos, - _IO_default_uflow + JUMP_INIT_DUMMY, + JUMP_INIT (finish, _IO_default_finish), + JUMP_INIT (overflow, _IO_helper_overflow), + JUMP_INIT (underflow, _IO_default_underflow), + JUMP_INIT (uflow, _IO_default_uflow), + JUMP_INIT (pbackfail, _IO_default_pbackfail), + JUMP_INIT (xsputn, _IO_default_xsputn), + JUMP_INIT (xsgetn, _IO_default_xsgetn), + JUMP_INIT (seekoff, _IO_default_seekoff), + JUMP_INIT (seekpos, _IO_default_seekpos), + JUMP_INIT (setbuf, _IO_default_setbuf), + JUMP_INIT (sync, _IO_default_sync), + JUMP_INIT (doallocate, _IO_default_doallocate), + JUMP_INIT (read, _IO_default_read), + JUMP_INIT (write, _IO_default_write), + JUMP_INIT (seek, _IO_default_seek), + JUMP_INIT (close, _IO_default_close), + JUMP_INIT (stat, _IO_default_stat) }; static int @@ -781,8 +782,8 @@ buffered_vfprintf (s, format, args) hp->_IO_write_ptr = buf; hp->_IO_write_end = buf + sizeof buf; hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS; - hp->_jumps = (struct _IO_jump_t *) &_IO_helper_jumps; - + _IO_JUMPS (hp) = (struct _IO_jump_t *) &_IO_helper_jumps; + /* Now print to helper instead. */ result = _IO_vfprintf (hp, format, args); diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index a778346287..a3c058495e 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -34,23 +34,79 @@ Cambridge, MA 02139, USA. */ #define LONGLONG long #endif - -#define inchar() ((c = getc(s)) == EOF ? EOF : (++read_in, c)) -#define conv_error() return (ungetc(c, s), done) -#define input_error() return (done == 0 ? EOF : done) -#define memory_error() return ((errno = ENOMEM), EOF) +#ifdef USE_IN_LIBIO +# include +# include + +/* Those are flags in the conversion format. */ +# define LONG 0x01 /* l: long or double */ +# define LONGDBL 0x02 /* L: long long or long double */ +# define SHORT 0x04 /* h: short */ +# define SUPPRESS 0x08 /* suppress assignment */ +# define POINTER 0x10 /* weird %p pointer (`fake hex') */ +# define NOSKIP 0x20 /* do not skip blanks */ +# define WIDTH 0x40 /* width */ + + +# define va_list _IO_va_list +# define ungetc(c, s) _IO_ungetc (c, s) +# define inchar() ((c = _IO_getc(s)), ++read_in, c) +# define conv_error() return ((errp != NULL && (*errp |= 2)), \ + (c == EOF || _IO_ungetc(c, s)), done) + +# define input_error() return ((errp != NULL && (*errp |= 1)), \ + done == 0 ? EOF : done) +# define memory_error() return ((errno = ENOMEM), EOF) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + CHECK_FILE (s, -1); \ + if (s->_flags & _IO_NO_READS || format == NULL) \ + { \ + MAYBE_SET_EINVAL; \ + return -1; \ + } \ + } while (0) +#else +# define inchar() ((c = getc(s)) == EOF ? EOF : (++read_in, c)) +# define conv_error() return (ungetc(c, s), done) +# define input_error() return (done == 0 ? EOF : done) +# define memory_error() return ((errno = ENOMEM), EOF) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + if (!__validfp (s) || !s->__mode.__read || format == NULL) \ + { \ + errno = EINVAL; \ + return -1; \ + } \ + } while (0) +#endif /* Read formatted input from S according to the format string FORMAT, using the argument list in ARG. Return the number of assignments made, or -1 for an input error. */ +#ifdef USE_IN_LIBIO int -DEFUN(__vfscanf, (s, format, arg), - FILE *s AND CONST char *format AND va_list argptr) +_IO_vfscanf (s, format, argptr, errp) + _IO_FILE *s; + const char *format; + _IO_va_list argptr; + int *errp; +#else +int +__vfscanf (s, format, arg) + FILE *s; + const char *format; + va_list argptr; +#endif { va_list arg = (va_list) argptr; - register CONST char *f = format; + register const char *f = format; register char fc; /* Current character of the format. */ register size_t done = 0; /* Assignments done. */ register size_t read_in = 0; /* Chars read in. */ @@ -58,14 +114,17 @@ DEFUN(__vfscanf, (s, format, arg), register int do_assign; /* Whether to do an assignment. */ register int width; /* Maximum field width. */ int group_flag; /* %' modifier flag. */ +#ifdef USE_IN_LIBIO + int flags; /* Trace flags for current format element. */ +#endif /* Type modifiers. */ int is_short, is_long, is_long_double; #ifdef HAVE_LONGLONG /* We use the `L' modifier for `long long int'. */ -#define is_longlong is_long_double +# define is_longlong is_long_double #else -#define is_longlong 0 +# define is_longlong 0 #endif int malloc_string; /* Args are char ** to be filled in. */ /* Status for reading F-P nums. */ @@ -92,18 +151,14 @@ DEFUN(__vfscanf, (s, format, arg), char *w; /* Pointer into WORK. */ wchar_t decimal; /* Decimal point character. */ - if (!__validfp(s) || !s->__mode.__read || format == NULL) - { - errno = EINVAL; - return EOF; - } + ARGCHECK (s, format); /* Figure out the decimal point character. */ if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT), strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0) decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); - c = inchar(); + c = inchar (); /* Run through the format string. */ while (*f != '\0') @@ -112,27 +167,38 @@ DEFUN(__vfscanf, (s, format, arg), /* Extract the next argument, which is of type TYPE. For a %N$... spec, this is the Nth argument from the beginning; otherwise it is the next argument after the state now in ARG. */ -#define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ +#if 0 + /* XXX Possible optimization. */ +# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ + ({ va_list arg = (va_list) argptr; \ + arg = (va_list) ((char *) arg \ + + (argpos - 1) \ + * __va_rounded_size (void *)); \ + va_arg (arg, type); \ + })) +#else +# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ ({ unsigned int pos = argpos; \ va_list arg = (va_list) argptr; \ while (--pos > 0) \ (void) va_arg (arg, void *); \ va_arg (arg, type); \ })) +#endif if (!isascii (*f)) { /* Non-ASCII, may be a multibyte. */ - int len = mblen (f, strlen(f)); + int len = mblen (f, strlen (f)); if (len > 0) { while (len-- > 0) if (c == EOF) - input_error(); + input_error (); else if (c == *f++) - (void) inchar(); + (void) inchar (); else - conv_error(); + conv_error (); continue; } } @@ -142,8 +208,8 @@ DEFUN(__vfscanf, (s, format, arg), { /* Characters other than format specs must just match. */ if (c == EOF) - input_error(); - if (isspace(fc)) + input_error (); + if (isspace (fc)) { /* Whitespace characters match any amount of whitespace. */ while (isspace (c)) @@ -151,12 +217,17 @@ DEFUN(__vfscanf, (s, format, arg), continue; } else if (c == fc) - (void) inchar(); + (void) inchar (); else - conv_error(); + conv_error (); continue; } +#ifdef USE_IN_LIBIO + /* That is the start of the coversion string. */ + flags = 0; +#endif + /* Initialize state of modifiers. */ argpos = 0; do_assign = 1; @@ -185,6 +256,9 @@ DEFUN(__vfscanf, (s, format, arg), switch (*f++) { case '*': +#ifdef USE_IN_LIBIO + flags = SUPPRESS; +#endif do_assign = 0; break; case '\'': @@ -192,9 +266,15 @@ DEFUN(__vfscanf, (s, format, arg), break; } +#ifdef USE_IN_LIBIO + /* We have seen width. */ + if (isdigit (*f)) + flags |= WIDTH; +#endif + /* Find the maximum field width. */ width = 0; - while (isdigit(*f)) + while (isdigit (*f)) { width *= 10; width += *f++ - '0'; @@ -209,19 +289,44 @@ DEFUN(__vfscanf, (s, format, arg), { case 'h': /* int's are short int's. */ +#ifdef USE_IN_LIBIO + if (flags & ~(SUPPRESS | WIDTH)) + /* Signal illegal format element. */ + conv_error (); + flags |= SHORT; +#endif is_short = 1; break; case 'l': if (is_long) - /* A double `l' is equivalent to an `L'. */ - is_longlong = 1; + { + /* A double `l' is equivalent to an `L'. */ +#ifdef USE_IN_LIBIO + if ((flags & ~(SUPPRESS | WIDTH)) && (flags & LONGDBL)) + conv_error (); + flags &= ~LONG; + flags |= LONGDBL; +#endif + is_longlong = 1; + } else - /* int's are long int's. */ - is_long = 1; + { + /* int's are long int's. */ +#ifdef USE_IN_LIBIO + flags |= LONG; +#endif + is_long = 1; + } break; case 'q': case 'L': /* double's are long double's, and int's are long long int's. */ +#ifdef USE_IN_LIBIO + if (flags & ~(SUPPRESS | WIDTH)) + /* Signal illegal format element. */ + conv_error (); + flags |= LONGDBL; +#endif is_long_double = 1; break; case 'a': @@ -233,20 +338,20 @@ DEFUN(__vfscanf, (s, format, arg), /* End of the format string? */ if (*f == '\0') - conv_error(); + conv_error (); /* Find the conversion specifier. */ w = work; fc = *f++; if (fc != '[' && fc != 'c' && fc != 'n') /* Eat whitespace. */ - while (isspace(c)) - (void) inchar(); + while (isspace (c)) + (void) inchar (); switch (fc) { case '%': /* Must match a literal '%'. */ if (c != fc) - conv_error(); + conv_error (); break; case 'n': /* Answer number of assignments done. */ @@ -263,7 +368,7 @@ DEFUN(__vfscanf, (s, format, arg), } if (c == EOF) - input_error(); + input_error (); if (width == -1) width = 1; @@ -272,10 +377,10 @@ DEFUN(__vfscanf, (s, format, arg), { do *str++ = c; - while (inchar() != EOF && --width > 0); + while (inchar () != EOF && --width > 0); } else - while (inchar() != EOF && --width > 0); + while (inchar () != EOF && --width > 0); if (do_assign) ++done; @@ -289,7 +394,7 @@ DEFUN(__vfscanf, (s, format, arg), if (malloc_string) \ { \ /* The string is to be stored in a malloc'd buffer. */ \ - strptr = ARG (char **); \ + strptr = ARG (char **); \ if (strptr == NULL) \ conv_error (); \ /* Allocate an initial buffer. */ \ @@ -297,7 +402,7 @@ DEFUN(__vfscanf, (s, format, arg), *strptr = str = malloc (strsize); \ } \ else \ - str = ARG (char *); \ + str = ARG (char *); \ if (str == NULL) \ conv_error (); \ } @@ -357,7 +462,7 @@ DEFUN(__vfscanf, (s, format, arg), break; case 'x': /* Hexadecimal integer. */ - case 'X': /* Ditto. */ + case 'X': /* Ditto. */ base = 16; number_signed = 0; goto number; @@ -383,7 +488,7 @@ DEFUN(__vfscanf, (s, format, arg), number: if (c == EOF) - input_error(); + input_error (); /* Check for a sign. */ if (c == '-' || c == '+') @@ -391,7 +496,7 @@ DEFUN(__vfscanf, (s, format, arg), *w++ = c; if (width > 0) --width; - (void) inchar(); + (void) inchar (); } /* Look for a leading indication of base. */ @@ -401,9 +506,9 @@ DEFUN(__vfscanf, (s, format, arg), --width; *w++ = '0'; - (void) inchar(); + (void) inchar (); - if (tolower(c) == 'x') + if (tolower (c) == 'x') { if (base == 0) base = 16; @@ -411,7 +516,7 @@ DEFUN(__vfscanf, (s, format, arg), { if (width > 0) --width; - (void) inchar(); + (void) inchar (); } } else if (base == 0) @@ -422,21 +527,21 @@ DEFUN(__vfscanf, (s, format, arg), base = 10; /* Read the number into WORK. */ - while (width != 0 && c != EOF) + do { - if (base == 16 ? !isxdigit(c) : - (!isdigit(c) || c - '0' >= base)) + if (base == 16 ? !isxdigit (c) : + (!isdigit (c) || c - '0' >= base)) break; *w++ = c; if (width > 0) --width; - (void) inchar (); } + while (inchar () != EOF && width != 0); if (w == work || (w - work == 1 && (work[0] == '+' || work[0] == '-'))) /* There was no number. */ - conv_error(); + conv_error (); /* Convert the number. */ *w = '\0'; @@ -492,15 +597,15 @@ DEFUN(__vfscanf, (s, format, arg), case 'g': case 'G': if (c == EOF) - input_error(); + input_error (); /* Check for a sign. */ if (c == '-' || c == '+') { *w++ = c; - if (inchar() == EOF) + if (inchar () == EOF) /* EOF is only an input error before we read any chars. */ - conv_error(); + conv_error (); if (width > 0) --width; } @@ -508,11 +613,11 @@ DEFUN(__vfscanf, (s, format, arg), got_dot = got_e = 0; do { - if (isdigit(c)) + if (isdigit (c)) *w++ = c; else if (got_e && w[-1] == 'e' && (c == '-' || c == '+')) *w++ = c; - else if (!got_e && tolower(c) == 'e') + else if (!got_e && tolower (c) == 'e') { *w++ = 'e'; got_e = got_dot = 1; @@ -526,12 +631,12 @@ DEFUN(__vfscanf, (s, format, arg), break; if (width > 0) --width; - } while (inchar() != EOF && width != 0); + } while (inchar () != EOF && width != 0); if (w == work) conv_error(); if (w[-1] == '-' || w[-1] == '+' || w[-1] == 'e') - conv_error(); + conv_error (); /* Convert the number. */ *w = '\0'; @@ -614,11 +719,14 @@ DEFUN(__vfscanf, (s, format, arg), base = 16; /* A PTR must be the same size as a `long int'. */ is_long = 1; + number_signed = 0; goto number; } } - conv_error(); + return ((c == EOF || ungetc (c, s)), done); } +#ifndef USE_IN_LIBIO weak_alias (__vfscanf, vfscanf) +#endif -- cgit 1.4.1