main.c (4807B)
1 #include <assert.h> 2 #include <errno.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <sys/stat.h> 7 #include <unistd.h> 8 #include "ast.h" 9 #include "check.h" 10 #include "emit.h" 11 #include "gen.h" 12 #include "lex.h" 13 #include "parse.h" 14 #include "qbe.h" 15 #include "type_store.h" 16 #include "typedef.h" 17 #include "util.h" 18 19 static void 20 usage(const char *argv_0) 21 { 22 fprintf(stderr, 23 "Usage: %s [-a arch] [-D ident[:type]=value] [-o output] [-T] [-t typedefs] [-N namespace] input.ha...\n", 24 argv_0); 25 } 26 27 enum stage { 28 STAGE_LEX, 29 STAGE_PARSE, 30 STAGE_CHECK, 31 STAGE_GEN, 32 STAGE_EMIT, 33 }; 34 35 static enum stage 36 parse_stage(const char *s) 37 { 38 if (s == NULL) { 39 return STAGE_EMIT; 40 } else if (strcmp(s, "lex") == 0) { 41 return STAGE_LEX; 42 } else if (strcmp(s, "parse") == 0) { 43 return STAGE_PARSE; 44 } else if (strcmp(s, "check") == 0) { 45 return STAGE_CHECK; 46 } else if (strcmp(s, "gen") == 0) { 47 return STAGE_GEN; 48 } else if (strcmp(s, "emit") == 0) { 49 return STAGE_EMIT; 50 } else { 51 fprintf(stderr, "Unknown HA_STAGE value '%s'\n", s); 52 exit(EXIT_FAILURE); 53 } 54 } 55 56 static struct ast_global_decl * 57 parse_define(const char *argv_0, const char *in) 58 { 59 struct ast_global_decl *def = xcalloc(1, sizeof(struct ast_global_decl)); 60 61 struct token tok; 62 struct lexer lexer; 63 FILE *f = fmemopen((char *)in, strlen(in), "r"); 64 const char *d = "-D"; 65 sources = &d; 66 lex_init(&lexer, f, 0); 67 68 parse_identifier(&lexer, &def->ident, false); 69 def->type = NULL; 70 if (lex(&lexer, &tok) == T_COLON) { 71 def->type = parse_type(&lexer); 72 lex(&lexer, &tok); 73 } 74 75 if (tok.token != T_EQUAL) { 76 lex_finish(&lexer); 77 usage(argv_0); 78 exit(EXIT_FAILURE); 79 } 80 def->init = parse_expression(&lexer); 81 82 lex_finish(&lexer); 83 return def; 84 } 85 86 int 87 main(int argc, char *argv[]) 88 { 89 char *output = NULL, *typedefs = NULL; 90 char *target = DEFAULT_TARGET; 91 bool is_test = false; 92 struct unit unit = {0}; 93 struct lexer lexer; 94 struct ast_global_decl *defines = NULL, **next_def = &defines; 95 96 int c; 97 while ((c = getopt(argc, argv, "D:ho:Tt:N:")) != -1) { 98 switch (c) { 99 case 'a': 100 target = optarg; 101 break; 102 case 'D': 103 *next_def = parse_define(argv[0], optarg); 104 next_def = &(*next_def)->next; 105 break; 106 case 'o': 107 output = optarg; 108 break; 109 case 'T': 110 is_test = true; 111 break; 112 case 't': 113 typedefs = optarg; 114 break; 115 case 'N': 116 unit.ns = xcalloc(1, sizeof(struct identifier)); 117 FILE *in = fmemopen(optarg, strlen(optarg), "r"); 118 const char *ns = "-N"; 119 sources = &ns; 120 lex_init(&lexer, in, 0); 121 parse_identifier(&lexer, unit.ns, false); 122 lex_finish(&lexer); 123 break; 124 case 'h': 125 default: 126 usage(argv[0]); 127 return EXIT_FAILURE; 128 } 129 } 130 131 builtin_types_init(target); 132 133 size_t ninputs = argc - optind; 134 if (ninputs == 0) { 135 usage(argv[0]); 136 return EXIT_FAILURE; 137 } 138 139 struct ast_unit aunit = {0}; 140 struct ast_subunit *subunit = &aunit.subunits; 141 struct ast_subunit **next = &aunit.subunits.next; 142 enum stage stage = parse_stage(getenv("HA_STAGE")); 143 144 sources = xcalloc(ninputs + 2, sizeof(char **)); 145 memcpy((char **)sources + 1, argv + optind, sizeof(char **) * ninputs); 146 sources[0] = "<unknown>"; 147 sources[ninputs + 1] = NULL; 148 149 for (size_t i = 0; i < ninputs; ++i) { 150 FILE *in; 151 const char *path = argv[optind + i]; 152 if (strcmp(path, "-") == 0) { 153 in = stdin; 154 } else { 155 in = fopen(path, "r"); 156 struct stat buf; 157 if (in && fstat(fileno(in), &buf) == 0 158 && S_ISDIR(buf.st_mode) != 0) { 159 fprintf(stderr, "Unable to open %s for reading: Is a directory\n", 160 path); 161 return EXIT_FAILURE; 162 } 163 } 164 165 if (!in) { 166 fprintf(stderr, "Unable to open %s for reading: %s\n", 167 path, strerror(errno)); 168 return EXIT_FAILURE; 169 } 170 171 lex_init(&lexer, in, i + 1); 172 if (stage == STAGE_LEX) { 173 struct token tok; 174 while (lex(&lexer, &tok) != T_EOF); 175 } else { 176 parse(&lexer, subunit); 177 if (i + 1 < ninputs) { 178 *next = xcalloc(1, sizeof(struct ast_subunit)); 179 subunit = *next; 180 next = &subunit->next; 181 } 182 } 183 lex_finish(&lexer); 184 } 185 186 if (stage == STAGE_PARSE || stage == STAGE_LEX) { 187 return EXIT_SUCCESS; 188 } 189 190 static struct type_store ts = {0}; 191 check(&ts, is_test, defines, &aunit, &unit); 192 if (stage == STAGE_CHECK) { 193 return EXIT_SUCCESS; 194 } 195 196 if (typedefs) { 197 FILE *out = fopen(typedefs, "w"); 198 if (!out) { 199 fprintf(stderr, "Unable to open %s for writing: %s\n", 200 typedefs, strerror(errno)); 201 return EXIT_FAILURE; 202 } 203 emit_typedefs(&unit, out); 204 fclose(out); 205 } 206 207 struct qbe_program prog = {0}; 208 gen(&unit, &ts, &prog); 209 if (stage == STAGE_GEN) { 210 return EXIT_SUCCESS; 211 } 212 213 FILE *out; 214 if (!output) { 215 out = stdout; 216 } else { 217 out = fopen(output, "w"); 218 if (!out) { 219 fprintf(stderr, "Unable to open %s for writing: %s\n", 220 output, strerror(errno)); 221 return EXIT_FAILURE; 222 } 223 } 224 emit(&prog, out); 225 fclose(out); 226 return EXIT_SUCCESS; 227 }