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