add strdup for S5
[unix-history] / usr / src / lib / libc / stdio / vfscanf.c
CommitLineData
2ce81398
DS
1#if defined(LIBC_SCCS) && !defined(lint)
2static char sccsid[] = "@(#)vfscanf.c 5.2 (Berkeley) %G%";
3#endif LIBC_SCCS and not lint
87bdee5f 4
87bdee5f
KM
5#include <stdio.h>
6#include <ctype.h>
7
8#define SPC 01
9#define STP 02
10
11#define SHORT 0
12#define REGULAR 1
13#define LONG 2
14#define INT 0
15#define FLOAT 1
16
41e01b3e 17static char *_getccl();
87bdee5f 18
41e01b3e 19static char _sctab[256] = {
87bdee5f
KM
20 0,0,0,0,0,0,0,0,
21 0,SPC,SPC,0,0,0,0,0,
22 0,0,0,0,0,0,0,0,
23 0,0,0,0,0,0,0,0,
24 SPC,0,0,0,0,0,0,0,
25 0,0,0,0,0,0,0,0,
26 0,0,0,0,0,0,0,0,
27 0,0,0,0,0,0,0,0,
28};
29
30_doscan(iop, fmt, argp)
31FILE *iop;
32register char *fmt;
33register int **argp;
34{
35 register int ch;
36 int nmatch, len, ch1;
37 int **ptr, fileended, size;
38
39 nmatch = 0;
40 fileended = 0;
41 for (;;) switch (ch = *fmt++) {
42 case '\0':
43 return (nmatch);
44 case '%':
45 if ((ch = *fmt++) == '%')
46 goto def;
47 ptr = 0;
48 if (ch != '*')
49 ptr = argp++;
50 else
51 ch = *fmt++;
52 len = 0;
53 size = REGULAR;
54 while (isdigit(ch)) {
55 len = len*10 + ch - '0';
56 ch = *fmt++;
57 }
58 if (len == 0)
59 len = 30000;
60 if (ch=='l') {
61 size = LONG;
62 ch = *fmt++;
63 } else if (ch=='h') {
64 size = SHORT;
65 ch = *fmt++;
66 } else if (ch=='[')
67 fmt = _getccl(fmt);
68 if (isupper(ch)) {
69 ch = tolower(ch);
70 size = LONG;
71 }
72 if (ch == '\0')
73 return(-1);
74 if (_innum(ptr, ch, len, size, iop, &fileended) && ptr)
75 nmatch++;
76 if (fileended)
77 return(nmatch? nmatch: -1);
78 break;
79
80 case ' ':
81 case '\n':
82 case '\t':
83 while ((ch1 = getc(iop))==' ' || ch1=='\t' || ch1=='\n')
84 ;
85 if (ch1 != EOF)
86 ungetc(ch1, iop);
87 break;
88
89 default:
90 def:
91 ch1 = getc(iop);
92 if (ch1 != ch) {
93 if (ch1==EOF)
94 return(-1);
95 ungetc(ch1, iop);
96 return(nmatch);
97 }
98 }
99}
100
41e01b3e 101static
87bdee5f
KM
102_innum(ptr, type, len, size, iop, eofptr)
103int **ptr, *eofptr;
41e01b3e 104FILE *iop;
87bdee5f
KM
105{
106 extern double atof();
107 register char *np;
108 char numbuf[64];
109 register c, base;
110 int expseen, scale, negflg, c1, ndigit;
111 long lcval;
112
113 if (type=='c' || type=='s' || type=='[')
114 return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr));
115 lcval = 0;
116 ndigit = 0;
117 scale = INT;
118 if (type=='e'||type=='f')
119 scale = FLOAT;
120 base = 10;
121 if (type=='o')
122 base = 8;
123 else if (type=='x')
124 base = 16;
125 np = numbuf;
126 expseen = 0;
127 negflg = 0;
128 while ((c = getc(iop))==' ' || c=='\t' || c=='\n');
129 if (c=='-') {
130 negflg++;
131 *np++ = c;
132 c = getc(iop);
133 len--;
134 } else if (c=='+') {
135 len--;
136 c = getc(iop);
137 }
138 for ( ; --len>=0; *np++ = c, c = getc(iop)) {
139 if (isdigit(c)
140 || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) {
141 ndigit++;
142 if (base==8)
143 lcval <<=3;
144 else if (base==10)
145 lcval = ((lcval<<2) + lcval)<<1;
146 else
147 lcval <<= 4;
148 c1 = c;
149 if (isdigit(c))
150 c -= '0';
151 else if ('a'<=c && c<='f')
152 c -= 'a'-10;
153 else
154 c -= 'A'-10;
155 lcval += c;
156 c = c1;
157 continue;
158 } else if (c=='.') {
159 if (base!=10 || scale==INT)
160 break;
161 ndigit++;
162 continue;
163 } else if ((c=='e'||c=='E') && expseen==0) {
164 if (base!=10 || scale==INT || ndigit==0)
165 break;
166 expseen++;
167 *np++ = c;
168 c = getc(iop);
169 if (c!='+'&&c!='-'&&('0'>c||c>'9'))
170 break;
171 } else
172 break;
173 }
174 if (negflg)
175 lcval = -lcval;
176 if (c != EOF) {
177 ungetc(c, iop);
178 *eofptr = 0;
179 } else
180 *eofptr = 1;
8ed00122 181 if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) )/* gene dykes*/
87bdee5f
KM
182 return(0);
183 *np++ = 0;
184 switch((scale<<4) | size) {
185
186 case (FLOAT<<4) | SHORT:
187 case (FLOAT<<4) | REGULAR:
188 **(float **)ptr = atof(numbuf);
189 break;
190
191 case (FLOAT<<4) | LONG:
192 **(double **)ptr = atof(numbuf);
193 break;
194
195 case (INT<<4) | SHORT:
196 **(short **)ptr = lcval;
197 break;
198
199 case (INT<<4) | REGULAR:
200 **(int **)ptr = lcval;
201 break;
202
203 case (INT<<4) | LONG:
204 **(long **)ptr = lcval;
205 break;
206 }
207 return(1);
208}
209
41e01b3e 210static
87bdee5f
KM
211_instr(ptr, type, len, iop, eofptr)
212register char *ptr;
41e01b3e 213register FILE *iop;
87bdee5f
KM
214int *eofptr;
215{
216 register ch;
217 register char *optr;
218 int ignstp;
219
220 *eofptr = 0;
221 optr = ptr;
222 if (type=='c' && len==30000)
223 len = 1;
224 ignstp = 0;
225 if (type=='s')
226 ignstp = SPC;
41e01b3e
S
227 while ((ch = getc(iop)) != EOF && _sctab[ch] & ignstp)
228 ;
87bdee5f
KM
229 ignstp = SPC;
230 if (type=='c')
231 ignstp = 0;
232 else if (type=='[')
233 ignstp = STP;
234 while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
235 if (ptr)
236 *ptr++ = ch;
237 if (--len <= 0)
238 break;
239 ch = getc(iop);
240 }
241 if (ch != EOF) {
242 if (len > 0)
243 ungetc(ch, iop);
244 *eofptr = 0;
245 } else
246 *eofptr = 1;
247 if (ptr && ptr!=optr) {
248 if (type!='c')
249 *ptr++ = '\0';
250 return(1);
251 }
252 return(0);
253}
254
41e01b3e 255static char *
87bdee5f 256_getccl(s)
41e01b3e 257register unsigned char *s;
87bdee5f
KM
258{
259 register c, t;
260
261 t = 0;
262 if (*s == '^') {
263 t++;
264 s++;
265 }
41e01b3e 266 for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++)
87bdee5f
KM
267 if (t)
268 _sctab[c] &= ~STP;
269 else
270 _sctab[c] |= STP;
41e01b3e 271 if ((c = *s) == ']' || c == '-') { /* first char is special */
87bdee5f 272 if (t)
41e01b3e 273 _sctab[c] |= STP;
87bdee5f 274 else
41e01b3e
S
275 _sctab[c] &= ~STP;
276 s++;
277 }
278 while ((c = *s++) != ']') {
87bdee5f 279 if (c==0)
41e01b3e
S
280 return((char *)--s);
281 else if (c == '-' && *s != ']' && s[-2] < *s) {
282 for (c = s[-2] + 1; c < *s; c++)
283 if (t)
284 _sctab[c] |= STP;
285 else
286 _sctab[c] &= ~STP;
287 } else if (t)
288 _sctab[c] |= STP;
289 else
290 _sctab[c] &= ~STP;
87bdee5f 291 }
41e01b3e 292 return((char *)s);
87bdee5f 293}