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 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 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 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 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