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