allow extrn symbols to be defined by the unit itself (part II)
[xorcyst.git] / parser.y
blob908003c096699751363820eb94f425095451d945
1 %{
2 /*
3 * $Id: parser.y,v 1.14 2007/11/11 22:35:51 khansen Exp $
4 * $Log: parser.y,v $
5 * Revision 1.14 2007/11/11 22:35:51 khansen
6 * compile on mac
8 * Revision 1.13 2007/08/19 11:19:47 khansen
9 * --case-insensitive option
11 * Revision 1.12 2007/08/12 18:59:00 khansen
12 * ability to generate pure 6502 binary
14 * Revision 1.11 2007/08/11 01:25:50 khansen
15 * includepaths support (-I option)
17 * Revision 1.10 2007/07/22 13:34:38 khansen
18 * convert tabs to whitespaces
20 * Revision 1.9 2005/01/05 02:28:40 kenth
21 * anonymous union parsing
23 * Revision 1.8 2004/12/29 21:45:26 kenth
24 * xorcyst 1.4.2
25 * static indexing
27 * Revision 1.7 2004/12/19 19:59:14 kenth
28 * xorcyst 1.4.0
30 * Revision 1.6 2004/12/16 13:22:27 kenth
31 * xorcyst 1.3.5
33 * Revision 1.5 2004/12/14 01:50:42 kenth
34 * xorcyst 1.3.0
36 * Revision 1.4 2004/12/11 02:12:41 kenth
37 * xorcyst 1.2.0
39 * Revision 1.3 2004/12/09 11:17:15 kenth
40 * added: warning_statement, error_statement
42 * Revision 1.2 2004/12/06 05:06:21 kenth
43 * xorcyst 1.1.0
45 * Revision 1.1 2004/06/30 07:57:03 kenth
46 * Initial revision
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include "symtab.h"
53 #include "loc.h"
54 #include "xasm.h"
55 //#define YYDEBUG 1
56 int yyparse(void);
57 void yyerror(const char *); /* In lexer */
58 int yylex(void); /* In lexer */
59 int yypushandrestart(const char *, int); /* In lexer */
60 void __yy_memcpy(char *, char *, int);
61 extern char *yytext; /* In lexer */
62 extern YYLTYPE yylloc; /* In lexer */
63 char *scan_include(int); /* In lexer */
64 extern astnode *root_node; /* Root of the generated parse tree */
65 void handle_incsrc(astnode *); /* See below */
66 void handle_incbin(astnode *); /* See below */
69 %union {
70 long integer;
71 int mnemonic;
72 const char *string;
73 const char *label;
74 const char *ident;
75 astnode *node;
78 %error-verbose
80 %token <integer> INTEGER_LITERAL
81 %token <string> STRING_LITERAL
82 %token <string> FILE_PATH
83 %token <ident> IDENTIFIER
84 %token <ident> LOCAL_ID
85 %token <ident> FORWARD_BRANCH
86 %token <ident> BACKWARD_BRANCH
87 %token <label> LABEL
88 %token <label> LOCAL_LABEL
89 %token <mnemonic> MNEMONIC
91 %type <node> identifier identifier_opt local_id assembly_unit statement labelable_statement statement_list statement_list_opt if_statement elif_statement elif_statement_list elif_statement_list_opt ifdef_statement ifndef_statement macro_decl_statement macro_statement instruction_statement data_statement storage_statement null_statement incsrc_statement incbin_statement equ_statement assign_statement public_statement extrn_statement dataseg_statement codeseg_statement charmap_statement struc_decl_statement union_decl_statement enum_decl_statement record_decl_statement instruction expression extended_expression expression_opt arithmetic_expression comparison_expression literal label label_decl identifier_list expression_list file_specifier param_list_opt arg_list_opt else_part_opt scope_access struc_access struc_initializer field_initializer_list field_initializer_list_opt field_initializer datatype storage named_data_statement unnamed_data_statement named_storage_statement unnamed_storage_statement proc_statement rept_statement label_statement message_statement warning_statement error_statement while_statement define_statement align_statement org_statement symbol_type enum_item_list enum_item record_field_list record_field sizeof_arg label_addr_part_opt label_type_part_opt from_part_opt indexed_identifier
93 %token _LABEL_ BYTE CHAR WORD DWORD DSB DSW DSD DATASEG CODESEG IF IFDEF IFNDEF ELSE ELIF ENDIF INCSRC INCBIN MACRO REPT WHILE ENDM ALIGN EQU DEFINE END PUBLIC EXTRN CHARMAP STRUC UNION ENDS RECORD ENUM ENDE PROC ENDP SIZEOF MASK TAG MESSAGE WARNING ERROR ZEROPAGE ORG
95 %token '\n'
96 %token ':'
97 %token '@'
98 %token SCOPE_OP
99 %token 'A' 'X' 'Y'
100 %token '='
101 %token '$'
102 %token '{' '}'
103 %token '[' ']'
104 %left ','
105 %token '.'
106 %right '#'
107 %right LO_OP HI_OP
108 %left '|'
109 %left '^'
110 %left '&'
111 %left EQ_OP NE_OP
112 %left LE_OP GE_OP '>' '<'
113 %left SHL_OP SHR_OP
114 %left '+' '-'
115 %right UMINUS
116 %left '*' '/' '%'
117 %right '!' '~'
118 %left '('
119 %right ')'
120 %start assembly_unit
122 assembly_unit:
123 statement_list end_opt { root_node = astnode_create_list($1); }
126 end_opt:
127 END line_tail { ; }
128 | /* empty */
131 statement_list:
132 labelable_statement { $$ = $1; }
133 | statement_list labelable_statement {
134 if ($1 != NULL) { $$ = $1; astnode_add_sibling($$, $2); }
135 else { $$ = $2; }
139 statement_list_opt:
140 statement_list { $$ = $1; }
141 | { $$ = NULL; }
144 labelable_statement:
145 label_decl statement { $$ = $1; astnode_add_sibling($$, $2); }
146 | statement { $$ = $1; }
149 statement:
150 if_statement { $$ = $1; }
151 | ifdef_statement { $$ = $1; }
152 | ifndef_statement { $$ = $1; }
153 | macro_decl_statement { $$ = $1; }
154 | macro_statement { $$ = $1; }
155 | incsrc_statement { $$ = $1; }
156 | incbin_statement { $$ = $1; }
157 | equ_statement { $$ = $1; }
158 | assign_statement { $$ = $1; }
159 | public_statement { $$ = $1; }
160 | extrn_statement { $$ = $1; }
161 | instruction_statement { $$ = $1; }
162 | data_statement { $$ = $1; }
163 | storage_statement { $$ = $1; }
164 | dataseg_statement { $$ = $1; }
165 | codeseg_statement { $$ = $1; }
166 | charmap_statement { $$ = $1; }
167 | struc_decl_statement { $$ = $1; }
168 | union_decl_statement { $$ = $1; }
169 | enum_decl_statement { $$ = $1; }
170 | record_decl_statement { $$ = $1; }
171 | proc_statement { $$ = $1; }
172 | rept_statement { $$ = $1; }
173 | while_statement { $$ = $1; }
174 | label_statement { $$ = $1; }
175 | message_statement { $$ = $1; }
176 | warning_statement { $$ = $1; }
177 | error_statement { $$ = $1; }
178 | define_statement { $$ = $1; }
179 | align_statement { $$ = $1; }
180 | org_statement { $$ = $1; }
181 | null_statement { $$ = $1; }
182 | error line_tail { $$ = NULL; }
185 org_statement:
186 ORG expression line_tail { $$ = astnode_create_org($2, @$); }
189 align_statement:
190 ALIGN identifier_list expression line_tail { $$ = astnode_create_align($2, $3, @$); }
193 warning_statement:
194 WARNING expression line_tail { $$ = astnode_create_warning($2, @$); }
197 error_statement:
198 ERROR expression line_tail { $$ = astnode_create_error($2, @$); }
201 message_statement:
202 MESSAGE expression line_tail { $$ = astnode_create_message($2, @$); }
205 label_statement:
206 _LABEL_ identifier label_addr_part_opt label_type_part_opt line_tail { $$ = astnode_create_label($2->label, $3, $4, @$); astnode_finalize($2); }
209 label_addr_part_opt:
210 '=' expression { $$ = $2; }
211 | { $$ = NULL; }
214 label_type_part_opt:
215 ':' symbol_type { $$ = $2; }
216 | { $$ = NULL; }
219 while_statement:
220 WHILE expression line_tail statement_list_opt ENDM line_tail { $$ = astnode_create_while($2, $4, @$); }
223 rept_statement:
224 REPT expression line_tail statement_list_opt ENDM line_tail { $$ = astnode_create_rept($2, $4, @$); }
227 proc_statement:
228 PROC identifier line_tail statement_list_opt ENDP line_tail { $$ = astnode_create_proc($2, $4, @$); }
231 struc_decl_statement:
232 STRUC identifier line_tail statement_list_opt ENDS line_tail { $$ = astnode_create_struc_decl($2, $4, @$); }
235 union_decl_statement:
236 UNION identifier_opt line_tail statement_list_opt ENDS line_tail { $$ = astnode_create_union_decl($2, $4, @$); }
239 enum_decl_statement:
240 ENUM identifier line_tail enum_item_list ENDE line_tail { $$ = astnode_create_enum_decl($2, $4, @$); }
243 enum_item_list:
244 enum_item { $$ = $1; }
245 | enum_item_list enum_item { $$ = $1; astnode_add_sibling($$, $2); }
248 enum_item:
249 assign_statement { $$ = $1; }
250 | identifier line_tail { $$ = $1; }
253 record_decl_statement:
254 RECORD identifier record_field_list line_tail { $$ = astnode_create_record_decl($2, $3, @$); }
257 record_field_list:
258 record_field { $$ = $1; }
259 | record_field_list ',' record_field { $$ = $1; astnode_add_sibling($$, $3); }
262 record_field:
263 identifier ':' expression { $$ = astnode_create_bitfield_decl($1, $3, @$); }
266 charmap_statement:
267 CHARMAP file_specifier line_tail { $$ = astnode_create_charmap($2, @$); }
270 dataseg_statement:
271 DATASEG line_tail { $$ = astnode_create_dataseg(0, @$); }
272 | DATASEG ZEROPAGE line_tail { $$ = astnode_create_dataseg(ZEROPAGE_FLAG, @$); }
274 codeseg_statement:
275 CODESEG line_tail { $$ = astnode_create_codeseg(@$); }
278 null_statement:
279 line_tail { $$ = NULL; }
282 label_decl:
283 label { $$ = $1; }
286 line_tail:
287 newline { ; }
288 | ':' { ; }
291 newline:
292 '\n' { ; }
295 instruction_statement:
296 instruction line_tail { $$ = $1; }
299 instruction:
300 MNEMONIC { $$ = astnode_create_instruction($1, IMPLIED_MODE, NULL, @$); }
301 | MNEMONIC 'A' { $$ = astnode_create_instruction($1, ACCUMULATOR_MODE, NULL, @$); }
302 | MNEMONIC '#' expression { $$ = astnode_create_instruction($1, IMMEDIATE_MODE, $3, @$); }
303 | MNEMONIC expression { $$ = astnode_create_instruction($1, ABSOLUTE_MODE, $2, @$); }
304 | MNEMONIC expression ',' 'X' { $$ = astnode_create_instruction($1, ABSOLUTE_X_MODE, $2, @$); }
305 | MNEMONIC expression ',' 'Y' { $$ = astnode_create_instruction($1, ABSOLUTE_Y_MODE, $2, @$); }
306 | MNEMONIC '[' expression ',' 'X' ']' { $$ = astnode_create_instruction($1, PREINDEXED_INDIRECT_MODE, $3, @$); }
307 | MNEMONIC '[' expression ']' ',' 'Y' { $$ = astnode_create_instruction($1, POSTINDEXED_INDIRECT_MODE, $3, @$); }
308 | MNEMONIC '[' expression ']' { $$ = astnode_create_instruction($1, INDIRECT_MODE, $3, @$); }
311 expression:
312 indexed_identifier { $$ = $1; }
313 | SIZEOF sizeof_arg { $$ = astnode_create_sizeof($2, @$); }
314 | scope_access { $$ = $1; }
315 | struc_access { $$ = $1; }
316 | local_id { $$ = $1; }
317 | literal { $$ = $1; }
318 | '$' { $$ = astnode_create_pc(@$); }
319 | arithmetic_expression { $$ = $1; }
320 | comparison_expression { $$ = $1; }
321 | '(' expression ')' { $$ = $2; }
322 | '+' { $$ = astnode_create_forward_branch("+", @$); }
323 | '-' { $$ = astnode_create_backward_branch("-", @$); }
324 | FORWARD_BRANCH { $$ = astnode_create_forward_branch($1, @$); }
325 | BACKWARD_BRANCH { $$ = astnode_create_backward_branch($1, @$); }
326 | MASK scope_access { $$ = astnode_create_mask($2, @$); }
329 indexed_identifier:
330 identifier { $$ = $1; }
331 | identifier '[' expression ']' { $$ = astnode_create_index($1, $3, @$); }
332 | identifier '(' expression ')' { $$ = astnode_create_index($1, $3, @$); }
335 extended_expression:
336 expression { $$ = $1; }
337 | struc_initializer { $$ = $1; }
340 sizeof_arg:
341 identifier { $$ = $1; }
342 | datatype { $$ = $1; }
345 expression_opt:
346 expression { $$ = $1; }
347 | { $$ = NULL; }
350 scope_access:
351 identifier SCOPE_OP identifier { $$ = astnode_create_scope($1, $3, @$); }
354 struc_access:
355 indexed_identifier '.' struc_access { $$ = astnode_create_dot($1, $3, @$); }
356 | indexed_identifier '.' indexed_identifier { $$ = astnode_create_dot($1, $3, @$); }
359 struc_initializer:
360 '{' field_initializer_list_opt '}' { $$ = astnode_create_struc($2, @$); }
363 field_initializer_list_opt:
364 field_initializer_list { $$ = $1; }
365 | { $$ = NULL; }
368 field_initializer_list:
369 field_initializer { $$ = $1; }
370 | field_initializer_list ',' field_initializer { $$ = $1; astnode_add_sibling($$, $3); }
373 field_initializer:
374 extended_expression { $$ = $1; }
375 | { $$ = astnode_create_null(@$); }
378 local_id:
379 LOCAL_ID { $$ = astnode_create_local_id($1, @$); }
382 arithmetic_expression:
383 expression '+' expression { $$ = astnode_create_arithmetic(PLUS_OPERATOR, $1, $3, @$); }
384 | expression '-' expression { $$ = astnode_create_arithmetic(MINUS_OPERATOR, $1, $3, @$); }
385 | expression '*' expression { $$ = astnode_create_arithmetic(MUL_OPERATOR, $1, $3, @$); }
386 | expression '/' expression { $$ = astnode_create_arithmetic(DIV_OPERATOR, $1, $3, @$); }
387 | expression '%' expression { $$ = astnode_create_arithmetic(MOD_OPERATOR, $1, $3, @$); }
388 | expression '&' expression { $$ = astnode_create_arithmetic(AND_OPERATOR, $1, $3, @$); }
389 | expression '|' expression { $$ = astnode_create_arithmetic(OR_OPERATOR, $1, $3, @$); }
390 | expression '^' expression { $$ = astnode_create_arithmetic(XOR_OPERATOR, $1, $3, @$); }
391 | expression SHL_OP expression { $$ = astnode_create_arithmetic(SHL_OPERATOR, $1, $3, @$); }
392 | expression SHR_OP expression { $$ = astnode_create_arithmetic(SHR_OPERATOR, $1, $3, @$); }
393 | '~' expression { $$ = astnode_create_arithmetic(NEG_OPERATOR, $2, NULL, @$); }
394 | '!' expression { $$ = astnode_create_arithmetic(NOT_OPERATOR, $2, NULL, @$); }
395 | '^' identifier { $$ = astnode_create_arithmetic(BANK_OPERATOR, $2, NULL, @$); }
396 | '<' expression %prec LO_OP { $$ = astnode_create_arithmetic(LO_OPERATOR, $2, NULL, @$); }
397 | '>' expression %prec HI_OP { $$ = astnode_create_arithmetic(HI_OPERATOR, $2, NULL, @$); }
398 | '-' expression %prec UMINUS { $$ = astnode_create_arithmetic(UMINUS_OPERATOR, $2, NULL, @$); }
401 comparison_expression:
402 expression EQ_OP expression { $$ = astnode_create_arithmetic(EQ_OPERATOR, $1, $3, @$); }
403 | expression NE_OP expression { $$ = astnode_create_arithmetic(NE_OPERATOR, $1, $3, @$); }
404 | expression '>' expression { $$ = astnode_create_arithmetic(GT_OPERATOR, $1, $3, @$); }
405 | expression '<' expression { $$ = astnode_create_arithmetic(LT_OPERATOR, $1, $3, @$); }
406 | expression GE_OP expression { $$ = astnode_create_arithmetic(GE_OPERATOR, $1, $3, @$); }
407 | expression LE_OP expression { $$ = astnode_create_arithmetic(LE_OPERATOR, $1, $3, @$); }
410 label:
411 LABEL { $$ = astnode_create_label($1, NULL, NULL, @$); }
412 | LOCAL_LABEL { $$ = astnode_create_local_label($1, @$); }
413 | '+' { $$ = astnode_create_forward_branch_decl("+", @$); }
414 | '-' { $$ = astnode_create_backward_branch_decl("-", @$); }
415 | FORWARD_BRANCH { $$ = astnode_create_forward_branch_decl($1, @$); }
416 | BACKWARD_BRANCH { $$ = astnode_create_backward_branch_decl($1, @$); }
419 identifier:
420 IDENTIFIER { $$ = astnode_create_identifier($1, @$); }
423 identifier_opt:
424 identifier { $$ = $1; }
425 | { $$ = astnode_create_null(@$); }
428 literal:
429 INTEGER_LITERAL { $$ = astnode_create_integer($1, @$); }
430 | STRING_LITERAL { $$ = astnode_create_string($1, @$); }
433 if_statement:
434 IF expression line_tail statement_list_opt elif_statement_list_opt else_part_opt ENDIF line_tail { $$ = astnode_create_if($2, $4, $5, $6, @$); }
437 elif_statement_list_opt:
438 elif_statement_list { $$ = $1; }
439 | { $$ = NULL; }
442 elif_statement_list:
443 elif_statement { $$ = $1; }
444 | elif_statement_list elif_statement { $$ = $1; astnode_add_sibling($$, $2); }
447 elif_statement:
448 ELIF expression line_tail statement_list_opt { $$ = astnode_create_case($2, $4, @$); }
451 else_part_opt:
452 ELSE line_tail statement_list_opt { $$ = $3; }
453 | { $$ = NULL; }
456 ifdef_statement:
457 IFDEF identifier line_tail statement_list_opt else_part_opt ENDIF line_tail { $$ = astnode_create_ifdef($2, $4, $5, @$); }
460 ifndef_statement:
461 IFNDEF identifier line_tail statement_list_opt else_part_opt ENDIF line_tail { $$ = astnode_create_ifndef($2, $4, $5, @$); }
464 data_statement:
465 named_data_statement line_tail { $$ = $1; }
466 | unnamed_data_statement line_tail { $$ = $1; }
469 named_data_statement:
470 identifier unnamed_data_statement { $$ = astnode_create_var_decl(0, $1, $2, @$); }
471 | ZEROPAGE identifier unnamed_data_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG, $2, $3, @$); }
472 | PUBLIC identifier unnamed_data_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG, $2, $3, @$); }
473 | ZEROPAGE PUBLIC identifier unnamed_data_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG | PUBLIC_FLAG, $3, $4, @$); }
474 | PUBLIC ZEROPAGE identifier unnamed_data_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG | ZEROPAGE_FLAG, $3, $4, @$); }
477 unnamed_data_statement:
478 datatype expression_list { $$ = astnode_create_data($1, $2, @$); }
479 | datatype { $$ = astnode_create_storage($1, NULL, @$); }
480 | datatype '[' expression ']' { $$ = astnode_create_storage($1, $3, @$); }
483 datatype:
484 BYTE { $$ = astnode_create_datatype(BYTE_DATATYPE, NULL, @$); }
485 | CHAR { $$ = astnode_create_datatype(CHAR_DATATYPE, NULL, @$); }
486 | WORD { $$ = astnode_create_datatype(WORD_DATATYPE, NULL, @$); }
487 | DWORD { $$ = astnode_create_datatype(DWORD_DATATYPE, NULL, @$); }
488 | TAG identifier { $$ = astnode_create_datatype(USER_DATATYPE, $2, @$); }
489 | '.' identifier { $$ = astnode_create_datatype(USER_DATATYPE, $2, @$); }
492 expression_list:
493 extended_expression { $$ = $1; }
494 | expression_list ',' extended_expression { $$ = $1; astnode_add_sibling($$, $3); }
497 incsrc_statement:
498 INCSRC file_specifier line_tail { $$ = astnode_create_incsrc($2, @$); handle_incsrc($$); }
501 incbin_statement:
502 INCBIN file_specifier line_tail { $$ = astnode_create_incbin($2, @$); handle_incbin($$); }
505 file_specifier:
506 STRING_LITERAL { $$ = astnode_create_string($1, @$); }
507 | '<' { $$ = astnode_create_file_path(scan_include('>'), @$); }
510 macro_decl_statement:
511 MACRO identifier param_list_opt line_tail statement_list_opt ENDM line_tail { $$ = astnode_create_macro_decl($2, $3, $5, @$); }
514 param_list_opt:
515 identifier_list { $$ = $1; }
516 | { $$ = NULL; }
519 macro_statement:
520 identifier arg_list_opt line_tail { $$ = astnode_create_macro($1, $2, @$); }
523 arg_list_opt:
524 expression_list { $$ = $1; }
525 | { $$ = NULL; }
528 identifier_list:
529 identifier { $$ = $1; }
530 | identifier_list ',' identifier { $$ = $1; astnode_add_sibling($$, $3); }
533 equ_statement:
534 identifier EQU extended_expression line_tail { $$ = astnode_create_equ($1, $3, @$); }
537 assign_statement:
538 identifier '=' extended_expression line_tail { $$ = astnode_create_assign($1, $3, @$); }
541 define_statement:
542 DEFINE identifier line_tail { $$ = astnode_create_equ($2, astnode_create_integer(0, @$), @$); }
543 | DEFINE identifier extended_expression line_tail { $$ = astnode_create_equ($2, $3, @$); }
546 public_statement:
547 PUBLIC identifier_list line_tail { $$ = astnode_create_public($2, @$); }
550 extrn_statement:
551 EXTRN identifier_list ':' symbol_type from_part_opt line_tail { $$ = astnode_create_extrn($2, $4, $5, @$); }
554 from_part_opt:
555 '@' identifier { $$ = $2; }
556 | { $$ = NULL; }
559 symbol_type:
560 datatype { $$ = $1; }
561 | identifier { $$ = astnode_create_datatype(USER_DATATYPE, $1, @$); }
562 | PROC { $$ = astnode_create_integer(PROC_SYMBOL, @$); }
563 | _LABEL_ { $$ = astnode_create_integer(LABEL_SYMBOL, @$); }
566 storage_statement:
567 named_storage_statement { $$ = $1; }
568 | unnamed_storage_statement { $$ = $1; }
571 named_storage_statement:
572 identifier unnamed_storage_statement { $$ = astnode_create_var_decl(0, $1, $2, @$); }
573 | ZEROPAGE identifier unnamed_storage_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG, $2, $3, @$); }
574 | PUBLIC identifier unnamed_storage_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG, $2, $3, @$); }
575 | ZEROPAGE PUBLIC identifier unnamed_storage_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG | PUBLIC_FLAG, $3, $4, @$); }
576 | PUBLIC ZEROPAGE identifier unnamed_storage_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG | ZEROPAGE_FLAG, $3, $4, @$); }
579 unnamed_storage_statement:
580 storage expression_opt line_tail { $$ = astnode_create_storage($1, $2, @$); }
583 storage:
584 DSB { $$ = astnode_create_datatype(BYTE_DATATYPE, NULL, @$); }
585 | DSW { $$ = astnode_create_datatype(WORD_DATATYPE, NULL, @$); }
586 | DSD { $$ = astnode_create_datatype(DWORD_DATATYPE, NULL, @$); }
590 * Takes care of switching to a new scanner input stream when a "incsrc" statement
591 * has been encountered.
592 * The current stream is pushed on a stack, and will be popped when EOF is reached
593 * in the new stream.
594 * @param n A node of type INCSRC_NODE
596 void handle_incsrc(astnode *n)
598 char errs[512];
599 /* Get the node which describes the file to include */
600 astnode *file = astnode_get_child(n, 0);
601 int quoted_form = (astnode_get_type(file) == STRING_NODE) ? 1 : 0;
602 switch (yypushandrestart(file->string, quoted_form)) {
603 case 0:
604 /* Success */
605 break;
606 case 1:
607 /* Failed to open file */
608 sprintf(errs, "could not open '%s' for reading", file->string);
609 yyerror(errs);
610 break;
611 case 2:
612 /* Stack overflow */
613 yyerror("Maximum include nesting level reached");
614 break;
618 // TODO: This shouldn't be done here but rather in astproc module.
620 FILE *open_included_file(const char *, int, char **);
623 * Takes care of including the binary contents of the file specified by a parsed
624 * "incbin" statement.
625 * Calls yyerror() if the file can't be included for some reason.
626 * @param n A node of type INCBIN_NODE
628 void handle_incbin(astnode *n)
630 FILE *fp;
631 unsigned char *data;
632 int size;
633 char errs[512];
634 /* Get the node which describes the file to include */
635 astnode *file = astnode_get_child(n, 0);
636 const char *filename = file->string;
637 int quoted_form = (astnode_get_type(file) == STRING_NODE) ? 1 : 0;
638 /* Try to open it */
639 fp = open_included_file(filename, quoted_form, NULL);
640 if (fp) {
641 /* Get filesize */
642 fseek(fp, 0, SEEK_END);
643 size = ftell(fp);
644 rewind(fp);
645 if (size > 0) {
646 /* Allocate buffer to hold file contents */
647 data = (unsigned char *)malloc(size);
648 /* Read file contents into buffer */
649 fread(data, 1, size, fp);
650 /* Insert binary node */
651 astnode_add_sibling(n, astnode_create_binary(data, size, n->loc) );
653 /* Close file */
654 fclose(fp);
655 } else {
656 /* Couldn't open file */
657 sprintf(errs, "could not open '%s' for reading", file->string);
658 yyerror(errs);