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 }