From ec9a93aa6ad82ecd058ba4c4224372d6f8a79981 Mon Sep 17 00:00:00 2001 From: turbocat Date: Tue, 2 Aug 2022 13:30:05 +0000 Subject: [PATCH] libc.obj: - now using vsscanf from BaseLibc; - delete extra pragma - disable sort includes(clang-format) git-svn-id: svn://kolibrios.org@9868 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../develop/ktcc/trunk/libc.obj/.clang-format | 1 + .../develop/ktcc/trunk/libc.obj/source/libc.c | 3 +- .../libc.obj/source/stdio/format_print.h | 2 - .../trunk/libc.obj/source/stdio/format_scan.c | 435 ------------------ .../trunk/libc.obj/source/stdio/format_scan.h | 20 - .../ktcc/trunk/libc.obj/source/stdio/fscanf.c | 45 +- .../ktcc/trunk/libc.obj/source/stdio/scanf.c | 66 +-- .../trunk/libc.obj/source/stdio/sprintf.c | 1 - .../ktcc/trunk/libc.obj/source/stdio/sscanf.c | 50 +- .../trunk/libc.obj/source/stdio/strntoumax.c | 77 ++++ .../trunk/libc.obj/source/stdio/vprintf.c | 27 +- .../trunk/libc.obj/source/stdio/vsnprintf.c | 2 +- .../trunk/libc.obj/source/stdio/vsscanf.c | 405 ++++++++++++++++ 13 files changed, 531 insertions(+), 603 deletions(-) delete mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.c delete mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.h create mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdio/strntoumax.c create mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdio/vsscanf.c diff --git a/programs/develop/ktcc/trunk/libc.obj/.clang-format b/programs/develop/ktcc/trunk/libc.obj/.clang-format index 4ad4b7bf38..aeb74784fd 100755 --- a/programs/develop/ktcc/trunk/libc.obj/.clang-format +++ b/programs/develop/ktcc/trunk/libc.obj/.clang-format @@ -3,4 +3,5 @@ BasedOnStyle: WebKit AlignTrailingComments: true AlignConsecutiveMacros: true +SortIncludes: false ... diff --git a/programs/develop/ktcc/trunk/libc.obj/source/libc.c b/programs/develop/ktcc/trunk/libc.obj/source/libc.c index ae7acd9228..1d58689efb 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/libc.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/libc.c @@ -26,7 +26,6 @@ #include "stdio/fgets.c" #include "stdio/fopen.c" #include "stdio/format_print.c" -#include "stdio/format_scan.c" #include "stdio/fprintf.c" #include "stdio/fputc.c" #include "stdio/fputs.c" @@ -51,12 +50,14 @@ #include "stdio/snprintf.c" #include "stdio/sprintf.c" #include "stdio/sscanf.c" +#include "stdio/strntoumax.c" #include "stdio/tmpfile.c" #include "stdio/tmpnam.c" #include "stdio/ungetc.c" #include "stdio/vfprintf.c" #include "stdio/vprintf.c" #include "stdio/vsnprintf.c" +#include "stdio/vsscanf.c" #include "string/memccpy.c" #include "string/memchr.c" diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_print.h b/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_print.h index c1dd4aecd4..6a51138ddc 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_print.h +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_print.h @@ -1,12 +1,10 @@ #include #include -#pragma pack(push,1) typedef struct { void (*fct)(char character, void* arg); void* arg; } out_fct_wrap_type; -#pragma pack(pop) typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen); diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.c deleted file mode 100644 index 202e3737f9..0000000000 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - function for format read from any source - -Siemargl formats as http://www.cplusplus.com/reference/cstdio/scanf/, no wchar though -http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html is used too - -todo: -[characters], [^characters] --%n nothing scanned, filled only if good result --%d, i, u, o, x, p read similar - detect base by prefix 0 or 0x --%a --can overflow unsigned as signed --radix point always '.', no LOCALEs -*/ - - -#include -#include -#include -#include - -typedef int (*virtual_getc)(void *sp, const void *obj); -typedef void (*virtual_ungetc)(void *sp, int c, const void *obj); - -enum flags_t -{ - flag_unsigned = 0x02, - flag_register = 0x04, - flag_plus = 0x08, - flag_left_just = 0x10, - flag_lead_zeros = 0x20, - flag_space_plus = 0x40, - flag_hash_sign = 0x80, - flag_point = 0x100 -}; - -int try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) -// returns 1 if OK, -1 == EOF, -2 parse broken -{ - int sign = 1, have_digits = 0; - long long div; - - if (ch == '+') - { - ch = vgetc(save, src); - if (ch == EOF) return EOF; - } else - if (ch == '-') - { - sign = -1; - ch = vgetc(save, src); - if (ch == EOF) return EOF; - }; - *real = 0.0; - for (;;) // mantissa before point - { - // test ch is valid - if (isdigit(ch)) - { - *real = *real * 10 + ch - '0'; - have_digits++; - ch = vgetc(save, src); - if (ch == EOF || isspace(ch)) break; // ok, just finish num - } else - if (ch == '.' || ch == 'E' || ch == 'e') - { - break; // ok - } - else - { - vungetc(save, ch, src); - break; - } - } - if (ch != '.' && ch != 'E' && ch != 'e') // ok, just integer part - { - *real *= sign; - if (have_digits) - return 1; - else - return -2; - } - - if(ch == '.') - { - ch = vgetc(save, src); - div = 10; // use as divisor - for (;;) // mantissa after point - { - // test ch is valid - if (isdigit(ch)) - { - *real += (double)(ch - '0') / div; - div *= 10; - have_digits++; - ch = vgetc(save, src); - if (ch == EOF || isspace(ch)) break; // ok, just finish num - } else - if (ch == 'E' || ch == 'e') - { - break; // ok - } - else - { - vungetc(save, ch, src); - break; - } - } - if (ch != 'E' && ch != 'e') // ok, real as XX.YY - { - *real *= sign; - if (have_digits) - return 1; - else - return -2; - } - } - - ch = vgetc(save, src); - *real *= sign; - // exponent - sign = 1; - if (ch == '+') - { - ch = vgetc(save, src); - if (ch == EOF) return EOF; - } else - if (ch == '-') - { - sign = -1; - ch = vgetc(save, src); - if (ch == EOF) return EOF; - }; - div = 0; - for (;;) - { - // test ch is valid - if (isdigit(ch)) - { - div = div * 10 + ch - '0'; - ch = vgetc(save, src); - if (ch == EOF || isspace(ch)) break; // ok, just finish num - } - else - { - vungetc(save, ch, src); - break; - } - } - div *= sign; - *real *= pow(10, div); - - return 1; -} - -int try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) -{ - int sign = 1, base = 10, have_digits = 0; - - if (ch == '+') - { - ch = vgetc(save, src); - if (ch == EOF) return EOF; - } else - if (ch == '-') - { - sign = -1; - ch = vgetc(save, src); - if (ch == EOF) return EOF; - }; - - if (ch == '0') // octal or hex, read next - { - ch = vgetc(save, src); - if (ch == 'c' || ch == 'C') - base = 8; - else if (ch == 'x' || ch == 'X') - base = 16; - if (base == 10) - have_digits++; - else - { - char tch = vgetc(save, src); - if ((base == 8 && isdigit(tch) && tch < '8') || - (base == 16 && isxdigit(tch))) - ch = tch; - else - { - have_digits++; - //base = 10; // not required: zero is zero with any (base > 1) - vungetc(save, tch, src); - } - } - } - *digit = 0; - for (;;) - { - // test ch is valid - if ((isdigit(ch) && base == 10) || - (isdigit(ch) && base == 8 && ch < '8') || - (isxdigit(ch) && base == 16)) - { - if (base == 16) - { - if (ch <= '9') ch -= '0'; - else - if (ch <= 'F') ch = 10 + ch - 'A'; - else - ch = 10 + ch - 'a'; - } - else - ch -= '0'; - *digit = *digit * base + ch; - have_digits++; - ch = vgetc(save, src); - if (ch == EOF || isspace(ch)) break; // ok, just finish num - } - else if (ch == EOF || isspace(ch)) - break; - else - { - vungetc(save, ch, src); - break; - } - } - *digit *= sign; - if (have_digits) - return 1; - else - return -2; -} - - - -int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc) -{ - int i; - int length; - int fmt1, fmt2; // width, precision - size_t pos, posc; - const char *fmtc; // first point to %, fmtc points to specifier - int ch; - int format_flag; - int flag_long; // 2 = long double or long long int or wchar - int *point_to_n = NULL, nread = 0; - int flags; // parsed flags - int save = 0; - char *arg_str; - int *arg_int; - long *arg_long; - long long *arg_longlong; - float *arg_float; - double *arg_double; - long double *arg_longdouble; - long long digit; - long double real; - int skip_next; // skip arguments with * char format - - pos = 0; - while(*fmt) - { - while (*fmt && isspace(*fmt)) fmt++; // skip spaces in format str - - if (*fmt != '%') // usual char - { - ch = vgetc(&save, src); - if (ch != *fmt++) // char not match format - { - vungetc(&save, ch, src); - break; - } - pos++; - continue; - } - - if (*(fmt + 1) == '%') // %% - { - ch = vgetc(&save, src); - if (ch != '%') // char not match format - { - vungetc(&save, ch, src); - break; - } - pos++; - fmt += 2; - continue; - } - //checking to containg format in the string - fmtc = fmt; - posc = pos; - - skip_next = 0; - flags = 0; - format_flag = 0; - flag_long = 0; // 2 = long double or long long int or wchar - - while(*fmtc != '\0' && !format_flag) // searching end of format - { - fmtc++; posc++; - switch( *fmtc ) - { - case 'a': - format_flag = 1; - flags |= flag_unsigned; - break; - case 'c': case 'd': case 'i': case 'e': case 'f': case 'g': case 's': case 'n': - format_flag = 1; - break; - case 'l': - flag_long = flag_long ? 2 : 1; // ll.eq.L - break; - case 'L': - flag_long = 2; - break; - case 'o': case 'u': case 'x': case 'p': - format_flag = 1; - flags |= flag_unsigned; - break; - case '*': - skip_next = 1; - break; - case '.': // just skip - break; - default: - if(isdigit(*fmtc)) break; - goto exit_me; // non format char found - user error - } - } - - if (format_flag == 0) - { - goto exit_me; // format char not found - user error - } - - fmt1 = 0; - fmt2 = 0; - if (posc - pos > 1) // try to read width, precision - { - fmt++; - for(i = pos + 1; i < posc; i++) - { - switch(*fmt) - { - case '0': - if(fmt1 == 0 && (flags & flag_point) == 0) flags |= flag_lead_zeros; - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if ((flags & flag_point) == 0) - fmt1 = fmt1 * 10 + (*fmt -'0'); - else - fmt2 = fmt2 * 10 + (*fmt -'0'); - break; - case '*': // ignoring - break; - case '.': - flags |= flag_point; - break; - case 'l': case 'L': // valid chars - skip - break; - default: // must be error - goto exit_me; // format char not found - user error - } - fmt++; - } - } - - // do real work - format arguments values - // skip input spaces - do { - ch = vgetc(&save, src); - if (ch == EOF) goto exit_me; - } while (isspace(ch)); - - switch(*fmtc) - { - case 'n': - point_to_n = va_arg(argp, int*); - vungetc(&save, ch, src); - break; - case 'c': // read width chars, ever spaces - if (!skip_next) arg_str = va_arg(argp, char*); - if (fmt1 == 0) length = 1; - else length = fmt1; - for (i = 0; i < length;) - { - if (!skip_next) *arg_str++ = ch; - i++; - ch = vgetc(&save, src); - if (ch == EOF) break; - } - if (i < length) goto exit_me; // not enough chars - break; - case 's': - if (!skip_next) arg_str = va_arg(argp, char*); - if (fmt1 == 0) length = 4095; // max string scan 4096 - else length = fmt1; - for (i = 0; i < length; i++) - { - if (!skip_next) *arg_str++ = ch; - - ch = vgetc(&save, src); - if (ch == EOF || isspace(ch)) break; // ok, just finish string - } - if (!skip_next) *arg_str++ = '\0'; - break; - case 'd': case 'i': case 'u': - case 'o': case 'p': case 'x': - i = try_parse_int(&digit, ch, src, &save, vgetc, vungetc); - if (i < 0) goto exit_me; - - if (!skip_next) - if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else - if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else - if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; } - break; - case 'a': case 'A': case 'f': case 'F': - case 'e': case 'E': - case 'g': case 'G': - i = try_parse_real(&real, ch, src, &save, vgetc, vungetc); - if (i < 0) goto exit_me; - - if (!skip_next) - if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else - if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else - if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; } - break; - } - - fmt = fmtc + 1; - if (!skip_next) nread++; - } -exit_me: - if (point_to_n) *point_to_n = nread; - return nread; -} diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.h b/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.h deleted file mode 100644 index eea22f5641..0000000000 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.h +++ /dev/null @@ -1,20 +0,0 @@ -#include - -typedef int (*virtual_getc)(void *sp, const void *obj); -typedef void (*virtual_ungetc)(void *sp, int c, const void *obj); - -enum flags_t -{ - flag_unsigned = 0x02, - flag_register = 0x04, - flag_plus = 0x08, - flag_left_just = 0x10, - flag_lead_zeros = 0x20, - flag_space_plus = 0x40, - flag_hash_sign = 0x80, - flag_point = 0x100 -}; - -char *__scanf_buffer; - -extern int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc); \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/fscanf.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/fscanf.c index 9ae0ff86f8..45cf6b174a 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/fscanf.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/fscanf.c @@ -1,42 +1,23 @@ +#include #include #include #include -int virtual_getc_file(void *sp, const void *obj) -// get next chat from file obj, save point is ptr to string char ptr +int vfscanf(FILE* stream, const char* format, va_list arg) { - FILE *f = (FILE *)obj; - int ch = fgetc(f); - -//printf("getc '%c'[%d];", ch, ch); - - return ch; + static char scanf_buffer[STDIO_MAX_MEM]; + fgets(scanf_buffer, STDIO_MAX_MEM-1, stream); + return vsscanf(scanf_buffer, format, arg); } -void virtual_ungetc_file(void *sp, int c, const void *obj) -// if can, one step back savepoint in s +int fscanf(FILE* stream, const char* format, ...) { - FILE *f = (FILE *)obj; + va_list arg; + int n; + va_start(arg, format); - if (f) ungetc(c, f); + n = vfscanf(stream, format, arg); + + va_end(arg); + return n; } - - -int vfscanf ( FILE * stream, const char * format, va_list arg ) -{ - return format_scan(stream, format, arg, &virtual_getc_file, &virtual_ungetc_file); -}; - -int fscanf ( FILE * stream, const char * format, ...) -{ - va_list arg; - int n; - va_start(arg, format); - - n = vfscanf(stream, format, arg); - - va_end(arg); - return n; -} - - diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/scanf.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/scanf.c index b72b30e856..0aadf808ad 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/scanf.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/scanf.c @@ -1,65 +1,21 @@ +#include #include #include #include #include -char *__scanf_buffer = 0; -int virtual_getc_con(void *sp, const void *obj) -// get next chat from string obj, save point is ptr to string char ptr +int vscanf(const char* format, va_list arg) { - int ch; - const char**spc= (const char**)sp; - if (!spc) return EOF; // error - - if (!*spc) *spc = __scanf_buffer; // first call, init savepoint - - while (!**spc) // need to read more - { - if(!gets(__scanf_buffer)) return EOF; - *spc = __scanf_buffer; - strcat(__scanf_buffer,"\n"); // imitate delimiter - } - if (**spc == 26 || **spc == 3) // ^C ^Z end of scan, clear buffer - { - *spc = __scanf_buffer; - *__scanf_buffer = 0; - return EOF; // ^C ^Z - } - - ch = **spc; (*spc)++ ; - -//printf("getc '%c'[%d];", ch, ch); - return ch; -} - -void virtual_ungetc_con(void *sp, int c, const void *obj) -// if can, one step back savepoint in s -{ - const char**spc= (const char**)sp; - - if (spc && *spc > __scanf_buffer) (*spc)--; -//printf("Ungetc '%c'[%d];", c, c); -} - -int vscanf ( const char * format, va_list arg ) -{ - return format_scan(NULL, format, arg, &virtual_getc_con, &virtual_ungetc_con); + static char scanf_buffer[STDIO_MAX_MEM]; + gets(scanf_buffer); + return vsscanf(scanf_buffer, format, arg); }; -int scanf ( const char * format, ...) +int scanf(const char* format, ...) { - va_list arg; - int n; - va_start(arg, format); - - if(__scanf_buffer == NULL) __scanf_buffer = malloc(4096); - if(__scanf_buffer == NULL) return -3; - - *__scanf_buffer = 0; - n = vscanf(format, arg); - - va_end(arg); - return n; + va_list arg; + va_start(arg, format); + int n = vscanf(format, arg); + va_end(arg); + return n; } - - diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/sprintf.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/sprintf.c index 949dcfb43f..7c7b3aa1b6 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/sprintf.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/sprintf.c @@ -1,6 +1,5 @@ /* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ -//#include "format_print.h" #include int sprintf(char* buffer, const char* format, ...) diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/sscanf.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/sscanf.c index 2595506703..eade2ba2b3 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/sscanf.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/sscanf.c @@ -1,46 +1,12 @@ -#include #include +#include -int virtual_getc_str(void *sp, const void *obj) -// get next chat from string obj, save point is ptr to string char ptr +int sscanf(const char* s, const char* format, ...) { - int ch; - const char *s = (const char *)obj; - const char**spc= (const char**)sp; - if (!s || !spc) return EOF; // error - - if (!*spc) *spc = s; // first call, init savepoint - - if (!**spc) return EOF; // EOS - - ch = **spc; (*spc)++ ; - - return ch; + va_list arg; + int n; + va_start(arg, format); + n = vsscanf(s, format, arg); + va_end(arg); + return n; } - -void virtual_ungetc_str(void *sp, int c, const void *obj) -// if can, one step back savepoint in s -{ - const char *s = (const char *)obj; - const char**spc= (const char**)sp; - - if (s && spc && *spc > s) (*spc)--; -} - -int vsscanf ( const char * s, const char * format, va_list arg ) -{ - return format_scan(s, format, arg, &virtual_getc_str, &virtual_ungetc_str); -}; - -int sscanf ( const char * s, const char * format, ...) -{ - va_list arg; - int n; - va_start(arg, format); - - n = vsscanf(s, format, arg); - - va_end(arg); - return n; -} - diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/strntoumax.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/strntoumax.c new file mode 100644 index 0000000000..56dddad89c --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/strntoumax.c @@ -0,0 +1,77 @@ +/* + * strntoumax.c + * + * The strntoumax() function and associated + */ + +#include +#include +#include +#include + +static inline int digitval(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else { + return -1; + } +} + +uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) +{ + int minus = 0; + uintmax_t v = 0; + int d; + + while (n && isspace((unsigned char)*nptr)) { + nptr++; + n--; + } + + /* Single optional + or - */ + if (n) { + char c = *nptr; + if (c == '-' || c == '+') { + minus = (c == '-'); + nptr++; + n--; + } + } + + if (base == 0) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + base = 16; + } else if (n >= 1 && nptr[0] == '0') { + n--; + nptr++; + base = 8; + } else { + base = 10; + } + } else if (base == 16) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + } + } + + while (n && (d = digitval(*nptr)) >= 0 && d < base) { + v = v * base + d; + n--; + nptr++; + } + + if (endptr) + *endptr = (char *)nptr; + + return minus ? -v : v; +} diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/vprintf.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/vprintf.c index 9af1f74600..4607bb9f12 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/vprintf.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/vprintf.c @@ -8,24 +8,23 @@ #include #include #include -//#include "format_print.h" -int vsprintf (char * s, const char * format, va_list arg) +int vsprintf(char* s, const char* format, va_list arg) { return vsnprintf(s, STDIO_MAX_MEM, format, arg); } -int vprintf ( const char * format, va_list arg ) +int vprintf(const char* format, va_list arg) { - int len = 0; - char *s = malloc(STDIO_MAX_MEM); - if(!s){ - errno = ENOMEM; - return errno; - } - con_init(); - len = vsnprintf(s, STDIO_MAX_MEM, format, arg); - con_write_string(s, len); - free(s); - return(len); + int len = 0; + char* s = malloc(STDIO_MAX_MEM); + if (!s) { + errno = ENOMEM; + return errno; + } + con_init(); + len = vsnprintf(s, STDIO_MAX_MEM, format, arg); + con_write_string(s, len); + free(s); + return (len); } diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsnprintf.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsnprintf.c index baf1990a38..e939c3c8c3 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsnprintf.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsnprintf.c @@ -1,4 +1,4 @@ -//#include "format_print.h" +#include int vsnprintf(char* buffer, size_t count, const char* format, va_list va) { diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsscanf.c b/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsscanf.c new file mode 100644 index 0000000000..be58f11e22 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsscanf.c @@ -0,0 +1,405 @@ +/* + * vsscanf.c + * + * vsscanf(), from which the rest of the scanf() + * family is built + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT * sizeof(long)) +#endif + +enum flags { + FL_SPLAT = 0x01, /* Drop the value, do not assign */ + FL_INV = 0x02, /* Character-set with inverse */ + FL_WIDTH = 0x04, /* Field width specified */ + FL_MINUS = 0x08, /* Negative number */ +}; + +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2, + rank_ptr = INT_MAX /* Special value used for pointers */ +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +enum bail { + bail_none = 0, /* No error condition */ + bail_eof, /* Hit EOF */ + bail_err /* Conversion mismatch */ +}; + +static inline const char* skipspace(const char* p) +{ + while (isspace((unsigned char)*p)) + p++; + return p; +} + +#undef set_bit +static inline void set_bit(unsigned long* bitmap, unsigned int bit) +{ + bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); +} + +#undef test_bit +static inline int test_bit(unsigned long* bitmap, unsigned int bit) +{ + return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1; +} + +int vsscanf(const char* buffer, const char* format, va_list ap) +{ + const char* p = format; + char ch; + unsigned char uc; + const char* q = buffer; + const char* qq; + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + unsigned int width = UINT_MAX; + int base; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_modifiers, /* Length or conversion modifiers */ + st_match_init, /* Initial state of %[ sequence */ + st_match, /* Main state of %[ sequence */ + st_match_range, /* After - in a %[ sequence */ + } state + = st_normal; + char* sarg = NULL; /* %s %c or %[ string argument */ + enum bail bail = bail_none; + int sign; + int converted = 0; /* Successful conversions */ + unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT]; + int matchinv = 0; /* Is match map inverted? */ + unsigned char range_start = 0; + (void)sign; + + while ((ch = *p++) && !bail) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = UINT_MAX; + } else if (isspace((unsigned char)ch)) { + q = skipspace(q); + } else { + if (*q == ch) + q++; + else + bail = bail_err; /* Match failure */ + } + break; + + case st_flags: + switch (ch) { + case '*': + flags |= FL_SPLAT; + break; + case '0': /* falls-through */ + case '1': /* falls-through */ + case '2': /* falls-through */ + case '3': /* falls-through */ + case '4': /* falls-through */ + case '5': /* falls-through */ + case '6': /* falls-through */ + case '7': /* falls-through */ + case '8': /* falls-through */ + case '9': + width = (ch - '0'); + state = st_width; + flags |= FL_WIDTH; + break; + default: + state = st_modifiers; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank = rank_longlong; /* long double/long long */ + break; + + default: + /* Output modifiers - terminal sequences */ + /* Next state will be normal */ + state = st_normal; + + /* Canonicalize rank */ + if (rank < MIN_RANK) + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + case 'p': /* Pointer */ + rank = rank_ptr; + base = 0; + sign = 0; + goto scan_int; + + case 'i': /* Base-independent integer */ + base = 0; + sign = 1; + goto scan_int; + + case 'd': /* Decimal integer */ + base = 10; + sign = 1; + goto scan_int; + + case 'o': /* Octal integer */ + base = 8; + sign = 0; + goto scan_int; + + case 'u': /* Unsigned decimal integer */ + base = 10; + sign = 0; + goto scan_int; + + case 'x': /* Hexadecimal integer */ + case 'X': + base = 16; + sign = 0; + goto scan_int; + + case 'n': /* # of characters consumed */ + val = (q - buffer); + goto set_integer; + + scan_int: + q = skipspace(q); + if (!*q) { + bail = bail_eof; + break; + } + val = strntoumax(q, (char**)&qq, base, + width); + if (qq == q) { + bail = bail_err; + break; + } + q = qq; + if (!(flags & FL_SPLAT)) + converted++; + /* fall through */ + + set_integer: + if (!(flags & FL_SPLAT)) { + switch (rank) { + case rank_char: + *va_arg(ap, + unsigned char*) + = val; + break; + case rank_short: + *va_arg(ap, + unsigned short*) + = val; + break; + case rank_int: + *va_arg(ap, + unsigned int*) + = val; + break; + case rank_long: + *va_arg(ap, + unsigned long*) + = val; + break; + case rank_longlong: + *va_arg(ap, + unsigned long long*) + = val; + break; + case rank_ptr: + *va_arg(ap, void**) = (void*)(uintptr_t)val; + break; + } + } + break; + + case 'c': /* Character */ + /* Default width == 1 */ + width = (flags & FL_WIDTH) ? width : 1; + if (flags & FL_SPLAT) { + while (width--) { + if (!*q) { + bail = bail_eof; + break; + } + } + } else { + sarg = va_arg(ap, char*); + while (width--) { + if (!*q) { + bail = bail_eof; + break; + } + *sarg++ = *q++; + } + if (!bail) + converted++; + } + break; + + case 's': /* String */ + uc = 1; /* Anything nonzero */ + if (flags & FL_SPLAT) { + while (width-- && (uc = *q) && !isspace(uc)) { + q++; + } + } else { + char* sp; + sp = sarg = va_arg(ap, char*); + while (width-- && (uc = *q) && !isspace(uc)) { + *sp++ = uc; + q++; + } + if (sarg != sp) { + /* Terminate output */ + *sp = '\0'; + converted++; + } + } + if (!uc) + bail = bail_eof; + break; + + case '[': /* Character range */ + sarg = (flags & FL_SPLAT) ? NULL + : va_arg(ap, char*); + state = st_match_init; + matchinv = 0; + memset(matchmap, 0, sizeof matchmap); + break; + + case '%': /* %% sequence */ + if (*q == '%') + q++; + else + bail = bail_err; + break; + + default: /* Anything else */ + /* Unknown sequence */ + bail = bail_err; + break; + } + } + break; + + case st_match_init: /* Initial state for %[ match */ + if (ch == '^' && !(flags & FL_INV)) { + matchinv = 1; + } else { + set_bit(matchmap, (unsigned char)ch); + state = st_match; + } + break; + + case st_match: /* Main state for %[ match */ + if (ch == ']') { + goto match_run; + } else if (ch == '-') { + range_start = (unsigned char)ch; + state = st_match_range; + } else { + set_bit(matchmap, (unsigned char)ch); + } + break; + + case st_match_range: /* %[ match after - */ + if (ch == ']') { + /* - was last character */ + set_bit(matchmap, (unsigned char)'-'); + goto match_run; + } else { + int i; + for (i = range_start; i < (unsigned char)ch; + i++) + set_bit(matchmap, i); + state = st_match; + } + break; + + match_run: /* Match expression finished */ + qq = q; + uc = 1; /* Anything nonzero */ + while (width && (uc = *q) + && test_bit(matchmap, uc) ^ matchinv) { + if (sarg) + *sarg++ = uc; + q++; + } + if (q != qq && sarg) { + *sarg = '\0'; + converted++; + } else { + bail = bail_err; + } + if (!uc) + bail = bail_eof; + break; + } + } + + if (bail == bail_eof && !converted) + converted = -1; /* Return EOF (-1) */ + + return converted; +}