00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "char.h"
00018 #include "scanf.h"
00019 #include "str.h"
00020
00021 enum __scanf_flags {
00022 SFL_NOOP = 0x01,
00023 SFL_WIDTH = 0x02,
00024 };
00025
00026 enum __scanf_rank {
00027 SFR_CHAR,
00028 SFR_SHORT,
00029 SFR_INT,
00030 SFR_LONG,
00031 SFR_LLONG,
00032 };
00033
00034 #define SFR_MIN SFR_CHAR
00035 #define SFR_MAX SFR_LLONG
00036
00037 enum __scanf_state {
00038 SFS_NORMAL,
00039 SFS_FLAGS,
00040 SFS_WIDTH,
00041 SFS_MOD,
00042 SFS_CONV,
00043 SFS_STORE,
00044 SFS_EOF,
00045 SFS_ERR,
00046 };
00047
00048 typedef struct {
00049 int f;
00050 int l;
00051 int s;
00052 int w;
00053 } __scanf_t;
00054
00055
00056
00057
00058
00059 int _lucid_vsscanf(const char *str, const char *fmt, va_list _ap)
00060 {
00061
00062 int converted = 0;
00063
00064
00065 char c;
00066
00067
00068 __scanf_t f;
00069
00070
00071 union {
00072
00073 unsigned long long int u;
00074
00075
00076 char *s;
00077 } arg;
00078
00079
00080 int base;
00081
00082
00083 int len;
00084
00085
00086 char *sp;
00087
00088
00089 va_list ap;
00090 va_copy(ap, _ap);
00091
00092
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':
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':
00259
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':
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':
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 }