G Programming Language
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

135 lines
3.8 KiB

// main.c
// Main source file for G
// Copyright (C) 2021, Jakob Wakeling
// MIT Licence
#include "analyse.h"
#include "init.h"
#include "llvm.h"
#include "log.h"
#include "parse.h"
#include "util/error.h"
#include "util/optget.h"
#include "util/util.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
static struct lop lops[] = {
{ "help", ARG_NUL, 256 },
{ "version", ARG_NUL, 257 },
{ NULL, 0, 0 }
};
static char *aw[] = {
"g", "/home/deus/Workspace/G/examples/main.g", NULL
};
static bool bflag = false, Bflag = false, cflag = false;
static bool Eflag = false, pflag = false, Pflag = false;
static void compile(const char *file, char *src, UINT len);
static void compile_file(const char *file);
static void opt_f(const char *arg);
static void opt_O(const char *arg);
static void opt_W(const char *arg);
static void hlp(void);
static void ver(void);
int main(int ac, char *av[]) { A0 = av[0];
/* DEBUG */
if (ac == 1) { ac = (sizeof (aw) / sizeof (*aw)) - 1; av = aw; }
struct opt opt = OPTGET_INIT; opt.str = "bBcEf:O:pPW:"; opt.lops = lops;
for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) {
case 'b': { bflag = true; } break; /* Output LLVM IR files */
case 'B': { Bflag = true; } break; /* Output LLVM bitcode files */
case 'c': { cflag = true; } break; /* Output object files */
case 'E': { Eflag = true; } break; /* Output lexer tokens */
case 'f': { opt_f(opt.arg); } break; /* Configure formatting */
case 'O': { opt_O(opt.arg); } break; /* Configure optimisation */
case 'p': { pflag = true; } break; /* Output parser AST */
case 'P': { Pflag = true; } break; /* Output analyser AST */
case 'W': { opt_W(opt.arg); } break; /* Configure warnings and errors */
case 256: { hlp(); } return 0;
case 257: { ver(); } return 0;
default: {} return 1;
}
if (opt.ind == ac) { error(1, "Missing operand"); }
else for (char **p = &av[opt.ind]; *p; ++p) { compile_file(*p); }
return 0;
}
static void compile(const char * file, char *src, UINT len) {
initialise();
lex l = lex_init(file, src, len);
if (Eflag) { lex_debug(&l); goto end; }
ast *a = parse(&l);
if (pflag) { ast_print(a, 0); goto end; }
analyse(a);
if (Pflag) { ast_print(a, 0); goto end; }
llvm(a);
end:; return;
}
static void compile_file(const char *file) {
FILE *fi; char *fb; size_t fl;
if (!(fi = fopen(file, "r"))) { error(1, "%s: %s", file, serr()); }
fseek(fi, 0, SEEK_END); fl = ftell(fi); rewind(fi);
fb = malloc((fl + 1) * sizeof (*fb));
fread(fb, 1, fl, fi); fb[fl] = 0; fclose(fi);
compile(file, fb, fl); free(fb); return;
}
/* Configure formatting */
static void opt_f(const char *arg) {}
/* Configure optimisation */
static void opt_O(const char *arg) {}
/* Configure warnings and errors */
static void opt_W(const char *arg) {
if (strcmp(arg, "0") == 0) { log_level = 0; }
else if (strcmp(arg, "1") == 0) { log_level = 1; }
else if (strcmp(arg, "2") == 0) { log_level = 2; }
else if (strcmp(arg, "3") == 0) { log_level = 3; }
else if (strcmp(arg, "4") == 0) { log_level = 4; }
else if (strcmp(arg, "error") == 0) { log_waerr = true; }
else { note(NULL, 0, 0, 1, "-W%s: unknown warning option", arg); }
}
/* Print help information. */
static void hlp(void) {
puts("G - G Programming Language\n");
puts("Usage: g\n");
puts("Options:");
puts(" -b, Output LLVM IR files");
puts(" -B, Output LLVM bitcode files");
puts(" -c, Output object files");
puts(" -E, Output lexer tokens");
puts(" -p, Output parser AST");
puts(" -P, Output analyser AST");
puts(" --help Display help information");
puts(" --version Display version information");
}
/* Print version information. */
static void ver(void) {
puts("G, version " PROJECT_VERSION);
puts("Copyright (C) 2021, Jakob Wakeling");
puts("MIT Licence (https://opensource.org/licenses/MIT)");
}