xref: /onnv-gate/usr/src/lib/libbc/libc/stdio/common/scanf.c (revision 722:636b850d4ee9)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*722Smuffin /*
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 
300Sstevel@tonic-gate #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 <errno.h>
37*722Smuffin #include <string.h>
38*722Smuffin #include <malloc.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #define ON	1
410Sstevel@tonic-gate #define OFF	0
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #define ARGMAX  64
440Sstevel@tonic-gate static unsigned char newap[ARGMAX * sizeof(double)];
450Sstevel@tonic-gate static unsigned char newform[256];
460Sstevel@tonic-gate 
470Sstevel@tonic-gate extern int _doscan();
480Sstevel@tonic-gate 
49*722Smuffin static int	format_arg(unsigned char *, unsigned char *, unsigned char *);
50*722Smuffin 
510Sstevel@tonic-gate int
scanf(char * fmt,...)52*722Smuffin scanf(char *fmt, ...)
53*722Smuffin {
54*722Smuffin 	va_list ap;
55*722Smuffin 	char *nf;
56*722Smuffin 	int ret_val;
57*722Smuffin 
58*722Smuffin 
59*722Smuffin 	va_start(ap, fmt);
60*722Smuffin 	if (strlen(fmt) >= sizeof(newform)) {
61*722Smuffin 		nf = malloc(strlen(fmt)+1);
62*722Smuffin 		if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
63*722Smuffin 		    == ON) {
64*722Smuffin 			va_end(ap);
65*722Smuffin 			ret_val = _doscan(stdin, nf, newap);
66*722Smuffin 			free(nf);
67*722Smuffin 			return(ret_val);
68*722Smuffin 		}
69*722Smuffin 		free(nf);
70*722Smuffin 	} else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
71*722Smuffin 	    == ON) {
72*722Smuffin 		va_end(ap);
73*722Smuffin 		return(_doscan(stdin, newform, newap));
74*722Smuffin 	}
75*722Smuffin 	ret_val = _doscan(stdin, fmt, ap);
76*722Smuffin 	va_end(ap);
77*722Smuffin 	return (ret_val);
78*722Smuffin }
79*722Smuffin 
80*722Smuffin int
fscanf(FILE * iop,char * fmt,...)81*722Smuffin fscanf(FILE *iop, char *fmt, ...)
820Sstevel@tonic-gate {
830Sstevel@tonic-gate 	va_list ap;
840Sstevel@tonic-gate 	char *nf;
850Sstevel@tonic-gate 	int ret_val;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate #ifdef POSIX
880Sstevel@tonic-gate         if ( !(iop->_flag & (_IOREAD|_IORW)) ) {
890Sstevel@tonic-gate                 iop->_flag |= _IOERR;
900Sstevel@tonic-gate                 errno = EBADF;
910Sstevel@tonic-gate                 return (EOF);
920Sstevel@tonic-gate         }
93*722Smuffin #endif	/* POSIX */
94*722Smuffin 	va_start(ap, fmt);
950Sstevel@tonic-gate 	if (strlen(fmt) >= sizeof(newform)) {
960Sstevel@tonic-gate 		nf = malloc(strlen(fmt)+1);
97*722Smuffin 		if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
98*722Smuffin 		    == ON) {
99*722Smuffin 			va_end(ap);
1000Sstevel@tonic-gate 			ret_val = _doscan(stdin, nf, newap);
1010Sstevel@tonic-gate 			free(nf);
1020Sstevel@tonic-gate 			return(ret_val);
1030Sstevel@tonic-gate 		}
1040Sstevel@tonic-gate 		free(nf);
105*722Smuffin 	} else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
106*722Smuffin 	    == ON) {
107*722Smuffin 		va_end(ap);
1080Sstevel@tonic-gate 		return(_doscan(iop, newform, newap));
1090Sstevel@tonic-gate 	}
110*722Smuffin 	ret_val = _doscan(iop, fmt, ap);
111*722Smuffin 	va_end(ap);
112*722Smuffin 	return (ret_val);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate int
sscanf(char * str,char * fmt,...)116*722Smuffin sscanf(char *str, char *fmt, ...)
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate 	va_list ap;
1190Sstevel@tonic-gate 	FILE strbuf;
1200Sstevel@tonic-gate 	char *nf;
1210Sstevel@tonic-gate 	int ret_val;
1220Sstevel@tonic-gate 
123*722Smuffin 	va_start(ap, fmt);
1240Sstevel@tonic-gate 	strbuf._flag = _IOREAD|_IOSTRG;
1250Sstevel@tonic-gate 	strbuf._ptr = strbuf._base = (unsigned char*)str;
1260Sstevel@tonic-gate 	strbuf._cnt = strlen(str);
1270Sstevel@tonic-gate 	strbuf._bufsiz = strbuf._cnt;
1280Sstevel@tonic-gate 	if (strlen(fmt) >= sizeof(newform)) {
1290Sstevel@tonic-gate 		nf = malloc(strlen(fmt)+1);
130*722Smuffin 		if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
131*722Smuffin 		    == ON) {
132*722Smuffin 			va_end(ap);
1330Sstevel@tonic-gate 			ret_val = _doscan(stdin, nf, newap);
1340Sstevel@tonic-gate 			free(nf);
1350Sstevel@tonic-gate 			return(ret_val);
1360Sstevel@tonic-gate 		}
1370Sstevel@tonic-gate 		free(nf);
138*722Smuffin 	} else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
139*722Smuffin 	    == ON) {
140*722Smuffin 		va_end(ap);
1410Sstevel@tonic-gate 		return(_doscan(&strbuf, newform, newap));
1420Sstevel@tonic-gate 	}
143*722Smuffin 	ret_val = _doscan(&strbuf, fmt, ap);
144*722Smuffin 	va_end(ap);
145*722Smuffin 	return (ret_val);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate  * This function reorganises the format string and argument list.
1500Sstevel@tonic-gate  */
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate #ifndef NL_ARGMAX
1540Sstevel@tonic-gate #define NL_ARGMAX	9
1550Sstevel@tonic-gate #endif
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate struct al {
1580Sstevel@tonic-gate 	int a_num;		/* arg # specified at this position */
1590Sstevel@tonic-gate 	unsigned char *a_start;	/* ptr to 'n' part of '%n$' in format str */
1600Sstevel@tonic-gate 	unsigned char *a_end;	/* ptr to '$'+1 part of '%n$' in format str */
1610Sstevel@tonic-gate 	int *a_val;		/* pointers to arguments */
1620Sstevel@tonic-gate };
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate static int
format_arg(unsigned char * format,unsigned char * list,unsigned char * newlist)165*722Smuffin format_arg(unsigned char *format, unsigned char *list, unsigned char *newlist)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate 	unsigned char *aptr, *bptr, *cptr;
168*722Smuffin 	int i, fcode, nl_fmt, num, length, j;
1690Sstevel@tonic-gate 	unsigned char *fmtsav;
1700Sstevel@tonic-gate 	struct al args[ARGMAX + 1];
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate #ifdef VTEST
1730Sstevel@tonic-gate 	{
1740Sstevel@tonic-gate 		int fd;
1750Sstevel@tonic-gate 		fd = creat("/tmp/SCANF", 0666);
1760Sstevel@tonic-gate 	}
1770Sstevel@tonic-gate #endif
1780Sstevel@tonic-gate 	for (i = 0; i <= ARGMAX; args[i++].a_num = 0);
1790Sstevel@tonic-gate 	nl_fmt = 0;
1800Sstevel@tonic-gate 	i = j = 1;
1810Sstevel@tonic-gate 	while (*format) {
1820Sstevel@tonic-gate 		while ((fcode = *format++) != '\0' && fcode != '%') ;
1830Sstevel@tonic-gate 		if (!fcode || i > ARGMAX)
1840Sstevel@tonic-gate 			break;
1850Sstevel@tonic-gate 	charswitch:
1860Sstevel@tonic-gate 		switch (fcode = *format++) {
1870Sstevel@tonic-gate 		case 'l':
1880Sstevel@tonic-gate 		case 'h':
1890Sstevel@tonic-gate 			goto charswitch;
1900Sstevel@tonic-gate 		case '0': case '1': case '2':
1910Sstevel@tonic-gate 		case '3': case '4': case '5':
1920Sstevel@tonic-gate 		case '6': case '7': case '8':
1930Sstevel@tonic-gate 		case '9':
1940Sstevel@tonic-gate 			num = fcode - '0';
1950Sstevel@tonic-gate 			fmtsav = format;
1960Sstevel@tonic-gate 			while (isdigit(fcode = *format)) {
1970Sstevel@tonic-gate 				num = num * 10 + fcode - '0';
1980Sstevel@tonic-gate 				format++;
1990Sstevel@tonic-gate 			}
2000Sstevel@tonic-gate 			if (*format == '$') {
2010Sstevel@tonic-gate 				nl_fmt++;
2020Sstevel@tonic-gate 				args[i].a_start = fmtsav - 1;
2030Sstevel@tonic-gate 				args[i].a_end = ++format;
2040Sstevel@tonic-gate 				if (num > NL_ARGMAX)
2050Sstevel@tonic-gate 					num = num;
2060Sstevel@tonic-gate 				args[i].a_num = num;
2070Sstevel@tonic-gate 			}
2080Sstevel@tonic-gate 			goto charswitch;
2090Sstevel@tonic-gate 	/* now have arg type only to parse */
2100Sstevel@tonic-gate 		case 'd': case 'u': case 'o':
2110Sstevel@tonic-gate 		case 'x': case 'e': case 'f':
2120Sstevel@tonic-gate 		case 'g': case 'c': case '[':
2130Sstevel@tonic-gate 		case 's':
2140Sstevel@tonic-gate 			if (nl_fmt == 0)
2150Sstevel@tonic-gate 				return(OFF);
2160Sstevel@tonic-gate 			if (!args[i].a_num) {
2170Sstevel@tonic-gate 				args[i].a_start = args[i].a_end = format - 1;
2180Sstevel@tonic-gate 				args[i].a_num = j++;
2190Sstevel@tonic-gate 			}
2200Sstevel@tonic-gate 			i++;
2210Sstevel@tonic-gate 			break;
2220Sstevel@tonic-gate 		case '*':
2230Sstevel@tonic-gate 		case '%':
2240Sstevel@tonic-gate 			break;
2250Sstevel@tonic-gate 		default:
2260Sstevel@tonic-gate 			format--;
2270Sstevel@tonic-gate 			break;
2280Sstevel@tonic-gate 		}
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 	length = i;
2310Sstevel@tonic-gate 	if (nl_fmt == 0)
2320Sstevel@tonic-gate 		return (OFF);
2330Sstevel@tonic-gate 	for (i = 1; i < length && args[i].a_num == 0; i++);
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	/*
2360Sstevel@tonic-gate 	 * Reformat the format string
2370Sstevel@tonic-gate 	 */
2380Sstevel@tonic-gate 	cptr = aptr = args[i].a_start;
2390Sstevel@tonic-gate 	do {
2400Sstevel@tonic-gate 		bptr = args[i++].a_end;
2410Sstevel@tonic-gate 		for (; i < length && args[i].a_num == 0; i++);
2420Sstevel@tonic-gate 		if (i == length)
2430Sstevel@tonic-gate 			while (*cptr++);
2440Sstevel@tonic-gate 		else
2450Sstevel@tonic-gate 			cptr = args[i].a_start;
2460Sstevel@tonic-gate 		for (; bptr != cptr; *aptr++ = *bptr++);
2470Sstevel@tonic-gate 	} while (i < length);
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	/*
2500Sstevel@tonic-gate 	 * Create arglist
2510Sstevel@tonic-gate 	 * assuming that pointer to all variable type have
2520Sstevel@tonic-gate 	 * same size.
2530Sstevel@tonic-gate 	 */
2540Sstevel@tonic-gate 	for (i = 1; i < length; i++)
2550Sstevel@tonic-gate 		args[i].a_val = ((int **)(list += sizeof(int *)))[-1];
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	for (i = 1; i < length; i++) {
2580Sstevel@tonic-gate 		int **ptr;
2590Sstevel@tonic-gate 		ptr = (int **)newlist;
2600Sstevel@tonic-gate 		*ptr = args[args[i].a_num].a_val;
2610Sstevel@tonic-gate 		newlist += sizeof(int *);
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 	return(ON);
2640Sstevel@tonic-gate }
265