Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Libc> Add support for scanf to accept formatted #289

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/lib/libc/include/stdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extern FILE stddev[];

int __printf(const char *fmt, ...);
int __eprintf(const char *fmt, ...);
int scanf(const char *fmt, ...);
int fputs(const FILE *, const char *);
int fputc(const FILE *, const char);
int fgetc(const FILE *, char *);
Expand All @@ -39,6 +40,7 @@ char getchar();
#ifdef _STDBOOL_H_
int fprintf(const FILE *, bool, const char *fmt, ...);
#ifdef _STDARG_H_
int vscanf(const FILE *, const char *fmt, va_list args);
int vprintf(const FILE *, bool, const char *fmt, va_list args);
#endif
#endif
Expand Down
4 changes: 3 additions & 1 deletion src/lib/libc/printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ static int fltprint(const FILE *dev, bool en_stdout, double flt,
{
frac *= 10.0;
padf--;
d = (long) frac;
if (!d)
__fputc(dev, en_stdout, '0');
}
d = (long) frac;
ret += unumprint(dev, en_stdout, d,10, '0', 0);

return ret;
Expand Down
200 changes: 200 additions & 0 deletions src/lib/libc/scanf.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <ccpfs.h>
#include <stdio.h>
#include <stddev.h>
#include <stdarg.h>
#include <ctype.h>

int fgetc(const FILE *dev, char *c)
{
Expand Down Expand Up @@ -42,3 +44,201 @@ char getchar()
} while(temp != '\r');
return c;
}

int vscanf(const FILE *dev, const char *fmt, va_list args)
{
int ret = 0;
int l_ret;
int N;
char c;
while (*fmt != '\0')
{
l_ret = 0;
if (*fmt == '%')
{
fmt++;
loop:
switch (*fmt)
{
case 'i':
case 'd':
{
int a = 0;
N = 0;
// skip leading whitespaces
do
{
fgetc(dev, &c);
if (c == '\r')
fputc(stdout, '\n');
else
fputc(stdout, c);
} while (isSpace(c));
// initialize first int digit
if (c == '-')
N = 1;
else if (isDigit(c))
a = c - '0';
// append rest of digits till whitespace
do
{
fgetc(dev, &c);
if (isDigit(c))
{
a *= 10;
a += (c - '0');
fputc(stdout, c);
}
else if (a && (c == 0x7f || c== 0x08))
{
a /= 10;
fputs(stdout, "\b \b");
}
} while (!isSpace(c));
(c == '\r') ? fputc(stdout, '\n') : fputc(stdout, c);
if (l_ret >= 2)
*(int64_t *)va_arg(args, int64_t *) = (N) ? -(a) : a;
else if (l_ret == 1)
*(long *)va_arg(args, long *) = (N) ? -(a) : a;
else
*(int *)va_arg(args, int *) = (N) ? -(a) : a;
ret++;
break;
}
case 'l':
{
l_ret++;
fmt++;
goto loop;
}
#if USE_FLOAT == 1
case 'f':
{
float a = 0;
unsigned int rp = 0; // radix point
float e = 1;
unsigned int fl = 1; // floating length - length after radix point
N = 0;
// skip leading whitespaces
do
{
fgetc(dev, &c);
if (c == '\r')
fputc(stdout, '\n');
else
fputc(stdout, c);
} while (isSpace(c));
if (c == '.')
rp = 1;
else if (c == '-')
N = 1;
else if (isDigit(c))
a = (float)(c - '0');
// append rest of digits till whitespace
do
{
fgetc(dev, &c);
if (!rp && c == '.')
{
rp = 1;
fputc(stdout, c);
}
else if (isDigit(c))
{
if (rp)
{
e /= 10.0;
a += (e * (float)(c - '0'));
fl *= 10;
}
else
{
a *= 10.0;
a += (float)(c - '0');
}
fputc(stdout, c);
}
else if (a && (c == 0x7f || c == 0x08))
{
long d = (long)a;
float frac = a - (float)d;
if (frac == 0.0 && rp)
rp = 0;
else if (rp)
{
fl /= 10;
frac *= fl;
frac = (long)frac / (float)fl;
a = d + frac;
}
else
a = (int)a / 10;
fputs(stdout, "\b \b");
}
} while (!isSpace(c));
(c == '\r') ? fputc(stdout, '\n') : fputc(stdout, c);
*(float *)va_arg(args, float *) = (N) ? -(a) : a;
ret++;
break;
}
#endif
case 'c':
{
*(char *)va_arg(args, char *) = getchar();
ret++;
break;
}
case 's':
{
int i = 0;
char *s = va_arg(args, char *);
//skip leading whitespaces
do
{
fgetc(dev, &c);
if (c == '\r')
fputc(stdout, '\n');
else
fputc(stdout, c);
} while (isSpace(c));
s[i++] = c;
do
{
fgetc(dev, &c);
if (isSpace(c))
break;
else if (i && (c == 0x7f || c == 0x08))
{
i--;
fputs(stdout, "\b \b");
}
else
s[i++] = c;
fputc(stdout, c);
} while (!isSpace(c));
(c == '\r') ? fputc(stdout, '\n') : fputc(stdout, c);
s[i] = '\0';
ret++;
break;
}
default:
return -1;
}
continue;
}
/* increment pointer if % not found */
fmt++;
}
fputc(stdout, '\n');
return ret;
}

int scanf(const char *fmt, ...)
{
int ret;
va_list va;
va_start(va, fmt);
ret = vscanf(stdin, fmt, va);
va_end(va);
return ret;
}
Loading