refactor: libc - share printf, split the float path, fix relink deps
This commit is contained in:
@@ -16,6 +16,8 @@ programs/obj/
|
|||||||
programs/src/*/obj/
|
programs/src/*/obj/
|
||||||
programs/libs/*/obj/
|
programs/libs/*/obj/
|
||||||
programs/lib/libc/liblibc.a
|
programs/lib/libc/liblibc.a
|
||||||
|
programs/lib/libc/liblibc-full.a
|
||||||
|
programs/lib/libc/obj/libc-merged.o
|
||||||
programs/lib/libloader/liblibloader.a
|
programs/lib/libloader/liblibloader.a
|
||||||
programs/gui/icons/
|
programs/gui/icons/
|
||||||
CLAUDE.md
|
CLAUDE.md
|
||||||
|
|||||||
+29
-9
@@ -105,8 +105,24 @@ lib/bearssl/build/libbearssl.a:
|
|||||||
bearssl: lib/bearssl/build/libbearssl.a
|
bearssl: lib/bearssl/build/libbearssl.a
|
||||||
|
|
||||||
# Build shared libc static library.
|
# Build shared libc static library.
|
||||||
libc:
|
#
|
||||||
$(MAKE) -C lib/libc
|
# The archives and CRT objects get a real file rule, not just the `libc`
|
||||||
|
# phony, so that programs can list them as prerequisites and actually relink
|
||||||
|
# when libc changes. A phony prerequisite would instead make every program
|
||||||
|
# permanently out of date; no prerequisite at all (the old state) both races
|
||||||
|
# under -j and silently leaves programs linked against a stale libc.
|
||||||
|
# Grouped target (&:, GNU make 4.3+): one sub-make produces all of them.
|
||||||
|
LIBC_DIR := lib/libc
|
||||||
|
LIBC_LIB := $(LIBC_DIR)/liblibc.a
|
||||||
|
LIBC_SRCS := $(wildcard $(LIBC_DIR)/*.c $(LIBC_DIR)/*.h $(LIBC_DIR)/*.S \
|
||||||
|
$(LIBC_DIR)/crt/*.c) $(LIBC_DIR)/Makefile
|
||||||
|
LIBC_OUTPUTS := $(LIBC_LIB) $(LIBC_DIR)/liblibc-full.a \
|
||||||
|
$(LIBC_DIR)/crt1.o $(LIBC_DIR)/crti.o $(LIBC_DIR)/crtn.o
|
||||||
|
|
||||||
|
$(LIBC_OUTPUTS) &: $(LIBC_SRCS)
|
||||||
|
$(MAKE) -C $(LIBC_DIR)
|
||||||
|
|
||||||
|
libc: $(LIBC_OUTPUTS)
|
||||||
|
|
||||||
# Build shared TLS helper library.
|
# Build shared TLS helper library.
|
||||||
tls: bearssl libc
|
tls: bearssl libc
|
||||||
@@ -144,8 +160,8 @@ libjpegwrite: libc
|
|||||||
imageviewer: libc libjpeg
|
imageviewer: libc libjpeg
|
||||||
$(MAKE) -C src/imageviewer
|
$(MAKE) -C src/imageviewer
|
||||||
|
|
||||||
# Build fontpreview standalone GUI client (no library deps).
|
# Build fontpreview standalone GUI client (links libc).
|
||||||
fontpreview:
|
fontpreview: libc
|
||||||
$(MAKE) -C src/fontpreview
|
$(MAKE) -C src/fontpreview
|
||||||
|
|
||||||
# Build spreadsheet standalone GUI client (depends on libc and libdialogs).
|
# Build spreadsheet standalone GUI client (depends on libc and libdialogs).
|
||||||
@@ -271,8 +287,9 @@ mandelbrot: libc
|
|||||||
rpgdemo: libc
|
rpgdemo: libc
|
||||||
$(MAKE) -C src/rpgdemo
|
$(MAKE) -C src/rpgdemo
|
||||||
|
|
||||||
# Build doom via its own Makefile (depends on libc).
|
# Build doom via its own Makefile (depends on libc and the shared-lib loader,
|
||||||
doom: libc
|
# both of which it links).
|
||||||
|
doom: libc libloader
|
||||||
$(MAKE) -C src/doom
|
$(MAKE) -C src/doom
|
||||||
|
|
||||||
# Build screenshot tool (depends on libc, libjpegwrite, libloader, and libdialogs).
|
# Build screenshot tool (depends on libc, libjpegwrite, libloader, and libdialogs).
|
||||||
@@ -369,10 +386,10 @@ $(BINDIR)/os/wallpapers/%: $(WPDIR)/%
|
|||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
# Build each system program from its source files.
|
# Build each system program from its source files.
|
||||||
$(BINDIR)/os/%.elf: src/%/main.cpp link.ld GNUmakefile
|
$(BINDIR)/os/%.elf: src/%/main.cpp link.ld GNUmakefile $(LIBC_LIB)
|
||||||
mkdir -p $(BINDIR)/os obj/$*
|
mkdir -p $(BINDIR)/os obj/$*
|
||||||
$(CXX) $(CXXFLAGS) -c src/$*/main.cpp -o obj/$*/main.o
|
$(CXX) $(CXXFLAGS) -c src/$*/main.cpp -o obj/$*/main.o
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) obj/$*/main.o lib/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) obj/$*/main.o $(LIBC_LIB) -o $@
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Native development kit (Montauk SDK): binutils built for MontaukOS
|
# Native development kit (Montauk SDK): binutils built for MontaukOS
|
||||||
@@ -399,7 +416,10 @@ ifneq ($(wildcard $(NATIVE_BIN)/as),)
|
|||||||
cp -r include/montauk $(BINDIR)/sdk/include/montauk
|
cp -r include/montauk $(BINDIR)/sdk/include/montauk
|
||||||
cp -r include/Api $(BINDIR)/sdk/include/Api
|
cp -r include/Api $(BINDIR)/sdk/include/Api
|
||||||
cp -r ../kernel/freestnd-cxx-hdrs/x86_64/include/. $(BINDIR)/sdk/include/
|
cp -r ../kernel/freestnd-cxx-hdrs/x86_64/include/. $(BINDIR)/sdk/include/
|
||||||
cp lib/libc/liblibc.a $(BINDIR)/sdk/lib/libc.a
|
# liblibc-full.a, not liblibc.a: on-OS builds cannot pass
|
||||||
|
# -Wl,-u,_pf_putfloat, so the sysroot ships the variant with the printf
|
||||||
|
# float path already bound in. See lib/libc/Makefile.
|
||||||
|
cp lib/libc/liblibc-full.a $(BINDIR)/sdk/lib/libc.a
|
||||||
cp lib/libc/crt1.o lib/libc/crti.o lib/libc/crtn.o $(BINDIR)/sdk/lib/
|
cp lib/libc/crt1.o lib/libc/crti.o lib/libc/crtn.o $(BINDIR)/sdk/lib/
|
||||||
ar rcs $(BINDIR)/sdk/lib/libm.a
|
ar rcs $(BINDIR)/sdk/lib/libm.a
|
||||||
cp ../toolchain/local/x86_64-montauk/lib/libstdc++.a $(BINDIR)/sdk/lib/libstdc++.a
|
cp ../toolchain/local/x86_64-montauk/lib/libstdc++.a $(BINDIR)/sdk/lib/libstdc++.a
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-monta
|
|||||||
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
||||||
CC := $(TOOLCHAIN_PREFIX)gcc
|
CC := $(TOOLCHAIN_PREFIX)gcc
|
||||||
AR := $(TOOLCHAIN_PREFIX)ar
|
AR := $(TOOLCHAIN_PREFIX)ar
|
||||||
|
LD := $(TOOLCHAIN_PREFIX)ld
|
||||||
else
|
else
|
||||||
CC := gcc
|
CC := gcc
|
||||||
AR := ar
|
AR := ar
|
||||||
|
LD := ld
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# ---- Paths ----
|
# ---- Paths ----
|
||||||
@@ -63,16 +65,25 @@ CRT_CFLAGS := \
|
|||||||
# ---- Target ----
|
# ---- Target ----
|
||||||
|
|
||||||
TARGET := liblibc.a
|
TARGET := liblibc.a
|
||||||
|
SDK_TARGET := liblibc-full.a
|
||||||
CRT_OBJS := crt1.o crti.o crtn.o
|
CRT_OBJS := crt1.o crti.o crtn.o
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET) $(CRT_OBJS)
|
all: $(TARGET) $(SDK_TARGET) $(CRT_OBJS)
|
||||||
|
|
||||||
$(TARGET): $(OBJDIR)/libc.o $(ASM_OBJS)
|
# printf_float.o is deliberately a SEPARATE archive member: a weak undefined
|
||||||
|
# reference does not extract an archive member, so programs that never format
|
||||||
|
# a float leave the decimal-conversion and pow/exp/log code behind. Programs
|
||||||
|
# that do need %e/%f/%g must link with -Wl,-u,_pf_putfloat to force it in.
|
||||||
|
$(TARGET): $(OBJDIR)/libc.o $(OBJDIR)/printf_float.o $(ASM_OBJS)
|
||||||
$(AR) rcs $@ $^
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
$(OBJDIR)/libc.o: libc.c Makefile
|
$(OBJDIR)/libc.o: libc.c printf_internal.h Makefile
|
||||||
|
@mkdir -p $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/printf_float.o: printf_float.c printf_internal.h Makefile
|
||||||
@mkdir -p $(OBJDIR)
|
@mkdir -p $(OBJDIR)
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
@@ -80,6 +91,17 @@ $(OBJDIR)/setjmp.o: setjmp.S Makefile
|
|||||||
@mkdir -p $(OBJDIR)
|
@mkdir -p $(OBJDIR)
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Variant shipped in the on-OS sysroots (0:/sdk/lib/libc.a and tcc's), where
|
||||||
|
# nobody can pass -Wl,-u,_pf_putfloat by hand. `ld -r` binds vsnprintf's weak
|
||||||
|
# reference to the float module at merge time, so %e/%f/%g just work for code
|
||||||
|
# compiled ON MontaukOS. Function-level --gc-sections still applies to the
|
||||||
|
# rest; only the float path is pinned. Image size is not a concern here.
|
||||||
|
$(SDK_TARGET): $(OBJDIR)/libc-merged.o $(ASM_OBJS)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
$(OBJDIR)/libc-merged.o: $(OBJDIR)/libc.o $(OBJDIR)/printf_float.o
|
||||||
|
$(LD) -r -o $@ $(OBJDIR)/libc.o $(OBJDIR)/printf_float.o
|
||||||
|
|
||||||
crt1.o: $(CRTDIR)/crt1.c Makefile
|
crt1.o: $(CRTDIR)/crt1.c Makefile
|
||||||
$(CC) $(CRT_CFLAGS) -c $< -o $@
|
$(CC) $(CRT_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
@@ -90,4 +112,4 @@ crtn.o: $(CRTDIR)/crtn.c Makefile
|
|||||||
$(CC) $(CRT_CFLAGS) -c $< -o $@
|
$(CC) $(CRT_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJDIR) $(TARGET) $(CRT_OBJS)
|
rm -rf $(OBJDIR) $(TARGET) $(SDK_TARGET) $(CRT_OBJS)
|
||||||
|
|||||||
+19
-226
@@ -1150,13 +1150,17 @@ int system(const char *command) {
|
|||||||
printf family — vsnprintf core
|
printf family — vsnprintf core
|
||||||
======================================================================== */
|
======================================================================== */
|
||||||
|
|
||||||
struct _pf_state {
|
#include "printf_internal.h"
|
||||||
char *buf;
|
|
||||||
size_t pos;
|
|
||||||
size_t max;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void _pf_putc(struct _pf_state *st, char c) {
|
/* Weak: resolves to 0 unless the program pulls in printf_float.o with
|
||||||
|
-Wl,-u,_pf_putfloat. See the %e/%f/%g case in vsnprintf below. */
|
||||||
|
extern __attribute__((weak)) void _pf_putfloat(struct _pf_state *st, double v,
|
||||||
|
char conv, int precision,
|
||||||
|
int width, char pad,
|
||||||
|
int left_align, int plus,
|
||||||
|
int space, int alt);
|
||||||
|
|
||||||
|
void _pf_putc(struct _pf_state *st, char c) {
|
||||||
if (st->pos < st->max)
|
if (st->pos < st->max)
|
||||||
st->buf[st->pos] = c;
|
st->buf[st->pos] = c;
|
||||||
st->pos++;
|
st->pos++;
|
||||||
@@ -1208,226 +1212,6 @@ static void _pf_putnum(struct _pf_state *st, unsigned long val, int base, int up
|
|||||||
_pf_putc(st, tmp[--i]);
|
_pf_putc(st, tmp[--i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Union for double bit manipulation (used by float formatting and math). */
|
|
||||||
typedef union { double d; uint64_t u; } _dbl_bits;
|
|
||||||
|
|
||||||
/* Base-10 exponent of the leading digit of a positive finite value, i.e. the
|
|
||||||
E such that value = m * 10^E with m in [1, 10). No rounding is applied. */
|
|
||||||
static int _pf_exp10(double v) {
|
|
||||||
int E = (int)floor(log10(v));
|
|
||||||
double s = v / pow(10.0, (double)E);
|
|
||||||
if (s >= 10.0) E++;
|
|
||||||
else if (s < 1.0) E--;
|
|
||||||
return E;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate `nsig` significant decimal digits of a positive finite value into
|
|
||||||
`out` (ASCII, no terminator). Returns the base-10 exponent of the leading
|
|
||||||
digit, i.e. value ~= (out[0].out[1..]) * 10^E. Rounding is half-up and may
|
|
||||||
carry into a new leading digit, bumping the returned exponent. */
|
|
||||||
static int _pf_gendigits(double v, int nsig, char *out) {
|
|
||||||
int E = (int)floor(log10(v));
|
|
||||||
double scale = v / pow(10.0, (double)E);
|
|
||||||
/* Correct estimate errors so scale lands in [1, 10). */
|
|
||||||
if (scale >= 10.0) { scale /= 10.0; E++; }
|
|
||||||
else if (scale < 1.0) { scale *= 10.0; E--; }
|
|
||||||
|
|
||||||
for (int i = 0; i < nsig; i++) {
|
|
||||||
int d = (int)scale;
|
|
||||||
if (d < 0) d = 0; else if (d > 9) d = 9;
|
|
||||||
out[i] = (char)('0' + d);
|
|
||||||
scale = (scale - d) * 10.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scale >= 5.0) { /* round up based on the next digit */
|
|
||||||
int i = nsig - 1;
|
|
||||||
while (i >= 0) {
|
|
||||||
if (out[i] == '9') { out[i] = '0'; i--; }
|
|
||||||
else { out[i]++; break; }
|
|
||||||
}
|
|
||||||
if (i < 0) { out[0] = '1'; E++; } /* all nines carried out */
|
|
||||||
}
|
|
||||||
return E;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append the two-or-more-digit exponent field of %e/%g ("e+NN"). */
|
|
||||||
static void _pf_put_exp(char *mbuf, int *mlen, int E, int upper) {
|
|
||||||
int m = *mlen;
|
|
||||||
mbuf[m++] = upper ? 'E' : 'e';
|
|
||||||
int ex = E; char es = '+';
|
|
||||||
if (ex < 0) { es = '-'; ex = -ex; }
|
|
||||||
mbuf[m++] = es;
|
|
||||||
char eb[8]; int el = 0;
|
|
||||||
if (ex == 0) eb[el++] = '0';
|
|
||||||
while (ex > 0) { eb[el++] = (char)('0' + ex % 10); ex /= 10; }
|
|
||||||
while (el < 2) eb[el++] = '0';
|
|
||||||
while (el > 0) mbuf[m++] = eb[--el];
|
|
||||||
*mlen = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Format a floating-point value for the %e/%f/%g conversions (and uppercase
|
|
||||||
variants), honoring precision, width, padding and sign flags. */
|
|
||||||
static void _pf_putfloat(struct _pf_state *st, double v, char conv,
|
|
||||||
int precision, int width, char pad,
|
|
||||||
int left_align, int plus, int space, int alt) {
|
|
||||||
int upper = (conv >= 'A' && conv <= 'Z');
|
|
||||||
char lc = upper ? (char)(conv - 'A' + 'a') : conv;
|
|
||||||
|
|
||||||
_dbl_bits bits; bits.d = v;
|
|
||||||
int neg = (int)(bits.u >> 63);
|
|
||||||
uint64_t expo = (bits.u >> 52) & 0x7FF;
|
|
||||||
uint64_t mant = bits.u & 0x000FFFFFFFFFFFFFULL;
|
|
||||||
|
|
||||||
char sign = 0;
|
|
||||||
if (neg) sign = '-';
|
|
||||||
else if (plus) sign = '+';
|
|
||||||
else if (space) sign = ' ';
|
|
||||||
|
|
||||||
/* Infinity / NaN: never zero-padded. */
|
|
||||||
if (expo == 0x7FF) {
|
|
||||||
const char *word = mant ? (upper ? "NAN" : "nan") : (upper ? "INF" : "inf");
|
|
||||||
if (mant) sign = 0;
|
|
||||||
char tmp[8]; int tl = 0;
|
|
||||||
if (sign) tmp[tl++] = sign;
|
|
||||||
for (const char *p = word; *p; p++) tmp[tl++] = *p;
|
|
||||||
if (!left_align) for (int w = tl; w < width; w++) _pf_putc(st, ' ');
|
|
||||||
for (int i = 0; i < tl; i++) _pf_putc(st, tmp[i]);
|
|
||||||
if (left_align) for (int w = tl; w < width; w++) _pf_putc(st, ' ');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (precision < 0) precision = 6;
|
|
||||||
if (precision > 340) precision = 340;
|
|
||||||
|
|
||||||
double av = neg ? -v : v;
|
|
||||||
|
|
||||||
char mbuf[800];
|
|
||||||
int mlen = 0;
|
|
||||||
|
|
||||||
if (lc == 'e') {
|
|
||||||
int nsig = precision + 1;
|
|
||||||
char dig[400];
|
|
||||||
int E;
|
|
||||||
if (av == 0.0) { for (int i = 0; i < nsig; i++) dig[i] = '0'; E = 0; }
|
|
||||||
else E = _pf_gendigits(av, nsig, dig);
|
|
||||||
mbuf[mlen++] = dig[0];
|
|
||||||
if (precision > 0 || alt) {
|
|
||||||
mbuf[mlen++] = '.';
|
|
||||||
for (int i = 1; i <= precision; i++) mbuf[mlen++] = dig[i];
|
|
||||||
}
|
|
||||||
_pf_put_exp(mbuf, &mlen, E, upper);
|
|
||||||
}
|
|
||||||
else if (lc == 'f') {
|
|
||||||
if (av == 0.0) {
|
|
||||||
mbuf[mlen++] = '0';
|
|
||||||
if (precision > 0 || alt) {
|
|
||||||
mbuf[mlen++] = '.';
|
|
||||||
for (int i = 0; i < precision; i++) mbuf[mlen++] = '0';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int Ef = _pf_exp10(av);
|
|
||||||
int keep = Ef + 1 + precision;
|
|
||||||
if (keep <= 0) {
|
|
||||||
char d1[4];
|
|
||||||
_pf_gendigits(av, 1, d1);
|
|
||||||
int roundUp = (keep == 0 && d1[0] >= '5');
|
|
||||||
mbuf[mlen++] = '0';
|
|
||||||
if (precision > 0 || alt) {
|
|
||||||
mbuf[mlen++] = '.';
|
|
||||||
for (int i = 0; i < precision; i++) mbuf[mlen++] = '0';
|
|
||||||
}
|
|
||||||
if (roundUp) mbuf[mlen - 1] = '1';
|
|
||||||
} else {
|
|
||||||
if (keep > 380) keep = 380;
|
|
||||||
char dig[400];
|
|
||||||
int E = _pf_gendigits(av, keep, dig);
|
|
||||||
int len = keep;
|
|
||||||
int intlen = (E >= 0) ? (E + 1) : 0;
|
|
||||||
if (intlen == 0) mbuf[mlen++] = '0';
|
|
||||||
else for (int i = 0; i < intlen; i++) mbuf[mlen++] = (i < len ? dig[i] : '0');
|
|
||||||
if (precision > 0 || alt) {
|
|
||||||
mbuf[mlen++] = '.';
|
|
||||||
if (E < 0) {
|
|
||||||
int lead = -E - 1;
|
|
||||||
for (int k = 0; k < precision; k++) {
|
|
||||||
if (k < lead) mbuf[mlen++] = '0';
|
|
||||||
else { int idx = k - lead; mbuf[mlen++] = (idx < len ? dig[idx] : '0'); }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int k = 0; k < precision; k++) {
|
|
||||||
int idx = intlen + k;
|
|
||||||
mbuf[mlen++] = (idx < len ? dig[idx] : '0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* 'g' / 'G' */
|
|
||||||
int P = precision; if (P == 0) P = 1;
|
|
||||||
char dig[400];
|
|
||||||
int E;
|
|
||||||
if (av == 0.0) { E = 0; for (int i = 0; i < P; i++) dig[i] = '0'; }
|
|
||||||
else E = _pf_gendigits(av, P, dig);
|
|
||||||
int len = P;
|
|
||||||
int useExp = (E < -4 || E >= P);
|
|
||||||
int hasDot = 0;
|
|
||||||
if (useExp) {
|
|
||||||
int fp = P - 1;
|
|
||||||
mbuf[mlen++] = dig[0];
|
|
||||||
if (fp > 0 || alt) {
|
|
||||||
mbuf[mlen++] = '.'; hasDot = 1;
|
|
||||||
for (int i = 1; i <= fp; i++) mbuf[mlen++] = dig[i];
|
|
||||||
}
|
|
||||||
if (!alt && hasDot) {
|
|
||||||
while (mbuf[mlen - 1] == '0') mlen--;
|
|
||||||
if (mbuf[mlen - 1] == '.') mlen--;
|
|
||||||
}
|
|
||||||
_pf_put_exp(mbuf, &mlen, E, upper);
|
|
||||||
} else {
|
|
||||||
int fp = P - 1 - E;
|
|
||||||
if (fp < 0) fp = 0;
|
|
||||||
int intlen = (E >= 0) ? (E + 1) : 0;
|
|
||||||
if (intlen == 0) mbuf[mlen++] = '0';
|
|
||||||
else for (int i = 0; i < intlen; i++) mbuf[mlen++] = (i < len ? dig[i] : '0');
|
|
||||||
if (fp > 0 || alt) {
|
|
||||||
mbuf[mlen++] = '.'; hasDot = 1;
|
|
||||||
if (E < 0) {
|
|
||||||
int lead = -E - 1;
|
|
||||||
for (int k = 0; k < fp; k++) {
|
|
||||||
if (k < lead) mbuf[mlen++] = '0';
|
|
||||||
else { int idx = k - lead; mbuf[mlen++] = (idx < len ? dig[idx] : '0'); }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int k = 0; k < fp; k++) {
|
|
||||||
int idx = intlen + k;
|
|
||||||
mbuf[mlen++] = (idx < len ? dig[idx] : '0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!alt && hasDot) {
|
|
||||||
while (mbuf[mlen - 1] == '0') mlen--;
|
|
||||||
if (mbuf[mlen - 1] == '.') mlen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int total = (sign ? 1 : 0) + mlen;
|
|
||||||
if (!left_align && pad == '0') {
|
|
||||||
if (sign) _pf_putc(st, sign);
|
|
||||||
for (int w = total; w < width; w++) _pf_putc(st, '0');
|
|
||||||
for (int i = 0; i < mlen; i++) _pf_putc(st, mbuf[i]);
|
|
||||||
} else if (!left_align) {
|
|
||||||
for (int w = total; w < width; w++) _pf_putc(st, ' ');
|
|
||||||
if (sign) _pf_putc(st, sign);
|
|
||||||
for (int i = 0; i < mlen; i++) _pf_putc(st, mbuf[i]);
|
|
||||||
} else {
|
|
||||||
if (sign) _pf_putc(st, sign);
|
|
||||||
for (int i = 0; i < mlen; i++) _pf_putc(st, mbuf[i]);
|
|
||||||
for (int w = total; w < width; w++) _pf_putc(st, ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) {
|
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) {
|
||||||
struct _pf_state st;
|
struct _pf_state st;
|
||||||
st.buf = buf;
|
st.buf = buf;
|
||||||
@@ -1579,9 +1363,18 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) {
|
|||||||
case 'f': case 'F':
|
case 'f': case 'F':
|
||||||
case 'e': case 'E':
|
case 'e': case 'E':
|
||||||
case 'g': case 'G': {
|
case 'g': case 'G': {
|
||||||
|
/* Consume the argument either way: skipping it would desync every
|
||||||
|
later conversion in the same format string. */
|
||||||
double dv = va_arg(ap, double);
|
double dv = va_arg(ap, double);
|
||||||
|
if (_pf_putfloat) {
|
||||||
_pf_putfloat(&st, dv, *fmt, precision, width, pad,
|
_pf_putfloat(&st, dv, *fmt, precision, width, pad,
|
||||||
left_align, plus, space, alt);
|
left_align, plus, space, alt);
|
||||||
|
} else {
|
||||||
|
/* printf_float.o was not linked in; echo the spec so the gap
|
||||||
|
is visible rather than silently printing a wrong number. */
|
||||||
|
_pf_putc(&st, '%');
|
||||||
|
_pf_putc(&st, *fmt);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '%':
|
case '%':
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* printf_float.c
|
||||||
|
* Floating-point conversions (%e/%f/%g and uppercase variants) for the
|
||||||
|
* printf family. Kept in its own translation unit -- and therefore its own
|
||||||
|
* archive member -- so that --gc-sections can drop it, along with the
|
||||||
|
* pow/exp/log it drags in, from the many programs that only ever format
|
||||||
|
* integers and strings. vsnprintf reaches this through a weak reference;
|
||||||
|
* see printf_internal.h and lib/libc/Makefile.
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "printf_internal.h"
|
||||||
|
|
||||||
|
/* Base-10 exponent of the leading digit of a positive finite value, i.e. the
|
||||||
|
E such that value = m * 10^E with m in [1, 10). No rounding is applied. */
|
||||||
|
static int _pf_exp10(double v) {
|
||||||
|
int E = (int)floor(log10(v));
|
||||||
|
double s = v / pow(10.0, (double)E);
|
||||||
|
if (s >= 10.0) E++;
|
||||||
|
else if (s < 1.0) E--;
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate `nsig` significant decimal digits of a positive finite value into
|
||||||
|
`out` (ASCII, no terminator). Returns the base-10 exponent of the leading
|
||||||
|
digit, i.e. value ~= (out[0].out[1..]) * 10^E. Rounding is half-up and may
|
||||||
|
carry into a new leading digit, bumping the returned exponent. */
|
||||||
|
static int _pf_gendigits(double v, int nsig, char *out) {
|
||||||
|
int E = (int)floor(log10(v));
|
||||||
|
double scale = v / pow(10.0, (double)E);
|
||||||
|
/* Correct estimate errors so scale lands in [1, 10). */
|
||||||
|
if (scale >= 10.0) { scale /= 10.0; E++; }
|
||||||
|
else if (scale < 1.0) { scale *= 10.0; E--; }
|
||||||
|
|
||||||
|
for (int i = 0; i < nsig; i++) {
|
||||||
|
int d = (int)scale;
|
||||||
|
if (d < 0) d = 0; else if (d > 9) d = 9;
|
||||||
|
out[i] = (char)('0' + d);
|
||||||
|
scale = (scale - d) * 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale >= 5.0) { /* round up based on the next digit */
|
||||||
|
int i = nsig - 1;
|
||||||
|
while (i >= 0) {
|
||||||
|
if (out[i] == '9') { out[i] = '0'; i--; }
|
||||||
|
else { out[i]++; break; }
|
||||||
|
}
|
||||||
|
if (i < 0) { out[0] = '1'; E++; } /* all nines carried out */
|
||||||
|
}
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the two-or-more-digit exponent field of %e/%g ("e+NN"). */
|
||||||
|
static void _pf_put_exp(char *mbuf, int *mlen, int E, int upper) {
|
||||||
|
int m = *mlen;
|
||||||
|
mbuf[m++] = upper ? 'E' : 'e';
|
||||||
|
int ex = E; char es = '+';
|
||||||
|
if (ex < 0) { es = '-'; ex = -ex; }
|
||||||
|
mbuf[m++] = es;
|
||||||
|
char eb[8]; int el = 0;
|
||||||
|
if (ex == 0) eb[el++] = '0';
|
||||||
|
while (ex > 0) { eb[el++] = (char)('0' + ex % 10); ex /= 10; }
|
||||||
|
while (el < 2) eb[el++] = '0';
|
||||||
|
while (el > 0) mbuf[m++] = eb[--el];
|
||||||
|
*mlen = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format a floating-point value for the %e/%f/%g conversions (and uppercase
|
||||||
|
variants), honoring precision, width, padding and sign flags. */
|
||||||
|
void _pf_putfloat(struct _pf_state *st, double v, char conv,
|
||||||
|
int precision, int width, char pad,
|
||||||
|
int left_align, int plus, int space, int alt) {
|
||||||
|
int upper = (conv >= 'A' && conv <= 'Z');
|
||||||
|
char lc = upper ? (char)(conv - 'A' + 'a') : conv;
|
||||||
|
|
||||||
|
_dbl_bits bits; bits.d = v;
|
||||||
|
int neg = (int)(bits.u >> 63);
|
||||||
|
uint64_t expo = (bits.u >> 52) & 0x7FF;
|
||||||
|
uint64_t mant = bits.u & 0x000FFFFFFFFFFFFFULL;
|
||||||
|
|
||||||
|
char sign = 0;
|
||||||
|
if (neg) sign = '-';
|
||||||
|
else if (plus) sign = '+';
|
||||||
|
else if (space) sign = ' ';
|
||||||
|
|
||||||
|
/* Infinity / NaN: never zero-padded. */
|
||||||
|
if (expo == 0x7FF) {
|
||||||
|
const char *word = mant ? (upper ? "NAN" : "nan") : (upper ? "INF" : "inf");
|
||||||
|
if (mant) sign = 0;
|
||||||
|
char tmp[8]; int tl = 0;
|
||||||
|
if (sign) tmp[tl++] = sign;
|
||||||
|
for (const char *p = word; *p; p++) tmp[tl++] = *p;
|
||||||
|
if (!left_align) for (int w = tl; w < width; w++) _pf_putc(st, ' ');
|
||||||
|
for (int i = 0; i < tl; i++) _pf_putc(st, tmp[i]);
|
||||||
|
if (left_align) for (int w = tl; w < width; w++) _pf_putc(st, ' ');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (precision < 0) precision = 6;
|
||||||
|
if (precision > 340) precision = 340;
|
||||||
|
|
||||||
|
double av = neg ? -v : v;
|
||||||
|
|
||||||
|
char mbuf[800];
|
||||||
|
int mlen = 0;
|
||||||
|
|
||||||
|
if (lc == 'e') {
|
||||||
|
int nsig = precision + 1;
|
||||||
|
char dig[400];
|
||||||
|
int E;
|
||||||
|
if (av == 0.0) { for (int i = 0; i < nsig; i++) dig[i] = '0'; E = 0; }
|
||||||
|
else E = _pf_gendigits(av, nsig, dig);
|
||||||
|
mbuf[mlen++] = dig[0];
|
||||||
|
if (precision > 0 || alt) {
|
||||||
|
mbuf[mlen++] = '.';
|
||||||
|
for (int i = 1; i <= precision; i++) mbuf[mlen++] = dig[i];
|
||||||
|
}
|
||||||
|
_pf_put_exp(mbuf, &mlen, E, upper);
|
||||||
|
}
|
||||||
|
else if (lc == 'f') {
|
||||||
|
if (av == 0.0) {
|
||||||
|
mbuf[mlen++] = '0';
|
||||||
|
if (precision > 0 || alt) {
|
||||||
|
mbuf[mlen++] = '.';
|
||||||
|
for (int i = 0; i < precision; i++) mbuf[mlen++] = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int Ef = _pf_exp10(av);
|
||||||
|
int keep = Ef + 1 + precision;
|
||||||
|
if (keep <= 0) {
|
||||||
|
char d1[4];
|
||||||
|
_pf_gendigits(av, 1, d1);
|
||||||
|
int roundUp = (keep == 0 && d1[0] >= '5');
|
||||||
|
mbuf[mlen++] = '0';
|
||||||
|
if (precision > 0 || alt) {
|
||||||
|
mbuf[mlen++] = '.';
|
||||||
|
for (int i = 0; i < precision; i++) mbuf[mlen++] = '0';
|
||||||
|
}
|
||||||
|
if (roundUp) mbuf[mlen - 1] = '1';
|
||||||
|
} else {
|
||||||
|
if (keep > 380) keep = 380;
|
||||||
|
char dig[400];
|
||||||
|
int E = _pf_gendigits(av, keep, dig);
|
||||||
|
int len = keep;
|
||||||
|
int intlen = (E >= 0) ? (E + 1) : 0;
|
||||||
|
if (intlen == 0) mbuf[mlen++] = '0';
|
||||||
|
else for (int i = 0; i < intlen; i++) mbuf[mlen++] = (i < len ? dig[i] : '0');
|
||||||
|
if (precision > 0 || alt) {
|
||||||
|
mbuf[mlen++] = '.';
|
||||||
|
if (E < 0) {
|
||||||
|
int lead = -E - 1;
|
||||||
|
for (int k = 0; k < precision; k++) {
|
||||||
|
if (k < lead) mbuf[mlen++] = '0';
|
||||||
|
else { int idx = k - lead; mbuf[mlen++] = (idx < len ? dig[idx] : '0'); }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int k = 0; k < precision; k++) {
|
||||||
|
int idx = intlen + k;
|
||||||
|
mbuf[mlen++] = (idx < len ? dig[idx] : '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* 'g' / 'G' */
|
||||||
|
int P = precision; if (P == 0) P = 1;
|
||||||
|
char dig[400];
|
||||||
|
int E;
|
||||||
|
if (av == 0.0) { E = 0; for (int i = 0; i < P; i++) dig[i] = '0'; }
|
||||||
|
else E = _pf_gendigits(av, P, dig);
|
||||||
|
int len = P;
|
||||||
|
int useExp = (E < -4 || E >= P);
|
||||||
|
int hasDot = 0;
|
||||||
|
if (useExp) {
|
||||||
|
int fp = P - 1;
|
||||||
|
mbuf[mlen++] = dig[0];
|
||||||
|
if (fp > 0 || alt) {
|
||||||
|
mbuf[mlen++] = '.'; hasDot = 1;
|
||||||
|
for (int i = 1; i <= fp; i++) mbuf[mlen++] = dig[i];
|
||||||
|
}
|
||||||
|
if (!alt && hasDot) {
|
||||||
|
while (mbuf[mlen - 1] == '0') mlen--;
|
||||||
|
if (mbuf[mlen - 1] == '.') mlen--;
|
||||||
|
}
|
||||||
|
_pf_put_exp(mbuf, &mlen, E, upper);
|
||||||
|
} else {
|
||||||
|
int fp = P - 1 - E;
|
||||||
|
if (fp < 0) fp = 0;
|
||||||
|
int intlen = (E >= 0) ? (E + 1) : 0;
|
||||||
|
if (intlen == 0) mbuf[mlen++] = '0';
|
||||||
|
else for (int i = 0; i < intlen; i++) mbuf[mlen++] = (i < len ? dig[i] : '0');
|
||||||
|
if (fp > 0 || alt) {
|
||||||
|
mbuf[mlen++] = '.'; hasDot = 1;
|
||||||
|
if (E < 0) {
|
||||||
|
int lead = -E - 1;
|
||||||
|
for (int k = 0; k < fp; k++) {
|
||||||
|
if (k < lead) mbuf[mlen++] = '0';
|
||||||
|
else { int idx = k - lead; mbuf[mlen++] = (idx < len ? dig[idx] : '0'); }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int k = 0; k < fp; k++) {
|
||||||
|
int idx = intlen + k;
|
||||||
|
mbuf[mlen++] = (idx < len ? dig[idx] : '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!alt && hasDot) {
|
||||||
|
while (mbuf[mlen - 1] == '0') mlen--;
|
||||||
|
if (mbuf[mlen - 1] == '.') mlen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int total = (sign ? 1 : 0) + mlen;
|
||||||
|
if (!left_align && pad == '0') {
|
||||||
|
if (sign) _pf_putc(st, sign);
|
||||||
|
for (int w = total; w < width; w++) _pf_putc(st, '0');
|
||||||
|
for (int i = 0; i < mlen; i++) _pf_putc(st, mbuf[i]);
|
||||||
|
} else if (!left_align) {
|
||||||
|
for (int w = total; w < width; w++) _pf_putc(st, ' ');
|
||||||
|
if (sign) _pf_putc(st, sign);
|
||||||
|
for (int i = 0; i < mlen; i++) _pf_putc(st, mbuf[i]);
|
||||||
|
} else {
|
||||||
|
if (sign) _pf_putc(st, sign);
|
||||||
|
for (int i = 0; i < mlen; i++) _pf_putc(st, mbuf[i]);
|
||||||
|
for (int w = total; w < width; w++) _pf_putc(st, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* printf_internal.h
|
||||||
|
* Shared state between the integer printf core (libc.c) and the optional
|
||||||
|
* floating-point conversion module (printf_float.c).
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBC_PRINTF_INTERNAL_H
|
||||||
|
#define _LIBC_PRINTF_INTERNAL_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Output cursor shared by every conversion. `pos` counts the characters a
|
||||||
|
conversion WOULD have written, so it may run past `max`; only writes below
|
||||||
|
`max` land in `buf`. That is what gives snprintf its C99 return value. */
|
||||||
|
struct _pf_state {
|
||||||
|
char *buf;
|
||||||
|
size_t pos;
|
||||||
|
size_t max;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Defined in libc.c. External rather than static so the float module can
|
||||||
|
reach it; it is the only core helper the float conversions need. */
|
||||||
|
void _pf_putc(struct _pf_state *st, char c);
|
||||||
|
|
||||||
|
/* Union for double bit manipulation (used by float formatting and math). */
|
||||||
|
typedef union { double d; uint64_t u; } _dbl_bits;
|
||||||
|
|
||||||
|
/* Defined in printf_float.c, which is a SEPARATE archive member so that
|
||||||
|
--gc-sections can drop the decimal-conversion and pow/exp/log code from
|
||||||
|
programs that never format a float. vsnprintf calls this through a WEAK
|
||||||
|
reference: link with -Wl,-u,_pf_putfloat to pull the module in. Without
|
||||||
|
that flag %e/%f/%g echo their conversion spec instead of a number. */
|
||||||
|
void _pf_putfloat(struct _pf_state *st, double v, char conv,
|
||||||
|
int precision, int width, char pad,
|
||||||
|
int left_align, int plus, int space, int alt);
|
||||||
|
|
||||||
|
#endif /* _LIBC_PRINTF_INTERNAL_H */
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -62,7 +62,7 @@ TARGET := $(BINDIR)/apps/audio/audio.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/audio
|
mkdir -p $(BINDIR)/apps/audio
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ TARGET := $(BINDIR)/apps/bluetooth/bluetooth.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/bluetooth
|
mkdir -p $(BINDIR)/apps/bluetooth
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ TARGET := $(BINDIR)/apps/calculator/calculator.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/calculator
|
mkdir -p $(BINDIR)/apps/calculator
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ TARGET := $(BINDIR)/apps/charmap/charmap.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/charmap
|
mkdir -p $(BINDIR)/apps/charmap
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ TARGET := $(BINDIR)/apps/devexplorer/devexplorer.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/devexplorer
|
mkdir -p $(BINDIR)/apps/devexplorer
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -7,96 +7,11 @@
|
|||||||
|
|
||||||
#include <montauk/syscall.h>
|
#include <montauk/syscall.h>
|
||||||
#include <montauk/string.h>
|
#include <montauk/string.h>
|
||||||
|
#include <libc/stdio.h>
|
||||||
|
|
||||||
using montauk::memcpy;
|
using montauk::memcpy;
|
||||||
using montauk::memset;
|
using montauk::memset;
|
||||||
|
|
||||||
// ---- Minimal snprintf (no libc available) ----
|
|
||||||
|
|
||||||
using va_list = __builtin_va_list;
|
|
||||||
#define va_start __builtin_va_start
|
|
||||||
#define va_end __builtin_va_end
|
|
||||||
#define va_arg __builtin_va_arg
|
|
||||||
|
|
||||||
struct PfState {
|
|
||||||
char* buf;
|
|
||||||
int pos;
|
|
||||||
int max;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pf_putc(PfState* st, char c) {
|
|
||||||
if (st->pos < st->max) st->buf[st->pos] = c;
|
|
||||||
st->pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pf_putnum(PfState* st, unsigned long val, int base, int width, char pad, int neg) {
|
|
||||||
char tmp[24];
|
|
||||||
int i = 0;
|
|
||||||
const char* digits = "0123456789abcdef";
|
|
||||||
if (val == 0) { tmp[i++] = '0'; }
|
|
||||||
else { while (val > 0) { tmp[i++] = digits[val % base]; val /= base; } }
|
|
||||||
int total = (neg ? 1 : 0) + i;
|
|
||||||
if (neg && pad == '0') pf_putc(st, '-');
|
|
||||||
for (int w = total; w < width; w++) pf_putc(st, pad);
|
|
||||||
if (neg && pad != '0') pf_putc(st, '-');
|
|
||||||
while (i > 0) pf_putc(st, tmp[--i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vsnprintf(char* buf, int size, const char* fmt, va_list ap) {
|
|
||||||
PfState st;
|
|
||||||
st.buf = buf;
|
|
||||||
st.pos = 0;
|
|
||||||
st.max = size > 0 ? size - 1 : 0;
|
|
||||||
while (*fmt) {
|
|
||||||
if (*fmt != '%') { pf_putc(&st, *fmt++); continue; }
|
|
||||||
fmt++;
|
|
||||||
char pad = ' ';
|
|
||||||
if (*fmt == '0') { pad = '0'; fmt++; }
|
|
||||||
int width = 0;
|
|
||||||
while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + (*fmt - '0'); fmt++; }
|
|
||||||
if (*fmt == 'l') fmt++;
|
|
||||||
switch (*fmt) {
|
|
||||||
case 'd': case 'i': {
|
|
||||||
long val = va_arg(ap, int);
|
|
||||||
int neg = 0; unsigned long uval;
|
|
||||||
if (val < 0) { neg = 1; uval = (unsigned long)(-val); }
|
|
||||||
else uval = (unsigned long)val;
|
|
||||||
pf_putnum(&st, uval, 10, width, pad, neg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'u': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 10, width, pad, 0); break; }
|
|
||||||
case 'x': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 16, width, pad, 0); break; }
|
|
||||||
case 's': {
|
|
||||||
const char* s = va_arg(ap, const char*);
|
|
||||||
if (!s) s = "(null)";
|
|
||||||
int slen = 0; while (s[slen]) slen++;
|
|
||||||
for (int w = slen; w < width; w++) pf_putc(&st, ' ');
|
|
||||||
for (int j = 0; j < slen; j++) pf_putc(&st, s[j]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'c': { char c = (char)va_arg(ap, int); pf_putc(&st, c); break; }
|
|
||||||
case '%': pf_putc(&st, '%'); break;
|
|
||||||
default: pf_putc(&st, '%'); pf_putc(&st, *fmt); break;
|
|
||||||
}
|
|
||||||
if (*fmt) fmt++;
|
|
||||||
}
|
|
||||||
if (size > 0) {
|
|
||||||
if (st.pos < size) st.buf[st.pos] = '\0';
|
|
||||||
else st.buf[size - 1] = '\0';
|
|
||||||
}
|
|
||||||
return st.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snprintf(char* buf, int size, const char* fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
int ret = vsnprintf(buf, size, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---- DHCP constants ----
|
// ---- DHCP constants ----
|
||||||
|
|
||||||
static constexpr uint8_t BOOTREQUEST = 1;
|
static constexpr uint8_t BOOTREQUEST = 1;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ TARGET := $(BINDIR)/apps/disks/disks.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/disks
|
mkdir -p $(BINDIR)/apps/disks
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ TARGET := $(BINDIR)/apps/doom/doom.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(ALL_OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(ALL_OBJS) $(LINK_LD) Makefile $(LOADER_LIB)/liblibloader.a $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/doom
|
mkdir -p $(BINDIR)/apps/doom
|
||||||
$(LD) $(CFLAGS) $(LDFLAGS) $(ALL_OBJS) $(LOADER_LIB)/liblibloader.a $(LIBDIR)/libc/liblibc.a -o $@
|
$(LD) $(CFLAGS) $(LDFLAGS) $(ALL_OBJS) $(LOADER_LIB)/liblibloader.a $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -8,96 +8,13 @@
|
|||||||
|
|
||||||
#include <montauk/syscall.h>
|
#include <montauk/syscall.h>
|
||||||
#include <montauk/string.h>
|
#include <montauk/string.h>
|
||||||
|
#include <libc/stdio.h>
|
||||||
|
|
||||||
using montauk::slen;
|
using montauk::slen;
|
||||||
using montauk::streq;
|
using montauk::streq;
|
||||||
using montauk::starts_with;
|
using montauk::starts_with;
|
||||||
using montauk::skip_spaces;
|
using montauk::skip_spaces;
|
||||||
|
|
||||||
// ---- Minimal snprintf (no libc available) ----
|
|
||||||
|
|
||||||
using va_list = __builtin_va_list;
|
|
||||||
#define va_start __builtin_va_start
|
|
||||||
#define va_end __builtin_va_end
|
|
||||||
#define va_arg __builtin_va_arg
|
|
||||||
|
|
||||||
struct PfState {
|
|
||||||
char* buf;
|
|
||||||
int pos;
|
|
||||||
int max;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pf_putc(PfState* st, char c) {
|
|
||||||
if (st->pos < st->max) st->buf[st->pos] = c;
|
|
||||||
st->pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pf_putnum(PfState* st, unsigned long val, int base, int width, char pad, int neg) {
|
|
||||||
char tmp[24];
|
|
||||||
int i = 0;
|
|
||||||
const char* digits = "0123456789abcdef";
|
|
||||||
if (val == 0) { tmp[i++] = '0'; }
|
|
||||||
else { while (val > 0) { tmp[i++] = digits[val % base]; val /= base; } }
|
|
||||||
int total = (neg ? 1 : 0) + i;
|
|
||||||
if (neg && pad == '0') pf_putc(st, '-');
|
|
||||||
for (int w = total; w < width; w++) pf_putc(st, pad);
|
|
||||||
if (neg && pad != '0') pf_putc(st, '-');
|
|
||||||
while (i > 0) pf_putc(st, tmp[--i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vsnprintf(char* buf, int size, const char* fmt, va_list ap) {
|
|
||||||
PfState st;
|
|
||||||
st.buf = buf;
|
|
||||||
st.pos = 0;
|
|
||||||
st.max = size > 0 ? size - 1 : 0;
|
|
||||||
while (*fmt) {
|
|
||||||
if (*fmt != '%') { pf_putc(&st, *fmt++); continue; }
|
|
||||||
fmt++;
|
|
||||||
char pad = ' ';
|
|
||||||
if (*fmt == '0') { pad = '0'; fmt++; }
|
|
||||||
int width = 0;
|
|
||||||
while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + (*fmt - '0'); fmt++; }
|
|
||||||
if (*fmt == 'l') fmt++;
|
|
||||||
switch (*fmt) {
|
|
||||||
case 'd': case 'i': {
|
|
||||||
long val = va_arg(ap, int);
|
|
||||||
int neg = 0; unsigned long uval;
|
|
||||||
if (val < 0) { neg = 1; uval = (unsigned long)(-val); }
|
|
||||||
else uval = (unsigned long)val;
|
|
||||||
pf_putnum(&st, uval, 10, width, pad, neg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'u': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 10, width, pad, 0); break; }
|
|
||||||
case 'x': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 16, width, pad, 0); break; }
|
|
||||||
case 's': {
|
|
||||||
const char* s = va_arg(ap, const char*);
|
|
||||||
if (!s) s = "(null)";
|
|
||||||
int slen = 0; while (s[slen]) slen++;
|
|
||||||
for (int w = slen; w < width; w++) pf_putc(&st, ' ');
|
|
||||||
for (int j = 0; j < slen; j++) pf_putc(&st, s[j]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'c': { char c = (char)va_arg(ap, int); pf_putc(&st, c); break; }
|
|
||||||
case '%': pf_putc(&st, '%'); break;
|
|
||||||
default: pf_putc(&st, '%'); pf_putc(&st, *fmt); break;
|
|
||||||
}
|
|
||||||
if (*fmt) fmt++;
|
|
||||||
}
|
|
||||||
if (size > 0) {
|
|
||||||
if (st.pos < size) st.buf[st.pos] = '\0';
|
|
||||||
else st.buf[size - 1] = '\0';
|
|
||||||
}
|
|
||||||
return st.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snprintf(char* buf, int size, const char* fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
int ret = vsnprintf(buf, size, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- IP/port parsing ----
|
// ---- IP/port parsing ----
|
||||||
|
|
||||||
static bool parse_uint16(const char* s, uint16_t* out) {
|
static bool parse_uint16(const char* s, uint16_t* out) {
|
||||||
|
|||||||
@@ -6,74 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <montauk/syscall.h>
|
#include <montauk/syscall.h>
|
||||||
|
#include <libc/stdio.h>
|
||||||
// ---- Minimal snprintf ----
|
|
||||||
|
|
||||||
using va_list = __builtin_va_list;
|
|
||||||
#define va_start __builtin_va_start
|
|
||||||
#define va_end __builtin_va_end
|
|
||||||
#define va_arg __builtin_va_arg
|
|
||||||
|
|
||||||
struct PfState { char* buf; int pos; int max; };
|
|
||||||
|
|
||||||
static void pf_putc(PfState* st, char c) {
|
|
||||||
if (st->pos < st->max) st->buf[st->pos] = c;
|
|
||||||
st->pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pf_putnum(PfState* st, unsigned long val, int base, int width, char pad, int neg) {
|
|
||||||
char tmp[24]; int i = 0;
|
|
||||||
const char* digits = "0123456789abcdef";
|
|
||||||
if (val == 0) { tmp[i++] = '0'; }
|
|
||||||
else { while (val > 0) { tmp[i++] = digits[val % base]; val /= base; } }
|
|
||||||
int total = (neg ? 1 : 0) + i;
|
|
||||||
if (neg && pad == '0') pf_putc(st, '-');
|
|
||||||
for (int w = total; w < width; w++) pf_putc(st, pad);
|
|
||||||
if (neg && pad != '0') pf_putc(st, '-');
|
|
||||||
while (i > 0) pf_putc(st, tmp[--i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vsnprintf(char* buf, int size, const char* fmt, va_list ap) {
|
|
||||||
PfState st; st.buf = buf; st.pos = 0; st.max = size > 0 ? size - 1 : 0;
|
|
||||||
while (*fmt) {
|
|
||||||
if (*fmt != '%') { pf_putc(&st, *fmt++); continue; }
|
|
||||||
fmt++;
|
|
||||||
char pad = ' ';
|
|
||||||
if (*fmt == '0') { pad = '0'; fmt++; }
|
|
||||||
int width = 0;
|
|
||||||
while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + (*fmt - '0'); fmt++; }
|
|
||||||
if (*fmt == 'l') fmt++;
|
|
||||||
switch (*fmt) {
|
|
||||||
case 'd': case 'i': {
|
|
||||||
long val = va_arg(ap, int);
|
|
||||||
int neg = 0; unsigned long uval;
|
|
||||||
if (val < 0) { neg = 1; uval = (unsigned long)(-val); } else uval = (unsigned long)val;
|
|
||||||
pf_putnum(&st, uval, 10, width, pad, neg); break;
|
|
||||||
}
|
|
||||||
case 'u': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 10, width, pad, 0); break; }
|
|
||||||
case 'x': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 16, width, pad, 0); break; }
|
|
||||||
case 's': {
|
|
||||||
const char* s = va_arg(ap, const char*); if (!s) s = "(null)";
|
|
||||||
int slen = 0; while (s[slen]) slen++;
|
|
||||||
for (int w = slen; w < width; w++) pf_putc(&st, ' ');
|
|
||||||
for (int j = 0; j < slen; j++) pf_putc(&st, s[j]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'c': { char c = (char)va_arg(ap, int); pf_putc(&st, c); break; }
|
|
||||||
case '%': pf_putc(&st, '%'); break;
|
|
||||||
default: pf_putc(&st, '%'); pf_putc(&st, *fmt); break;
|
|
||||||
}
|
|
||||||
if (*fmt) fmt++;
|
|
||||||
}
|
|
||||||
if (size > 0) { if (st.pos < size) st.buf[st.pos] = '\0'; else st.buf[size - 1] = '\0'; }
|
|
||||||
return st.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snprintf(char* buf, int size, const char* fmt, ...) {
|
|
||||||
va_list ap; va_start(ap, fmt);
|
|
||||||
int ret = vsnprintf(buf, size, fmt, ap);
|
|
||||||
va_end(ap); return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- ANSI color codes ----
|
// ---- ANSI color codes ----
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ TARGET := $(BINDIR)/apps/installer/installer.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/installer
|
mkdir -p $(BINDIR)/apps/installer
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <montauk/syscall.h>
|
#include <montauk/syscall.h>
|
||||||
#include <montauk/string.h>
|
#include <montauk/string.h>
|
||||||
|
#include <libc/stdio.h>
|
||||||
|
|
||||||
using montauk::slen;
|
using montauk::slen;
|
||||||
using montauk::streq;
|
using montauk::streq;
|
||||||
@@ -17,90 +18,6 @@ using montauk::strncpy;
|
|||||||
using montauk::memcpy;
|
using montauk::memcpy;
|
||||||
using montauk::memmove;
|
using montauk::memmove;
|
||||||
|
|
||||||
// ---- Minimal snprintf (no libc available) ----
|
|
||||||
|
|
||||||
using va_list = __builtin_va_list;
|
|
||||||
#define va_start __builtin_va_start
|
|
||||||
#define va_end __builtin_va_end
|
|
||||||
#define va_arg __builtin_va_arg
|
|
||||||
|
|
||||||
struct PfState {
|
|
||||||
char* buf;
|
|
||||||
int pos;
|
|
||||||
int max;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pf_putc(PfState* st, char c) {
|
|
||||||
if (st->pos < st->max) st->buf[st->pos] = c;
|
|
||||||
st->pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pf_putnum(PfState* st, unsigned long val, int base, int width, char pad, int neg) {
|
|
||||||
char tmp[24];
|
|
||||||
int i = 0;
|
|
||||||
const char* digits = "0123456789abcdef";
|
|
||||||
if (val == 0) { tmp[i++] = '0'; }
|
|
||||||
else { while (val > 0) { tmp[i++] = digits[val % base]; val /= base; } }
|
|
||||||
int total = (neg ? 1 : 0) + i;
|
|
||||||
if (neg && pad == '0') pf_putc(st, '-');
|
|
||||||
for (int w = total; w < width; w++) pf_putc(st, pad);
|
|
||||||
if (neg && pad != '0') pf_putc(st, '-');
|
|
||||||
while (i > 0) pf_putc(st, tmp[--i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vsnprintf(char* buf, int size, const char* fmt, va_list ap) {
|
|
||||||
PfState st;
|
|
||||||
st.buf = buf;
|
|
||||||
st.pos = 0;
|
|
||||||
st.max = size > 0 ? size - 1 : 0;
|
|
||||||
while (*fmt) {
|
|
||||||
if (*fmt != '%') { pf_putc(&st, *fmt++); continue; }
|
|
||||||
fmt++;
|
|
||||||
char pad = ' ';
|
|
||||||
if (*fmt == '0') { pad = '0'; fmt++; }
|
|
||||||
int width = 0;
|
|
||||||
while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + (*fmt - '0'); fmt++; }
|
|
||||||
if (*fmt == 'l') fmt++;
|
|
||||||
switch (*fmt) {
|
|
||||||
case 'd': case 'i': {
|
|
||||||
long val = va_arg(ap, int);
|
|
||||||
int neg = 0; unsigned long uval;
|
|
||||||
if (val < 0) { neg = 1; uval = (unsigned long)(-val); }
|
|
||||||
else uval = (unsigned long)val;
|
|
||||||
pf_putnum(&st, uval, 10, width, pad, neg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'u': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 10, width, pad, 0); break; }
|
|
||||||
case 'x': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 16, width, pad, 0); break; }
|
|
||||||
case 's': {
|
|
||||||
const char* s = va_arg(ap, const char*);
|
|
||||||
if (!s) s = "(null)";
|
|
||||||
int slen = 0; while (s[slen]) slen++;
|
|
||||||
for (int w = slen; w < width; w++) pf_putc(&st, ' ');
|
|
||||||
for (int j = 0; j < slen; j++) pf_putc(&st, s[j]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'c': { char c = (char)va_arg(ap, int); pf_putc(&st, c); break; }
|
|
||||||
case '%': pf_putc(&st, '%'); break;
|
|
||||||
default: pf_putc(&st, '%'); pf_putc(&st, *fmt); break;
|
|
||||||
}
|
|
||||||
if (*fmt) fmt++;
|
|
||||||
}
|
|
||||||
if (size > 0) {
|
|
||||||
if (st.pos < size) st.buf[st.pos] = '\0';
|
|
||||||
else st.buf[size - 1] = '\0';
|
|
||||||
}
|
|
||||||
return st.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snprintf(char* buf, int size, const char* fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
int ret = vsnprintf(buf, size, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case-insensitive comparison for IRC commands
|
// Case-insensitive comparison for IRC commands
|
||||||
static bool streqi(const char* a, const char* b) {
|
static bool streqi(const char* a, const char* b) {
|
||||||
while (*a && *b) {
|
while (*a && *b) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ TARGET := $(BINDIR)/apps/klog/klog.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/klog
|
mkdir -p $(BINDIR)/apps/klog
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -39,9 +39,13 @@ CFLAGS := \
|
|||||||
-isystem ../../include/libc \
|
-isystem ../../include/libc \
|
||||||
-isystem $(shell $(CC) -print-file-name=include)
|
-isystem $(shell $(CC) -print-file-name=include)
|
||||||
|
|
||||||
|
# -u _pf_putfloat forces liblibc.a's optional printf_float.o member to be
|
||||||
|
# linked: Lua formats floats (%.14g in lobject.c, %f/%e/%g via string.format),
|
||||||
|
# and vsnprintf only references the float conversions weakly.
|
||||||
LDFLAGS := \
|
LDFLAGS := \
|
||||||
-nostdlib \
|
-nostdlib \
|
||||||
-Wl,--gc-sections \
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-u,_pf_putfloat \
|
||||||
-T ../../link.ld
|
-T ../../link.ld
|
||||||
|
|
||||||
CORE_SRCS := \
|
CORE_SRCS := \
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ TARGET := $(BINDIR)/apps/mandelbrot/mandelbrot.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/mandelbrot
|
mkdir -p $(BINDIR)/apps/mandelbrot
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ TARGET := $(BINDIR)/apps/music/music.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/music
|
mkdir -p $(BINDIR)/apps/music
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ TARGET := $(BINDIR)/apps/paint/paint.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/paint
|
mkdir -p $(BINDIR)/apps/paint
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ LOADER_LIB := $(LIBDIR)/libloader/liblibloader.a
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB)
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/pdfviewer
|
mkdir -p $(BINDIR)/apps/pdfviewer
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ TARGET := $(BINDIR)/apps/powermgr/powermgr.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/powermgr
|
mkdir -p $(BINDIR)/apps/powermgr
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ DEPS := $(OBJDIR)/main.d
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJDIR)/main.o $(LINK_LD) Makefile
|
$(TARGET): $(OBJDIR)/main.o $(LINK_LD) Makefile $(LIBC_LIB)/liblibc.a
|
||||||
mkdir -p $(BINDIR)/os
|
mkdir -p $(BINDIR)/os
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJDIR)/main.o $(TLS_LIB)/libtls.a $(BEARSSL)/libbearssl.a $(LIBC_LIB)/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJDIR)/main.o $(TLS_LIB)/libtls.a $(BEARSSL)/libbearssl.a $(LIBC_LIB)/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ TARGET := $(BINDIR)/apps/procmgr/procmgr.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/procmgr
|
mkdir -p $(BINDIR)/apps/procmgr
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ APP_DIR := $(BINDIR)/apps/rpgdemo
|
|||||||
|
|
||||||
all: $(TARGET) assets
|
all: $(TARGET) assets
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(APP_DIR)
|
mkdir -p $(APP_DIR)
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ LOADER_LIB := $(LIBDIR)/libloader/liblibloader.a
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB)
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/spreadsheet
|
mkdir -p $(BINDIR)/apps/spreadsheet
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -53,9 +53,13 @@ CFLAGS := \
|
|||||||
-isystem $(PROG_INC)/libc \
|
-isystem $(PROG_INC)/libc \
|
||||||
-isystem $(shell $(CC) -print-file-name=include)
|
-isystem $(shell $(CC) -print-file-name=include)
|
||||||
|
|
||||||
|
# -u _pf_putfloat forces liblibc.a's optional printf_float.o member to be
|
||||||
|
# linked: tcc formats floats when dumping constants (tccpp.c), and vsnprintf
|
||||||
|
# only references the float conversions weakly.
|
||||||
LDFLAGS := \
|
LDFLAGS := \
|
||||||
-nostdlib \
|
-nostdlib \
|
||||||
-Wl,--gc-sections \
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-u,_pf_putfloat \
|
||||||
-T ../../link.ld
|
-T ../../link.ld
|
||||||
|
|
||||||
# ---- Sources ----
|
# ---- Sources ----
|
||||||
@@ -110,7 +114,7 @@ $(OBJDIR)/%.o: %.S Makefile
|
|||||||
@mkdir -p $(OBJDIR)
|
@mkdir -p $(OBJDIR)
|
||||||
$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
|
$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
|
||||||
|
|
||||||
$(SHARED_CRT_DIR)/liblibc.a $(SHARED_CRT_DIR)/crt1.o $(SHARED_CRT_DIR)/crti.o $(SHARED_CRT_DIR)/crtn.o:
|
$(SHARED_CRT_DIR)/liblibc.a $(SHARED_CRT_DIR)/liblibc-full.a $(SHARED_CRT_DIR)/crt1.o $(SHARED_CRT_DIR)/crti.o $(SHARED_CRT_DIR)/crtn.o:
|
||||||
$(MAKE) -C $(SHARED_CRT_DIR)
|
$(MAKE) -C $(SHARED_CRT_DIR)
|
||||||
|
|
||||||
$(CRT_DIR)/crt1.o: $(SHARED_CRT_DIR)/crt1.o
|
$(CRT_DIR)/crt1.o: $(SHARED_CRT_DIR)/crt1.o
|
||||||
@@ -125,7 +129,10 @@ $(CRT_DIR)/crtn.o: $(SHARED_CRT_DIR)/crtn.o
|
|||||||
@mkdir -p $(CRT_DIR)
|
@mkdir -p $(CRT_DIR)
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
$(CRT_DIR)/libc.a: $(LIBDIR)/libc/liblibc.a
|
# liblibc-full.a, not liblibc.a: programs compiled on-OS with tcc cannot pass
|
||||||
|
# -u _pf_putfloat, so this sysroot ships the variant with the printf float path
|
||||||
|
# already bound in. See lib/libc/Makefile.
|
||||||
|
$(CRT_DIR)/libc.a: $(LIBDIR)/libc/liblibc-full.a
|
||||||
@mkdir -p $(CRT_DIR)
|
@mkdir -p $(CRT_DIR)
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ TARGET := $(BINDIR)/apps/terminal/terminal.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/terminal
|
mkdir -p $(BINDIR)/apps/terminal
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ LOADER_LIB := $(LIBDIR)/libloader/liblibloader.a
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB)
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/texteditor
|
mkdir -p $(BINDIR)/apps/texteditor
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ TARGET := $(BINDIR)/apps/video/video.elf
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBDIR)/libc/liblibc.a
|
||||||
mkdir -p $(BINDIR)/apps/video
|
mkdir -p $(BINDIR)/apps/video
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user