summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/lib/libc/stdio/vfscanf.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/lib/libc/stdio/vfscanf.c')
-rw-r--r--qemu/roms/SLOF/lib/libc/stdio/vfscanf.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/lib/libc/stdio/vfscanf.c b/qemu/roms/SLOF/lib/libc/stdio/vfscanf.c
new file mode 100644
index 000000000..4ddd210a9
--- /dev/null
+++ b/qemu/roms/SLOF/lib/libc/stdio/vfscanf.c
@@ -0,0 +1,266 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "string.h"
+#include "ctype.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "unistd.h"
+
+
+static int
+_getc(FILE * stream)
+{
+ int count;
+ char c;
+
+ if (stream->mode == _IONBF || stream->buf == NULL) {
+ if (read(stream->fd, &c, 1) == 1)
+ return (int) c;
+ else
+ return EOF;
+ }
+
+ if (stream->pos == 0 || stream->pos >= BUFSIZ ||
+ stream->buf[stream->pos] == '\0') {
+ count = read(stream->fd, stream->buf, BUFSIZ);
+ if (count < 0)
+ count = 0;
+ if (count < BUFSIZ)
+ stream->buf[count] = '\0';
+ stream->pos = 0;
+ }
+
+ return stream->buf[stream->pos++];
+}
+
+static void
+_ungetc(int ch, FILE * stream)
+{
+ if (stream->mode != _IONBF && stream->pos > 0)
+ stream->pos--;
+}
+
+static int
+_is_voidage(int ch)
+{
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\0')
+ return 1;
+ else
+ return 0;
+}
+
+
+static int
+_scanf(FILE * stream, const char *fmt, va_list * ap)
+{
+ int i = 0;
+ int length = 0;
+
+ fmt++;
+
+ while (*fmt != '\0') {
+
+ char tbuf[256];
+ char ch;
+
+ switch (*fmt) {
+ case 'd':
+ case 'i':
+ ch = _getc(stream);
+ if (length == 0) {
+ while (!_is_voidage(ch) && isdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while (!_is_voidage(ch) && i < length
+ && isdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ /* We tried to understand what this is good for...
+ * but we did not. We know for sure that it does not
+ * work on SLOF if this is active. */
+ /* _ungetc(ch, stream); */
+ tbuf[i] = '\0';
+
+ /* ch = _getc(stream); */
+ if (!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ if (strlen(tbuf) == 0)
+ return 0;
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 10);
+ break;
+ case 'X':
+ case 'x':
+ ch = _getc(stream);
+ if (length == 0) {
+ while (!_is_voidage(ch) && isxdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while (!_is_voidage(ch) && i < length
+ && isxdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ /* _ungetc(ch, stream); */
+ tbuf[i] = '\0';
+
+ /* ch = _getc(stream); */
+ if (!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ if (strlen(tbuf) == 0)
+ return 0;
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 16);
+ break;
+ case 'O':
+ case 'o':
+ ch = _getc(stream);
+ if (length == 0) {
+ while (!_is_voidage(ch)
+ && !(ch < '0' || ch > '7')) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while (!_is_voidage(ch) && i < length
+ && !(ch < '0' || ch > '7')) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ /* _ungetc(ch, stream); */
+ tbuf[i] = '\0';
+
+ /* ch = _getc(stream); */
+ if (!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ if (strlen(tbuf) == 0)
+ return 0;
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 8);
+ break;
+ case 'c':
+ ch = _getc(stream);
+ while (_is_voidage(ch))
+ ch = _getc(stream);
+
+ *(va_arg(*ap, char *)) = ch;
+
+ ch = _getc(stream);
+ if (!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ break;
+ case 's':
+ ch = _getc(stream);
+ if (length == 0) {
+ while (!_is_voidage(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while (!_is_voidage(ch) && i < length) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ /* _ungetc(ch, stream); */
+ tbuf[i] = '\0';
+
+ /* ch = _getc(stream); */
+ if (!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ strcpy(va_arg(*ap, char *), tbuf);
+ break;
+ default:
+ if (*fmt >= '0' && *fmt <= '9')
+ length += *fmt - '0';
+ break;
+ }
+ fmt++;
+ }
+
+ return 1;
+}
+
+
+
+int
+vfscanf(FILE * stream, const char *fmt, va_list ap)
+{
+ int args = 0;
+
+ while (*fmt != '\0') {
+
+ if (*fmt == '%') {
+
+ char formstr[20];
+ int i = 0;
+
+ do {
+ formstr[i] = *fmt;
+ fmt++;
+ i++;
+ } while (!
+ (*fmt == 'd' || *fmt == 'i' || *fmt == 'x'
+ || *fmt == 'X' || *fmt == 'p' || *fmt == 'c'
+ || *fmt == 's' || *fmt == '%' || *fmt == 'O'
+ || *fmt == 'o'));
+ formstr[i++] = *fmt;
+ formstr[i] = '\0';
+ if (*fmt != '%') {
+ if (_scanf(stream, formstr, &ap) <= 0)
+ return args;
+ else
+ args++;
+ }
+
+ }
+
+ fmt++;
+
+ }
+
+ return args;
+}
+
+int
+getc(FILE * stream)
+{
+ return _getc(stream);
+}
+
+int
+getchar(void)
+{
+ return _getc(stdin);
+}