0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
|
// Copyright (C) 2021, Jakob Wakeling
// All rights reserved.
#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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
static struct {
bool bflag, Bflag, cflag, Eflag, pflag, Pflag, qflag, Sflag;
} args = {};
static char *output = null;
static int verbosity = 0;
static const char *const help;
static const char *const version;
static void compile(const char *file, char *src, uptr 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);
int main(int ac, char *av[]) { A0 = av[0];
struct opt opt = OPTGET_INIT;
opt.str = "bBcEf:O:pPqSvW:";
opt.lops = (struct lop[]){
{ "help", ARG_NUL, 256 },
{ "version", ARG_NUL, 257 },
{ null, 0, 0 }
};
for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) {
case 'b': { args.bflag = true; } break; /* Output LLVM IR files */
case 'B': { args.Bflag = true; } break; /* Output LLVM bitcode files */
case 'c': { args.cflag = true; } break; /* Output object files */
case 'E': { args.Eflag = true; } break; /* Output lexer tokens */
case 'f': { opt_f(opt.arg); } break; /* Configure formatting */
case 'o': { output = opt.arg; } break; /* Specify output file */
case 'O': { opt_O(opt.arg); } break; /* Configure optimisation */
case 'p': { args.pflag = true; } break; /* Output parser AST */
case 'P': { args.Pflag = true; } break; /* Output analyser AST */
case 'q': { args.qflag = true; } break; /* Silence certain outputs (for benchmarking) */
case 'S': { args.Sflag = true; } break; /* Output assembly files */
case 'v': { verbosity += 1; } break; /* Increase verbosity */
case 'W': { opt_W(opt.arg); } break; /* Configure warnings and errors */
case 256: { fputs(help, stdout); } return 0;
case 257: { fputs(version, stdout); } 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, uptr len) {
initialise();
lex l = lex_init(file, src, len);
if (args.Eflag) { lex_debug(&l); goto end; }
ast *a = parse(&l);
if (args.pflag) { if (!args.qflag) { ast_print(a, 0); } goto end; }
if (has_error()) { exit(1); }
assert(a->k == AK_PROG); analyse(a);
if (args.Pflag) { if (!args.qflag) { ast_print(a, 0); } goto end; }
if (has_error()) { exit(1); }
if (args.bflag) { llvm(a, strdup(file), llvm_ir); }
else if (args.Bflag) { llvm(a, strdup(file), llvm_bc); }
else if (args.Sflag) { llvm(a, strdup(file), llvm_asm); }
else { llvm(a, strdup(file), llvm_obj); }
if (has_error()) { exit(1); }
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); }
}
static const char *const help =
"G - G Programming Language\n"
"Usage: g file...\n"
"Options:\n"
" -b, Output LLVM IR files\n"
" -B, Output LLVM bitcode files\n"
" -c, Output object files\n"
" -E, Output lexer tokens\n"
// " -f, Configure formatting\n"
// " -o file, Specify output file\n"
// " -O, Configure optimisation\n"
" -p, Output parser AST\n"
" -P, Output analyser AST\n"
" -q, Silence certain outputs (for benchmarking)\n"
" -S, Output assembly files\n"
// " -v, Increase verbosity \n"
// " -W, Configure warnings and errors\n"
" --help Display help information\n"
" --version Display version information\n"
;
static const char *const version =
"G, version " VERSION "\n"
"Copyright (C) 2021, Jakob Wakeling\n"
"All rights reserved.\n"
;
|