Mercurial > hg-old > index.cgi
annotate lwasm/main.c @ 448:5cccf90bf838 3.0 tip
Fixed bug with complex external references generating invalid relocations in the object file
author | lost@l-w.ca |
---|---|
date | Fri, 05 Nov 2010 22:27:00 -0600 |
parents | 027d7fbcdcfc |
children |
rev | line source |
---|---|
323 | 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 <config.h> | |
23 | |
24 #include <argp.h> | |
25 #include <stdio.h> | |
26 #include <stdlib.h> | |
27 | |
329 | 28 #include <lw_alloc.h> |
325 | 29 #include <lw_string.h> |
30 #include <lw_stringlist.h> | |
335 | 31 #include <lw_expr.h> |
325 | 32 |
323 | 33 #include "lwasm.h" |
330 | 34 #include "input.h" |
323 | 35 |
352 | 36 extern int parse_pragma_string(asmstate_t *as, char *str, int ignoreerr); |
325 | 37 |
323 | 38 /* command line option handling */ |
39 const char *argp_program_version = "lwasm from " PACKAGE_STRING; | |
40 const char *argp_program_bug_address = PACKAGE_BUGREPORT; | |
41 char *program_name; | |
42 | |
43 static struct argp_option options[] = | |
44 { | |
45 { "output", 'o', "FILE", 0, "Output to FILE"}, | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
46 { "debug", 'd', "LEVEL", OPTION_ARG_OPTIONAL, "Set debug mode"}, |
323 | 47 { "format", 'f', "TYPE", 0, "Select output format: decb, raw, obj, os9"}, |
48 { "list", 'l', "FILE", OPTION_ARG_OPTIONAL, "Generate list [to FILE]"}, | |
390
027d7fbcdcfc
Basic symbol table output; needs work for non-constant symbols
lost@l-w.ca
parents:
387
diff
changeset
|
49 { "symbols", 's', 0, OPTION_ARG_OPTIONAL, "Generate symbol list in listing, no effect without --list"}, |
323 | 50 { "decb", 'b', 0, 0, "Generate DECB .bin format output, equivalent of --format=decb"}, |
51 { "raw", 'r', 0, 0, "Generate raw binary format output, equivalent of --format=raw"}, | |
52 { "obj", 0x100, 0, 0, "Generate proprietary object file format for later linking, equivalent of --format=obj" }, | |
53 { "depend", 0x101, 0, 0, "Output a dependency list to stdout; do not do any actual output though assembly is completed as usual" }, | |
54 { "pragma", 'p', "PRAGMA", 0, "Set an assembler pragma to any value understood by the \"pragma\" pseudo op"}, | |
55 { "6809", '9', 0, 0, "Set assembler to 6809 only mode" }, | |
56 { "6309", '3', 0, 0, "Set assembler to 6309 mode (default)" }, | |
57 { "includedir", 'I', "PATH", 0, "Add entry to include path" }, | |
58 { 0 } | |
59 }; | |
60 | |
61 | |
62 static error_t parse_opts(int key, char *arg, struct argp_state *state) | |
63 { | |
64 asmstate_t *as = state -> input; | |
65 | |
66 switch (key) | |
67 { | |
68 case 'I': | |
325 | 69 lw_stringlist_addstring(as -> include_list, arg); |
70 break; | |
71 | |
323 | 72 case 'o': |
325 | 73 if (as -> output_file) |
74 lw_free(as -> output_file); | |
75 as -> output_file = lw_strdup(arg); | |
76 break; | |
77 | |
323 | 78 case 'd': |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
79 if (!arg) |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
80 as -> debug_level = 50; |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
81 else |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
82 as -> debug_level = atoi(arg); |
323 | 83 break; |
84 | |
85 case 'l': | |
325 | 86 if (as -> list_file) |
87 lw_free(as -> list_file); | |
88 if (!arg) | |
89 as -> list_file = NULL; | |
90 else | |
91 as -> list_file = lw_strdup(arg); | |
92 as -> flags |= FLAG_LIST; | |
93 break; | |
390
027d7fbcdcfc
Basic symbol table output; needs work for non-constant symbols
lost@l-w.ca
parents:
387
diff
changeset
|
94 |
027d7fbcdcfc
Basic symbol table output; needs work for non-constant symbols
lost@l-w.ca
parents:
387
diff
changeset
|
95 case 's': |
027d7fbcdcfc
Basic symbol table output; needs work for non-constant symbols
lost@l-w.ca
parents:
387
diff
changeset
|
96 as -> flags |= FLAG_SYMBOLS; |
027d7fbcdcfc
Basic symbol table output; needs work for non-constant symbols
lost@l-w.ca
parents:
387
diff
changeset
|
97 break; |
325 | 98 |
323 | 99 case 'b': |
100 as -> output_format = OUTPUT_DECB; | |
101 break; | |
102 | |
103 case 'r': | |
104 as -> output_format = OUTPUT_RAW; | |
105 break; | |
106 | |
107 case 0x100: | |
108 as -> output_format = OUTPUT_OBJ; | |
109 break; | |
110 | |
111 case 0x101: | |
325 | 112 as -> flags |= FLAG_DEPEND; |
113 break; | |
114 | |
323 | 115 case 'f': |
116 if (!strcasecmp(arg, "decb")) | |
117 as -> output_format = OUTPUT_DECB; | |
118 else if (!strcasecmp(arg, "raw")) | |
119 as -> output_format = OUTPUT_RAW; | |
120 else if (!strcasecmp(arg, "obj")) | |
121 as -> output_format = OUTPUT_OBJ; | |
122 else if (!strcasecmp(arg, "os9")) | |
123 { | |
325 | 124 as -> pragmas |= PRAGMA_DOLLARNOTLOCAL; |
323 | 125 as -> output_format = OUTPUT_OS9; |
126 } | |
127 else | |
128 { | |
129 fprintf(stderr, "Invalid output format: %s\n", arg); | |
130 exit(1); | |
131 } | |
132 break; | |
133 | |
134 case 'p': | |
352 | 135 if (parse_pragma_string(as, arg, 0) == 0) |
325 | 136 { |
137 fprintf(stderr, "Unrecognized pragma string: %s\n", arg); | |
138 exit(1); | |
139 } | |
140 break; | |
141 | |
323 | 142 case '9': |
143 as -> target = TARGET_6809; | |
144 break; | |
145 | |
146 case '3': | |
147 as -> target = TARGET_6309; | |
148 break; | |
149 | |
150 case ARGP_KEY_END: | |
151 break; | |
152 | |
153 case ARGP_KEY_ARG: | |
325 | 154 lw_stringlist_addstring(as -> input_files, arg); |
323 | 155 break; |
156 | |
157 default: | |
158 return ARGP_ERR_UNKNOWN; | |
159 } | |
160 return 0; | |
161 } | |
162 | |
163 static struct argp argp = | |
164 { | |
165 options, | |
166 parse_opts, | |
167 "<input file>", | |
168 "LWASM, a HD6309 and MC6809 cross-assembler" | |
169 }; | |
170 | |
171 /* | |
172 main function; parse command line, set up assembler state, and run the | |
173 assembler on the first file | |
174 */ | |
332 | 175 extern void do_pass1(asmstate_t *as); |
363
d96c30e60ddf
Added pass2 and various supporting logic including symbol lookups
lost@starbug
parents:
352
diff
changeset
|
176 extern void do_pass2(asmstate_t *as); |
364 | 177 extern void do_pass3(asmstate_t *as); |
365 | 178 extern void do_pass4(asmstate_t *as); |
367 | 179 extern void do_pass5(asmstate_t *as); |
180 extern void do_pass6(asmstate_t *as); | |
368 | 181 extern void do_pass7(asmstate_t *as); |
374 | 182 extern void do_output(asmstate_t *as); |
383
848d3cca8078
Fixed imm8 to actually use expression and also fixed gen mode to respect > and <
lost@starbug
parents:
374
diff
changeset
|
183 extern void do_list(asmstate_t *as); |
346
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
345
diff
changeset
|
184 extern lw_expr_t lwasm_evaluate_special(int t, void *ptr, void *priv); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
345
diff
changeset
|
185 extern lw_expr_t lwasm_evaluate_var(char *var, void *priv); |
a82c55070624
Added expression parsing infrastructure and misc fixes
lost@starbug
parents:
345
diff
changeset
|
186 extern lw_expr_t lwasm_parse_term(char **p, void *priv); |
364 | 187 |
188 struct passlist_s | |
189 { | |
190 char *passname; | |
191 void (*fn)(asmstate_t *as); | |
385 | 192 int fordep; |
364 | 193 } passlist[] = { |
385 | 194 { "parse", do_pass1, 1 }, |
364 | 195 { "symcheck", do_pass2 }, |
196 { "resolve1", do_pass3 }, | |
365 | 197 { "resolve2", do_pass4 }, |
367 | 198 { "addressresolve", do_pass5 }, |
199 { "finalize", do_pass6 }, | |
368 | 200 { "emit", do_pass7 }, |
364 | 201 { NULL, NULL } |
202 }; | |
203 | |
370 | 204 |
323 | 205 int main(int argc, char **argv) |
206 { | |
364 | 207 int passnum; |
208 | |
323 | 209 /* assembler state */ |
210 asmstate_t asmstate = { 0 }; | |
325 | 211 program_name = argv[0]; |
323 | 212 |
337 | 213 lw_expr_set_special_handler(lwasm_evaluate_special); |
214 lw_expr_set_var_handler(lwasm_evaluate_var); | |
370 | 215 lw_expr_set_term_parser(lwasm_parse_term); |
337 | 216 |
325 | 217 /* initialize assembler state */ |
329 | 218 asmstate.include_list = lw_stringlist_create(); |
325 | 219 asmstate.input_files = lw_stringlist_create(); |
345
7416c3f9c321
Basic macro processor ported forward; added context break handling for local symbols
lost@starbug
parents:
342
diff
changeset
|
220 asmstate.nextcontext = 1; |
325 | 221 |
222 /* parse command line arguments */ | |
323 | 223 argp_parse(&argp, argc, argv, 0, 0, &asmstate); |
224 | |
328 | 225 if (!asmstate.output_file) |
226 { | |
227 asmstate.output_file = lw_strdup("a.out"); | |
228 } | |
229 | |
330 | 230 input_init(&asmstate); |
231 | |
364 | 232 for (passnum = 0; passlist[passnum].fn; passnum++) |
363
d96c30e60ddf
Added pass2 and various supporting logic including symbol lookups
lost@starbug
parents:
352
diff
changeset
|
233 { |
385 | 234 if ((asmstate.flags & FLAG_DEPEND) && passlist[passnum].fordep == 0) |
235 continue; | |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
236 debug_message(&asmstate, 50, "Doing pass %d (%s)\n", passnum, passlist[passnum].passname); |
364 | 237 (passlist[passnum].fn)(&asmstate); |
372
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
238 debug_message(&asmstate, 50, "After pass %d (%s)\n", passnum, passlist[passnum].passname); |
90de73ba0cac
Created a useful debug framework and adjusted lw_expr_print() to return a "static" dynamic string
lost@starbug
parents:
370
diff
changeset
|
239 dump_state(&asmstate); |
364 | 240 |
241 if (asmstate.errorcount > 0) | |
242 { | |
243 lwasm_show_errors(&asmstate); | |
244 exit(1); | |
245 } | |
363
d96c30e60ddf
Added pass2 and various supporting logic including symbol lookups
lost@starbug
parents:
352
diff
changeset
|
246 } |
384 | 247 |
248 if (asmstate.flags & FLAG_DEPEND) | |
249 { | |
250 // output dependencies | |
251 char *n; | |
252 | |
253 while (n = lw_stack_pop(asmstate.includelist)) | |
254 { | |
255 fprintf(stdout, "%s\n", n); | |
256 lw_free(n); | |
257 } | |
258 } | |
259 else | |
260 { | |
261 debug_message(&asmstate, 50, "Doing output"); | |
262 do_output(&asmstate); | |
263 } | |
374 | 264 |
265 debug_message(&asmstate, 50, "Done assembly"); | |
383
848d3cca8078
Fixed imm8 to actually use expression and also fixed gen mode to respect > and <
lost@starbug
parents:
374
diff
changeset
|
266 |
848d3cca8078
Fixed imm8 to actually use expression and also fixed gen mode to respect > and <
lost@starbug
parents:
374
diff
changeset
|
267 do_list(&asmstate); |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
385
diff
changeset
|
268 |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
385
diff
changeset
|
269 exit(0); |
323 | 270 } |