/programs/develop/ktcc/trunk/libc.obj/.clang-format |
---|
3,4 → 3,5 |
BasedOnStyle: WebKit |
AlignTrailingComments: true |
AlignConsecutiveMacros: true |
SortIncludes: false |
... |
/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,6 → 50,7 |
#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,6 → 57,7 |
#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/source/stdio/format_scan.c |
---|
File deleted |
/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_scan.h |
---|
File deleted |
\ No newline at end of file |
/programs/develop/ktcc/trunk/libc.obj/source/stdio/format_print.h |
---|
1,12 → 1,10 |
#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/fscanf.c |
---|
1,42 → 1,23 |
#include <limits.h> |
#include <stdio.h> |
#include <stdarg.h> |
#include <stdlib.h> |
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); |
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; |
va_end(arg); |
return n; |
} |
/programs/develop/ktcc/trunk/libc.obj/source/stdio/scanf.c |
---|
1,65 → 1,21 |
#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 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; |
} |
/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 <stdio.h> |
int sprintf(char* buffer, const char* format, ...) |
/programs/develop/ktcc/trunk/libc.obj/source/stdio/sscanf.c |
---|
1,46 → 1,12 |
#include <stdarg.h> |
#include <stdio.h> |
#include <stdarg.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 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; |
} |
/programs/develop/ktcc/trunk/libc.obj/source/stdio/strntoumax.c |
---|
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; |
} |
/programs/develop/ktcc/trunk/libc.obj/source/stdio/vprintf.c |
---|
8,24 → 8,23 |
#include <sys/ksys.h> |
#include <errno.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); |
} |
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); |
} |
/programs/develop/ktcc/trunk/libc.obj/source/stdio/vsnprintf.c |
---|
1,4 → 1,4 |
//#include "format_print.h" |
#include <stdio.h> |
int vsnprintf(char* buffer, size_t count, const char* format, va_list va) |
{ |
/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 <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; |
} |