From d99657bbb9a56f5ab06c659e7af013a8784b02fa Mon Sep 17 00:00:00 2001 From: Sagar Ladla Date: Tue, 30 Apr 2024 03:57:37 +0530 Subject: [PATCH 1/5] Add support for scanf to accept formatted input modified: src/lib/libc/include/stdio.h modified: src/lib/libc/scanf.c - Support for int, char, string, float format specifiers added for scanf - Added gets function to accept string with spaces Issue: #225 --- src/lib/libc/include/stdio.h | 2 + src/lib/libc/scanf.c | 156 +++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) diff --git a/src/lib/libc/include/stdio.h b/src/lib/libc/include/stdio.h index ae15c575..60ea17bf 100644 --- a/src/lib/libc/include/stdio.h +++ b/src/lib/libc/include/stdio.h @@ -35,6 +35,8 @@ int fputc(const FILE *, const char); int fgetc(const FILE *, char *); char getch(); char getchar(); +char *gets(); +int scanf(const char * restrict, ...); #ifdef _STDBOOL_H_ int fprintf(const FILE *, bool, const char *fmt, ...); diff --git a/src/lib/libc/scanf.c b/src/lib/libc/scanf.c index 9700bff8..f8aa0a34 100644 --- a/src/lib/libc/scanf.c +++ b/src/lib/libc/scanf.c @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include int fgetc(const FILE *dev, char *c) { @@ -42,3 +45,156 @@ char getchar() } while(temp != '\r'); return c; } + +/** + * get string with spaces + * + * @brief This function will take string input with spaces + * + */ +char *gets() +{ + char *s = (char *)malloc(sizeof(char)), temp; + int i = 0; + do + { + temp = getch(); + fputc(stdout, temp); + if(temp == '\r') + { + fputc(stdout, '\n'); + } + else + { + s[i++] = temp; + } + } while(temp != '\r'); + return s; +} + +/** + * scanf + * + * @brief This function will take standard input for default data types. + * input will break at spaces + * + */ + +#define CURRCHAR (temp) +#define CHARIN() (temp = getch()) +int scanf(const char * restrict fmt, ...) +{ + unsigned int count = 0; + char c = '0', temp; + va_list ap; + va_start(ap, fmt); + while (*fmt) + { + if (*fmt == '%') + { + fmt++; + /* char length : %7d */ + unsigned int cl = 0; + while (isDigit(*fmt)) + { + cl *= 10; + cl += *fmt++ - '0'; + } + switch (*fmt++) + { + case 'c': + { + /* skip leading spaces */ + while (isSpace(CHARIN())) + { + if (CURRCHAR == '\r') + fputc(stdout, '\n'); + else + fputc(stdout, CURRCHAR); + } + fputc(stdout, CURRCHAR); + c = CURRCHAR; + while (CHARIN()) + { + fputc(stdout, CURRCHAR); + if (isSpace(CURRCHAR)) + break; + } + fputc(stdout, '\n'); + *(char *)va_arg(ap, char *) = c; + count++; + break; + } + case 's': + { + char *s = va_arg(ap, char *); + /* skip leading spaces */ + while (isSpace(CHARIN())) + { + if (CURRCHAR == '\r') + fputc(stdout, '\n'); + else + fputc(stdout, CURRCHAR); + } + fputc(stdout, CURRCHAR); + *s++ = CURRCHAR; + while (CHARIN()) + { + fputc(stdout, CURRCHAR); + if (isSpace(CURRCHAR)) + break; + *s++ = CURRCHAR; + } + fputc(stdout, '\n'); + *s = '\0'; + count++; + break; + } + case 'u': + case 'd': + { + int a = 0; + /* skip leading spaces */ + while (isSpace(CHARIN())) + { + if (CURRCHAR == '\r') + fputc(stdout, '\n'); + else + fputc(stdout, CURRCHAR); + } + fputc(stdout, CURRCHAR); + c = CURRCHAR; + while (CHARIN()) + { + a *= 10; + if (isDigit(c)) + a += (c - '0'); + else + a += (int)c; + if (isSpace(CURRCHAR)) + break; + c = CURRCHAR; + fputc(stdout, CURRCHAR); + } + fputc(stdout, '\n'); + *(int *)va_arg(ap, int *) = a; + count++; + break; + } + case 'f': + { + char *a = gets(); + *(float *)va_arg(ap, float *) = (float)atof(a); + count++; + break; + } + default: + break; + } + continue; + } + /* increment pointer if % not found */ + fmt++; + } + return count; +} From ab8440e64988cfb6e9dd097dba492e3fedf329cd Mon Sep 17 00:00:00 2001 From: Sagar Ladla Date: Tue, 30 Apr 2024 20:06:48 +0530 Subject: [PATCH 2/5] Add support for scanf to accept formatted modified: src/lib/libc/scanf.c bug fix for https://github.com/VisorFolks/cyancore/pull/289#issue-2270495556 - removed usage of macros https://github.com/VisorFolks/cyancore/pull/289#discussion_r1584138333 - removed buffer overflow condition https://github.com/VisorFolks/cyancore/pull/289#discussion_r1584139514 - variable decalaration in new line https://github.com/VisorFolks/cyancore/pull/289#discussion_r1584138879 Issue: #289 --- src/lib/libc/scanf.c | 70 ++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/lib/libc/scanf.c b/src/lib/libc/scanf.c index f8aa0a34..b5b7591c 100644 --- a/src/lib/libc/scanf.c +++ b/src/lib/libc/scanf.c @@ -52,10 +52,10 @@ char getchar() * @brief This function will take string input with spaces * */ -char *gets() +char *gets(char *str) { - char *s = (char *)malloc(sizeof(char)), temp; - int i = 0; + char *p = str; + char temp; do { temp = getch(); @@ -66,10 +66,11 @@ char *gets() } else { - s[i++] = temp; + *str++ = temp; } } while(temp != '\r'); - return s; + str = '\0'; + return p; } /** @@ -80,8 +81,6 @@ char *gets() * */ -#define CURRCHAR (temp) -#define CHARIN() (temp = getch()) int scanf(const char * restrict fmt, ...) { unsigned int count = 0; @@ -105,19 +104,19 @@ int scanf(const char * restrict fmt, ...) case 'c': { /* skip leading spaces */ - while (isSpace(CHARIN())) + while (isSpace(temp = getch())) { - if (CURRCHAR == '\r') + if (temp == '\r') fputc(stdout, '\n'); else - fputc(stdout, CURRCHAR); + fputc(stdout, temp); } - fputc(stdout, CURRCHAR); - c = CURRCHAR; - while (CHARIN()) + fputc(stdout, temp); + c = temp; + while ((temp = getch())) { - fputc(stdout, CURRCHAR); - if (isSpace(CURRCHAR)) + fputc(stdout, temp); + if (isSpace(temp)) break; } fputc(stdout, '\n'); @@ -129,21 +128,21 @@ int scanf(const char * restrict fmt, ...) { char *s = va_arg(ap, char *); /* skip leading spaces */ - while (isSpace(CHARIN())) + while (isSpace(temp = getch())) { - if (CURRCHAR == '\r') + if (temp == '\r') fputc(stdout, '\n'); else - fputc(stdout, CURRCHAR); + fputc(stdout, temp); } - fputc(stdout, CURRCHAR); - *s++ = CURRCHAR; - while (CHARIN()) + fputc(stdout, temp); + *s++ = temp; + while ((temp = getch())) { - fputc(stdout, CURRCHAR); - if (isSpace(CURRCHAR)) + fputc(stdout, temp); + if (isSpace(temp)) break; - *s++ = CURRCHAR; + *s++ = temp; } fputc(stdout, '\n'); *s = '\0'; @@ -155,26 +154,26 @@ int scanf(const char * restrict fmt, ...) { int a = 0; /* skip leading spaces */ - while (isSpace(CHARIN())) + while (isSpace(temp = getch())) { - if (CURRCHAR == '\r') + if (temp == '\r') fputc(stdout, '\n'); else - fputc(stdout, CURRCHAR); + fputc(stdout, temp); } - fputc(stdout, CURRCHAR); - c = CURRCHAR; - while (CHARIN()) + fputc(stdout, temp); + c = temp; + while ((temp = getch())) { a *= 10; if (isDigit(c)) a += (c - '0'); else a += (int)c; - if (isSpace(CURRCHAR)) + if (isSpace(temp)) break; - c = CURRCHAR; - fputc(stdout, CURRCHAR); + c = temp; + fputc(stdout, temp); } fputc(stdout, '\n'); *(int *)va_arg(ap, int *) = a; @@ -183,8 +182,9 @@ int scanf(const char * restrict fmt, ...) } case 'f': { - char *a = gets(); - *(float *)va_arg(ap, float *) = (float)atof(a); + char buff[50]; + gets(buff); + *(float *)va_arg(ap, float *) = (float)atof(buff); count++; break; } From 2054ffa43b1d556a1021526b51d7ac0a6a8a3b87 Mon Sep 17 00:00:00 2001 From: Sagar Ladla Date: Tue, 30 Apr 2024 21:07:54 +0530 Subject: [PATCH 3/5] Add support for scanf to accept formatted modified: src/lib/libc/scanf.c - buffer allocation modified to heap from stack --- src/lib/libc/scanf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/libc/scanf.c b/src/lib/libc/scanf.c index b5b7591c..f28a2bbb 100644 --- a/src/lib/libc/scanf.c +++ b/src/lib/libc/scanf.c @@ -182,7 +182,7 @@ int scanf(const char * restrict fmt, ...) } case 'f': { - char buff[50]; + char *buff = (char *)malloc(sizeof(char) * 50); gets(buff); *(float *)va_arg(ap, float *) = (float)atof(buff); count++; From 645063ce7a3c7bc40a94d1cf2594b80c8d91a3e6 Mon Sep 17 00:00:00 2001 From: Sagar Ladla <29002865+sagarladla@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:13:33 +0000 Subject: [PATCH 4/5] Add-support-for-scanf-accept-formatted-input Optimize printf for fractional point of floating point value Issue: #225 --- src/lib/libc/printf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/libc/printf.c b/src/lib/libc/printf.c index e6558a96..849863cb 100644 --- a/src/lib/libc/printf.c +++ b/src/lib/libc/printf.c @@ -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; From 731b0a30e98c36955516278bca7b1ee4d763d8ac Mon Sep 17 00:00:00 2001 From: Sagar Ladla <29002865+sagarladla@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:16:11 +0000 Subject: [PATCH 5/5] Add-support-for-scanf-accept-formatted-input scanf support for multi byte input Added support for int, long, float, char, string datatype Added support for value deletion (backspace) Issue: #225 --- src/lib/libc/include/stdio.h | 4 +- src/lib/libc/scanf.c | 278 ++++++++++++++++++++--------------- 2 files changed, 163 insertions(+), 119 deletions(-) diff --git a/src/lib/libc/include/stdio.h b/src/lib/libc/include/stdio.h index 60ea17bf..8e19fb5f 100644 --- a/src/lib/libc/include/stdio.h +++ b/src/lib/libc/include/stdio.h @@ -30,17 +30,17 @@ 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 *); char getch(); char getchar(); -char *gets(); -int scanf(const char * restrict, ...); #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 diff --git a/src/lib/libc/scanf.c b/src/lib/libc/scanf.c index f28a2bbb..b0bfe3dc 100644 --- a/src/lib/libc/scanf.c +++ b/src/lib/libc/scanf.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -46,155 +45,200 @@ char getchar() return c; } -/** - * get string with spaces - * - * @brief This function will take string input with spaces - * - */ -char *gets(char *str) -{ - char *p = str; - char temp; - do - { - temp = getch(); - fputc(stdout, temp); - if(temp == '\r') - { - fputc(stdout, '\n'); - } - else - { - *str++ = temp; - } - } while(temp != '\r'); - str = '\0'; - return p; -} - -/** - * scanf - * - * @brief This function will take standard input for default data types. - * input will break at spaces - * - */ - -int scanf(const char * restrict fmt, ...) +int vscanf(const FILE *dev, const char *fmt, va_list args) { - unsigned int count = 0; - char c = '0', temp; - va_list ap; - va_start(ap, fmt); - while (*fmt) + int ret = 0; + int l_ret; + int N; + char c; + while (*fmt != '\0') { + l_ret = 0; if (*fmt == '%') { fmt++; - /* char length : %7d */ - unsigned int cl = 0; - while (isDigit(*fmt)) +loop: + switch (*fmt) { - cl *= 10; - cl += *fmt++ - '0'; - } - switch (*fmt++) - { - case 'c': + case 'i': + case 'd': { - /* skip leading spaces */ - while (isSpace(temp = getch())) + int a = 0; + N = 0; + // skip leading whitespaces + do { - if (temp == '\r') + fgetc(dev, &c); + if (c == '\r') fputc(stdout, '\n'); else - fputc(stdout, temp); - } - fputc(stdout, temp); - c = temp; - while ((temp = getch())) + 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 { - fputc(stdout, temp); - if (isSpace(temp)) - break; - } - fputc(stdout, '\n'); - *(char *)va_arg(ap, char *) = c; - count++; + 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 's': + case 'l': { - char *s = va_arg(ap, char *); - /* skip leading spaces */ - while (isSpace(temp = getch())) + 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 { - if (temp == '\r') + fgetc(dev, &c); + if (c == '\r') fputc(stdout, '\n'); else - fputc(stdout, temp); - } - fputc(stdout, temp); - *s++ = temp; - while ((temp = getch())) + 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 { - fputc(stdout, temp); - if (isSpace(temp)) - break; - *s++ = temp; - } - fputc(stdout, '\n'); - *s = '\0'; - count++; + 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; } - case 'u': - case 'd': +#endif + case 'c': { - int a = 0; - /* skip leading spaces */ - while (isSpace(temp = getch())) + *(char *)va_arg(args, char *) = getchar(); + ret++; + break; + } + case 's': + { + int i = 0; + char *s = va_arg(args, char *); + //skip leading whitespaces + do { - if (temp == '\r') + fgetc(dev, &c); + if (c == '\r') fputc(stdout, '\n'); else - fputc(stdout, temp); - } - fputc(stdout, temp); - c = temp; - while ((temp = getch())) + fputc(stdout, c); + } while (isSpace(c)); + s[i++] = c; + do { - a *= 10; - if (isDigit(c)) - a += (c - '0'); - else - a += (int)c; - if (isSpace(temp)) + fgetc(dev, &c); + if (isSpace(c)) break; - c = temp; - fputc(stdout, temp); - } - fputc(stdout, '\n'); - *(int *)va_arg(ap, int *) = a; - count++; - break; - } - case 'f': - { - char *buff = (char *)malloc(sizeof(char) * 50); - gets(buff); - *(float *)va_arg(ap, float *) = (float)atof(buff); - count++; + 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: - break; + return -1; } continue; } /* increment pointer if % not found */ fmt++; } - return count; + 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; }