|
|
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.