summaryrefslogtreecommitdiff
path: root/chapter25/src/main/c/simple_crt.c
blob: 8656a3ccd430aece17a44603f1a4c7cac67a5f73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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);
}