int xgettok(XFILE *xfp, char sepa, char *tok, int len) { int i = 0; int c = 0; int quoted=0; while (i < len && (c = xgetc(xfp)) != EOF && (quoted || (c != sepa && !isspace(c)))) { if (c == '"') { quoted = !quoted; continue; } tok[i++] = c; if (i >= 4 && tok[i-4] == '\\' && isoctal(tok[i-3]) && isoctal(tok[i-2]) && isoctal(tok[i-1]) && ((tok[i]=0), (c = strtol(tok+i-3,NULL, 8)) < 256)) { i -= 4; tok[i++] = c; } } if (c == '\n') xungetc(c, xfp); if (!i) return 0; if (i >= len || (sepa && c != sepa)) return -1; tok[i] = '\0'; return 1; }
void xskip(XFILE *xfp, char *str) { int c; while ((c = xgetc(xfp)) != EOF) { if (c == '#') c = xskipcomment(xfp); if (strchr(str, c) == NULL) break; } xungetc(c, xfp); }
static pic_value pic_port_peek_char(pic_state *pic) { int c; struct pic_port *port = pic_stdin(pic); pic_get_args(pic, "|p", &port); assert_port_profile(port, PIC_PORT_IN | PIC_PORT_TEXT, PIC_PORT_OPEN, "peek-char"); if ((c = xfgetc(port->file)) == EOF) { return pic_eof_object(); } else { xungetc(c, port->file); return pic_char_value((char)c); } }
static pic_value pic_port_peek_byte(pic_state *pic) { int c; struct pic_port *port = pic_stdin(pic); pic_get_args(pic, "|p", &port); assert_port_profile(port, PIC_PORT_IN | PIC_PORT_BINARY, PIC_PORT_OPEN, "peek-u8"); c = xfgetc(port->file); if (c == EOF) { return pic_eof_object(); } else { xungetc(c, port->file); return pic_int_value(c); } }
size_t xfread(void *ptr, size_t size, size_t count, xFILE *fp) { char *bptr = ptr; long nbytes; int c; nbytes = size * count; while (nbytes > fp->cnt) { memcpy(bptr, fp->ptr, fp->cnt); fp->ptr += fp->cnt; bptr += fp->cnt; nbytes -= fp->cnt; if ((c = x_fillbuf(fp)) == EOF) { return (size * count - nbytes) / size; } else { xungetc(c, fp); } } memcpy(bptr, fp->ptr, nbytes); fp->ptr += nbytes; fp->cnt -= nbytes; return count; }
int vxscanf(int (*xgetc)(void **), void (*xungetc)(int, void **), void *stream, const char *fmt, va_list ap) { union { #if SCANF_LEVEL >= SCANF_FLT float d; #endif unsigned long ul; long l; char *cp; } a; char c; /* holds a char from the format string */ u8 base = 0; int nconvs, i, j = 0, olen, clen; #if SCANF_LEVEL > SCANF_MIN s8 width = 0; #endif u8 flags; #if SCANF_LEVEL >= SCANF_FLT char *buf, *bp; char fltchars[] = "0123456789Ee."; #endif flags = 0; nconvs = 0; i = 0; olen = clen = 0; #if SCANF_LEVEL >= SCANF_FLT buf = 0; #endif a.ul = 0; while ((c = *(fmt++))) { #if SCANF_LEVEL >= SCANF_FLT if (isspace(c)) continue; if (flags & FLBRACKET) { if (c == '^' && i == 0 && !(flags & FLNEGATE)) { flags |= FLNEGATE; /* negate set */ continue; /* without bumping i */ } if (c == '-') { if (i == 0) { addbit: xscanf_set_bit(c); i++; continue; } flags |= FLMINUS; i++; continue; } if (c == ']') { if (i == 0) goto addbit; if (flags & FLMINUS) /* trailing - before ] */ xscanf_set_bit('-'); if (flags & FLNEGATE) for (i = 0; i < 256 / 8; i++) buf[i] = ~buf[i]; if (!(flags & FLSTAR)) a.cp = va_arg(ap, char *); while (width-- > 0) { i = w_xgetc(&stream); if (i == EOF) break; if (!xscanf_bit_is_set(i)) { xungetc(i, &stream); break; } if (!(flags & FLSTAR)) *a.cp++ = i; } if (!(flags & FLSTAR)) *a.cp = '\0'; goto nextconv; } if (flags & FLMINUS) { flags &= ~FLMINUS; while ((unsigned char)j < (unsigned char)c) { xscanf_set_bit(j); j++; } } j = (unsigned char)c; /* remember for x-y range */ goto addbit; } #endif /* SCANF_LEVEL >= SCANF_FLT */ if (flags & FLHASPERCENT) { if (c == '%') { flags &= ~FLHASPERCENT; #if SCANF_LEVEL > SCANF_MIN goto literal; #else continue; #endif } /* * Modifiers go first. They all end up in a * "continue" statement so to fetch the next * char from the format string. */ #if SCANF_LEVEL > SCANF_MIN if (c >= '0' && c <= '9') { c -= '0'; if (width == SCHAR_MAX) width = 0; else width *= 10; width += c; continue; } #endif /* SCANF_LEVEL > SCANF_MIN */ c = tolower(c); #if SCANF_LEVEL >= SCANF_FLT if ((c == '[' || c == 'e' || c == 'f' || c == 'g') && buf == 0) { if ((buf = malloc(FLTBUF)) == 0) return EOF; } #endif /* SCANF_LEVEL >= SCANF_FLT */ switch (c) { #if SCANF_LEVEL > SCANF_MIN case '*': flags |= FLSTAR; continue; #endif /* SCANF_LEVEL > SCANF_MIN */ case 'h': #if SHRT_MAX != INT_MAX flags |= FLSHORT; #endif /* * short int and int are identical on * our target platform, ignore. */ continue; case 'l': flags |= FLLONG; continue; /* * Actual conversion specifications go * here. */ case 'c': #if SCANF_LEVEL > SCANF_MIN if (!(flags & FLSTAR)) #endif /* SCANF_LEVEL > SCANF_MIN */ a.cp = va_arg(ap, char *); #if SCANF_LEVEL > SCANF_MIN if (width == SCHAR_MAX) width = 1; while (width-- > 0) { #endif /* SCANF_LEVEL > SCANF_MIN */ i = w_xgetc(&stream); if (i == EOF) goto leave; #if SCANF_LEVEL > SCANF_MIN if (!(flags & FLSTAR)) #endif /* SCANF_LEVEL > SCANF_MIN */ *a.cp++ = i; #if SCANF_LEVEL > SCANF_MIN } #endif /* SCANF_LEVEL > SCANF_MIN */ break; case 's': #if SCANF_LEVEL > SCANF_MIN if (!(flags & FLSTAR)) #endif /* SCANF_LEVEL > SCANF_MIN */ a.cp = va_arg(ap, char *); do { i = w_xgetc(&stream); } while (isspace(i)); if (i == EOF) goto leave; #if SCANF_LEVEL > SCANF_MIN while (width-- > 0) #else for (;;) #endif /* SCANF_LEVEL > SCANF_MIN */ { if (isspace(i)) { xungetc(i, &stream); break; } #if SCANF_LEVEL > SCANF_MIN if (!(flags & FLSTAR)) #endif /* SCANF_LEVEL > SCANF_MIN */ *a.cp++ = i; i = w_xgetc(&stream); if (i == EOF) break; } #if SCANF_LEVEL > SCANF_MIN if (!(flags & FLSTAR)) #endif /* SCANF_LEVEL > SCANF_MIN */ *a.cp = '\0'; break; case 'o': base = 8; flags |= FLUNSIGNED; goto dointeger; case 'p': /* * Handle pointers as plain unsigned * integers. This assumes that * sizeof(void *) == sizeof(unsigned int). */ case 'x': base = 16; /* FALLTHROUGH */ case 'u': flags |= FLUNSIGNED; /* FALLTHROUGH */ case 'd': case 'i': dointeger: do { i = w_xgetc(&stream); } while (isspace(i)); if (i == EOF) goto leave; if ((char)i == '-' || (char)i == '+') { #if SCANF_LEVEL > SCANF_MIN if (--width <= 0) /* * Incomplete conversion * due to field width * truncation. */ goto leave; #endif /* SCANF_LEVEL > SCANF_MIN */ if ((char)i == '-') flags |= FLMINUS; i = w_xgetc(&stream); if (i == EOF) goto leave; } if ((char)i == '0') { /* * %i conversions default to base * 10, but allow for base 8 * indicated by a leading 0 in * input, or base 16 indicated by * leading 0x/0X. * * For %x (and %p) conversions, the * leading 0x/0X is explicitly * allowable. * * If we fail the conversion here, * it is a mismatch condition, but * since we already saw a zero, * this means the current * conversion succeeded, assigning * 0. */ a.ul = 0; #if SCANF_LEVEL > SCANF_MIN if (--width <= 0) goto intdone; #endif /* SCANF_LEVEL > SCANF_MIN */ i = w_xgetc(&stream); if (i == EOF) goto intdone; if ((char)tolower(i) == 'x') { if (c == 'o' || c == 'd' || c == 'u') { /* * Invalid 0x in * %d/%u/%o */ xungetc(i, &stream); goto intdone; } base = 16; i = w_xgetc(&stream); if (i == EOF) goto intdone; } else if (c == 'i') base = 8; } a.ul = 0; for (;;) { j = tolower(i); /* * First, assume it is a decimal * digit. */ j -= '0'; if (j > 9) { /* * Not a decimal digit. * Try hex next. */ j += '0'; /* undo "- '0'" * above */ j -= 'a'; /* 'a' is first * hex digit */ if (j >= 0) /* 'a' has value * 10 */ j += 10; /* * else: not a hex digit, * gets caught below. */ } if (j < 0 || j >= base) { xungetc(i, &stream); break; } a.ul *= base; a.ul += j; #if SCANF_LEVEL > SCANF_MIN if (--width <= 0) break; #endif /* SCANF_LEVEL > SCANF_MIN */ i = w_xgetc(&stream); if (i == EOF) break; } /* * This is a bit of a hack: while we * collect all integer digits in an * unsigned long number in order to be * safe for unsigned conversions, the * standard allows for optional signs. * We are thus faced to the concept of * possibly negating an unsigned * number. :-/ We rely here on union a * mapping the signed and unsigned * fields suitably. */ if (flags & FLMINUS) a.l = -a.l; intdone: #if SCANF_LEVEL > SCANF_MIN if (!(flags & FLSTAR)) { #endif /* SCANF_LEVEL > SCANF_MIN */ if ((flags & (FLLONG | FLUNSIGNED)) == (FLLONG | FLUNSIGNED)) *(va_arg(ap, unsigned long *)) = a.ul; else if ((flags & (FLSHORT | FLUNSIGNED)) == (FLSHORT | FLUNSIGNED)) *(va_arg(ap, unsigned short *)) = (unsigned short)a.ul; else if (flags & (FLUNSIGNED)) *(va_arg(ap, unsigned *)) = (unsigned)a.ul; else if (flags & FLLONG) *(va_arg(ap, long *)) = a.l; else if (flags & FLSHORT) *(va_arg(ap, short *)) = (short)a.l; else *(va_arg(ap, int *)) = (int)a.l; #if SCANF_LEVEL > SCANF_MIN } #endif /* SCANF_LEVEL > SCANF_MIN */ break; #if SCANF_LEVEL > SCANF_MIN case 'n': if (!(flags & FLSTAR)) *(va_arg(ap, int *)) = clen; break; #endif /* SCANF_LEVEL > SCANF_MIN */ #if SCANF_LEVEL >= SCANF_FLT case 'e': case 'f': case 'g': do { i = w_xgetc(&stream); } while (isspace(i)); if (i == EOF) goto leave; if ((char)i == '-' || (char)i == '+') { if ((char)i == '-') flags |= FLMINUS; i = w_xgetc(&stream); if (i == EOF) goto leave; } a.d = 0.0; for (bp = buf; bp < buf + FLTBUF - 1 && width > 0; width--) { if (isspace(i)) break; if (strchr(fltchars, i) == 0) { xungetc(i, &stream); break; } if ((char)i == 'e' || (char)i == 'E') { /* * Prevent another 'E' * from being recognized. */ fltchars[10] = 0; *bp++ = i; i = w_xgetc(&stream); if (i == EOF) break; if ((char)i != '-' && (char)i != '+') continue; } else if ((char)i == '.') /* * Prevent another dot from * being recognized. If we * already saw an 'E' * above, we could not get * here at all. */ fltchars[12] = 0; *bp++ = i; i = w_xgetc(&stream); if (i == EOF) break; } *bp++ = 0; a.d = (float)strtod(buf, 0); if (flags & FLMINUS) a.d = -a.d; *(va_arg(ap, float *)) = a.d; /* * Restore the 'E' and '.' chars that * might have been clobbered above. */ fltchars[10] = 'E'; fltchars[12] = '.'; break; case '[': flags |= FLBRACKET; i = j = 0; memset(buf, 0, 256 / 8); continue; #endif /* SCANF_LEVEL >= SCANF_FLT */ } #if SCANF_LEVEL >= SCANF_FLT nextconv: #endif if (clen > olen && !(flags & FLSTAR)) { flags = 0; nconvs++; } else if (i == EOF) { /* * If one conversion failed completely, * punt. */ flags = 0; goto leave; } else flags = 0; } else if (c == '%') { flags = FLHASPERCENT; base = 10; olen = clen; #if SCANF_LEVEL > SCANF_MIN width = SCHAR_MAX; } else if (isspace(c)) { /* match against any whitspace */ do { i = w_xgetc(&stream); } while (isspace(i)); if (i == EOF) goto leave; xungetc(i, &stream); } else { /* literal character in format, match it */ literal: i = w_xgetc(&stream); if (i == EOF) goto leave; if (i != c) goto leave; #endif /* SCANF_LEVEL > SCANF_MIN */ } }