xref: /titanic_51/usr/src/lib/libbc/libc/stdio/common/scanf.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 
307c478bd9Sstevel@tonic-gate #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 <errno.h>
37*5d54f3d8Smuffin #include <string.h>
38*5d54f3d8Smuffin #include <malloc.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #define ON	1
417c478bd9Sstevel@tonic-gate #define OFF	0
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #define ARGMAX  64
447c478bd9Sstevel@tonic-gate static unsigned char newap[ARGMAX * sizeof(double)];
457c478bd9Sstevel@tonic-gate static unsigned char newform[256];
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate extern int _doscan();
487c478bd9Sstevel@tonic-gate 
49*5d54f3d8Smuffin static int	format_arg(unsigned char *, unsigned char *, unsigned char *);
50*5d54f3d8Smuffin 
517c478bd9Sstevel@tonic-gate int
52*5d54f3d8Smuffin scanf(char *fmt, ...)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	va_list ap;
557c478bd9Sstevel@tonic-gate 	char *nf;
567c478bd9Sstevel@tonic-gate 	int ret_val;
577c478bd9Sstevel@tonic-gate 
58*5d54f3d8Smuffin 
59*5d54f3d8Smuffin 	va_start(ap, fmt);
607c478bd9Sstevel@tonic-gate 	if (strlen(fmt) >= sizeof(newform)) {
617c478bd9Sstevel@tonic-gate 		nf = malloc(strlen(fmt)+1);
62*5d54f3d8Smuffin 		if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
63*5d54f3d8Smuffin 		    == ON) {
64*5d54f3d8Smuffin 			va_end(ap);
657c478bd9Sstevel@tonic-gate 			ret_val = _doscan(stdin, nf, newap);
667c478bd9Sstevel@tonic-gate 			free(nf);
677c478bd9Sstevel@tonic-gate 			return(ret_val);
687c478bd9Sstevel@tonic-gate 		}
697c478bd9Sstevel@tonic-gate 		free(nf);
70*5d54f3d8Smuffin 	} else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
71*5d54f3d8Smuffin 	    == ON) {
72*5d54f3d8Smuffin 		va_end(ap);
737c478bd9Sstevel@tonic-gate 		return(_doscan(stdin, newform, newap));
747c478bd9Sstevel@tonic-gate 	}
75*5d54f3d8Smuffin 	ret_val = _doscan(stdin, fmt, ap);
76*5d54f3d8Smuffin 	va_end(ap);
77*5d54f3d8Smuffin 	return (ret_val);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate int
81*5d54f3d8Smuffin fscanf(FILE *iop, char *fmt, ...)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	va_list ap;
847c478bd9Sstevel@tonic-gate 	char *nf;
857c478bd9Sstevel@tonic-gate 	int ret_val;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate #ifdef POSIX
887c478bd9Sstevel@tonic-gate         if ( !(iop->_flag & (_IOREAD|_IORW)) ) {
897c478bd9Sstevel@tonic-gate                 iop->_flag |= _IOERR;
907c478bd9Sstevel@tonic-gate                 errno = EBADF;
917c478bd9Sstevel@tonic-gate                 return (EOF);
927c478bd9Sstevel@tonic-gate         }
93*5d54f3d8Smuffin #endif	/* POSIX */
94*5d54f3d8Smuffin 	va_start(ap, fmt);
957c478bd9Sstevel@tonic-gate 	if (strlen(fmt) >= sizeof(newform)) {
967c478bd9Sstevel@tonic-gate 		nf = malloc(strlen(fmt)+1);
97*5d54f3d8Smuffin 		if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
98*5d54f3d8Smuffin 		    == ON) {
99*5d54f3d8Smuffin 			va_end(ap);
1007c478bd9Sstevel@tonic-gate 			ret_val = _doscan(stdin, nf, newap);
1017c478bd9Sstevel@tonic-gate 			free(nf);
1027c478bd9Sstevel@tonic-gate 			return(ret_val);
1037c478bd9Sstevel@tonic-gate 		}
1047c478bd9Sstevel@tonic-gate 		free(nf);
105*5d54f3d8Smuffin 	} else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
106*5d54f3d8Smuffin 	    == ON) {
107*5d54f3d8Smuffin 		va_end(ap);
1087c478bd9Sstevel@tonic-gate 		return(_doscan(iop, newform, newap));
1097c478bd9Sstevel@tonic-gate 	}
110*5d54f3d8Smuffin 	ret_val = _doscan(iop, fmt, ap);
111*5d54f3d8Smuffin 	va_end(ap);
112*5d54f3d8Smuffin 	return (ret_val);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate int
116*5d54f3d8Smuffin sscanf(char *str, char *fmt, ...)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate 	va_list ap;
1197c478bd9Sstevel@tonic-gate 	FILE strbuf;
1207c478bd9Sstevel@tonic-gate 	char *nf;
1217c478bd9Sstevel@tonic-gate 	int ret_val;
1227c478bd9Sstevel@tonic-gate 
123*5d54f3d8Smuffin 	va_start(ap, fmt);
1247c478bd9Sstevel@tonic-gate 	strbuf._flag = _IOREAD|_IOSTRG;
1257c478bd9Sstevel@tonic-gate 	strbuf._ptr = strbuf._base = (unsigned char*)str;
1267c478bd9Sstevel@tonic-gate 	strbuf._cnt = strlen(str);
1277c478bd9Sstevel@tonic-gate 	strbuf._bufsiz = strbuf._cnt;
1287c478bd9Sstevel@tonic-gate 	if (strlen(fmt) >= sizeof(newform)) {
1297c478bd9Sstevel@tonic-gate 		nf = malloc(strlen(fmt)+1);
130*5d54f3d8Smuffin 		if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
131*5d54f3d8Smuffin 		    == ON) {
132*5d54f3d8Smuffin 			va_end(ap);
1337c478bd9Sstevel@tonic-gate 			ret_val = _doscan(stdin, nf, newap);
1347c478bd9Sstevel@tonic-gate 			free(nf);
1357c478bd9Sstevel@tonic-gate 			return(ret_val);
1367c478bd9Sstevel@tonic-gate 		}
1377c478bd9Sstevel@tonic-gate 		free(nf);
138*5d54f3d8Smuffin 	} else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
139*5d54f3d8Smuffin 	    == ON) {
140*5d54f3d8Smuffin 		va_end(ap);
1417c478bd9Sstevel@tonic-gate 		return(_doscan(&strbuf, newform, newap));
1427c478bd9Sstevel@tonic-gate 	}
143*5d54f3d8Smuffin 	ret_val = _doscan(&strbuf, fmt, ap);
144*5d54f3d8Smuffin 	va_end(ap);
145*5d54f3d8Smuffin 	return (ret_val);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate  * This function reorganises the format string and argument list.
1507c478bd9Sstevel@tonic-gate  */
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate #ifndef NL_ARGMAX
1547c478bd9Sstevel@tonic-gate #define NL_ARGMAX	9
1557c478bd9Sstevel@tonic-gate #endif
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate struct al {
1587c478bd9Sstevel@tonic-gate 	int a_num;		/* arg # specified at this position */
1597c478bd9Sstevel@tonic-gate 	unsigned char *a_start;	/* ptr to 'n' part of '%n$' in format str */
1607c478bd9Sstevel@tonic-gate 	unsigned char *a_end;	/* ptr to '$'+1 part of '%n$' in format str */
1617c478bd9Sstevel@tonic-gate 	int *a_val;		/* pointers to arguments */
1627c478bd9Sstevel@tonic-gate };
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate static int
165*5d54f3d8Smuffin format_arg(unsigned char *format, unsigned char *list, unsigned char *newlist)
1667c478bd9Sstevel@tonic-gate {
1677c478bd9Sstevel@tonic-gate 	unsigned char *aptr, *bptr, *cptr;
168*5d54f3d8Smuffin 	int i, fcode, nl_fmt, num, length, j;
1697c478bd9Sstevel@tonic-gate 	unsigned char *fmtsav;
1707c478bd9Sstevel@tonic-gate 	struct al args[ARGMAX + 1];
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate #ifdef VTEST
1737c478bd9Sstevel@tonic-gate 	{
1747c478bd9Sstevel@tonic-gate 		int fd;
1757c478bd9Sstevel@tonic-gate 		fd = creat("/tmp/SCANF", 0666);
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate #endif
1787c478bd9Sstevel@tonic-gate 	for (i = 0; i <= ARGMAX; args[i++].a_num = 0);
1797c478bd9Sstevel@tonic-gate 	nl_fmt = 0;
1807c478bd9Sstevel@tonic-gate 	i = j = 1;
1817c478bd9Sstevel@tonic-gate 	while (*format) {
1827c478bd9Sstevel@tonic-gate 		while ((fcode = *format++) != '\0' && fcode != '%') ;
1837c478bd9Sstevel@tonic-gate 		if (!fcode || i > ARGMAX)
1847c478bd9Sstevel@tonic-gate 			break;
1857c478bd9Sstevel@tonic-gate 	charswitch:
1867c478bd9Sstevel@tonic-gate 		switch (fcode = *format++) {
1877c478bd9Sstevel@tonic-gate 		case 'l':
1887c478bd9Sstevel@tonic-gate 		case 'h':
1897c478bd9Sstevel@tonic-gate 			goto charswitch;
1907c478bd9Sstevel@tonic-gate 		case '0': case '1': case '2':
1917c478bd9Sstevel@tonic-gate 		case '3': case '4': case '5':
1927c478bd9Sstevel@tonic-gate 		case '6': case '7': case '8':
1937c478bd9Sstevel@tonic-gate 		case '9':
1947c478bd9Sstevel@tonic-gate 			num = fcode - '0';
1957c478bd9Sstevel@tonic-gate 			fmtsav = format;
1967c478bd9Sstevel@tonic-gate 			while (isdigit(fcode = *format)) {
1977c478bd9Sstevel@tonic-gate 				num = num * 10 + fcode - '0';
1987c478bd9Sstevel@tonic-gate 				format++;
1997c478bd9Sstevel@tonic-gate 			}
2007c478bd9Sstevel@tonic-gate 			if (*format == '$') {
2017c478bd9Sstevel@tonic-gate 				nl_fmt++;
2027c478bd9Sstevel@tonic-gate 				args[i].a_start = fmtsav - 1;
2037c478bd9Sstevel@tonic-gate 				args[i].a_end = ++format;
2047c478bd9Sstevel@tonic-gate 				if (num > NL_ARGMAX)
2057c478bd9Sstevel@tonic-gate 					num = num;
2067c478bd9Sstevel@tonic-gate 				args[i].a_num = num;
2077c478bd9Sstevel@tonic-gate 			}
2087c478bd9Sstevel@tonic-gate 			goto charswitch;
2097c478bd9Sstevel@tonic-gate 	/* now have arg type only to parse */
2107c478bd9Sstevel@tonic-gate 		case 'd': case 'u': case 'o':
2117c478bd9Sstevel@tonic-gate 		case 'x': case 'e': case 'f':
2127c478bd9Sstevel@tonic-gate 		case 'g': case 'c': case '[':
2137c478bd9Sstevel@tonic-gate 		case 's':
2147c478bd9Sstevel@tonic-gate 			if (nl_fmt == 0)
2157c478bd9Sstevel@tonic-gate 				return(OFF);
2167c478bd9Sstevel@tonic-gate 			if (!args[i].a_num) {
2177c478bd9Sstevel@tonic-gate 				args[i].a_start = args[i].a_end = format - 1;
2187c478bd9Sstevel@tonic-gate 				args[i].a_num = j++;
2197c478bd9Sstevel@tonic-gate 			}
2207c478bd9Sstevel@tonic-gate 			i++;
2217c478bd9Sstevel@tonic-gate 			break;
2227c478bd9Sstevel@tonic-gate 		case '*':
2237c478bd9Sstevel@tonic-gate 		case '%':
2247c478bd9Sstevel@tonic-gate 			break;
2257c478bd9Sstevel@tonic-gate 		default:
2267c478bd9Sstevel@tonic-gate 			format--;
2277c478bd9Sstevel@tonic-gate 			break;
2287c478bd9Sstevel@tonic-gate 		}
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 	length = i;
2317c478bd9Sstevel@tonic-gate 	if (nl_fmt == 0)
2327c478bd9Sstevel@tonic-gate 		return (OFF);
2337c478bd9Sstevel@tonic-gate 	for (i = 1; i < length && args[i].a_num == 0; i++);
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	/*
2367c478bd9Sstevel@tonic-gate 	 * Reformat the format string
2377c478bd9Sstevel@tonic-gate 	 */
2387c478bd9Sstevel@tonic-gate 	cptr = aptr = args[i].a_start;
2397c478bd9Sstevel@tonic-gate 	do {
2407c478bd9Sstevel@tonic-gate 		bptr = args[i++].a_end;
2417c478bd9Sstevel@tonic-gate 		for (; i < length && args[i].a_num == 0; i++);
2427c478bd9Sstevel@tonic-gate 		if (i == length)
2437c478bd9Sstevel@tonic-gate 			while (*cptr++);
2447c478bd9Sstevel@tonic-gate 		else
2457c478bd9Sstevel@tonic-gate 			cptr = args[i].a_start;
2467c478bd9Sstevel@tonic-gate 		for (; bptr != cptr; *aptr++ = *bptr++);
2477c478bd9Sstevel@tonic-gate 	} while (i < length);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	/*
2507c478bd9Sstevel@tonic-gate 	 * Create arglist
2517c478bd9Sstevel@tonic-gate 	 * assuming that pointer to all variable type have
2527c478bd9Sstevel@tonic-gate 	 * same size.
2537c478bd9Sstevel@tonic-gate 	 */
2547c478bd9Sstevel@tonic-gate 	for (i = 1; i < length; i++)
2557c478bd9Sstevel@tonic-gate 		args[i].a_val = ((int **)(list += sizeof(int *)))[-1];
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	for (i = 1; i < length; i++) {
2587c478bd9Sstevel@tonic-gate 		int **ptr;
2597c478bd9Sstevel@tonic-gate 		ptr = (int **)newlist;
2607c478bd9Sstevel@tonic-gate 		*ptr = args[args[i].a_num].a_val;
2617c478bd9Sstevel@tonic-gate 		newlist += sizeof(int *);
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 	return(ON);
2647c478bd9Sstevel@tonic-gate }
265