If the number of conversion specifications in format exceeds the number of pointer arguments, the results are undefined. If the number of pointer arguments exceeds the number of conversion specifications, then the excess pointer arguments are evaluated, but are otherwise ignored.
The format string consists of a sequence of directives which describe how to process the sequence of input characters. If processing of a directive fails, no further input is read, and scanf() returns. A "failure" can be either of the following: input failure, meaning that input characters were unavailable, or matching failure, meaning that the input was inappropriate (see below).
A directive is one of the following:
The following conversion specifiers are available:
Functions | |
int | _lucid_vsscanf (const char *str, const char *fmt, va_list ap) |
read conversion from string using va_list | |
int | _lucid_sscanf (const char *str, const char *fmt,...) |
read conversion from string using variable number of arguments |
int _lucid_vsscanf | ( | const char * | str, | |
const char * | fmt, | |||
va_list | ap | |||
) |
read conversion from string using va_list
[in] | str | source string |
[in] | fmt | format string |
[out] | ap | variable number of arguments |
Definition at line 59 of file vsscanf.c.
References char_isspace, __scanf_t::f, __scanf_t::l, __scanf_t::s, SFL_NOOP, SFL_WIDTH, SFR_CHAR, SFR_INT, SFR_LLONG, SFR_LONG, SFR_MAX, SFR_MIN, SFR_SHORT, SFS_CONV, SFS_EOF, SFS_ERR, SFS_FLAGS, SFS_MOD, SFS_NORMAL, SFS_WIDTH, str_len(), str_toumax(), and __scanf_t::w.
Referenced by _lucid_sscanf().
00060 { 00061 /* keep track of converted arguments */ 00062 int converted = 0; 00063 00064 /* current character in format */ 00065 char c; 00066 00067 /* current conversion data */ 00068 __scanf_t f; 00069 00070 /* arguments */ 00071 union { 00072 /* unsigned argument */ 00073 unsigned long long int u; 00074 00075 /* string argument */ 00076 char *s; 00077 } arg; 00078 00079 /* base used for integer conversions */ 00080 int base; 00081 00082 /* number of bytes converted in str_toumax */ 00083 int len; 00084 00085 /* pointer for string conversion */ 00086 char *sp; 00087 00088 /* don't consume original ap */ 00089 va_list ap; 00090 va_copy(ap, _ap); 00091 00092 /* initialize conversion data */ 00093 f.f = 0; 00094 f.l = SFR_INT; 00095 f.s = SFS_NORMAL; 00096 f.w = str_len(str); 00097 00098 while ((c = *fmt++)) { 00099 switch (f.s) { 00100 case SFS_NORMAL: 00101 if (c == '%') { 00102 f.f = 0; 00103 f.l = SFR_INT; 00104 f.s = SFS_FLAGS; 00105 f.w = str_len(str); 00106 } 00107 00108 else if (char_isspace(c)) 00109 while (char_isspace(*str)) 00110 str++; 00111 00112 else if (*str == c) 00113 str++; 00114 00115 else 00116 f.s = SFS_ERR; 00117 00118 break; 00119 00120 case SFS_FLAGS: 00121 switch (c) { 00122 case '*': 00123 f.f |= SFL_NOOP; 00124 break; 00125 00126 case '0': 00127 case '1': 00128 case '2': 00129 case '3': 00130 case '4': 00131 case '5': 00132 case '6': 00133 case '7': 00134 case '8': 00135 case '9': 00136 f.w = (c - '0'); 00137 f.f |= SFL_WIDTH; 00138 f.s = SFS_WIDTH; 00139 break; 00140 00141 default: 00142 f.s = SFS_MOD; 00143 fmt--; 00144 break; 00145 } 00146 00147 break; 00148 00149 case SFS_WIDTH: 00150 if (c >= '0' && c <= '9') 00151 f.w = f.w * 10 + (c - '0'); 00152 00153 else { 00154 f.s = SFS_MOD; 00155 fmt--; 00156 } 00157 00158 break; 00159 00160 case SFS_MOD: 00161 switch (c) { 00162 case 'h': 00163 f.l--; 00164 break; 00165 00166 case 'l': 00167 f.l++; 00168 break; 00169 00170 default: 00171 f.s = SFS_CONV; 00172 fmt--; 00173 break; 00174 } 00175 00176 break; 00177 00178 case SFS_CONV: 00179 f.s = SFS_NORMAL; 00180 00181 if (f.l > SFR_MAX) 00182 f.l = SFR_MAX; 00183 00184 if (f.l < SFR_MIN) 00185 f.l = SFR_MIN; 00186 00187 switch (c) { 00188 case 'd': 00189 base = 10; 00190 goto scan_int; 00191 00192 case 'i': /* signed conversion */ 00193 base = 0; 00194 goto scan_int; 00195 00196 case 'o': 00197 base = 8; 00198 goto scan_int; 00199 00200 case 'u': 00201 base = 10; 00202 goto scan_int; 00203 00204 case 'X': 00205 case 'x': 00206 base = 16; 00207 goto scan_int; 00208 00209 scan_int: 00210 while (char_isspace(*str)) 00211 str++; 00212 00213 if (!*str) { 00214 f.s = SFS_EOF; 00215 break; 00216 } 00217 00218 len = str_toumax(str, &arg.u, base, f.w); 00219 00220 if (len <= 0) { 00221 f.s = SFS_ERR; 00222 break; 00223 } 00224 00225 str += len; 00226 converted++; 00227 00228 if (!(f.f & SFL_NOOP)) { 00229 switch (f.l) { 00230 case SFR_CHAR: 00231 *va_arg(ap, unsigned char *) = arg.u; 00232 break; 00233 00234 case SFR_SHORT: 00235 *va_arg(ap, unsigned short int *) = arg.u; 00236 break; 00237 00238 case SFR_INT: 00239 *va_arg(ap, unsigned int *) = arg.u; 00240 break; 00241 00242 case SFR_LONG: 00243 *va_arg(ap, unsigned long int *) = arg.u; 00244 break; 00245 00246 case SFR_LLONG: 00247 *va_arg(ap, unsigned long long int *) = arg.u; 00248 break; 00249 00250 default: 00251 *va_arg(ap, unsigned long long int *) = arg.u; 00252 break; 00253 } 00254 } 00255 00256 break; 00257 00258 case 'c': /* character conversion */ 00259 /* default width = 1 */ 00260 f.w = (f.f & SFL_WIDTH) ? f.w : 1; 00261 00262 if ((f.f & SFL_NOOP)) { 00263 while (f.w--) { 00264 if (!*str) { 00265 f.s = SFS_EOF; 00266 break; 00267 } 00268 00269 str++; 00270 } 00271 } 00272 00273 else { 00274 arg.s = va_arg(ap, char *); 00275 00276 while (f.w--) { 00277 if (!*str) { 00278 f.s = SFS_EOF; 00279 break; 00280 } 00281 00282 *arg.s++ = *str++; 00283 } 00284 } 00285 00286 if (f.s != SFS_EOF && !(f.f & SFL_NOOP)) 00287 converted++; 00288 00289 break; 00290 00291 case 's': /* string conversion */ 00292 if (!(f.f & SFL_NOOP)) { 00293 while (f.w-- && !char_isspace(*str)) { 00294 if (!*str) { 00295 f.s = SFS_EOF; 00296 break; 00297 } 00298 00299 str++; 00300 } 00301 } 00302 00303 else { 00304 sp = arg.s = va_arg(ap, char *); 00305 00306 while (f.w-- && !char_isspace(*str)) { 00307 if (!*str) { 00308 f.s = SFS_EOF; 00309 break; 00310 } 00311 00312 *sp++ = *str++; 00313 } 00314 00315 if (f.s != SFS_EOF) 00316 *sp = '\0'; 00317 } 00318 00319 if (f.s != SFS_EOF && !(f.f & SFL_NOOP)) 00320 converted++; 00321 00322 break; 00323 00324 case 'P': 00325 case 'p': /* pointer conversion */ 00326 while (char_isspace(*str)) 00327 str++; 00328 00329 if (!*str) { 00330 f.s = SFS_EOF; 00331 break; 00332 } 00333 00334 len = str_toumax(str, &arg.u, 0, f.w); 00335 00336 if (len <= 0) { 00337 f.s = SFS_ERR; 00338 break; 00339 } 00340 00341 if (!(f.f & SFL_NOOP)) 00342 *va_arg(ap, void **) = (void *) (unsigned long int) arg.u; 00343 00344 str += len; 00345 converted++; 00346 00347 break; 00348 00349 case 'n': 00350 *va_arg(ap, int *) = converted; 00351 00352 break; 00353 00354 case '%': 00355 if (*str == '%') 00356 str++; 00357 else 00358 f.s = SFS_ERR; 00359 00360 break; 00361 00362 default: 00363 f.s = SFS_ERR; 00364 break; 00365 } 00366 00367 break; 00368 00369 case SFS_EOF: 00370 converted = converted ? converted : -1; 00371 00372 case SFS_ERR: 00373 va_end(ap); 00374 return converted; 00375 } 00376 } 00377 00378 if (f.s == SFS_EOF) 00379 converted = converted ? converted : -1; 00380 00381 va_end(ap); 00382 return converted; 00383 }
int _lucid_sscanf | ( | const char * | str, | |
const char * | fmt, | |||
... | ||||
) |
read conversion from string using variable number of arguments
[in] | str | source string |
[in] | fmt | format string |
[out] | ... | variable number of arguments |
Definition at line 19 of file sscanf.c.
References _lucid_vsscanf().
Referenced by addr_from_str().
00020 { 00021 va_list ap; 00022 va_start(ap, fmt); 00023 00024 return _lucid_vsscanf(str, fmt, ap); 00025 }