|
|
1.1 ! root 1: ! 2: /* ! 3: * Alas, doscan is not documented, so people feel they have license to ! 4: * change the parameters. The 3B implementation does not even look ! 5: * callable from C, and without documentation is not comprehensible. ! 6: * Since many systems have their own doprnt which is written in assembly ! 7: * language, and thus faster, but callable from C, we try to use the ! 8: * standard system version where possible. The ifdefs below attempt ! 9: * to decide where it is possible - it may need to be updated later. ! 10: */ ! 11: ! 12: #ifdef u3b ! 13: #define NEEDDOSCAN ! 14: #endif ! 15: ! 16: #ifdef NEEDDOSCAN ! 17: /* @(#) doscan.c: 1.1 10/15/83 (1.2 9/29/82) */ ! 18: /* @(#)doscan.c 2.5 */ ! 19: /*LINTLIBRARY*/ ! 20: #include <stdio.h> ! 21: #include <ctype.h> ! 22: #include <varargs.h> ! 23: #include <values.h> ! 24: ! 25: #define NCHARS (1 << BITSPERBYTE) ! 26: ! 27: extern double atof(); ! 28: extern char *memset(); ! 29: extern int ungetc(); ! 30: ! 31: int ! 32: _doscan(iop, fmt, va_alist) ! 33: register FILE *iop; ! 34: register unsigned char *fmt; ! 35: va_list va_alist; ! 36: { ! 37: extern unsigned char *setup(); ! 38: char tab[NCHARS]; ! 39: register int ch; ! 40: int nmatch = 0, len, inchar, stow, size; ! 41: ! 42: /******************************************************* ! 43: * Main loop: reads format to determine a pattern, ! 44: * and then goes to read input stream ! 45: * in attempt to match the pattern. ! 46: *******************************************************/ ! 47: for( ; ; ) { ! 48: if((ch = *fmt++) == '\0') ! 49: return(nmatch); /* end of format */ ! 50: if(isspace(ch)) { ! 51: while(isspace(inchar = getc(iop))) ! 52: ; ! 53: if(ungetc(inchar, iop) != EOF) ! 54: continue; ! 55: break; ! 56: } ! 57: if(ch != '%' || (ch = *fmt++) == '%') { ! 58: if((inchar = getc(iop)) == ch) ! 59: continue; ! 60: if(ungetc(inchar, iop) != EOF) ! 61: return(nmatch); /* failed to match input */ ! 62: break; ! 63: } ! 64: if(ch == '*') { ! 65: stow = 0; ! 66: ch = *fmt++; ! 67: } else ! 68: stow = 1; ! 69: ! 70: for(len = 0; isdigit(ch); ch = *fmt++) ! 71: len = len * 10 + ch - '0'; ! 72: if(len == 0) ! 73: len = MAXINT; ! 74: ! 75: if((size = ch) == 'l' || size == 'h') ! 76: ch = *fmt++; ! 77: if(ch == '\0' || ! 78: ch == '[' && (fmt = setup(fmt, tab)) == NULL) ! 79: return(EOF); /* unexpected end of format */ ! 80: if(isupper(ch)) { /* no longer documented */ ! 81: size = 'l'; ! 82: ch = _tolower(ch); ! 83: } ! 84: if(ch != 'c' && ch != '[') { ! 85: while(isspace(inchar = getc(iop))) ! 86: ; ! 87: if(ungetc(inchar, iop) == EOF) ! 88: break; ! 89: } ! 90: if((size = (ch == 'c' || ch == 's' || ch == '[') ? ! 91: string(stow, ch, len, tab, iop, &va_alist) : ! 92: number(stow, ch, len, size, iop, &va_alist)) != 0) ! 93: nmatch += stow; ! 94: if(va_alist == NULL) /* end of input */ ! 95: break; ! 96: if(size == 0) ! 97: return(nmatch); /* failed to match input */ ! 98: } ! 99: return(nmatch != 0 ? nmatch : EOF); /* end of input */ ! 100: } ! 101: ! 102: /*************************************************************** ! 103: * Functions to read the input stream in an attempt to match incoming ! 104: * data to the current pattern from the main loop of _doscan(). ! 105: ***************************************************************/ ! 106: static int ! 107: number(stow, type, len, size, iop, listp) ! 108: int stow, type, len, size; ! 109: register FILE *iop; ! 110: va_list *listp; ! 111: { ! 112: char numbuf[64]; ! 113: register char *np = numbuf; ! 114: register int c, base; ! 115: int digitseen = 0, dotseen = 0, expseen = 0, floater = 0, negflg = 0; ! 116: long lcval = 0; ! 117: ! 118: switch(type) { ! 119: case 'e': ! 120: case 'f': ! 121: case 'g': ! 122: floater++; ! 123: case 'd': ! 124: case 'u': ! 125: base = 10; ! 126: break; ! 127: case 'o': ! 128: base = 8; ! 129: break; ! 130: case 'x': ! 131: base = 16; ! 132: break; ! 133: default: ! 134: return(0); /* unrecognized conversion character */ ! 135: } ! 136: switch(c = getc(iop)) { ! 137: case '-': ! 138: negflg++; ! 139: case '+': /* fall-through */ ! 140: len--; ! 141: c = getc(iop); ! 142: } ! 143: for( ; --len >= 0; *np++ = c, c = getc(iop)) { ! 144: if(isdigit(c) || base == 16 && isxdigit(c)) { ! 145: int digit = c - (isdigit(c) ? '0' : ! 146: isupper(c) ? 'A' - 10 : 'a' - 10); ! 147: if(digit >= base) ! 148: break; ! 149: if(stow && !floater) ! 150: lcval = base * lcval + digit; ! 151: digitseen++; ! 152: continue; ! 153: } ! 154: if(!floater) ! 155: break; ! 156: if(c == '.' && !dotseen++) ! 157: continue; ! 158: if((c == 'e' || c == 'E') && digitseen && !expseen++) { ! 159: *np++ = c; ! 160: c = getc(iop); ! 161: if(isdigit(c) || c == '+' || c == '-') ! 162: continue; ! 163: } ! 164: break; ! 165: } ! 166: if(stow && digitseen) ! 167: if(floater) { ! 168: register double dval; ! 169: ! 170: *np = '\0'; ! 171: dval = atof(numbuf); ! 172: if(negflg) ! 173: dval = -dval; ! 174: if(size == 'l') ! 175: *va_arg(*listp, double *) = dval; ! 176: else ! 177: *va_arg(*listp, float *) = (float)dval; ! 178: } else { ! 179: /* suppress possible overflow on 2's-comp negation */ ! 180: if(negflg && lcval != HIBITL) ! 181: lcval = -lcval; ! 182: if(size == 'l') ! 183: *va_arg(*listp, long *) = lcval; ! 184: else if(size == 'h') ! 185: *va_arg(*listp, short *) = (short)lcval; ! 186: else ! 187: *va_arg(*listp, int *) = (int)lcval; ! 188: } ! 189: if(ungetc(c, iop) == EOF) ! 190: *listp = NULL; /* end of input */ ! 191: return(digitseen); /* successful match if non-zero */ ! 192: } ! 193: ! 194: static int ! 195: string(stow, type, len, tab, iop, listp) ! 196: register int stow, type, len; ! 197: register char *tab; ! 198: register FILE *iop; ! 199: va_list *listp; ! 200: { ! 201: register int ch; ! 202: register char *ptr; ! 203: char *start; ! 204: ! 205: start = ptr = stow ? va_arg(*listp, char *) : NULL; ! 206: if(type == 'c' && len == MAXINT) ! 207: len = 1; ! 208: while((ch = getc(iop)) != EOF && ! 209: !(type == 's' && isspace(ch) || type == '[' && tab[ch])) { ! 210: if(stow) ! 211: *ptr = ch; ! 212: ptr++; ! 213: if(--len <= 0) ! 214: break; ! 215: } ! 216: if(ch == EOF || len > 0 && ungetc(ch, iop) == EOF) ! 217: *listp = NULL; /* end of input */ ! 218: if(ptr == start) ! 219: return(0); /* no match */ ! 220: if(stow && type != 'c') ! 221: *ptr = '\0'; ! 222: return(1); /* successful match */ ! 223: } ! 224: ! 225: static unsigned char * ! 226: setup(fmt, tab) ! 227: register unsigned char *fmt; ! 228: register char *tab; ! 229: { ! 230: register int b, c, d, t = 0; ! 231: ! 232: if(*fmt == '^') { ! 233: t++; ! 234: fmt++; ! 235: } ! 236: (void)memset(tab, !t, NCHARS); ! 237: if((c = *fmt) == ']' || c == '-') { /* first char is special */ ! 238: tab[c] = t; ! 239: fmt++; ! 240: } ! 241: while((c = *fmt++) != ']') { ! 242: if(c == '\0') ! 243: return(NULL); /* unexpected end of format */ ! 244: if(c == '-' && (d = *fmt) != ']' && (b = fmt[-2]) < d) { ! 245: (void)memset(&tab[b], t, d - b); ! 246: fmt++; ! 247: } else ! 248: tab[c] = t; ! 249: } ! 250: return(fmt); ! 251: } ! 252: #else ! 253: /* This is just to keep from getting a diagnostic from ranlib. */ ! 254: __dsdummy__() ! 255: { ! 256: } ! 257: #endif NEEDDOSCAN
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.