macro allocate_args($argc) { ... }

Allocates the space for program arguments

It allocates the memory for the slice on the stack, hence a macro. This is done to avoid a dependency on malloc for simple programs, but it is potentially problematic if a large number of arguments is passed as a significant portion of the stack space will be consumed. The size of the slice is argc * sizeof(usize) * 2 as only the pointers and lengths are stored in the slice, the contents of the arguments stays in the memory region pointed to by argv.

If number of arguments exceeds STACK_ARGS_MAX, the function will fall back to using malloc.

This is not great and probably a reason why Rust has env::args() instead of an argument to the main function, but I kind of like the C-style arguments to main, so for now this is the approach.