xref: /titanic_52/usr/src/lib/libbc/libc/stdio/common/doscan.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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 /*
23*5d54f3d8Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*5d54f3d8Smuffin  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
30*5d54f3d8Smuffin #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate #include <ctype.h>
35*5d54f3d8Smuffin #include <stdarg.h>
367c478bd9Sstevel@tonic-gate #include <values.h>
377c478bd9Sstevel@tonic-gate #include <floatingpoint.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
39*5d54f3d8Smuffin #include <memory.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #define NCHARS	(1 << BITSPERBYTE)
427c478bd9Sstevel@tonic-gate #define locgetc()	(chcount+=1,getc(iop))
437c478bd9Sstevel@tonic-gate #define locungetc(x)	(chcount-=1,ungetc(x,iop))
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate static int chcount,flag_eof;
467c478bd9Sstevel@tonic-gate 
47*5d54f3d8Smuffin static int	number(int, int, int, int, FILE *, va_list *);
48*5d54f3d8Smuffin static int	string(int, int, int, char *, FILE *, va_list *);
49*5d54f3d8Smuffin static unsigned char	*setup(unsigned char *, char *);
50*5d54f3d8Smuffin 
517c478bd9Sstevel@tonic-gate #ifdef S5EMUL
527c478bd9Sstevel@tonic-gate #define	isws(c)		isspace(c)
537c478bd9Sstevel@tonic-gate #else
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * _sptab[c+1] is 1 iff 'c' is a white space character according to the
567c478bd9Sstevel@tonic-gate  * 4.2BSD "scanf" definition - namely, SP, TAB, and NL are the only
577c478bd9Sstevel@tonic-gate  * whitespace characters.
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate static char _sptab[1+256] = {
607c478bd9Sstevel@tonic-gate 	0,				/* EOF - not a whitespace char */
617c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
627c478bd9Sstevel@tonic-gate 	0,1,1,0,0,0,0,0,
637c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
647c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
657c478bd9Sstevel@tonic-gate 	1,0,0,0,0,0,0,0,
667c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
677c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
687c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
697c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
707c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
717c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
727c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
737c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
747c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
757c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
767c478bd9Sstevel@tonic-gate 	0,0,0,0,0,0,0,0,
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #define	isws(c)		((_sptab + 1)[c] != 0)
807c478bd9Sstevel@tonic-gate #endif
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate int
83*5d54f3d8Smuffin _doscan(FILE *iop, unsigned char *fmt, va_list va_alist)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	char tab[NCHARS];
86*5d54f3d8Smuffin 	int ch;
877c478bd9Sstevel@tonic-gate 	int nmatch = 0, len, inchar, stow, size;
887c478bd9Sstevel@tonic-gate 	chcount=0; flag_eof=0;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	/*******************************************************
917c478bd9Sstevel@tonic-gate 	 * Main loop: reads format to determine a pattern,
927c478bd9Sstevel@tonic-gate 	 *		and then goes to read input stream
937c478bd9Sstevel@tonic-gate 	 *		in attempt to match the pattern.
947c478bd9Sstevel@tonic-gate 	 *******************************************************/
957c478bd9Sstevel@tonic-gate 	for ( ; ; )
967c478bd9Sstevel@tonic-gate 	{
977c478bd9Sstevel@tonic-gate 		if ( (ch = *fmt++) == '\0')
987c478bd9Sstevel@tonic-gate 			return(nmatch); /* end of format */
997c478bd9Sstevel@tonic-gate 		if (isws(ch))
1007c478bd9Sstevel@tonic-gate 		{
1017c478bd9Sstevel@tonic-gate 		  	if (!flag_eof)
1027c478bd9Sstevel@tonic-gate 			{
1037c478bd9Sstevel@tonic-gate 			   while (isws(inchar = locgetc()))
1047c478bd9Sstevel@tonic-gate 				;
1057c478bd9Sstevel@tonic-gate 			   if (inchar == EOF) {
1067c478bd9Sstevel@tonic-gate 				chcount--;
1077c478bd9Sstevel@tonic-gate 				flag_eof = 1;
1087c478bd9Sstevel@tonic-gate 			   }
1097c478bd9Sstevel@tonic-gate 			   else if (locungetc(inchar) == EOF)
1107c478bd9Sstevel@tonic-gate 				flag_eof = 1;
1117c478bd9Sstevel@tonic-gate 			}
1127c478bd9Sstevel@tonic-gate 		  continue;
1137c478bd9Sstevel@tonic-gate 		}
1147c478bd9Sstevel@tonic-gate 		if (ch != '%' || (ch = *fmt++) == '%')
1157c478bd9Sstevel@tonic-gate                 {
1167c478bd9Sstevel@tonic-gate 			if ( (inchar = locgetc()) == ch )
1177c478bd9Sstevel@tonic-gate 				continue;
1187c478bd9Sstevel@tonic-gate 			if (inchar != EOF) {
1197c478bd9Sstevel@tonic-gate 				if (locungetc(inchar) != EOF)
1207c478bd9Sstevel@tonic-gate 					return(nmatch); /* failed to match input */
1217c478bd9Sstevel@tonic-gate 			} else {
1227c478bd9Sstevel@tonic-gate 				chcount--;
1237c478bd9Sstevel@tonic-gate 			}
1247c478bd9Sstevel@tonic-gate 			break;
1257c478bd9Sstevel@tonic-gate 		}
1267c478bd9Sstevel@tonic-gate 		if (ch == '*')
1277c478bd9Sstevel@tonic-gate 		{
1287c478bd9Sstevel@tonic-gate 			stow = 0;
1297c478bd9Sstevel@tonic-gate 			ch = *fmt++;
1307c478bd9Sstevel@tonic-gate 		}
1317c478bd9Sstevel@tonic-gate 		else
1327c478bd9Sstevel@tonic-gate 			stow = 1;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 		for (len = 0; isdigit(ch); ch = *fmt++)
1357c478bd9Sstevel@tonic-gate 			len = len * 10 + ch - '0';
1367c478bd9Sstevel@tonic-gate 		if (len == 0)
1377c478bd9Sstevel@tonic-gate 			len = MAXINT;
1387c478bd9Sstevel@tonic-gate 		if ( (size = ch) == 'l' || (size == 'h') || (size == 'L') )
1397c478bd9Sstevel@tonic-gate 			ch = *fmt++;
1407c478bd9Sstevel@tonic-gate 		if (ch == '\0' ||
1417c478bd9Sstevel@tonic-gate 		    ch == '[' && (fmt = setup(fmt, tab)) == NULL)
1427c478bd9Sstevel@tonic-gate 			return(EOF); /* unexpected end of format */
1437c478bd9Sstevel@tonic-gate 		if (isupper(ch))  /* no longer documented */
1447c478bd9Sstevel@tonic-gate 		{
1457c478bd9Sstevel@tonic-gate 			/*
1467c478bd9Sstevel@tonic-gate 			 * The rationale behind excluding the size
1477c478bd9Sstevel@tonic-gate 			 * of 'L' is that the 'L' size specifier was
1487c478bd9Sstevel@tonic-gate 			 * introduced in ANSI/ISO-C.  If the user
1497c478bd9Sstevel@tonic-gate 			 * specifies a format of %LG, it can mean
1507c478bd9Sstevel@tonic-gate 			 * nothing other than "long double", be the
1517c478bd9Sstevel@tonic-gate 			 * code ANSI or not.  Mapping it to "double"
1527c478bd9Sstevel@tonic-gate 			 * makes no sense.
1537c478bd9Sstevel@tonic-gate 			 */
1547c478bd9Sstevel@tonic-gate 			if (size != 'L')
1557c478bd9Sstevel@tonic-gate 				size = 'l';
1567c478bd9Sstevel@tonic-gate #ifdef S5EMUL
1577c478bd9Sstevel@tonic-gate 			ch = _tolower(ch);
1587c478bd9Sstevel@tonic-gate #else
1597c478bd9Sstevel@tonic-gate 			ch = tolower(ch);
1607c478bd9Sstevel@tonic-gate #endif
1617c478bd9Sstevel@tonic-gate 		}
1627c478bd9Sstevel@tonic-gate 		switch(ch)
1637c478bd9Sstevel@tonic-gate 		{
1647c478bd9Sstevel@tonic-gate 		 case 'c':
1657c478bd9Sstevel@tonic-gate 		 case 's':
1667c478bd9Sstevel@tonic-gate 		 case '[':
1677c478bd9Sstevel@tonic-gate 			  if ((size = string(stow,ch,len,tab,iop,&va_alist)) < 0)
1687c478bd9Sstevel@tonic-gate 				goto out;	/* EOF seen, nothing converted */
1697c478bd9Sstevel@tonic-gate 			  break;
1707c478bd9Sstevel@tonic-gate                  case 'n':
1717c478bd9Sstevel@tonic-gate 			  if (stow == 0)
1727c478bd9Sstevel@tonic-gate 				continue;
1737c478bd9Sstevel@tonic-gate 			  if (size == 'h')
1747c478bd9Sstevel@tonic-gate 				*va_arg(va_alist, short *) = (short) chcount;
1757c478bd9Sstevel@tonic-gate 		          else if (size == 'l')
1767c478bd9Sstevel@tonic-gate 				*va_arg(va_alist, long *) = (long) chcount;
1777c478bd9Sstevel@tonic-gate 			  else
1787c478bd9Sstevel@tonic-gate 			  	*va_arg(va_alist, int *) = (int) chcount;
1797c478bd9Sstevel@tonic-gate 			  continue;
1807c478bd9Sstevel@tonic-gate                  default:
1817c478bd9Sstevel@tonic-gate 			 if ((size = number(stow, ch, len, size, iop, &va_alist)) < 0)
1827c478bd9Sstevel@tonic-gate 				goto out;	/* EOF seen, nothing converted */
1837c478bd9Sstevel@tonic-gate 			 break;
1847c478bd9Sstevel@tonic-gate                  }
1857c478bd9Sstevel@tonic-gate 		   if (size)
1867c478bd9Sstevel@tonic-gate 			nmatch += stow;
1877c478bd9Sstevel@tonic-gate 		   else
1887c478bd9Sstevel@tonic-gate 			return((flag_eof && !nmatch) ? EOF : nmatch);
1897c478bd9Sstevel@tonic-gate 		continue;
1907c478bd9Sstevel@tonic-gate 	}
1917c478bd9Sstevel@tonic-gate out:
1927c478bd9Sstevel@tonic-gate 	return (nmatch != 0 ? nmatch : EOF); /* end of input */
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate 
195*5d54f3d8Smuffin /*
196*5d54f3d8Smuffin  **************************************************************
1977c478bd9Sstevel@tonic-gate  * Functions to read the input stream in an attempt to match incoming
1987c478bd9Sstevel@tonic-gate  * data to the current pattern from the main loop of _doscan().
199*5d54f3d8Smuffin  **************************************************************
200*5d54f3d8Smuffin  */
2017c478bd9Sstevel@tonic-gate static int
202*5d54f3d8Smuffin number(int stow, int type, int len, int size, FILE *iop, va_list *listp)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate 	char numbuf[64], inchar, lookahead;
205*5d54f3d8Smuffin 	char *np = numbuf;
206*5d54f3d8Smuffin 	int c, base;
2077c478bd9Sstevel@tonic-gate 	int digitseen = 0, floater = 0, negflg = 0;
2087c478bd9Sstevel@tonic-gate 	long lcval = 0;
2097c478bd9Sstevel@tonic-gate 	switch(type)
2107c478bd9Sstevel@tonic-gate 	{
2117c478bd9Sstevel@tonic-gate 	case 'e':
2127c478bd9Sstevel@tonic-gate 	case 'f':
2137c478bd9Sstevel@tonic-gate 	case 'g':
2147c478bd9Sstevel@tonic-gate 		floater++;
2157c478bd9Sstevel@tonic-gate 	case 'd':
2167c478bd9Sstevel@tonic-gate 	case 'u':
2177c478bd9Sstevel@tonic-gate 	case 'i':
2187c478bd9Sstevel@tonic-gate 		base = 10;
2197c478bd9Sstevel@tonic-gate 		break;
2207c478bd9Sstevel@tonic-gate 	case 'o':
2217c478bd9Sstevel@tonic-gate 		base = 8;
2227c478bd9Sstevel@tonic-gate 		break;
2237c478bd9Sstevel@tonic-gate 	case 'x':
2247c478bd9Sstevel@tonic-gate 		base = 16;
2257c478bd9Sstevel@tonic-gate 		break;
2267c478bd9Sstevel@tonic-gate 	default:
2277c478bd9Sstevel@tonic-gate 		return(0); /* unrecognized conversion character */
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 	if (!flag_eof)
2307c478bd9Sstevel@tonic-gate 	{
2317c478bd9Sstevel@tonic-gate 		while (isws(c = locgetc()))
2327c478bd9Sstevel@tonic-gate 			;
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 	else
2357c478bd9Sstevel@tonic-gate 		c = locgetc();
2367c478bd9Sstevel@tonic-gate 	if (c == EOF) {
2377c478bd9Sstevel@tonic-gate 		chcount--;
2387c478bd9Sstevel@tonic-gate 		return(-1);	/* EOF before match */
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate         if (floater != 0) {     /* Handle floating point with
2417c478bd9Sstevel@tonic-gate                                  * file_to_decimal. */
2427c478bd9Sstevel@tonic-gate                 decimal_mode    dm;
2437c478bd9Sstevel@tonic-gate                 decimal_record  dr;
2447c478bd9Sstevel@tonic-gate                 fp_exception_field_type efs;
2457c478bd9Sstevel@tonic-gate                 enum decimal_string_form form;
2467c478bd9Sstevel@tonic-gate                 char           *echar;
2477c478bd9Sstevel@tonic-gate                 int             nread, ic;
2487c478bd9Sstevel@tonic-gate                 char            buffer[1024];
2497c478bd9Sstevel@tonic-gate                 char           *nb = buffer;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate                 locungetc(c);
2527c478bd9Sstevel@tonic-gate 		if (len > 1024)
2537c478bd9Sstevel@tonic-gate 			len = 1024;
2547c478bd9Sstevel@tonic-gate                 file_to_decimal(&nb, len, 0, &dr, &form, &echar, iop, &nread);
2557c478bd9Sstevel@tonic-gate                 if (stow && (form != invalid_form)) {
2567c478bd9Sstevel@tonic-gate                         dm.rd = fp_direction;
2577c478bd9Sstevel@tonic-gate                         if (size == 'l') {      /* double */
2587c478bd9Sstevel@tonic-gate                                 decimal_to_double((double *) va_arg(*listp, double *), &dm, &dr, &efs);
2597c478bd9Sstevel@tonic-gate                         } else if (size == 'L') {      /* quad */
2607c478bd9Sstevel@tonic-gate                                 decimal_to_quadruple((quadruple *)va_arg(*listp, double *), &dm, &dr, &efs);
2617c478bd9Sstevel@tonic-gate                         } else {/* single */
2627c478bd9Sstevel@tonic-gate                                 decimal_to_single((float *) va_arg(*listp, float *), &dm, &dr, &efs);
2637c478bd9Sstevel@tonic-gate                         }
2647c478bd9Sstevel@tonic-gate 			if ((efs & (1 << fp_overflow)) != 0) {
2657c478bd9Sstevel@tonic-gate 				errno = ERANGE;
2667c478bd9Sstevel@tonic-gate 			}
2677c478bd9Sstevel@tonic-gate 			if ((efs & (1 << fp_underflow)) != 0) {
2687c478bd9Sstevel@tonic-gate 				errno = ERANGE;
2697c478bd9Sstevel@tonic-gate                         }
2707c478bd9Sstevel@tonic-gate                 }
2717c478bd9Sstevel@tonic-gate 		chcount += nread;	/* Count characters read. */
2727c478bd9Sstevel@tonic-gate                 c = *nb;        /* Get first unused character. */
2737c478bd9Sstevel@tonic-gate                 ic = c;
2747c478bd9Sstevel@tonic-gate                 if (c == NULL) {
2757c478bd9Sstevel@tonic-gate                         ic = locgetc();
2767c478bd9Sstevel@tonic-gate                         c = ic;
2777c478bd9Sstevel@tonic-gate                         /*
2787c478bd9Sstevel@tonic-gate                          * If null, first unused may have been put back
2797c478bd9Sstevel@tonic-gate                          * already.
2807c478bd9Sstevel@tonic-gate                          */
2817c478bd9Sstevel@tonic-gate                 }
2827c478bd9Sstevel@tonic-gate                 if (ic == EOF) {
2837c478bd9Sstevel@tonic-gate                         chcount--;
2847c478bd9Sstevel@tonic-gate                         flag_eof = 1;
2857c478bd9Sstevel@tonic-gate                 } else if (locungetc(c) == EOF)
2867c478bd9Sstevel@tonic-gate                         flag_eof = 1;
2877c478bd9Sstevel@tonic-gate                 return ((form == invalid_form) ? 0 : 1);        /* successful match if
2887c478bd9Sstevel@tonic-gate                                                                  * non-zero */
2897c478bd9Sstevel@tonic-gate         }
2907c478bd9Sstevel@tonic-gate 	switch(c) {
2917c478bd9Sstevel@tonic-gate 	case '-':
2927c478bd9Sstevel@tonic-gate 		negflg++;
2937c478bd9Sstevel@tonic-gate 		if (type == 'u')
2947c478bd9Sstevel@tonic-gate 			break;
2957c478bd9Sstevel@tonic-gate 	case '+': /* fall-through */
2967c478bd9Sstevel@tonic-gate 		if (--len <= 0)
2977c478bd9Sstevel@tonic-gate 			break;
2987c478bd9Sstevel@tonic-gate 		if ( (c = locgetc()) != '0')
2997c478bd9Sstevel@tonic-gate 			break;
3007c478bd9Sstevel@tonic-gate         case '0':
3017c478bd9Sstevel@tonic-gate                 if ( (type != 'i') || (len <= 1) )
3027c478bd9Sstevel@tonic-gate 		   break;
3037c478bd9Sstevel@tonic-gate 	        if ( ((inchar = locgetc()) == 'x') || (inchar == 'X') )
3047c478bd9Sstevel@tonic-gate 	        {
3057c478bd9Sstevel@tonic-gate 		      /* If not using sscanf and *
3067c478bd9Sstevel@tonic-gate 		       * at the buffer's end     *
3077c478bd9Sstevel@tonic-gate 		       * then LOOK ahead         */
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate                    if ( (iop->_flag & _IOSTRG) || (iop->_cnt != 0) )
3107c478bd9Sstevel@tonic-gate 		      lookahead = locgetc();
3117c478bd9Sstevel@tonic-gate 		   else
3127c478bd9Sstevel@tonic-gate 		   {
3137c478bd9Sstevel@tonic-gate 		      if ( read(fileno(iop),np,1) == 1)
3147c478bd9Sstevel@tonic-gate 		         lookahead = *np;
3157c478bd9Sstevel@tonic-gate                       else
3167c478bd9Sstevel@tonic-gate 		         lookahead = EOF;
3177c478bd9Sstevel@tonic-gate                       chcount += 1;
3187c478bd9Sstevel@tonic-gate                    }
3197c478bd9Sstevel@tonic-gate 		   if ( isxdigit(lookahead) )
3207c478bd9Sstevel@tonic-gate 		   {
3217c478bd9Sstevel@tonic-gate 		       base =16;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 		       if ( len <= 2)
3247c478bd9Sstevel@tonic-gate 		       {
3257c478bd9Sstevel@tonic-gate 			  locungetc(lookahead);
3267c478bd9Sstevel@tonic-gate 			  len -= 1;            /* Take into account the 'x'*/
3277c478bd9Sstevel@tonic-gate                        }
3287c478bd9Sstevel@tonic-gate 		       else
3297c478bd9Sstevel@tonic-gate 		       {
3307c478bd9Sstevel@tonic-gate 		          c = lookahead;
3317c478bd9Sstevel@tonic-gate 			  len -= 2;           /* Take into account '0x'*/
3327c478bd9Sstevel@tonic-gate 		       }
3337c478bd9Sstevel@tonic-gate                    }
3347c478bd9Sstevel@tonic-gate 	           else
3357c478bd9Sstevel@tonic-gate 	           {
3367c478bd9Sstevel@tonic-gate 	               locungetc(lookahead);
3377c478bd9Sstevel@tonic-gate 	               locungetc(inchar);
3387c478bd9Sstevel@tonic-gate                    }
3397c478bd9Sstevel@tonic-gate 		}
3407c478bd9Sstevel@tonic-gate 	        else
3417c478bd9Sstevel@tonic-gate 	        {
3427c478bd9Sstevel@tonic-gate 		    locungetc(inchar);
3437c478bd9Sstevel@tonic-gate 	            base = 8;
3447c478bd9Sstevel@tonic-gate                 }
3457c478bd9Sstevel@tonic-gate 	}
3467c478bd9Sstevel@tonic-gate 	if (!negflg || type != 'u')
3477c478bd9Sstevel@tonic-gate 	    for (; --len  >= 0 ; *np++ = c, c = locgetc())
3487c478bd9Sstevel@tonic-gate 	    {
3497c478bd9Sstevel@tonic-gate 		if (np > numbuf + 62)
3507c478bd9Sstevel@tonic-gate 		{
3517c478bd9Sstevel@tonic-gate 		    errno = ERANGE;
3527c478bd9Sstevel@tonic-gate 		    return(0);
3537c478bd9Sstevel@tonic-gate                 }
3547c478bd9Sstevel@tonic-gate 		if (isdigit(c))
3557c478bd9Sstevel@tonic-gate 		{
356*5d54f3d8Smuffin 			int digit;
3577c478bd9Sstevel@tonic-gate 			digit = c - '0';
3587c478bd9Sstevel@tonic-gate 			if (base == 8)
3597c478bd9Sstevel@tonic-gate 			{
3607c478bd9Sstevel@tonic-gate 				if (digit >= 8)
3617c478bd9Sstevel@tonic-gate 					break;
3627c478bd9Sstevel@tonic-gate 				if (stow)
3637c478bd9Sstevel@tonic-gate 					lcval = (lcval<<3) + digit;
3647c478bd9Sstevel@tonic-gate 			}
3657c478bd9Sstevel@tonic-gate 			else
3667c478bd9Sstevel@tonic-gate 			{
3677c478bd9Sstevel@tonic-gate 				if (stow)
3687c478bd9Sstevel@tonic-gate 				{
3697c478bd9Sstevel@tonic-gate 					if (base == 10)
3707c478bd9Sstevel@tonic-gate 						lcval = (((lcval<<2) + lcval)<<1) + digit;
3717c478bd9Sstevel@tonic-gate 					else /* base == 16 */
3727c478bd9Sstevel@tonic-gate 						lcval = (lcval<<4) + digit;
3737c478bd9Sstevel@tonic-gate 				}
3747c478bd9Sstevel@tonic-gate 			}
3757c478bd9Sstevel@tonic-gate 			digitseen++;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 			continue;
3797c478bd9Sstevel@tonic-gate 		}
3807c478bd9Sstevel@tonic-gate 		else if (base == 16 && isxdigit(c))
3817c478bd9Sstevel@tonic-gate 		{
382*5d54f3d8Smuffin 			int digit;
3837c478bd9Sstevel@tonic-gate 			digit = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
3847c478bd9Sstevel@tonic-gate 			if (stow)
3857c478bd9Sstevel@tonic-gate 				lcval = (lcval<<4) + digit;
3867c478bd9Sstevel@tonic-gate 			digitseen++;
3877c478bd9Sstevel@tonic-gate 			continue;
3887c478bd9Sstevel@tonic-gate 		}
3897c478bd9Sstevel@tonic-gate 		break;
3907c478bd9Sstevel@tonic-gate 	    }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	if (stow && digitseen)
3947c478bd9Sstevel@tonic-gate 		{
3957c478bd9Sstevel@tonic-gate 	 	/* suppress possible overflow on 2's-comp negation */
3967c478bd9Sstevel@tonic-gate 			if (negflg && lcval != HIBITL)
3977c478bd9Sstevel@tonic-gate 				lcval = -lcval;
3987c478bd9Sstevel@tonic-gate 			if (size == 'l')
3997c478bd9Sstevel@tonic-gate 				*va_arg(*listp, long *) = lcval;
4007c478bd9Sstevel@tonic-gate 			else if (size == 'h')
4017c478bd9Sstevel@tonic-gate 				*va_arg(*listp, short *) = (short)lcval;
4027c478bd9Sstevel@tonic-gate 			else
4037c478bd9Sstevel@tonic-gate 				*va_arg(*listp, int *) = (int)lcval;
4047c478bd9Sstevel@tonic-gate 		}
4057c478bd9Sstevel@tonic-gate 	if (c == EOF) {
4067c478bd9Sstevel@tonic-gate 		chcount--;
4077c478bd9Sstevel@tonic-gate 		flag_eof=1;
4087c478bd9Sstevel@tonic-gate 	} else if (locungetc(c) == EOF)
4097c478bd9Sstevel@tonic-gate 		flag_eof=1;
4107c478bd9Sstevel@tonic-gate 	return (digitseen); /* successful match if non-zero */
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate static int
414*5d54f3d8Smuffin string(int stow, int type, int len, char *tab, FILE *iop, va_list *listp)
4157c478bd9Sstevel@tonic-gate {
416*5d54f3d8Smuffin 	int ch;
417*5d54f3d8Smuffin 	char *ptr;
4187c478bd9Sstevel@tonic-gate 	char *start;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	start = ptr = stow ? va_arg(*listp, char *) : NULL;
4217c478bd9Sstevel@tonic-gate 	if (type == 's')
4227c478bd9Sstevel@tonic-gate 	{
4237c478bd9Sstevel@tonic-gate 		if (!flag_eof)
4247c478bd9Sstevel@tonic-gate 		{
4257c478bd9Sstevel@tonic-gate 			while (isws(ch = locgetc()))
4267c478bd9Sstevel@tonic-gate 				;
4277c478bd9Sstevel@tonic-gate 		}
4287c478bd9Sstevel@tonic-gate 		else
4297c478bd9Sstevel@tonic-gate 			ch = locgetc();
4307c478bd9Sstevel@tonic-gate 		if (ch == EOF)
4317c478bd9Sstevel@tonic-gate 			return(-1);	/* EOF before match */
4327c478bd9Sstevel@tonic-gate 		while (ch != EOF && !isws(ch))
4337c478bd9Sstevel@tonic-gate 		{
4347c478bd9Sstevel@tonic-gate 			if (stow)
4357c478bd9Sstevel@tonic-gate 				*ptr = ch;
4367c478bd9Sstevel@tonic-gate 			ptr++;
4377c478bd9Sstevel@tonic-gate 			if (--len <= 0)
4387c478bd9Sstevel@tonic-gate 				break;
4397c478bd9Sstevel@tonic-gate 			ch = locgetc();
4407c478bd9Sstevel@tonic-gate 		}
4417c478bd9Sstevel@tonic-gate 	} else if (type == 'c') {
4427c478bd9Sstevel@tonic-gate 		if (len == MAXINT)
4437c478bd9Sstevel@tonic-gate 			len = 1;
4447c478bd9Sstevel@tonic-gate 		while ( (ch = locgetc()) != EOF)
4457c478bd9Sstevel@tonic-gate 		{
4467c478bd9Sstevel@tonic-gate 			if (stow)
4477c478bd9Sstevel@tonic-gate 				*ptr = ch;
4487c478bd9Sstevel@tonic-gate 			ptr++;
4497c478bd9Sstevel@tonic-gate 			if (--len <= 0)
4507c478bd9Sstevel@tonic-gate 				break;
4517c478bd9Sstevel@tonic-gate 		}
4527c478bd9Sstevel@tonic-gate 	} else { /* type == '[' */
4537c478bd9Sstevel@tonic-gate 		while ( (ch = locgetc()) != EOF && !tab[ch])
4547c478bd9Sstevel@tonic-gate 		{
4557c478bd9Sstevel@tonic-gate 			if (stow)
4567c478bd9Sstevel@tonic-gate 				*ptr = ch;
4577c478bd9Sstevel@tonic-gate 			ptr++;
4587c478bd9Sstevel@tonic-gate 			if (--len <= 0)
4597c478bd9Sstevel@tonic-gate 				break;
4607c478bd9Sstevel@tonic-gate 		}
4617c478bd9Sstevel@tonic-gate 	}
4627c478bd9Sstevel@tonic-gate 	if (ch == EOF )
4637c478bd9Sstevel@tonic-gate 	{
4647c478bd9Sstevel@tonic-gate 		chcount-=1;
4657c478bd9Sstevel@tonic-gate 		flag_eof = 1;
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 	else if (len > 0 && locungetc(ch) == EOF)
4687c478bd9Sstevel@tonic-gate 		flag_eof = 1;
4697c478bd9Sstevel@tonic-gate 	if (ptr == start)
4707c478bd9Sstevel@tonic-gate 		return(0); /* no match */
4717c478bd9Sstevel@tonic-gate 	if (stow && type != 'c')
4727c478bd9Sstevel@tonic-gate 		*ptr = '\0';
4737c478bd9Sstevel@tonic-gate 	return (1); /* successful match */
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate static unsigned char *
477*5d54f3d8Smuffin setup(unsigned char *fmt, char *tab)
4787c478bd9Sstevel@tonic-gate {
479*5d54f3d8Smuffin 	int b, c, d, t = 0;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (*fmt == '^')
4827c478bd9Sstevel@tonic-gate 	{
4837c478bd9Sstevel@tonic-gate 		t++;
4847c478bd9Sstevel@tonic-gate 		fmt++;
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 	(void) memset(tab, !t, NCHARS);
4877c478bd9Sstevel@tonic-gate 	if ( (c = *fmt) == ']' || c == '-')  /* first char is special */
4887c478bd9Sstevel@tonic-gate 	{
4897c478bd9Sstevel@tonic-gate 		tab[c] = t;
4907c478bd9Sstevel@tonic-gate 		fmt++;
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 	while ( (c = *fmt++) != ']')
4937c478bd9Sstevel@tonic-gate 	{
4947c478bd9Sstevel@tonic-gate 		if (c == '\0')
4957c478bd9Sstevel@tonic-gate 			return(NULL); /* unexpected end of format */
4967c478bd9Sstevel@tonic-gate 		if (c == '-' && (d = *fmt) != ']' && (b = fmt[-2]) < d)
4977c478bd9Sstevel@tonic-gate 		{
4987c478bd9Sstevel@tonic-gate 			(void) memset(&tab[b], t, d - b + 1);
4997c478bd9Sstevel@tonic-gate 			fmt++;
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 		else
5027c478bd9Sstevel@tonic-gate 			tab[c] = t;
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 	return (fmt);
5057c478bd9Sstevel@tonic-gate }
506