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