diff options
Diffstat (limited to 'src/main/c/simple_crt.c')
| -rw-r--r-- | src/main/c/simple_crt.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/main/c/simple_crt.c b/src/main/c/simple_crt.c new file mode 100644 index 00000000..8656a3cc --- /dev/null +++ b/src/main/c/simple_crt.c @@ -0,0 +1,61 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +// errno may be thread-local or a macro calling a platform accessor. +int32_t simple_errno(void) { return errno; } + +// Native process arguments converted to ordinary Simple array layouts. +// The outer array is mutable; every contained byte array is published as +// immutable and non-null to Simple code. +typedef struct SimpleBytes { + uint32_t len; + unsigned char bytes[]; +} SimpleBytes; + +typedef struct SimpleArgs { + uint32_t len; + uint32_t pad; + SimpleBytes *args[]; +} SimpleArgs; + +__attribute__((CALL_CONV)) +extern int64_t simple_main(SimpleArgs *args); + +static SimpleArgs *simple_args(int argc, char **argv) { + if (argc < 0 || (uint64_t)argc > UINT32_MAX) + return NULL; + + SimpleArgs *args = calloc(1, sizeof(*args) + (size_t)argc * sizeof(args->args[0])); + if (args == NULL) + return NULL; + args->len = (uint32_t)argc; + + for (int i = 0; i < argc; i++) { + size_t len = strlen(argv[i]); + if (len > UINT32_MAX) { + free(args); + return NULL; + } + SimpleBytes *str = malloc(sizeof(*str) + len); + if (str == NULL) { + for (int j = 0; j < i; j++) free(args->args[j]); + free(args); + return NULL; + } + str->len = (uint32_t)len; + memcpy(str->bytes, argv[i], len); + args->args[i] = str; + } + return args; +} + +int main(int argc, char **argv) { + SimpleArgs *args = simple_args(argc, argv); + if (args == NULL) + return 1; + // The language-level hidden receiver is not part of the emitted ABI for + // free functions; source argument zero occupies native argument zero. + return (int)simple_main(args); +} |
