diff --git a/WEGA/contrib/lcc/lib/libc/port/stdio/doscan.c b/WEGA/contrib/lcc/lib/libc/port/stdio/doscan.c new file mode 100644 index 0000000..d980323 --- /dev/null +++ b/WEGA/contrib/lcc/lib/libc/port/stdio/doscan.c @@ -0,0 +1,232 @@ +#include +#include +#include +#include + +#define NCHARS (1 << BITSPERBYTE) + +extern double atof(); +extern char *memset(); +extern int ungetc(); + +int +_doscan(iop, fmt, va_alist) +register FILE *iop; +register unsigned char *fmt; +va_list va_alist; +{ + extern unsigned char *setup(); + char tab[NCHARS]; + register int ch; + int nmatch = 0, len, inchar, stow, size; + + /******************************************************* + * Main loop: reads format to determine a pattern, + * and then goes to read input stream + * in attempt to match the pattern. + *******************************************************/ + for( ; ; ) { + if((ch = *fmt++) == '\0') + return(nmatch); /* end of format */ + if(isspace(ch)) { + while(isspace(inchar = getc(iop))) + ; + if(ungetc(inchar, iop) != EOF) + continue; + break; + } + if(ch != '%' || (ch = *fmt++) == '%') { + if((inchar = getc(iop)) == ch) + continue; + if(ungetc(inchar, iop) != EOF) + return(nmatch); /* failed to match input */ + break; + } + if(ch == '*') { + stow = 0; + ch = *fmt++; + } else + stow = 1; + + for(len = 0; isdigit(ch); ch = *fmt++) + len = len * 10 + ch - '0'; + if(len == 0) + len = MAXINT; + + if((size = ch) == 'l' || size == 'h') + ch = *fmt++; + if(ch == '\0' || + ch == '[' && (fmt = setup(fmt, tab)) == NULL) + return(EOF); /* unexpected end of format */ + if(isupper(ch)) { /* no longer documented */ + size = 'l'; + ch = _tolower(ch); + } + if(ch != 'c' && ch != '[') { + while(isspace(inchar = getc(iop))) + ; + if(ungetc(inchar, iop) == EOF) + break; + } + if((size = (ch == 'c' || ch == 's' || ch == '[') ? + string(stow, ch, len, tab, iop, &va_alist) : + number(stow, ch, len, size, iop, &va_alist)) != 0) + nmatch += stow; + if(va_alist == NULL) /* end of input */ + break; + if(size == 0) + return(nmatch); /* failed to match input */ + } + return(nmatch != 0 ? nmatch : EOF); /* end of input */ +} + +/*************************************************************** + * Functions to read the input stream in an attempt to match incoming + * data to the current pattern from the main loop of _doscan(). + ***************************************************************/ +static int +number(stow, type, len, size, iop, listp) +int stow, type, len, size; +register FILE *iop; +va_list *listp; +{ + char numbuf[64]; + register char *np = numbuf; + register int c, base; + int digitseen = 0, dotseen = 0, expseen = 0, floater = 0, negflg = 0; + long lcval = 0; + + switch(type) { + case 'e': + case 'f': + case 'g': + floater++; + case 'd': + case 'u': + base = 10; + break; + case 'o': + base = 8; + break; + case 'x': + base = 16; + break; + default: + return(0); /* unrecognized conversion character */ + } + switch(c = getc(iop)) { + case '-': + negflg++; + case '+': /* fall-through */ + len--; + c = getc(iop); + } + for( ; --len >= 0; *np++ = c, c = getc(iop)) { + if(isdigit(c) || base == 16 && isxdigit(c)) { + int digit = c - (isdigit(c) ? '0' : + isupper(c) ? 'A' - 10 : 'a' - 10); + if(digit >= base) + break; + if(stow && !floater) + lcval = base * lcval + digit; + digitseen++; + continue; + } + if(!floater) + break; + if(c == '.' && !dotseen++) + continue; + if((c == 'e' || c == 'E') && digitseen && !expseen++) { + *np++ = c; + c = getc(iop); + if(isdigit(c) || c == '+' || c == '-') + continue; + } + break; + } + if(stow && digitseen) + if(floater) { + register double dval; + + *np = '\0'; + dval = atof(numbuf); + if(negflg) + dval = -dval; + if(size == 'l') + *va_arg(*listp, double *) = dval; + else + *va_arg(*listp, float *) = (float)dval; + } else { + /* suppress possible overflow on 2's-comp negation */ + if(negflg && lcval != HIBITL) + lcval = -lcval; + if(size == 'l') + *va_arg(*listp, long *) = lcval; + else if(size == 'h') + *va_arg(*listp, short *) = (short)lcval; + else + *va_arg(*listp, int *) = (int)lcval; + } + if(ungetc(c, iop) == EOF) + *listp = NULL; /* end of input */ + return(digitseen); /* successful match if non-zero */ +} + +static int +string(stow, type, len, tab, iop, listp) +register int stow, type, len; +register char *tab; +register FILE *iop; +va_list *listp; +{ + register int ch; + register char *ptr; + char *start; + + start = ptr = stow ? va_arg(*listp, char *) : NULL; + if(type == 'c' && len == MAXINT) + len = 1; + while((ch = getc(iop)) != EOF && + !(type == 's' && isspace(ch) || type == '[' && tab[ch])) { + if(stow) + *ptr = ch; + ptr++; + if(--len <= 0) + break; + } + if(ch == EOF || len > 0 && ungetc(ch, iop) == EOF) + *listp = NULL; /* end of input */ + if(ptr == start) + return(0); /* no match */ + if(stow && type != 'c') + *ptr = '\0'; + return(1); /* successful match */ +} + +static unsigned char * +setup(fmt, tab) +register unsigned char *fmt; +register char *tab; +{ + register int b, c, d, t = 0; + + if(*fmt == '^') { + t++; + fmt++; + } + (void)memset(tab, !t, NCHARS); + if((c = *fmt) == ']' || c == '-') { /* first char is special */ + tab[c] = t; + fmt++; + } + while((c = *fmt++) != ']') { + if(c == '\0') + return(NULL); /* unexpected end of format */ + if(c == '-' && (d = *fmt) != ']' && (b = fmt[-2]) < d) { + (void)memset(&tab[b], t, d - b); + fmt++; + } else + tab[c] = t; + } + return(fmt); +}