goon

goon

https://git.tonybtw.com/goon.git git://git.tonybtw.com/goon.git
3,249 bytes raw
1
#include "goon.h"
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <string.h>
5
6
static void print_usage(const char *prog) {
7
    fprintf(stderr, "usage: %s <command> [options]\n", prog);
8
    fprintf(stderr, "\n");
9
    fprintf(stderr, "commands:\n");
10
    fprintf(stderr, "  eval <file>     evaluate file and output JSON\n");
11
    fprintf(stderr, "  check <file>    validate syntax\n");
12
    fprintf(stderr, "\n");
13
    fprintf(stderr, "options:\n");
14
    fprintf(stderr, "  -p, --pretty    pretty print JSON output\n");
15
    fprintf(stderr, "  -h, --help      show this help\n");
16
    fprintf(stderr, "  -v, --version   show version\n");
17
}
18
19
static void print_version(void) {
20
    printf("goon %s\n", GOON_VERSION);
21
}
22
23
static int cmd_eval(const char *path, bool pretty) {
24
    Goon_Ctx *ctx = goon_create();
25
    if (!ctx) {
26
        fprintf(stderr, "error: failed to create context\n");
27
        return 1;
28
    }
29
30
    if (!goon_load_file(ctx, path)) {
31
        const Goon_Error *err = goon_get_error_info(ctx);
32
        if (err) {
33
            goon_error_print(err);
34
        } else {
35
            fprintf(stderr, "error: unknown error\n");
36
        }
37
        goon_destroy(ctx);
38
        return 1;
39
    }
40
41
    Goon_Value *result = goon_eval_result(ctx);
42
    char *json = pretty ? goon_to_json_pretty(result, 2) : goon_to_json(result);
43
    if (json) {
44
        printf("%s\n", json);
45
        free(json);
46
    }
47
48
    goon_destroy(ctx);
49
    return 0;
50
}
51
52
static int cmd_check(const char *path) {
53
    Goon_Ctx *ctx = goon_create();
54
    if (!ctx) {
55
        fprintf(stderr, "error: failed to create context\n");
56
        return 1;
57
    }
58
59
    if (!goon_load_file(ctx, path)) {
60
        const Goon_Error *err = goon_get_error_info(ctx);
61
        if (err) {
62
            goon_error_print(err);
63
        } else {
64
            fprintf(stderr, "error: unknown error\n");
65
        }
66
        goon_destroy(ctx);
67
        return 1;
68
    }
69
70
    goon_destroy(ctx);
71
    return 0;
72
}
73
74
int main(int argc, char **argv) {
75
    if (argc < 2) {
76
        print_usage(argv[0]);
77
        return 1;
78
    }
79
80
    const char *cmd = argv[1];
81
82
    if (strcmp(cmd, "-h") == 0 || strcmp(cmd, "--help") == 0) {
83
        print_usage(argv[0]);
84
        return 0;
85
    }
86
87
    if (strcmp(cmd, "-v") == 0 || strcmp(cmd, "--version") == 0) {
88
        print_version();
89
        return 0;
90
    }
91
92
    if (strcmp(cmd, "eval") == 0) {
93
        if (argc < 3) {
94
            fprintf(stderr, "error: eval requires a file argument\n");
95
            return 1;
96
        }
97
        bool pretty = false;
98
        const char *path = NULL;
99
        for (int i = 2; i < argc; i++) {
100
            if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pretty") == 0) {
101
                pretty = true;
102
            } else if (!path) {
103
                path = argv[i];
104
            }
105
        }
106
        if (!path) {
107
            fprintf(stderr, "error: eval requires a file argument\n");
108
            return 1;
109
        }
110
        return cmd_eval(path, pretty);
111
    }
112
113
    if (strcmp(cmd, "check") == 0) {
114
        if (argc < 3) {
115
            fprintf(stderr, "error: check requires a file argument\n");
116
            return 1;
117
        }
118
        return cmd_check(argv[2]);
119
    }
120
121
    fprintf(stderr, "error: unknown command '%s'\n", cmd);
122
    print_usage(argv[0]);
123
    return 1;
124
}