#define SPC 01 #define STP 02 #define SHORT 0 #define REGULAR 1 #define LONG 2 #define INT 0 #define FLOAT 1 #define NULL 0 #define EOF (-1) #ifdef USEFLOAT extern double atof(); #endif typedef struct _iop { char *p; int r; } FILE; #define getc(f) (--(f)->r < 0 ? EOF : *(f)->p++) #define ungetc(c, f) (++(f)->r, *--(f)->p) #define isdigit(c) (c >= '0' && c <= '9') static char _sctab[256] = { 0,0,0,0,0,0,0,0, 0,SPC,SPC,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, SPC,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, }; static _innum(int **ptr, int type, int len, int size, FILE *iop, int *eofptr); static _instr(char *ptr, int type, int len, FILE *iop, int *eofptr); static char *_getccl(unsigned char *s); #ifdef TEST main() { char s1[8], s2[8]; int i, j; long l; sscanf("foo barx 1 2 a", "%s %[^x]x %d %ld %x", s1, s2, &i, &l, &j); printf("%s %s %d %ld %x\n", s1, s2, i, l, j); exit(0); } #endif sscanf(s, fmt, args) char *s, *fmt; int args; { FILE f; f.p = s; for (f.r = 0; *s++; f.r++) ; return vscanf(&f, fmt, &args); } vscanf(iop, fmt, argp) FILE *iop; char *fmt; int **argp; { register int ch; int nmatch = 0, len, ch1; int **ptr, fileended = 0, size; while (1) { switch (ch = *fmt++) { case '\0': return (nmatch); case '%': if ((ch = *fmt++) == '%') goto def; ptr = 0; if (ch != '*') ptr = argp++; else ch = *fmt++; len = 0; size = REGULAR; while (isdigit(ch)) { len = len*10 + ch - '0'; ch = *fmt++; } if (len == 0) len = 30000; if (ch == 'l') { size = LONG; ch = *fmt++; } else if (ch == 'h') { size = SHORT; ch = *fmt++; } else if (ch == '[') fmt = _getccl(fmt); if (ch >= 'A' && ch <= 'Z') { ch |= 0x20; size = LONG; } if (ch == '\0') return(-1); if (_innum(ptr, ch, len, size, iop, &fileended) && ptr) nmatch++; if (fileended) return(nmatch ? nmatch : -1); break; case ' ': case '\n': case '\t': while ((ch1 = getc(iop)) == ' ' || ch1 == '\t' || ch1 == '\n') ; if (ch1 != EOF) ungetc(ch1, iop); break; default: def: ch1 = getc(iop); if (ch1 != ch) { if (ch1 == EOF) return -1; ungetc(ch1, iop); return(nmatch); } } } } static _innum(int **ptr, int type, int len, int size, FILE *iop, int *eofptr) { register char *np; char numbuf[64]; register c, base; int expseen = 0, scale = INT, negflg = 0, c1, ndigit = 0; long lcval = 0; if (type == 'c' || type == 's' || type == '[') return(_instr(ptr ? *(char **)ptr : NULL, type, len, iop, eofptr)); #ifdef USEFLOAT if (type == 'e' || type == 'f') scale = FLOAT; #endif if (type == 'o') base = 8; else if (type == 'x') base = 16; else base = 10; np = numbuf; while ((c = getc(iop)) == ' ' || c == '\t' || c == '\n') ; if (c == '-') { negflg++; *np++ = c; c = getc(iop); len--; } else if (c == '+') { len--; c = getc(iop); } for ( ; --len >= 0; *np++ = c, c = getc(iop)) { if (isdigit(c) || base == 16 && ('a' <= c && c <= 'f' || 'A' <= c && c <= 'F')) { ndigit++; if (base==8) lcval <<=3; else if (base==10) lcval = ((lcval<<2) + lcval)<<1; else lcval <<= 4; c1 = c; if (isdigit(c)) c -= '0'; else if ('a' <= c && c <= 'f') c -= 'a' - 10; else c -= 'A' - 10; lcval += c; c = c1; continue; } else if (c == '.') { if (base != 10 || scale == INT) break; ndigit++; continue; } else if ((c == 'e' || c == 'E') && !expseen) { if (base != 10 || scale == INT || ndigit == 0) break; expseen++; *np++ = c; c = getc(iop); if (c != '+' && c != '-' && ('0' > c || c > '9')) break; } else break; } if (negflg) lcval = -lcval; if (c != EOF) { ungetc(c, iop); *eofptr = 0; } else *eofptr = 1; if (ptr == NULL || np == numbuf || (negflg && np == numbuf+1)) return 0; *np++ = 0; switch ((scale << 4) | size) { #ifdef USEFLOAT case (FLOAT<<4) | SHORT: case (FLOAT<<4) | REGULAR: **(float **)ptr = atof(numbuf); break; case (FLOAT<<4) | LONG: **(double **)ptr = atof(numbuf); break; #endif case (INT<<4) | SHORT: **(short **)ptr = lcval; break; case (INT<<4) | REGULAR: **(int **)ptr = lcval; break; case (INT<<4) | LONG: **(long **)ptr = lcval; break; } return 1; } static _instr(char *ptr, int type, int len, FILE *iop, int *eofptr) { int ch, ignstp; char *optr = ptr; *eofptr = 0; if (type == 'c' && len == 30000) len = 1; ignstp = (type == 's') ? SPC : 0; while ((ch = getc(iop)) != EOF && (_sctab[ch] & ignstp)) ; if (type == 'c') ignstp = 0; else if (type == '[') ignstp = STP; else ignstp = SPC; while (ch != EOF && !(_sctab[ch] & ignstp)) { if (ptr) *ptr++ = ch; if (--len <= 0) break; ch = getc(iop); } if (ch != EOF) { if (len > 0) ungetc(ch, iop); *eofptr = 0; } else *eofptr = 1; if (ptr && ptr != optr) { if (type != 'c') *ptr++ = '\0'; return 1; } return 0; } static char * _getccl(unsigned char *s) { int c, t; t = 0; if (*s == '^') { t++; s++; } for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++) if (t) _sctab[c] &= ~STP; else _sctab[c] |= STP; if ((c = *s) == ']' || c == '-') { /* first char is special */ if (t) _sctab[c] |= STP; else _sctab[c] &= ~STP; s++; } while ((c = *s++) != ']') { if (!c) return((char *)--s); else if (c == '-' && *s != ']' && s[-2] < *s) { for (c = s[-2] + 1; c < *s; c++) if (t) _sctab[c] |= STP; else _sctab[c] &= ~STP; } else if (t) _sctab[c] |= STP; else _sctab[c] &= ~STP; } return((char *)s); }