mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Make more fixes and improvements
This commit is contained in:
parent
01b25e267b
commit
1599b818d9
24 changed files with 858 additions and 538 deletions
|
@ -46,7 +46,7 @@ LIBC_CALLS_A_DIRECTDEPS = \
|
|||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_PDH \
|
||||
LIBC_NT_PSAPI \
|
||||
LIBC_NT_POWERPROF \
|
||||
LIBC_NT_POWRPROF \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
|
|
397
libc/fmt/fmt.c
397
libc/fmt/fmt.c
|
@ -21,7 +21,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/fmt/fmt.internal.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
|
@ -33,25 +33,6 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
|
||||
#define PUT(C) \
|
||||
do { \
|
||||
char Buf[1] = {C}; \
|
||||
if (out(Buf, arg, 1) == -1) { \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static const char kSpecialFloats[2][2][4] = {{"INF", "inf"}, {"NAN", "nan"}};
|
||||
|
||||
static void __fmt_free_dtoa(char **mem) {
|
||||
if (*mem) {
|
||||
if (weaken(freedtoa)) {
|
||||
weaken(freedtoa)(*mem);
|
||||
}
|
||||
*mem = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int __fmt_atoi(const char **str) {
|
||||
int i;
|
||||
for (i = 0; '0' <= **str && **str <= '9'; ++*str) {
|
||||
|
@ -129,11 +110,6 @@ static int __fmt_atoi(const char **str) {
|
|||
* @vforksafe if floating point isn't used
|
||||
*/
|
||||
hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||
union {
|
||||
double d;
|
||||
uint32_t u[2];
|
||||
uint64_t q;
|
||||
} pun;
|
||||
long ld;
|
||||
void *p;
|
||||
unsigned u;
|
||||
|
@ -145,13 +121,12 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
const char *alphabet;
|
||||
int (*out)(const char *, void *, size_t);
|
||||
unsigned char signbit, log2base;
|
||||
int c, d, k, w, n, i1, ui, bw, bex;
|
||||
char *s, *q, *se, *mem, qchar, special[8];
|
||||
int sgn, alt, sign, prec, prec1, flags, width, decpt, lasterr;
|
||||
char *s, *q, qchar;
|
||||
int d, w, n;
|
||||
int sign, prec, flags, width, lasterr;
|
||||
|
||||
lasterr = errno;
|
||||
out = fn ? fn : (void *)missingno;
|
||||
mem = 0;
|
||||
|
||||
while (*format) {
|
||||
if (*format != '%') {
|
||||
|
@ -361,7 +336,6 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
prec = 1;
|
||||
flags |= FLAGS_PRECISION;
|
||||
|
@ -369,12 +343,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
p = charbuf;
|
||||
charbuf[0] = va_arg(va, int);
|
||||
goto FormatString;
|
||||
|
||||
case 'm':
|
||||
p = weaken(strerror) ? weaken(strerror)(lasterr) : "?";
|
||||
signbit = 0;
|
||||
goto FormatString;
|
||||
|
||||
case 'r':
|
||||
// undocumented %r specifier
|
||||
// used for good carriage return
|
||||
|
@ -385,11 +357,9 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
p = "\r\e[K";
|
||||
goto FormatString;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
flags |= FLAGS_QUOTE;
|
||||
/* fallthrough */
|
||||
|
||||
case 's':
|
||||
p = va_arg(va, void *);
|
||||
FormatString:
|
||||
|
@ -397,369 +367,40 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
// nonstandard %n specifier
|
||||
// used to print newlines that work in raw terminal modes
|
||||
if (__nomultics) PUT('\r');
|
||||
PUT('\n');
|
||||
if (__nomultics) __FMT_PUT('\r');
|
||||
__FMT_PUT('\n');
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
case 'f':
|
||||
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
FormatDtoa:
|
||||
case 'G':
|
||||
case 'g':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'a':
|
||||
case 'A':
|
||||
if (!weaken(__fmt_dtoa)) {
|
||||
p = "?";
|
||||
goto FormatThatThing;
|
||||
}
|
||||
assert(!mem);
|
||||
s = mem = weaken(__fmt_dtoa)(pun.d, 3, prec, &decpt, &sgn, &se);
|
||||
if (decpt == 9999) {
|
||||
Format9999:
|
||||
bzero(special, sizeof(special));
|
||||
p = q = special;
|
||||
if (sgn) {
|
||||
*q++ = '-';
|
||||
} else if (flags & FLAGS_PLUS) {
|
||||
*q++ = '+';
|
||||
} else if (flags & FLAGS_SPACE) {
|
||||
*q++ = ' ';
|
||||
}
|
||||
memcpy(q, kSpecialFloats[*s == 'N'][d >= 'a'], 4);
|
||||
FormatThatThing:
|
||||
__fmt_free_dtoa(&mem);
|
||||
mem = 0;
|
||||
prec = alt = 0;
|
||||
prec = 0;
|
||||
flags &= ~(FLAGS_PRECISION | FLAGS_PLUS | FLAGS_SPACE);
|
||||
goto FormatString;
|
||||
}
|
||||
FormatReal:
|
||||
if (sgn) sign = '-';
|
||||
if (prec > 0) width -= prec;
|
||||
if (width > 0) {
|
||||
if (sign) --width;
|
||||
if (decpt <= 0) {
|
||||
--width;
|
||||
if (prec > 0) --width;
|
||||
} else {
|
||||
if (s == se) decpt = 1;
|
||||
width -= decpt;
|
||||
if (prec > 0 || alt) --width;
|
||||
}
|
||||
}
|
||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) PUT(sign);
|
||||
sign = 0;
|
||||
do PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
if (sign) PUT(sign);
|
||||
if (decpt <= 0) {
|
||||
PUT('0');
|
||||
if (prec > 0 || alt) PUT('.');
|
||||
while (decpt < 0) {
|
||||
PUT('0');
|
||||
prec--;
|
||||
decpt++;
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
if ((c = *s)) {
|
||||
s++;
|
||||
} else {
|
||||
c = '0';
|
||||
}
|
||||
PUT(c);
|
||||
} while (--decpt > 0);
|
||||
if (prec > 0 || alt) PUT('.');
|
||||
}
|
||||
while (--prec >= 0) {
|
||||
if ((c = *s)) {
|
||||
s++;
|
||||
} else {
|
||||
c = '0';
|
||||
}
|
||||
PUT(c);
|
||||
}
|
||||
while (--width >= 0) {
|
||||
PUT(' ');
|
||||
}
|
||||
__fmt_free_dtoa(&mem);
|
||||
continue;
|
||||
|
||||
case 'G':
|
||||
case 'g':
|
||||
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
if (prec < 0) prec = 0;
|
||||
if (!weaken(__fmt_dtoa)) {
|
||||
p = "?";
|
||||
goto FormatThatThing;
|
||||
}
|
||||
assert(!mem);
|
||||
s = mem =
|
||||
weaken(__fmt_dtoa)(pun.d, prec ? 2 : 0, prec, &decpt, &sgn, &se);
|
||||
if (decpt == 9999) goto Format9999;
|
||||
c = se - s;
|
||||
prec1 = prec;
|
||||
if (!prec) {
|
||||
prec = c;
|
||||
prec1 = c + (s[1] || alt ? 5 : 4);
|
||||
}
|
||||
if (decpt > -4 && decpt <= prec1) {
|
||||
if (alt) {
|
||||
prec -= decpt;
|
||||
} else {
|
||||
prec = c - decpt;
|
||||
}
|
||||
if (prec < 0) prec = 0;
|
||||
goto FormatReal;
|
||||
}
|
||||
d -= 2;
|
||||
if (!alt && prec > c) prec = c;
|
||||
--prec;
|
||||
goto FormatExpo;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
if (prec < 0) prec = 0;
|
||||
if (!weaken(__fmt_dtoa)) {
|
||||
p = "?";
|
||||
goto FormatThatThing;
|
||||
}
|
||||
assert(!mem);
|
||||
s = mem = weaken(__fmt_dtoa)(pun.d, 2, prec + 1, &decpt, &sgn, &se);
|
||||
if (decpt == 9999) goto Format9999;
|
||||
FormatExpo:
|
||||
if (sgn) sign = '-';
|
||||
if ((width -= prec + 5) > 0) {
|
||||
if (sign) --width;
|
||||
if (prec || alt) --width;
|
||||
}
|
||||
if ((c = --decpt) < 0) c = -c;
|
||||
while (c >= 100) {
|
||||
--width;
|
||||
c /= 10;
|
||||
}
|
||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) PUT(sign);
|
||||
sign = 0;
|
||||
do PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
if (sign) PUT(sign);
|
||||
PUT(*s++);
|
||||
if (prec || alt) PUT('.');
|
||||
while (--prec >= 0) {
|
||||
if ((c = *s)) {
|
||||
s++;
|
||||
} else {
|
||||
c = '0';
|
||||
}
|
||||
PUT(c);
|
||||
}
|
||||
__fmt_free_dtoa(&mem);
|
||||
PUT(d);
|
||||
if (decpt < 0) {
|
||||
PUT('-');
|
||||
decpt = -decpt;
|
||||
} else {
|
||||
PUT('+');
|
||||
}
|
||||
for (c = 2, k = 10; 10 * k <= decpt; c++) k *= 10;
|
||||
for (;;) {
|
||||
i1 = decpt / k;
|
||||
PUT(i1 + '0');
|
||||
if (--c <= 0) break;
|
||||
decpt -= i1 * k;
|
||||
decpt *= 10;
|
||||
}
|
||||
while (--width >= 0) {
|
||||
PUT(' ');
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'a':
|
||||
alphabet = "0123456789abcdefpx";
|
||||
goto FormatBinary;
|
||||
case 'A':
|
||||
alphabet = "0123456789ABCDEFPX";
|
||||
FormatBinary:
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
if ((pun.u[1] & 0x7ff00000) == 0x7ff00000) {
|
||||
goto FormatDtoa;
|
||||
}
|
||||
if (pun.u[1] & 0x80000000) {
|
||||
sign = '-';
|
||||
pun.u[1] &= 0x7fffffff;
|
||||
}
|
||||
if (pun.d) {
|
||||
c = '1';
|
||||
bex = (pun.u[1] >> 20) - 1023;
|
||||
pun.u[1] &= 0xfffff;
|
||||
if (bex == -1023) {
|
||||
++bex;
|
||||
if (pun.u[1]) {
|
||||
do {
|
||||
--bex;
|
||||
pun.u[1] <<= 1;
|
||||
if (pun.u[0] & 0x80000000) pun.u[1] |= 1;
|
||||
pun.u[0] <<= 1;
|
||||
} while (pun.u[1] < 0x100000);
|
||||
} else {
|
||||
while (!(pun.u[0] & 0x80000000)) {
|
||||
--bex;
|
||||
pun.u[0] <<= 1;
|
||||
}
|
||||
bex -= 21;
|
||||
pun.u[1] = pun.u[0] >> 11;
|
||||
pun.u[0] <<= 21;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c = '0';
|
||||
bex = 0;
|
||||
}
|
||||
if (flags & FLAGS_PRECISION) {
|
||||
if (prec > 13) prec = 13;
|
||||
if (pun.d && prec < 13) {
|
||||
pun.u[1] |= 0x100000;
|
||||
if (prec < 5) {
|
||||
ui = 1u << ((5 - prec) * 4 - 1);
|
||||
if (pun.u[1] & ui) {
|
||||
if (pun.u[1] & ((ui - 1) | (ui << 1)) || pun.u[0]) {
|
||||
pun.u[1] += ui;
|
||||
BexCheck:
|
||||
if (pun.u[1] & 0x200000) {
|
||||
++bex;
|
||||
pun.u[1] >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (prec == 5) {
|
||||
if (pun.u[0] & 0x80000000) {
|
||||
BumpIt:
|
||||
++pun.u[1];
|
||||
goto BexCheck;
|
||||
}
|
||||
} else {
|
||||
i1 = (13 - prec) * 4;
|
||||
ui = 1u << (i1 - 1);
|
||||
if (pun.u[0] & ui && pun.u[0] & ((ui - 1) | (ui << 1))) {
|
||||
pun.u[0] += ui;
|
||||
if (!(pun.u[0] >> i1)) goto BumpIt;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((ui = pun.u[0])) {
|
||||
ui = __builtin_ctz(ui);
|
||||
prec = 6 + ((32 - ROUNDDOWN(ui, 4)) >> 2) - 1;
|
||||
} else if ((ui = pun.u[1] & 0xfffff)) {
|
||||
ui = __builtin_ctz(ui);
|
||||
prec = (20 - ROUNDDOWN(ui, 4)) >> 2;
|
||||
} else {
|
||||
prec = 0;
|
||||
}
|
||||
}
|
||||
bw = 1;
|
||||
if (bex) {
|
||||
if ((i1 = bex) < 0) i1 = -i1;
|
||||
while (i1 >= 10) {
|
||||
++bw;
|
||||
i1 /= 10;
|
||||
}
|
||||
}
|
||||
if (pun.u[1] & 0x80000000) {
|
||||
pun.u[1] &= 0x7fffffff;
|
||||
if (pun.d || sign) sign = '-';
|
||||
}
|
||||
if ((width -= bw + 5) > 0) {
|
||||
if (sign) --width;
|
||||
if (prec || alt) --width;
|
||||
}
|
||||
if (pun.q && prec > 0) {
|
||||
width -= ROUNDUP(bsrl(pun.q) + 1, 4) >> 2;
|
||||
}
|
||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) {
|
||||
PUT(sign);
|
||||
sign = 0;
|
||||
}
|
||||
do PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
if (sign) PUT(sign);
|
||||
PUT('0');
|
||||
PUT(alphabet[17]);
|
||||
PUT(c);
|
||||
if (prec > 0 || alt) PUT('.');
|
||||
while (prec-- > 0) {
|
||||
PUT(alphabet[(pun.q >> 48) & 0xf]);
|
||||
pun.q <<= 4;
|
||||
}
|
||||
PUT(alphabet[16]);
|
||||
if (bex < 0) {
|
||||
PUT('-');
|
||||
bex = -bex;
|
||||
} else {
|
||||
PUT('+');
|
||||
}
|
||||
for (c = 1; 10 * c <= bex;) c *= 10;
|
||||
for (;;) {
|
||||
i1 = bex / c;
|
||||
PUT('0' + i1);
|
||||
if (!--bw) break;
|
||||
bex -= i1 * c;
|
||||
bex *= 10;
|
||||
if (weaken(__fmt_dtoa)(out, arg, d, flags, prec, sign, width,
|
||||
longdouble, qchar, signbit, alphabet,
|
||||
va) == -1) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
PUT('%');
|
||||
__FMT_PUT('%');
|
||||
break;
|
||||
|
||||
default:
|
||||
PUT(format[-1]);
|
||||
__FMT_PUT(format[-1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!mem);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_FMTS_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_FMTS_H_
|
||||
#ifndef COSMOPOLITAN_LIBC_FMT_FMT_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_FMT_INTERNAL_H_
|
||||
|
||||
#define PRINTF_NTOA_BUFFER_SIZE 144
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define __FMT_PUT(C) \
|
||||
do { \
|
||||
char Buf[1] = {C}; \
|
||||
if (out(Buf, arg, 1) == -1) { \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int __fmt_pad(int (*)(const char *, void *, size_t), void *,
|
||||
unsigned long) hidden;
|
||||
int __fmt_stoa(int (*)(const char *, void *, size_t), void *, void *,
|
||||
|
@ -14,8 +22,9 @@ int __fmt_stoa(int (*)(const char *, void *, size_t), void *, void *,
|
|||
int __fmt_ntoa(int (*)(const char *, void *, size_t), void *, va_list,
|
||||
unsigned char, unsigned long, unsigned long, unsigned long,
|
||||
unsigned char, const char *) hidden;
|
||||
char *__fmt_dtoa(double, int, int, int *, int *, char **) hidden;
|
||||
int __fmt_dtoa(int (*)(const char *, void *, size_t), void *, int, int, int,
|
||||
int, int, bool, char, unsigned char, const char *, va_list);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_FMTS_H_ */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_FMT_INTERNAL_H_ */
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/divmod10.internal.h"
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/fmt/fmt.internal.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/fmt/fmt.internal.h"
|
||||
|
||||
int __fmt_pad(int out(const char *, void *, size_t), void *arg,
|
||||
unsigned long n) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_PFLINK_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_PFLINK_H_
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -23,7 +22,6 @@
|
|||
({ \
|
||||
if (___PFLINK(FMT, strpbrk, "faAeg")) STATIC_YOINK("__fmt_dtoa"); \
|
||||
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
|
||||
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
|
||||
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
|
||||
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
|
||||
___PFLINK(FMT, strpbrk, "0123456789"))) { \
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/fmt/fmt.internal.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -46,7 +46,7 @@ static int __fmt_stoa_wide(out_f out, void *a, uint64_t w) {
|
|||
|
||||
static int __fmt_stoa_bing(out_f out, void *a, uint64_t w) {
|
||||
char buf[8];
|
||||
w = tpenc((*weaken(kCp437))[w & 0xFF]);
|
||||
w = tpenc(kCp437[w & 0xFF]);
|
||||
WRITE64LE(buf, w);
|
||||
return out(buf, a, w ? (bsr(w) >> 3) + 1 : 1);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp PowerProf,__imp_SetSuspendState,SetSuspendState,0
|
||||
.imp PowrProf,__imp_SetSuspendState,SetSuspendState,0
|
||||
|
||||
.text.windows
|
||||
SetSuspendState:
|
|
@ -4052,10 +4052,10 @@ imp 'SetTcpEntry' SetTcpEntry iphlpapi 0
|
|||
imp 'UnenableRouter' UnenableRouter iphlpapi 0
|
||||
imp 'UnregisterInterfaceTimestampConfigChange' UnregisterInterfaceTimestampConfigChange iphlpapi 0
|
||||
|
||||
# POWERPROF.DLL
|
||||
# POWRPROF.DLL
|
||||
#
|
||||
# Name Actual DLL Hint Arity
|
||||
imp 'SetSuspendState' SetSuspendState PowerProf 0 3
|
||||
imp 'SetSuspendState' SetSuspendState PowrProf 0 3
|
||||
|
||||
# PDH.DLL
|
||||
#
|
||||
|
|
|
@ -311,22 +311,22 @@ $(LIBC_NT_IPHLPAPI_A).pkg: \
|
|||
|
||||
#───────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
LIBC_NT_ARTIFACTS += LIBC_NT_POWERPROF_A
|
||||
LIBC_NT_POWERPROF = $(LIBC_NT_POWERPROF_A_DEPS) $(LIBC_NT_POWERPROF_A)
|
||||
LIBC_NT_POWERPROF_A = o/$(MODE)/libc/nt/powerprof.a
|
||||
LIBC_NT_POWERPROF_A_SRCS := $(wildcard libc/nt/PowerProf/*.s)
|
||||
LIBC_NT_POWERPROF_A_OBJS = $(LIBC_NT_POWERPROF_A_SRCS:%.s=o/$(MODE)/%.o)
|
||||
LIBC_NT_POWERPROF_A_CHECKS = $(LIBC_NT_POWERPROF_A).pkg
|
||||
LIBC_NT_POWERPROF_A_DIRECTDEPS = LIBC_NT_KERNEL32
|
||||
LIBC_NT_POWERPROF_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_NT_POWERPROF_A_DIRECTDEPS),$($(x))))
|
||||
$(LIBC_NT_POWERPROF_A): \
|
||||
libc/nt/PowerProf/ \
|
||||
$(LIBC_NT_POWERPROF_A).pkg \
|
||||
$(LIBC_NT_POWERPROF_A_OBJS)
|
||||
$(LIBC_NT_POWERPROF_A).pkg: \
|
||||
$(LIBC_NT_POWERPROF_A_OBJS) \
|
||||
$(foreach x,$(LIBC_NT_POWERPROF_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
LIBC_NT_ARTIFACTS += LIBC_NT_POWRPROF_A
|
||||
LIBC_NT_POWRPROF = $(LIBC_NT_POWRPROF_A_DEPS) $(LIBC_NT_POWRPROF_A)
|
||||
LIBC_NT_POWRPROF_A = o/$(MODE)/libc/nt/powrprof.a
|
||||
LIBC_NT_POWRPROF_A_SRCS := $(wildcard libc/nt/PowrProf/*.s)
|
||||
LIBC_NT_POWRPROF_A_OBJS = $(LIBC_NT_POWRPROF_A_SRCS:%.s=o/$(MODE)/%.o)
|
||||
LIBC_NT_POWRPROF_A_CHECKS = $(LIBC_NT_POWRPROF_A).pkg
|
||||
LIBC_NT_POWRPROF_A_DIRECTDEPS = LIBC_NT_KERNEL32
|
||||
LIBC_NT_POWRPROF_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_NT_POWRPROF_A_DIRECTDEPS),$($(x))))
|
||||
$(LIBC_NT_POWRPROF_A): \
|
||||
libc/nt/PowrProf/ \
|
||||
$(LIBC_NT_POWRPROF_A).pkg \
|
||||
$(LIBC_NT_POWRPROF_A_OBJS)
|
||||
$(LIBC_NT_POWRPROF_A).pkg: \
|
||||
$(LIBC_NT_POWRPROF_A_OBJS) \
|
||||
$(foreach x,$(LIBC_NT_POWRPROF_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
#───────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,10 +16,379 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/fmt.internal.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
|
||||
char *__fmt_dtoa(double d0, int mode, int ndigits, int *decpt, int *sign,
|
||||
char **rve) {
|
||||
return dtoa(d0, mode, ndigits, decpt, sign, rve);
|
||||
static const char kSpecialFloats[2][2][4] = {{"INF", "inf"}, {"NAN", "nan"}};
|
||||
|
||||
static void __fmt_free_dtoa(char **mem) {
|
||||
if (*mem) {
|
||||
freedtoa(*mem);
|
||||
*mem = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int __fmt_dtoa(int (*out)(const char *, void *, size_t), void *arg, int d,
|
||||
int flags, int prec, int sign, int width, bool longdouble,
|
||||
char qchar, unsigned char signbit, const char *alphabet,
|
||||
va_list va) {
|
||||
union {
|
||||
double d;
|
||||
uint32_t u[2];
|
||||
uint64_t q;
|
||||
} pun;
|
||||
int c, k, i1, ui, bw, bex, sgn, prec1, decpt;
|
||||
char *s, *p, *q, *se, *mem, special[8];
|
||||
mem = 0;
|
||||
switch (d) {
|
||||
case 'F':
|
||||
case 'f':
|
||||
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
FormatDtoa:
|
||||
assert(!mem);
|
||||
s = mem = dtoa(pun.d, 3, prec, &decpt, &sgn, &se);
|
||||
if (decpt == 9999) {
|
||||
Format9999:
|
||||
bzero(special, sizeof(special));
|
||||
p = q = special;
|
||||
if (sgn) {
|
||||
*q++ = '-';
|
||||
} else if (flags & FLAGS_PLUS) {
|
||||
*q++ = '+';
|
||||
} else if (flags & FLAGS_SPACE) {
|
||||
*q++ = ' ';
|
||||
}
|
||||
memcpy(q, kSpecialFloats[*s == 'N'][d >= 'a'], 4);
|
||||
FormatThatThing:
|
||||
__fmt_free_dtoa(&mem);
|
||||
mem = 0;
|
||||
prec = 0;
|
||||
flags &= ~(FLAGS_PRECISION | FLAGS_PLUS | FLAGS_SPACE);
|
||||
goto FormatString;
|
||||
}
|
||||
FormatReal:
|
||||
if (sgn) sign = '-';
|
||||
if (prec > 0) width -= prec;
|
||||
if (width > 0) {
|
||||
if (sign) --width;
|
||||
if (decpt <= 0) {
|
||||
--width;
|
||||
if (prec > 0) --width;
|
||||
} else {
|
||||
if (s == se) decpt = 1;
|
||||
width -= decpt;
|
||||
if (prec > 0) --width;
|
||||
}
|
||||
}
|
||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) __FMT_PUT(sign);
|
||||
sign = 0;
|
||||
do
|
||||
__FMT_PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do
|
||||
__FMT_PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
if (sign) __FMT_PUT(sign);
|
||||
if (decpt <= 0) {
|
||||
__FMT_PUT('0');
|
||||
if (prec > 0) __FMT_PUT('.');
|
||||
while (decpt < 0) {
|
||||
__FMT_PUT('0');
|
||||
prec--;
|
||||
decpt++;
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
if ((c = *s)) {
|
||||
s++;
|
||||
} else {
|
||||
c = '0';
|
||||
}
|
||||
__FMT_PUT(c);
|
||||
} while (--decpt > 0);
|
||||
if (prec > 0) __FMT_PUT('.');
|
||||
}
|
||||
while (--prec >= 0) {
|
||||
if ((c = *s)) {
|
||||
s++;
|
||||
} else {
|
||||
c = '0';
|
||||
}
|
||||
__FMT_PUT(c);
|
||||
}
|
||||
while (--width >= 0) {
|
||||
__FMT_PUT(' ');
|
||||
}
|
||||
__fmt_free_dtoa(&mem);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
case 'g':
|
||||
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
if (prec < 0) prec = 0;
|
||||
assert(!mem);
|
||||
s = mem = dtoa(pun.d, prec ? 2 : 0, prec, &decpt, &sgn, &se);
|
||||
if (decpt == 9999) goto Format9999;
|
||||
c = se - s;
|
||||
prec1 = prec;
|
||||
if (!prec) {
|
||||
prec = c;
|
||||
prec1 = c + (s[1] ? 5 : 4);
|
||||
}
|
||||
if (decpt > -4 && decpt <= prec1) {
|
||||
prec = c - decpt;
|
||||
if (prec < 0) prec = 0;
|
||||
goto FormatReal;
|
||||
}
|
||||
d -= 2;
|
||||
if (prec > c) prec = c;
|
||||
--prec;
|
||||
goto FormatExpo;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
if (prec < 0) prec = 0;
|
||||
if (!dtoa) {
|
||||
p = "?";
|
||||
goto FormatThatThing;
|
||||
}
|
||||
assert(!mem);
|
||||
s = mem = dtoa(pun.d, 2, prec + 1, &decpt, &sgn, &se);
|
||||
if (decpt == 9999) goto Format9999;
|
||||
FormatExpo:
|
||||
if (sgn) sign = '-';
|
||||
if ((width -= prec + 5) > 0) {
|
||||
if (sign) --width;
|
||||
if (prec) --width;
|
||||
}
|
||||
if ((c = --decpt) < 0) c = -c;
|
||||
while (c >= 100) {
|
||||
--width;
|
||||
c /= 10;
|
||||
}
|
||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) __FMT_PUT(sign);
|
||||
sign = 0;
|
||||
do
|
||||
__FMT_PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do
|
||||
__FMT_PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
if (sign) __FMT_PUT(sign);
|
||||
__FMT_PUT(*s++);
|
||||
if (prec) __FMT_PUT('.');
|
||||
while (--prec >= 0) {
|
||||
if ((c = *s)) {
|
||||
s++;
|
||||
} else {
|
||||
c = '0';
|
||||
}
|
||||
__FMT_PUT(c);
|
||||
}
|
||||
__fmt_free_dtoa(&mem);
|
||||
__FMT_PUT(d);
|
||||
if (decpt < 0) {
|
||||
__FMT_PUT('-');
|
||||
decpt = -decpt;
|
||||
} else {
|
||||
__FMT_PUT('+');
|
||||
}
|
||||
for (c = 2, k = 10; 10 * k <= decpt; c++) k *= 10;
|
||||
for (;;) {
|
||||
i1 = decpt / k;
|
||||
__FMT_PUT(i1 + '0');
|
||||
if (--c <= 0) break;
|
||||
decpt -= i1 * k;
|
||||
decpt *= 10;
|
||||
}
|
||||
while (--width >= 0) {
|
||||
__FMT_PUT(' ');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
alphabet = "0123456789abcdefpx";
|
||||
goto FormatBinary;
|
||||
case 'A':
|
||||
alphabet = "0123456789ABCDEFPX";
|
||||
FormatBinary:
|
||||
if (longdouble) {
|
||||
pun.d = va_arg(va, long double);
|
||||
} else {
|
||||
pun.d = va_arg(va, double);
|
||||
}
|
||||
if ((pun.u[1] & 0x7ff00000) == 0x7ff00000) {
|
||||
goto FormatDtoa;
|
||||
}
|
||||
if (pun.u[1] & 0x80000000) {
|
||||
sign = '-';
|
||||
pun.u[1] &= 0x7fffffff;
|
||||
}
|
||||
if (pun.d) {
|
||||
c = '1';
|
||||
bex = (pun.u[1] >> 20) - 1023;
|
||||
pun.u[1] &= 0xfffff;
|
||||
if (bex == -1023) {
|
||||
++bex;
|
||||
if (pun.u[1]) {
|
||||
do {
|
||||
--bex;
|
||||
pun.u[1] <<= 1;
|
||||
if (pun.u[0] & 0x80000000) pun.u[1] |= 1;
|
||||
pun.u[0] <<= 1;
|
||||
} while (pun.u[1] < 0x100000);
|
||||
} else {
|
||||
while (!(pun.u[0] & 0x80000000)) {
|
||||
--bex;
|
||||
pun.u[0] <<= 1;
|
||||
}
|
||||
bex -= 21;
|
||||
pun.u[1] = pun.u[0] >> 11;
|
||||
pun.u[0] <<= 21;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c = '0';
|
||||
bex = 0;
|
||||
}
|
||||
if (flags & FLAGS_PRECISION) {
|
||||
if (prec > 13) prec = 13;
|
||||
if (pun.d && prec < 13) {
|
||||
pun.u[1] |= 0x100000;
|
||||
if (prec < 5) {
|
||||
ui = 1u << ((5 - prec) * 4 - 1);
|
||||
if (pun.u[1] & ui) {
|
||||
if (pun.u[1] & ((ui - 1) | (ui << 1)) || pun.u[0]) {
|
||||
pun.u[1] += ui;
|
||||
BexCheck:
|
||||
if (pun.u[1] & 0x200000) {
|
||||
++bex;
|
||||
pun.u[1] >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (prec == 5) {
|
||||
if (pun.u[0] & 0x80000000) {
|
||||
BumpIt:
|
||||
++pun.u[1];
|
||||
goto BexCheck;
|
||||
}
|
||||
} else {
|
||||
i1 = (13 - prec) * 4;
|
||||
ui = 1u << (i1 - 1);
|
||||
if (pun.u[0] & ui && pun.u[0] & ((ui - 1) | (ui << 1))) {
|
||||
pun.u[0] += ui;
|
||||
if (!(pun.u[0] >> i1)) goto BumpIt;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((ui = pun.u[0])) {
|
||||
ui = __builtin_ctz(ui);
|
||||
prec = 6 + ((32 - ROUNDDOWN(ui, 4)) >> 2) - 1;
|
||||
} else if ((ui = pun.u[1] & 0xfffff)) {
|
||||
ui = __builtin_ctz(ui);
|
||||
prec = (20 - ROUNDDOWN(ui, 4)) >> 2;
|
||||
} else {
|
||||
prec = 0;
|
||||
}
|
||||
}
|
||||
bw = 1;
|
||||
if (bex) {
|
||||
if ((i1 = bex) < 0) i1 = -i1;
|
||||
while (i1 >= 10) {
|
||||
++bw;
|
||||
i1 /= 10;
|
||||
}
|
||||
}
|
||||
if (pun.u[1] & 0x80000000) {
|
||||
pun.u[1] &= 0x7fffffff;
|
||||
if (pun.d || sign) sign = '-';
|
||||
}
|
||||
if ((width -= bw + 5) > 0) {
|
||||
if (sign) --width;
|
||||
if (prec) --width;
|
||||
}
|
||||
if (pun.q && prec > 0) {
|
||||
width -= ROUNDUP(bsrl(pun.q) + 1, 4) >> 2;
|
||||
}
|
||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) {
|
||||
__FMT_PUT(sign);
|
||||
sign = 0;
|
||||
}
|
||||
do
|
||||
__FMT_PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do
|
||||
__FMT_PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
if (sign) __FMT_PUT(sign);
|
||||
__FMT_PUT('0');
|
||||
__FMT_PUT(alphabet[17]);
|
||||
__FMT_PUT(c);
|
||||
if (prec > 0) __FMT_PUT('.');
|
||||
while (prec-- > 0) {
|
||||
__FMT_PUT(alphabet[(pun.q >> 48) & 0xf]);
|
||||
pun.q <<= 4;
|
||||
}
|
||||
__FMT_PUT(alphabet[16]);
|
||||
if (bex < 0) {
|
||||
__FMT_PUT('-');
|
||||
bex = -bex;
|
||||
} else {
|
||||
__FMT_PUT('+');
|
||||
}
|
||||
for (c = 1; 10 * c <= bex;) c *= 10;
|
||||
for (;;) {
|
||||
i1 = bex / c;
|
||||
__FMT_PUT('0' + i1);
|
||||
if (!--bw) break;
|
||||
bex -= i1 * c;
|
||||
bex *= 10;
|
||||
}
|
||||
break;
|
||||
|
||||
FormatString:
|
||||
if (__fmt_stoa(out, arg, p, flags, prec, width, signbit, qchar) == -1) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue