#include #include #include static inline bool isspace(char c) { return (c == ' ') || (c == '\t') || (c == '\n'); } static inline bool isdigit(char c) { return (c >= '0') && (c <= '9'); } static inline bool isxdigit(char c) { return ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')); } static int parse_dec(int (*peek)(void *userp), void (*pop)(void *userp), void *userp, long *vp) { long v = 0; int n = 0; int minus = 0; char ch; if ((*peek)(userp) == '-') { (*pop)(userp); n++; minus = 1; } ch = (*peek)(userp); if (!isdigit(ch)) return -1; do { v = v * 10 + ch - '0'; (*pop)(userp); n++; ch = (*peek)(userp); } while (isdigit(ch)); *vp = minus ? -v : v; return n; } static int parse_chars(int (*peek)(void *userp), void (*pop)(void *userp), void *userp, char *vp, bool fake) { int n = 0; char *pt=vp; while (!isspace((*peek)(userp))) { if(fake==false) *(pt++) = (*peek)(userp); n++; (*pop)(userp); } if(fake==false) (*pt)='\0'; return n; } static int parse_hex(int (*peek)(void *userp), void (*pop)(void *userp), void *userp, unsigned long *vp) { unsigned long v = 0; int n = 0; char ch; ch = (*peek)(userp); if (!isxdigit(ch)) return -1; do { if (ch >= 'a') ch = ch - 'a' + 10; else if (ch >= 'A') ch = ch - 'A' + 10; else ch = ch - '0'; v = v * 16 + ch; (*pop)(userp); n++; ch = (*peek)(userp); } while (isxdigit(ch)); *vp = v; return n; } static int skip_spaces(int (*peek)(void *userp), void (*pop)(void *userp), void *userp) { int n = 0; while (isspace((*peek)(userp))) { n++; (*pop)(userp); } return n; } static int scan(int (*peek)(void *userp), void (*pop)(void *userp), void *userp, const char *fmt, va_list ap) { char ch; int n = 0; int n_chars = 0; int r; long lval; bool skip=false; unsigned long ulval; while ((ch = *fmt++) != '\0') { bool literal = false; if (ch == '%') { ch = *fmt++; if(ch== '*') /* We should process this, but not store it in an arguement */ { ch=*fmt++; skip=true; } else { skip=false; } switch (ch) { case 'x': n_chars += skip_spaces(peek, pop, userp); if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0) { if(skip==false) { *(va_arg(ap, unsigned int *)) = ulval; n++; } n_chars += r; } else return n; break; case 'd': n_chars += skip_spaces(peek, pop, userp); if ((r = parse_dec(peek, pop, userp, &lval)) >= 0) { if(skip==false) { *(va_arg(ap, int *)) = lval; n++; } n_chars += r; } else return n; break; case 'n': if(skip==false) { *(va_arg(ap, int *)) = n_chars; n++; } break; case 'l': n_chars += skip_spaces(peek, pop, userp); ch = *fmt++; switch (ch) { case 'x': if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0) { if(skip==false) { *(va_arg(ap, unsigned long *)) = ulval; n++; } n_chars += r; } else return n; break; case 'd': if ((r = parse_dec(peek, pop, userp, &lval)) >= 0) { if(skip==false) { *(va_arg(ap, long *)) = lval; n++; } n_chars += r; } else return n; break; case '\0': return n; default: literal = true; break; } break; case 's': n_chars += skip_spaces(peek, pop, userp); n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip ); if(skip==false) { n++; } break; case '\0': return n; default: literal = true; break; } } else literal = true; if (literal) { n_chars += skip_spaces(peek, pop, userp); if ((*peek)(userp) != ch) continue; else { (*pop)(userp); n_chars++; } } } return n; } static int sspeek(void *userp) { return **((char **)userp); } static void sspop(void *userp) { (*((char **)userp))++; } int sscanf(const char *s, const char *fmt, ...) { int r; va_list ap; const char *p; p = s; va_start(ap, fmt); r = scan(sspeek, sspop, &p, fmt, ap); va_end(ap); return r; }