Contiki 2.6
|
00001 /* 00002 FUNCTION 00003 <<vscanf>>, <<vfscanf>>, <<vsscanf>>---format argument list 00004 00005 INDEX 00006 vscanf 00007 INDEX 00008 vfscanf 00009 INDEX 00010 vsscanf 00011 00012 ANSI_SYNOPSIS 00013 #include <stdio.h> 00014 #include <stdarg.h> 00015 int vscanf(const char *<[fmt]>, va_list <[list]>); 00016 int vfscanf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>); 00017 int vsscanf(const char *<[str]>, const char *<[fmt]>, va_list <[list]>); 00018 00019 int _vscanf_r(void *<[reent]>, const char *<[fmt]>, 00020 va_list <[list]>); 00021 int _vfscanf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>, 00022 va_list <[list]>); 00023 int _vsscanf_r(void *<[reent]>, const char *<[str]>, const char *<[fmt]>, 00024 va_list <[list]>); 00025 00026 TRAD_SYNOPSIS 00027 #include <stdio.h> 00028 #include <varargs.h> 00029 int vscanf( <[fmt]>, <[ist]>) 00030 char *<[fmt]>; 00031 va_list <[list]>; 00032 00033 int vfscanf( <[fp]>, <[fmt]>, <[list]>) 00034 FILE *<[fp]>; 00035 char *<[fmt]>; 00036 va_list <[list]>; 00037 00038 int vsscanf( <[str]>, <[fmt]>, <[list]>) 00039 char *<[str]>; 00040 char *<[fmt]>; 00041 va_list <[list]>; 00042 00043 int _vscanf_r( <[reent]>, <[fmt]>, <[ist]>) 00044 char *<[reent]>; 00045 char *<[fmt]>; 00046 va_list <[list]>; 00047 00048 int _vfscanf_r( <[reent]>, <[fp]>, <[fmt]>, <[list]>) 00049 char *<[reent]>; 00050 FILE *<[fp]>; 00051 char *<[fmt]>; 00052 va_list <[list]>; 00053 00054 int _vsscanf_r( <[reent]>, <[str]>, <[fmt]>, <[list]>) 00055 char *<[reent]>; 00056 char *<[str]>; 00057 char *<[fmt]>; 00058 va_list <[list]>; 00059 00060 DESCRIPTION 00061 <<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants 00062 of <<scanf>>, <<fscanf>>, and <<sscanf>>. They differ only in 00063 allowing their caller to pass the variable argument list as a 00064 <<va_list>> object (initialized by <<va_start>>) rather than 00065 directly accepting a variable number of arguments. 00066 00067 RETURNS 00068 The return values are consistent with the corresponding functions: 00069 <<vscanf>> returns the number of input fields successfully scanned, 00070 converted, and stored; the return value does not include scanned 00071 fields which were not stored. 00072 00073 If <<vscanf>> attempts to read at end-of-file, the return value 00074 is <<EOF>>. 00075 00076 If no fields were stored, the return value is <<0>>. 00077 00078 The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are 00079 reentrant versions which take an additional first parameter which points to the 00080 reentrancy structure. 00081 00082 PORTABILITY 00083 These are GNU extensions. 00084 00085 Supporting OS subroutines required: 00086 */ 00087 00088 /*- 00089 * Copyright (c) 1990 The Regents of the University of California. 00090 * All rights reserved. 00091 * 00092 * Redistribution and use in source and binary forms are permitted 00093 * provided that the above copyright notice and this paragraph are 00094 * duplicated in all such forms and that any documentation, 00095 * advertising materials, and other materials related to such 00096 * distribution and use acknowledge that the software was developed 00097 * by the University of California, Berkeley. The name of the 00098 * University may not be used to endorse or promote products derived 00099 * from this software without specific prior written permission. 00100 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00101 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00102 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00103 */ 00104 00105 00106 00107 #include <_ansi.h> 00108 //#include <ctype.h> 00109 #include <wctype.h> 00110 #include <stdio.h> 00111 #include <stdlib.h> 00112 #include <limits.h> 00113 #include <wchar.h> 00114 #include <string.h> 00115 00116 00117 #ifdef _HAVE_STDC 00118 #include <stdarg.h> 00119 #else 00120 #include <varargs.h> 00121 #endif 00122 00123 #ifndef SMALL_SCANF 00124 #include "local.h" 00125 #endif 00126 00127 00128 #ifndef NO_FLOATING_POINT 00129 #include <float.h> 00130 #endif 00131 00132 00133 00134 #ifndef NO_FLOATING_POINT 00135 #define FLOATING_POINT 00136 #endif 00137 00138 #ifdef FLOATING_POINT 00139 #include <float.h> 00140 00141 /* Currently a test is made to see if long double processing is warranted. 00142 This could be changed in the future should the _ldtoa_r code be 00143 preferred over _dtoa_r. */ 00144 #define _NO_LONGDBL 00145 #if defined WANT_IO_LONG_DBL && (LDBL_MANT_DIG > DBL_MANT_DIG) 00146 #undef _NO_LONGDBL 00147 extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr)); 00148 #endif 00149 00150 #define _NO_LONGLONG 00151 #if defined WANT_PRINTF_LONG_LONG && defined __GNUC__ 00152 # undef _NO_LONGLONG 00153 #endif 00154 00155 #include "floatio.h" 00156 00157 #if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX) 00158 # define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */ 00159 #else 00160 # define BUF MB_LEN_MAX 00161 #endif 00162 00163 /* An upper bound for how long a long prints in decimal. 4 / 13 approximates 00164 log (2). Add one char for roundoff compensation and one for the sign. */ 00165 #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2) 00166 #else 00167 #define BUF 40 00168 #endif 00169 00170 00171 /* 00172 * Flags used during conversion. 00173 */ 00174 00175 #define LONG 0x01 /* l: long or double */ 00176 #define LONGDBL 0x02 /* L/ll: long double or long long */ 00177 #define SHORT 0x04 /* h: short */ 00178 #define CHAR 0x08 /* hh: 8 bit integer */ 00179 #define SUPPRESS 0x10 /* suppress assignment */ 00180 #define POINTER 0x20 /* weird %p pointer (`fake hex') */ 00181 #define NOSKIP 0x40 /* do not skip blanks */ 00182 00183 /* 00184 * The following are used in numeric conversions only: 00185 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; 00186 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. 00187 */ 00188 00189 #define SIGNOK 0x80 /* +/- is (still) legal */ 00190 #define NDIGITS 0x100 /* no digits detected */ 00191 00192 #define DPTOK 0x200 /* (float) decimal point is still legal */ 00193 #define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */ 00194 00195 #define PFXOK 0x200 /* 0x prefix is (still) legal */ 00196 #define NZDIGITS 0x400 /* no zero digits detected */ 00197 00198 /* 00199 * Conversion types. 00200 */ 00201 00202 #define CT_CHAR 0 /* %c conversion */ 00203 #define CT_CCL 1 /* %[...] conversion */ 00204 #define CT_STRING 2 /* %s conversion */ 00205 #define CT_INT 3 /* integer, i.e., strtol or strtoul */ 00206 #define CT_FLOAT 4 /* floating, i.e., strtod */ 00207 00208 #if 0 00209 #define u_char unsigned char 00210 #endif 00211 #define u_char char 00212 #define u_long unsigned long 00213 00214 #ifndef _NO_LONGLONG 00215 typedef unsigned long long u_long_long; 00216 #endif 00217 00218 /*static*/ u_char *__sccl (); 00219 00220 /* 00221 * vfscanf 00222 */ 00223 00224 #ifndef SMALL_SCANF 00225 #define BufferEmpty (fp->_r <= 0 && __srefill(fp)) 00226 00227 #else // SMALL_SCANF 00228 00229 unsigned char buf_ungetc ; 00230 int flag_buf_ungetc = 0 ; 00231 #define buf_ungetc_empty 0 00232 #define buf_ungetc_full 1 00233 00234 00235 /* 00236 Redefinition of ungetc : store in a buffer a character 00237 Only ONE ungetc is allowed before a getchar 00238 For each getchar, new_getchar() is called, then the buf is tested: 00239 - if flag_buf_ungetc == 0 : new_getchar call __io_getchar() 00240 - if flag_buf_ungetc == 1 : new_getchar returns character in the buffer 00241 00242 */ 00243 00244 00245 00246 00247 int __io_ungetc(int c){ 00248 00249 if (flag_buf_ungetc == 0){ 00250 flag_buf_ungetc = buf_ungetc_full; //flag to 1 to indicate that a caracter is in the buffer 00251 } 00252 buf_ungetc= (unsigned char)c ; 00253 00254 return (c); 00255 } 00256 00257 int new_getchar() { 00258 if (flag_buf_ungetc == 0){ 00259 00260 return __io_getchar(); 00261 00262 } 00263 else { 00264 00265 flag_buf_ungetc = buf_ungetc_empty; 00266 return buf_ungetc; 00267 00268 } 00269 00270 } 00271 00272 #endif // SMALL_SCANF 00273 00274 #ifndef _REENT_ONLY 00275 00276 int 00277 _DEFUN (vfscanf, (fp, fmt, ap), 00278 register FILE *fp _AND 00279 _CONST char *fmt _AND 00280 va_list ap) 00281 { 00282 00283 #ifndef SMALL_SCANF 00284 CHECK_INIT(fp); 00285 #endif 00286 00287 return __svfscanf_r (_REENT, fp, fmt, ap); 00288 } 00289 00290 int 00291 __svfscanf (fp, fmt0, ap) 00292 register FILE *fp; 00293 char _CONST *fmt0; 00294 va_list ap; 00295 { 00296 return __svfscanf_r (_REENT, fp, fmt0, ap); 00297 } 00298 00299 #endif /* !_REENT_ONLY */ 00300 00301 int 00302 _DEFUN (_vfscanf_r, (data, fp, fmt, ap), 00303 struct _reent *data _AND 00304 register FILE *fp _AND 00305 _CONST char *fmt _AND 00306 va_list ap) 00307 { 00308 return __svfscanf_r (data, fp, fmt, ap); 00309 } 00310 00311 00312 00313 /* 00314 00315 00316 For SMALL_SCANF : 00317 The use of files has been removed so as to use directly __io_getchar() 00318 Buffer_empty is not anymore tested since _io_getchar() is blocked until 00319 a character is entered. 00320 Generally each *fp->_p ++ which equal to read a character on the file 00321 has been replaced by a new_getchar() which call __io_getchar(); 00322 00323 00324 */ 00325 00326 int 00327 __svfscanf_r (rptr, fp, fmt0, ap) 00328 struct _reent *rptr; 00329 register FILE *fp; 00330 char _CONST *fmt0; 00331 va_list ap; 00332 { 00333 00334 register char * bufread; 00335 register u_char *fmt = (u_char *) fmt0; 00336 register int c; /* character from format, or conversion */ 00337 register int car; 00338 register size_t width; /* field width, or 0 */ 00339 register char *p; /* points into all kinds of strings */ 00340 register int n; /* handy integer */ 00341 register int flags; /* flags as defined above */ 00342 register char *p0; /* saves original value of p when necessary */ 00343 int nassigned; /* number of fields assigned */ 00344 int nread; /* number of characters consumed from fp */ 00345 int base = 0; /* base argument to strtol/strtoul */ 00346 int nbytes = 1; /* number of bytes read from fmt string */ 00347 wchar_t wc; /* wchar to use to read format string */ 00348 wchar_t *wcp; /* handy wide character pointer */ 00349 size_t mbslen; /* length of converted multibyte sequence */ 00350 mbstate_t state; /* value to keep track of multibyte state */ 00351 00352 u_long (*ccfn) () = 0; /* conversion function (strtol/strtoul) */ 00353 char ccltab[256]; /* character class table for %[...] */ 00354 char buf[BUF]; /* buffer for numeric conversions */ 00355 char *lptr; /* literal pointer */ 00356 00357 char *cp; 00358 short *sp; 00359 int *ip; 00360 float *flp; 00361 _LONG_DOUBLE *ldp; 00362 double *dp; 00363 long *lp; 00364 #ifndef _NO_LONGLONG 00365 long long *llp; 00366 #endif 00367 00368 /* `basefix' is used to avoid `if' tests in the integer scanner */ 00369 static _CONST short basefix[17] = 00370 {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 00371 00372 nassigned = 0; 00373 nread = 0; 00374 for (;;) 00375 { 00376 #ifndef MB_CAPABLE 00377 wc = *fmt; 00378 #else 00379 memset (&state, '\0', sizeof (state)); 00380 nbytes = _mbtowc_r (rptr, &wc, fmt, MB_CUR_MAX, &state); 00381 #endif 00382 fmt += nbytes; 00383 if (wc == 0) 00384 return nassigned; 00385 if (nbytes == 1 && isspace (wc)) 00386 { 00387 for (;;) 00388 { 00389 #ifndef SMALL_SCANF 00390 if (BufferEmpty || !isspace (*fp->_p)) 00391 break; 00392 nread++, fp->_r--, fp->_p++; 00393 00394 #else 00395 if (!isspace (*fp->_p)) break; 00396 nread++, fp->_r--; 00397 *fp->_p = new_getchar(); 00398 00399 #endif 00400 } 00401 00402 continue; 00403 } 00404 if (wc != '%') 00405 goto literal; 00406 width = 0; 00407 flags = 0; 00408 00409 /* 00410 * switch on the format. continue if done; break once format 00411 * type is derived. 00412 */ 00413 00414 again: 00415 c = *fmt++; 00416 switch (c) 00417 { 00418 case '%': 00419 literal: 00420 lptr = fmt - nbytes; 00421 for (n = 0; n < nbytes; ++n) 00422 { 00423 #ifndef SMALL_SCANF 00424 if (BufferEmpty) 00425 goto input_failure; 00426 #else 00427 *fp->_p = new_getchar(); 00428 #endif 00429 00430 if (*fp->_p != *lptr) 00431 goto match_failure; 00432 #ifndef SMALL_SCANF 00433 fp->_r--, fp->_p++; 00434 nread++; 00435 #else 00436 fp->_r--; 00437 *fp->_p = new_getchar(); 00438 nread++; 00439 #endif 00440 ++lptr; 00441 } 00442 continue; 00443 00444 case '*': 00445 flags |= SUPPRESS; 00446 goto again; 00447 case 'l': 00448 if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */ 00449 { 00450 ++fmt; 00451 flags |= LONGDBL; 00452 } 00453 else 00454 flags |= LONG; 00455 goto again; 00456 case 'L': 00457 flags |= LONGDBL; 00458 goto again; 00459 case 'h': 00460 if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */ 00461 { 00462 ++fmt; 00463 flags |= CHAR; 00464 } 00465 else 00466 flags |= SHORT; 00467 goto again; 00468 00469 case '0': 00470 case '1': 00471 case '2': 00472 case '3': 00473 case '4': 00474 case '5': 00475 case '6': 00476 case '7': 00477 case '8': 00478 case '9': 00479 width = width * 10 + c - '0'; 00480 goto again; 00481 00482 /* 00483 * Conversions. Those marked `compat' are for 00484 * 4.[123]BSD compatibility. 00485 * 00486 * (According to ANSI, E and X formats are supposed to 00487 * the same as e and x. Sorry about that.) 00488 */ 00489 00490 case 'D': /* compat */ 00491 flags |= LONG; 00492 /* FALLTHROUGH */ 00493 case 'd': 00494 c = CT_INT; 00495 ccfn = (u_long (*)())_strtol_r; 00496 base = 10; 00497 break; 00498 00499 case 'i': 00500 c = CT_INT; 00501 ccfn = (u_long (*)())_strtol_r; 00502 base = 0; 00503 break; 00504 00505 case 'O': /* compat */ 00506 flags |= LONG; 00507 /* FALLTHROUGH */ 00508 case 'o': 00509 c = CT_INT; 00510 ccfn = _strtoul_r; 00511 base = 8; 00512 break; 00513 00514 case 'u': 00515 c = CT_INT; 00516 ccfn = _strtoul_r; 00517 base = 10; 00518 break; 00519 00520 case 'X': /* compat XXX */ 00521 case 'x': 00522 flags |= PFXOK; /* enable 0x prefixing */ 00523 c = CT_INT; 00524 ccfn = _strtoul_r; 00525 base = 16; 00526 break; 00527 00528 #ifdef FLOATING_POINT 00529 case 'E': /* compat XXX */ 00530 case 'G': /* compat XXX */ 00531 /* ANSI says that E,G and X behave the same way as e,g,x */ 00532 /* FALLTHROUGH */ 00533 case 'e': 00534 case 'f': 00535 case 'g': 00536 c = CT_FLOAT; 00537 break; 00538 #endif 00539 case 'S': 00540 flags |= LONG; 00541 /* FALLTHROUGH */ 00542 00543 case 's': 00544 c = CT_STRING; 00545 break; 00546 00547 case '[': 00548 fmt = __sccl (ccltab, fmt); 00549 flags |= NOSKIP; 00550 c = CT_CCL; 00551 break; 00552 00553 case 'C': 00554 flags |= LONG; 00555 /* FALLTHROUGH */ 00556 00557 case 'c': 00558 flags |= NOSKIP; 00559 c = CT_CHAR; 00560 break; 00561 00562 case 'p': /* pointer format is like hex */ 00563 flags |= POINTER | PFXOK; 00564 c = CT_INT; 00565 ccfn = _strtoul_r; 00566 base = 16; 00567 break; 00568 00569 case 'n': 00570 if (flags & SUPPRESS) /* ??? */ 00571 continue; 00572 if (flags & CHAR) 00573 { 00574 cp = va_arg (ap, char *); 00575 *cp = nread; 00576 } 00577 else if (flags & SHORT) 00578 { 00579 sp = va_arg (ap, short *); 00580 *sp = nread; 00581 } 00582 else if (flags & LONG) 00583 { 00584 lp = va_arg (ap, long *); 00585 *lp = nread; 00586 } 00587 #ifndef _NO_LONGLONG 00588 else if (flags & LONGDBL) 00589 { 00590 llp = va_arg (ap, long long*); 00591 *llp = nread; 00592 } 00593 #endif 00594 else 00595 { 00596 ip = va_arg (ap, int *); 00597 *ip = nread; 00598 } 00599 continue; 00600 00601 /* 00602 * Disgusting backwards compatibility hacks. XXX 00603 */ 00604 case '\0': /* compat */ 00605 return EOF; 00606 00607 default: /* compat */ 00608 if (isupper (c)) 00609 flags |= LONG; 00610 c = CT_INT; 00611 ccfn = (u_long (*)())_strtol_r; 00612 base = 10; 00613 break; 00614 } 00615 00616 /* 00617 * We have a conversion that requires input. 00618 */ 00619 #ifndef SMALL_SCANF 00620 if (BufferEmpty) 00621 goto input_failure; 00622 #else 00623 *fp->_p = new_getchar(); 00624 #endif 00625 00626 /* 00627 * Consume leading white space, except for formats that 00628 * suppress this. 00629 */ 00630 00631 if ((flags & NOSKIP) == 0) 00632 { 00633 while (isspace (*fp->_p)) 00634 { 00635 #ifndef SMALL_SCANF 00636 nread++; 00637 if (--fp->_r > 0) 00638 fp->_p++; 00639 else 00640 if (__srefill (fp)) 00641 goto input_failure; 00642 #else 00643 *fp->_p = new_getchar(); 00644 #endif 00645 } 00646 /* 00647 * Note that there is at least one character in the 00648 * buffer, so conversions that do not set NOSKIP ca 00649 * no longer result in an input failure. 00650 */ 00651 } 00652 00653 /* 00654 * Do the conversion. 00655 */ 00656 switch (c) 00657 { 00658 00659 case CT_CHAR: 00660 /* scan arbitrary characters (sets NOSKIP) */ 00661 if (width == 0) 00662 width = 1; 00663 if (flags & LONG) 00664 { 00665 if ((flags & SUPPRESS) == 0) 00666 wcp = va_arg(ap, wchar_t *); 00667 else 00668 wcp = NULL; 00669 n = 0; 00670 while (width != 0) 00671 { 00672 00673 if (n == MB_CUR_MAX) 00674 goto input_failure; 00675 #ifndef SMALL_SCANF 00676 buf[n++] = *fp->_p; 00677 fp->_r -= 1; 00678 fp->_p += 1; 00679 memset((void *)&state, '\0', sizeof(mbstate_t)); 00680 if ((mbslen = _mbrtowc_r(rptr, wcp, buf, n, &state)) 00681 == (size_t)-1) 00682 goto input_failure; /* Invalid sequence */ 00683 #else 00684 buf[n++] = *fp->_p; 00685 *fp->_p = new_getchar(); 00686 00687 #endif 00688 00689 if (mbslen == 0 && !(flags & SUPPRESS)) 00690 *wcp = L'\0'; 00691 if (mbslen != (size_t)-2) /* Incomplete sequence */ 00692 { 00693 nread += n; 00694 width -= 1; 00695 if (!(flags & SUPPRESS)) 00696 wcp += 1; 00697 n = 0; 00698 } 00699 #ifndef SMALL_SCANF 00700 if (BufferEmpty) 00701 { 00702 if (n != 0) 00703 goto input_failure; 00704 break; 00705 } 00706 #endif 00707 } 00708 if (!(flags & SUPPRESS)) 00709 nassigned++; 00710 } 00711 else if (flags & SUPPRESS) 00712 { 00713 size_t sum = 0; 00714 for (;;) 00715 { 00716 if ((n = fp->_r) < (int)width) 00717 { 00718 sum += n; 00719 width -= n; 00720 #ifndef SMALL_SCANF 00721 fp->_p += n; 00722 if (__srefill (fp)) 00723 { 00724 if (sum == 0) 00725 goto input_failure; 00726 break; 00727 } 00728 #else 00729 *fp->_p = new_getchar(); 00730 #endif 00731 00732 } 00733 else 00734 { 00735 sum += width; 00736 fp->_r -= width; 00737 #ifndef SMALL_SCANF 00738 fp->_p += width; 00739 #else 00740 *fp->_p = new_getchar(); 00741 #endif 00742 00743 break; 00744 } 00745 } 00746 nread += sum; 00747 } 00748 else 00749 { 00750 00751 #ifndef SMALL_SCANF 00752 size_t r = fread ((_PTR) va_arg (ap, char *), 1, width, fp); 00753 if (r == 0) 00754 goto input_failure; 00755 nread += r; 00756 nassigned++; 00757 00758 #else 00759 bufread=(_PTR)va_arg(ap,char *); 00760 int r; 00761 for (r=0;r<width;r++){ 00762 *bufread++= *fp->_p; 00763 if ( r+1 < width){ 00764 *fp->_p = new_getchar(); 00765 } 00766 } 00767 #endif 00768 } 00769 break; 00770 00771 case CT_CCL: 00772 /* scan a (nonempty) character class (sets NOSKIP) */ 00773 if (width == 0) 00774 width = ~0; /* `infinity' */ 00775 /* take only those things in the class */ 00776 if (flags & SUPPRESS) 00777 { 00778 n = 0; 00779 while (ccltab[*fp->_p]) 00780 { 00781 #ifndef SMALL_SCANF 00782 n++, fp->_r--, fp->_p++; 00783 if (--width == 0) 00784 break; 00785 if (BufferEmpty) 00786 { 00787 if (n == 0) 00788 goto input_failure; 00789 break; 00790 } 00791 #else 00792 n++; 00793 fp->_r++; 00794 *fp->_p = new_getchar(); 00795 #endif 00796 00797 } 00798 if (n == 0) 00799 goto match_failure; 00800 } 00801 else 00802 { 00803 p0 = p = va_arg (ap, char *); 00804 while (ccltab[*fp->_p]) 00805 { 00806 fp->_r--; 00807 #ifndef SMALL_SCANF 00808 *p++ = *fp->_p++; 00809 if (--width == 0) 00810 break; 00811 if (BufferEmpty) 00812 { 00813 if (p == p0) 00814 goto input_failure; 00815 break; 00816 } 00817 #else 00818 *p++ = *fp->_p; 00819 *fp->_p= new_getchar(); 00820 if (--width == 0) 00821 break; 00822 #endif 00823 00824 } 00825 n = p - p0; 00826 if (n == 0) 00827 goto match_failure; 00828 *p = 0; 00829 nassigned++; 00830 } 00831 nread += n; 00832 break; 00833 00834 case CT_STRING: 00835 /* like CCL, but zero-length string OK, & no NOSKIP */ 00836 00837 if (width == 0) 00838 width = (size_t)~0; 00839 if (flags & LONG) 00840 { 00841 /* Process %S and %ls placeholders */ 00842 if ((flags & SUPPRESS) == 0) 00843 wcp = va_arg(ap, wchar_t *); 00844 else 00845 wcp = &wc; 00846 n = 0; 00847 while (!isspace(*fp->_p) && width != 0) 00848 { 00849 if (n == MB_CUR_MAX) 00850 goto input_failure; 00851 buf[n++] = *fp->_p; 00852 fp->_r -= 1; 00853 #ifndef SMALL_SCANF 00854 fp->_p += 1; 00855 memset((void *)&state, '\0', sizeof(mbstate_t)); 00856 if ((mbslen = _mbrtowc_r(rptr, wcp, buf, n, &state)) 00857 == (size_t)-1) 00858 goto input_failure; 00859 #else 00860 *fp->_p = new_getchar(); 00861 #endif 00862 00863 if (mbslen == 0) 00864 *wcp = L'\0'; 00865 00866 if (mbslen != (size_t)-2) /* Incomplete sequence */ 00867 { 00868 if (iswspace(*wcp)) 00869 { 00870 00871 while (n != 0) 00872 #ifndef SMALL_SCANF 00873 ungetc(buf[--n], fp); 00874 #else 00875 __io_ungetc(buf[--n]); 00876 #endif 00877 break; 00878 00879 } 00880 00881 nread += n; 00882 width -= 1; 00883 if ((flags & SUPPRESS) == 0) 00884 wcp += 1; 00885 n = 0; 00886 } 00887 #ifndef SMALL_SCANF 00888 if (BufferEmpty) 00889 { 00890 if (n != 0) 00891 goto input_failure; 00892 break; 00893 } 00894 #endif 00895 00896 } 00897 if (!(flags & SUPPRESS)) 00898 { 00899 *wcp = L'\0'; 00900 nassigned++; 00901 } 00902 } 00903 else if (flags & SUPPRESS) 00904 { 00905 n = 0; 00906 while (!isspace (*fp->_p)) 00907 { 00908 #ifndef SMALL_SCANF 00909 n++, fp->_r--, fp->_p++; 00910 if (--width == 0) 00911 break; 00912 if (BufferEmpty) 00913 break; 00914 #else 00915 n++; 00916 *fp->_p = new_getchar(); 00917 if (*fp->_p == '\0') break; 00918 #endif 00919 00920 } 00921 nread += n; 00922 } 00923 else 00924 { 00925 p0 = p = va_arg (ap, char *); 00926 while (!isspace (*fp->_p)) 00927 { 00928 #ifndef SMALL_SCANF 00929 fp->_r--; 00930 *p++ = *fp->_p++; 00931 if (--width == 0) 00932 break; 00933 if (BufferEmpty) 00934 break; 00935 #else 00936 *p++=*fp->_p; 00937 *fp->_p = new_getchar(); 00938 if (*fp->_p == '\0') break; 00939 #endif 00940 00941 00942 } 00943 *p = 0; 00944 nread += p - p0; 00945 nassigned++; 00946 } 00947 continue; 00948 00949 case CT_INT: 00950 /* scan an integer as if by strtol/strtoul */ 00951 #ifdef hardway 00952 if (width == 0 || width > sizeof (buf) - 1) 00953 width = sizeof (buf) - 1; 00954 #else 00955 /* size_t is unsigned, hence this optimisation */ 00956 if (--width > sizeof (buf) - 2) 00957 width = sizeof (buf) - 2; 00958 width++; 00959 #endif 00960 flags |= SIGNOK | NDIGITS | NZDIGITS; 00961 for (p = buf; width; width--) 00962 { 00963 c = *fp->_p; 00964 /* 00965 * Switch on the character; `goto ok' if we 00966 * accept it as a part of number. 00967 */ 00968 switch (c) 00969 { 00970 /* 00971 * The digit 0 is always legal, but is special. 00972 * For %i conversions, if no digits (zero or nonzero) 00973 * have been scanned (only signs), we will have base==0. 00974 * In that case, we should set it to 8 and enable 0x 00975 * prefixing. Also, if we have not scanned zero digits 00976 * before this, do not turn off prefixing (someone else 00977 * will turn it off if we have scanned any nonzero digits). 00978 */ 00979 case '0': 00980 if (base == 0) 00981 { 00982 base = 8; 00983 flags |= PFXOK; 00984 } 00985 if (flags & NZDIGITS) 00986 flags &= ~(SIGNOK | NZDIGITS | NDIGITS); 00987 else 00988 flags &= ~(SIGNOK | PFXOK | NDIGITS); 00989 goto ok; 00990 00991 /* 1 through 7 always legal */ 00992 case '1': 00993 case '2': 00994 case '3': 00995 case '4': 00996 case '5': 00997 case '6': 00998 case '7': 00999 base = basefix[base]; 01000 flags &= ~(SIGNOK | PFXOK | NDIGITS); 01001 goto ok; 01002 01003 /* digits 8 and 9 ok iff decimal or hex */ 01004 case '8': 01005 case '9': 01006 base = basefix[base]; 01007 if (base <= 8) 01008 break; /* not legal here */ 01009 flags &= ~(SIGNOK | PFXOK | NDIGITS); 01010 goto ok; 01011 01012 /* letters ok iff hex */ 01013 case 'A': 01014 case 'B': 01015 case 'C': 01016 case 'D': 01017 case 'E': 01018 case 'F': 01019 case 'a': 01020 case 'b': 01021 case 'c': 01022 case 'd': 01023 case 'e': 01024 case 'f': 01025 /* no need to fix base here */ 01026 if (base <= 10) 01027 break; /* not legal here */ 01028 flags &= ~(SIGNOK | PFXOK | NDIGITS); 01029 goto ok; 01030 01031 /* sign ok only as first character */ 01032 case '+': 01033 case '-': 01034 if (flags & SIGNOK) 01035 { 01036 flags &= ~SIGNOK; 01037 goto ok; 01038 } 01039 break; 01040 01041 /* x ok iff flag still set & 2nd char */ 01042 case 'x': 01043 case 'X': 01044 if (flags & PFXOK && p == buf + 1) 01045 { 01046 base = 16;/* if %i */ 01047 flags &= ~PFXOK; 01048 goto ok; 01049 } 01050 break; 01051 } 01052 /* 01053 * If we got here, c is not a legal character 01054 * for a number. Stop accumulating digits. 01055 */ 01056 01057 break; 01058 ok: 01059 /* 01060 * c is legal: store it and look at the next. 01061 */ 01062 *p++ = c; 01063 #ifndef SMALL_SCANF 01064 if (--fp->_r > 0) 01065 fp->_p++; 01066 else 01067 if (__srefill (fp)) 01068 break; /* EOF */ 01069 #else 01070 01071 *fp->_p = new_getchar(); 01072 01073 #endif 01074 01075 } 01076 /* 01077 * If we had only a sign, it is no good; push back the sign. 01078 * If the number ends in `x', it was [sign] '0' 'x', so push back 01079 * the x and treat it as [sign] '0'. 01080 */ 01081 01082 if (flags & NDIGITS) 01083 { 01084 if (p > buf) 01085 #ifndef SMALL_SCANF 01086 _CAST_VOID ungetc (*(u_char *)-- p, fp); 01087 #else 01088 _CAST_VOID __io_ungetc (*(u_char *)-- p); 01089 #endif 01090 goto match_failure; 01091 01092 } 01093 01094 c = ((u_char *) p)[-1]; 01095 if (c == 'x' || c == 'X') 01096 { 01097 --p; 01098 #ifndef SMALL_SCANF 01099 /*(void)*/ ungetc (c, fp); 01100 #else 01101 __io_ungetc (c); 01102 #endif 01103 01104 } 01105 if ((flags & SUPPRESS) == 0) 01106 { 01107 u_long res; 01108 01109 *p = 0; 01110 res = (*ccfn) (rptr, buf, (char **) NULL, base); 01111 if (flags & POINTER) 01112 *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res; 01113 else if (flags & CHAR) 01114 { 01115 cp = va_arg (ap, char *); 01116 *cp = res; 01117 } 01118 else if (flags & SHORT) 01119 { 01120 sp = va_arg (ap, short *); 01121 *sp = res; 01122 } 01123 else if (flags & LONG) 01124 { 01125 lp = va_arg (ap, long *); 01126 *lp = res; 01127 } 01128 #ifndef _NO_LONGLONG 01129 else if (flags & LONGDBL) 01130 { 01131 u_long_long resll; 01132 if (ccfn == _strtoul_r) 01133 resll = _strtoull_r (rptr, buf, (char **) NULL, base); 01134 else 01135 resll = _strtoll_r (rptr, buf, (char **) NULL, base); 01136 llp = va_arg (ap, long long*); 01137 *llp = resll; 01138 } 01139 #endif 01140 else 01141 { 01142 ip = va_arg (ap, int *); 01143 *ip = res; 01144 } 01145 nassigned++; 01146 } 01147 nread += p - buf; 01148 break; 01149 01150 #ifdef FLOATING_POINT 01151 case CT_FLOAT: 01152 { 01153 /* scan a floating point number as if by strtod */ 01154 /* This code used to assume that the number of digits is reasonable. 01155 However, ANSI / ISO C makes no such stipulation; we have to get 01156 exact results even when there is an unreasonable amount of 01157 leading zeroes. */ 01158 long leading_zeroes = 0; 01159 long zeroes, exp_adjust; 01160 char *exp_start = NULL; 01161 #ifdef hardway 01162 if (width == 0 || width > sizeof (buf) - 1) 01163 width = sizeof (buf) - 1; 01164 #else 01165 /* size_t is unsigned, hence this optimisation */ 01166 if (--width > sizeof (buf) - 2) 01167 width = sizeof (buf) - 2; 01168 width++; 01169 #endif 01170 flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; 01171 zeroes = 0; 01172 exp_adjust = 0; 01173 for (p = buf; width; ) 01174 { 01175 c = *fp->_p; 01176 /* 01177 * This code mimicks the integer conversion 01178 * code, but is much simpler. 01179 */ 01180 switch (c) 01181 { 01182 01183 case '0': 01184 if (flags & NDIGITS) 01185 { 01186 flags &= ~SIGNOK; 01187 zeroes++; 01188 goto fskip; 01189 } 01190 /* Fall through. */ 01191 case '1': 01192 case '2': 01193 case '3': 01194 case '4': 01195 case '5': 01196 case '6': 01197 case '7': 01198 case '8': 01199 case '9': 01200 flags &= ~(SIGNOK | NDIGITS); 01201 goto fok; 01202 01203 case '+': 01204 case '-': 01205 if (flags & SIGNOK) 01206 { 01207 flags &= ~SIGNOK; 01208 goto fok; 01209 } 01210 break; 01211 case '.': 01212 if (flags & DPTOK) 01213 { 01214 flags &= ~(SIGNOK | DPTOK); 01215 leading_zeroes = zeroes; 01216 goto fok; 01217 } 01218 break; 01219 case 'e': 01220 case 'E': 01221 /* no exponent without some digits */ 01222 if ((flags & (NDIGITS | EXPOK)) == EXPOK 01223 || ((flags & EXPOK) && zeroes)) 01224 { 01225 if (! (flags & DPTOK)) 01226 { 01227 exp_adjust = zeroes - leading_zeroes; 01228 exp_start = p; 01229 } 01230 flags = 01231 (flags & ~(EXPOK | DPTOK)) | 01232 SIGNOK | NDIGITS; 01233 zeroes = 0; 01234 goto fok; 01235 } 01236 break; 01237 } 01238 break; 01239 fok: 01240 *p++ = c; 01241 fskip: 01242 width--; 01243 ++nread; 01244 #ifndef SMALL_SCANF 01245 if (--fp->_r > 0) 01246 fp->_p++; 01247 else 01248 if (__srefill (fp)) 01249 break; /* EOF */ 01250 #else 01251 *fp->_p = new_getchar(); 01252 if ( (47<*fp->_p<58) && (64<*fp->_p < 71) && (96<*fp->_p<103) ){ 01253 ; 01254 } 01255 else 01256 { 01257 break; 01258 } 01259 #endif 01260 } 01261 if (zeroes) 01262 flags &= ~NDIGITS; 01263 /* 01264 * If no digits, might be missing exponent digits 01265 * (just give back the exponent) or might be missing 01266 * regular digits, but had sign and/or decimal point. 01267 */ 01268 if (flags & NDIGITS) 01269 { 01270 if (flags & EXPOK) 01271 { 01272 /* no digits at all */ 01273 01274 while (p > buf) 01275 { 01276 #ifndef SMALL_SCANF 01277 ungetc (*(u_char *)-- p, fp); 01278 #else 01279 __io_ungetc(*(u_char *)-- p); 01280 #endif 01281 --nread; 01282 } 01283 01284 goto match_failure; 01285 01286 } 01287 01288 /* just a bad exponent (e and maybe sign) */ 01289 c = *(u_char *)-- p; 01290 --nread; 01291 if (c != 'e' && c != 'E') 01292 { 01293 #ifndef SMALL_SCANF 01294 _CAST_VOID ungetc (c, fp); /* sign */ 01295 #else 01296 _CAST_VOID __io_ungetc (c); 01297 #endif 01298 c = *(u_char *)-- p; 01299 --nread; 01300 } 01301 #ifndef SMALL_SCANF 01302 _CAST_VOID ungetc (c, fp); 01303 #else 01304 _CAST_VOID __io_ungetc (c); 01305 #endif 01306 01307 } 01308 if ((flags & SUPPRESS) == 0) 01309 { 01310 double res = 0; 01311 #ifdef _NO_LONGDBL 01312 #define QUAD_RES res; 01313 #else /* !_NO_LONG_DBL */ 01314 long double qres = 0; 01315 #define QUAD_RES qres; 01316 #endif /* !_NO_LONG_DBL */ 01317 long new_exp = 0; 01318 01319 *p = 0; 01320 if ((flags & (DPTOK | EXPOK)) == EXPOK) 01321 { 01322 exp_adjust = zeroes - leading_zeroes; 01323 new_exp = -exp_adjust; 01324 exp_start = p; 01325 } 01326 else if (exp_adjust) 01327 new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust; 01328 if (exp_adjust) 01329 { 01330 01331 /* If there might not be enough space for the new exponent, 01332 truncate some trailing digits to make room. */ 01333 if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN) 01334 exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1; 01335 sprintf (exp_start, "e%ld", new_exp); 01336 } 01337 01338 /* Current _strtold routine is markedly slower than 01339 _strtod_r. Only use it if we have a long double 01340 result. */ 01341 #ifndef _NO_LONGDBL /* !_NO_LONGDBL */ 01342 if (flags & LONGDBL) 01343 qres = _strtold (buf, NULL); 01344 else 01345 #endif 01346 res = _strtod_r (rptr, buf, NULL); 01347 if (flags & LONG) 01348 { 01349 dp = va_arg (ap, double *); 01350 *dp = res; 01351 } 01352 else if (flags & LONGDBL) 01353 { 01354 ldp = va_arg (ap, _LONG_DOUBLE *); 01355 *ldp = QUAD_RES; 01356 } 01357 else 01358 { 01359 flp = va_arg (ap, float *); 01360 *flp = res; 01361 } 01362 nassigned++; 01363 } 01364 break; 01365 } 01366 #endif /* FLOATING_POINT */ 01367 01368 } 01369 } 01370 input_failure: 01371 return nassigned ? nassigned : -1; 01372 match_failure: 01373 return nassigned; 01374 } 01375 01376 /* 01377 * Fill in the given table from the scanset at the given format 01378 * (just after `['). Return a pointer to the character past the 01379 * closing `]'. The table has a 1 wherever characters should be 01380 * considered part of the scanset. 01381 */ 01382 01383 /*static*/ 01384 u_char * 01385 __sccl (tab, fmt) 01386 register char *tab; 01387 register u_char *fmt; 01388 { 01389 register int c, n, v; 01390 01391 /* first `clear' the whole table */ 01392 c = *fmt++; /* first char hat => negated scanset */ 01393 if (c == '^') 01394 { 01395 v = 1; /* default => accept */ 01396 c = *fmt++; /* get new first char */ 01397 } 01398 else 01399 v = 0; /* default => reject */ 01400 /* should probably use memset here */ 01401 for (n = 0; n < 256; n++) 01402 tab[n] = v; 01403 if (c == 0) 01404 return fmt - 1; /* format ended before closing ] */ 01405 01406 /* 01407 * Now set the entries corresponding to the actual scanset to the 01408 * opposite of the above. 01409 * 01410 * The first character may be ']' (or '-') without being special; the 01411 * last character may be '-'. 01412 */ 01413 01414 v = 1 - v; 01415 for (;;) 01416 { 01417 tab[c] = v; /* take character c */ 01418 doswitch: 01419 n = *fmt++; /* and examine the next */ 01420 switch (n) 01421 { 01422 01423 case 0: /* format ended too soon */ 01424 return fmt - 1; 01425 01426 case '-': 01427 /* 01428 * A scanset of the form [01+-] is defined as `the digit 0, the 01429 * digit 1, the character +, the character -', but the effect of a 01430 * scanset such as [a-zA-Z0-9] is implementation defined. The V7 01431 * Unix scanf treats `a-z' as `the letters a through z', but treats 01432 * `a-a' as `the letter a, the character -, and the letter a'. 01433 * 01434 * For compatibility, the `-' is not considerd to define a range if 01435 * the character following it is either a close bracket (required by 01436 * ANSI) or is not numerically greater than the character we just 01437 * stored in the table (c). 01438 */ 01439 n = *fmt; 01440 if (n == ']' || n < c) 01441 { 01442 c = '-'; 01443 break; /* resume the for(;;) */ 01444 } 01445 fmt++; 01446 do 01447 { /* fill in the range */ 01448 tab[++c] = v; 01449 } 01450 while (c < n); 01451 #if 1 /* XXX another disgusting compatibility hack */ 01452 /* 01453 * Alas, the V7 Unix scanf also treats formats such 01454 * as [a-c-e] as `the letters a through e'. This too 01455 * is permitted by the standard.... 01456 */ 01457 goto doswitch; 01458 #else 01459 c = *fmt++; 01460 if (c == 0) 01461 return fmt - 1; 01462 if (c == ']') 01463 return fmt; 01464 #endif 01465 01466 break; 01467 01468 01469 case ']': /* end of scanset */ 01470 return fmt; 01471 01472 default: /* just another character */ 01473 c = n; 01474 break; 01475 } 01476 } 01477 /* NOTREACHED */ 01478 } 01479 01480 01481