forked from KolibriOS/kolibrios
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
This commit is contained in:
parent
a7f779193d
commit
ec9a93aa6a
@ -3,4 +3,5 @@
|
|||||||
BasedOnStyle: WebKit
|
BasedOnStyle: WebKit
|
||||||
AlignTrailingComments: true
|
AlignTrailingComments: true
|
||||||
AlignConsecutiveMacros: true
|
AlignConsecutiveMacros: true
|
||||||
|
SortIncludes: false
|
||||||
...
|
...
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "stdio/fgets.c"
|
#include "stdio/fgets.c"
|
||||||
#include "stdio/fopen.c"
|
#include "stdio/fopen.c"
|
||||||
#include "stdio/format_print.c"
|
#include "stdio/format_print.c"
|
||||||
#include "stdio/format_scan.c"
|
|
||||||
#include "stdio/fprintf.c"
|
#include "stdio/fprintf.c"
|
||||||
#include "stdio/fputc.c"
|
#include "stdio/fputc.c"
|
||||||
#include "stdio/fputs.c"
|
#include "stdio/fputs.c"
|
||||||
@ -51,12 +50,14 @@
|
|||||||
#include "stdio/snprintf.c"
|
#include "stdio/snprintf.c"
|
||||||
#include "stdio/sprintf.c"
|
#include "stdio/sprintf.c"
|
||||||
#include "stdio/sscanf.c"
|
#include "stdio/sscanf.c"
|
||||||
|
#include "stdio/strntoumax.c"
|
||||||
#include "stdio/tmpfile.c"
|
#include "stdio/tmpfile.c"
|
||||||
#include "stdio/tmpnam.c"
|
#include "stdio/tmpnam.c"
|
||||||
#include "stdio/ungetc.c"
|
#include "stdio/ungetc.c"
|
||||||
#include "stdio/vfprintf.c"
|
#include "stdio/vfprintf.c"
|
||||||
#include "stdio/vprintf.c"
|
#include "stdio/vprintf.c"
|
||||||
#include "stdio/vsnprintf.c"
|
#include "stdio/vsnprintf.c"
|
||||||
|
#include "stdio/vsscanf.c"
|
||||||
|
|
||||||
#include "string/memccpy.c"
|
#include "string/memccpy.c"
|
||||||
#include "string/memchr.c"
|
#include "string/memchr.c"
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#pragma pack(push,1)
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (*fct)(char character, void* arg);
|
void (*fct)(char character, void* arg);
|
||||||
void* arg;
|
void* arg;
|
||||||
} out_fct_wrap_type;
|
} out_fct_wrap_type;
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
|
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);
|
void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen);
|
||||||
|
@ -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 <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;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
#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);
|
|
@ -1,42 +1,23 @@
|
|||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int virtual_getc_file(void *sp, const void *obj)
|
int vfscanf(FILE* stream, const char* format, va_list arg)
|
||||||
// get next chat from file obj, save point is ptr to string char ptr
|
|
||||||
{
|
{
|
||||||
FILE *f = (FILE *)obj;
|
static char scanf_buffer[STDIO_MAX_MEM];
|
||||||
int ch = fgetc(f);
|
fgets(scanf_buffer, STDIO_MAX_MEM-1, stream);
|
||||||
|
return vsscanf(scanf_buffer, format, arg);
|
||||||
//printf("getc '%c'[%d];", ch, ch);
|
|
||||||
|
|
||||||
return ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtual_ungetc_file(void *sp, int c, const void *obj)
|
int fscanf(FILE* stream, const char* format, ...)
|
||||||
// if can, one step back savepoint in s
|
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,65 +1,21 @@
|
|||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
char *__scanf_buffer = 0;
|
|
||||||
|
|
||||||
int virtual_getc_con(void *sp, const void *obj)
|
int vscanf(const char* format, va_list arg)
|
||||||
// get next chat from string obj, save point is ptr to string char ptr
|
|
||||||
{
|
{
|
||||||
int ch;
|
static char scanf_buffer[STDIO_MAX_MEM];
|
||||||
const char**spc= (const char**)sp;
|
gets(scanf_buffer);
|
||||||
if (!spc) return EOF; // error
|
return vsscanf(scanf_buffer, format, arg);
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int scanf ( const char * format, ...)
|
int scanf(const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list arg;
|
va_list arg;
|
||||||
int n;
|
va_start(arg, format);
|
||||||
va_start(arg, format);
|
int n = vscanf(format, arg);
|
||||||
|
va_end(arg);
|
||||||
if(__scanf_buffer == NULL) __scanf_buffer = malloc(4096);
|
return n;
|
||||||
if(__scanf_buffer == NULL) return -3;
|
|
||||||
|
|
||||||
*__scanf_buffer = 0;
|
|
||||||
n = vscanf(format, arg);
|
|
||||||
|
|
||||||
va_end(arg);
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||||
|
|
||||||
//#include "format_print.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int sprintf(char* buffer, const char* format, ...)
|
int sprintf(char* buffer, const char* format, ...)
|
||||||
|
@ -1,46 +1,12 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
int virtual_getc_str(void *sp, const void *obj)
|
int sscanf(const char* s, const char* format, ...)
|
||||||
// get next chat from string obj, save point is ptr to string char ptr
|
|
||||||
{
|
{
|
||||||
int ch;
|
va_list arg;
|
||||||
const char *s = (const char *)obj;
|
int n;
|
||||||
const char**spc= (const char**)sp;
|
va_start(arg, format);
|
||||||
if (!s || !spc) return EOF; // error
|
n = vsscanf(s, format, arg);
|
||||||
|
va_end(arg);
|
||||||
if (!*spc) *spc = s; // first call, init savepoint
|
return n;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* strntoumax.c
|
||||||
|
*
|
||||||
|
* The strntoumax() function and associated
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -8,24 +8,23 @@
|
|||||||
#include <sys/ksys.h>
|
#include <sys/ksys.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
//#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);
|
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;
|
int len = 0;
|
||||||
char *s = malloc(STDIO_MAX_MEM);
|
char* s = malloc(STDIO_MAX_MEM);
|
||||||
if(!s){
|
if (!s) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
con_init();
|
con_init();
|
||||||
len = vsnprintf(s, STDIO_MAX_MEM, format, arg);
|
len = vsnprintf(s, STDIO_MAX_MEM, format, arg);
|
||||||
con_write_string(s, len);
|
con_write_string(s, len);
|
||||||
free(s);
|
free(s);
|
||||||
return(len);
|
return (len);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//#include "format_print.h"
|
#include <stdio.h>
|
||||||
|
|
||||||
int vsnprintf(char* buffer, size_t count, const char* format, va_list va)
|
int vsnprintf(char* buffer, size_t count, const char* format, va_list va)
|
||||||
{
|
{
|
||||||
|
405
programs/develop/ktcc/trunk/libc.obj/source/stdio/vsscanf.c
Normal file
405
programs/develop/ktcc/trunk/libc.obj/source/stdio/vsscanf.c
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
/*
|
||||||
|
* vsscanf.c
|
||||||
|
*
|
||||||
|
* vsscanf(), from which the rest of the scanf()
|
||||||
|
* family is built
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user