00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #include <cfg/crt.h>
00069
00070 #include "nut_io.h"
00071
00072 #include <ctype.h>
00073 #include <limits.h>
00074 #include <stdlib.h>
00075 #include <string.h>
00076
00081
00082 #define CF_LONG 0x01
00083 #define CF_SUPPRESS 0x02
00084 #define CF_SIGNOK 0x04
00085 #define CF_NDIGITS 0x08
00086 #define CF_PFXOK 0x10
00087 #define CF_NZDIGITS 0x20
00088 #define CF_DPTOK 0x10
00089 #define CF_EXPOK 0x20
00090
00091
00092
00093
00094 #define CT_CHAR 0
00095 #define CT_STRING 2
00096 #define CT_INT 3
00097 #define CT_FLOAT 4
00098
00112 int _getf(int _getb(int, void *, size_t), int fd, CONST char *fmt, va_list ap)
00113 {
00114
00115 u_char cf;
00116 u_char ch;
00117 size_t width;
00118 u_char flags;
00119 u_char ct;
00120 u_char base;
00121 u_char ccnt = 0;
00122 u_char acnt = 0;
00123 char buf[16];
00124 char *cp;
00125 u_char ch_ready = 0;
00126
00127
00128 for (;;) {
00129 cf = *fmt++;
00130 if (cf == 0)
00131 return acnt;
00132
00133
00134
00135
00136 if (isspace(cf)) {
00137 for (;;) {
00138 if (_getb(fd, &ch, 1) != 1)
00139 break;
00140 if (!isspace(ch)) {
00141 ch_ready = 1;
00142 break;
00143 }
00144 }
00145 continue;
00146 }
00147
00148
00149
00150
00151 if (cf != '%') {
00152 if (!ch_ready && _getb(fd, &ch, 1) != 1)
00153 return ccnt ? acnt : EOF;
00154 if (ch != cf)
00155 return acnt;
00156 ch_ready = 0;
00157 continue;
00158 }
00159
00160 cf = *fmt++;
00161
00162
00163
00164 if (cf == '%') {
00165 if (!ch_ready && _getb(fd, &ch, 1) != 1)
00166 return ccnt ? acnt : EOF;
00167 if (ch != cf)
00168 return acnt;
00169 ch_ready = 0;
00170 continue;
00171 }
00172
00173
00174
00175
00176 width = 0;
00177 flags = 0;
00178 for (;;) {
00179 if (cf == '*')
00180 flags |= CF_SUPPRESS;
00181 else if (cf == 'l')
00182 flags |= CF_LONG;
00183 else if (cf >= '0' && cf <= '9')
00184 width = width * 10 + cf - '0';
00185 else
00186 break;
00187
00188 cf = *fmt++;
00189 }
00190
00191
00192
00193
00194 base = 10;
00195 ct = CT_INT;
00196 switch (cf) {
00197 case '\0':
00198 return EOF;
00199 case 's':
00200 ct = CT_STRING;
00201 break;
00202 case 'c':
00203 ct = CT_CHAR;
00204 break;
00205 case 'i':
00206 base = 0;
00207 break;
00208 case 'u':
00209 base = 10;
00210 break;
00211 case 'o':
00212 base = 8;
00213 break;
00214 case 'x':
00215 flags |= CF_PFXOK;
00216 base = 16;
00217 break;
00218 #ifdef STDIO_FLOATING_POINT
00219 case 'e':
00220 case 'f':
00221 case 'g':
00222 ct = CT_FLOAT;
00223 break;
00224 #endif
00225 }
00226
00227
00228
00229
00230 if (ct == CT_CHAR) {
00231 if (width == 0)
00232 width = 1;
00233 if (flags & CF_SUPPRESS) {
00234 while (width > sizeof(buf)) {
00235 if (!ch_ready && _getb(fd, buf, sizeof(buf)) <= 0)
00236 return ccnt ? acnt : EOF;
00237 width -= sizeof(buf);
00238 }
00239 if (width)
00240 if (!ch_ready && _getb(fd, &buf, width) <= 0)
00241 return ccnt ? acnt : EOF;
00242 } else {
00243 if (!ch_ready && _getb(fd, (void *) va_arg(ap, char *), width) <= 0)
00244 return ccnt ? acnt : EOF;
00245 acnt++;
00246 }
00247 ch_ready = 0;
00248 ccnt++;
00249 continue;
00250 }
00251
00252
00253
00254
00255 if (!ch_ready && _getb(fd, &ch, 1) != 1)
00256 return ccnt ? acnt : EOF;
00257 ch_ready = 0;
00258 while (isspace(ch)) {
00259 if (_getb(fd, &ch, 1) != 1)
00260 return ccnt ? acnt : EOF;
00261 }
00262
00263
00264
00265
00266 if (ct == CT_STRING) {
00267 if (width == 0)
00268 width = 0xFFFF;
00269 if (flags & CF_SUPPRESS) {
00270 while (!isspace(ch)) {
00271 if (--width == 0)
00272 break;
00273 if (_getb(fd, &ch, 1) != 1)
00274 break;
00275 }
00276 } else {
00277 cp = va_arg(ap, char *);
00278 while (!isspace(ch)) {
00279 *cp++ = ch;
00280 if (--width == 0)
00281 break;
00282 if (_getb(fd, &ch, 1) != 1)
00283 break;
00284 }
00285 *cp = 0;
00286 acnt++;
00287 }
00288 ccnt++;
00289 }
00290
00291
00292
00293
00294 else if (ct == CT_INT) {
00295 if (width == 0 || width > sizeof(buf) - 1)
00296 width = sizeof(buf) - 1;
00297
00298 flags |= CF_SIGNOK | CF_NDIGITS | CF_NZDIGITS;
00299
00300 for (cp = buf; width; width--) {
00301 if (ch == '0') {
00302 if (base == 0) {
00303 base = 8;
00304 flags |= CF_PFXOK;
00305 }
00306 if (flags & CF_NZDIGITS)
00307 flags &= ~(CF_SIGNOK | CF_NZDIGITS | CF_NDIGITS);
00308 else
00309 flags &= ~(CF_SIGNOK | CF_PFXOK | CF_NDIGITS);
00310 } else if (ch >= '1' && ch <= '7') {
00311 if (base == 0)
00312 base = 10;
00313 flags &= ~(CF_SIGNOK | CF_PFXOK | CF_NDIGITS);
00314 } else if (ch == '8' || ch == '9') {
00315 if (base == 0)
00316 base = 10;
00317 else if (base <= 8)
00318 break;
00319 flags &= ~(CF_SIGNOK | CF_PFXOK | CF_NDIGITS);
00320 } else if ((ch >= 'A' && ch <= 'F')
00321 || (ch >= 'a' && ch <= 'f')) {
00322 if (base <= 10)
00323 break;
00324 flags &= ~(CF_SIGNOK | CF_PFXOK | CF_NDIGITS);
00325 } else if (ch == '-' || ch == '+') {
00326 if ((flags & CF_SIGNOK) == 0)
00327 break;
00328 flags &= ~CF_SIGNOK;
00329 } else if (ch == 'x' || ch == 'X') {
00330 if ((flags & CF_PFXOK) == 0)
00331 break;
00332 base = 16;
00333 flags &= ~CF_PFXOK;
00334 } else {
00335 ch_ready = 1;
00336 break;
00337 }
00338 *cp++ = ch;
00339 if (width > 1) {
00340 if (_getb(fd, &ch, 1) != 1)
00341 break;
00342 }
00343 }
00344
00345 if (flags & CF_NDIGITS)
00346 return acnt;
00347
00348 if ((flags & CF_SUPPRESS) == 0) {
00349 u_long res;
00350
00351 *cp = 0;
00352 res = strtol(buf, 0, base);
00353 if (flags & CF_LONG)
00354 *va_arg(ap, long *) = res;
00355 else
00356 *va_arg(ap, int *) = res;
00357 acnt++;
00358 }
00359 ccnt++;
00360 }
00361 #ifdef STDIO_FLOATING_POINT
00362 else if (ct == CT_FLOAT) {
00363 if (width == 0 || width > sizeof(buf) - 1)
00364 width = sizeof(buf) - 1;
00365 flags |= CF_SIGNOK | CF_NDIGITS | CF_DPTOK | CF_EXPOK;
00366 for (cp = buf; width; width--) {
00367 if (ch >= '0' && ch <= '9')
00368 flags &= ~(CF_SIGNOK | CF_NDIGITS);
00369 else if (ch == '+' || ch == '-') {
00370 if ((flags & CF_SIGNOK) == 0)
00371 break;
00372 flags &= ~CF_SIGNOK;
00373 } else if (ch == '.') {
00374 if ((flags & CF_DPTOK) == 0)
00375 break;
00376 flags &= ~(CF_SIGNOK | CF_DPTOK);
00377 } else if (ch == 'e' || ch == 'E') {
00378 if ((flags & (CF_NDIGITS | CF_EXPOK)) != CF_EXPOK)
00379 break;
00380 flags = (flags & ~(CF_EXPOK | CF_DPTOK)) | CF_SIGNOK | CF_NDIGITS;
00381 } else {
00382 ch_ready = 1;
00383 break;
00384 }
00385 *cp++ = ch;
00386 if (_getb(fd, &ch, 1) != 1)
00387 break;
00388 }
00389 if (flags & CF_NDIGITS) {
00390 if (flags & CF_EXPOK)
00391 return acnt;
00392 }
00393 if ((flags & CF_SUPPRESS) == 0) {
00394 double res;
00395
00396 *cp = 0;
00397 res = strtod(buf, 0);
00398 *va_arg(ap, double *) = res;
00399 acnt++;
00400 }
00401 ccnt++;
00402 }
00403 #endif
00404 }
00405 }
00406