17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1996, by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * System V.2 Emulation Stdio Library -- vfscanf
297c478bd9Sstevel@tonic-gate  *
307c478bd9Sstevel@tonic-gate  * Copyright 1985, 1992 by Mortice Kern Systems Inc.  All rights reserved.
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #ifdef M_RCSID
357c478bd9Sstevel@tonic-gate #ifndef lint
367c478bd9Sstevel@tonic-gate static char rcsID[] = "$Id: vfscanf.c 1.27 1995/09/20 19:07:52 ant Exp $";
377c478bd9Sstevel@tonic-gate #endif
387c478bd9Sstevel@tonic-gate #endif
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include <mks.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate #include <limits.h>
437c478bd9Sstevel@tonic-gate #include <stdarg.h>
447c478bd9Sstevel@tonic-gate #include <stdlib.h>
457c478bd9Sstevel@tonic-gate #include <string.h>
467c478bd9Sstevel@tonic-gate #ifdef __FLOAT__
477c478bd9Sstevel@tonic-gate #include <math.h>
487c478bd9Sstevel@tonic-gate #endif
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #define	CONVTYPE	1
517c478bd9Sstevel@tonic-gate #define STAR		2
527c478bd9Sstevel@tonic-gate #define PERCENT		3
537c478bd9Sstevel@tonic-gate #define NUMBER		4
547c478bd9Sstevel@tonic-gate #define MODCONVL	5
557c478bd9Sstevel@tonic-gate #define NSCAN		6
567c478bd9Sstevel@tonic-gate #define	BRACKET		7
577c478bd9Sstevel@tonic-gate #define MODCONVH	8
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #define BASE16	16
607c478bd9Sstevel@tonic-gate #define BASE10	10
617c478bd9Sstevel@tonic-gate #define BASE8	8
627c478bd9Sstevel@tonic-gate #define NOBASE	0
637c478bd9Sstevel@tonic-gate #define SIGNED	1
647c478bd9Sstevel@tonic-gate #define UNSIGNED 0
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #define	CBUFSIZ	100	/* size of character buffer for input conversion */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate struct lexlist {
697c478bd9Sstevel@tonic-gate 	char	name;
707c478bd9Sstevel@tonic-gate 	char	type;
717c478bd9Sstevel@tonic-gate };
727c478bd9Sstevel@tonic-gate static struct lexlist *lexp;
737c478bd9Sstevel@tonic-gate static struct lexlist lexlist[] ={
747c478bd9Sstevel@tonic-gate 	'*',	STAR,
757c478bd9Sstevel@tonic-gate 	'%',	PERCENT,
767c478bd9Sstevel@tonic-gate 	'l',	MODCONVL,
777c478bd9Sstevel@tonic-gate 	'h',	MODCONVH,
787c478bd9Sstevel@tonic-gate 	'n',	NSCAN,
797c478bd9Sstevel@tonic-gate 	'[',	BRACKET,
807c478bd9Sstevel@tonic-gate 	'd',	CONVTYPE,
817c478bd9Sstevel@tonic-gate 	'S',	CONVTYPE,	/* dummy entry (for multibyte characters) */
827c478bd9Sstevel@tonic-gate 	's',	CONVTYPE,
837c478bd9Sstevel@tonic-gate 	'u',	CONVTYPE,
847c478bd9Sstevel@tonic-gate 	'c',	CONVTYPE,
857c478bd9Sstevel@tonic-gate 	'x',	CONVTYPE,
867c478bd9Sstevel@tonic-gate 	'o',	CONVTYPE,
877c478bd9Sstevel@tonic-gate 	'0',	NUMBER,
887c478bd9Sstevel@tonic-gate 	'1',	NUMBER,
897c478bd9Sstevel@tonic-gate 	'2',	NUMBER,
907c478bd9Sstevel@tonic-gate 	'3',	NUMBER,
917c478bd9Sstevel@tonic-gate 	'4',	NUMBER,
927c478bd9Sstevel@tonic-gate 	'5',	NUMBER,
937c478bd9Sstevel@tonic-gate 	'6',	NUMBER,
947c478bd9Sstevel@tonic-gate 	'7',	NUMBER,
957c478bd9Sstevel@tonic-gate 	'8',	NUMBER,
967c478bd9Sstevel@tonic-gate 	'9',	NUMBER,
977c478bd9Sstevel@tonic-gate 	'i',	CONVTYPE,
987c478bd9Sstevel@tonic-gate 	'f',	CONVTYPE,
997c478bd9Sstevel@tonic-gate 	'e',	CONVTYPE,
1007c478bd9Sstevel@tonic-gate 	'g',	CONVTYPE,
1017c478bd9Sstevel@tonic-gate 	0,	0
1027c478bd9Sstevel@tonic-gate };
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate static int	scan(int, const char *, const char *);
1057c478bd9Sstevel@tonic-gate static	int	gettoken(void);
1067c478bd9Sstevel@tonic-gate static	void	whitespace(void);
1077c478bd9Sstevel@tonic-gate static	int	match(const char *, char *);
1087c478bd9Sstevel@tonic-gate static	long	unsigned	getnum(int, int, int);
1097c478bd9Sstevel@tonic-gate static	int	getin(void);
1107c478bd9Sstevel@tonic-gate static	void	unget(int);
1117c478bd9Sstevel@tonic-gate #ifdef	__FLOAT__
1127c478bd9Sstevel@tonic-gate static	double	lstrtod(void);
1137c478bd9Sstevel@tonic-gate #endif
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate static	int	ungot;		/* getin/unget char */
1167c478bd9Sstevel@tonic-gate static	FILE	*fpin;		/* input file pointer */
1177c478bd9Sstevel@tonic-gate static	int	pflag;		/*indicator of conversion description present */
1187c478bd9Sstevel@tonic-gate static	int	width;		/* field width value */
1197c478bd9Sstevel@tonic-gate static	const	char	*fmtptr;	/* format string pointer */
1207c478bd9Sstevel@tonic-gate static	int	charcnt;	/* number of characters scanned (for %n) */
1217c478bd9Sstevel@tonic-gate static	int	from;		/* token type we've come from */
1227c478bd9Sstevel@tonic-gate static	int	gfail;		/* getnum() fail flag, non-zero for fail */
123*1da57d55SToomas Soome 
1247c478bd9Sstevel@tonic-gate /*
1257c478bd9Sstevel@tonic-gate  * Convert formatted input from given input.
1267c478bd9Sstevel@tonic-gate  * This is the workhorse for scanf, sscanf, and fscanf.
1277c478bd9Sstevel@tonic-gate  * Returns the number of matched and assigned input items.
1287c478bd9Sstevel@tonic-gate  */
1297c478bd9Sstevel@tonic-gate int
mks_vfscanf(FILE * pfin,const char * fmt,va_list ap)1307c478bd9Sstevel@tonic-gate mks_vfscanf(FILE *pfin, const char *fmt, va_list ap)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	int	nitems;
1337c478bd9Sstevel@tonic-gate 	int	ltoken;
1347c478bd9Sstevel@tonic-gate 	int	c;
1357c478bd9Sstevel@tonic-gate 	int	modconv;	/* flag indicating conversion modifier */
1367c478bd9Sstevel@tonic-gate 	int	suppression;	/* flag to suppress conversion */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	long unsigned number;	/* return value from getnumber */
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	ungot = EOF;
1417c478bd9Sstevel@tonic-gate 	fpin = pfin;
1427c478bd9Sstevel@tonic-gate 	fmtptr = fmt;
1437c478bd9Sstevel@tonic-gate 	from = 'X';
1447c478bd9Sstevel@tonic-gate 	nitems = 0;
1457c478bd9Sstevel@tonic-gate 	charcnt = 0;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	for (;;) {
1487c478bd9Sstevel@tonic-gate 		if (from == 'X') {
1497c478bd9Sstevel@tonic-gate 			pflag = 0;
1507c478bd9Sstevel@tonic-gate 			modconv = 0;
1517c478bd9Sstevel@tonic-gate 			suppression = 0;
1527c478bd9Sstevel@tonic-gate 			width = 0;
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 		ltoken = gettoken();
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 		switch (ltoken) {
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 		case 0:
1597c478bd9Sstevel@tonic-gate 			goto retitems;
160*1da57d55SToomas Soome 
1617c478bd9Sstevel@tonic-gate 		case MODCONVL:
1627c478bd9Sstevel@tonic-gate 		case MODCONVH:
1637c478bd9Sstevel@tonic-gate 			switch (from) {
164*1da57d55SToomas Soome 
1657c478bd9Sstevel@tonic-gate 			case 'A':
1667c478bd9Sstevel@tonic-gate 			case 'D':
1677c478bd9Sstevel@tonic-gate 			case 'P':
1687c478bd9Sstevel@tonic-gate 				from = 'E';
1697c478bd9Sstevel@tonic-gate 				modconv = ltoken;
1707c478bd9Sstevel@tonic-gate 				break;
1717c478bd9Sstevel@tonic-gate 			default:
1727c478bd9Sstevel@tonic-gate 				from = 'X';
1737c478bd9Sstevel@tonic-gate 				break;
1747c478bd9Sstevel@tonic-gate 			}
1757c478bd9Sstevel@tonic-gate 			break;
176*1da57d55SToomas Soome 
1777c478bd9Sstevel@tonic-gate 		case CONVTYPE:
1787c478bd9Sstevel@tonic-gate 			switch (from) {
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 			int	intassign;
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 			case 'E':
1837c478bd9Sstevel@tonic-gate 			case 'P':
1847c478bd9Sstevel@tonic-gate 			case 'D':
1857c478bd9Sstevel@tonic-gate 			case 'A':
1867c478bd9Sstevel@tonic-gate 				from = 'X';
1877c478bd9Sstevel@tonic-gate 				intassign = 1;
1887c478bd9Sstevel@tonic-gate 				pflag = 0;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 				switch (lexp->name) {
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 				case 'd':
1937c478bd9Sstevel@tonic-gate 					number = getnum(BASE10, width, SIGNED);
1947c478bd9Sstevel@tonic-gate 					if (gfail)
1957c478bd9Sstevel@tonic-gate 						goto retitems;
1967c478bd9Sstevel@tonic-gate 					break;
1977c478bd9Sstevel@tonic-gate 				case 'u':
1987c478bd9Sstevel@tonic-gate 					number = getnum(BASE10, width, UNSIGNED);
1997c478bd9Sstevel@tonic-gate 					if (gfail)
2007c478bd9Sstevel@tonic-gate 						goto retitems;
2017c478bd9Sstevel@tonic-gate 					break;
2027c478bd9Sstevel@tonic-gate 				case 'x':
2037c478bd9Sstevel@tonic-gate 					number = getnum(BASE16, width, SIGNED);
2047c478bd9Sstevel@tonic-gate 					if (gfail)
2057c478bd9Sstevel@tonic-gate 						goto retitems;
2067c478bd9Sstevel@tonic-gate 					break;
2077c478bd9Sstevel@tonic-gate 				case 'o':
2087c478bd9Sstevel@tonic-gate 					number = getnum(BASE8, width, SIGNED);
2097c478bd9Sstevel@tonic-gate 					if (gfail)
2107c478bd9Sstevel@tonic-gate 						goto retitems;
2117c478bd9Sstevel@tonic-gate 					break;
2127c478bd9Sstevel@tonic-gate 				case 'i':
2137c478bd9Sstevel@tonic-gate 					number = getnum(NOBASE, width, SIGNED);
2147c478bd9Sstevel@tonic-gate 					if (gfail)
2157c478bd9Sstevel@tonic-gate 						goto retitems;
2167c478bd9Sstevel@tonic-gate 					break;
2177c478bd9Sstevel@tonic-gate 				case 'c':
2187c478bd9Sstevel@tonic-gate 				/* 'S' dummy entry (for multibyte characters) */
2197c478bd9Sstevel@tonic-gate 				case 'S':
2207c478bd9Sstevel@tonic-gate 				case 's': {
2217c478bd9Sstevel@tonic-gate 					int gotitem = 0;
2227c478bd9Sstevel@tonic-gate 					char	*str;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 					if (!suppression)
2257c478bd9Sstevel@tonic-gate 						str = va_arg(ap, char *);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 					/* Input whitespace is not skipped
2287c478bd9Sstevel@tonic-gate 					 * for %c, which implies that %c
2297c478bd9Sstevel@tonic-gate 					 * can return whitespace.
2307c478bd9Sstevel@tonic-gate 					 */
2317c478bd9Sstevel@tonic-gate 					if (lexp->name != 'c')
2327c478bd9Sstevel@tonic-gate 						whitespace();
2337c478bd9Sstevel@tonic-gate 					for (;;) {
2347c478bd9Sstevel@tonic-gate 						c = getin();
2357c478bd9Sstevel@tonic-gate 
236*1da57d55SToomas Soome 						/* Only %s and %S stop on
237*1da57d55SToomas Soome 						 * whitespace.
2387c478bd9Sstevel@tonic-gate 						 */
2397c478bd9Sstevel@tonic-gate 						if (lexp->name != 'c' && isspace(c)) {
2407c478bd9Sstevel@tonic-gate 							unget(c);
2417c478bd9Sstevel@tonic-gate 							break;
2427c478bd9Sstevel@tonic-gate 						}
2437c478bd9Sstevel@tonic-gate 						if (c == EOF) {
2447c478bd9Sstevel@tonic-gate 							if(!gotitem)
2457c478bd9Sstevel@tonic-gate 								goto retitems;
2467c478bd9Sstevel@tonic-gate 							break;
2477c478bd9Sstevel@tonic-gate 						}
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 						gotitem = 1;
2507c478bd9Sstevel@tonic-gate 						if (!suppression)
2517c478bd9Sstevel@tonic-gate 							*str++ = c;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 						if (width) {
2547c478bd9Sstevel@tonic-gate 							if (--width == 0)
2557c478bd9Sstevel@tonic-gate 								break;
2567c478bd9Sstevel@tonic-gate 						}
2577c478bd9Sstevel@tonic-gate 					}
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 					/*
260*1da57d55SToomas Soome 					 * ANSI C states that %c does not
2617c478bd9Sstevel@tonic-gate 					 * terminate with a null character.
2627c478bd9Sstevel@tonic-gate 					 */
2637c478bd9Sstevel@tonic-gate 					if (!suppression && lexp->name != 'c')
2647c478bd9Sstevel@tonic-gate 						*str = '\0';
2657c478bd9Sstevel@tonic-gate 					intassign = 0;
2667c478bd9Sstevel@tonic-gate 					break;
2677c478bd9Sstevel@tonic-gate 				}
2687c478bd9Sstevel@tonic-gate #ifdef	__FLOAT__
2697c478bd9Sstevel@tonic-gate 				case 'f':
2707c478bd9Sstevel@tonic-gate 				case 'g':
2717c478bd9Sstevel@tonic-gate 				case 'e': {
2727c478bd9Sstevel@tonic-gate 					double	fresult;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 					fresult = lstrtod();
2757c478bd9Sstevel@tonic-gate 					if(gfail)
2767c478bd9Sstevel@tonic-gate 						goto retitems;
2777c478bd9Sstevel@tonic-gate 					if(suppression)
2787c478bd9Sstevel@tonic-gate 						break;
2797c478bd9Sstevel@tonic-gate 					if (modconv == MODCONVL)
2807c478bd9Sstevel@tonic-gate 						*(double *)va_arg(ap, double *) = fresult;
2817c478bd9Sstevel@tonic-gate 					else
2827c478bd9Sstevel@tonic-gate 						*(float *)va_arg(ap, float *) = (float)fresult;
2837c478bd9Sstevel@tonic-gate 					/*FALLTHROUGH*/
2847c478bd9Sstevel@tonic-gate 				}
2857c478bd9Sstevel@tonic-gate #else	/* !__FLOAT__ */
2867c478bd9Sstevel@tonic-gate 				case 'f':
2877c478bd9Sstevel@tonic-gate 				case 'g':
2887c478bd9Sstevel@tonic-gate 				case 'e':
2897c478bd9Sstevel@tonic-gate #endif	/* __FLOAT__ */
2907c478bd9Sstevel@tonic-gate 				default:
2917c478bd9Sstevel@tonic-gate 					intassign = 0;
2927c478bd9Sstevel@tonic-gate 					break;
2937c478bd9Sstevel@tonic-gate 				}
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 				if (suppression)
2967c478bd9Sstevel@tonic-gate 					break;
2977c478bd9Sstevel@tonic-gate 				else
2987c478bd9Sstevel@tonic-gate 					nitems++;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 				if (intassign == 0)
3017c478bd9Sstevel@tonic-gate 					break;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 				switch (modconv) {
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 				case MODCONVH:
3067c478bd9Sstevel@tonic-gate 					*(short *)va_arg(ap, short *) = (short)number;
3077c478bd9Sstevel@tonic-gate 					break;
3087c478bd9Sstevel@tonic-gate 				case MODCONVL:
3097c478bd9Sstevel@tonic-gate 					*(long *)va_arg(ap, long *) = (long)number;
3107c478bd9Sstevel@tonic-gate 					break;
3117c478bd9Sstevel@tonic-gate 				default:
3127c478bd9Sstevel@tonic-gate 					*(int *)va_arg(ap, int *) = (int)number;
3137c478bd9Sstevel@tonic-gate 					break;
3147c478bd9Sstevel@tonic-gate 				}
3157c478bd9Sstevel@tonic-gate 				break;
3167c478bd9Sstevel@tonic-gate 			default:
3177c478bd9Sstevel@tonic-gate 				from = 'X';
3187c478bd9Sstevel@tonic-gate 				break;
3197c478bd9Sstevel@tonic-gate 			}
3207c478bd9Sstevel@tonic-gate 			break;
321*1da57d55SToomas Soome 
3227c478bd9Sstevel@tonic-gate 		case STAR:
3237c478bd9Sstevel@tonic-gate 			if (from == 'P') {
3247c478bd9Sstevel@tonic-gate 				from = 'A';
3257c478bd9Sstevel@tonic-gate 				suppression = 1;
3267c478bd9Sstevel@tonic-gate 			} else {
3277c478bd9Sstevel@tonic-gate 				from = 'X';
3287c478bd9Sstevel@tonic-gate 			}
3297c478bd9Sstevel@tonic-gate 			break;
330*1da57d55SToomas Soome 
3317c478bd9Sstevel@tonic-gate 		case PERCENT:
3327c478bd9Sstevel@tonic-gate 			if (from == 'P') {
3337c478bd9Sstevel@tonic-gate 				from = 'X';
3347c478bd9Sstevel@tonic-gate 				pflag = 0;
3357c478bd9Sstevel@tonic-gate 				c = getin();
3367c478bd9Sstevel@tonic-gate 				if (c != '%')
3377c478bd9Sstevel@tonic-gate 					goto retitems;
3387c478bd9Sstevel@tonic-gate 			} else {
3397c478bd9Sstevel@tonic-gate 				from = 'X';
3407c478bd9Sstevel@tonic-gate 			}
3417c478bd9Sstevel@tonic-gate 			break;
342*1da57d55SToomas Soome 
3437c478bd9Sstevel@tonic-gate 		case NUMBER:
3447c478bd9Sstevel@tonic-gate 			if (from == 'P' || from == 'A') {
3457c478bd9Sstevel@tonic-gate 				from = 'D';
3467c478bd9Sstevel@tonic-gate 			} else {
3477c478bd9Sstevel@tonic-gate 				from = 'X';
3487c478bd9Sstevel@tonic-gate 			}
3497c478bd9Sstevel@tonic-gate 			break;
350*1da57d55SToomas Soome 
3517c478bd9Sstevel@tonic-gate 		case NSCAN:
3527c478bd9Sstevel@tonic-gate 			if (from == 'P') {
3537c478bd9Sstevel@tonic-gate 				pflag = 0;
3547c478bd9Sstevel@tonic-gate 				if (!suppression) {
3557c478bd9Sstevel@tonic-gate 					*(int *)va_arg(ap, int *) = charcnt;
3567c478bd9Sstevel@tonic-gate 				}
3577c478bd9Sstevel@tonic-gate 			}
3587c478bd9Sstevel@tonic-gate 			from = 'X';
3597c478bd9Sstevel@tonic-gate 			break;
360*1da57d55SToomas Soome 
3617c478bd9Sstevel@tonic-gate 		case BRACKET:
3627c478bd9Sstevel@tonic-gate 			switch (from) {
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 			case 'A':
3657c478bd9Sstevel@tonic-gate 			case 'D':
3667c478bd9Sstevel@tonic-gate 			case 'P': {
3677c478bd9Sstevel@tonic-gate 				char *ptr;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 				pflag = 0;
3707c478bd9Sstevel@tonic-gate 				if (width == 0)
3717c478bd9Sstevel@tonic-gate 					width = INT_MAX;
3727c478bd9Sstevel@tonic-gate 				ptr = suppression ? NULL : va_arg(ap, char *);
373*1da57d55SToomas Soome 				if (match(fmtptr, ptr) && !feof(fpin)
3747c478bd9Sstevel@tonic-gate 				&& !suppression)
3757c478bd9Sstevel@tonic-gate 					nitems++;
3767c478bd9Sstevel@tonic-gate 				while (*fmtptr++ != ']')
3777c478bd9Sstevel@tonic-gate 					;
3787c478bd9Sstevel@tonic-gate 				break;
3797c478bd9Sstevel@tonic-gate 			}
3807c478bd9Sstevel@tonic-gate 			default:
3817c478bd9Sstevel@tonic-gate 				break;
3827c478bd9Sstevel@tonic-gate 			}
3837c478bd9Sstevel@tonic-gate 			from = 'X';
3847c478bd9Sstevel@tonic-gate 			break;
385*1da57d55SToomas Soome 
3867c478bd9Sstevel@tonic-gate 		default:
3877c478bd9Sstevel@tonic-gate 			c = *(fmtptr-1);
3887c478bd9Sstevel@tonic-gate 			if (c == ' ' || c == '\t' || c == '\n' || c == '\f')
3897c478bd9Sstevel@tonic-gate 				whitespace();
3907c478bd9Sstevel@tonic-gate 			else {
3917c478bd9Sstevel@tonic-gate 				c = getin();
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 				if (c != *(fmtptr-1))
3947c478bd9Sstevel@tonic-gate 					goto retitems;
3957c478bd9Sstevel@tonic-gate 			}
3967c478bd9Sstevel@tonic-gate 			from = 'X';
3977c478bd9Sstevel@tonic-gate 			break;
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate retitems:
4017c478bd9Sstevel@tonic-gate 	if (ungot != EOF) {
4027c478bd9Sstevel@tonic-gate 		ungetc(ungot, fpin);
4037c478bd9Sstevel@tonic-gate 		ungot = EOF;
4047c478bd9Sstevel@tonic-gate 	}
4057c478bd9Sstevel@tonic-gate 	return nitems==0 ? EOF : nitems;
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate static int
gettoken()4097c478bd9Sstevel@tonic-gate gettoken()
4107c478bd9Sstevel@tonic-gate {
4117c478bd9Sstevel@tonic-gate 	char	c;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	if (*fmtptr == 0)
4147c478bd9Sstevel@tonic-gate 		return 0;	/* return 0 for end of string */
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	c = *fmtptr++;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	if (pflag) {
4197c478bd9Sstevel@tonic-gate 		for(lexp=lexlist; lexp->name != 0; lexp++) {
4207c478bd9Sstevel@tonic-gate 			if (c == lexp->name) {
4217c478bd9Sstevel@tonic-gate 				if (lexp->type == NUMBER) {
4227c478bd9Sstevel@tonic-gate 					width = (int) strtol(fmtptr-1, (char **)0, BASE10);
4237c478bd9Sstevel@tonic-gate 					while (*fmtptr >= '0' && *fmtptr <= '9')
4247c478bd9Sstevel@tonic-gate 						fmtptr++;
4257c478bd9Sstevel@tonic-gate 				} else if (c == 'c') {
4267c478bd9Sstevel@tonic-gate 					/* No width specified for %c, default
4277c478bd9Sstevel@tonic-gate 					 * is one.
4287c478bd9Sstevel@tonic-gate 					 */
4297c478bd9Sstevel@tonic-gate 					width = 1;
4307c478bd9Sstevel@tonic-gate 				}
4317c478bd9Sstevel@tonic-gate 				return lexp->type;
4327c478bd9Sstevel@tonic-gate 			}
4337c478bd9Sstevel@tonic-gate 		}
4347c478bd9Sstevel@tonic-gate 		return -1;
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	if (c == '%') {
4387c478bd9Sstevel@tonic-gate 		pflag = 1;
4397c478bd9Sstevel@tonic-gate 		from = 'P';
4407c478bd9Sstevel@tonic-gate 		return gettoken();
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 	return -1;
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate static void
whitespace()4467c478bd9Sstevel@tonic-gate whitespace()
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate 	register int	c;
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	do {
4517c478bd9Sstevel@tonic-gate 		c = getin();
4527c478bd9Sstevel@tonic-gate 	} while (isspace(c));
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	unget(c);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate static int
scan(int ch,const char * str,const char * estr)4587c478bd9Sstevel@tonic-gate scan(int ch, const char *str, const char *estr)
4597c478bd9Sstevel@tonic-gate {
4607c478bd9Sstevel@tonic-gate 	for (; str < estr; ++str)
4617c478bd9Sstevel@tonic-gate 		if (*str == ch)
4627c478bd9Sstevel@tonic-gate 			return 1;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	return 0;
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate static int
match(const char * str,char * outstr)4687c478bd9Sstevel@tonic-gate match(const char *str, char *outstr)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate 	int	complement;
4717c478bd9Sstevel@tonic-gate 	int	i;
4727c478bd9Sstevel@tonic-gate 	char	start, end;
4737c478bd9Sstevel@tonic-gate 	int	c;
4747c478bd9Sstevel@tonic-gate 	const	char	*bscan, *escan;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	if (*str == '^') {
4777c478bd9Sstevel@tonic-gate 		complement = 1;
4787c478bd9Sstevel@tonic-gate 		str++;
4797c478bd9Sstevel@tonic-gate 	} else
4807c478bd9Sstevel@tonic-gate 		complement = 0;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	start = *str++;
4837c478bd9Sstevel@tonic-gate 	end = 0;
4847c478bd9Sstevel@tonic-gate 	if (*str == '-') {
4857c478bd9Sstevel@tonic-gate 		if (str[2] == ']')
4867c478bd9Sstevel@tonic-gate 			end = str[1];
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 	if (start > end) {
4897c478bd9Sstevel@tonic-gate 		bscan = str - 1;
4907c478bd9Sstevel@tonic-gate 		while (*str++ != ']')
4917c478bd9Sstevel@tonic-gate 			;
4927c478bd9Sstevel@tonic-gate 		escan = str - 1;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 		for (i=0; i<width; i++) {
4957c478bd9Sstevel@tonic-gate 			if ((c = getin()) == EOF)
4967c478bd9Sstevel@tonic-gate 				return 0;
4977c478bd9Sstevel@tonic-gate 			if (!scan(c, bscan, escan) ^ complement)
4987c478bd9Sstevel@tonic-gate 				break;
4997c478bd9Sstevel@tonic-gate 			if (outstr != NULL)
5007c478bd9Sstevel@tonic-gate 				*outstr++ = c;
5017c478bd9Sstevel@tonic-gate 		}
5027c478bd9Sstevel@tonic-gate 	} else {
5037c478bd9Sstevel@tonic-gate 		for (i=0; i<width; i++) {
5047c478bd9Sstevel@tonic-gate 			c = getin();
5057c478bd9Sstevel@tonic-gate 			if (complement) {
5067c478bd9Sstevel@tonic-gate 				if (c >= start && c <= end)
5077c478bd9Sstevel@tonic-gate 					break;
5087c478bd9Sstevel@tonic-gate 				else if (outstr != NULL)
5097c478bd9Sstevel@tonic-gate 					*outstr++ = c;
5107c478bd9Sstevel@tonic-gate 			} else {
5117c478bd9Sstevel@tonic-gate 				if (c < start || c > end)
5127c478bd9Sstevel@tonic-gate 					break;
5137c478bd9Sstevel@tonic-gate 				else if (outstr != NULL)
5147c478bd9Sstevel@tonic-gate 					*outstr++ = c;
5157c478bd9Sstevel@tonic-gate 			}
5167c478bd9Sstevel@tonic-gate 		}
5177c478bd9Sstevel@tonic-gate 	}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	if (i < width)
5207c478bd9Sstevel@tonic-gate 		unget(c);
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (outstr != NULL)
5237c478bd9Sstevel@tonic-gate 		*outstr = '\0';
5247c478bd9Sstevel@tonic-gate 	return (i > 1);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate /*
5287c478bd9Sstevel@tonic-gate  * Get a number from the input stream.
5297c478bd9Sstevel@tonic-gate  * The base, if zero, will be determined by the nature of the number.
5307c478bd9Sstevel@tonic-gate  * A leading 0x means hexadecimal, a leading 0 for octal, otherwise decimal.
531*1da57d55SToomas Soome  *
5327c478bd9Sstevel@tonic-gate  * if the width is 0 then the max input string length of number is used.
5337c478bd9Sstevel@tonic-gate  *
5347c478bd9Sstevel@tonic-gate  * The sign tell us that a signed number is expected (rather than the
5357c478bd9Sstevel@tonic-gate  *	'u' conversion type which is unsigned).
5367c478bd9Sstevel@tonic-gate  */
5377c478bd9Sstevel@tonic-gate static long unsigned
getnum(int base,int width,int sign)5387c478bd9Sstevel@tonic-gate getnum(int base, int width, int sign)
5397c478bd9Sstevel@tonic-gate {
5407c478bd9Sstevel@tonic-gate 	char	*s;
5417c478bd9Sstevel@tonic-gate 	char	cbuf[CBUFSIZ];			/* char buffer for number */
5427c478bd9Sstevel@tonic-gate 	int	w;
5437c478bd9Sstevel@tonic-gate 	register int	c;
5447c478bd9Sstevel@tonic-gate 	int	neg;
5457c478bd9Sstevel@tonic-gate 	long	ret;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	gfail = 0;
5487c478bd9Sstevel@tonic-gate 	whitespace();
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (width == 0)
5517c478bd9Sstevel@tonic-gate 		width = sizeof cbuf;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	neg = 0;
5547c478bd9Sstevel@tonic-gate 	if (sign) {
5557c478bd9Sstevel@tonic-gate 		c = getin();
5567c478bd9Sstevel@tonic-gate 		if (c == '+' || c == '-')
5577c478bd9Sstevel@tonic-gate 			neg = c=='-' ? 1 : 0;
5587c478bd9Sstevel@tonic-gate 		else
5597c478bd9Sstevel@tonic-gate 			unget(c);
5607c478bd9Sstevel@tonic-gate 	}
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	if (base == 0) {
5637c478bd9Sstevel@tonic-gate 		base = 10;
5647c478bd9Sstevel@tonic-gate 		c = getin();
5657c478bd9Sstevel@tonic-gate 		if (c == '0') {
5667c478bd9Sstevel@tonic-gate 			base = 8;
5677c478bd9Sstevel@tonic-gate 			c = getin();
5687c478bd9Sstevel@tonic-gate 			if (c == 'X' || c == 'x')
5697c478bd9Sstevel@tonic-gate 				base = 16;
5707c478bd9Sstevel@tonic-gate 			else
5717c478bd9Sstevel@tonic-gate 				unget(c);
5727c478bd9Sstevel@tonic-gate 		} else
5737c478bd9Sstevel@tonic-gate 			unget(c);
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 	if (base == 10) {
5767c478bd9Sstevel@tonic-gate 		w = 0;
5777c478bd9Sstevel@tonic-gate 		s = cbuf;
5787c478bd9Sstevel@tonic-gate 		while (w < width && w < sizeof cbuf) {
5797c478bd9Sstevel@tonic-gate 			c = getin();
5807c478bd9Sstevel@tonic-gate 			switch (c) {
581*1da57d55SToomas Soome 
5827c478bd9Sstevel@tonic-gate 			case '0':
5837c478bd9Sstevel@tonic-gate 			case '1':
5847c478bd9Sstevel@tonic-gate 			case '2':
5857c478bd9Sstevel@tonic-gate 			case '3':
5867c478bd9Sstevel@tonic-gate 			case '4':
5877c478bd9Sstevel@tonic-gate 			case '5':
5887c478bd9Sstevel@tonic-gate 			case '6':
5897c478bd9Sstevel@tonic-gate 			case '7':
5907c478bd9Sstevel@tonic-gate 			case '8':
5917c478bd9Sstevel@tonic-gate 			case '9':
5927c478bd9Sstevel@tonic-gate 				*s++ = c;
5937c478bd9Sstevel@tonic-gate 				w++;
5947c478bd9Sstevel@tonic-gate 				continue;
5957c478bd9Sstevel@tonic-gate 			default:
5967c478bd9Sstevel@tonic-gate 				unget(c);
5977c478bd9Sstevel@tonic-gate 				w = width;	/* force end of loop */
5987c478bd9Sstevel@tonic-gate 				break;
5997c478bd9Sstevel@tonic-gate 			}
6007c478bd9Sstevel@tonic-gate 		}
6017c478bd9Sstevel@tonic-gate 		*s = '\0';
6027c478bd9Sstevel@tonic-gate 		ret = strtol(cbuf, (char **)0, 10);
6037c478bd9Sstevel@tonic-gate 		goto retn;
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 	if (base == 8) {
6067c478bd9Sstevel@tonic-gate 		w = 0;
6077c478bd9Sstevel@tonic-gate 		s = cbuf;
6087c478bd9Sstevel@tonic-gate 		while (w < width && w < sizeof cbuf) {
6097c478bd9Sstevel@tonic-gate 			c = getin();
6107c478bd9Sstevel@tonic-gate 			switch (c) {
611*1da57d55SToomas Soome 
6127c478bd9Sstevel@tonic-gate 			case '0':
6137c478bd9Sstevel@tonic-gate 			case '1':
6147c478bd9Sstevel@tonic-gate 			case '2':
6157c478bd9Sstevel@tonic-gate 			case '3':
6167c478bd9Sstevel@tonic-gate 			case '4':
6177c478bd9Sstevel@tonic-gate 			case '5':
6187c478bd9Sstevel@tonic-gate 			case '6':
6197c478bd9Sstevel@tonic-gate 			case '7':
6207c478bd9Sstevel@tonic-gate 				*s++ = c;
6217c478bd9Sstevel@tonic-gate 				w++;
6227c478bd9Sstevel@tonic-gate 				continue;
6237c478bd9Sstevel@tonic-gate 			default:
6247c478bd9Sstevel@tonic-gate 				unget(c);
6257c478bd9Sstevel@tonic-gate 				w = width;	/* force end of loop */
6267c478bd9Sstevel@tonic-gate 				break;
6277c478bd9Sstevel@tonic-gate 			}
6287c478bd9Sstevel@tonic-gate 		}
6297c478bd9Sstevel@tonic-gate 		*s = '\0';
6307c478bd9Sstevel@tonic-gate 		ret = strtol(cbuf, (char **)0, 8);
6317c478bd9Sstevel@tonic-gate 		goto retn;
6327c478bd9Sstevel@tonic-gate 	}
6337c478bd9Sstevel@tonic-gate 	if (base == 16) {
6347c478bd9Sstevel@tonic-gate 		w = 0;
6357c478bd9Sstevel@tonic-gate 		s = cbuf;
6367c478bd9Sstevel@tonic-gate 		while (w < width && w < sizeof cbuf) {
6377c478bd9Sstevel@tonic-gate 			c = getin();
6387c478bd9Sstevel@tonic-gate 			c = toupper(c);
6397c478bd9Sstevel@tonic-gate 			switch (c) {
640*1da57d55SToomas Soome 
6417c478bd9Sstevel@tonic-gate 			case '0':
6427c478bd9Sstevel@tonic-gate 			case '1':
6437c478bd9Sstevel@tonic-gate 			case '2':
6447c478bd9Sstevel@tonic-gate 			case '3':
6457c478bd9Sstevel@tonic-gate 			case '4':
6467c478bd9Sstevel@tonic-gate 			case '5':
6477c478bd9Sstevel@tonic-gate 			case '6':
6487c478bd9Sstevel@tonic-gate 			case '7':
6497c478bd9Sstevel@tonic-gate 			case '8':
6507c478bd9Sstevel@tonic-gate 			case '9':
6517c478bd9Sstevel@tonic-gate 			case 'A':
6527c478bd9Sstevel@tonic-gate 			case 'B':
6537c478bd9Sstevel@tonic-gate 			case 'C':
6547c478bd9Sstevel@tonic-gate 			case 'D':
6557c478bd9Sstevel@tonic-gate 			case 'E':
6567c478bd9Sstevel@tonic-gate 			case 'F':
6577c478bd9Sstevel@tonic-gate 				*s++ = c;
6587c478bd9Sstevel@tonic-gate 				w++;
6597c478bd9Sstevel@tonic-gate 				continue;
6607c478bd9Sstevel@tonic-gate 			default:
6617c478bd9Sstevel@tonic-gate 				unget(c);
6627c478bd9Sstevel@tonic-gate 				w = width;	/* force end of loop */
6637c478bd9Sstevel@tonic-gate 				break;
6647c478bd9Sstevel@tonic-gate 			}
6657c478bd9Sstevel@tonic-gate 		}
6667c478bd9Sstevel@tonic-gate 		*s = '\0';
6677c478bd9Sstevel@tonic-gate 		ret = strtol(cbuf, (char **)0, 16);
6687c478bd9Sstevel@tonic-gate 		goto retn;
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate /*
6727c478bd9Sstevel@tonic-gate  * if we get this far then a bad base was passed.
6737c478bd9Sstevel@tonic-gate  */
6747c478bd9Sstevel@tonic-gate 	gfail = -1;
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate retn:
6777c478bd9Sstevel@tonic-gate 	if (*cbuf == '\0')	/* No number at all?? */
6787c478bd9Sstevel@tonic-gate 		gfail = -1;
6797c478bd9Sstevel@tonic-gate 	if (neg)
6807c478bd9Sstevel@tonic-gate 		ret = -ret;
6817c478bd9Sstevel@tonic-gate 	return ret;
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate #ifdef	__FLOAT__
6857c478bd9Sstevel@tonic-gate static double
lstrtod()6867c478bd9Sstevel@tonic-gate lstrtod()
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate 	int	slen;
6897c478bd9Sstevel@tonic-gate 	int	neg, eneg;
6907c478bd9Sstevel@tonic-gate 	char	cbuf[CBUFSIZ];
6917c478bd9Sstevel@tonic-gate 	register int	c;
6927c478bd9Sstevel@tonic-gate 	register char	*sp, *s1, *s2, *s3;
6937c478bd9Sstevel@tonic-gate 	double	total, exp, tens;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	neg = eneg = 1;
6967c478bd9Sstevel@tonic-gate 	gfail = 0;
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	whitespace();
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	c = getin();
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	if (c == '-' || c == '+')
7037c478bd9Sstevel@tonic-gate 		if (c == '-') {
7047c478bd9Sstevel@tonic-gate 			neg = -1;
7057c478bd9Sstevel@tonic-gate 			c = getin();
7067c478bd9Sstevel@tonic-gate 		}
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	sp = s1 = cbuf;
7097c478bd9Sstevel@tonic-gate 	while (c >= '0' && c <= '9') {
7107c478bd9Sstevel@tonic-gate 		*sp++ = c;
7117c478bd9Sstevel@tonic-gate 		c = getin();
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	s2 = sp;
7157c478bd9Sstevel@tonic-gate 	if (c == '.') {
7167c478bd9Sstevel@tonic-gate 		c = getin();
7177c478bd9Sstevel@tonic-gate 		while (c >= '0' && c <= '9') {
7187c478bd9Sstevel@tonic-gate 			*sp++ = c;
7197c478bd9Sstevel@tonic-gate 			c = getin();
7207c478bd9Sstevel@tonic-gate 		}
7217c478bd9Sstevel@tonic-gate 	}
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 	s3 = sp;
7247c478bd9Sstevel@tonic-gate 	if (c == 'e' || c == 'E') {
7257c478bd9Sstevel@tonic-gate 		c = getin();
7267c478bd9Sstevel@tonic-gate 		if (c == '-' || c == '+')
7277c478bd9Sstevel@tonic-gate 			if (c == '-') {
7287c478bd9Sstevel@tonic-gate 				eneg = -1;
7297c478bd9Sstevel@tonic-gate 				c = getin();
7307c478bd9Sstevel@tonic-gate 			}
7317c478bd9Sstevel@tonic-gate 		while (c >= '0' && c <= '9') {
7327c478bd9Sstevel@tonic-gate 			*sp++ = c;
7337c478bd9Sstevel@tonic-gate 			c = getin();
7347c478bd9Sstevel@tonic-gate 		}
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate 	*sp = '\0';
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	if (s1 == s2 && s2 == s3) {
7397c478bd9Sstevel@tonic-gate 		gfail = -1;
7407c478bd9Sstevel@tonic-gate 		return 0.0;
7417c478bd9Sstevel@tonic-gate 	}
7427c478bd9Sstevel@tonic-gate 	unget(c);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	/*
7457c478bd9Sstevel@tonic-gate 	 * convert the three strings (integer, fraction, and exponent)
7467c478bd9Sstevel@tonic-gate 	 * into a floating point number.
7477c478bd9Sstevel@tonic-gate 	 */
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	total = 0.0;
7507c478bd9Sstevel@tonic-gate 	tens = 1.0;
7517c478bd9Sstevel@tonic-gate 	for (sp=s2-1; sp >= s1; sp--) {
7527c478bd9Sstevel@tonic-gate 		total += (*sp -'0') * tens;
7537c478bd9Sstevel@tonic-gate 		tens *= 10.0;
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	tens = .1;
7577c478bd9Sstevel@tonic-gate 	for (sp=s2; sp < s3; sp++) {
7587c478bd9Sstevel@tonic-gate 		total += (*sp - '0') * tens;
7597c478bd9Sstevel@tonic-gate 		tens /= 10.0;
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 	total *= (double)neg;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	exp = 0.0;
7647c478bd9Sstevel@tonic-gate 	tens = 1.0;
7657c478bd9Sstevel@tonic-gate 	if ((slen = strlen(s3)) > 0) {
7667c478bd9Sstevel@tonic-gate 		sp = s3 + slen - 1;
7677c478bd9Sstevel@tonic-gate 		for ( ; sp >= s3; sp--) {
7687c478bd9Sstevel@tonic-gate 			exp += (*sp - '0') * tens;
7697c478bd9Sstevel@tonic-gate 			tens *= 10.0;
7707c478bd9Sstevel@tonic-gate 		}
7717c478bd9Sstevel@tonic-gate 	}
7727c478bd9Sstevel@tonic-gate 	*sp = '\0';
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	exp *= (double)eneg;
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	total *= pow(10.0, exp);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	return total;
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate #endif	/* __FLOAT__ */
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate static	int
getin()7837c478bd9Sstevel@tonic-gate getin()
7847c478bd9Sstevel@tonic-gate {
7857c478bd9Sstevel@tonic-gate 	int	c;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	if (ungot != EOF) {
7887c478bd9Sstevel@tonic-gate 		c = ungot;
7897c478bd9Sstevel@tonic-gate 		ungot = EOF;
7907c478bd9Sstevel@tonic-gate 	} else
7917c478bd9Sstevel@tonic-gate 		c = getc(fpin);
7927c478bd9Sstevel@tonic-gate 	charcnt++;
7937c478bd9Sstevel@tonic-gate 	return c;
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate static void
unget(int c)7977c478bd9Sstevel@tonic-gate unget(int c)
7987c478bd9Sstevel@tonic-gate {
7997c478bd9Sstevel@tonic-gate 	/* Dont' use ungetc because it doesn't work with m_fsopen */
8007c478bd9Sstevel@tonic-gate 	ungot = c;
8017c478bd9Sstevel@tonic-gate 	charcnt--;
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate 
804