clean up stb_sprintf; implementation of fprintf et al, remove

This commit is contained in:
pommicket 2022-02-14 12:04:49 -05:00
parent f7a8a193c2
commit d0d868433e
5 changed files with 167 additions and 57 deletions

View file

@ -1,4 +1,4 @@
all: out04 all: out04 a.out
in04: *.b ../04a/out04 in04: *.b ../04a/out04
../04a/out04 main.b in04 ../04a/out04 main.b in04
out04: in04 ../04/out03 out04: in04 ../04/out03
@ -7,5 +7,7 @@ out04: in04 ../04/out03
../markdown $< ../markdown $<
%.out: %.c %.out: %.c
./out04 $< $@ ./out04 $< $@
a.out: main.c
./out04
clean: clean:
rm -f out* README.html *.out rm -f out* README.html *.out

View file

@ -1,10 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
int main(int argc, char **argv) { int main(int argc, char **argv) {
char buf[200] = {0}; printf("%s\n",remove("test_file")?"failure":"success");
snprintf(buf, sizeof buf, "Hello, %d %.2f %g %s %p\n", 187, 77.3, 349e12, "Wow!", "yea");
/* write(1, buf, sizeof buf); */
printf("%s\n",buf);
return 0; return 0;
} }

View file

@ -5,6 +5,7 @@
#define volatile #define volatile
#define register #define register
#define const #define const
#define NULL ((void*)0)
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
typedef char int8_t; typedef char int8_t;

View file

@ -11,30 +11,20 @@ int printf(const char *, ...);
#ifndef STB_SPRINTF_MIN #ifndef STB_SPRINTF_MIN
#define STB_SPRINTF_MIN 512 // how many characters per callback #define STB_SPRINTF_MIN 512 // how many characters per callback
#endif #endif
typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); typedef char *_STBSP_SPRINTFCB(const char *buf, void *user, int len);
#ifndef STB_SPRINTF_DECORATE
#define STB_SPRINTF_DECORATE(name) __##name // define this before including if you want to change the names
#endif
#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses
#define STBSP__UNALIGNED(code)
#else
#define STBSP__UNALIGNED(code) code
#endif
// internal float utility functions // internal float utility functions
static int32_t stbsp__real_to_str(char const **start, uint32_t *len, char *out, int32_t *decimal_pos, double value, uint32_t frac_digits); static int32_t _stbsp__real_to_str(char const **start, uint32_t *len, char *out, int32_t *decimal_pos, double value, uint32_t frac_digits);
static int32_t stbsp__real_to_parts(int64_t *bits, int32_t *expo, double value); static int32_t _stbsp__real_to_parts(int64_t *bits, int32_t *expo, double value);
#define STBSP__SPECIAL 0x7000 #define STBSP__SPECIAL 0x7000
static char stbsp__period = '.'; static char _stbsp__period = '.';
static char stbsp__comma = ','; static char _stbsp__comma = ',';
static struct static struct
{ {
short temp; // force next field to be 2-byte aligned short temp; // force next field to be 2-byte aligned
char pair[201]; char pair[201];
} stbsp__digitpair = } _stbsp__digitpair =
{ {
0, 0,
"00010203040506070809101112131415161718192021222324" "00010203040506070809101112131415161718192021222324"
@ -57,7 +47,7 @@ static struct
#define STBSP__METRIC_1024 2048 #define STBSP__METRIC_1024 2048
#define STBSP__METRIC_JEDEC 4096 #define STBSP__METRIC_JEDEC 4096
static void stbsp__lead_sign(uint32_t fl, char *sign) static void _stbsp__lead_sign(uint32_t fl, char *sign)
{ {
sign[0] = 0; sign[0] = 0;
if (fl & STBSP__NEGATIVE) { if (fl & STBSP__NEGATIVE) {
@ -72,7 +62,7 @@ static void stbsp__lead_sign(uint32_t fl, char *sign)
} }
} }
static uint32_t stbsp__strlen_limited(char const *s, uint32_t limit) static uint32_t _stbsp__strlen_limited(char const *s, uint32_t limit)
{ {
char const * sn = s; char const * sn = s;
@ -112,7 +102,7 @@ static uint32_t stbsp__strlen_limited(char const *s, uint32_t limit)
return (uint32_t)(sn - s); return (uint32_t)(sn - s);
} }
int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) int __vsprintfcb(_STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va)
{ {
static char hex[] = "0123456789abcdefxp"; static char hex[] = "0123456789abcdefxp";
static char hexu[] = "0123456789ABCDEFXP"; static char hexu[] = "0123456789ABCDEFXP";
@ -347,7 +337,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
s = (char *)"null"; s = (char *)"null";
// get the length, limited to desired precision // get the length, limited to desired precision
// always limit to ~0u chars since our counts are 32b // always limit to ~0u chars since our counts are 32b
l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); l = _stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u);
lead[0] = 0; lead[0] = 0;
tail[0] = 0; tail[0] = 0;
pr = 0; pr = 0;
@ -381,12 +371,12 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
if (pr == -1) if (pr == -1)
pr = 6; // default is 6 pr = 6; // default is 6
// read the double into a string // read the double into a string
if (stbsp__real_to_parts((int64_t *)&n64, &dp, fv)) if (_stbsp__real_to_parts((int64_t *)&n64, &dp, fv))
fl |= STBSP__NEGATIVE; fl |= STBSP__NEGATIVE;
s = num + 64; s = num + 64;
stbsp__lead_sign(fl, lead); _stbsp__lead_sign(fl, lead);
if (dp == -1023) if (dp == -1023)
dp = (n64) ? -1022 : 0; dp = (n64) ? -1022 : 0;
@ -402,7 +392,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
*s++ = h[(n64 >> 60) & 15]; *s++ = h[(n64 >> 60) & 15];
n64 <<= 4; n64 <<= 4;
if (pr) if (pr)
*s++ = stbsp__period; *s++ = _stbsp__period;
sn = s; sn = s;
// print the bits // print the bits
@ -449,7 +439,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
else if (pr == 0) else if (pr == 0)
pr = 1; // default is 6 pr = 1; // default is 6
// read the double into a string // read the double into a string
if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000)) if (_stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000))
fl |= STBSP__NEGATIVE; fl |= STBSP__NEGATIVE;
// clamp the precision and delete extra zeros after clamp // clamp the precision and delete extra zeros after clamp
@ -484,11 +474,11 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
if (pr == -1) if (pr == -1)
pr = 6; // default is 6 pr = 6; // default is 6
// read the double into a string // read the double into a string
if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000)) if (_stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000))
fl |= STBSP__NEGATIVE; fl |= STBSP__NEGATIVE;
doexpfromg: doexpfromg:
tail[0] = 0; tail[0] = 0;
stbsp__lead_sign(fl, lead); _stbsp__lead_sign(fl, lead);
if (dp == STBSP__SPECIAL) { if (dp == STBSP__SPECIAL) {
s = (char *)sn; s = (char *)sn;
cs = 0; cs = 0;
@ -500,7 +490,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
*s++ = sn[0]; *s++ = sn[0];
if (pr) if (pr)
*s++ = stbsp__period; *s++ = _stbsp__period;
// handle after decimal // handle after decimal
if ((l - 1) > (uint32_t)pr) if ((l - 1) > (uint32_t)pr)
@ -549,11 +539,11 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
if (pr == -1) if (pr == -1)
pr = 6; // default is 6 pr = 6; // default is 6
// read the double into a string // read the double into a string
if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr)) if (_stbsp__real_to_str(&sn, &l, num, &dp, fv, pr))
fl |= STBSP__NEGATIVE; fl |= STBSP__NEGATIVE;
dofloatfromg: dofloatfromg:
tail[0] = 0; tail[0] = 0;
stbsp__lead_sign(fl, lead); _stbsp__lead_sign(fl, lead);
if (dp == STBSP__SPECIAL) { if (dp == STBSP__SPECIAL) {
s = (char *)sn; s = (char *)sn;
cs = 0; cs = 0;
@ -568,7 +558,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
// handle 0.000*000xxxx // handle 0.000*000xxxx
*s++ = '0'; *s++ = '0';
if (pr) if (pr)
*s++ = stbsp__period; *s++ = _stbsp__period;
n = -dp; n = -dp;
if ((int32_t)n > pr) if ((int32_t)n > pr)
n = pr; n = pr;
@ -605,7 +595,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
for (;;) { for (;;) {
if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
cs = 0; cs = 0;
*s++ = stbsp__comma; *s++ = _stbsp__comma;
} else { } else {
*s++ = sn[n]; *s++ = sn[n];
++n; ++n;
@ -631,7 +621,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
while (n) { while (n) {
if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
cs = 0; cs = 0;
*s++ = stbsp__comma; *s++ = _stbsp__comma;
} else { } else {
*s++ = '0'; *s++ = '0';
--n; --n;
@ -640,7 +630,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
} }
cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
if (pr) { if (pr) {
*s++ = stbsp__period; *s++ = _stbsp__period;
tz = pr; tz = pr;
} }
} else { } else {
@ -649,7 +639,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
for (;;) { for (;;) {
if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
cs = 0; cs = 0;
*s++ = stbsp__comma; *s++ = _stbsp__comma;
} else { } else {
*s++ = sn[n]; *s++ = sn[n];
++n; ++n;
@ -659,7 +649,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
} }
cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
if (pr) if (pr)
*s++ = stbsp__period; *s++ = _stbsp__period;
if ((l - dp) > (uint32_t)pr) if ((l - dp) > (uint32_t)pr)
l = pr + dp; l = pr + dp;
while (n < l) { while (n < l) {
@ -769,7 +759,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
++l; ++l;
if ((l & 15) == ((l >> 4) & 15)) { if ((l & 15) == ((l >> 4) & 15)) {
l &= ~15; l &= ~15;
*--s = stbsp__comma; *--s = _stbsp__comma;
} }
} }
}; };
@ -826,14 +816,14 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
if ((fl & STBSP__TRIPLET_COMMA) == 0) { if ((fl & STBSP__TRIPLET_COMMA) == 0) {
do { do {
s -= 2; s -= 2;
*(uint16_t *)s = *(uint16_t *)&stbsp__digitpair.pair[(n % 100) * 2]; *(uint16_t *)s = *(uint16_t *)&_stbsp__digitpair.pair[(n % 100) * 2];
n /= 100; n /= 100;
} while (n); } while (n);
} }
while (n) { while (n) {
if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
l = 0; l = 0;
*--s = stbsp__comma; *--s = _stbsp__comma;
--o; --o;
} else { } else {
*--s = (char)(n % 10) + '0'; *--s = (char)(n % 10) + '0';
@ -848,7 +838,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
while (s != o) while (s != o)
if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
l = 0; l = 0;
*--s = stbsp__comma; *--s = _stbsp__comma;
--o; --o;
} else { } else {
*--s = '0'; *--s = '0';
@ -856,7 +846,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
} }
tail[0] = 0; tail[0] = 0;
stbsp__lead_sign(fl, lead); _stbsp__lead_sign(fl, lead);
// get the length that we copied // get the length that we copied
l = (uint32_t)((num + STBSP__NUMSZ) - s); l = (uint32_t)((num + STBSP__NUMSZ) - s);
@ -952,7 +942,7 @@ int __vsprintfcb(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *f
while (i) { while (i) {
if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) { if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) {
cs = 0; cs = 0;
*bf++ = stbsp__comma; *bf++ = _stbsp__comma;
} else } else
*bf++ = '0'; *bf++ = '0';
--i; --i;
@ -1214,7 +1204,7 @@ int vsprintf(char *buf, char const *fmt, va_list va)
*/ */
// get float info // get float info
int32_t stbsp__real_to_parts(int64_t *bits, int32_t *expo, double value) int32_t _stbsp__real_to_parts(int64_t *bits, int32_t *expo, double value)
{ {
double d; double d;
int64_t b = 0; int64_t b = 0;
@ -1402,7 +1392,7 @@ static void stbsp__raise_to_power10(double *ohi, double *olo, double d, int32_t
// decimal point in decimal_pos. +/-INF and NAN are specified by special values // decimal point in decimal_pos. +/-INF and NAN are specified by special values
// returned in the decimal_pos parameter. // returned in the decimal_pos parameter.
// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 // frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000
static int32_t stbsp__real_to_str(char const **start, uint32_t *len, char *out, int32_t *decimal_pos, double value, uint32_t frac_digits) static int32_t _stbsp__real_to_str(char const **start, uint32_t *len, char *out, int32_t *decimal_pos, double value, uint32_t frac_digits)
{ {
double d; double d;
int64_t bits = 0; int64_t bits = 0;
@ -1521,7 +1511,7 @@ static int32_t stbsp__real_to_str(char const **start, uint32_t *len, char *out,
} }
while (n) { while (n) {
out -= 2; out -= 2;
*(uint16_t *)out = *(uint16_t *)&stbsp__digitpair.pair[(n % 100) * 2]; *(uint16_t *)out = *(uint16_t *)&_stbsp__digitpair.pair[(n % 100) * 2];
n /= 100; n /= 100;
e += 2; e += 2;
} }
@ -1551,18 +1541,123 @@ static int32_t stbsp__real_to_str(char const **start, uint32_t *len, char *out,
#undef STBSP__SPECIAL #undef STBSP__SPECIAL
#undef STBSP__COPYFP #undef STBSP__COPYFP
typedef void FILE;
FILE *stdin = 0;
FILE *stdout = 1;
FILE *stderr = 2;
int __fd_puts(int fd, const char *s) { int __fd_puts(int fd, const char *s) {
return write(fd, s, strlen(s)); return write(fd, s, strlen(s));
} }
int printf(const char *fmt, ...) { // these are the constants that gnu uses, but they don't really matter for us
// @TODO: use a callback with __vsnprintfcb #define _IOFBF 0
va_list args; #define _IOLBF 1
char buf[2000]; #define _IONBF 2
va_start(args, fmt); #define BUFSIZ 8192
vsprintf(buf, fmt, args);
va_end(args);
return __fd_puts(1, buf); #define EOF (-1)
#define FILENAME_MAX 4096
#define FOPEN_MAX 16
typedef long fpos_t;
#define L_tmpnam 20
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#define TMP_MAX 10000
static char *__fprintf_callback(const char *buf, void *user, int len) {
write((int)user, buf, len);
return buf;
} }
int vfprintf(FILE *fp, const char *fmt, va_list args) {
char buf[STB_SPRINTF_MIN];
return __vsprintfcb(__fprintf_callback, fp, buf, fmt, args);
}
int fprintf(FILE *fp, const char *fmt, ...) {
va_list args;
int ret;
va_start(args, fmt);
ret = vfprintf(fp, fmt, args);
va_end(args);
return ret;
}
int vprintf(const char *fmt, va_list args) {
return vfprintf(stdout, fmt, args);
}
int printf(const char *fmt, ...) {
va_list args;
int ret;
va_start(args, fmt);
ret = vfprintf(stdout, fmt, args);
va_end(args);
return ret;
}
int unlink(const char *pathname) {
return __syscall(87, pathname, 0, 0, 0, 0, 0);
}
int rmdir(const char *pathname) {
return __syscall(84, pathname, 0, 0, 0, 0, 0);
}
int remove(const char *filename) {
return rmdir(filename)
? unlink(filename)
: 0;
}
int rename(const char *old, const char *new);
FILE *tmpfile(void);
char *tmpnam(char *s);
int fclose(FILE *stream);
int fflush(FILE *stream);
FILE *fopen(const char *filename, const char *mode);
FILE *freopen(const char *filename, const char *mode,
FILE *stream);
void setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
int fprintf(FILE *stream, const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int printf(const char *format, ...);
int scanf(const char *format, ...);
int sprintf(char *s, const char *format, ...);
int sscanf(const char *s, const char *format, ...);
int vfprintf(FILE *stream, const char *format, va_list arg);
int vprintf(const char *format, va_list arg);
int vsprintf(char *s, const char *format, va_list arg);
int fgetc(FILE *stream);
char *fgets(char *s, int n, FILE *stream);
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);
int ungetc(int c, FILE *stream);
size_t fread(void *ptr, size_t size, size_t nmemb,
FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);
int fseek(FILE *stream, long int offset, int whence);
int fsetpos(FILE *stream, const fpos_t *pos);
long int ftell(FILE *stream);
void rewind(FILE *stream);
void clearerr(FILE *stream);
int feof(FILE *stream);
int ferror(FILE *stream);
void perror(const char *s);
#undef STB_SPRINTF_MIN
#endif // _STDIO_H #endif // _STDIO_H

14
05/string.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef _STRING_H
#define _STRING_H
#include <stdc_common.h>
void *memset(void *s, int c, size_t n) {
char *p = s, *end = p + n;
while (p < end)
*p++ = c;
return s;
}
#endif // _STRING_H