Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 9868 → Rev 9867

/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsscanf.c
File deleted
/programs/develop/ktcc/trunk/libc.obj/source/stdio/strntoumax.c
File deleted
/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.c
0,0 → 1,435
/*
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 <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
 
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;
}
/programs/develop/ktcc/trunk/libc.obj/source/stdio/vprintf.c
8,6 → 8,7
#include <sys/ksys.h>
#include <errno.h>
#include <limits.h>
//#include "format_print.h"
 
int vsprintf(char* s, const char* format, va_list arg)
{
/programs/develop/ktcc/trunk/libc.obj/source/stdio/fscanf.c
1,15 → 1,32
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
 
int vfscanf(FILE* stream, const char* format, va_list arg)
int virtual_getc_file(void *sp, const void *obj)
// get next chat from file obj, save point is ptr to string char ptr
{
static char scanf_buffer[STDIO_MAX_MEM];
fgets(scanf_buffer, STDIO_MAX_MEM-1, stream);
return vsscanf(scanf_buffer, format, arg);
FILE *f = (FILE *)obj;
int ch = fgetc(f);
 
//printf("getc '%c'[%d];", ch, ch);
 
return ch;
}
 
void virtual_ungetc_file(void *sp, int c, const void *obj)
// if can, one step back savepoint in s
{
FILE *f = (FILE *)obj;
 
if (f) ungetc(c, f);
}
 
 
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;
21,3 → 38,5
va_end(arg);
return n;
}
 
 
/programs/develop/ktcc/trunk/libc.obj/source/stdio/scanf.c
1,21 → 1,65
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
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 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)
{
static char scanf_buffer[STDIO_MAX_MEM];
gets(scanf_buffer);
return vsscanf(scanf_buffer, format, arg);
return format_scan(NULL, format, arg, &virtual_getc_con, &virtual_ungetc_con);
};
 
int scanf(const char* format, ...)
{
va_list arg;
int n;
va_start(arg, format);
int n = vscanf(format, arg);
 
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;
}
 
 
/programs/develop/ktcc/trunk/libc.obj/source/stdio/sscanf.c
1,12 → 1,46
#include <stdio.h>
#include <stdarg.h>
#include <stdio.h>
 
int virtual_getc_str(void *sp, const void *obj)
// get next chat from string obj, save point is ptr to string char ptr
{
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;
}
 
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;
}
 
/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_print.h
1,10 → 1,12
#include <stddef.h>
#include <stdarg.h>
 
#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);
/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.h
0,0 → 1,20
#include <stdio.h>
 
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);
/programs/develop/ktcc/trunk/libc.obj/source/stdio/sprintf.c
1,5 → 1,6
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
 
//#include "format_print.h"
#include <stdio.h>
 
int sprintf(char* buffer, const char* format, ...)
/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsnprintf.c
1,4 → 1,4
#include <stdio.h>
//#include "format_print.h"
 
int vsnprintf(char* buffer, size_t count, const char* format, va_list va)
{
/programs/develop/ktcc/trunk/libc.obj/source/libc.c
26,6 → 26,7
#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"
50,7 → 51,6
#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"
57,7 → 57,6
#include "stdio/vfprintf.c"
#include "stdio/vprintf.c"
#include "stdio/vsnprintf.c"
#include "stdio/vsscanf.c"
 
#include "string/memccpy.c"
#include "string/memchr.c"
/programs/develop/ktcc/trunk/libc.obj/.clang-format
3,5 → 3,4
BasedOnStyle: WebKit
AlignTrailingComments: true
AlignConsecutiveMacros: true
SortIncludes: false
...