1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984 AT&T */
28 /* All Rights Reserved */
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32 /*LINTLIBRARY*/
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <stdarg.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <malloc.h>
39
40 #define ON 1
41 #define OFF 0
42
43 #define ARGMAX 64
44 static unsigned char newap[ARGMAX * sizeof(double)];
45 static unsigned char newform[256];
46
47 extern int _doscan();
48
49 static int format_arg(unsigned char *, unsigned char *, unsigned char *);
50
51 int
scanf(char * fmt,...)52 scanf(char *fmt, ...)
53 {
54 va_list ap;
55 char *nf;
56 int ret_val;
57
58
59 va_start(ap, fmt);
60 if (strlen(fmt) >= sizeof(newform)) {
61 nf = malloc(strlen(fmt)+1);
62 if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
63 == ON) {
64 va_end(ap);
65 ret_val = _doscan(stdin, nf, newap);
66 free(nf);
67 return(ret_val);
68 }
69 free(nf);
70 } else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
71 == ON) {
72 va_end(ap);
73 return(_doscan(stdin, newform, newap));
74 }
75 ret_val = _doscan(stdin, fmt, ap);
76 va_end(ap);
77 return (ret_val);
78 }
79
80 int
fscanf(FILE * iop,char * fmt,...)81 fscanf(FILE *iop, char *fmt, ...)
82 {
83 va_list ap;
84 char *nf;
85 int ret_val;
86
87 #ifdef POSIX
88 if ( !(iop->_flag & (_IOREAD|_IORW)) ) {
89 iop->_flag |= _IOERR;
90 errno = EBADF;
91 return (EOF);
92 }
93 #endif /* POSIX */
94 va_start(ap, fmt);
95 if (strlen(fmt) >= sizeof(newform)) {
96 nf = malloc(strlen(fmt)+1);
97 if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
98 == ON) {
99 va_end(ap);
100 ret_val = _doscan(stdin, nf, newap);
101 free(nf);
102 return(ret_val);
103 }
104 free(nf);
105 } else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
106 == ON) {
107 va_end(ap);
108 return(_doscan(iop, newform, newap));
109 }
110 ret_val = _doscan(iop, fmt, ap);
111 va_end(ap);
112 return (ret_val);
113 }
114
115 int
sscanf(char * str,char * fmt,...)116 sscanf(char *str, char *fmt, ...)
117 {
118 va_list ap;
119 FILE strbuf;
120 char *nf;
121 int ret_val;
122
123 va_start(ap, fmt);
124 strbuf._flag = _IOREAD|_IOSTRG;
125 strbuf._ptr = strbuf._base = (unsigned char*)str;
126 strbuf._cnt = strlen(str);
127 strbuf._bufsiz = strbuf._cnt;
128 if (strlen(fmt) >= sizeof(newform)) {
129 nf = malloc(strlen(fmt)+1);
130 if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
131 == ON) {
132 va_end(ap);
133 ret_val = _doscan(stdin, nf, newap);
134 free(nf);
135 return(ret_val);
136 }
137 free(nf);
138 } else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
139 == ON) {
140 va_end(ap);
141 return(_doscan(&strbuf, newform, newap));
142 }
143 ret_val = _doscan(&strbuf, fmt, ap);
144 va_end(ap);
145 return (ret_val);
146 }
147
148 /*
149 * This function reorganises the format string and argument list.
150 */
151
152
153 #ifndef NL_ARGMAX
154 #define NL_ARGMAX 9
155 #endif
156
157 struct al {
158 int a_num; /* arg # specified at this position */
159 unsigned char *a_start; /* ptr to 'n' part of '%n$' in format str */
160 unsigned char *a_end; /* ptr to '$'+1 part of '%n$' in format str */
161 int *a_val; /* pointers to arguments */
162 };
163
164 static int
format_arg(unsigned char * format,unsigned char * list,unsigned char * newlist)165 format_arg(unsigned char *format, unsigned char *list, unsigned char *newlist)
166 {
167 unsigned char *aptr, *bptr, *cptr;
168 int i, fcode, nl_fmt, num, length, j;
169 unsigned char *fmtsav;
170 struct al args[ARGMAX + 1];
171
172 #ifdef VTEST
173 {
174 int fd;
175 fd = creat("/tmp/SCANF", 0666);
176 }
177 #endif
178 for (i = 0; i <= ARGMAX; args[i++].a_num = 0);
179 nl_fmt = 0;
180 i = j = 1;
181 while (*format) {
182 while ((fcode = *format++) != '\0' && fcode != '%') ;
183 if (!fcode || i > ARGMAX)
184 break;
185 charswitch:
186 switch (fcode = *format++) {
187 case 'l':
188 case 'h':
189 goto charswitch;
190 case '0': case '1': case '2':
191 case '3': case '4': case '5':
192 case '6': case '7': case '8':
193 case '9':
194 num = fcode - '0';
195 fmtsav = format;
196 while (isdigit(fcode = *format)) {
197 num = num * 10 + fcode - '0';
198 format++;
199 }
200 if (*format == '$') {
201 nl_fmt++;
202 args[i].a_start = fmtsav - 1;
203 args[i].a_end = ++format;
204 if (num > NL_ARGMAX)
205 num = num;
206 args[i].a_num = num;
207 }
208 goto charswitch;
209 /* now have arg type only to parse */
210 case 'd': case 'u': case 'o':
211 case 'x': case 'e': case 'f':
212 case 'g': case 'c': case '[':
213 case 's':
214 if (nl_fmt == 0)
215 return(OFF);
216 if (!args[i].a_num) {
217 args[i].a_start = args[i].a_end = format - 1;
218 args[i].a_num = j++;
219 }
220 i++;
221 break;
222 case '*':
223 case '%':
224 break;
225 default:
226 format--;
227 break;
228 }
229 }
230 length = i;
231 if (nl_fmt == 0)
232 return (OFF);
233 for (i = 1; i < length && args[i].a_num == 0; i++);
234
235 /*
236 * Reformat the format string
237 */
238 cptr = aptr = args[i].a_start;
239 do {
240 bptr = args[i++].a_end;
241 for (; i < length && args[i].a_num == 0; i++);
242 if (i == length)
243 while (*cptr++);
244 else
245 cptr = args[i].a_start;
246 for (; bptr != cptr; *aptr++ = *bptr++);
247 } while (i < length);
248
249 /*
250 * Create arglist
251 * assuming that pointer to all variable type have
252 * same size.
253 */
254 for (i = 1; i < length; i++)
255 args[i].a_val = ((int **)(list += sizeof(int *)))[-1];
256
257 for (i = 1; i < length; i++) {
258 int **ptr;
259 ptr = (int **)newlist;
260 *ptr = args[args[i].a_num].a_val;
261 newlist += sizeof(int *);
262 }
263 return(ON);
264 }
265