aboutsummaryrefslogtreecommitdiffstats
path: root/src/bootstrap/main.c
blob: b5fd8216fa2c9f3f5187e0f352c81f3b16b09c07 (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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include "string_view.c"

void
process_source(const StringView *source) {
    sv_write(source, stdout);
}

#define REPL_PROMPT "bdl> "

void
run_repl(void) {
    printf("BDL REPL (Press Ctrl-C to exit)\n");
    while (true) {
        printf(REPL_PROMPT);
        getchar();
        process_source(NULL);
    }
}

void
run_file(char *file_name) {
    FILE *file = fopen(file_name, "r");
    if (!file) {
        fprintf(stderr, "error: couldn't open input file: %s\n", file_name);
        exit(EXIT_FAILURE);
    }

    // Read entire file into memory.
    fseek(file, 0, SEEK_END);
    size_t file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    char *source = malloc(file_size + 1);
    fread(source, 1, file_size, file);
    source[file_size] = 0;

    StringView sv = (StringView){
        .start = source,
        .n = file_size,
    };

    process_source(&sv);

    free(source);
    fclose(file);
}

#define STDIN_BUF_SIZE 16

void
run_stdin(void) {
    size_t buf_size = 0;
    size_t buf_cap = STDIN_BUF_SIZE;
    char *source = malloc(sizeof(char) * buf_cap);

    char c;
    while ((c = getchar()) != EOF) {
        if (buf_size == buf_cap) {
            buf_cap *= 2;
            source = realloc(source, buf_cap * sizeof(char));
        }
        source[buf_size] = c;
        buf_size++;
    }

    StringView sv = (StringView){
        .start = source,
        .n = buf_size,
    };

    process_source(&sv);

    free(source);
}

#ifndef BIN_NAME
#define BIN_NAME "bdl"
#endif

void
print_usage(void) {
    printf("Usage: %s [options] <filename filename ...>\n", BIN_NAME);
    printf("\n");
    printf("\t-i\tInteractive mode (REPL).\n");
    printf("\n");
}

int
main(int argc, char *argv[]) {
    int option;
    while ((option = getopt(argc, argv, "i")) != -1) {
        switch (option) {
            case 'i': {
                // Interactive mode.
                run_repl();
                return EXIT_SUCCESS;
            } break;
            default: {
                print_usage();
                return EXIT_FAILURE;
            } break;
        }
    }

    // Run from stdin.
    if (optind == argc) {
        run_stdin();
        return EXIT_SUCCESS;
    }

    // Run from file.
    while (optind < argc) {
        char *file_name = argv[optind];
        run_file(file_name);
        optind++;
    }

    return EXIT_SUCCESS;
}