Here's the freestanding version for Linux on x86 or x86-64:
// SPDX-License-Identifier: CC0-1.0
//
// Converts native byte order signed 32-bit integers to native byte order floats.
//
// To compile, use
// gcc -Wall -O2 -static -s -ffreestanding -nostdlib this.c -o executable
//
#include <stdint.h>
#if defined(__x86_64__)
/*
* Linux on x86-64
*/
#define SYS_exit 60
#define SYS_read 0
#define SYS_write 1
static inline long syscall3(long num, long arg1, long arg2, long arg3)
{
long ret;
asm volatile ( "syscall"
: "=a" (ret)
: "a" (num), "D" (arg1), "S" (arg2), "d" (arg3)
: "rcx", "r11", "memory");
return ret;
}
static inline long syscall1(long num, long arg1)
{
long ret;
asm volatile ( "syscall"
: "=a" (ret)
: "a" (num), "D" (arg1)
: "rcx", "r11", "memory");
return ret;
}
#elif defined(__i386__)
/*
* Linux on x86
*/
#define SYS_exit 1
#define SYS_read 3
#define SYS_write 4
static inline long syscall3(long num, long arg1, long arg2, long arg3)
{
long ret;
asm volatile ( "int $0x80"
: "=a" (ret)
: "a" (num), "b" (arg1), "c" (arg2), "d" (arg3)
: "cc", "memory");
return ret;
}
static inline long syscall1(long num, long arg1)
{
long ret;
asm volatile ( "int $0x80"
: "=a" (ret)
: "a" (num), "D" (arg1)
: "ecx", "edx", "cc", "memory");
return ret;
}
#else
#error Unsupported architecture.
#endif
/*
* Linux kernel interface (same across architectures)
*/
static inline long read_stdin(void *buffer, long length)
{
return syscall3(SYS_read, 0, (long)buffer, length);
}
static inline long write_stdout(const void *buffer, long length)
{
return syscall3(SYS_write, 1, (long)buffer, length);
}
static inline void exit_success(void)
{
syscall1(SYS_exit, 0);
while (1) /* nothing */;
}
static inline void exit_failure(void)
{
syscall1(SYS_exit, 1);
while (1) /* nothing */;
}
/*
* Application itself
*/
#ifndef BLOCK_SIZE
#define BLOCK_SIZE 8192
#endif
void _start(void)
{
int32_t in_buf[BLOCK_SIZE];
float out_buf[BLOCK_SIZE];
while (1) {
long have = 0;
/* Read some (complete) int32_t's. */
do {
long n = read_stdin((char *)(in_buf) + have, (sizeof in_buf) - have);
if (n > 0)
have += n;
else
if (n == 0)
exit_success();
else
exit_failure();
} while (!have || (have % sizeof in_buf[0]));
/* Count in number of samples in input. */
have /= sizeof in_buf[0];
/* Convert to float. */
{
float *const end = out_buf + have;
int32_t *src = in_buf;
float *dst = out_buf;
while (dst < end)
*(dst++) = *(src++);
}
/* Write floats. */
{
const char *const end = (const char *)(out_buf + have);
const char *ptr = (const char *)(out_buf);
while (ptr < end) {
long n = write_stdout(ptr, (long)(intptr_t)(end - ptr));
if (n > 0)
ptr += n;
else
exit_failure();
}
}
}
/* Never reached. */
exit_success();
}
Compiles to a static binary less than 9k in size. There's a lot of bloat even in standard C nowadays...