summaryrefslogtreecommitdiff
path: root/src/main/c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/c')
-rw-r--r--src/main/c/simple_crt.c61
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);
+}