Rev 8733 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8733 | Rev 9234 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Tiny BASIC |
2 | * Tiny BASIC |
3 | * Interpreter and Compiler Main Program |
3 | * Interpreter and Compiler Main Program |
4 | * |
4 | * |
5 | * Released as Public Domain by Damian Gareth Walker 2019 |
5 | * Released as Public Domain by Damian Gareth Walker 2019 |
6 | * Created: 04-Aug-2019 |
6 | * Created: 04-Aug-2019 |
7 | */ |
7 | */ |
8 | 8 | ||
9 | 9 | ||
10 | /* included headers */ |
10 | /* included headers */ |
11 | #include |
11 | #include |
12 | #include |
12 | #include |
13 | #include |
13 | #include |
14 | #include "options.h" |
14 | #include "options.h" |
15 | #include "errors.h" |
15 | #include "errors.h" |
16 | #include "parser.h" |
16 | #include "parser.h" |
17 | #include "statement.h" |
17 | #include "statement.h" |
18 | #include "interpret.h" |
18 | #include "interpret.h" |
19 | #include "formatter.h" |
19 | #include "formatter.h" |
20 | #include "generatec.h" |
20 | #include "generatec.h" |
21 | 21 | ||
22 | #ifdef _KOLIBRI |
22 | #ifdef _KOLIBRI |
- | 23 | #include |
|
23 | #define KTCC_BIN "/kolibrios/develop/tcc/tcc" |
24 | #define KTCC_BIN "/kolibrios/develop/tcc/tcc" |
24 | #define KTCC_FLAGS "%s -o %s -lck" |
25 | #define KTCC_FLAGS "-nobss %s -o %s -ltcc -lc.obj" |
25 | #endif |
26 | #endif |
26 | 27 | ||
27 | /* static variables */ |
28 | /* static variables */ |
28 | static char *input_filename = NULL; /* name of the input file */ |
29 | static char *input_filename = NULL; /* name of the input file */ |
29 | static enum { /* action to take with parsed program */ |
30 | static enum { /* action to take with parsed program */ |
30 | OUTPUT_INTERPRET, /* interpret the program */ |
31 | OUTPUT_INTERPRET, /* interpret the program */ |
31 | OUTPUT_LST, /* output a formatted listing */ |
32 | OUTPUT_LST, /* output a formatted listing */ |
32 | OUTPUT_C, /* output a C program */ |
33 | OUTPUT_C, /* output a C program */ |
33 | OUTPUT_EXE /* output an executable */ |
34 | OUTPUT_EXE /* output an executable */ |
34 | } output = OUTPUT_INTERPRET; |
35 | } output = OUTPUT_INTERPRET; |
35 | static ErrorHandler *errors; /* universal error handler */ |
36 | static ErrorHandler *errors; /* universal error handler */ |
36 | static LanguageOptions *loptions; /* language options */ |
37 | static LanguageOptions *loptions; /* language options */ |
37 | 38 | ||
38 | 39 | ||
39 | /* |
40 | /* |
40 | * Level 2 Routines |
41 | * Level 2 Routines |
41 | */ |
42 | */ |
42 | 43 | ||
43 | 44 | ||
44 | /* |
45 | /* |
45 | * Set line number option |
46 | * Set line number option |
46 | * params: |
47 | * params: |
47 | * char* option the option supplied on the command line |
48 | * char* option the option supplied on the command line |
48 | */ |
49 | */ |
49 | static void set_line_numbers (char *option) { |
50 | static void set_line_numbers (char *option) { |
50 | if (! strncmp ("optional", option, strlen (option))) |
51 | if (! strncmp ("optional", option, strlen (option))) |
51 | loptions->set_line_numbers (loptions, LINE_NUMBERS_OPTIONAL); |
52 | loptions->set_line_numbers (loptions, LINE_NUMBERS_OPTIONAL); |
52 | else if (! strncmp ("implied", option, strlen (option))) |
53 | else if (! strncmp ("implied", option, strlen (option))) |
53 | loptions->set_line_numbers (loptions, LINE_NUMBERS_IMPLIED); |
54 | loptions->set_line_numbers (loptions, LINE_NUMBERS_IMPLIED); |
54 | else if (! strncmp ("mandatory", option, strlen (option))) |
55 | else if (! strncmp ("mandatory", option, strlen (option))) |
55 | loptions->set_line_numbers (loptions, LINE_NUMBERS_MANDATORY); |
56 | loptions->set_line_numbers (loptions, LINE_NUMBERS_MANDATORY); |
56 | else |
57 | else |
57 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
58 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
58 | } |
59 | } |
59 | 60 | ||
60 | /* |
61 | /* |
61 | * Set line number limit |
62 | * Set line number limit |
62 | * params: |
63 | * params: |
63 | * char* option the option supplied on the command line |
64 | * char* option the option supplied on the command line |
64 | */ |
65 | */ |
65 | static void set_line_limit (char *option) { |
66 | static void set_line_limit (char *option) { |
66 | int limit; /* the limit contained in the option */ |
67 | int limit; /* the limit contained in the option */ |
67 | if (sscanf (option, "%d", &limit)) |
68 | if (sscanf (option, "%d", &limit)) |
68 | loptions->set_line_limit (loptions, limit); |
69 | loptions->set_line_limit (loptions, limit); |
69 | else |
70 | else |
70 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
71 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
71 | } |
72 | } |
72 | 73 | ||
73 | /* |
74 | /* |
74 | * Set comment option |
75 | * Set comment option |
75 | * params: |
76 | * params: |
76 | * char* option the option supplied on the command line |
77 | * char* option the option supplied on the command line |
77 | */ |
78 | */ |
78 | static void set_comments (char *option) { |
79 | static void set_comments (char *option) { |
79 | if (! strncmp ("enabled", option, strlen (option))) |
80 | if (! strncmp ("enabled", option, strlen (option))) |
80 | loptions->set_comments (loptions, COMMENTS_ENABLED); |
81 | loptions->set_comments (loptions, COMMENTS_ENABLED); |
81 | else if (! strncmp ("disabled", option, strlen (option))) |
82 | else if (! strncmp ("disabled", option, strlen (option))) |
82 | loptions->set_comments (loptions, COMMENTS_DISABLED); |
83 | loptions->set_comments (loptions, COMMENTS_DISABLED); |
83 | else |
84 | else |
84 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
85 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
85 | } |
86 | } |
86 | 87 | ||
87 | /* |
88 | /* |
88 | * Set the output options |
89 | * Set the output options |
89 | * params: |
90 | * params: |
90 | * char* option the option supplied on the command line |
91 | * char* option the option supplied on the command line |
91 | */ |
92 | */ |
92 | static void set_output (char *option) { |
93 | static void set_output (char *option) { |
93 | if (! strcmp ("lst", option)) |
94 | if (! strcmp ("lst", option)) |
94 | output = OUTPUT_LST; |
95 | output = OUTPUT_LST; |
95 | else if (! strcmp ("c", option)) |
96 | else if (! strcmp ("c", option)) |
96 | output = OUTPUT_C; |
97 | output = OUTPUT_C; |
97 | else if (! strcmp ("exe", option)) |
98 | else if (! strcmp ("exe", option)) |
98 | output = OUTPUT_EXE; |
99 | output = OUTPUT_EXE; |
99 | else |
100 | else |
100 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
101 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
101 | } |
102 | } |
102 | 103 | ||
103 | /* |
104 | /* |
104 | * Set the GOSUB stack limit option |
105 | * Set the GOSUB stack limit option |
105 | * params: |
106 | * params: |
106 | * char* option the option supplied on the command line |
107 | * char* option the option supplied on the command line |
107 | */ |
108 | */ |
108 | static void set_gosub_limit (char *option) { |
109 | static void set_gosub_limit (char *option) { |
109 | int limit; /* the limit contained in the option */ |
110 | int limit; /* the limit contained in the option */ |
110 | if (sscanf (option, "%d", &limit)) |
111 | if (sscanf (option, "%d", &limit)) |
111 | loptions->set_gosub_limit (loptions, limit); |
112 | loptions->set_gosub_limit (loptions, limit); |
112 | else |
113 | else |
113 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
114 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
114 | } |
115 | } |
115 | 116 | ||
116 | 117 | ||
117 | /* |
118 | /* |
118 | * Level 1 Routines |
119 | * Level 1 Routines |
119 | */ |
120 | */ |
120 | 121 | ||
121 | 122 | ||
122 | /* |
123 | /* |
123 | * Process the command line options |
124 | * Process the command line options |
124 | * params: |
125 | * params: |
125 | * int argc number of arguments on the command line |
126 | * int argc number of arguments on the command line |
126 | * char** argv the arguments |
127 | * char** argv the arguments |
127 | */ |
128 | */ |
128 | static void set_options (int argc, char **argv) { |
129 | static void set_options (int argc, char **argv) { |
129 | 130 | ||
130 | /* local variables */ |
131 | /* local variables */ |
131 | int argn; /* argument number count */ |
132 | int argn; /* argument number count */ |
132 | 133 | ||
133 | /* loop through all parameters */ |
134 | /* loop through all parameters */ |
134 | for (argn = 1; argn < argc && ! errors->get_code (errors); ++argn) { |
135 | for (argn = 1; argn < argc && ! errors->get_code (errors); ++argn) { |
135 | 136 | ||
136 | /* scan for line number options */ |
137 | /* scan for line number options */ |
137 | if (! strncmp (argv[argn], "-n", 2)) |
138 | if (! strncmp (argv[argn], "-n", 2)) |
138 | set_line_numbers (&argv[argn][2]); |
139 | set_line_numbers (&argv[argn][2]); |
139 | else if (! strncmp (argv[argn], "--line-numbers=", 15)) |
140 | else if (! strncmp (argv[argn], "--line-numbers=", 15)) |
140 | set_line_numbers (&argv[argn][15]); |
141 | set_line_numbers (&argv[argn][15]); |
141 | 142 | ||
142 | /* scan for line number limit */ |
143 | /* scan for line number limit */ |
143 | else if (! strncmp (argv[argn], "-N", 2)) |
144 | else if (! strncmp (argv[argn], "-N", 2)) |
144 | set_line_limit (&argv[argn][2]); |
145 | set_line_limit (&argv[argn][2]); |
145 | else if (! strncmp (argv[argn], "--line-limit=", 13)) |
146 | else if (! strncmp (argv[argn], "--line-limit=", 13)) |
146 | set_line_limit (&argv[argn][13]); |
147 | set_line_limit (&argv[argn][13]); |
147 | 148 | ||
148 | /* scan for comment option */ |
149 | /* scan for comment option */ |
149 | else if (! strncmp (argv[argn], "-o", 2)) |
150 | else if (! strncmp (argv[argn], "-o", 2)) |
150 | set_comments (&argv[argn][2]); |
151 | set_comments (&argv[argn][2]); |
151 | else if (! strncmp (argv[argn], "--comments=", 11)) |
152 | else if (! strncmp (argv[argn], "--comments=", 11)) |
152 | set_comments (&argv[argn][11]); |
153 | set_comments (&argv[argn][11]); |
153 | 154 | ||
154 | /* scan for output option */ |
155 | /* scan for output option */ |
155 | else if (! strncmp (argv[argn], "-O", 2)) |
156 | else if (! strncmp (argv[argn], "-O", 2)) |
156 | set_output (&argv[argn][2]); |
157 | set_output (&argv[argn][2]); |
157 | else if (! strncmp (argv[argn], "--output=", 9)) |
158 | else if (! strncmp (argv[argn], "--output=", 9)) |
158 | set_output (&argv[argn][9]); |
159 | set_output (&argv[argn][9]); |
159 | 160 | ||
160 | /* scan for gosub stack limit */ |
161 | /* scan for gosub stack limit */ |
161 | else if (! strncmp (argv[argn], "-g", 2)) |
162 | else if (! strncmp (argv[argn], "-g", 2)) |
162 | set_gosub_limit (&argv[argn][2]); |
163 | set_gosub_limit (&argv[argn][2]); |
163 | else if (! strncmp (argv[argn], "--gosub-limit=", 14)) |
164 | else if (! strncmp (argv[argn], "--gosub-limit=", 14)) |
164 | set_gosub_limit (&argv[argn][14]); |
165 | set_gosub_limit (&argv[argn][14]); |
165 | 166 | ||
166 | /* accept filename */ |
167 | /* accept filename */ |
167 | else if (! input_filename) |
168 | else if (! input_filename) |
168 | input_filename = argv[argn]; |
169 | input_filename = argv[argn]; |
169 | 170 | ||
170 | /* raise an error upon illegal option */ |
171 | /* raise an error upon illegal option */ |
171 | else |
172 | else |
172 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
173 | errors->set_code (errors, E_BAD_COMMAND_LINE, 0, 0); |
173 | } |
174 | } |
174 | } |
175 | } |
175 | 176 | ||
176 | /* |
177 | /* |
177 | * Output a formatted program listing |
178 | * Output a formatted program listing |
178 | * params: |
179 | * params: |
179 | * ProgramNode* program the program to output |
180 | * ProgramNode* program the program to output |
180 | */ |
181 | */ |
181 | static void output_lst (ProgramNode *program) { |
182 | static void output_lst (ProgramNode *program) { |
182 | 183 | ||
183 | /* local variables */ |
184 | /* local variables */ |
184 | FILE *output; /* the output file */ |
185 | FILE *output; /* the output file */ |
185 | char *output_filename; /* the output filename */ |
186 | char *output_filename; /* the output filename */ |
186 | Formatter *formatter; /* the formatter object */ |
187 | Formatter *formatter; /* the formatter object */ |
187 | 188 | ||
188 | /* ascertain the output filename */ |
189 | /* ascertain the output filename */ |
189 | output_filename = malloc (strlen (input_filename) + 5); |
190 | output_filename = malloc (strlen (input_filename) + 5); |
190 | if (output_filename) { |
191 | if (output_filename) { |
191 | 192 | ||
192 | /* open the output file */ |
193 | /* open the output file */ |
193 | sprintf (output_filename, "%s.lst", input_filename); |
194 | sprintf (output_filename, "%s.lst", input_filename); |
194 | if ((output = fopen (output_filename, "w"))) { |
195 | if ((output = fopen (output_filename, "w"))) { |
195 | 196 | ||
196 | /* write to the output file */ |
197 | /* write to the output file */ |
197 | formatter = new_Formatter (errors); |
198 | formatter = new_Formatter (errors); |
198 | if (formatter) { |
199 | if (formatter) { |
199 | formatter->generate (formatter, program); |
200 | formatter->generate (formatter, program); |
200 | if (formatter->output) |
201 | if (formatter->output) |
201 | fprintf (output, "%s", formatter->output); |
202 | fprintf (output, "%s", formatter->output); |
202 | formatter->destroy (formatter); |
203 | formatter->destroy (formatter); |
203 | } |
204 | } |
204 | fclose (output); |
205 | fclose (output); |
205 | } |
206 | } |
206 | 207 | ||
207 | /* deal with errors */ |
208 | /* deal with errors */ |
208 | else |
209 | else |
209 | errors->set_code (errors, E_FILE_NOT_FOUND, 0, 0); |
210 | errors->set_code (errors, E_FILE_NOT_FOUND, 0, 0); |
210 | 211 | ||
211 | /* free the output filename */ |
212 | /* free the output filename */ |
212 | free (output_filename); |
213 | free (output_filename); |
213 | } |
214 | } |
214 | 215 | ||
215 | /* deal with out of memory error */ |
216 | /* deal with out of memory error */ |
216 | else |
217 | else |
217 | errors->set_code (errors, E_MEMORY, 0, 0); |
218 | errors->set_code (errors, E_MEMORY, 0, 0); |
218 | } |
219 | } |
219 | 220 | ||
220 | /* |
221 | /* |
221 | * Output a C source file |
222 | * Output a C source file |
222 | * params: |
223 | * params: |
223 | * ProgramNode* program the parsed program |
224 | * ProgramNode* program the parsed program |
224 | */ |
225 | */ |
225 | static void output_c (ProgramNode *program) { |
226 | static void output_c (ProgramNode *program) { |
226 | 227 | ||
227 | /* local variables */ |
228 | /* local variables */ |
228 | FILE *output; /* the output file */ |
229 | FILE *output; /* the output file */ |
229 | char *output_filename; /* the output filename */ |
230 | char *output_filename; /* the output filename */ |
230 | CProgram *c_program; /* the C program */ |
231 | CProgram *c_program; /* the C program */ |
231 | 232 | ||
232 | /* open the output file */ |
233 | /* open the output file */ |
233 | output_filename = malloc (strlen (input_filename) + 5); |
234 | output_filename = malloc (strlen (input_filename) + 5); |
234 | sprintf (output_filename, "%s.c", input_filename); |
235 | sprintf (output_filename, "%s.c", input_filename); |
235 | if ((output = fopen (output_filename, "w"))) { |
236 | if ((output = fopen (output_filename, "w"))) { |
236 | 237 | ||
237 | /* write to the output file */ |
238 | /* write to the output file */ |
238 | c_program = new_CProgram (errors, loptions); |
239 | c_program = new_CProgram (errors, loptions); |
239 | if (c_program) { |
240 | if (c_program) { |
240 | c_program->generate (c_program, program); |
241 | c_program->generate (c_program, program); |
241 | if (c_program->c_output) |
242 | if (c_program->c_output) |
242 | fprintf (output, "%s", c_program->c_output); |
243 | fprintf (output, "%s", c_program->c_output); |
243 | c_program->destroy (c_program); |
244 | c_program->destroy (c_program); |
244 | } |
245 | } |
245 | fclose (output); |
246 | fclose (output); |
246 | } |
247 | } |
247 | 248 | ||
248 | /* deal with errors */ |
249 | /* deal with errors */ |
249 | else |
250 | else |
250 | errors->set_code (errors, E_FILE_NOT_FOUND, 0, 0); |
251 | errors->set_code (errors, E_FILE_NOT_FOUND, 0, 0); |
251 | 252 | ||
252 | /* clean up allocated memory */ |
253 | /* clean up allocated memory */ |
253 | free (output_filename); |
254 | free (output_filename); |
254 | } |
255 | } |
255 | 256 | ||
256 | /* |
257 | /* |
257 | * Invoke a compiler to turn a C source file into an executable |
258 | * Invoke a compiler to turn a C source file into an executable |
258 | * params: |
259 | * params: |
259 | * char* basic_filename The BASIC program's name |
260 | * char* basic_filename The BASIC program's name |
260 | */ |
261 | */ |
261 | static void output_exe (char *command, char *basic_filename) { |
262 | static void output_exe (char *command, char *basic_filename) { |
262 | 263 | ||
263 | /* local variables */ |
264 | /* local variables */ |
264 | char |
265 | char |
265 | c_filename[256], /* the name of the C source */ |
266 | c_filename[256], /* the name of the C source */ |
266 | exe_filename[256], /* the base name of the executable */ |
267 | exe_filename[256], /* the base name of the executable */ |
267 | final_command[1024], /* the constructed compiler command */ |
268 | final_command[1024], /* the constructed compiler command */ |
268 | *ext, /* position of extension character '.' in filename */ |
269 | *ext, /* position of extension character '.' in filename */ |
269 | *src, /* source pointer for string copying */ |
270 | *src, /* source pointer for string copying */ |
270 | *dst; /* destination pointer for string copying */ |
271 | *dst; /* destination pointer for string copying */ |
271 | 272 | ||
272 | /* work out the C and EXE filenames */ |
273 | /* work out the C and EXE filenames */ |
273 | sprintf (c_filename, "%s.c", basic_filename); |
274 | sprintf (c_filename, "%s.c", basic_filename); |
274 | strcpy (exe_filename, basic_filename); |
275 | strcpy (exe_filename, basic_filename); |
275 | if ((ext = strchr (exe_filename, '.'))) |
276 | if ((ext = strchr (exe_filename, '.'))) |
276 | *ext = '\0'; |
277 | *ext = '\0'; |
277 | else |
278 | else |
278 | strcat (exe_filename, ".out"); |
279 | strcat (exe_filename, ".out"); |
279 | 280 | ||
280 | #ifndef _KOLIBRI |
281 | #ifndef _KOLIBRI |
281 | /* build the compiler command */ |
282 | /* build the compiler command */ |
282 | src = command; |
283 | src = command; |
283 | dst = final_command; |
284 | dst = final_command; |
284 | while (*src) { |
285 | while (*src) { |
285 | if (! strncmp (src, "$(TARGET)", strlen ("$(TARGET)"))) { |
286 | if (! strncmp (src, "$(TARGET)", strlen ("$(TARGET)"))) { |
286 | strcpy (dst, exe_filename); |
287 | strcpy (dst, exe_filename); |
287 | dst += strlen (exe_filename); |
288 | dst += strlen (exe_filename); |
288 | src += strlen ("$(TARGET)"); |
289 | src += strlen ("$(TARGET)"); |
289 | } else if (! strncmp (src, "$(SOURCE)", strlen ("$(SOURCE)"))) { |
290 | } else if (! strncmp (src, "$(SOURCE)", strlen ("$(SOURCE)"))) { |
290 | strcpy (dst, c_filename); |
291 | strcpy (dst, c_filename); |
291 | dst += strlen (c_filename); |
292 | dst += strlen (c_filename); |
292 | src += strlen ("$(SOURCE)"); |
293 | src += strlen ("$(SOURCE)"); |
293 | } else |
294 | } else |
294 | *(dst++) = *(src++); |
295 | *(dst++) = *(src++); |
295 | } |
296 | } |
296 | *dst = '\0'; |
297 | *dst = '\0'; |
297 | 298 | ||
298 | /* run the compiler command */ |
299 | /* run the compiler command */ |
299 | system (final_command); |
300 | system (final_command); |
300 | #else |
301 | #else |
301 | sprintf(final_command, KTCC_FLAGS, c_filename, exe_filename); |
302 | sprintf(final_command, KTCC_FLAGS, c_filename, exe_filename); |
302 | if(!_ksys_exec(KTCC_BIN, final_command)){ |
303 | if(!_ksys_exec(KTCC_BIN, final_command)){ |
303 | printf(final_command); |
- | |
304 | }else{ |
- | |
305 | printf("Bad command: %s %s\n", KTCC_BIN, final_command); |
304 | printf("Bad command: %s %s\n", KTCC_BIN, final_command); |
306 | exit(0); |
305 | exit(0); |
307 | } |
306 | } |
308 | #endif |
307 | #endif |
309 | } |
308 | } |
310 | - | ||
311 | 309 | ||
312 | /* |
310 | /* |
313 | * Top Level Routine |
311 | * Top Level Routine |
314 | */ |
312 | */ |
315 | 313 | ||
316 | 314 | ||
317 | /* |
315 | /* |
318 | * Main Program |
316 | * Main Program |
319 | * params: |
317 | * params: |
320 | * int argc number of arguments on the command line |
318 | * int argc number of arguments on the command line |
321 | * char** argv the arguments |
319 | * char** argv the arguments |
322 | * returns: |
320 | * returns: |
323 | * int any error code from processing/running the program |
321 | * int any error code from processing/running the program |
324 | */ |
322 | */ |
325 | int main (int argc, char **argv) { |
323 | int main (int argc, char **argv) { |
326 | /* local variables */ |
324 | /* local variables */ |
327 | FILE *input; /* input file */ |
325 | FILE *input; /* input file */ |
328 | ProgramNode *program; /* the parsed program */ |
326 | ProgramNode *program; /* the parsed program */ |
329 | ErrorCode code; /* error returned */ |
327 | ErrorCode code; /* error returned */ |
330 | Parser *parser; /* parser object */ |
328 | Parser *parser; /* parser object */ |
331 | Interpreter *interpreter; /* interpreter object */ |
329 | Interpreter *interpreter; /* interpreter object */ |
332 | char |
330 | char |
333 | *error_text, /* error text message */ |
331 | *error_text, /* error text message */ |
334 | *command; /* command for compilation */ |
332 | *command; /* command for compilation */ |
335 | 333 | ||
336 | /* interpret the command line arguments */ |
334 | /* interpret the command line arguments */ |
337 | errors = new_ErrorHandler (); |
335 | errors = new_ErrorHandler (); |
338 | loptions = new_LanguageOptions (); |
336 | loptions = new_LanguageOptions (); |
339 | set_options (argc, argv); |
337 | set_options (argc, argv); |
340 | 338 | ||
341 | /* give usage if filename not given */ |
339 | /* give usage if filename not given */ |
342 | if (! input_filename) { |
340 | if (! input_filename) { |
343 | printf ("Usage: tinybas [OPTIONS] INPUT-FILE\n"); |
341 | printf ("Usage: tinybas [OPTIONS] INPUT-FILE\n"); |
344 | errors->destroy (errors); |
342 | errors->destroy (errors); |
345 | loptions->destroy (loptions); |
343 | loptions->destroy (loptions); |
346 | return 0; |
344 | return 0; |
347 | } |
345 | } |
348 | /* otherwise attempt to open the file */ |
346 | /* otherwise attempt to open the file */ |
349 | if (!(input = fopen (input_filename, "r"))) { |
347 | if (!(input = fopen (input_filename, "r"))) { |
350 | printf ("Error: cannot open file %s\n", input_filename); |
348 | printf ("Error: cannot open file %s\n", input_filename); |
351 | errors->destroy (errors); |
349 | errors->destroy (errors); |
352 | loptions->destroy (loptions); |
350 | loptions->destroy (loptions); |
353 | return E_FILE_NOT_FOUND; |
351 | return E_FILE_NOT_FOUND; |
354 | } |
352 | } |
355 | 353 | ||
356 | /* get the parse tree */ |
354 | /* get the parse tree */ |
357 | parser = new_Parser (errors, loptions, input); |
355 | parser = new_Parser (errors, loptions, input); |
358 | program = parser->parse (parser); |
356 | program = parser->parse (parser); |
359 | parser->destroy (parser); |
357 | parser->destroy (parser); |
360 | fclose (input); |
358 | fclose (input); |
361 | 359 | ||
362 | /* deal with errors */ |
360 | /* deal with errors */ |
363 | if ((code = errors->get_code (errors))) { |
361 | if ((code = errors->get_code (errors))) { |
364 | error_text = errors->get_text (errors); |
362 | error_text = errors->get_text (errors); |
365 | printf ("Parse error: %s\n", error_text); |
363 | printf ("Parse error: %s\n", error_text); |
366 | free (error_text); |
364 | free (error_text); |
367 | loptions->destroy (loptions); |
365 | loptions->destroy (loptions); |
368 | errors->destroy (errors); |
366 | errors->destroy (errors); |
369 | return code; |
367 | return code; |
370 | } |
368 | } |
371 | 369 | ||
372 | /* perform the desired action */ |
370 | /* perform the desired action */ |
373 | switch (output) { |
371 | switch (output) { |
374 | case OUTPUT_INTERPRET: |
372 | case OUTPUT_INTERPRET: |
375 | interpreter = new_Interpreter (errors, loptions); |
373 | interpreter = new_Interpreter (errors, loptions); |
376 | interpreter->interpret (interpreter, program); |
374 | interpreter->interpret (interpreter, program); |
377 | interpreter->destroy (interpreter); |
375 | interpreter->destroy (interpreter); |
378 | if ((code = errors->get_code (errors))) { |
376 | if ((code = errors->get_code (errors))) { |
379 | error_text = errors->get_text (errors); |
377 | error_text = errors->get_text (errors); |
380 | printf ("Runtime error: %s\n", error_text); |
378 | printf ("Runtime error: %s\n", error_text); |
381 | free (error_text); |
379 | free (error_text); |
382 | } |
380 | } |
383 | break; |
381 | break; |
384 | case OUTPUT_LST: |
382 | case OUTPUT_LST: |
385 | output_lst (program); |
383 | output_lst (program); |
386 | break; |
384 | break; |
387 | case OUTPUT_C: |
385 | case OUTPUT_C: |
388 | output_c (program); |
386 | output_c (program); |
389 | break; |
387 | break; |
390 | case OUTPUT_EXE: |
388 | case OUTPUT_EXE: |
391 | 389 | ||
392 | #ifndef _KOLIBRI |
390 | #ifndef _KOLIBRI |
393 | if ((command = getenv ("TBEXE"))) { |
391 | if ((command = getenv ("TBEXE"))) { |
394 | output_c (program); |
392 | output_c (program); |
395 | output_exe (command, input_filename); |
393 | output_exe (command, input_filename); |
396 | } else { |
394 | } else { |
397 | printf ("TBEXE not set.\n"); |
395 | printf ("TBEXE not set.\n"); |
398 | break; |
396 | break; |
399 | } |
397 | } |
400 | #else |
398 | #else |
401 | output_c (program); |
399 | output_c (program); |
402 | output_exe (NULL, input_filename); |
400 | output_exe (NULL, input_filename); |
403 | break; |
401 | break; |
404 | #endif |
402 | #endif |
405 | } |
403 | } |
406 | /* clean up and return success */ |
404 | /* clean up and return success */ |
407 | program_destroy (program); |
405 | program_destroy (program); |
408 | loptions->destroy (loptions); |
406 | loptions->destroy (loptions); |
409 | errors->destroy (errors); |
407 | errors->destroy (errors); |
410 | exit(0); |
408 | exit(0); |
411 | }> |
409 | }> |