make include <foo.h> work, make nested includes work
[xorcyst.git] / parser.y
blob1fd09775250f44cc56ef627443bcd3d0fd3cd01a
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 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 labelable_statement:
140 label_decl statement { $$ = $1; astnode_add_sibling($$, $2); }
141 | statement { $$ = $1; }
144 statement:
145 if_statement { $$ = $1; }
146 | ifdef_statement { $$ = $1; }
147 | ifndef_statement { $$ = $1; }
148 | macro_decl_statement { $$ = $1; }
149 | macro_statement { $$ = $1; }
150 | incsrc_statement { $$ = $1; }
151 | incbin_statement { $$ = $1; }
152 | equ_statement { $$ = $1; }
153 | assign_statement { $$ = $1; }
154 | public_statement { $$ = $1; }
155 | extrn_statement { $$ = $1; }
156 | instruction_statement { $$ = $1; }
157 | data_statement { $$ = $1; }
158 | storage_statement { $$ = $1; }
159 | dataseg_statement { $$ = $1; }
160 | codeseg_statement { $$ = $1; }
161 | charmap_statement { $$ = $1; }
162 | struc_decl_statement { $$ = $1; }
163 | union_decl_statement { $$ = $1; }
164 | enum_decl_statement { $$ = $1; }
165 | record_decl_statement { $$ = $1; }
166 | proc_statement { $$ = $1; }
167 | rept_statement { $$ = $1; }
168 | while_statement { $$ = $1; }
169 | label_statement { $$ = $1; }
170 | message_statement { $$ = $1; }
171 | warning_statement { $$ = $1; }
172 | error_statement { $$ = $1; }
173 | define_statement { $$ = $1; }
174 | align_statement { $$ = $1; }
175 | org_statement { $$ = $1; }
176 | null_statement { $$ = $1; }
177 | error line_tail { $$ = NULL; }
180 org_statement:
181 ORG expression line_tail { $$ = astnode_create_org($2, @$); }
184 align_statement:
185 ALIGN identifier_list expression line_tail { $$ = astnode_create_align($2, $3, @$); }
188 warning_statement:
189 WARNING expression line_tail { $$ = astnode_create_warning($2, @$); }
192 error_statement:
193 ERROR expression line_tail { $$ = astnode_create_error($2, @$); }
196 message_statement:
197 MESSAGE expression line_tail { $$ = astnode_create_message($2, @$); }
200 label_statement:
201 _LABEL_ identifier label_addr_part_opt label_type_part_opt line_tail { $$ = astnode_create_label($2->label, $3, $4, @$); }
204 label_addr_part_opt:
205 '=' expression { $$ = $2; }
206 | { $$ = NULL; }
209 label_type_part_opt:
210 ':' symbol_type { $$ = $2; }
211 | { $$ = NULL; }
214 while_statement:
215 WHILE expression line_tail statement_list ENDM line_tail { $$ = astnode_create_while($2, $4, @$); }
218 rept_statement:
219 REPT expression line_tail statement_list ENDM line_tail { $$ = astnode_create_rept($2, $4, @$); }
222 proc_statement:
223 PROC identifier line_tail statement_list ENDP line_tail { $$ = astnode_create_proc($2, $4, @$); }
226 struc_decl_statement:
227 STRUC identifier line_tail statement_list ENDS line_tail { $$ = astnode_create_struc_decl($2, $4, @$); }
230 union_decl_statement:
231 UNION identifier_opt line_tail statement_list ENDS line_tail { $$ = astnode_create_union_decl($2, $4, @$); }
234 enum_decl_statement:
235 ENUM identifier line_tail enum_item_list ENDE line_tail { $$ = astnode_create_enum_decl($2, $4, @$); }
238 enum_item_list:
239 enum_item { $$ = $1; }
240 | enum_item_list enum_item { $$ = $1; astnode_add_sibling($$, $2); }
243 enum_item:
244 assign_statement { $$ = $1; }
245 | identifier line_tail { $$ = $1; }
248 record_decl_statement:
249 RECORD identifier record_field_list line_tail { $$ = astnode_create_record_decl($2, $3, @$); }
252 record_field_list:
253 record_field { $$ = $1; }
254 | record_field_list ',' record_field { $$ = $1; astnode_add_sibling($$, $3); }
257 record_field:
258 identifier ':' expression { $$ = astnode_create_bitfield_decl($1, $3, @$); }
261 charmap_statement:
262 CHARMAP file_specifier line_tail { $$ = astnode_create_charmap($2, @$); }
265 dataseg_statement:
266 DATASEG line_tail { $$ = astnode_create_dataseg(0, @$); }
267 | DATASEG ZEROPAGE line_tail { $$ = astnode_create_dataseg(ZEROPAGE_FLAG, @$); }
269 codeseg_statement:
270 CODESEG line_tail { $$ = astnode_create_codeseg(@$); }
273 null_statement:
274 line_tail { $$ = NULL; }
277 label_decl:
278 label { $$ = $1; }
281 line_tail:
282 newline { ; }
283 | ':' { ; }
286 newline:
287 '\n' { ; }
290 instruction_statement:
291 instruction line_tail { $$ = $1; }
294 instruction:
295 MNEMONIC { $$ = astnode_create_instruction($1, IMPLIED_MODE, NULL, @$); }
296 | MNEMONIC 'A' { $$ = astnode_create_instruction($1, ACCUMULATOR_MODE, NULL, @$); }
297 | MNEMONIC '#' expression { $$ = astnode_create_instruction($1, IMMEDIATE_MODE, $3, @$); }
298 | MNEMONIC expression { $$ = astnode_create_instruction($1, ABSOLUTE_MODE, $2, @$); }
299 | MNEMONIC expression ',' 'X' { $$ = astnode_create_instruction($1, ABSOLUTE_X_MODE, $2, @$); }
300 | MNEMONIC expression ',' 'Y' { $$ = astnode_create_instruction($1, ABSOLUTE_Y_MODE, $2, @$); }
301 | MNEMONIC '[' expression ',' 'X' ']' { $$ = astnode_create_instruction($1, PREINDEXED_INDIRECT_MODE, $3, @$); }
302 | MNEMONIC '[' expression ']' ',' 'Y' { $$ = astnode_create_instruction($1, POSTINDEXED_INDIRECT_MODE, $3, @$); }
303 | MNEMONIC '[' expression ']' { $$ = astnode_create_instruction($1, INDIRECT_MODE, $3, @$); }
306 expression:
307 indexed_identifier { $$ = $1; }
308 | SIZEOF sizeof_arg { $$ = astnode_create_sizeof($2, @$); }
309 | scope_access { $$ = $1; }
310 | struc_access { $$ = $1; }
311 | local_id { $$ = $1; }
312 | literal { $$ = $1; }
313 | '$' { $$ = astnode_create_pc(@$); }
314 | arithmetic_expression { $$ = $1; }
315 | comparison_expression { $$ = $1; }
316 | '(' expression ')' { $$ = $2; }
317 | '+' { $$ = astnode_create_forward_branch("+", @$); }
318 | '-' { $$ = astnode_create_backward_branch("-", @$); }
319 | FORWARD_BRANCH { $$ = astnode_create_forward_branch($1, @$); }
320 | BACKWARD_BRANCH { $$ = astnode_create_backward_branch($1, @$); }
321 | MASK scope_access { $$ = astnode_create_mask($2, @$); }
324 indexed_identifier:
325 identifier { $$ = $1; }
326 | identifier '[' expression ']' { $$ = astnode_create_index($1, $3, @$); }
327 | identifier '(' expression ')' { $$ = astnode_create_index($1, $3, @$); }
330 extended_expression:
331 expression { $$ = $1; }
332 | struc_initializer { $$ = $1; }
335 sizeof_arg:
336 identifier { $$ = $1; }
337 | datatype { $$ = $1; }
340 expression_opt:
341 expression { $$ = $1; }
342 | { $$ = NULL; }
345 scope_access:
346 identifier SCOPE_OP identifier { $$ = astnode_create_scope($1, $3, @$); }
349 struc_access:
350 indexed_identifier '.' struc_access { $$ = astnode_create_dot($1, $3, @$); }
351 | indexed_identifier '.' indexed_identifier { $$ = astnode_create_dot($1, $3, @$); }
354 struc_initializer:
355 '{' field_initializer_list_opt '}' { $$ = astnode_create_struc($2, @$); }
358 field_initializer_list_opt:
359 field_initializer_list { $$ = $1; }
360 | { $$ = NULL; }
363 field_initializer_list:
364 field_initializer { $$ = $1; }
365 | field_initializer_list ',' field_initializer { $$ = $1; astnode_add_sibling($$, $3); }
368 field_initializer:
369 extended_expression { $$ = $1; }
370 | { $$ = astnode_create_null(@$); }
373 local_id:
374 LOCAL_ID { $$ = astnode_create_local_id($1, @$); }
377 arithmetic_expression:
378 expression '+' expression { $$ = astnode_create_arithmetic(PLUS_OPERATOR, $1, $3, @$); }
379 | expression '-' expression { $$ = astnode_create_arithmetic(MINUS_OPERATOR, $1, $3, @$); }
380 | expression '*' expression { $$ = astnode_create_arithmetic(MUL_OPERATOR, $1, $3, @$); }
381 | expression '/' expression { $$ = astnode_create_arithmetic(DIV_OPERATOR, $1, $3, @$); }
382 | expression '%' expression { $$ = astnode_create_arithmetic(MOD_OPERATOR, $1, $3, @$); }
383 | expression '&' expression { $$ = astnode_create_arithmetic(AND_OPERATOR, $1, $3, @$); }
384 | expression '|' expression { $$ = astnode_create_arithmetic(OR_OPERATOR, $1, $3, @$); }
385 | expression '^' expression { $$ = astnode_create_arithmetic(XOR_OPERATOR, $1, $3, @$); }
386 | expression SHL_OP expression { $$ = astnode_create_arithmetic(SHL_OPERATOR, $1, $3, @$); }
387 | expression SHR_OP expression { $$ = astnode_create_arithmetic(SHR_OPERATOR, $1, $3, @$); }
388 | '~' expression { $$ = astnode_create_arithmetic(NEG_OPERATOR, $2, NULL, @$); }
389 | '!' expression { $$ = astnode_create_arithmetic(NOT_OPERATOR, $2, NULL, @$); }
390 | '^' identifier { $$ = astnode_create_arithmetic(BANK_OPERATOR, $2, NULL, @$); }
391 | '<' expression %prec LO_OP { $$ = astnode_create_arithmetic(LO_OPERATOR, $2, NULL, @$); }
392 | '>' expression %prec HI_OP { $$ = astnode_create_arithmetic(HI_OPERATOR, $2, NULL, @$); }
393 | '-' expression %prec UMINUS { $$ = astnode_create_arithmetic(UMINUS_OPERATOR, $2, NULL, @$); }
396 comparison_expression:
397 expression EQ_OP expression { $$ = astnode_create_arithmetic(EQ_OPERATOR, $1, $3, @$); }
398 | expression NE_OP expression { $$ = astnode_create_arithmetic(NE_OPERATOR, $1, $3, @$); }
399 | expression '>' expression { $$ = astnode_create_arithmetic(GT_OPERATOR, $1, $3, @$); }
400 | expression '<' expression { $$ = astnode_create_arithmetic(LT_OPERATOR, $1, $3, @$); }
401 | expression GE_OP expression { $$ = astnode_create_arithmetic(GE_OPERATOR, $1, $3, @$); }
402 | expression LE_OP expression { $$ = astnode_create_arithmetic(LE_OPERATOR, $1, $3, @$); }
405 label:
406 LABEL { $$ = astnode_create_label($1, NULL, NULL, @$); }
407 | LOCAL_LABEL { $$ = astnode_create_local_label($1, @$); }
408 | '+' { $$ = astnode_create_forward_branch_decl("+", @$); }
409 | '-' { $$ = astnode_create_backward_branch_decl("-", @$); }
410 | FORWARD_BRANCH { $$ = astnode_create_forward_branch_decl($1, @$); }
411 | BACKWARD_BRANCH { $$ = astnode_create_backward_branch_decl($1, @$); }
414 identifier:
415 IDENTIFIER { $$ = astnode_create_identifier($1, @$); }
418 identifier_opt:
419 identifier { $$ = $1; }
420 | { $$ = astnode_create_null(@$); }
423 literal:
424 INTEGER_LITERAL { $$ = astnode_create_integer($1, @$); }
425 | STRING_LITERAL { $$ = astnode_create_string($1, @$); }
428 if_statement:
429 IF expression line_tail statement_list elif_statement_list_opt else_part_opt ENDIF line_tail { $$ = astnode_create_if($2, $4, $5, $6, @$); }
432 elif_statement_list_opt:
433 elif_statement_list { $$ = $1; }
434 | { $$ = NULL; }
437 elif_statement_list:
438 elif_statement { $$ = $1; }
439 | elif_statement_list elif_statement { $$ = $1; astnode_add_sibling($$, $2); }
442 elif_statement:
443 ELIF expression line_tail statement_list { $$ = astnode_create_case($2, $4, @$); }
446 else_part_opt:
447 ELSE line_tail statement_list { $$ = $3; }
448 | { $$ = NULL; }
451 ifdef_statement:
452 IFDEF identifier line_tail statement_list else_part_opt ENDIF line_tail { $$ = astnode_create_ifdef($2, $4, $5, @$); }
455 ifndef_statement:
456 IFNDEF identifier line_tail statement_list else_part_opt ENDIF line_tail { $$ = astnode_create_ifndef($2, $4, $5, @$); }
459 data_statement:
460 named_data_statement line_tail { $$ = $1; }
461 | unnamed_data_statement line_tail { $$ = $1; }
464 named_data_statement:
465 identifier unnamed_data_statement { $$ = astnode_create_var_decl(0, $1, $2, @$); }
466 | ZEROPAGE identifier unnamed_data_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG, $2, $3, @$); }
467 | PUBLIC identifier unnamed_data_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG, $2, $3, @$); }
468 | ZEROPAGE PUBLIC identifier unnamed_data_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG | PUBLIC_FLAG, $3, $4, @$); }
469 | PUBLIC ZEROPAGE identifier unnamed_data_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG | ZEROPAGE_FLAG, $3, $4, @$); }
472 unnamed_data_statement:
473 datatype expression_list { $$ = astnode_create_data($1, $2, @$); }
474 | datatype { $$ = astnode_create_storage($1, NULL, @$); }
475 | datatype '[' expression ']' { $$ = astnode_create_storage($1, $3, @$); }
478 datatype:
479 BYTE { $$ = astnode_create_datatype(BYTE_DATATYPE, NULL, @$); }
480 | CHAR { $$ = astnode_create_datatype(CHAR_DATATYPE, NULL, @$); }
481 | WORD { $$ = astnode_create_datatype(WORD_DATATYPE, NULL, @$); }
482 | DWORD { $$ = astnode_create_datatype(DWORD_DATATYPE, NULL, @$); }
483 | TAG identifier { $$ = astnode_create_datatype(USER_DATATYPE, $2, @$); }
484 | '.' identifier { $$ = astnode_create_datatype(USER_DATATYPE, $2, @$); }
487 expression_list:
488 extended_expression { $$ = $1; }
489 | expression_list ',' extended_expression { $$ = $1; astnode_add_sibling($$, $3); }
492 incsrc_statement:
493 INCSRC file_specifier line_tail { $$ = astnode_create_incsrc($2, @$); handle_incsrc($$); }
496 incbin_statement:
497 INCBIN file_specifier line_tail { $$ = astnode_create_incbin($2, @$); handle_incbin($$); }
500 file_specifier:
501 STRING_LITERAL { $$ = astnode_create_string($1, @$); }
502 | '<' { $$ = astnode_create_file_path(scan_include('>'), @$); }
505 macro_decl_statement:
506 MACRO identifier param_list_opt line_tail statement_list ENDM line_tail { $$ = astnode_create_macro_decl($2, $3, $5, @$); }
509 param_list_opt:
510 identifier_list { $$ = $1; }
511 | { $$ = NULL; }
514 macro_statement:
515 identifier arg_list_opt line_tail { $$ = astnode_create_macro($1, $2, @$); }
518 arg_list_opt:
519 expression_list { $$ = $1; }
520 | { $$ = NULL; }
523 identifier_list:
524 identifier { $$ = $1; }
525 | identifier_list ',' identifier { $$ = $1; astnode_add_sibling($$, $3); }
528 equ_statement:
529 identifier EQU extended_expression line_tail { $$ = astnode_create_equ($1, $3, @$); }
532 assign_statement:
533 identifier '=' extended_expression line_tail { $$ = astnode_create_assign($1, $3, @$); }
536 define_statement:
537 DEFINE identifier line_tail { $$ = astnode_create_equ($2, astnode_create_integer(0, @$), @$); }
538 | DEFINE identifier extended_expression line_tail { $$ = astnode_create_equ($2, $3, @$); }
541 public_statement:
542 PUBLIC identifier_list line_tail { $$ = astnode_create_public($2, @$); }
545 extrn_statement:
546 EXTRN identifier_list ':' symbol_type from_part_opt line_tail { $$ = astnode_create_extrn($2, $4, $5, @$); }
549 from_part_opt:
550 '@' identifier { $$ = $2; }
551 | { $$ = NULL; }
554 symbol_type:
555 datatype { $$ = $1; }
556 | identifier { $$ = astnode_create_datatype(USER_DATATYPE, $1, @$); }
557 | PROC { $$ = astnode_create_integer(PROC_SYMBOL, @$); }
558 | _LABEL_ { $$ = astnode_create_integer(LABEL_SYMBOL, @$); }
561 storage_statement:
562 named_storage_statement { $$ = $1; }
563 | unnamed_storage_statement { $$ = $1; }
566 named_storage_statement:
567 identifier unnamed_storage_statement { $$ = astnode_create_var_decl(0, $1, $2, @$); }
568 | ZEROPAGE identifier unnamed_storage_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG, $2, $3, @$); }
569 | PUBLIC identifier unnamed_storage_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG, $2, $3, @$); }
570 | ZEROPAGE PUBLIC identifier unnamed_storage_statement { $$ = astnode_create_var_decl(ZEROPAGE_FLAG | PUBLIC_FLAG, $3, $4, @$); }
571 | PUBLIC ZEROPAGE identifier unnamed_storage_statement { $$ = astnode_create_var_decl(PUBLIC_FLAG | ZEROPAGE_FLAG, $3, $4, @$); }
574 unnamed_storage_statement:
575 storage expression_opt line_tail { $$ = astnode_create_storage($1, $2, @$); }
578 storage:
579 DSB { $$ = astnode_create_datatype(BYTE_DATATYPE, NULL, @$); }
580 | DSW { $$ = astnode_create_datatype(WORD_DATATYPE, NULL, @$); }
581 | DSD { $$ = astnode_create_datatype(DWORD_DATATYPE, NULL, @$); }
585 * Takes care of switching to a new scanner input stream when a "incsrc" statement
586 * has been encountered.
587 * The current stream is pushed on a stack, and will be popped when EOF is reached
588 * in the new stream.
589 * @param n A node of type INCSRC_NODE
591 void handle_incsrc(astnode *n)
593 char errs[512];
594 /* Get the node which describes the file to include */
595 astnode *file = astnode_get_child(n, 0);
596 int quoted_form = (astnode_get_type(file) == STRING_NODE) ? 1 : 0;
597 switch (yypushandrestart(file->string, quoted_form)) {
598 case 0:
599 /* Success */
600 break;
601 case 1:
602 /* Failed to open file */
603 sprintf(errs, "could not open '%s' for reading", file->string);
604 yyerror(errs);
605 break;
606 case 2:
607 /* Stack overflow */
608 yyerror("Maximum include nesting level reached");
609 break;
613 // TODO: This shouldn't be done here but rather in astproc module.
615 FILE *open_included_file(const char *, int, char **);
618 * Takes care of including the binary contents of the file specified by a parsed
619 * "incbin" statement.
620 * Calls yyerror() if the file can't be included for some reason.
621 * @param n A node of type INCBIN_NODE
623 void handle_incbin(astnode *n)
625 FILE *fp;
626 unsigned char *data;
627 int size;
628 char errs[512];
629 /* Get the node which describes the file to include */
630 astnode *file = astnode_get_child(n, 0);
631 const char *filename = file->string;
632 int quoted_form = (astnode_get_type(file) == STRING_NODE) ? 1 : 0;
633 /* Try to open it */
634 fp = open_included_file(filename, quoted_form, NULL);
635 if (fp) {
636 /* Get filesize */
637 fseek(fp, 0, SEEK_END);
638 size = ftell(fp);
639 rewind(fp);
640 if (size > 0) {
641 /* Allocate buffer to hold file contents */
642 data = (unsigned char *)malloc(size);
643 /* Read file contents into buffer */
644 fread(data, 1, size, fp);
645 /* Insert binary node */
646 astnode_add_sibling(n, astnode_create_binary(data, size, n->loc) );
648 /* Close file */
649 fclose(fp);
650 } else {
651 /* Couldn't open file */
652 sprintf(errs, "could not open '%s' for reading", file->string);
653 yyerror(errs);