#include #include #include #include #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] \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; }