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
_doscan(FILE * iop,unsigned char * fmt,va_list va_alist)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
number(int stow,int type,int len,int size,FILE * iop,va_list * listp)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
string(int stow,int type,int len,char * tab,FILE * iop,va_list * listp)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 *
setup(unsigned char * fmt,char * tab)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