fixed more binutils issues (newer gcc/libc)
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / stdio / vfscanf.c
blobeef38b9e87537a430e162e0661d98a246c2581bb
1 /*
2 FUNCTION
3 <<vscanf>>, <<vfscanf>>, <<vsscanf>>---format argument list
5 INDEX
6 vscanf
7 INDEX
8 vfscanf
9 INDEX
10 vsscanf
12 ANSI_SYNOPSIS
13 #include <stdio.h>
14 #include <stdarg.h>
15 int vscanf(const char *<[fmt]>, va_list <[list]>);
16 int vfscanf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
17 int vsscanf(const char *<[str]>, const char *<[fmt]>, va_list <[list]>);
19 int _vscanf_r(void *<[reent]>, const char *<[fmt]>,
20 va_list <[list]>);
21 int _vfscanf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
22 va_list <[list]>);
23 int _vsscanf_r(void *<[reent]>, const char *<[str]>, const char *<[fmt]>,
24 va_list <[list]>);
26 TRAD_SYNOPSIS
27 #include <stdio.h>
28 #include <varargs.h>
29 int vscanf( <[fmt]>, <[ist]>)
30 char *<[fmt]>;
31 va_list <[list]>;
33 int vfscanf( <[fp]>, <[fmt]>, <[list]>)
34 FILE *<[fp]>;
35 char *<[fmt]>;
36 va_list <[list]>;
38 int vsscanf( <[str]>, <[fmt]>, <[list]>)
39 char *<[str]>;
40 char *<[fmt]>;
41 va_list <[list]>;
43 int _vscanf_r( <[reent]>, <[fmt]>, <[ist]>)
44 char *<[reent]>;
45 char *<[fmt]>;
46 va_list <[list]>;
48 int _vfscanf_r( <[reent]>, <[fp]>, <[fmt]>, <[list]>)
49 char *<[reent]>;
50 FILE *<[fp]>;
51 char *<[fmt]>;
52 va_list <[list]>;
54 int _vsscanf_r( <[reent]>, <[str]>, <[fmt]>, <[list]>)
55 char *<[reent]>;
56 char *<[str]>;
57 char *<[fmt]>;
58 va_list <[list]>;
60 DESCRIPTION
61 <<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
62 of <<scanf>>, <<fscanf>>, and <<sscanf>>. They differ only in
63 allowing their caller to pass the variable argument list as a
64 <<va_list>> object (initialized by <<va_start>>) rather than
65 directly accepting a variable number of arguments.
67 RETURNS
68 The return values are consistent with the corresponding functions:
69 <<vscanf>> returns the number of input fields successfully scanned,
70 converted, and stored; the return value does not include scanned
71 fields which were not stored.
73 If <<vscanf>> attempts to read at end-of-file, the return value
74 is <<EOF>>.
76 If no fields were stored, the return value is <<0>>.
78 The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
79 reentrant versions which take an additional first parameter which points to the
80 reentrancy structure.
82 PORTABILITY
83 These are GNU extensions.
85 Supporting OS subroutines required:
88 /*-
89 * Copyright (c) 1990 The Regents of the University of California.
90 * All rights reserved.
92 * Redistribution and use in source and binary forms are permitted
93 * provided that the above copyright notice and this paragraph are
94 * duplicated in all such forms and that any documentation,
95 * advertising materials, and other materials related to such
96 * distribution and use acknowledge that the software was developed
97 * by the University of California, Berkeley. The name of the
98 * University may not be used to endorse or promote products derived
99 * from this software without specific prior written permission.
100 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
101 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
102 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
105 #include <_ansi.h>
106 #include <ctype.h>
107 #include <wctype.h>
108 #include <stdio.h>
109 #include <stdlib.h>
110 #include <limits.h>
111 #include <wchar.h>
112 #include <string.h>
113 #ifdef _HAVE_STDC
114 #include <stdarg.h>
115 #else
116 #include <varargs.h>
117 #endif
118 #include "local.h"
120 #ifndef NO_FLOATING_POINT
121 #define FLOATING_POINT
122 #endif
124 #ifdef FLOATING_POINT
125 #include <float.h>
127 /* Currently a test is made to see if long double processing is warranted.
128 This could be changed in the future should the _ldtoa_r code be
129 preferred over _dtoa_r. */
130 #define _NO_LONGDBL
131 #if defined WANT_IO_LONG_DBL && (LDBL_MANT_DIG > DBL_MANT_DIG)
132 #undef _NO_LONGDBL
133 extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
134 #endif
136 #define _NO_LONGLONG
137 #if defined WANT_PRINTF_LONG_LONG && defined __GNUC__
138 # undef _NO_LONGLONG
139 #endif
141 #include "floatio.h"
143 #if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX)
144 # define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
145 #else
146 # define BUF MB_LEN_MAX
147 #endif
149 /* An upper bound for how long a long prints in decimal. 4 / 13 approximates
150 log (2). Add one char for roundoff compensation and one for the sign. */
151 #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2)
152 #else
153 #define BUF 40
154 #endif
157 * Flags used during conversion.
160 #define LONG 0x01 /* l: long or double */
161 #define LONGDBL 0x02 /* L/ll: long double or long long */
162 #define SHORT 0x04 /* h: short */
163 #define CHAR 0x08 /* hh: 8 bit integer */
164 #define SUPPRESS 0x10 /* suppress assignment */
165 #define POINTER 0x20 /* weird %p pointer (`fake hex') */
166 #define NOSKIP 0x40 /* do not skip blanks */
169 * The following are used in numeric conversions only:
170 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
171 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
174 #define SIGNOK 0x80 /* +/- is (still) legal */
175 #define NDIGITS 0x100 /* no digits detected */
177 #define DPTOK 0x200 /* (float) decimal point is still legal */
178 #define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */
180 #define PFXOK 0x200 /* 0x prefix is (still) legal */
181 #define NZDIGITS 0x400 /* no zero digits detected */
184 * Conversion types.
187 #define CT_CHAR 0 /* %c conversion */
188 #define CT_CCL 1 /* %[...] conversion */
189 #define CT_STRING 2 /* %s conversion */
190 #define CT_INT 3 /* integer, i.e., strtol or strtoul */
191 #define CT_FLOAT 4 /* floating, i.e., strtod */
193 #if 0
194 #define u_char unsigned char
195 #endif
196 #define u_char char
197 #define u_long unsigned long
199 #ifndef _NO_LONGLONG
200 typedef unsigned long long u_long_long;
201 #endif
203 /*static*/ u_char *__sccl ();
206 * vfscanf
209 #define BufferEmpty (fp->_r <= 0 && __srefill(fp))
211 #ifndef _REENT_ONLY
214 _DEFUN (vfscanf, (fp, fmt, ap),
215 register FILE *fp _AND
216 _CONST char *fmt _AND
217 va_list ap)
219 CHECK_INIT(fp);
220 return __svfscanf_r (_REENT, fp, fmt, ap);
224 __svfscanf (fp, fmt0, ap)
225 register FILE *fp;
226 char _CONST *fmt0;
227 va_list ap;
229 return __svfscanf_r (_REENT, fp, fmt0, ap);
232 #endif /* !_REENT_ONLY */
235 _DEFUN (_vfscanf_r, (data, fp, fmt, ap),
236 struct _reent *data _AND
237 register FILE *fp _AND
238 _CONST char *fmt _AND
239 va_list ap)
241 return __svfscanf_r (data, fp, fmt, ap);
246 __svfscanf_r (rptr, fp, fmt0, ap)
247 struct _reent *rptr;
248 register FILE *fp;
249 char _CONST *fmt0;
250 va_list ap;
252 register u_char *fmt = (u_char *) fmt0;
253 register int c; /* character from format, or conversion */
254 register size_t width; /* field width, or 0 */
255 register char *p; /* points into all kinds of strings */
256 register int n; /* handy integer */
257 register int flags; /* flags as defined above */
258 register char *p0; /* saves original value of p when necessary */
259 int nassigned; /* number of fields assigned */
260 int nread; /* number of characters consumed from fp */
261 int base = 0; /* base argument to strtol/strtoul */
262 int nbytes = 1; /* number of bytes read from fmt string */
263 wchar_t wc; /* wchar to use to read format string */
264 wchar_t *wcp; /* handy wide character pointer */
265 size_t mbslen; /* length of converted multibyte sequence */
266 mbstate_t state; /* value to keep track of multibyte state */
268 u_long (*ccfn) () = 0; /* conversion function (strtol/strtoul) */
269 char ccltab[256]; /* character class table for %[...] */
270 char buf[BUF]; /* buffer for numeric conversions */
271 char *lptr; /* literal pointer */
273 char *cp;
274 short *sp;
275 int *ip;
276 float *flp;
277 _LONG_DOUBLE *ldp;
278 double *dp;
279 long *lp;
280 #ifndef _NO_LONGLONG
281 long long *llp;
282 #endif
284 /* `basefix' is used to avoid `if' tests in the integer scanner */
285 static _CONST short basefix[17] =
286 {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
288 nassigned = 0;
289 nread = 0;
290 for (;;)
292 #ifndef MB_CAPABLE
293 wc = *fmt;
294 #else
295 memset (&state, '\0', sizeof (state));
296 nbytes = _mbtowc_r (rptr, &wc, fmt, MB_CUR_MAX, &state);
297 #endif
298 fmt += nbytes;
299 if (wc == 0)
300 return nassigned;
301 if (nbytes == 1 && isspace (wc))
303 for (;;)
305 if (BufferEmpty || !isspace (*fp->_p))
306 break;
307 nread++, fp->_r--, fp->_p++;
309 continue;
311 if (wc != '%')
312 goto literal;
313 width = 0;
314 flags = 0;
317 * switch on the format. continue if done; break once format
318 * type is derived.
321 again:
322 c = *fmt++;
324 switch (c)
326 case '%':
327 literal:
328 lptr = fmt - nbytes;
329 for (n = 0; n < nbytes; ++n)
331 if (BufferEmpty)
332 goto input_failure;
333 if (*fp->_p != *lptr)
334 goto match_failure;
335 fp->_r--, fp->_p++;
336 nread++;
337 ++lptr;
339 continue;
341 case '*':
342 flags |= SUPPRESS;
343 goto again;
344 case 'l':
345 if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */
347 ++fmt;
348 flags |= LONGDBL;
350 else
351 flags |= LONG;
352 goto again;
353 case 'L':
354 flags |= LONGDBL;
355 goto again;
356 case 'h':
357 if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
359 ++fmt;
360 flags |= CHAR;
362 else
363 flags |= SHORT;
364 goto again;
366 case '0':
367 case '1':
368 case '2':
369 case '3':
370 case '4':
371 case '5':
372 case '6':
373 case '7':
374 case '8':
375 case '9':
376 width = width * 10 + c - '0';
377 goto again;
380 * Conversions. Those marked `compat' are for
381 * 4.[123]BSD compatibility.
383 * (According to ANSI, E and X formats are supposed to
384 * the same as e and x. Sorry about that.)
387 case 'D': /* compat */
388 flags |= LONG;
389 /* FALLTHROUGH */
390 case 'd':
391 c = CT_INT;
392 ccfn = (u_long (*)())_strtol_r;
393 base = 10;
394 break;
396 case 'i':
397 c = CT_INT;
398 ccfn = (u_long (*)())_strtol_r;
399 base = 0;
400 break;
402 case 'O': /* compat */
403 flags |= LONG;
404 /* FALLTHROUGH */
405 case 'o':
406 c = CT_INT;
407 ccfn = _strtoul_r;
408 base = 8;
409 break;
411 case 'u':
412 c = CT_INT;
413 ccfn = _strtoul_r;
414 base = 10;
415 break;
417 case 'X': /* compat XXX */
418 case 'x':
419 flags |= PFXOK; /* enable 0x prefixing */
420 c = CT_INT;
421 ccfn = _strtoul_r;
422 base = 16;
423 break;
425 #ifdef FLOATING_POINT
426 case 'E': /* compat XXX */
427 case 'G': /* compat XXX */
428 /* ANSI says that E,G and X behave the same way as e,g,x */
429 /* FALLTHROUGH */
430 case 'e':
431 case 'f':
432 case 'g':
433 c = CT_FLOAT;
434 break;
435 #endif
436 case 'S':
437 flags |= LONG;
438 /* FALLTHROUGH */
440 case 's':
441 c = CT_STRING;
442 break;
444 case '[':
445 fmt = __sccl (ccltab, fmt);
446 flags |= NOSKIP;
447 c = CT_CCL;
448 break;
450 case 'C':
451 flags |= LONG;
452 /* FALLTHROUGH */
454 case 'c':
455 flags |= NOSKIP;
456 c = CT_CHAR;
457 break;
459 case 'p': /* pointer format is like hex */
460 flags |= POINTER | PFXOK;
461 c = CT_INT;
462 ccfn = _strtoul_r;
463 base = 16;
464 break;
466 case 'n':
467 if (flags & SUPPRESS) /* ??? */
468 continue;
469 if (flags & CHAR)
471 cp = va_arg (ap, char *);
472 *cp = nread;
474 else if (flags & SHORT)
476 sp = va_arg (ap, short *);
477 *sp = nread;
479 else if (flags & LONG)
481 lp = va_arg (ap, long *);
482 *lp = nread;
484 #ifndef _NO_LONGLONG
485 else if (flags & LONGDBL)
487 llp = va_arg (ap, long long*);
488 *llp = nread;
490 #endif
491 else
493 ip = va_arg (ap, int *);
494 *ip = nread;
496 continue;
499 * Disgusting backwards compatibility hacks. XXX
501 case '\0': /* compat */
502 return EOF;
504 default: /* compat */
505 if (isupper (c))
506 flags |= LONG;
507 c = CT_INT;
508 ccfn = (u_long (*)())_strtol_r;
509 base = 10;
510 break;
514 * We have a conversion that requires input.
516 if (BufferEmpty)
517 goto input_failure;
520 * Consume leading white space, except for formats that
521 * suppress this.
523 if ((flags & NOSKIP) == 0)
525 while (isspace (*fp->_p))
527 nread++;
528 if (--fp->_r > 0)
529 fp->_p++;
530 else
531 if (__srefill (fp))
532 goto input_failure;
535 * Note that there is at least one character in the
536 * buffer, so conversions that do not set NOSKIP ca
537 * no longer result in an input failure.
542 * Do the conversion.
544 switch (c)
547 case CT_CHAR:
548 /* scan arbitrary characters (sets NOSKIP) */
549 if (width == 0)
550 width = 1;
551 if (flags & LONG)
553 if ((flags & SUPPRESS) == 0)
554 wcp = va_arg(ap, wchar_t *);
555 else
556 wcp = NULL;
557 n = 0;
558 while (width != 0)
560 if (n == MB_CUR_MAX)
561 goto input_failure;
562 buf[n++] = *fp->_p;
563 fp->_r -= 1;
564 fp->_p += 1;
565 memset((void *)&state, '\0', sizeof(mbstate_t));
566 if ((mbslen = _mbrtowc_r(rptr, wcp, buf, n, &state))
567 == (size_t)-1)
568 goto input_failure; /* Invalid sequence */
569 if (mbslen == 0 && !(flags & SUPPRESS))
570 *wcp = L'\0';
571 if (mbslen != (size_t)-2) /* Incomplete sequence */
573 nread += n;
574 width -= 1;
575 if (!(flags & SUPPRESS))
576 wcp += 1;
577 n = 0;
579 if (BufferEmpty)
581 if (n != 0)
582 goto input_failure;
583 break;
586 if (!(flags & SUPPRESS))
587 nassigned++;
589 else if (flags & SUPPRESS)
591 size_t sum = 0;
592 for (;;)
594 if ((n = fp->_r) < (int)width)
596 sum += n;
597 width -= n;
598 fp->_p += n;
599 if (__srefill (fp))
601 if (sum == 0)
602 goto input_failure;
603 break;
606 else
608 sum += width;
609 fp->_r -= width;
610 fp->_p += width;
611 break;
614 nread += sum;
616 else
618 size_t r = fread ((_PTR) va_arg (ap, char *), 1, width, fp);
620 if (r == 0)
621 goto input_failure;
622 nread += r;
623 nassigned++;
625 break;
627 case CT_CCL:
628 /* scan a (nonempty) character class (sets NOSKIP) */
629 if (width == 0)
630 width = ~0; /* `infinity' */
631 /* take only those things in the class */
632 if (flags & SUPPRESS)
634 n = 0;
635 while (ccltab[*fp->_p])
637 n++, fp->_r--, fp->_p++;
638 if (--width == 0)
639 break;
640 if (BufferEmpty)
642 if (n == 0)
643 goto input_failure;
644 break;
647 if (n == 0)
648 goto match_failure;
650 else
652 p0 = p = va_arg (ap, char *);
653 while (ccltab[*fp->_p])
655 fp->_r--;
656 *p++ = *fp->_p++;
657 if (--width == 0)
658 break;
659 if (BufferEmpty)
661 if (p == p0)
662 goto input_failure;
663 break;
666 n = p - p0;
667 if (n == 0)
668 goto match_failure;
669 *p = 0;
670 nassigned++;
672 nread += n;
673 break;
675 case CT_STRING:
676 /* like CCL, but zero-length string OK, & no NOSKIP */
677 if (width == 0)
678 width = (size_t)~0;
679 if (flags & LONG)
681 /* Process %S and %ls placeholders */
682 if ((flags & SUPPRESS) == 0)
683 wcp = va_arg(ap, wchar_t *);
684 else
685 wcp = &wc;
686 n = 0;
687 while (!isspace(*fp->_p) && width != 0)
689 if (n == MB_CUR_MAX)
690 goto input_failure;
691 buf[n++] = *fp->_p;
692 fp->_r -= 1;
693 fp->_p += 1;
694 memset((void *)&state, '\0', sizeof(mbstate_t));
695 if ((mbslen = _mbrtowc_r(rptr, wcp, buf, n, &state))
696 == (size_t)-1)
697 goto input_failure;
698 if (mbslen == 0)
699 *wcp = L'\0';
700 if (mbslen != (size_t)-2) /* Incomplete sequence */
702 if (iswspace(*wcp))
704 while (n != 0)
705 ungetc(buf[--n], fp);
706 break;
708 nread += n;
709 width -= 1;
710 if ((flags & SUPPRESS) == 0)
711 wcp += 1;
712 n = 0;
714 if (BufferEmpty)
716 if (n != 0)
717 goto input_failure;
718 break;
721 if (!(flags & SUPPRESS))
723 *wcp = L'\0';
724 nassigned++;
727 else if (flags & SUPPRESS)
729 n = 0;
730 while (!isspace (*fp->_p))
732 n++, fp->_r--, fp->_p++;
733 if (--width == 0)
734 break;
735 if (BufferEmpty)
736 break;
738 nread += n;
740 else
742 p0 = p = va_arg (ap, char *);
743 while (!isspace (*fp->_p))
745 fp->_r--;
746 *p++ = *fp->_p++;
747 if (--width == 0)
748 break;
749 if (BufferEmpty)
750 break;
752 *p = 0;
753 nread += p - p0;
754 nassigned++;
756 continue;
758 case CT_INT:
759 /* scan an integer as if by strtol/strtoul */
760 #ifdef hardway
761 if (width == 0 || width > sizeof (buf) - 1)
762 width = sizeof (buf) - 1;
763 #else
764 /* size_t is unsigned, hence this optimisation */
765 if (--width > sizeof (buf) - 2)
766 width = sizeof (buf) - 2;
767 width++;
768 #endif
769 flags |= SIGNOK | NDIGITS | NZDIGITS;
770 for (p = buf; width; width--)
772 c = *fp->_p;
774 * Switch on the character; `goto ok' if we
775 * accept it as a part of number.
777 switch (c)
780 * The digit 0 is always legal, but is special.
781 * For %i conversions, if no digits (zero or nonzero)
782 * have been scanned (only signs), we will have base==0.
783 * In that case, we should set it to 8 and enable 0x
784 * prefixing. Also, if we have not scanned zero digits
785 * before this, do not turn off prefixing (someone else
786 * will turn it off if we have scanned any nonzero digits).
788 case '0':
789 if (base == 0)
791 base = 8;
792 flags |= PFXOK;
794 if (flags & NZDIGITS)
795 flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
796 else
797 flags &= ~(SIGNOK | PFXOK | NDIGITS);
798 goto ok;
800 /* 1 through 7 always legal */
801 case '1':
802 case '2':
803 case '3':
804 case '4':
805 case '5':
806 case '6':
807 case '7':
808 base = basefix[base];
809 flags &= ~(SIGNOK | PFXOK | NDIGITS);
810 goto ok;
812 /* digits 8 and 9 ok iff decimal or hex */
813 case '8':
814 case '9':
815 base = basefix[base];
816 if (base <= 8)
817 break; /* not legal here */
818 flags &= ~(SIGNOK | PFXOK | NDIGITS);
819 goto ok;
821 /* letters ok iff hex */
822 case 'A':
823 case 'B':
824 case 'C':
825 case 'D':
826 case 'E':
827 case 'F':
828 case 'a':
829 case 'b':
830 case 'c':
831 case 'd':
832 case 'e':
833 case 'f':
834 /* no need to fix base here */
835 if (base <= 10)
836 break; /* not legal here */
837 flags &= ~(SIGNOK | PFXOK | NDIGITS);
838 goto ok;
840 /* sign ok only as first character */
841 case '+':
842 case '-':
843 if (flags & SIGNOK)
845 flags &= ~SIGNOK;
846 goto ok;
848 break;
850 /* x ok iff flag still set & 2nd char */
851 case 'x':
852 case 'X':
853 if (flags & PFXOK && p == buf + 1)
855 base = 16;/* if %i */
856 flags &= ~PFXOK;
857 goto ok;
859 break;
863 * If we got here, c is not a legal character
864 * for a number. Stop accumulating digits.
866 break;
869 * c is legal: store it and look at the next.
871 *p++ = c;
872 if (--fp->_r > 0)
873 fp->_p++;
874 else
875 if (__srefill (fp))
876 break; /* EOF */
879 * If we had only a sign, it is no good; push back the sign.
880 * If the number ends in `x', it was [sign] '0' 'x', so push back
881 * the x and treat it as [sign] '0'.
883 if (flags & NDIGITS)
885 if (p > buf)
886 _CAST_VOID ungetc (*(u_char *)-- p, fp);
887 goto match_failure;
889 c = ((u_char *) p)[-1];
890 if (c == 'x' || c == 'X')
892 --p;
893 /*(void)*/ ungetc (c, fp);
895 if ((flags & SUPPRESS) == 0)
897 u_long res;
899 *p = 0;
900 res = (*ccfn) (rptr, buf, (char **) NULL, base);
901 if (flags & POINTER)
902 *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res;
903 else if (flags & CHAR)
905 cp = va_arg (ap, char *);
906 *cp = res;
908 else if (flags & SHORT)
910 sp = va_arg (ap, short *);
911 *sp = res;
913 else if (flags & LONG)
915 lp = va_arg (ap, long *);
916 *lp = res;
918 #ifndef _NO_LONGLONG
919 else if (flags & LONGDBL)
921 u_long_long resll;
922 if (ccfn == _strtoul_r)
923 resll = _strtoull_r (rptr, buf, (char **) NULL, base);
924 else
925 resll = _strtoll_r (rptr, buf, (char **) NULL, base);
926 llp = va_arg (ap, long long*);
927 *llp = resll;
929 #endif
930 else
932 ip = va_arg (ap, int *);
933 *ip = res;
935 nassigned++;
937 nread += p - buf;
938 break;
940 #ifdef FLOATING_POINT
941 case CT_FLOAT:
943 /* scan a floating point number as if by strtod */
944 /* This code used to assume that the number of digits is reasonable.
945 However, ANSI / ISO C makes no such stipulation; we have to get
946 exact results even when there is an unreasonable amount of
947 leading zeroes. */
948 long leading_zeroes = 0;
949 long zeroes, exp_adjust;
950 char *exp_start = NULL;
951 #ifdef hardway
952 if (width == 0 || width > sizeof (buf) - 1)
953 width = sizeof (buf) - 1;
954 #else
955 /* size_t is unsigned, hence this optimisation */
956 if (--width > sizeof (buf) - 2)
957 width = sizeof (buf) - 2;
958 width++;
959 #endif
960 flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
961 zeroes = 0;
962 exp_adjust = 0;
963 for (p = buf; width; )
965 c = *fp->_p;
967 * This code mimicks the integer conversion
968 * code, but is much simpler.
970 switch (c)
973 case '0':
974 if (flags & NDIGITS)
976 flags &= ~SIGNOK;
977 zeroes++;
978 goto fskip;
980 /* Fall through. */
981 case '1':
982 case '2':
983 case '3':
984 case '4':
985 case '5':
986 case '6':
987 case '7':
988 case '8':
989 case '9':
990 flags &= ~(SIGNOK | NDIGITS);
991 goto fok;
993 case '+':
994 case '-':
995 if (flags & SIGNOK)
997 flags &= ~SIGNOK;
998 goto fok;
1000 break;
1001 case '.':
1002 if (flags & DPTOK)
1004 flags &= ~(SIGNOK | DPTOK);
1005 leading_zeroes = zeroes;
1006 goto fok;
1008 break;
1009 case 'e':
1010 case 'E':
1011 /* no exponent without some digits */
1012 if ((flags & (NDIGITS | EXPOK)) == EXPOK
1013 || ((flags & EXPOK) && zeroes))
1015 if (! (flags & DPTOK))
1017 exp_adjust = zeroes - leading_zeroes;
1018 exp_start = p;
1020 flags =
1021 (flags & ~(EXPOK | DPTOK)) |
1022 SIGNOK | NDIGITS;
1023 zeroes = 0;
1024 goto fok;
1026 break;
1028 break;
1029 fok:
1030 *p++ = c;
1031 fskip:
1032 width--;
1033 ++nread;
1034 if (--fp->_r > 0)
1035 fp->_p++;
1036 else
1037 if (__srefill (fp))
1038 break; /* EOF */
1040 if (zeroes)
1041 flags &= ~NDIGITS;
1043 * If no digits, might be missing exponent digits
1044 * (just give back the exponent) or might be missing
1045 * regular digits, but had sign and/or decimal point.
1047 if (flags & NDIGITS)
1049 if (flags & EXPOK)
1051 /* no digits at all */
1052 while (p > buf)
1054 ungetc (*(u_char *)-- p, fp);
1055 --nread;
1057 goto match_failure;
1059 /* just a bad exponent (e and maybe sign) */
1060 c = *(u_char *)-- p;
1061 --nread;
1062 if (c != 'e' && c != 'E')
1064 _CAST_VOID ungetc (c, fp); /* sign */
1065 c = *(u_char *)-- p;
1066 --nread;
1068 _CAST_VOID ungetc (c, fp);
1070 if ((flags & SUPPRESS) == 0)
1072 double res = 0;
1073 #ifdef _NO_LONGDBL
1074 #define QUAD_RES res;
1075 #else /* !_NO_LONG_DBL */
1076 long double qres = 0;
1077 #define QUAD_RES qres;
1078 #endif /* !_NO_LONG_DBL */
1079 long new_exp = 0;
1081 *p = 0;
1082 if ((flags & (DPTOK | EXPOK)) == EXPOK)
1084 exp_adjust = zeroes - leading_zeroes;
1085 new_exp = -exp_adjust;
1086 exp_start = p;
1088 else if (exp_adjust)
1089 new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;
1090 if (exp_adjust)
1093 /* If there might not be enough space for the new exponent,
1094 truncate some trailing digits to make room. */
1095 if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
1096 exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
1097 sprintf (exp_start, "e%ld", new_exp);
1100 /* Current _strtold routine is markedly slower than
1101 _strtod_r. Only use it if we have a long double
1102 result. */
1103 #ifndef _NO_LONGDBL /* !_NO_LONGDBL */
1104 if (flags & LONGDBL)
1105 qres = _strtold (buf, NULL);
1106 else
1107 #endif
1108 res = _strtod_r (rptr, buf, NULL);
1110 if (flags & LONG)
1112 dp = va_arg (ap, double *);
1113 *dp = res;
1115 else if (flags & LONGDBL)
1117 ldp = va_arg (ap, _LONG_DOUBLE *);
1118 *ldp = QUAD_RES;
1120 else
1122 flp = va_arg (ap, float *);
1123 *flp = res;
1125 nassigned++;
1127 break;
1129 #endif /* FLOATING_POINT */
1132 input_failure:
1133 return nassigned ? nassigned : -1;
1134 match_failure:
1135 return nassigned;
1139 * Fill in the given table from the scanset at the given format
1140 * (just after `['). Return a pointer to the character past the
1141 * closing `]'. The table has a 1 wherever characters should be
1142 * considered part of the scanset.
1145 /*static*/
1146 u_char *
1147 __sccl (tab, fmt)
1148 register char *tab;
1149 register u_char *fmt;
1151 register int c, n, v;
1153 /* first `clear' the whole table */
1154 c = *fmt++; /* first char hat => negated scanset */
1155 if (c == '^')
1157 v = 1; /* default => accept */
1158 c = *fmt++; /* get new first char */
1160 else
1161 v = 0; /* default => reject */
1162 /* should probably use memset here */
1163 for (n = 0; n < 256; n++)
1164 tab[n] = v;
1165 if (c == 0)
1166 return fmt - 1; /* format ended before closing ] */
1169 * Now set the entries corresponding to the actual scanset to the
1170 * opposite of the above.
1172 * The first character may be ']' (or '-') without being special; the
1173 * last character may be '-'.
1176 v = 1 - v;
1177 for (;;)
1179 tab[c] = v; /* take character c */
1180 doswitch:
1181 n = *fmt++; /* and examine the next */
1182 switch (n)
1185 case 0: /* format ended too soon */
1186 return fmt - 1;
1188 case '-':
1190 * A scanset of the form [01+-] is defined as `the digit 0, the
1191 * digit 1, the character +, the character -', but the effect of a
1192 * scanset such as [a-zA-Z0-9] is implementation defined. The V7
1193 * Unix scanf treats `a-z' as `the letters a through z', but treats
1194 * `a-a' as `the letter a, the character -, and the letter a'.
1196 * For compatibility, the `-' is not considerd to define a range if
1197 * the character following it is either a close bracket (required by
1198 * ANSI) or is not numerically greater than the character we just
1199 * stored in the table (c).
1201 n = *fmt;
1202 if (n == ']' || n < c)
1204 c = '-';
1205 break; /* resume the for(;;) */
1207 fmt++;
1209 { /* fill in the range */
1210 tab[++c] = v;
1212 while (c < n);
1213 #if 1 /* XXX another disgusting compatibility hack */
1215 * Alas, the V7 Unix scanf also treats formats such
1216 * as [a-c-e] as `the letters a through e'. This too
1217 * is permitted by the standard....
1219 goto doswitch;
1220 #else
1221 c = *fmt++;
1222 if (c == 0)
1223 return fmt - 1;
1224 if (c == ']')
1225 return fmt;
1226 #endif
1228 break;
1231 case ']': /* end of scanset */
1232 return fmt;
1234 default: /* just another character */
1235 c = n;
1236 break;
1239 /* NOTREACHED */