xref: /onnv-gate/usr/src/lib/libxcurses/src/libc/stdio/vfscanf.c (revision 0:68f95e015346)
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