I'm looking for a tiny libc (C runtime library) targeting small model DOS 8086, and providing (most of) the C89 library functions, including fread(...), printf(...) and scanf(...). The libc must work with at least one of these C compilers: Watcom C, Borland C++, Microsoft C or Zortech C++. The libc must seperate unrelated functions, so e.g. if printf(...) and scanf(...) are not used in the source code, then they shouldn't be linked into the final program. Also it should be possible to specify that I don't need floating point support in printf(...) and scanf(...), so they will become smaller.
My baseline is the output of the OpenWatcom 2 C compiler:
/* 8894 bytes: owcc -bcom -W -Wall -fsigned-char -fno-stack-check -march=i86 -s -Os -o hellopf.com hellopf.c */
#include <stdio.h>
int main(int argc, char **argv) {
(void)argc; (void)argv;
printf("Hello, World!\n");
return 0;
}
/* 4046 bytes: owcc -bcom -W -Wall -fsigned-char -fno-stack-check -march=i86 -s -Os -o hellowr.com hellowr.c */
/* 2206 bytes: Zortech C++ 3.1 on DOS: ztc -mt -b -o+space hellowr.c */
#include <io.h>
int main(int argc, char **argv) {
(void)argc; (void)argv;
(void)!write(1, "Hello, World!\n", 14);
return 0;
}
FYI here is the memory map of hellowr.com (showing the size of each function and variable): https://gist.github.com/pts/143db336182267eb4e306f6a3c5f354e
Surely the hello-world with write(...) can be implemented in less than 300 bytes, including the parsing of argv and calling the DOS int 21h functions corresponding to write(...) and exit(...). However, the OpenWatcom 2 C compiler generates 4046 bytes, most of which is coming from the OpenWatcom 2 libc. I'm looking for a libc which doesn't generate so much bloat by default, or at least it's configurable.
FYI Turbo Pascal 7.0 can generate a smaller program:
{ 2208 bytes: DOS: tpc hellopas }
{$I-} {$S-} begin write('Hello, World!'#13#10); end.
Example of unnecessary bloat: putchar(...) calls a flush function, which allocates a buffer (if it hasn't existed yet) with malloc(...), which may be in the same object file as free(...) and realloc(...), so all 3 get included. Solution: if the program uses only stdin, stdout and stderr, then preallocate these buffers in bss, and link in a version of a flush function which doesn't call malloc(...).
I've taken a look at the libc as UTILPROG on SAC. Freelib contains functions which can be called from assembly, not C. J.R.Ferguson's C Library uses printf from the libc, it doesn't define one. I haven't found anything else there.
FYI For 32-bit targets (not only x86) there are musl libc and Picolibc and others.
I'm not aiming for the smallest possible program size (because then I would write the program, or at least a custom libc in assembly, see e.g. dosmc), but I'm loooking for a better compromise (i.e. smaller by default) than what the OpenWatcom 2 libc provides, but still providing printf(...), scanf(...) and malloc(...) (and most other C89 functions) if needed by the program.
printf()
,scanf()
and friends - it tends to take up a lot of space.