2 Copyright (C) 1993 Free Software Foundation
4 This file is part of the GNU IO Library. This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
26 * Copyright (c) 1990 The Regents of the University of California.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms are permitted
30 * provided that the above copyright notice and this paragraph are
31 * duplicated in all such forms and that any documentation,
32 * advertising materials, and other materials related to such
33 * distribution and use acknowledge that the software was developed
34 * by the University of California, Berkeley. The name of the
35 * University may not be used to endorse or promote products derived
36 * from this software without specific prior written permission.
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
38 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
42 /* Extensively hacked for GNU iostream by Per Bothner 1991, 1992, 1993.
43 Changes copyright Free Software Foundation 1992, 1993. */
45 #if defined(LIBC_SCCS) && !defined(lint)
46 static char sccsid
[] = "%W% (Berkeley) %G%";
47 #endif /* LIBC_SCCS and not lint */
57 #ifndef NO_FLOATING_POINT
58 #define FLOATING_POINT
63 #define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
69 * Flags used during conversion.
71 #define LONG 0x01 /* l: long or double */
72 #define LONGDBL 0x02 /* L: long double; unimplemented */
73 #define SHORT 0x04 /* h: short */
74 #define SUPPRESS 0x08 /* suppress assignment */
75 #define POINTER 0x10 /* weird %p pointer (`fake hex') */
76 #define NOSKIP 0x20 /* do not skip blanks */
77 #define WIDTH 0x40 /* width */
80 * The following are used in numeric conversions only:
81 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
82 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
84 #define SIGNOK 0x40 /* +/- is (still) legal */
85 #define NDIGITS 0x80 /* no digits detected */
87 #define DPTOK 0x100 /* (float) decimal point is still legal */
88 #define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
90 #define PFXOK 0x100 /* 0x prefix is (still) legal */
91 #define NZDIGITS 0x200 /* no zero digits detected */
96 #define CT_CHAR 0 /* %c conversion */
97 #define CT_CCL 1 /* %[...] conversion */
98 #define CT_STRING 2 /* %s conversion */
99 #define CT_INT 3 /* integer, i.e., strtol or strtoul */
100 #define CT_FLOAT 4 /* floating, i.e., strtod */
102 #define u_char unsigned char
103 #define u_long unsigned long
108 extern u_long strtoul
__P((const char*, char**, int));
109 extern long strtol
__P((const char*, char**, int));
110 static const u_char
*__sccl
__P((char *tab
, const u_char
*fmt
));
112 extern double atof();
118 /* If errp != NULL, *errp|=1 if we see a premature EOF;
119 *errp|=2 if we an invalid character. */
122 DEFUN(_IO_vfscanf
, (fp
, fmt0
, ap
, errp
),
123 register _IO_FILE
*fp AND
char const *fmt0
124 AND _IO_va_list ap AND
int *errp
)
126 register const u_char
*fmt
= (const u_char
*)fmt0
;
127 register int c
; /* character from format, or conversion */
128 register _IO_ssize_t width
; /* field width, or 0 */
129 register char *p
; /* points into all kinds of strings */
130 register int n
; /* handy integer */
131 register int flags
= 0; /* flags as defined above */
132 register char *p0
; /* saves original value of p when necessary */
133 int nassigned
; /* number of fields assigned */
134 int nread
; /* number of characters consumed from fp */
135 /* Assignments to base and ccfn are just to suppress warnings from gcc.*/
136 int base
= 0; /* base argument to strtol/strtoul */
137 typedef u_long (*strtoulfn
) __P((const char*, char**, int));
139 /* conversion function (strtol/strtoul) */
140 char ccltab
[256]; /* character class table for %[...] */
141 char buf
[BUF
]; /* buffer for numeric conversions */
144 /* `basefix' is used to avoid `if' tests in the integer scanner */
145 static short basefix
[17] =
146 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
174 * switch on the format. continue if done;
175 * break once format type is derived.
192 if (flags
) goto control_failure
;
196 if (flags
& ~(SUPPRESS
| WIDTH
)) goto control_failure
;
200 if (flags
& ~(SUPPRESS
| WIDTH
)) goto control_failure
;
204 if (flags
& ~(SUPPRESS
| WIDTH
)) goto control_failure
;
208 case '0': case '1': case '2': case '3': case '4':
209 case '5': case '6': case '7': case '8': case '9':
210 if (flags
& ~(SUPPRESS
| WIDTH
)) goto control_failure
;
212 width
= width
* 10 + c
- '0';
217 * Those marked `compat' are for 4.[123]BSD compatibility.
219 * (According to ANSI, E and X formats are supposed
220 * to the same as e and x. Sorry about that.)
222 case 'D': /* compat */
227 ccfn
= (strtoulfn
)strtol
;
233 ccfn
= (strtoulfn
)strtol
;
237 case 'O': /* compat */
254 flags
|= PFXOK
; /* enable 0x prefixing */
260 #ifdef FLOATING_POINT
262 case 'e': case 'f': case 'g':
272 fmt
= __sccl(ccltab
, fmt
);
282 case 'p': /* pointer format is like hex */
283 flags
|= POINTER
| PFXOK
;
290 if (flags
& SUPPRESS
) /* ??? */
293 *va_arg(ap
, short *) = nread
;
294 else if (flags
& LONG
)
295 *va_arg(ap
, long *) = nread
;
297 *va_arg(ap
, int *) = nread
;
301 * Disgusting backwards compatibility hacks. XXX
303 case '\0': /* compat */
307 default: /* compat */
311 ccfn
= (strtoulfn
)strtol
;
317 * We have a conversion that requires input.
319 if (_IO_peekc(fp
) == EOF
)
323 * Consume leading white space, except for formats
324 * that suppress this.
326 if ((flags
& NOSKIP
) == 0) {
327 n
= (unsigned char)*fp
->_IO_read_ptr
;
335 /* Note that there is at least one character in
336 the buffer, so conversions that do not set NOSKIP
337 can no longer result in an input failure. */
346 /* scan arbitrary characters (sets NOSKIP) */
347 if (width
== 0) /* FIXME! */
349 if (flags
& SUPPRESS
) {
352 n
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
353 if (n
< (int)width
) {
356 fp
->_IO_read_ptr
+= n
;
357 if (__underflow(fp
) == EOF
)
366 fp
->_IO_read_ptr
+= width
;
374 _IO_XSGETN (fp
, (char*)va_arg(ap
, char*), width
);
383 /* scan a (nonempty) character class (sets NOSKIP) */
385 width
= ~0; /* `infinity' */
386 /* take only those things in the class */
387 if (flags
& SUPPRESS
) {
389 while (ccltab
[(unsigned char)*fp
->_IO_read_ptr
]) {
390 n
++, fp
->_IO_read_ptr
++;
393 if (_IO_peekc(fp
) == EOF
) {
403 p0
= p
= va_arg(ap
, char *);
404 while (ccltab
[(unsigned char)*fp
->_IO_read_ptr
]) {
405 *p
++ = *fp
->_IO_read_ptr
++;
408 if (_IO_peekc(fp
) == EOF
) {
425 /* like CCL, but zero-length string OK, & no NOSKIP */
428 if (flags
& SUPPRESS
) {
430 while (!isspace((unsigned char)*fp
->_IO_read_ptr
)) {
431 n
++, fp
->_IO_read_ptr
++;
434 if (_IO_peekc(fp
) == EOF
) {
441 p0
= p
= va_arg(ap
, char *);
442 while (!isspace((unsigned char)*fp
->_IO_read_ptr
)) {
443 *p
++ = *fp
->_IO_read_ptr
++;
446 if (_IO_peekc(fp
) == EOF
) {
458 /* scan an integer as if by strtol/strtoul */
459 if (width
== 0 || width
> sizeof(buf
) - 1)
460 width
= sizeof(buf
) - 1;
461 flags
|= SIGNOK
| NDIGITS
| NZDIGITS
;
462 for (p
= buf
; width
; width
--) {
463 c
= (unsigned char)*fp
->_IO_read_ptr
;
465 * Switch on the character; `goto ok'
466 * if we accept it as a part of number.
471 * The digit 0 is always legal, but is
472 * special. For %i conversions, if no
473 * digits (zero or nonzero) have been
474 * scanned (only signs), we will have
475 * base==0. In that case, we should set
476 * it to 8 and enable 0x prefixing.
477 * Also, if we have not scanned zero digits
478 * before this, do not turn off prefixing
479 * (someone else will turn it off if we
480 * have scanned any nonzero digits).
487 if (flags
& NZDIGITS
)
488 flags
&= ~(SIGNOK
|NZDIGITS
|NDIGITS
);
490 flags
&= ~(SIGNOK
|PFXOK
|NDIGITS
);
493 /* 1 through 7 always legal */
494 case '1': case '2': case '3':
495 case '4': case '5': case '6': case '7':
496 base
= basefix
[base
];
497 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
500 /* digits 8 and 9 ok iff decimal or hex */
502 base
= basefix
[base
];
504 break; /* not legal here */
505 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
508 /* letters ok iff hex */
509 case 'A': case 'B': case 'C':
510 case 'D': case 'E': case 'F':
511 case 'a': case 'b': case 'c':
512 case 'd': case 'e': case 'f':
513 /* no need to fix base here */
515 break; /* not legal here */
516 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
519 /* sign ok only as first character */
521 if (flags
& SIGNOK
) {
527 /* x ok iff flag still set & 2nd char */
529 if (flags
& PFXOK
&& p
== buf
+ 1) {
530 base
= 16; /* if %i */
538 * If we got here, c is not a legal character
539 * for a number. Stop accumulating digits.
544 * c is legal: store it and look at the next.
548 if (_IO_peekc(fp
) == EOF
) {
554 * If we had only a sign, it is no good; push
555 * back the sign. If the number ends in `x',
556 * it was [sign] '0' 'x', so push back the x
557 * and treat it as [sign] '0'.
559 if (flags
& NDIGITS
) {
561 (void) _IO_ungetc(*(u_char
*)--p
, fp
);
564 c
= ((u_char
*)p
)[-1];
565 if (c
== 'x' || c
== 'X') {
567 (void) _IO_ungetc (c
, fp
);
569 if ((flags
& SUPPRESS
) == 0) {
573 res
= (*ccfn
)(buf
, (char **)NULL
, base
);
575 *va_arg(ap
, void **) = (void *)res
;
576 else if (flags
& SHORT
)
577 *va_arg(ap
, short *) = res
;
578 else if (flags
& LONG
)
579 *va_arg(ap
, long *) = res
;
581 *va_arg(ap
, int *) = res
;
587 #ifdef FLOATING_POINT
589 /* scan a floating point number as if by strtod */
590 if (width
== 0 || width
> sizeof(buf
) - 1)
591 width
= sizeof(buf
) - 1;
592 flags
|= SIGNOK
| NDIGITS
| DPTOK
| EXPOK
;
593 for (p
= buf
; width
; width
--) {
594 c
= (unsigned char)*fp
->_IO_read_ptr
;
596 * This code mimicks the integer conversion
597 * code, but is much simpler.
601 case '0': case '1': case '2': case '3':
602 case '4': case '5': case '6': case '7':
604 flags
&= ~(SIGNOK
| NDIGITS
);
608 if (flags
& SIGNOK
) {
615 flags
&= ~(SIGNOK
| DPTOK
);
620 /* no exponent without some digits */
621 if ((flags
&(NDIGITS
|EXPOK
)) == EXPOK
) {
623 (flags
& ~(EXPOK
|DPTOK
)) |
633 if (_IO_peekc(fp
) == EOF
) {
639 * If no digits, might be missing exponent digits
640 * (just give back the exponent) or might be missing
641 * regular digits, but had sign and/or decimal point.
643 if (flags
& NDIGITS
) {
645 /* no digits at all */
647 _IO_ungetc (*(u_char
*)--p
, fp
);
650 /* just a bad exponent (e and maybe sign) */
652 if (c
!= 'e' && c
!= 'E') {
653 (void) _IO_ungetc (c
, fp
);/* sign */
656 (void) _IO_ungetc (c
, fp
);
658 if ((flags
& SUPPRESS
) == 0) {
662 res
= _IO_strtod(buf
, NULL
);
667 *va_arg(ap
, double *) = res
;
669 *va_arg(ap
, float *) = res
;
674 #endif /* FLOATING_POINT */
687 if (errp
&& seen_eof
)
693 * Fill in the given table from the scanset at the given format
694 * (just after `['). Return a pointer to the character past the
695 * closing `]'. The table has a 1 wherever characters should be
696 * considered part of the scanset.
698 static const u_char
*
699 DEFUN(__sccl
, (tab
, fmt
),
700 register char *tab AND
register const u_char
*fmt
)
702 register int c
, n
, v
;
704 /* first `clear' the whole table */
705 c
= *fmt
++; /* first char hat => negated scanset */
707 v
= 1; /* default => accept */
708 c
= *fmt
++; /* get new first char */
710 v
= 0; /* default => reject */
711 /* should probably use memset here */
712 for (n
= 0; n
< 256; n
++)
715 return (fmt
- 1);/* format ended before closing ] */
718 * Now set the entries corresponding to the actual scanset
719 * to the opposite of the above.
721 * The first character may be ']' (or '-') without being special;
722 * the last character may be '-'.
726 tab
[c
] = v
; /* take character c */
728 n
= *fmt
++; /* and examine the next */
731 case 0: /* format ended too soon */
736 * A scanset of the form
738 * is defined as `the digit 0, the digit 1,
739 * the character +, the character -', but
740 * the effect of a scanset such as
742 * is implementation defined. The V7 Unix
743 * scanf treats `a-z' as `the letters a through
744 * z', but treats `a-a' as `the letter a, the
745 * character -, and the letter a'.
747 * For compatibility, the `-' is not considerd
748 * to define a range if the character following
749 * it is either a close bracket (required by ANSI)
750 * or is not numerically greater than the character
751 * we just stored in the table (c).
754 if (n
== ']' || n
< c
) {
756 break; /* resume the for(;;) */
759 do { /* fill in the range */
762 #if 1 /* XXX another disgusting compatibility hack */
764 * Alas, the V7 Unix scanf also treats formats
765 * such as [a-c-e] as `the letters a through e'.
766 * This too is permitted by the standard....
778 case ']': /* end of scanset */
781 default: /* just another character */