xref: /onnv-gate/usr/src/lib/libbc/libc/stdio/common/doscan.c (revision 722:636b850d4ee9)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*722Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*722Smuffin  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
30*722Smuffin #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate /*LINTLIBRARY*/
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <ctype.h>
35*722Smuffin #include <stdarg.h>
360Sstevel@tonic-gate #include <values.h>
370Sstevel@tonic-gate #include <floatingpoint.h>
380Sstevel@tonic-gate #include <errno.h>
39*722Smuffin #include <memory.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #define NCHARS	(1 << BITSPERBYTE)
420Sstevel@tonic-gate #define locgetc()	(chcount+=1,getc(iop))
430Sstevel@tonic-gate #define locungetc(x)	(chcount-=1,ungetc(x,iop))
440Sstevel@tonic-gate 
450Sstevel@tonic-gate static int chcount,flag_eof;
460Sstevel@tonic-gate 
47*722Smuffin static int	number(int, int, int, int, FILE *, va_list *);
48*722Smuffin static int	string(int, int, int, char *, FILE *, va_list *);
49*722Smuffin static unsigned char	*setup(unsigned char *, char *);
50*722Smuffin 
510Sstevel@tonic-gate #ifdef S5EMUL
520Sstevel@tonic-gate #define	isws(c)		isspace(c)
530Sstevel@tonic-gate #else
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate  * _sptab[c+1] is 1 iff 'c' is a white space character according to the
560Sstevel@tonic-gate  * 4.2BSD "scanf" definition - namely, SP, TAB, and NL are the only
570Sstevel@tonic-gate  * whitespace characters.
580Sstevel@tonic-gate  */
590Sstevel@tonic-gate static char _sptab[1+256] = {
600Sstevel@tonic-gate 	0,				/* EOF - not a whitespace char */
610Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
620Sstevel@tonic-gate 	0,1,1,0,0,0,0,0,
630Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
640Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
650Sstevel@tonic-gate 	1,0,0,0,0,0,0,0,
660Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
670Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
680Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
690Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
700Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
710Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
720Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
730Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
740Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
750Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
760Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
770Sstevel@tonic-gate };
780Sstevel@tonic-gate 
790Sstevel@tonic-gate #define	isws(c)		((_sptab + 1)[c] != 0)
800Sstevel@tonic-gate #endif
810Sstevel@tonic-gate 
820Sstevel@tonic-gate int
_doscan(FILE * iop,unsigned char * fmt,va_list va_alist)83*722Smuffin _doscan(FILE *iop, unsigned char *fmt, va_list va_alist)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 	char tab[NCHARS];
86*722Smuffin 	int ch;
870Sstevel@tonic-gate 	int nmatch = 0, len, inchar, stow, size;
880Sstevel@tonic-gate 	chcount=0; flag_eof=0;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	/*******************************************************
910Sstevel@tonic-gate 	 * Main loop: reads format to determine a pattern,
920Sstevel@tonic-gate 	 *		and then goes to read input stream
930Sstevel@tonic-gate 	 *		in attempt to match the pattern.
940Sstevel@tonic-gate 	 *******************************************************/
950Sstevel@tonic-gate 	for ( ; ; )
960Sstevel@tonic-gate 	{
970Sstevel@tonic-gate 		if ( (ch = *fmt++) == '\0')
980Sstevel@tonic-gate 			return(nmatch); /* end of format */
990Sstevel@tonic-gate 		if (isws(ch))
1000Sstevel@tonic-gate 		{
1010Sstevel@tonic-gate 		  	if (!flag_eof)
1020Sstevel@tonic-gate 			{
1030Sstevel@tonic-gate 			   while (isws(inchar = locgetc()))
1040Sstevel@tonic-gate 				;
1050Sstevel@tonic-gate 			   if (inchar == EOF) {
1060Sstevel@tonic-gate 				chcount--;
1070Sstevel@tonic-gate 				flag_eof = 1;
1080Sstevel@tonic-gate 			   }
1090Sstevel@tonic-gate 			   else if (locungetc(inchar) == EOF)
1100Sstevel@tonic-gate 				flag_eof = 1;
1110Sstevel@tonic-gate 			}
1120Sstevel@tonic-gate 		  continue;
1130Sstevel@tonic-gate 		}
1140Sstevel@tonic-gate 		if (ch != '%' || (ch = *fmt++) == '%')
1150Sstevel@tonic-gate                 {
1160Sstevel@tonic-gate 			if ( (inchar = locgetc()) == ch )
1170Sstevel@tonic-gate 				continue;
1180Sstevel@tonic-gate 			if (inchar != EOF) {
1190Sstevel@tonic-gate 				if (locungetc(inchar) != EOF)
1200Sstevel@tonic-gate 					return(nmatch); /* failed to match input */
1210Sstevel@tonic-gate 			} else {
1220Sstevel@tonic-gate 				chcount--;
1230Sstevel@tonic-gate 			}
1240Sstevel@tonic-gate 			break;
1250Sstevel@tonic-gate 		}
1260Sstevel@tonic-gate 		if (ch == '*')
1270Sstevel@tonic-gate 		{
1280Sstevel@tonic-gate 			stow = 0;
1290Sstevel@tonic-gate 			ch = *fmt++;
1300Sstevel@tonic-gate 		}
1310Sstevel@tonic-gate 		else
1320Sstevel@tonic-gate 			stow = 1;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 		for (len = 0; isdigit(ch); ch = *fmt++)
1350Sstevel@tonic-gate 			len = len * 10 + ch - '0';
1360Sstevel@tonic-gate 		if (len == 0)
1370Sstevel@tonic-gate 			len = MAXINT;
1380Sstevel@tonic-gate 		if ( (size = ch) == 'l' || (size == 'h') || (size == 'L') )
1390Sstevel@tonic-gate 			ch = *fmt++;
1400Sstevel@tonic-gate 		if (ch == '\0' ||
1410Sstevel@tonic-gate 		    ch == '[' && (fmt = setup(fmt, tab)) == NULL)
1420Sstevel@tonic-gate 			return(EOF); /* unexpected end of format */
1430Sstevel@tonic-gate 		if (isupper(ch))  /* no longer documented */
1440Sstevel@tonic-gate 		{
1450Sstevel@tonic-gate 			/*
1460Sstevel@tonic-gate 			 * The rationale behind excluding the size
1470Sstevel@tonic-gate 			 * of 'L' is that the 'L' size specifier was
1480Sstevel@tonic-gate 			 * introduced in ANSI/ISO-C.  If the user
1490Sstevel@tonic-gate 			 * specifies a format of %LG, it can mean
1500Sstevel@tonic-gate 			 * nothing other than "long double", be the
1510Sstevel@tonic-gate 			 * code ANSI or not.  Mapping it to "double"
1520Sstevel@tonic-gate 			 * makes no sense.
1530Sstevel@tonic-gate 			 */
1540Sstevel@tonic-gate 			if (size != 'L')
1550Sstevel@tonic-gate 				size = 'l';
1560Sstevel@tonic-gate #ifdef S5EMUL
1570Sstevel@tonic-gate 			ch = _tolower(ch);
1580Sstevel@tonic-gate #else
1590Sstevel@tonic-gate 			ch = tolower(ch);
1600Sstevel@tonic-gate #endif
1610Sstevel@tonic-gate 		}
1620Sstevel@tonic-gate 		switch(ch)
1630Sstevel@tonic-gate 		{
1640Sstevel@tonic-gate 		 case 'c':
1650Sstevel@tonic-gate 		 case 's':
1660Sstevel@tonic-gate 		 case '[':
1670Sstevel@tonic-gate 			  if ((size = string(stow,ch,len,tab,iop,&va_alist)) < 0)
1680Sstevel@tonic-gate 				goto out;	/* EOF seen, nothing converted */
1690Sstevel@tonic-gate 			  break;
1700Sstevel@tonic-gate                  case 'n':
1710Sstevel@tonic-gate 			  if (stow == 0)
1720Sstevel@tonic-gate 				continue;
1730Sstevel@tonic-gate 			  if (size == 'h')
1740Sstevel@tonic-gate 				*va_arg(va_alist, short *) = (short) chcount;
1750Sstevel@tonic-gate 		          else if (size == 'l')
1760Sstevel@tonic-gate 				*va_arg(va_alist, long *) = (long) chcount;
1770Sstevel@tonic-gate 			  else
1780Sstevel@tonic-gate 			  	*va_arg(va_alist, int *) = (int) chcount;
1790Sstevel@tonic-gate 			  continue;
1800Sstevel@tonic-gate                  default:
1810Sstevel@tonic-gate 			 if ((size = number(stow, ch, len, size, iop, &va_alist)) < 0)
1820Sstevel@tonic-gate 				goto out;	/* EOF seen, nothing converted */
1830Sstevel@tonic-gate 			 break;
1840Sstevel@tonic-gate                  }
1850Sstevel@tonic-gate 		   if (size)
1860Sstevel@tonic-gate 			nmatch += stow;
1870Sstevel@tonic-gate 		   else
1880Sstevel@tonic-gate 			return((flag_eof && !nmatch) ? EOF : nmatch);
1890Sstevel@tonic-gate 		continue;
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate out:
1920Sstevel@tonic-gate 	return (nmatch != 0 ? nmatch : EOF); /* end of input */
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate 
195*722Smuffin /*
196*722Smuffin  **************************************************************
1970Sstevel@tonic-gate  * Functions to read the input stream in an attempt to match incoming
1980Sstevel@tonic-gate  * data to the current pattern from the main loop of _doscan().
199*722Smuffin  **************************************************************
200*722Smuffin  */
2010Sstevel@tonic-gate static int
number(int stow,int type,int len,int size,FILE * iop,va_list * listp)202*722Smuffin number(int stow, int type, int len, int size, FILE *iop, va_list *listp)
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate 	char numbuf[64], inchar, lookahead;
205*722Smuffin 	char *np = numbuf;
206*722Smuffin 	int c, base;
2070Sstevel@tonic-gate 	int digitseen = 0, floater = 0, negflg = 0;
2080Sstevel@tonic-gate 	long lcval = 0;
2090Sstevel@tonic-gate 	switch(type)
2100Sstevel@tonic-gate 	{
2110Sstevel@tonic-gate 	case 'e':
2120Sstevel@tonic-gate 	case 'f':
2130Sstevel@tonic-gate 	case 'g':
2140Sstevel@tonic-gate 		floater++;
2150Sstevel@tonic-gate 	case 'd':
2160Sstevel@tonic-gate 	case 'u':
2170Sstevel@tonic-gate 	case 'i':
2180Sstevel@tonic-gate 		base = 10;
2190Sstevel@tonic-gate 		break;
2200Sstevel@tonic-gate 	case 'o':
2210Sstevel@tonic-gate 		base = 8;
2220Sstevel@tonic-gate 		break;
2230Sstevel@tonic-gate 	case 'x':
2240Sstevel@tonic-gate 		base = 16;
2250Sstevel@tonic-gate 		break;
2260Sstevel@tonic-gate 	default:
2270Sstevel@tonic-gate 		return(0); /* unrecognized conversion character */
2280Sstevel@tonic-gate 	}
2290Sstevel@tonic-gate 	if (!flag_eof)
2300Sstevel@tonic-gate 	{
2310Sstevel@tonic-gate 		while (isws(c = locgetc()))
2320Sstevel@tonic-gate 			;
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 	else
2350Sstevel@tonic-gate 		c = locgetc();
2360Sstevel@tonic-gate 	if (c == EOF) {
2370Sstevel@tonic-gate 		chcount--;
2380Sstevel@tonic-gate 		return(-1);	/* EOF before match */
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate         if (floater != 0) {     /* Handle floating point with
2410Sstevel@tonic-gate                                  * file_to_decimal. */
2420Sstevel@tonic-gate                 decimal_mode    dm;
2430Sstevel@tonic-gate                 decimal_record  dr;
2440Sstevel@tonic-gate                 fp_exception_field_type efs;
2450Sstevel@tonic-gate                 enum decimal_string_form form;
2460Sstevel@tonic-gate                 char           *echar;
2470Sstevel@tonic-gate                 int             nread, ic;
2480Sstevel@tonic-gate                 char            buffer[1024];
2490Sstevel@tonic-gate                 char           *nb = buffer;
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate                 locungetc(c);
2520Sstevel@tonic-gate 		if (len > 1024)
2530Sstevel@tonic-gate 			len = 1024;
2540Sstevel@tonic-gate                 file_to_decimal(&nb, len, 0, &dr, &form, &echar, iop, &nread);
2550Sstevel@tonic-gate                 if (stow && (form != invalid_form)) {
2560Sstevel@tonic-gate                         dm.rd = fp_direction;
2570Sstevel@tonic-gate                         if (size == 'l') {      /* double */
2580Sstevel@tonic-gate                                 decimal_to_double((double *) va_arg(*listp, double *), &dm, &dr, &efs);
2590Sstevel@tonic-gate                         } else if (size == 'L') {      /* quad */
2600Sstevel@tonic-gate                                 decimal_to_quadruple((quadruple *)va_arg(*listp, double *), &dm, &dr, &efs);
2610Sstevel@tonic-gate                         } else {/* single */
2620Sstevel@tonic-gate                                 decimal_to_single((float *) va_arg(*listp, float *), &dm, &dr, &efs);
2630Sstevel@tonic-gate                         }
2640Sstevel@tonic-gate 			if ((efs & (1 << fp_overflow)) != 0) {
2650Sstevel@tonic-gate 				errno = ERANGE;
2660Sstevel@tonic-gate 			}
2670Sstevel@tonic-gate 			if ((efs & (1 << fp_underflow)) != 0) {
2680Sstevel@tonic-gate 				errno = ERANGE;
2690Sstevel@tonic-gate                         }
2700Sstevel@tonic-gate                 }
2710Sstevel@tonic-gate 		chcount += nread;	/* Count characters read. */
2720Sstevel@tonic-gate                 c = *nb;        /* Get first unused character. */
2730Sstevel@tonic-gate                 ic = c;
2740Sstevel@tonic-gate                 if (c == NULL) {
2750Sstevel@tonic-gate                         ic = locgetc();
2760Sstevel@tonic-gate                         c = ic;
2770Sstevel@tonic-gate                         /*
2780Sstevel@tonic-gate                          * If null, first unused may have been put back
2790Sstevel@tonic-gate                          * already.
2800Sstevel@tonic-gate                          */
2810Sstevel@tonic-gate                 }
2820Sstevel@tonic-gate                 if (ic == EOF) {
2830Sstevel@tonic-gate                         chcount--;
2840Sstevel@tonic-gate                         flag_eof = 1;
2850Sstevel@tonic-gate                 } else if (locungetc(c) == EOF)
2860Sstevel@tonic-gate                         flag_eof = 1;
2870Sstevel@tonic-gate                 return ((form == invalid_form) ? 0 : 1);        /* successful match if
2880Sstevel@tonic-gate                                                                  * non-zero */
2890Sstevel@tonic-gate         }
2900Sstevel@tonic-gate 	switch(c) {
2910Sstevel@tonic-gate 	case '-':
2920Sstevel@tonic-gate 		negflg++;
2930Sstevel@tonic-gate 		if (type == 'u')
2940Sstevel@tonic-gate 			break;
2950Sstevel@tonic-gate 	case '+': /* fall-through */
2960Sstevel@tonic-gate 		if (--len <= 0)
2970Sstevel@tonic-gate 			break;
2980Sstevel@tonic-gate 		if ( (c = locgetc()) != '0')
2990Sstevel@tonic-gate 			break;
3000Sstevel@tonic-gate         case '0':
3010Sstevel@tonic-gate                 if ( (type != 'i') || (len <= 1) )
3020Sstevel@tonic-gate 		   break;
3030Sstevel@tonic-gate 	        if ( ((inchar = locgetc()) == 'x') || (inchar == 'X') )
3040Sstevel@tonic-gate 	        {
3050Sstevel@tonic-gate 		      /* If not using sscanf and *
3060Sstevel@tonic-gate 		       * at the buffer's end     *
3070Sstevel@tonic-gate 		       * then LOOK ahead         */
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate                    if ( (iop->_flag & _IOSTRG) || (iop->_cnt != 0) )
3100Sstevel@tonic-gate 		      lookahead = locgetc();
3110Sstevel@tonic-gate 		   else
3120Sstevel@tonic-gate 		   {
3130Sstevel@tonic-gate 		      if ( read(fileno(iop),np,1) == 1)
3140Sstevel@tonic-gate 		         lookahead = *np;
3150Sstevel@tonic-gate                       else
3160Sstevel@tonic-gate 		         lookahead = EOF;
3170Sstevel@tonic-gate                       chcount += 1;
3180Sstevel@tonic-gate                    }
3190Sstevel@tonic-gate 		   if ( isxdigit(lookahead) )
3200Sstevel@tonic-gate 		   {
3210Sstevel@tonic-gate 		       base =16;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 		       if ( len <= 2)
3240Sstevel@tonic-gate 		       {
3250Sstevel@tonic-gate 			  locungetc(lookahead);
3260Sstevel@tonic-gate 			  len -= 1;            /* Take into account the 'x'*/
3270Sstevel@tonic-gate                        }
3280Sstevel@tonic-gate 		       else
3290Sstevel@tonic-gate 		       {
3300Sstevel@tonic-gate 		          c = lookahead;
3310Sstevel@tonic-gate 			  len -= 2;           /* Take into account '0x'*/
3320Sstevel@tonic-gate 		       }
3330Sstevel@tonic-gate                    }
3340Sstevel@tonic-gate 	           else
3350Sstevel@tonic-gate 	           {
3360Sstevel@tonic-gate 	               locungetc(lookahead);
3370Sstevel@tonic-gate 	               locungetc(inchar);
3380Sstevel@tonic-gate                    }
3390Sstevel@tonic-gate 		}
3400Sstevel@tonic-gate 	        else
3410Sstevel@tonic-gate 	        {
3420Sstevel@tonic-gate 		    locungetc(inchar);
3430Sstevel@tonic-gate 	            base = 8;
3440Sstevel@tonic-gate                 }
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 	if (!negflg || type != 'u')
3470Sstevel@tonic-gate 	    for (; --len  >= 0 ; *np++ = c, c = locgetc())
3480Sstevel@tonic-gate 	    {
3490Sstevel@tonic-gate 		if (np > numbuf + 62)
3500Sstevel@tonic-gate 		{
3510Sstevel@tonic-gate 		    errno = ERANGE;
3520Sstevel@tonic-gate 		    return(0);
3530Sstevel@tonic-gate                 }
3540Sstevel@tonic-gate 		if (isdigit(c))
3550Sstevel@tonic-gate 		{
356*722Smuffin 			int digit;
3570Sstevel@tonic-gate 			digit = c - '0';
3580Sstevel@tonic-gate 			if (base == 8)
3590Sstevel@tonic-gate 			{
3600Sstevel@tonic-gate 				if (digit >= 8)
3610Sstevel@tonic-gate 					break;
3620Sstevel@tonic-gate 				if (stow)
3630Sstevel@tonic-gate 					lcval = (lcval<<3) + digit;
3640Sstevel@tonic-gate 			}
3650Sstevel@tonic-gate 			else
3660Sstevel@tonic-gate 			{
3670Sstevel@tonic-gate 				if (stow)
3680Sstevel@tonic-gate 				{
3690Sstevel@tonic-gate 					if (base == 10)
3700Sstevel@tonic-gate 						lcval = (((lcval<<2) + lcval)<<1) + digit;
3710Sstevel@tonic-gate 					else /* base == 16 */
3720Sstevel@tonic-gate 						lcval = (lcval<<4) + digit;
3730Sstevel@tonic-gate 				}
3740Sstevel@tonic-gate 			}
3750Sstevel@tonic-gate 			digitseen++;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 			continue;
3790Sstevel@tonic-gate 		}
3800Sstevel@tonic-gate 		else if (base == 16 && isxdigit(c))
3810Sstevel@tonic-gate 		{
382*722Smuffin 			int digit;
3830Sstevel@tonic-gate 			digit = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
3840Sstevel@tonic-gate 			if (stow)
3850Sstevel@tonic-gate 				lcval = (lcval<<4) + digit;
3860Sstevel@tonic-gate 			digitseen++;
3870Sstevel@tonic-gate 			continue;
3880Sstevel@tonic-gate 		}
3890Sstevel@tonic-gate 		break;
3900Sstevel@tonic-gate 	    }
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	if (stow && digitseen)
3940Sstevel@tonic-gate 		{
3950Sstevel@tonic-gate 	 	/* suppress possible overflow on 2's-comp negation */
3960Sstevel@tonic-gate 			if (negflg && lcval != HIBITL)
3970Sstevel@tonic-gate 				lcval = -lcval;
3980Sstevel@tonic-gate 			if (size == 'l')
3990Sstevel@tonic-gate 				*va_arg(*listp, long *) = lcval;
4000Sstevel@tonic-gate 			else if (size == 'h')
4010Sstevel@tonic-gate 				*va_arg(*listp, short *) = (short)lcval;
4020Sstevel@tonic-gate 			else
4030Sstevel@tonic-gate 				*va_arg(*listp, int *) = (int)lcval;
4040Sstevel@tonic-gate 		}
4050Sstevel@tonic-gate 	if (c == EOF) {
4060Sstevel@tonic-gate 		chcount--;
4070Sstevel@tonic-gate 		flag_eof=1;
4080Sstevel@tonic-gate 	} else if (locungetc(c) == EOF)
4090Sstevel@tonic-gate 		flag_eof=1;
4100Sstevel@tonic-gate 	return (digitseen); /* successful match if non-zero */
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate static int
string(int stow,int type,int len,char * tab,FILE * iop,va_list * listp)414*722Smuffin string(int stow, int type, int len, char *tab, FILE *iop, va_list *listp)
4150Sstevel@tonic-gate {
416*722Smuffin 	int ch;
417*722Smuffin 	char *ptr;
4180Sstevel@tonic-gate 	char *start;
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	start = ptr = stow ? va_arg(*listp, char *) : NULL;
4210Sstevel@tonic-gate 	if (type == 's')
4220Sstevel@tonic-gate 	{
4230Sstevel@tonic-gate 		if (!flag_eof)
4240Sstevel@tonic-gate 		{
4250Sstevel@tonic-gate 			while (isws(ch = locgetc()))
4260Sstevel@tonic-gate 				;
4270Sstevel@tonic-gate 		}
4280Sstevel@tonic-gate 		else
4290Sstevel@tonic-gate 			ch = locgetc();
4300Sstevel@tonic-gate 		if (ch == EOF)
4310Sstevel@tonic-gate 			return(-1);	/* EOF before match */
4320Sstevel@tonic-gate 		while (ch != EOF && !isws(ch))
4330Sstevel@tonic-gate 		{
4340Sstevel@tonic-gate 			if (stow)
4350Sstevel@tonic-gate 				*ptr = ch;
4360Sstevel@tonic-gate 			ptr++;
4370Sstevel@tonic-gate 			if (--len <= 0)
4380Sstevel@tonic-gate 				break;
4390Sstevel@tonic-gate 			ch = locgetc();
4400Sstevel@tonic-gate 		}
4410Sstevel@tonic-gate 	} else if (type == 'c') {
4420Sstevel@tonic-gate 		if (len == MAXINT)
4430Sstevel@tonic-gate 			len = 1;
4440Sstevel@tonic-gate 		while ( (ch = locgetc()) != EOF)
4450Sstevel@tonic-gate 		{
4460Sstevel@tonic-gate 			if (stow)
4470Sstevel@tonic-gate 				*ptr = ch;
4480Sstevel@tonic-gate 			ptr++;
4490Sstevel@tonic-gate 			if (--len <= 0)
4500Sstevel@tonic-gate 				break;
4510Sstevel@tonic-gate 		}
4520Sstevel@tonic-gate 	} else { /* type == '[' */
4530Sstevel@tonic-gate 		while ( (ch = locgetc()) != EOF && !tab[ch])
4540Sstevel@tonic-gate 		{
4550Sstevel@tonic-gate 			if (stow)
4560Sstevel@tonic-gate 				*ptr = ch;
4570Sstevel@tonic-gate 			ptr++;
4580Sstevel@tonic-gate 			if (--len <= 0)
4590Sstevel@tonic-gate 				break;
4600Sstevel@tonic-gate 		}
4610Sstevel@tonic-gate 	}
4620Sstevel@tonic-gate 	if (ch == EOF )
4630Sstevel@tonic-gate 	{
4640Sstevel@tonic-gate 		chcount-=1;
4650Sstevel@tonic-gate 		flag_eof = 1;
4660Sstevel@tonic-gate 	}
4670Sstevel@tonic-gate 	else if (len > 0 && locungetc(ch) == EOF)
4680Sstevel@tonic-gate 		flag_eof = 1;
4690Sstevel@tonic-gate 	if (ptr == start)
4700Sstevel@tonic-gate 		return(0); /* no match */
4710Sstevel@tonic-gate 	if (stow && type != 'c')
4720Sstevel@tonic-gate 		*ptr = '\0';
4730Sstevel@tonic-gate 	return (1); /* successful match */
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate static unsigned char *
setup(unsigned char * fmt,char * tab)477*722Smuffin setup(unsigned char *fmt, char *tab)
4780Sstevel@tonic-gate {
479*722Smuffin 	int b, c, d, t = 0;
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	if (*fmt == '^')
4820Sstevel@tonic-gate 	{
4830Sstevel@tonic-gate 		t++;
4840Sstevel@tonic-gate 		fmt++;
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 	(void) memset(tab, !t, NCHARS);
4870Sstevel@tonic-gate 	if ( (c = *fmt) == ']' || c == '-')  /* first char is special */
4880Sstevel@tonic-gate 	{
4890Sstevel@tonic-gate 		tab[c] = t;
4900Sstevel@tonic-gate 		fmt++;
4910Sstevel@tonic-gate 	}
4920Sstevel@tonic-gate 	while ( (c = *fmt++) != ']')
4930Sstevel@tonic-gate 	{
4940Sstevel@tonic-gate 		if (c == '\0')
4950Sstevel@tonic-gate 			return(NULL); /* unexpected end of format */
4960Sstevel@tonic-gate 		if (c == '-' && (d = *fmt) != ']' && (b = fmt[-2]) < d)
4970Sstevel@tonic-gate 		{
4980Sstevel@tonic-gate 			(void) memset(&tab[b], t, d - b + 1);
4990Sstevel@tonic-gate 			fmt++;
5000Sstevel@tonic-gate 		}
5010Sstevel@tonic-gate 		else
5020Sstevel@tonic-gate 			tab[c] = t;
5030Sstevel@tonic-gate 	}
5040Sstevel@tonic-gate 	return (fmt);
5050Sstevel@tonic-gate }
506