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) 1988-1995, 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 /*	Copyright (c) 1984 AT&T	*/
30*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate /*LINTLIBRARY*/
34*0Sstevel@tonic-gate #include <stdio.h>
35*0Sstevel@tonic-gate #include <ctype.h>
36*0Sstevel@tonic-gate #include <varargs.h>
37*0Sstevel@tonic-gate #include <values.h>
38*0Sstevel@tonic-gate #include <floatingpoint.h>
39*0Sstevel@tonic-gate #include <errno.h>
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #define NCHARS	(1 << BITSPERBYTE)
42*0Sstevel@tonic-gate #define locgetc()	(chcount+=1,getc(iop))
43*0Sstevel@tonic-gate #define locungetc(x)	(chcount-=1,ungetc(x,iop))
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate extern char *memset();
46*0Sstevel@tonic-gate static int chcount,flag_eof;
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate #ifdef S5EMUL
49*0Sstevel@tonic-gate #define	isws(c)		isspace(c)
50*0Sstevel@tonic-gate #else
51*0Sstevel@tonic-gate /*
52*0Sstevel@tonic-gate  * _sptab[c+1] is 1 iff 'c' is a white space character according to the
53*0Sstevel@tonic-gate  * 4.2BSD "scanf" definition - namely, SP, TAB, and NL are the only
54*0Sstevel@tonic-gate  * whitespace characters.
55*0Sstevel@tonic-gate  */
56*0Sstevel@tonic-gate static char _sptab[1+256] = {
57*0Sstevel@tonic-gate 	0,				/* EOF - not a whitespace char */
58*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
59*0Sstevel@tonic-gate 	0,1,1,0,0,0,0,0,
60*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
61*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
62*0Sstevel@tonic-gate 	1,0,0,0,0,0,0,0,
63*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
64*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
65*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
66*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
67*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
68*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
69*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
70*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
71*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
72*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
73*0Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
74*0Sstevel@tonic-gate };
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate #define	isws(c)		((_sptab + 1)[c] != 0)
77*0Sstevel@tonic-gate #endif
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate int
80*0Sstevel@tonic-gate _doscan(iop, fmt, va_alist)
81*0Sstevel@tonic-gate register FILE *iop;
82*0Sstevel@tonic-gate register unsigned char *fmt;
83*0Sstevel@tonic-gate va_list va_alist;
84*0Sstevel@tonic-gate {
85*0Sstevel@tonic-gate 	extern unsigned char *setup();
86*0Sstevel@tonic-gate 	char tab[NCHARS];
87*0Sstevel@tonic-gate 	register int ch;
88*0Sstevel@tonic-gate 	int nmatch = 0, len, inchar, stow, size;
89*0Sstevel@tonic-gate 	chcount=0; flag_eof=0;
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 	/*******************************************************
92*0Sstevel@tonic-gate 	 * Main loop: reads format to determine a pattern,
93*0Sstevel@tonic-gate 	 *		and then goes to read input stream
94*0Sstevel@tonic-gate 	 *		in attempt to match the pattern.
95*0Sstevel@tonic-gate 	 *******************************************************/
96*0Sstevel@tonic-gate 	for ( ; ; )
97*0Sstevel@tonic-gate 	{
98*0Sstevel@tonic-gate 		if ( (ch = *fmt++) == '\0')
99*0Sstevel@tonic-gate 			return(nmatch); /* end of format */
100*0Sstevel@tonic-gate 		if (isws(ch))
101*0Sstevel@tonic-gate 		{
102*0Sstevel@tonic-gate 		  	if (!flag_eof)
103*0Sstevel@tonic-gate 			{
104*0Sstevel@tonic-gate 			   while (isws(inchar = locgetc()))
105*0Sstevel@tonic-gate 				;
106*0Sstevel@tonic-gate 			   if (inchar == EOF) {
107*0Sstevel@tonic-gate 				chcount--;
108*0Sstevel@tonic-gate 				flag_eof = 1;
109*0Sstevel@tonic-gate 			   }
110*0Sstevel@tonic-gate 			   else if (locungetc(inchar) == EOF)
111*0Sstevel@tonic-gate 				flag_eof = 1;
112*0Sstevel@tonic-gate 			}
113*0Sstevel@tonic-gate 		  continue;
114*0Sstevel@tonic-gate 		}
115*0Sstevel@tonic-gate 		if (ch != '%' || (ch = *fmt++) == '%')
116*0Sstevel@tonic-gate                 {
117*0Sstevel@tonic-gate 			if ( (inchar = locgetc()) == ch )
118*0Sstevel@tonic-gate 				continue;
119*0Sstevel@tonic-gate 			if (inchar != EOF) {
120*0Sstevel@tonic-gate 				if (locungetc(inchar) != EOF)
121*0Sstevel@tonic-gate 					return(nmatch); /* failed to match input */
122*0Sstevel@tonic-gate 			} else {
123*0Sstevel@tonic-gate 				chcount--;
124*0Sstevel@tonic-gate 			}
125*0Sstevel@tonic-gate 			break;
126*0Sstevel@tonic-gate 		}
127*0Sstevel@tonic-gate 		if (ch == '*')
128*0Sstevel@tonic-gate 		{
129*0Sstevel@tonic-gate 			stow = 0;
130*0Sstevel@tonic-gate 			ch = *fmt++;
131*0Sstevel@tonic-gate 		}
132*0Sstevel@tonic-gate 		else
133*0Sstevel@tonic-gate 			stow = 1;
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 		for (len = 0; isdigit(ch); ch = *fmt++)
136*0Sstevel@tonic-gate 			len = len * 10 + ch - '0';
137*0Sstevel@tonic-gate 		if (len == 0)
138*0Sstevel@tonic-gate 			len = MAXINT;
139*0Sstevel@tonic-gate 		if ( (size = ch) == 'l' || (size == 'h') || (size == 'L') )
140*0Sstevel@tonic-gate 			ch = *fmt++;
141*0Sstevel@tonic-gate 		if (ch == '\0' ||
142*0Sstevel@tonic-gate 		    ch == '[' && (fmt = setup(fmt, tab)) == NULL)
143*0Sstevel@tonic-gate 			return(EOF); /* unexpected end of format */
144*0Sstevel@tonic-gate 		if (isupper(ch))  /* no longer documented */
145*0Sstevel@tonic-gate 		{
146*0Sstevel@tonic-gate 			/*
147*0Sstevel@tonic-gate 			 * The rationale behind excluding the size
148*0Sstevel@tonic-gate 			 * of 'L' is that the 'L' size specifier was
149*0Sstevel@tonic-gate 			 * introduced in ANSI/ISO-C.  If the user
150*0Sstevel@tonic-gate 			 * specifies a format of %LG, it can mean
151*0Sstevel@tonic-gate 			 * nothing other than "long double", be the
152*0Sstevel@tonic-gate 			 * code ANSI or not.  Mapping it to "double"
153*0Sstevel@tonic-gate 			 * makes no sense.
154*0Sstevel@tonic-gate 			 */
155*0Sstevel@tonic-gate 			if (size != 'L')
156*0Sstevel@tonic-gate 				size = 'l';
157*0Sstevel@tonic-gate #ifdef S5EMUL
158*0Sstevel@tonic-gate 			ch = _tolower(ch);
159*0Sstevel@tonic-gate #else
160*0Sstevel@tonic-gate 			ch = tolower(ch);
161*0Sstevel@tonic-gate #endif
162*0Sstevel@tonic-gate 		}
163*0Sstevel@tonic-gate 		switch(ch)
164*0Sstevel@tonic-gate 		{
165*0Sstevel@tonic-gate 		 case 'c':
166*0Sstevel@tonic-gate 		 case 's':
167*0Sstevel@tonic-gate 		 case '[':
168*0Sstevel@tonic-gate 			  if ((size = string(stow,ch,len,tab,iop,&va_alist)) < 0)
169*0Sstevel@tonic-gate 				goto out;	/* EOF seen, nothing converted */
170*0Sstevel@tonic-gate 			  break;
171*0Sstevel@tonic-gate                  case 'n':
172*0Sstevel@tonic-gate 			  if (stow == 0)
173*0Sstevel@tonic-gate 				continue;
174*0Sstevel@tonic-gate 			  if (size == 'h')
175*0Sstevel@tonic-gate 				*va_arg(va_alist, short *) = (short) chcount;
176*0Sstevel@tonic-gate 		          else if (size == 'l')
177*0Sstevel@tonic-gate 				*va_arg(va_alist, long *) = (long) chcount;
178*0Sstevel@tonic-gate 			  else
179*0Sstevel@tonic-gate 			  	*va_arg(va_alist, int *) = (int) chcount;
180*0Sstevel@tonic-gate 			  continue;
181*0Sstevel@tonic-gate                  default:
182*0Sstevel@tonic-gate 			 if ((size = number(stow, ch, len, size, iop, &va_alist)) < 0)
183*0Sstevel@tonic-gate 				goto out;	/* EOF seen, nothing converted */
184*0Sstevel@tonic-gate 			 break;
185*0Sstevel@tonic-gate                  }
186*0Sstevel@tonic-gate 		   if (size)
187*0Sstevel@tonic-gate 			nmatch += stow;
188*0Sstevel@tonic-gate 		   else
189*0Sstevel@tonic-gate 			return((flag_eof && !nmatch) ? EOF : nmatch);
190*0Sstevel@tonic-gate 		continue;
191*0Sstevel@tonic-gate 	}
192*0Sstevel@tonic-gate out:
193*0Sstevel@tonic-gate 	return (nmatch != 0 ? nmatch : EOF); /* end of input */
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate /***************************************************************
197*0Sstevel@tonic-gate  * Functions to read the input stream in an attempt to match incoming
198*0Sstevel@tonic-gate  * data to the current pattern from the main loop of _doscan().
199*0Sstevel@tonic-gate  ***************************************************************/
200*0Sstevel@tonic-gate static int
201*0Sstevel@tonic-gate number(stow, type, len, size, iop, listp)
202*0Sstevel@tonic-gate int stow, type, len, size;
203*0Sstevel@tonic-gate register FILE *iop;
204*0Sstevel@tonic-gate va_list *listp;
205*0Sstevel@tonic-gate {
206*0Sstevel@tonic-gate 	char numbuf[64], inchar, lookahead;
207*0Sstevel@tonic-gate 	register char *np = numbuf;
208*0Sstevel@tonic-gate 	register int c, base;
209*0Sstevel@tonic-gate 	int digitseen = 0, floater = 0, negflg = 0;
210*0Sstevel@tonic-gate 	long lcval = 0;
211*0Sstevel@tonic-gate 	switch(type)
212*0Sstevel@tonic-gate 	{
213*0Sstevel@tonic-gate 	case 'e':
214*0Sstevel@tonic-gate 	case 'f':
215*0Sstevel@tonic-gate 	case 'g':
216*0Sstevel@tonic-gate 		floater++;
217*0Sstevel@tonic-gate 	case 'd':
218*0Sstevel@tonic-gate 	case 'u':
219*0Sstevel@tonic-gate 	case 'i':
220*0Sstevel@tonic-gate 		base = 10;
221*0Sstevel@tonic-gate 		break;
222*0Sstevel@tonic-gate 	case 'o':
223*0Sstevel@tonic-gate 		base = 8;
224*0Sstevel@tonic-gate 		break;
225*0Sstevel@tonic-gate 	case 'x':
226*0Sstevel@tonic-gate 		base = 16;
227*0Sstevel@tonic-gate 		break;
228*0Sstevel@tonic-gate 	default:
229*0Sstevel@tonic-gate 		return(0); /* unrecognized conversion character */
230*0Sstevel@tonic-gate 	}
231*0Sstevel@tonic-gate 	if (!flag_eof)
232*0Sstevel@tonic-gate 	{
233*0Sstevel@tonic-gate 		while (isws(c = locgetc()))
234*0Sstevel@tonic-gate 			;
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 	else
237*0Sstevel@tonic-gate 		c = locgetc();
238*0Sstevel@tonic-gate 	if (c == EOF) {
239*0Sstevel@tonic-gate 		chcount--;
240*0Sstevel@tonic-gate 		return(-1);	/* EOF before match */
241*0Sstevel@tonic-gate 	}
242*0Sstevel@tonic-gate         if (floater != 0) {     /* Handle floating point with
243*0Sstevel@tonic-gate                                  * file_to_decimal. */
244*0Sstevel@tonic-gate                 decimal_mode    dm;
245*0Sstevel@tonic-gate                 decimal_record  dr;
246*0Sstevel@tonic-gate                 fp_exception_field_type efs;
247*0Sstevel@tonic-gate                 enum decimal_string_form form;
248*0Sstevel@tonic-gate                 char           *echar;
249*0Sstevel@tonic-gate                 int             nread, ic;
250*0Sstevel@tonic-gate                 char            buffer[1024];
251*0Sstevel@tonic-gate                 char           *nb = buffer;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate                 locungetc(c);
254*0Sstevel@tonic-gate 		if (len > 1024)
255*0Sstevel@tonic-gate 			len = 1024;
256*0Sstevel@tonic-gate                 file_to_decimal(&nb, len, 0, &dr, &form, &echar, iop, &nread);
257*0Sstevel@tonic-gate                 if (stow && (form != invalid_form)) {
258*0Sstevel@tonic-gate                         dm.rd = fp_direction;
259*0Sstevel@tonic-gate                         if (size == 'l') {      /* double */
260*0Sstevel@tonic-gate                                 decimal_to_double((double *) va_arg(*listp, double *), &dm, &dr, &efs);
261*0Sstevel@tonic-gate                         } else if (size == 'L') {      /* quad */
262*0Sstevel@tonic-gate                                 decimal_to_quadruple((quadruple *)va_arg(*listp, double *), &dm, &dr, &efs);
263*0Sstevel@tonic-gate                         } else {/* single */
264*0Sstevel@tonic-gate                                 decimal_to_single((float *) va_arg(*listp, float *), &dm, &dr, &efs);
265*0Sstevel@tonic-gate                         }
266*0Sstevel@tonic-gate 			if ((efs & (1 << fp_overflow)) != 0) {
267*0Sstevel@tonic-gate 				errno = ERANGE;
268*0Sstevel@tonic-gate 			}
269*0Sstevel@tonic-gate 			if ((efs & (1 << fp_underflow)) != 0) {
270*0Sstevel@tonic-gate 				errno = ERANGE;
271*0Sstevel@tonic-gate                         }
272*0Sstevel@tonic-gate                 }
273*0Sstevel@tonic-gate 		chcount += nread;	/* Count characters read. */
274*0Sstevel@tonic-gate                 c = *nb;        /* Get first unused character. */
275*0Sstevel@tonic-gate                 ic = c;
276*0Sstevel@tonic-gate                 if (c == NULL) {
277*0Sstevel@tonic-gate                         ic = locgetc();
278*0Sstevel@tonic-gate                         c = ic;
279*0Sstevel@tonic-gate                         /*
280*0Sstevel@tonic-gate                          * If null, first unused may have been put back
281*0Sstevel@tonic-gate                          * already.
282*0Sstevel@tonic-gate                          */
283*0Sstevel@tonic-gate                 }
284*0Sstevel@tonic-gate                 if (ic == EOF) {
285*0Sstevel@tonic-gate                         chcount--;
286*0Sstevel@tonic-gate                         flag_eof = 1;
287*0Sstevel@tonic-gate                 } else if (locungetc(c) == EOF)
288*0Sstevel@tonic-gate                         flag_eof = 1;
289*0Sstevel@tonic-gate                 return ((form == invalid_form) ? 0 : 1);        /* successful match if
290*0Sstevel@tonic-gate                                                                  * non-zero */
291*0Sstevel@tonic-gate         }
292*0Sstevel@tonic-gate 	switch(c) {
293*0Sstevel@tonic-gate 	case '-':
294*0Sstevel@tonic-gate 		negflg++;
295*0Sstevel@tonic-gate 		if (type == 'u')
296*0Sstevel@tonic-gate 			break;
297*0Sstevel@tonic-gate 	case '+': /* fall-through */
298*0Sstevel@tonic-gate 		if (--len <= 0)
299*0Sstevel@tonic-gate 			break;
300*0Sstevel@tonic-gate 		if ( (c = locgetc()) != '0')
301*0Sstevel@tonic-gate 			break;
302*0Sstevel@tonic-gate         case '0':
303*0Sstevel@tonic-gate                 if ( (type != 'i') || (len <= 1) )
304*0Sstevel@tonic-gate 		   break;
305*0Sstevel@tonic-gate 	        if ( ((inchar = locgetc()) == 'x') || (inchar == 'X') )
306*0Sstevel@tonic-gate 	        {
307*0Sstevel@tonic-gate 		      /* If not using sscanf and *
308*0Sstevel@tonic-gate 		       * at the buffer's end     *
309*0Sstevel@tonic-gate 		       * then LOOK ahead         */
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate                    if ( (iop->_flag & _IOSTRG) || (iop->_cnt != 0) )
312*0Sstevel@tonic-gate 		      lookahead = locgetc();
313*0Sstevel@tonic-gate 		   else
314*0Sstevel@tonic-gate 		   {
315*0Sstevel@tonic-gate 		      if ( read(fileno(iop),np,1) == 1)
316*0Sstevel@tonic-gate 		         lookahead = *np;
317*0Sstevel@tonic-gate                       else
318*0Sstevel@tonic-gate 		         lookahead = EOF;
319*0Sstevel@tonic-gate                       chcount += 1;
320*0Sstevel@tonic-gate                    }
321*0Sstevel@tonic-gate 		   if ( isxdigit(lookahead) )
322*0Sstevel@tonic-gate 		   {
323*0Sstevel@tonic-gate 		       base =16;
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 		       if ( len <= 2)
326*0Sstevel@tonic-gate 		       {
327*0Sstevel@tonic-gate 			  locungetc(lookahead);
328*0Sstevel@tonic-gate 			  len -= 1;            /* Take into account the 'x'*/
329*0Sstevel@tonic-gate                        }
330*0Sstevel@tonic-gate 		       else
331*0Sstevel@tonic-gate 		       {
332*0Sstevel@tonic-gate 		          c = lookahead;
333*0Sstevel@tonic-gate 			  len -= 2;           /* Take into account '0x'*/
334*0Sstevel@tonic-gate 		       }
335*0Sstevel@tonic-gate                    }
336*0Sstevel@tonic-gate 	           else
337*0Sstevel@tonic-gate 	           {
338*0Sstevel@tonic-gate 	               locungetc(lookahead);
339*0Sstevel@tonic-gate 	               locungetc(inchar);
340*0Sstevel@tonic-gate                    }
341*0Sstevel@tonic-gate 		}
342*0Sstevel@tonic-gate 	        else
343*0Sstevel@tonic-gate 	        {
344*0Sstevel@tonic-gate 		    locungetc(inchar);
345*0Sstevel@tonic-gate 	            base = 8;
346*0Sstevel@tonic-gate                 }
347*0Sstevel@tonic-gate 	}
348*0Sstevel@tonic-gate 	if (!negflg || type != 'u')
349*0Sstevel@tonic-gate 	    for (; --len  >= 0 ; *np++ = c, c = locgetc())
350*0Sstevel@tonic-gate 	    {
351*0Sstevel@tonic-gate 		if (np > numbuf + 62)
352*0Sstevel@tonic-gate 		{
353*0Sstevel@tonic-gate 		    errno = ERANGE;
354*0Sstevel@tonic-gate 		    return(0);
355*0Sstevel@tonic-gate                 }
356*0Sstevel@tonic-gate 		if (isdigit(c))
357*0Sstevel@tonic-gate 		{
358*0Sstevel@tonic-gate 			register int digit;
359*0Sstevel@tonic-gate 			digit = c - '0';
360*0Sstevel@tonic-gate 			if (base == 8)
361*0Sstevel@tonic-gate 			{
362*0Sstevel@tonic-gate 				if (digit >= 8)
363*0Sstevel@tonic-gate 					break;
364*0Sstevel@tonic-gate 				if (stow)
365*0Sstevel@tonic-gate 					lcval = (lcval<<3) + digit;
366*0Sstevel@tonic-gate 			}
367*0Sstevel@tonic-gate 			else
368*0Sstevel@tonic-gate 			{
369*0Sstevel@tonic-gate 				if (stow)
370*0Sstevel@tonic-gate 				{
371*0Sstevel@tonic-gate 					if (base == 10)
372*0Sstevel@tonic-gate 						lcval = (((lcval<<2) + lcval)<<1) + digit;
373*0Sstevel@tonic-gate 					else /* base == 16 */
374*0Sstevel@tonic-gate 						lcval = (lcval<<4) + digit;
375*0Sstevel@tonic-gate 				}
376*0Sstevel@tonic-gate 			}
377*0Sstevel@tonic-gate 			digitseen++;
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 			continue;
381*0Sstevel@tonic-gate 		}
382*0Sstevel@tonic-gate 		else if (base == 16 && isxdigit(c))
383*0Sstevel@tonic-gate 		{
384*0Sstevel@tonic-gate 			register int digit;
385*0Sstevel@tonic-gate 			digit = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
386*0Sstevel@tonic-gate 			if (stow)
387*0Sstevel@tonic-gate 				lcval = (lcval<<4) + digit;
388*0Sstevel@tonic-gate 			digitseen++;
389*0Sstevel@tonic-gate 			continue;
390*0Sstevel@tonic-gate 		}
391*0Sstevel@tonic-gate 		break;
392*0Sstevel@tonic-gate 	    }
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 	if (stow && digitseen)
396*0Sstevel@tonic-gate 		{
397*0Sstevel@tonic-gate 	 	/* suppress possible overflow on 2's-comp negation */
398*0Sstevel@tonic-gate 			if (negflg && lcval != HIBITL)
399*0Sstevel@tonic-gate 				lcval = -lcval;
400*0Sstevel@tonic-gate 			if (size == 'l')
401*0Sstevel@tonic-gate 				*va_arg(*listp, long *) = lcval;
402*0Sstevel@tonic-gate 			else if (size == 'h')
403*0Sstevel@tonic-gate 				*va_arg(*listp, short *) = (short)lcval;
404*0Sstevel@tonic-gate 			else
405*0Sstevel@tonic-gate 				*va_arg(*listp, int *) = (int)lcval;
406*0Sstevel@tonic-gate 		}
407*0Sstevel@tonic-gate 	if (c == EOF) {
408*0Sstevel@tonic-gate 		chcount--;
409*0Sstevel@tonic-gate 		flag_eof=1;
410*0Sstevel@tonic-gate 	} else if (locungetc(c) == EOF)
411*0Sstevel@tonic-gate 		flag_eof=1;
412*0Sstevel@tonic-gate 	return (digitseen); /* successful match if non-zero */
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate static int
416*0Sstevel@tonic-gate string(stow, type, len, tab, iop, listp)
417*0Sstevel@tonic-gate register int stow, type, len;
418*0Sstevel@tonic-gate register char *tab;
419*0Sstevel@tonic-gate register FILE *iop;
420*0Sstevel@tonic-gate va_list *listp;
421*0Sstevel@tonic-gate {
422*0Sstevel@tonic-gate 	register int ch;
423*0Sstevel@tonic-gate 	register char *ptr;
424*0Sstevel@tonic-gate 	char *start;
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	start = ptr = stow ? va_arg(*listp, char *) : NULL;
427*0Sstevel@tonic-gate 	if (type == 's')
428*0Sstevel@tonic-gate 	{
429*0Sstevel@tonic-gate 		if (!flag_eof)
430*0Sstevel@tonic-gate 		{
431*0Sstevel@tonic-gate 			while (isws(ch = locgetc()))
432*0Sstevel@tonic-gate 				;
433*0Sstevel@tonic-gate 		}
434*0Sstevel@tonic-gate 		else
435*0Sstevel@tonic-gate 			ch = locgetc();
436*0Sstevel@tonic-gate 		if (ch == EOF)
437*0Sstevel@tonic-gate 			return(-1);	/* EOF before match */
438*0Sstevel@tonic-gate 		while (ch != EOF && !isws(ch))
439*0Sstevel@tonic-gate 		{
440*0Sstevel@tonic-gate 			if (stow)
441*0Sstevel@tonic-gate 				*ptr = ch;
442*0Sstevel@tonic-gate 			ptr++;
443*0Sstevel@tonic-gate 			if (--len <= 0)
444*0Sstevel@tonic-gate 				break;
445*0Sstevel@tonic-gate 			ch = locgetc();
446*0Sstevel@tonic-gate 		}
447*0Sstevel@tonic-gate 	} else if (type == 'c') {
448*0Sstevel@tonic-gate 		if (len == MAXINT)
449*0Sstevel@tonic-gate 			len = 1;
450*0Sstevel@tonic-gate 		while ( (ch = locgetc()) != EOF)
451*0Sstevel@tonic-gate 		{
452*0Sstevel@tonic-gate 			if (stow)
453*0Sstevel@tonic-gate 				*ptr = ch;
454*0Sstevel@tonic-gate 			ptr++;
455*0Sstevel@tonic-gate 			if (--len <= 0)
456*0Sstevel@tonic-gate 				break;
457*0Sstevel@tonic-gate 		}
458*0Sstevel@tonic-gate 	} else { /* type == '[' */
459*0Sstevel@tonic-gate 		while ( (ch = locgetc()) != EOF && !tab[ch])
460*0Sstevel@tonic-gate 		{
461*0Sstevel@tonic-gate 			if (stow)
462*0Sstevel@tonic-gate 				*ptr = ch;
463*0Sstevel@tonic-gate 			ptr++;
464*0Sstevel@tonic-gate 			if (--len <= 0)
465*0Sstevel@tonic-gate 				break;
466*0Sstevel@tonic-gate 		}
467*0Sstevel@tonic-gate 	}
468*0Sstevel@tonic-gate 	if (ch == EOF )
469*0Sstevel@tonic-gate 	{
470*0Sstevel@tonic-gate 		chcount-=1;
471*0Sstevel@tonic-gate 		flag_eof = 1;
472*0Sstevel@tonic-gate 	}
473*0Sstevel@tonic-gate 	else if (len > 0 && locungetc(ch) == EOF)
474*0Sstevel@tonic-gate 		flag_eof = 1;
475*0Sstevel@tonic-gate 	if (ptr == start)
476*0Sstevel@tonic-gate 		return(0); /* no match */
477*0Sstevel@tonic-gate 	if (stow && type != 'c')
478*0Sstevel@tonic-gate 		*ptr = '\0';
479*0Sstevel@tonic-gate 	return (1); /* successful match */
480*0Sstevel@tonic-gate }
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate static unsigned char *
483*0Sstevel@tonic-gate setup(fmt, tab)
484*0Sstevel@tonic-gate register unsigned char *fmt;
485*0Sstevel@tonic-gate register char *tab;
486*0Sstevel@tonic-gate {
487*0Sstevel@tonic-gate 	register int b, c, d, t = 0;
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 	if (*fmt == '^')
490*0Sstevel@tonic-gate 	{
491*0Sstevel@tonic-gate 		t++;
492*0Sstevel@tonic-gate 		fmt++;
493*0Sstevel@tonic-gate 	}
494*0Sstevel@tonic-gate 	(void) memset(tab, !t, NCHARS);
495*0Sstevel@tonic-gate 	if ( (c = *fmt) == ']' || c == '-')  /* first char is special */
496*0Sstevel@tonic-gate 	{
497*0Sstevel@tonic-gate 		tab[c] = t;
498*0Sstevel@tonic-gate 		fmt++;
499*0Sstevel@tonic-gate 	}
500*0Sstevel@tonic-gate 	while ( (c = *fmt++) != ']')
501*0Sstevel@tonic-gate 	{
502*0Sstevel@tonic-gate 		if (c == '\0')
503*0Sstevel@tonic-gate 			return(NULL); /* unexpected end of format */
504*0Sstevel@tonic-gate 		if (c == '-' && (d = *fmt) != ']' && (b = fmt[-2]) < d)
505*0Sstevel@tonic-gate 		{
506*0Sstevel@tonic-gate 			(void) memset(&tab[b], t, d - b + 1);
507*0Sstevel@tonic-gate 			fmt++;
508*0Sstevel@tonic-gate 		}
509*0Sstevel@tonic-gate 		else
510*0Sstevel@tonic-gate 			tab[c] = t;
511*0Sstevel@tonic-gate 	}
512*0Sstevel@tonic-gate 	return (fmt);
513*0Sstevel@tonic-gate }
514