Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / lib / libc / stdio / vfscanf.c
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 #include "string.h"
14 #include "ctype.h"
15 #include "stdlib.h"
16 #include "stdio.h"
17 #include "unistd.h"
18
19
20 static int
21 _getc(FILE * stream)
22 {
23         int count;
24         char c;
25
26         if (stream->mode == _IONBF || stream->buf == NULL) {
27                 if (read(stream->fd, &c, 1) == 1)
28                         return (int) c;
29                 else
30                         return EOF;
31         }
32
33         if (stream->pos == 0 || stream->pos >= BUFSIZ ||
34             stream->buf[stream->pos] == '\0') {
35                 count = read(stream->fd, stream->buf, BUFSIZ);
36                 if (count < 0)
37                         count = 0;
38                 if (count < BUFSIZ)
39                         stream->buf[count] = '\0';
40                 stream->pos = 0;
41         }
42
43         return stream->buf[stream->pos++];
44 }
45
46 static void
47 _ungetc(int ch, FILE * stream)
48 {
49         if (stream->mode != _IONBF && stream->pos > 0)
50                 stream->pos--;
51 }
52
53 static int
54 _is_voidage(int ch)
55 {
56         if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\0')
57                 return 1;
58         else
59                 return 0;
60 }
61
62
63 static int
64 _scanf(FILE * stream, const char *fmt, va_list * ap)
65 {
66         int i = 0;
67         int length = 0;
68
69         fmt++;
70
71         while (*fmt != '\0') {
72
73                 char tbuf[256];
74                 char ch;
75
76                 switch (*fmt) {
77                 case 'd':
78                 case 'i':
79                         ch = _getc(stream);
80                         if (length == 0) {
81                                 while (!_is_voidage(ch) && isdigit(ch)) {
82                                         tbuf[i] = ch;
83                                         ch = _getc(stream);
84                                         i++;
85                                 }
86                         } else {
87                                 while (!_is_voidage(ch) && i < length
88                                        && isdigit(ch)) {
89                                         tbuf[i] = ch;
90                                         ch = _getc(stream);
91                                         i++;
92                                 }
93                         }
94                         /* We tried to understand what this is good for...
95                          * but we did not. We know for sure that it does not
96                          * work on SLOF if this is active. */
97                         /* _ungetc(ch, stream); */
98                         tbuf[i] = '\0';
99
100                         /* ch = _getc(stream); */
101                         if (!_is_voidage(ch))
102                                 _ungetc(ch, stream);
103
104                         if (strlen(tbuf) == 0)
105                                 return 0;
106
107                         *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 10);
108                         break;
109                 case 'X':
110                 case 'x':
111                         ch = _getc(stream);
112                         if (length == 0) {
113                                 while (!_is_voidage(ch) && isxdigit(ch)) {
114                                         tbuf[i] = ch;
115                                         ch = _getc(stream);
116                                         i++;
117                                 }
118                         } else {
119                                 while (!_is_voidage(ch) && i < length
120                                        && isxdigit(ch)) {
121                                         tbuf[i] = ch;
122                                         ch = _getc(stream);
123                                         i++;
124                                 }
125                         }
126                         /* _ungetc(ch, stream); */
127                         tbuf[i] = '\0';
128
129                         /* ch = _getc(stream); */
130                         if (!_is_voidage(ch))
131                                 _ungetc(ch, stream);
132
133                         if (strlen(tbuf) == 0)
134                                 return 0;
135
136                         *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 16);
137                         break;
138                 case 'O':
139                 case 'o':
140                         ch = _getc(stream);
141                         if (length == 0) {
142                                 while (!_is_voidage(ch)
143                                        && !(ch < '0' || ch > '7')) {
144                                         tbuf[i] = ch;
145                                         ch = _getc(stream);
146                                         i++;
147                                 }
148                         } else {
149                                 while (!_is_voidage(ch) && i < length
150                                        && !(ch < '0' || ch > '7')) {
151                                         tbuf[i] = ch;
152                                         ch = _getc(stream);
153                                         i++;
154                                 }
155                         }
156                         /* _ungetc(ch, stream); */
157                         tbuf[i] = '\0';
158
159                         /* ch = _getc(stream); */
160                         if (!_is_voidage(ch))
161                                 _ungetc(ch, stream);
162
163                         if (strlen(tbuf) == 0)
164                                 return 0;
165
166                         *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 8);
167                         break;
168                 case 'c':
169                         ch = _getc(stream);
170                         while (_is_voidage(ch))
171                                 ch = _getc(stream);
172
173                         *(va_arg(*ap, char *)) = ch;
174
175                         ch = _getc(stream);
176                         if (!_is_voidage(ch))
177                                 _ungetc(ch, stream);
178
179                         break;
180                 case 's':
181                         ch = _getc(stream);
182                         if (length == 0) {
183                                 while (!_is_voidage(ch)) {
184                                         tbuf[i] = ch;
185                                         ch = _getc(stream);
186                                         i++;
187                                 }
188                         } else {
189                                 while (!_is_voidage(ch) && i < length) {
190                                         tbuf[i] = ch;
191                                         ch = _getc(stream);
192                                         i++;
193                                 }
194                         }
195                         /* _ungetc(ch, stream); */
196                         tbuf[i] = '\0';
197
198                         /* ch = _getc(stream); */
199                         if (!_is_voidage(ch))
200                                 _ungetc(ch, stream);
201
202                         strcpy(va_arg(*ap, char *), tbuf);
203                         break;
204                 default:
205                         if (*fmt >= '0' && *fmt <= '9')
206                                 length += *fmt - '0';
207                         break;
208                 }
209                 fmt++;
210         }
211
212         return 1;
213 }
214
215
216
217 int
218 vfscanf(FILE * stream, const char *fmt, va_list ap)
219 {
220         int args = 0;
221
222         while (*fmt != '\0') {
223
224                 if (*fmt == '%') {
225
226                         char formstr[20];
227                         int i = 0;
228
229                         do {
230                                 formstr[i] = *fmt;
231                                 fmt++;
232                                 i++;
233                         } while (!
234                                  (*fmt == 'd' || *fmt == 'i' || *fmt == 'x'
235                                   || *fmt == 'X' || *fmt == 'p' || *fmt == 'c'
236                                   || *fmt == 's' || *fmt == '%' || *fmt == 'O'
237                                   || *fmt == 'o'));
238                         formstr[i++] = *fmt;
239                         formstr[i] = '\0';
240                         if (*fmt != '%') {
241                                 if (_scanf(stream, formstr, &ap) <= 0)
242                                         return args;
243                                 else
244                                         args++;
245                         }
246
247                 }
248
249                 fmt++;
250
251         }
252
253         return args;
254 }
255
256 int
257 getc(FILE * stream)
258 {
259         return _getc(stream);
260 }
261
262 int
263 getchar(void)
264 {
265         return _getc(stdin);
266 }