Mercurial > hg > index.cgi
comparison lwasm/main.c @ 0:2c24602be78f
Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
author | lost@l-w.ca |
---|---|
date | Wed, 19 Jan 2011 22:27:17 -0700 |
parents | |
children | 7317fbe024af |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:2c24602be78f |
---|---|
1 /* | |
2 main.c | |
3 | |
4 Copyright © 2010 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 #include <argp.h> | |
23 #include <stdio.h> | |
24 #include <stdlib.h> | |
25 | |
26 #include <lw_alloc.h> | |
27 #include <lw_string.h> | |
28 #include <lw_stringlist.h> | |
29 #include <lw_expr.h> | |
30 | |
31 #include "lwasm.h" | |
32 #include "input.h" | |
33 | |
34 extern int parse_pragma_string(asmstate_t *as, char *str, int ignoreerr); | |
35 | |
36 /* command line option handling */ | |
37 const char *argp_program_version = "lwasm from " PACKAGE_STRING; | |
38 const char *argp_program_bug_address = PACKAGE_BUGREPORT; | |
39 char *program_name; | |
40 | |
41 static struct argp_option options[] = | |
42 { | |
43 { "output", 'o', "FILE", 0, "Output to FILE"}, | |
44 { "debug", 'd', "LEVEL", OPTION_ARG_OPTIONAL, "Set debug mode"}, | |
45 { "format", 'f', "TYPE", 0, "Select output format: decb, raw, obj, os9"}, | |
46 { "list", 'l', "FILE", OPTION_ARG_OPTIONAL, "Generate list [to FILE]"}, | |
47 { "symbols", 's', 0, OPTION_ARG_OPTIONAL, "Generate symbol list in listing, no effect without --list"}, | |
48 { "decb", 'b', 0, 0, "Generate DECB .bin format output, equivalent of --format=decb"}, | |
49 { "raw", 'r', 0, 0, "Generate raw binary format output, equivalent of --format=raw"}, | |
50 { "obj", 0x100, 0, 0, "Generate proprietary object file format for later linking, equivalent of --format=obj" }, | |
51 { "depend", 0x101, 0, 0, "Output a dependency list to stdout; do not do any actual output though assembly is completed as usual" }, | |
52 { "pragma", 'p', "PRAGMA", 0, "Set an assembler pragma to any value understood by the \"pragma\" pseudo op"}, | |
53 { "6809", '9', 0, 0, "Set assembler to 6809 only mode" }, | |
54 { "6309", '3', 0, 0, "Set assembler to 6309 mode (default)" }, | |
55 { "includedir", 'I', "PATH", 0, "Add entry to include path" }, | |
56 { 0 } | |
57 }; | |
58 | |
59 | |
60 static error_t parse_opts(int key, char *arg, struct argp_state *state) | |
61 { | |
62 asmstate_t *as = state -> input; | |
63 | |
64 switch (key) | |
65 { | |
66 case 'I': | |
67 lw_stringlist_addstring(as -> include_list, arg); | |
68 break; | |
69 | |
70 case 'o': | |
71 if (as -> output_file) | |
72 lw_free(as -> output_file); | |
73 as -> output_file = lw_strdup(arg); | |
74 break; | |
75 | |
76 case 'd': | |
77 if (!arg) | |
78 as -> debug_level = 50; | |
79 else | |
80 as -> debug_level = atoi(arg); | |
81 break; | |
82 | |
83 case 'l': | |
84 if (as -> list_file) | |
85 lw_free(as -> list_file); | |
86 if (!arg) | |
87 as -> list_file = NULL; | |
88 else | |
89 as -> list_file = lw_strdup(arg); | |
90 as -> flags |= FLAG_LIST; | |
91 break; | |
92 | |
93 case 's': | |
94 as -> flags |= FLAG_SYMBOLS; | |
95 break; | |
96 | |
97 case 'b': | |
98 as -> output_format = OUTPUT_DECB; | |
99 break; | |
100 | |
101 case 'r': | |
102 as -> output_format = OUTPUT_RAW; | |
103 break; | |
104 | |
105 case 0x100: | |
106 as -> output_format = OUTPUT_OBJ; | |
107 break; | |
108 | |
109 case 0x101: | |
110 as -> flags |= FLAG_DEPEND; | |
111 break; | |
112 | |
113 case 'f': | |
114 if (!strcasecmp(arg, "decb")) | |
115 as -> output_format = OUTPUT_DECB; | |
116 else if (!strcasecmp(arg, "raw")) | |
117 as -> output_format = OUTPUT_RAW; | |
118 else if (!strcasecmp(arg, "obj")) | |
119 as -> output_format = OUTPUT_OBJ; | |
120 else if (!strcasecmp(arg, "os9")) | |
121 { | |
122 as -> pragmas |= PRAGMA_DOLLARNOTLOCAL; | |
123 as -> output_format = OUTPUT_OS9; | |
124 } | |
125 else | |
126 { | |
127 fprintf(stderr, "Invalid output format: %s\n", arg); | |
128 exit(1); | |
129 } | |
130 break; | |
131 | |
132 case 'p': | |
133 if (parse_pragma_string(as, arg, 0) == 0) | |
134 { | |
135 fprintf(stderr, "Unrecognized pragma string: %s\n", arg); | |
136 exit(1); | |
137 } | |
138 break; | |
139 | |
140 case '9': | |
141 as -> target = TARGET_6809; | |
142 break; | |
143 | |
144 case '3': | |
145 as -> target = TARGET_6309; | |
146 break; | |
147 | |
148 case ARGP_KEY_END: | |
149 break; | |
150 | |
151 case ARGP_KEY_ARG: | |
152 lw_stringlist_addstring(as -> input_files, arg); | |
153 break; | |
154 | |
155 default: | |
156 return ARGP_ERR_UNKNOWN; | |
157 } | |
158 return 0; | |
159 } | |
160 | |
161 static struct argp argp = | |
162 { | |
163 options, | |
164 parse_opts, | |
165 "<input file>", | |
166 "LWASM, a HD6309 and MC6809 cross-assembler" | |
167 }; | |
168 | |
169 /* | |
170 main function; parse command line, set up assembler state, and run the | |
171 assembler on the first file | |
172 */ | |
173 extern void do_pass1(asmstate_t *as); | |
174 extern void do_pass2(asmstate_t *as); | |
175 extern void do_pass3(asmstate_t *as); | |
176 extern void do_pass4(asmstate_t *as); | |
177 extern void do_pass5(asmstate_t *as); | |
178 extern void do_pass6(asmstate_t *as); | |
179 extern void do_pass7(asmstate_t *as); | |
180 extern void do_output(asmstate_t *as); | |
181 extern void do_list(asmstate_t *as); | |
182 extern lw_expr_t lwasm_evaluate_special(int t, void *ptr, void *priv); | |
183 extern lw_expr_t lwasm_evaluate_var(char *var, void *priv); | |
184 extern lw_expr_t lwasm_parse_term(char **p, void *priv); | |
185 | |
186 struct passlist_s | |
187 { | |
188 char *passname; | |
189 void (*fn)(asmstate_t *as); | |
190 int fordep; | |
191 } passlist[] = { | |
192 { "parse", do_pass1, 1 }, | |
193 { "symcheck", do_pass2 }, | |
194 { "resolve1", do_pass3 }, | |
195 { "resolve2", do_pass4 }, | |
196 { "addressresolve", do_pass5 }, | |
197 { "finalize", do_pass6 }, | |
198 { "emit", do_pass7 }, | |
199 { NULL, NULL } | |
200 }; | |
201 | |
202 | |
203 int main(int argc, char **argv) | |
204 { | |
205 int passnum; | |
206 | |
207 /* assembler state */ | |
208 asmstate_t asmstate = { 0 }; | |
209 program_name = argv[0]; | |
210 | |
211 lw_expr_set_special_handler(lwasm_evaluate_special); | |
212 lw_expr_set_var_handler(lwasm_evaluate_var); | |
213 lw_expr_set_term_parser(lwasm_parse_term); | |
214 | |
215 /* initialize assembler state */ | |
216 asmstate.include_list = lw_stringlist_create(); | |
217 asmstate.input_files = lw_stringlist_create(); | |
218 asmstate.nextcontext = 1; | |
219 | |
220 /* parse command line arguments */ | |
221 argp_parse(&argp, argc, argv, 0, 0, &asmstate); | |
222 | |
223 if (!asmstate.output_file) | |
224 { | |
225 asmstate.output_file = lw_strdup("a.out"); | |
226 } | |
227 | |
228 input_init(&asmstate); | |
229 | |
230 for (passnum = 0; passlist[passnum].fn; passnum++) | |
231 { | |
232 if ((asmstate.flags & FLAG_DEPEND) && passlist[passnum].fordep == 0) | |
233 continue; | |
234 debug_message(&asmstate, 50, "Doing pass %d (%s)\n", passnum, passlist[passnum].passname); | |
235 (passlist[passnum].fn)(&asmstate); | |
236 debug_message(&asmstate, 50, "After pass %d (%s)\n", passnum, passlist[passnum].passname); | |
237 dump_state(&asmstate); | |
238 | |
239 if (asmstate.errorcount > 0) | |
240 { | |
241 lwasm_show_errors(&asmstate); | |
242 exit(1); | |
243 } | |
244 } | |
245 | |
246 if (asmstate.flags & FLAG_DEPEND) | |
247 { | |
248 // output dependencies | |
249 char *n; | |
250 | |
251 while (n = lw_stack_pop(asmstate.includelist)) | |
252 { | |
253 fprintf(stdout, "%s\n", n); | |
254 lw_free(n); | |
255 } | |
256 } | |
257 else | |
258 { | |
259 debug_message(&asmstate, 50, "Doing output"); | |
260 do_output(&asmstate); | |
261 } | |
262 | |
263 debug_message(&asmstate, 50, "Done assembly"); | |
264 | |
265 do_list(&asmstate); | |
266 | |
267 exit(0); | |
268 } |