1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright (c) 1996, by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate * All rights reserved.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate * System V.2 Emulation Stdio Library -- vfscanf
31*0Sstevel@tonic-gate *
32*0Sstevel@tonic-gate * Copyright 1985, 1992 by Mortice Kern Systems Inc. All rights reserved.
33*0Sstevel@tonic-gate *
34*0Sstevel@tonic-gate */
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gate #ifdef M_RCSID
37*0Sstevel@tonic-gate #ifndef lint
38*0Sstevel@tonic-gate static char rcsID[] = "$Id: vfscanf.c 1.27 1995/09/20 19:07:52 ant Exp $";
39*0Sstevel@tonic-gate #endif
40*0Sstevel@tonic-gate #endif
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate #include <mks.h>
43*0Sstevel@tonic-gate #include <ctype.h>
44*0Sstevel@tonic-gate #include <limits.h>
45*0Sstevel@tonic-gate #include <stdarg.h>
46*0Sstevel@tonic-gate #include <stdlib.h>
47*0Sstevel@tonic-gate #include <string.h>
48*0Sstevel@tonic-gate #ifdef __FLOAT__
49*0Sstevel@tonic-gate #include <math.h>
50*0Sstevel@tonic-gate #endif
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate #define CONVTYPE 1
53*0Sstevel@tonic-gate #define STAR 2
54*0Sstevel@tonic-gate #define PERCENT 3
55*0Sstevel@tonic-gate #define NUMBER 4
56*0Sstevel@tonic-gate #define MODCONVL 5
57*0Sstevel@tonic-gate #define NSCAN 6
58*0Sstevel@tonic-gate #define BRACKET 7
59*0Sstevel@tonic-gate #define MODCONVH 8
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gate #define BASE16 16
62*0Sstevel@tonic-gate #define BASE10 10
63*0Sstevel@tonic-gate #define BASE8 8
64*0Sstevel@tonic-gate #define NOBASE 0
65*0Sstevel@tonic-gate #define SIGNED 1
66*0Sstevel@tonic-gate #define UNSIGNED 0
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate #define CBUFSIZ 100 /* size of character buffer for input conversion */
69*0Sstevel@tonic-gate
70*0Sstevel@tonic-gate struct lexlist {
71*0Sstevel@tonic-gate char name;
72*0Sstevel@tonic-gate char type;
73*0Sstevel@tonic-gate };
74*0Sstevel@tonic-gate static struct lexlist *lexp;
75*0Sstevel@tonic-gate static struct lexlist lexlist[] ={
76*0Sstevel@tonic-gate '*', STAR,
77*0Sstevel@tonic-gate '%', PERCENT,
78*0Sstevel@tonic-gate 'l', MODCONVL,
79*0Sstevel@tonic-gate 'h', MODCONVH,
80*0Sstevel@tonic-gate 'n', NSCAN,
81*0Sstevel@tonic-gate '[', BRACKET,
82*0Sstevel@tonic-gate 'd', CONVTYPE,
83*0Sstevel@tonic-gate 'S', CONVTYPE, /* dummy entry (for multibyte characters) */
84*0Sstevel@tonic-gate 's', CONVTYPE,
85*0Sstevel@tonic-gate 'u', CONVTYPE,
86*0Sstevel@tonic-gate 'c', CONVTYPE,
87*0Sstevel@tonic-gate 'x', CONVTYPE,
88*0Sstevel@tonic-gate 'o', CONVTYPE,
89*0Sstevel@tonic-gate '0', NUMBER,
90*0Sstevel@tonic-gate '1', NUMBER,
91*0Sstevel@tonic-gate '2', NUMBER,
92*0Sstevel@tonic-gate '3', NUMBER,
93*0Sstevel@tonic-gate '4', NUMBER,
94*0Sstevel@tonic-gate '5', NUMBER,
95*0Sstevel@tonic-gate '6', NUMBER,
96*0Sstevel@tonic-gate '7', NUMBER,
97*0Sstevel@tonic-gate '8', NUMBER,
98*0Sstevel@tonic-gate '9', NUMBER,
99*0Sstevel@tonic-gate 'i', CONVTYPE,
100*0Sstevel@tonic-gate 'f', CONVTYPE,
101*0Sstevel@tonic-gate 'e', CONVTYPE,
102*0Sstevel@tonic-gate 'g', CONVTYPE,
103*0Sstevel@tonic-gate 0, 0
104*0Sstevel@tonic-gate };
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gate static int scan(int, const char *, const char *);
107*0Sstevel@tonic-gate static int gettoken(void);
108*0Sstevel@tonic-gate static void whitespace(void);
109*0Sstevel@tonic-gate static int match(const char *, char *);
110*0Sstevel@tonic-gate static long unsigned getnum(int, int, int);
111*0Sstevel@tonic-gate static int getin(void);
112*0Sstevel@tonic-gate static void unget(int);
113*0Sstevel@tonic-gate #ifdef __FLOAT__
114*0Sstevel@tonic-gate static double lstrtod(void);
115*0Sstevel@tonic-gate #endif
116*0Sstevel@tonic-gate
117*0Sstevel@tonic-gate static int ungot; /* getin/unget char */
118*0Sstevel@tonic-gate static FILE *fpin; /* input file pointer */
119*0Sstevel@tonic-gate static int pflag; /*indicator of conversion description present */
120*0Sstevel@tonic-gate static int width; /* field width value */
121*0Sstevel@tonic-gate static const char *fmtptr; /* format string pointer */
122*0Sstevel@tonic-gate static int charcnt; /* number of characters scanned (for %n) */
123*0Sstevel@tonic-gate static int from; /* token type we've come from */
124*0Sstevel@tonic-gate static int gfail; /* getnum() fail flag, non-zero for fail */
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate /*
127*0Sstevel@tonic-gate * Convert formatted input from given input.
128*0Sstevel@tonic-gate * This is the workhorse for scanf, sscanf, and fscanf.
129*0Sstevel@tonic-gate * Returns the number of matched and assigned input items.
130*0Sstevel@tonic-gate */
131*0Sstevel@tonic-gate int
mks_vfscanf(FILE * pfin,const char * fmt,va_list ap)132*0Sstevel@tonic-gate mks_vfscanf(FILE *pfin, const char *fmt, va_list ap)
133*0Sstevel@tonic-gate {
134*0Sstevel@tonic-gate int nitems;
135*0Sstevel@tonic-gate int ltoken;
136*0Sstevel@tonic-gate int c;
137*0Sstevel@tonic-gate int modconv; /* flag indicating conversion modifier */
138*0Sstevel@tonic-gate int suppression; /* flag to suppress conversion */
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate long unsigned number; /* return value from getnumber */
141*0Sstevel@tonic-gate
142*0Sstevel@tonic-gate ungot = EOF;
143*0Sstevel@tonic-gate fpin = pfin;
144*0Sstevel@tonic-gate fmtptr = fmt;
145*0Sstevel@tonic-gate from = 'X';
146*0Sstevel@tonic-gate nitems = 0;
147*0Sstevel@tonic-gate charcnt = 0;
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate for (;;) {
150*0Sstevel@tonic-gate if (from == 'X') {
151*0Sstevel@tonic-gate pflag = 0;
152*0Sstevel@tonic-gate modconv = 0;
153*0Sstevel@tonic-gate suppression = 0;
154*0Sstevel@tonic-gate width = 0;
155*0Sstevel@tonic-gate }
156*0Sstevel@tonic-gate ltoken = gettoken();
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gate switch (ltoken) {
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate case 0:
161*0Sstevel@tonic-gate goto retitems;
162*0Sstevel@tonic-gate
163*0Sstevel@tonic-gate case MODCONVL:
164*0Sstevel@tonic-gate case MODCONVH:
165*0Sstevel@tonic-gate switch (from) {
166*0Sstevel@tonic-gate
167*0Sstevel@tonic-gate case 'A':
168*0Sstevel@tonic-gate case 'D':
169*0Sstevel@tonic-gate case 'P':
170*0Sstevel@tonic-gate from = 'E';
171*0Sstevel@tonic-gate modconv = ltoken;
172*0Sstevel@tonic-gate break;
173*0Sstevel@tonic-gate default:
174*0Sstevel@tonic-gate from = 'X';
175*0Sstevel@tonic-gate break;
176*0Sstevel@tonic-gate }
177*0Sstevel@tonic-gate break;
178*0Sstevel@tonic-gate
179*0Sstevel@tonic-gate case CONVTYPE:
180*0Sstevel@tonic-gate switch (from) {
181*0Sstevel@tonic-gate
182*0Sstevel@tonic-gate int intassign;
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate case 'E':
185*0Sstevel@tonic-gate case 'P':
186*0Sstevel@tonic-gate case 'D':
187*0Sstevel@tonic-gate case 'A':
188*0Sstevel@tonic-gate from = 'X';
189*0Sstevel@tonic-gate intassign = 1;
190*0Sstevel@tonic-gate pflag = 0;
191*0Sstevel@tonic-gate
192*0Sstevel@tonic-gate switch (lexp->name) {
193*0Sstevel@tonic-gate
194*0Sstevel@tonic-gate case 'd':
195*0Sstevel@tonic-gate number = getnum(BASE10, width, SIGNED);
196*0Sstevel@tonic-gate if (gfail)
197*0Sstevel@tonic-gate goto retitems;
198*0Sstevel@tonic-gate break;
199*0Sstevel@tonic-gate case 'u':
200*0Sstevel@tonic-gate number = getnum(BASE10, width, UNSIGNED);
201*0Sstevel@tonic-gate if (gfail)
202*0Sstevel@tonic-gate goto retitems;
203*0Sstevel@tonic-gate break;
204*0Sstevel@tonic-gate case 'x':
205*0Sstevel@tonic-gate number = getnum(BASE16, width, SIGNED);
206*0Sstevel@tonic-gate if (gfail)
207*0Sstevel@tonic-gate goto retitems;
208*0Sstevel@tonic-gate break;
209*0Sstevel@tonic-gate case 'o':
210*0Sstevel@tonic-gate number = getnum(BASE8, width, SIGNED);
211*0Sstevel@tonic-gate if (gfail)
212*0Sstevel@tonic-gate goto retitems;
213*0Sstevel@tonic-gate break;
214*0Sstevel@tonic-gate case 'i':
215*0Sstevel@tonic-gate number = getnum(NOBASE, width, SIGNED);
216*0Sstevel@tonic-gate if (gfail)
217*0Sstevel@tonic-gate goto retitems;
218*0Sstevel@tonic-gate break;
219*0Sstevel@tonic-gate case 'c':
220*0Sstevel@tonic-gate /* 'S' dummy entry (for multibyte characters) */
221*0Sstevel@tonic-gate case 'S':
222*0Sstevel@tonic-gate case 's': {
223*0Sstevel@tonic-gate int gotitem = 0;
224*0Sstevel@tonic-gate char *str;
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate if (!suppression)
227*0Sstevel@tonic-gate str = va_arg(ap, char *);
228*0Sstevel@tonic-gate
229*0Sstevel@tonic-gate /* Input whitespace is not skipped
230*0Sstevel@tonic-gate * for %c, which implies that %c
231*0Sstevel@tonic-gate * can return whitespace.
232*0Sstevel@tonic-gate */
233*0Sstevel@tonic-gate if (lexp->name != 'c')
234*0Sstevel@tonic-gate whitespace();
235*0Sstevel@tonic-gate for (;;) {
236*0Sstevel@tonic-gate c = getin();
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gate /* Only %s and %S stop on
239*0Sstevel@tonic-gate * whitespace.
240*0Sstevel@tonic-gate */
241*0Sstevel@tonic-gate if (lexp->name != 'c' && isspace(c)) {
242*0Sstevel@tonic-gate unget(c);
243*0Sstevel@tonic-gate break;
244*0Sstevel@tonic-gate }
245*0Sstevel@tonic-gate if (c == EOF) {
246*0Sstevel@tonic-gate if(!gotitem)
247*0Sstevel@tonic-gate goto retitems;
248*0Sstevel@tonic-gate break;
249*0Sstevel@tonic-gate }
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gate gotitem = 1;
252*0Sstevel@tonic-gate if (!suppression)
253*0Sstevel@tonic-gate *str++ = c;
254*0Sstevel@tonic-gate
255*0Sstevel@tonic-gate if (width) {
256*0Sstevel@tonic-gate if (--width == 0)
257*0Sstevel@tonic-gate break;
258*0Sstevel@tonic-gate }
259*0Sstevel@tonic-gate }
260*0Sstevel@tonic-gate
261*0Sstevel@tonic-gate /*
262*0Sstevel@tonic-gate * ANSI C states that %c does not
263*0Sstevel@tonic-gate * terminate with a null character.
264*0Sstevel@tonic-gate */
265*0Sstevel@tonic-gate if (!suppression && lexp->name != 'c')
266*0Sstevel@tonic-gate *str = '\0';
267*0Sstevel@tonic-gate intassign = 0;
268*0Sstevel@tonic-gate break;
269*0Sstevel@tonic-gate }
270*0Sstevel@tonic-gate #ifdef __FLOAT__
271*0Sstevel@tonic-gate case 'f':
272*0Sstevel@tonic-gate case 'g':
273*0Sstevel@tonic-gate case 'e': {
274*0Sstevel@tonic-gate double fresult;
275*0Sstevel@tonic-gate
276*0Sstevel@tonic-gate fresult = lstrtod();
277*0Sstevel@tonic-gate if(gfail)
278*0Sstevel@tonic-gate goto retitems;
279*0Sstevel@tonic-gate if(suppression)
280*0Sstevel@tonic-gate break;
281*0Sstevel@tonic-gate if (modconv == MODCONVL)
282*0Sstevel@tonic-gate *(double *)va_arg(ap, double *) = fresult;
283*0Sstevel@tonic-gate else
284*0Sstevel@tonic-gate *(float *)va_arg(ap, float *) = (float)fresult;
285*0Sstevel@tonic-gate /*FALLTHROUGH*/
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate #else /* !__FLOAT__ */
288*0Sstevel@tonic-gate case 'f':
289*0Sstevel@tonic-gate case 'g':
290*0Sstevel@tonic-gate case 'e':
291*0Sstevel@tonic-gate #endif /* __FLOAT__ */
292*0Sstevel@tonic-gate default:
293*0Sstevel@tonic-gate intassign = 0;
294*0Sstevel@tonic-gate break;
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate
297*0Sstevel@tonic-gate if (suppression)
298*0Sstevel@tonic-gate break;
299*0Sstevel@tonic-gate else
300*0Sstevel@tonic-gate nitems++;
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gate if (intassign == 0)
303*0Sstevel@tonic-gate break;
304*0Sstevel@tonic-gate
305*0Sstevel@tonic-gate switch (modconv) {
306*0Sstevel@tonic-gate
307*0Sstevel@tonic-gate case MODCONVH:
308*0Sstevel@tonic-gate *(short *)va_arg(ap, short *) = (short)number;
309*0Sstevel@tonic-gate break;
310*0Sstevel@tonic-gate case MODCONVL:
311*0Sstevel@tonic-gate *(long *)va_arg(ap, long *) = (long)number;
312*0Sstevel@tonic-gate break;
313*0Sstevel@tonic-gate default:
314*0Sstevel@tonic-gate *(int *)va_arg(ap, int *) = (int)number;
315*0Sstevel@tonic-gate break;
316*0Sstevel@tonic-gate }
317*0Sstevel@tonic-gate break;
318*0Sstevel@tonic-gate default:
319*0Sstevel@tonic-gate from = 'X';
320*0Sstevel@tonic-gate break;
321*0Sstevel@tonic-gate }
322*0Sstevel@tonic-gate break;
323*0Sstevel@tonic-gate
324*0Sstevel@tonic-gate case STAR:
325*0Sstevel@tonic-gate if (from == 'P') {
326*0Sstevel@tonic-gate from = 'A';
327*0Sstevel@tonic-gate suppression = 1;
328*0Sstevel@tonic-gate } else {
329*0Sstevel@tonic-gate from = 'X';
330*0Sstevel@tonic-gate }
331*0Sstevel@tonic-gate break;
332*0Sstevel@tonic-gate
333*0Sstevel@tonic-gate case PERCENT:
334*0Sstevel@tonic-gate if (from == 'P') {
335*0Sstevel@tonic-gate from = 'X';
336*0Sstevel@tonic-gate pflag = 0;
337*0Sstevel@tonic-gate c = getin();
338*0Sstevel@tonic-gate if (c != '%')
339*0Sstevel@tonic-gate goto retitems;
340*0Sstevel@tonic-gate } else {
341*0Sstevel@tonic-gate from = 'X';
342*0Sstevel@tonic-gate }
343*0Sstevel@tonic-gate break;
344*0Sstevel@tonic-gate
345*0Sstevel@tonic-gate case NUMBER:
346*0Sstevel@tonic-gate if (from == 'P' || from == 'A') {
347*0Sstevel@tonic-gate from = 'D';
348*0Sstevel@tonic-gate } else {
349*0Sstevel@tonic-gate from = 'X';
350*0Sstevel@tonic-gate }
351*0Sstevel@tonic-gate break;
352*0Sstevel@tonic-gate
353*0Sstevel@tonic-gate case NSCAN:
354*0Sstevel@tonic-gate if (from == 'P') {
355*0Sstevel@tonic-gate pflag = 0;
356*0Sstevel@tonic-gate if (!suppression) {
357*0Sstevel@tonic-gate *(int *)va_arg(ap, int *) = charcnt;
358*0Sstevel@tonic-gate }
359*0Sstevel@tonic-gate }
360*0Sstevel@tonic-gate from = 'X';
361*0Sstevel@tonic-gate break;
362*0Sstevel@tonic-gate
363*0Sstevel@tonic-gate case BRACKET:
364*0Sstevel@tonic-gate switch (from) {
365*0Sstevel@tonic-gate
366*0Sstevel@tonic-gate case 'A':
367*0Sstevel@tonic-gate case 'D':
368*0Sstevel@tonic-gate case 'P': {
369*0Sstevel@tonic-gate char *ptr;
370*0Sstevel@tonic-gate
371*0Sstevel@tonic-gate pflag = 0;
372*0Sstevel@tonic-gate if (width == 0)
373*0Sstevel@tonic-gate width = INT_MAX;
374*0Sstevel@tonic-gate ptr = suppression ? NULL : va_arg(ap, char *);
375*0Sstevel@tonic-gate if (match(fmtptr, ptr) && !feof(fpin)
376*0Sstevel@tonic-gate && !suppression)
377*0Sstevel@tonic-gate nitems++;
378*0Sstevel@tonic-gate while (*fmtptr++ != ']')
379*0Sstevel@tonic-gate ;
380*0Sstevel@tonic-gate break;
381*0Sstevel@tonic-gate }
382*0Sstevel@tonic-gate default:
383*0Sstevel@tonic-gate break;
384*0Sstevel@tonic-gate }
385*0Sstevel@tonic-gate from = 'X';
386*0Sstevel@tonic-gate break;
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate default:
389*0Sstevel@tonic-gate c = *(fmtptr-1);
390*0Sstevel@tonic-gate if (c == ' ' || c == '\t' || c == '\n' || c == '\f')
391*0Sstevel@tonic-gate whitespace();
392*0Sstevel@tonic-gate else {
393*0Sstevel@tonic-gate c = getin();
394*0Sstevel@tonic-gate
395*0Sstevel@tonic-gate if (c != *(fmtptr-1))
396*0Sstevel@tonic-gate goto retitems;
397*0Sstevel@tonic-gate }
398*0Sstevel@tonic-gate from = 'X';
399*0Sstevel@tonic-gate break;
400*0Sstevel@tonic-gate }
401*0Sstevel@tonic-gate }
402*0Sstevel@tonic-gate retitems:
403*0Sstevel@tonic-gate if (ungot != EOF) {
404*0Sstevel@tonic-gate ungetc(ungot, fpin);
405*0Sstevel@tonic-gate ungot = EOF;
406*0Sstevel@tonic-gate }
407*0Sstevel@tonic-gate return nitems==0 ? EOF : nitems;
408*0Sstevel@tonic-gate }
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate static int
gettoken()411*0Sstevel@tonic-gate gettoken()
412*0Sstevel@tonic-gate {
413*0Sstevel@tonic-gate char c;
414*0Sstevel@tonic-gate
415*0Sstevel@tonic-gate if (*fmtptr == 0)
416*0Sstevel@tonic-gate return 0; /* return 0 for end of string */
417*0Sstevel@tonic-gate
418*0Sstevel@tonic-gate c = *fmtptr++;
419*0Sstevel@tonic-gate
420*0Sstevel@tonic-gate if (pflag) {
421*0Sstevel@tonic-gate for(lexp=lexlist; lexp->name != 0; lexp++) {
422*0Sstevel@tonic-gate if (c == lexp->name) {
423*0Sstevel@tonic-gate if (lexp->type == NUMBER) {
424*0Sstevel@tonic-gate width = (int) strtol(fmtptr-1, (char **)0, BASE10);
425*0Sstevel@tonic-gate while (*fmtptr >= '0' && *fmtptr <= '9')
426*0Sstevel@tonic-gate fmtptr++;
427*0Sstevel@tonic-gate } else if (c == 'c') {
428*0Sstevel@tonic-gate /* No width specified for %c, default
429*0Sstevel@tonic-gate * is one.
430*0Sstevel@tonic-gate */
431*0Sstevel@tonic-gate width = 1;
432*0Sstevel@tonic-gate }
433*0Sstevel@tonic-gate return lexp->type;
434*0Sstevel@tonic-gate }
435*0Sstevel@tonic-gate }
436*0Sstevel@tonic-gate return -1;
437*0Sstevel@tonic-gate }
438*0Sstevel@tonic-gate
439*0Sstevel@tonic-gate if (c == '%') {
440*0Sstevel@tonic-gate pflag = 1;
441*0Sstevel@tonic-gate from = 'P';
442*0Sstevel@tonic-gate return gettoken();
443*0Sstevel@tonic-gate }
444*0Sstevel@tonic-gate return -1;
445*0Sstevel@tonic-gate }
446*0Sstevel@tonic-gate
447*0Sstevel@tonic-gate static void
whitespace()448*0Sstevel@tonic-gate whitespace()
449*0Sstevel@tonic-gate {
450*0Sstevel@tonic-gate register int c;
451*0Sstevel@tonic-gate
452*0Sstevel@tonic-gate do {
453*0Sstevel@tonic-gate c = getin();
454*0Sstevel@tonic-gate } while (isspace(c));
455*0Sstevel@tonic-gate
456*0Sstevel@tonic-gate unget(c);
457*0Sstevel@tonic-gate }
458*0Sstevel@tonic-gate
459*0Sstevel@tonic-gate static int
scan(int ch,const char * str,const char * estr)460*0Sstevel@tonic-gate scan(int ch, const char *str, const char *estr)
461*0Sstevel@tonic-gate {
462*0Sstevel@tonic-gate for (; str < estr; ++str)
463*0Sstevel@tonic-gate if (*str == ch)
464*0Sstevel@tonic-gate return 1;
465*0Sstevel@tonic-gate
466*0Sstevel@tonic-gate return 0;
467*0Sstevel@tonic-gate }
468*0Sstevel@tonic-gate
469*0Sstevel@tonic-gate static int
match(const char * str,char * outstr)470*0Sstevel@tonic-gate match(const char *str, char *outstr)
471*0Sstevel@tonic-gate {
472*0Sstevel@tonic-gate int complement;
473*0Sstevel@tonic-gate int i;
474*0Sstevel@tonic-gate char start, end;
475*0Sstevel@tonic-gate int c;
476*0Sstevel@tonic-gate const char *bscan, *escan;
477*0Sstevel@tonic-gate
478*0Sstevel@tonic-gate if (*str == '^') {
479*0Sstevel@tonic-gate complement = 1;
480*0Sstevel@tonic-gate str++;
481*0Sstevel@tonic-gate } else
482*0Sstevel@tonic-gate complement = 0;
483*0Sstevel@tonic-gate
484*0Sstevel@tonic-gate start = *str++;
485*0Sstevel@tonic-gate end = 0;
486*0Sstevel@tonic-gate if (*str == '-') {
487*0Sstevel@tonic-gate if (str[2] == ']')
488*0Sstevel@tonic-gate end = str[1];
489*0Sstevel@tonic-gate }
490*0Sstevel@tonic-gate if (start > end) {
491*0Sstevel@tonic-gate bscan = str - 1;
492*0Sstevel@tonic-gate while (*str++ != ']')
493*0Sstevel@tonic-gate ;
494*0Sstevel@tonic-gate escan = str - 1;
495*0Sstevel@tonic-gate
496*0Sstevel@tonic-gate for (i=0; i<width; i++) {
497*0Sstevel@tonic-gate if ((c = getin()) == EOF)
498*0Sstevel@tonic-gate return 0;
499*0Sstevel@tonic-gate if (!scan(c, bscan, escan) ^ complement)
500*0Sstevel@tonic-gate break;
501*0Sstevel@tonic-gate if (outstr != NULL)
502*0Sstevel@tonic-gate *outstr++ = c;
503*0Sstevel@tonic-gate }
504*0Sstevel@tonic-gate } else {
505*0Sstevel@tonic-gate for (i=0; i<width; i++) {
506*0Sstevel@tonic-gate c = getin();
507*0Sstevel@tonic-gate if (complement) {
508*0Sstevel@tonic-gate if (c >= start && c <= end)
509*0Sstevel@tonic-gate break;
510*0Sstevel@tonic-gate else if (outstr != NULL)
511*0Sstevel@tonic-gate *outstr++ = c;
512*0Sstevel@tonic-gate } else {
513*0Sstevel@tonic-gate if (c < start || c > end)
514*0Sstevel@tonic-gate break;
515*0Sstevel@tonic-gate else if (outstr != NULL)
516*0Sstevel@tonic-gate *outstr++ = c;
517*0Sstevel@tonic-gate }
518*0Sstevel@tonic-gate }
519*0Sstevel@tonic-gate }
520*0Sstevel@tonic-gate
521*0Sstevel@tonic-gate if (i < width)
522*0Sstevel@tonic-gate unget(c);
523*0Sstevel@tonic-gate
524*0Sstevel@tonic-gate if (outstr != NULL)
525*0Sstevel@tonic-gate *outstr = '\0';
526*0Sstevel@tonic-gate return (i > 1);
527*0Sstevel@tonic-gate }
528*0Sstevel@tonic-gate
529*0Sstevel@tonic-gate /*
530*0Sstevel@tonic-gate * Get a number from the input stream.
531*0Sstevel@tonic-gate * The base, if zero, will be determined by the nature of the number.
532*0Sstevel@tonic-gate * A leading 0x means hexadecimal, a leading 0 for octal, otherwise decimal.
533*0Sstevel@tonic-gate *
534*0Sstevel@tonic-gate * if the width is 0 then the max input string length of number is used.
535*0Sstevel@tonic-gate *
536*0Sstevel@tonic-gate * The sign tell us that a signed number is expected (rather than the
537*0Sstevel@tonic-gate * 'u' conversion type which is unsigned).
538*0Sstevel@tonic-gate */
539*0Sstevel@tonic-gate static long unsigned
getnum(int base,int width,int sign)540*0Sstevel@tonic-gate getnum(int base, int width, int sign)
541*0Sstevel@tonic-gate {
542*0Sstevel@tonic-gate char *s;
543*0Sstevel@tonic-gate char cbuf[CBUFSIZ]; /* char buffer for number */
544*0Sstevel@tonic-gate int w;
545*0Sstevel@tonic-gate register int c;
546*0Sstevel@tonic-gate int neg;
547*0Sstevel@tonic-gate long ret;
548*0Sstevel@tonic-gate
549*0Sstevel@tonic-gate gfail = 0;
550*0Sstevel@tonic-gate whitespace();
551*0Sstevel@tonic-gate
552*0Sstevel@tonic-gate if (width == 0)
553*0Sstevel@tonic-gate width = sizeof cbuf;
554*0Sstevel@tonic-gate
555*0Sstevel@tonic-gate neg = 0;
556*0Sstevel@tonic-gate if (sign) {
557*0Sstevel@tonic-gate c = getin();
558*0Sstevel@tonic-gate if (c == '+' || c == '-')
559*0Sstevel@tonic-gate neg = c=='-' ? 1 : 0;
560*0Sstevel@tonic-gate else
561*0Sstevel@tonic-gate unget(c);
562*0Sstevel@tonic-gate }
563*0Sstevel@tonic-gate
564*0Sstevel@tonic-gate if (base == 0) {
565*0Sstevel@tonic-gate base = 10;
566*0Sstevel@tonic-gate c = getin();
567*0Sstevel@tonic-gate if (c == '0') {
568*0Sstevel@tonic-gate base = 8;
569*0Sstevel@tonic-gate c = getin();
570*0Sstevel@tonic-gate if (c == 'X' || c == 'x')
571*0Sstevel@tonic-gate base = 16;
572*0Sstevel@tonic-gate else
573*0Sstevel@tonic-gate unget(c);
574*0Sstevel@tonic-gate } else
575*0Sstevel@tonic-gate unget(c);
576*0Sstevel@tonic-gate }
577*0Sstevel@tonic-gate if (base == 10) {
578*0Sstevel@tonic-gate w = 0;
579*0Sstevel@tonic-gate s = cbuf;
580*0Sstevel@tonic-gate while (w < width && w < sizeof cbuf) {
581*0Sstevel@tonic-gate c = getin();
582*0Sstevel@tonic-gate switch (c) {
583*0Sstevel@tonic-gate
584*0Sstevel@tonic-gate case '0':
585*0Sstevel@tonic-gate case '1':
586*0Sstevel@tonic-gate case '2':
587*0Sstevel@tonic-gate case '3':
588*0Sstevel@tonic-gate case '4':
589*0Sstevel@tonic-gate case '5':
590*0Sstevel@tonic-gate case '6':
591*0Sstevel@tonic-gate case '7':
592*0Sstevel@tonic-gate case '8':
593*0Sstevel@tonic-gate case '9':
594*0Sstevel@tonic-gate *s++ = c;
595*0Sstevel@tonic-gate w++;
596*0Sstevel@tonic-gate continue;
597*0Sstevel@tonic-gate default:
598*0Sstevel@tonic-gate unget(c);
599*0Sstevel@tonic-gate w = width; /* force end of loop */
600*0Sstevel@tonic-gate break;
601*0Sstevel@tonic-gate }
602*0Sstevel@tonic-gate }
603*0Sstevel@tonic-gate *s = '\0';
604*0Sstevel@tonic-gate ret = strtol(cbuf, (char **)0, 10);
605*0Sstevel@tonic-gate goto retn;
606*0Sstevel@tonic-gate }
607*0Sstevel@tonic-gate if (base == 8) {
608*0Sstevel@tonic-gate w = 0;
609*0Sstevel@tonic-gate s = cbuf;
610*0Sstevel@tonic-gate while (w < width && w < sizeof cbuf) {
611*0Sstevel@tonic-gate c = getin();
612*0Sstevel@tonic-gate switch (c) {
613*0Sstevel@tonic-gate
614*0Sstevel@tonic-gate case '0':
615*0Sstevel@tonic-gate case '1':
616*0Sstevel@tonic-gate case '2':
617*0Sstevel@tonic-gate case '3':
618*0Sstevel@tonic-gate case '4':
619*0Sstevel@tonic-gate case '5':
620*0Sstevel@tonic-gate case '6':
621*0Sstevel@tonic-gate case '7':
622*0Sstevel@tonic-gate *s++ = c;
623*0Sstevel@tonic-gate w++;
624*0Sstevel@tonic-gate continue;
625*0Sstevel@tonic-gate default:
626*0Sstevel@tonic-gate unget(c);
627*0Sstevel@tonic-gate w = width; /* force end of loop */
628*0Sstevel@tonic-gate break;
629*0Sstevel@tonic-gate }
630*0Sstevel@tonic-gate }
631*0Sstevel@tonic-gate *s = '\0';
632*0Sstevel@tonic-gate ret = strtol(cbuf, (char **)0, 8);
633*0Sstevel@tonic-gate goto retn;
634*0Sstevel@tonic-gate }
635*0Sstevel@tonic-gate if (base == 16) {
636*0Sstevel@tonic-gate w = 0;
637*0Sstevel@tonic-gate s = cbuf;
638*0Sstevel@tonic-gate while (w < width && w < sizeof cbuf) {
639*0Sstevel@tonic-gate c = getin();
640*0Sstevel@tonic-gate c = toupper(c);
641*0Sstevel@tonic-gate switch (c) {
642*0Sstevel@tonic-gate
643*0Sstevel@tonic-gate case '0':
644*0Sstevel@tonic-gate case '1':
645*0Sstevel@tonic-gate case '2':
646*0Sstevel@tonic-gate case '3':
647*0Sstevel@tonic-gate case '4':
648*0Sstevel@tonic-gate case '5':
649*0Sstevel@tonic-gate case '6':
650*0Sstevel@tonic-gate case '7':
651*0Sstevel@tonic-gate case '8':
652*0Sstevel@tonic-gate case '9':
653*0Sstevel@tonic-gate case 'A':
654*0Sstevel@tonic-gate case 'B':
655*0Sstevel@tonic-gate case 'C':
656*0Sstevel@tonic-gate case 'D':
657*0Sstevel@tonic-gate case 'E':
658*0Sstevel@tonic-gate case 'F':
659*0Sstevel@tonic-gate *s++ = c;
660*0Sstevel@tonic-gate w++;
661*0Sstevel@tonic-gate continue;
662*0Sstevel@tonic-gate default:
663*0Sstevel@tonic-gate unget(c);
664*0Sstevel@tonic-gate w = width; /* force end of loop */
665*0Sstevel@tonic-gate break;
666*0Sstevel@tonic-gate }
667*0Sstevel@tonic-gate }
668*0Sstevel@tonic-gate *s = '\0';
669*0Sstevel@tonic-gate ret = strtol(cbuf, (char **)0, 16);
670*0Sstevel@tonic-gate goto retn;
671*0Sstevel@tonic-gate }
672*0Sstevel@tonic-gate
673*0Sstevel@tonic-gate /*
674*0Sstevel@tonic-gate * if we get this far then a bad base was passed.
675*0Sstevel@tonic-gate */
676*0Sstevel@tonic-gate gfail = -1;
677*0Sstevel@tonic-gate
678*0Sstevel@tonic-gate retn:
679*0Sstevel@tonic-gate if (*cbuf == '\0') /* No number at all?? */
680*0Sstevel@tonic-gate gfail = -1;
681*0Sstevel@tonic-gate if (neg)
682*0Sstevel@tonic-gate ret = -ret;
683*0Sstevel@tonic-gate return ret;
684*0Sstevel@tonic-gate }
685*0Sstevel@tonic-gate
686*0Sstevel@tonic-gate #ifdef __FLOAT__
687*0Sstevel@tonic-gate static double
lstrtod()688*0Sstevel@tonic-gate lstrtod()
689*0Sstevel@tonic-gate {
690*0Sstevel@tonic-gate int slen;
691*0Sstevel@tonic-gate int neg, eneg;
692*0Sstevel@tonic-gate char cbuf[CBUFSIZ];
693*0Sstevel@tonic-gate register int c;
694*0Sstevel@tonic-gate register char *sp, *s1, *s2, *s3;
695*0Sstevel@tonic-gate double total, exp, tens;
696*0Sstevel@tonic-gate
697*0Sstevel@tonic-gate neg = eneg = 1;
698*0Sstevel@tonic-gate gfail = 0;
699*0Sstevel@tonic-gate
700*0Sstevel@tonic-gate whitespace();
701*0Sstevel@tonic-gate
702*0Sstevel@tonic-gate c = getin();
703*0Sstevel@tonic-gate
704*0Sstevel@tonic-gate if (c == '-' || c == '+')
705*0Sstevel@tonic-gate if (c == '-') {
706*0Sstevel@tonic-gate neg = -1;
707*0Sstevel@tonic-gate c = getin();
708*0Sstevel@tonic-gate }
709*0Sstevel@tonic-gate
710*0Sstevel@tonic-gate sp = s1 = cbuf;
711*0Sstevel@tonic-gate while (c >= '0' && c <= '9') {
712*0Sstevel@tonic-gate *sp++ = c;
713*0Sstevel@tonic-gate c = getin();
714*0Sstevel@tonic-gate }
715*0Sstevel@tonic-gate
716*0Sstevel@tonic-gate s2 = sp;
717*0Sstevel@tonic-gate if (c == '.') {
718*0Sstevel@tonic-gate c = getin();
719*0Sstevel@tonic-gate while (c >= '0' && c <= '9') {
720*0Sstevel@tonic-gate *sp++ = c;
721*0Sstevel@tonic-gate c = getin();
722*0Sstevel@tonic-gate }
723*0Sstevel@tonic-gate }
724*0Sstevel@tonic-gate
725*0Sstevel@tonic-gate s3 = sp;
726*0Sstevel@tonic-gate if (c == 'e' || c == 'E') {
727*0Sstevel@tonic-gate c = getin();
728*0Sstevel@tonic-gate if (c == '-' || c == '+')
729*0Sstevel@tonic-gate if (c == '-') {
730*0Sstevel@tonic-gate eneg = -1;
731*0Sstevel@tonic-gate c = getin();
732*0Sstevel@tonic-gate }
733*0Sstevel@tonic-gate while (c >= '0' && c <= '9') {
734*0Sstevel@tonic-gate *sp++ = c;
735*0Sstevel@tonic-gate c = getin();
736*0Sstevel@tonic-gate }
737*0Sstevel@tonic-gate }
738*0Sstevel@tonic-gate *sp = '\0';
739*0Sstevel@tonic-gate
740*0Sstevel@tonic-gate if (s1 == s2 && s2 == s3) {
741*0Sstevel@tonic-gate gfail = -1;
742*0Sstevel@tonic-gate return 0.0;
743*0Sstevel@tonic-gate }
744*0Sstevel@tonic-gate unget(c);
745*0Sstevel@tonic-gate
746*0Sstevel@tonic-gate /*
747*0Sstevel@tonic-gate * convert the three strings (integer, fraction, and exponent)
748*0Sstevel@tonic-gate * into a floating point number.
749*0Sstevel@tonic-gate */
750*0Sstevel@tonic-gate
751*0Sstevel@tonic-gate total = 0.0;
752*0Sstevel@tonic-gate tens = 1.0;
753*0Sstevel@tonic-gate for (sp=s2-1; sp >= s1; sp--) {
754*0Sstevel@tonic-gate total += (*sp -'0') * tens;
755*0Sstevel@tonic-gate tens *= 10.0;
756*0Sstevel@tonic-gate }
757*0Sstevel@tonic-gate
758*0Sstevel@tonic-gate tens = .1;
759*0Sstevel@tonic-gate for (sp=s2; sp < s3; sp++) {
760*0Sstevel@tonic-gate total += (*sp - '0') * tens;
761*0Sstevel@tonic-gate tens /= 10.0;
762*0Sstevel@tonic-gate }
763*0Sstevel@tonic-gate total *= (double)neg;
764*0Sstevel@tonic-gate
765*0Sstevel@tonic-gate exp = 0.0;
766*0Sstevel@tonic-gate tens = 1.0;
767*0Sstevel@tonic-gate if ((slen = strlen(s3)) > 0) {
768*0Sstevel@tonic-gate sp = s3 + slen - 1;
769*0Sstevel@tonic-gate for ( ; sp >= s3; sp--) {
770*0Sstevel@tonic-gate exp += (*sp - '0') * tens;
771*0Sstevel@tonic-gate tens *= 10.0;
772*0Sstevel@tonic-gate }
773*0Sstevel@tonic-gate }
774*0Sstevel@tonic-gate *sp = '\0';
775*0Sstevel@tonic-gate
776*0Sstevel@tonic-gate exp *= (double)eneg;
777*0Sstevel@tonic-gate
778*0Sstevel@tonic-gate total *= pow(10.0, exp);
779*0Sstevel@tonic-gate
780*0Sstevel@tonic-gate return total;
781*0Sstevel@tonic-gate }
782*0Sstevel@tonic-gate #endif /* __FLOAT__ */
783*0Sstevel@tonic-gate
784*0Sstevel@tonic-gate static int
getin()785*0Sstevel@tonic-gate getin()
786*0Sstevel@tonic-gate {
787*0Sstevel@tonic-gate int c;
788*0Sstevel@tonic-gate
789*0Sstevel@tonic-gate if (ungot != EOF) {
790*0Sstevel@tonic-gate c = ungot;
791*0Sstevel@tonic-gate ungot = EOF;
792*0Sstevel@tonic-gate } else
793*0Sstevel@tonic-gate c = getc(fpin);
794*0Sstevel@tonic-gate charcnt++;
795*0Sstevel@tonic-gate return c;
796*0Sstevel@tonic-gate }
797*0Sstevel@tonic-gate
798*0Sstevel@tonic-gate static void
unget(int c)799*0Sstevel@tonic-gate unget(int c)
800*0Sstevel@tonic-gate {
801*0Sstevel@tonic-gate /* Dont' use ungetc because it doesn't work with m_fsopen */
802*0Sstevel@tonic-gate ungot = c;
803*0Sstevel@tonic-gate charcnt--;
804*0Sstevel@tonic-gate }
805*0Sstevel@tonic-gate
806