#include #include #include #include #include #include "lexer.h" #include "parse.h" #include "gen.h" #include "opt.h" bool compile_warning = true; static void compile_diagnostic(const char *type, const char *fmt, va_list va) { fprintf(stderr, "%s %s: ", lexer_marker(), type); vfprintf(stderr, fmt, va); fprintf(stderr, "\n"); } void compile_error(const char *fmt, ...) { va_list a; va_start(a, fmt); compile_diagnostic("error", fmt, a); va_end(a); exit(EXIT_FAILURE); } void compile_warn(const char *fmt, ...) { if (!compile_warning) return; va_list a; va_start(a, fmt); compile_diagnostic("warning", fmt, a); va_end(a); } void compile_ice(const char *fmt, ...) { va_list a; va_start(a, fmt); compile_diagnostic("internal error", fmt, a); va_end(a); /* flush all streams */ fflush(NULL); abort(); } int compile_begin(bool dump) { parse_init(); list_t *block = parse_run(); size_t index = 0; for (list_iterator_t *it = list_iterator(block); !list_iterator_end(it); index++) { printf("# block %zu\n", index); if (!dump) { gen_toplevel(list_iterator_next(it)); } else { printf("%s", ast_string(list_iterator_next(it))); } } return true; } static bool parse_option(const char *optname, int *cargc, char ***cargv, char **out, int ds, bool split) { int argc = *cargc; char **argv = *cargv; size_t len = strlen(optname); if (strncmp(argv[0]+ds, optname, len)) return false; /* it's --optname, check how the parameter is supplied */ if (argv[0][ds+len] == '=') { *out = argv[0]+ds+len+1; return true; } if (!split || argc < ds) /* no parameter was provided, or only single-arg form accepted */ return false; /* using --opt param */ *out = argv[1]; --*cargc; ++*cargv; return true; } int main(int argc, char **argv) { bool dumpast = false; char *standard = NULL; while (argc > 1) { ++argv; --argc; if (argv[0][0] == '-') { if (parse_option("std", &argc, &argv, &standard, 1, false)) continue; } if (!strcmp(*argv, "--dump-ast")) { dumpast = true; continue; } fprintf(stderr, "unknown option: %s\n", argv[argc-1]); return EXIT_FAILURE; } if (standard) { if (!strcmp(standard, "licec")) opt_std_set(STANDARD_LICEC); else if (!strcmp(standard, "gnuc")) opt_std_set(STANDARD_GNUC); else if (!strcmp(standard, "c90")) opt_std_set(STANDARD_C90); else if (!strcmp(standard, "c99")) opt_std_set(STANDARD_C99); else if (!strcmp(standard, "c11")) opt_std_set(STANDARD_C11); else if (!strcmp(standard, "kandr")) opt_std_set(STANDARD_KANDR); else { fprintf(stderr, "unknown standard: %s\n", standard); return EXIT_FAILURE; } } return compile_begin(dumpast); }