fix memleak in macro handling
[xorcyst.git] / astnode.c
blob8c440490771969130136ebbb177cda3be54a4874
1 /*
2 * $Id: astnode.c,v 1.15 2007/08/12 18:58:12 khansen Exp $
3 * $Log: astnode.c,v $
4 * Revision 1.15 2007/08/12 18:58:12 khansen
5 * ability to generate pure 6502 binary (--pure-binary switch)
7 * Revision 1.14 2007/08/10 20:21:02 khansen
8 * *** empty log message ***
10 * Revision 1.13 2007/08/09 22:05:49 khansen
11 * general-purpose flags
13 * Revision 1.12 2007/08/07 21:12:16 khansen
14 * const
16 * Revision 1.11 2007/07/22 13:33:26 khansen
17 * convert tabs to whitespaces
19 * Revision 1.10 2004/12/29 21:44:04 kenth
20 * xorcyst 1.4.2
21 * added create_index()
23 * Revision 1.9 2004/12/19 19:58:23 kenth
24 * xorcyst 1.4.0
26 * Revision 1.8 2004/12/19 09:53:46 kenth
27 * added create_align()
29 * Revision 1.7 2004/12/18 16:56:12 kenth
30 * create_extrn() takes unit id
32 * Revision 1.6 2004/12/16 13:19:07 kenth
33 * astnode_create_label() takes datatype argument
35 * Revision 1.5 2004/12/14 01:48:57 kenth
36 * xorcyst 1.3.0
38 * Revision 1.4 2004/12/11 02:01:10 kenth
39 * added forward/backward branching
41 * Revision 1.3 2004/12/09 11:17:59 kenth
42 * added: warning, error nodes
44 * Revision 1.2 2004/12/06 04:52:05 kenth
45 * Major updates (xorcyst 1.1.0)
47 * Revision 1.1 2004/06/30 07:55:28 kenth
48 * Initial revision
52 /**
53 * (C) 2004 Kent Hansen
55 * The XORcyst is free software; you can redistribute it and/or modify
56 * it under the terms of the GNU General Public License as published by
57 * the Free Software Foundation; either version 2 of the License, or
58 * (at your option) any later version.
60 * The XORcyst is distributed in the hope that it will be useful,
61 * but WITHOUT ANY WARRANTY; without even the implied warranty of
62 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63 * GNU General Public License for more details.
65 * You should have received a copy of the GNU General Public License
66 * along with The XORcyst; if not, write to the Free Software
67 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
70 /**
71 * The result of parsing an assembly file is an Abstract Syntax Tree (AST).
72 * Such a tree consists of AST nodes.
73 * This file contains the code to manipulate such nodes.
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <stdarg.h>
79 #include <string.h>
80 #include <assert.h>
81 #include "astnode.h"
83 #define SAFE_FREE(a) if (a) { free(a); a = NULL; }
85 /*---------------------------------------------------------------------------*/
86 /* Functions to convert and print astnodes as string.
87 These are useful when debugging syntax trees.
90 /**
91 * Gets string representation of an addressing mode.
92 * @param am Addressing mode (enumerated type)
93 * @return String representation of am
95 const char *addressing_mode_to_string(addressing_mode am)
97 switch (am) {
98 case IMPLIED_MODE: return "IMPLIED_MODE";
99 case ACCUMULATOR_MODE: return "ACCUMULATOR_MODE";
100 case IMMEDIATE_MODE: return "IMMEDIATE_MODE";
101 case ZEROPAGE_MODE: return "ZEROPAGE_MODE";
102 case ZEROPAGE_X_MODE: return "ZEROPAGE_X_MODE";
103 case ZEROPAGE_Y_MODE: return "ZEROPAGE_Y_MODE";
104 case ABSOLUTE_MODE: return "ABSOLUTE_MODE";
105 case ABSOLUTE_X_MODE: return "ABSOLUTE_X_MODE";
106 case ABSOLUTE_Y_MODE: return "ABSOLUTE_Y_MODE";
107 case PREINDEXED_INDIRECT_MODE: return "PREINDEXED_INDIRECT_MODE";
108 case POSTINDEXED_INDIRECT_MODE: return "POSTINDEXED_INDIRECT_MODE";
109 case INDIRECT_MODE: return "INDIRECT_MODE";
110 case RELATIVE_MODE: return "RELATIVE_MODE";
111 case INVALID_MODE: assert(0); break;
113 return "addressing_mode_to_string: invalid addressing mode";
117 * Gets string representation of an instruction mnemonic.
118 * @param im Instruction mnemonic (enumerated type)
119 * @return String representation of im
121 const char *instr_mnemonic_to_string(instr_mnemonic im)
123 switch (im) {
124 case ADC_MNEMONIC: return "ADC_MNEMONIC";
125 case AND_MNEMONIC: return "AND_MNEMONIC";
126 case ASL_MNEMONIC: return "ASL_MNEMONIC";
127 case BCC_MNEMONIC: return "BCC_MNEMONIC";
128 case BCS_MNEMONIC: return "BCS_MNEMONIC";
129 case BEQ_MNEMONIC: return "BEQ_MNEMONIC";
130 case BIT_MNEMONIC: return "BIT_MNEMONIC";
131 case BMI_MNEMONIC: return "BMI_MNEMONIC";
132 case BNE_MNEMONIC: return "BNE_MNEMONIC";
133 case BPL_MNEMONIC: return "BPL_MNEMONIC";
134 case BRK_MNEMONIC: return "BRK_MNEMONIC";
135 case BVC_MNEMONIC: return "BVC_MNEMONIC";
136 case BVS_MNEMONIC: return "BVS_MNEMONIC";
137 case CLC_MNEMONIC: return "CLC_MNEMONIC";
138 case CLD_MNEMONIC: return "CLD_MNEMONIC";
139 case CLI_MNEMONIC: return "CLI_MNEMONIC";
140 case CLV_MNEMONIC: return "CLV_MNEMONIC";
141 case CMP_MNEMONIC: return "CMP_MNEMONIC";
142 case CPX_MNEMONIC: return "CPX_MNEMONIC";
143 case CPY_MNEMONIC: return "CPY_MNEMONIC";
144 case DEC_MNEMONIC: return "DEC_MNEMONIC";
145 case DEX_MNEMONIC: return "DEX_MNEMONIC";
146 case DEY_MNEMONIC: return "DEY_MNEMONIC";
147 case EOR_MNEMONIC: return "EOR_MNEMONIC";
148 case INC_MNEMONIC: return "INC_MNEMONIC";
149 case INX_MNEMONIC: return "INX_MNEMONIC";
150 case INY_MNEMONIC: return "INY_MNEMONIC";
151 case JMP_MNEMONIC: return "JMP_MNEMONIC";
152 case JSR_MNEMONIC: return "JSR_MNEMONIC";
153 case LDA_MNEMONIC: return "LDA_MNEMONIC";
154 case LDX_MNEMONIC: return "LDX_MNEMONIC";
155 case LDY_MNEMONIC: return "LDY_MNEMONIC";
156 case LSR_MNEMONIC: return "LSR_MNEMONIC";
157 case NOP_MNEMONIC: return "NOP_MNEMONIC";
158 case ORA_MNEMONIC: return "ORA_MNEMONIC";
159 case PHA_MNEMONIC: return "PHA_MNEMONIC";
160 case PHP_MNEMONIC: return "PHP_MNEMONIC";
161 case PLA_MNEMONIC: return "PLA_MNEMONIC";
162 case PLP_MNEMONIC: return "PLP_MNEMONIC";
163 case ROL_MNEMONIC: return "ROL_MNEMONIC";
164 case ROR_MNEMONIC: return "ROR_MNEMONIC";
165 case RTI_MNEMONIC: return "RTI_MNEMONIC";
166 case RTS_MNEMONIC: return "RTS_MNEMONIC";
167 case SBC_MNEMONIC: return "SBC_MNEMONIC";
168 case SEC_MNEMONIC: return "SEC_MNEMONIC";
169 case SED_MNEMONIC: return "SED_MNEMONIC";
170 case SEI_MNEMONIC: return "SEI_MNEMONIC";
171 case STA_MNEMONIC: return "STA_MNEMONIC";
172 case STX_MNEMONIC: return "STX_MNEMONIC";
173 case STY_MNEMONIC: return "STY_MNEMONIC";
174 case TAX_MNEMONIC: return "TAX_MNEMONIC";
175 case TAY_MNEMONIC: return "TAY_MNEMONIC";
176 case TSX_MNEMONIC: return "TSX_MNEMONIC";
177 case TXA_MNEMONIC: return "TXA_MNEMONIC";
178 case TXS_MNEMONIC: return "TXS_MNEMONIC";
179 case TYA_MNEMONIC: return "TYA_MNEMONIC";
181 return "instr_mnemonic_to_string: invalid mnemonic";
185 * Gets string representation of an astnode type.
186 * @param at Node type
187 * @return String representation of at
189 const char *astnode_type_to_string(astnode_type at) {
190 switch (at) {
191 case NULL_NODE: return "NULL_NODE";
192 case INTEGER_NODE: return "INTEGER_NODE";
193 case STRING_NODE: return "STRING_NODE";
194 case IDENTIFIER_NODE: return "IDENTIFIER_NODE";
195 case DATA_NODE: return "DATA_NODE";
196 case STORAGE_NODE: return "STORAGE_NODE";
197 case MACRO_DECL_NODE: return "MACRO_DECL_NODE";
198 case MACRO_NODE: return "MACRO_NODE";
199 case ARITHMETIC_NODE: return "ARITHMETIC_NODE";
200 case IF_NODE: return "IF_NODE";
201 case CASE_NODE: return "CASE_NODE";
202 case DEFAULT_NODE: return "DEFAULT_NODE";
203 case IFDEF_NODE: return "IFDEF_NODE";
204 case IFNDEF_NODE: return "IFNDEF_NODE";
205 case INCSRC_NODE: return "INCSRC_NODE";
206 case INCBIN_NODE: return "INCBIN_NODE";
207 case EQU_NODE: return "EQU_NODE";
208 case ASSIGN_NODE: return "ASSIGN_NODE";
209 case ALIGN_NODE: return "ALIGN_NODE";
210 case INSTRUCTION_NODE: return "INSTRUCTION_NODE";
211 case FILE_PATH_NODE: return "FILE_PATH_NODE";
212 case CURRENT_PC_NODE: return "CURRENT_PC_NODE";
213 case LIST_NODE: return "LIST_NODE";
214 case LABEL_NODE: return "LABEL_NODE";
215 case LOCAL_LABEL_NODE: return "LOCAL_LABEL_NODE";
216 case LOCAL_ID_NODE: return "LOCAL_ID_NODE";
217 case BINARY_NODE: return "BINARY_NODE";
218 case PUBLIC_NODE: return "PUBLIC_NODE";
219 case EXTRN_NODE: return "EXTRN_NODE";
220 case DATASEG_NODE: return "DATASEG_NODE";
221 case CODESEG_NODE: return "CODESEG_NODE";
222 case CHARMAP_NODE: return "CHARMAP_NODE";
223 case STRUC_NODE: return "STRUC_NODE";
224 case STRUC_DECL_NODE: return "STRUC_DECL_NODE";
225 case UNION_DECL_NODE: return "UNION_DECL_NODE";
226 case ENUM_DECL_NODE: return "ENUM_DECL_NODE";
227 case RECORD_DECL_NODE: return "RECORD_DECL_NODE";
228 case BITFIELD_DECL_NODE:return "BITFIELD_DECL_NODE";
229 case DOT_NODE: return "DOT_NODE";
230 case SIZEOF_NODE: return "SIZEOF_NODE";
231 case DATATYPE_NODE: return "DATATYPE_NODE";
232 case VAR_DECL_NODE: return "VAR_DECL_NODE";
233 case SCOPE_NODE: return "SCOPE_NODE";
234 case PROC_NODE: return "PROC_NODE";
235 case REPT_NODE: return "REPT_NODE";
236 case WHILE_NODE: return "WHILE_NODE";
237 case MESSAGE_NODE: return "MESSAGE_NODE";
238 case WARNING_NODE: return "WARNING_NODE";
239 case ERROR_NODE: return "ERROR_NODE";
240 case FORWARD_BRANCH_DECL_NODE: return "FORWARD_BRANCH_DECL_NODE";
241 case BACKWARD_BRANCH_DECL_NODE: return "BACKWARD_BRANCH_DECL_NODE";
242 case FORWARD_BRANCH_NODE: return "FORWARD_BRANCH_NODE";
243 case BACKWARD_BRANCH_NODE: return "BACKWARD_BRANCH_NODE";
244 case MASK_NODE: return "MASK_NODE";
245 case INDEX_NODE: return "INDEX_NODE";
246 case ORG_NODE: return "ORG_NODE";
247 case TOMBSTONE_NODE: return "TOMBSTONE_NODE";
249 return "astnode_type_to_string: invalid type";
253 * Gets string representation of a datatype.
254 * @param dt Datatype
255 * @return String representation of dt
257 const char *datatype_to_string(const astnode *dt)
259 switch (dt->datatype) {
260 case BYTE_DATATYPE: return "BYTE_DATATYPE";
261 case CHAR_DATATYPE: return "CHAR_DATATYPE";
262 case WORD_DATATYPE: return "WORD_DATATYPE";
263 case DWORD_DATATYPE: return "DWORD_DATATYPE";
264 case USER_DATATYPE: return "USER_DATATYPE"; // astnode_get_child(dt, 0)->ident;
266 return "datatype_to_string: invalid datatype";
270 * Gets string representation of an operator.
271 * @param op Operator
272 * @return String representation of op
274 const char *operator_to_string(int op)
276 switch (op) {
277 case PLUS_OPERATOR: return "PLUS_OPERATOR";
278 case MINUS_OPERATOR: return "MINUS_OPERATOR";
279 case MUL_OPERATOR: return "MUL_OPERATOR";
280 case DIV_OPERATOR: return "DIV_OPERATOR";
281 case MOD_OPERATOR: return "MOD_OPERATOR";
282 case AND_OPERATOR: return "AND_OPERATOR";
283 case OR_OPERATOR: return "OR_OPERATOR";
284 case XOR_OPERATOR: return "XOR_OPERATOR";
285 case SHL_OPERATOR: return "SHL_OPERATOR";
286 case SHR_OPERATOR: return "SHR_OPERATOR";
287 case LT_OPERATOR: return "LT_OPERATOR";
288 case GT_OPERATOR: return "GT_OPERATOR";
289 case EQ_OPERATOR: return "EQ_OPERATOR";
290 case NE_OPERATOR: return "NE_OPERATOR";
291 case LE_OPERATOR: return "LE_OPERATOR";
292 case GE_OPERATOR: return "GE_OPERATOR";
293 case NEG_OPERATOR: return "NEG_OPERATOR";
294 case NOT_OPERATOR: return "NOT_OPERATOR";
295 case LO_OPERATOR: return "LO_OPERATOR";
296 case HI_OPERATOR: return "HI_OPERATOR";
297 case UMINUS_OPERATOR: return "UMINUS_OPERATOR";
298 case BANK_OPERATOR: return "BANK_OPERATOR";
300 return "operator_to_string: invalid operator";
304 * Indents.
305 * @param nlevels Levels
307 void indent(int nlevels)
309 int i;
310 for (i=0; i<nlevels; i++) {
311 printf(" ");
316 * Prints a node recursively.
317 * @param n Node to print
318 * @param level Level (depth)
320 void astnode_print(const astnode *n, int level)
322 int i;
323 /* Indent so it looks pretty */
324 indent(level);
325 /* Print the node type */
326 printf(astnode_type_to_string(astnode_get_type(n)));
327 /* Print attributes for those that have */
328 switch (astnode_get_type(n)) {
329 case INTEGER_NODE: printf("(%d)", n->integer); break;
330 case STRING_NODE: printf("(\"%s\")", n->string); break;
331 case IDENTIFIER_NODE: printf("(%s)", n->ident); break;
332 case LOCAL_ID_NODE: printf("(%s)", n->ident); break;
333 case FILE_PATH_NODE: printf("(%s)", n->file_path); break;
334 case LABEL_NODE: printf("(%s)", n->label); break;
335 case LOCAL_LABEL_NODE: printf("(%s)", n->label); break;
336 case BINARY_NODE: printf("(%d)", n->binary.size); break;
338 case ARITHMETIC_NODE:
339 printf(
340 "(%s)",
341 operator_to_string(n->oper)
343 break;
345 case INSTRUCTION_NODE:
346 printf(
347 "(%s,%s,%.2X)",
348 instr_mnemonic_to_string(n->instr.mnemonic),
349 addressing_mode_to_string(n->instr.mode),
350 n->instr.opcode
352 break;
354 case DATATYPE_NODE:
355 printf(
356 "(%s)",
357 datatype_to_string(n)
359 break;
361 case FORWARD_BRANCH_DECL_NODE:
362 case BACKWARD_BRANCH_DECL_NODE:
363 case FORWARD_BRANCH_NODE:
364 case BACKWARD_BRANCH_NODE:
365 printf("(%s)", n->ident);
366 break;
368 case TOMBSTONE_NODE:
369 printf(
370 "(%s)",
371 astnode_type_to_string(n->param)
373 break;
375 default:
376 /* Has no internal attributes */
377 break;
379 printf("\n");
380 /* Print the children */
381 for (i=0; i<astnode_get_child_count(n); i++) {
382 astnode_print(astnode_get_child(n, i), level+1);
386 /*---------------------------------------------------------------------------*/
387 /* Functions for general-purpose node management:
388 Creation, destruction, children etc.
392 * Creates a new node of the given type.
393 * @param type The node's type
394 * @param loc File location
395 * @return The newly created node
397 astnode *astnode_create(astnode_type type, location loc)
399 extern const char *yy_current_filename();
400 if (loc.file == NULL) {
401 loc.file = yy_current_filename();
403 /* Allocate memory for node struct */
404 astnode *n = (astnode *)malloc(sizeof(astnode));
405 /* Fill in struct only if alloc succeeded */
406 if (n != NULL) {
407 n->type = type;
408 n->loc = loc;
409 n->flags = 0;
410 n->label = NULL;
411 n->string = NULL;
412 n->parent = n->first_child = n->prev_sibling = n->next_sibling = NULL;
414 return n;
418 * Finalizes a node.
419 * Any children of the node are also finalized, recursively.
420 * @param n The node to finalize.
422 void astnode_finalize(astnode *n)
424 astnode *c;
425 /* Remove the node from the tree it's in. */
426 astnode_remove(n);
427 /* Finalize all its children recursively. */
428 while ((c = astnode_get_first_child(n)) != NULL) {
429 astnode_remove_child(n, c);
430 astnode_finalize(c);
432 /* Free up memory. */
433 switch (astnode_get_type(n)) {
434 case LABEL_NODE: SAFE_FREE(n->label); break;
435 case LOCAL_LABEL_NODE: SAFE_FREE(n->label); break;
436 case STRING_NODE: SAFE_FREE(n->string); break;
437 case IDENTIFIER_NODE: SAFE_FREE(n->ident); break;
438 case LOCAL_ID_NODE: SAFE_FREE(n->ident); break;
439 case FILE_PATH_NODE: SAFE_FREE(n->file_path);break;
440 case BINARY_NODE: SAFE_FREE(n->binary.data); break;
441 case FORWARD_BRANCH_DECL_NODE:
442 case BACKWARD_BRANCH_DECL_NODE:
443 case FORWARD_BRANCH_NODE:
444 case BACKWARD_BRANCH_NODE:
445 SAFE_FREE(n->ident);
446 break;
447 default:
448 /* Has no internal attributes that are dynamically allocated */
449 break;
451 SAFE_FREE(n);
455 * Gets the node's type.
456 * @param n The node whose type to get
457 * @return The node's type (astnode_type)
459 astnode_type astnode_get_type(const astnode *n)
461 return (n != NULL) ? n->type : NULL_NODE;
465 * Sets the parent field of all nodes in c to p.
467 void astnode_set_parent(astnode *c, astnode *p)
469 astnode *n;
470 for (n = c; n != NULL; n = n->next_sibling) {
471 n->parent = p;
476 * Replaces a node with another.
478 void astnode_replace(astnode *old_node, astnode *new_node)
480 astnode *p;
481 int i;
482 /* Get the parent of the node to be replaced */
483 p = astnode_get_parent(old_node);
484 if (p != NULL) {
485 /* Call remove_child on parent */
486 i = astnode_remove_child(p, old_node);
487 /* Insert new child at old child's position */
488 astnode_insert_child(p, new_node, i);
493 * Removes a node from a tree.
494 * @param n The node to remove (can't be the root of the tree)
496 void astnode_remove(astnode *n)
498 astnode *p = astnode_get_parent(n);
499 if (n && p) {
500 astnode_remove_child(p, n);
505 * Removes a child node.
506 * @param p Parent node
507 * @param c Child node
508 * @return Index of the removed node
510 int astnode_remove_child(astnode *p, astnode *c)
512 int i;
513 i = astnode_get_child_index(p, c);
514 if (i == 0) {
515 /* Remove head of list. */
516 p->first_child = c->next_sibling;
517 if (p->first_child) {
518 p->first_child->prev_sibling = NULL;
520 c->parent = c->next_sibling = c->prev_sibling = NULL;
522 else if (i > 0) {
523 c->prev_sibling->next_sibling = c->next_sibling;
524 if (c->next_sibling) {
525 c->next_sibling->prev_sibling = c->prev_sibling;
527 c->parent = c->next_sibling = c->prev_sibling = NULL;
529 return i;
533 * Removes child node at specified index.
534 * @param p Parent node
535 * @param i Index >= 0
537 astnode *astnode_remove_child_at(astnode *p, int i)
539 astnode *c = astnode_get_child(p, i);
540 astnode_remove_child(p, c);
541 return c;
545 * Removes all children from a node and returns them as a list.
546 * @param p Parent node whose children to remove
548 astnode *astnode_remove_children(astnode *p)
550 astnode *c;
551 if (p == NULL) { return NULL; }
552 if (p->first_child != NULL) {
553 c = p->first_child;
554 p->first_child = NULL;
555 /* Set parent of all siblings to NULL. */
556 astnode_set_parent(c, NULL);
557 /* Return the list of children */
558 return c;
560 else {
561 /* Has no children. */
562 return NULL;
567 * Inserts a list of nodes as children.
570 void astnode_insert_child(astnode *p, astnode *c, int i)
572 astnode *n;
573 astnode *x;
574 if (p && c) {
575 x = astnode_get_child(p, i); /* Current child at that position */
576 if (x == NULL) {
577 /* There isn't a node here. Just add to end. */
578 astnode_add_child(p, c);
580 else {
581 n = astnode_get_last_sibling(c);
582 /* Make c..n precede x */
583 c->prev_sibling = x->prev_sibling;
584 if (x->prev_sibling) {
585 x->prev_sibling->next_sibling = c;
587 n->next_sibling = x;
588 x->prev_sibling = n;
590 /* Set parent */
591 astnode_set_parent(c, p);
592 /* Check if head */
593 if (i == 0) {
594 p->first_child = c;
600 * Gets the last node in a list.
602 astnode *astnode_get_last_sibling(const astnode *n)
604 astnode *s = NULL;
605 if (n) {
606 for (s = (astnode *)n; s->next_sibling != NULL; s = s->next_sibling) ;
608 return s;
612 * Gets the parent of a node.
613 * @param n The node whose parent to get
614 * @return The node's parent, or <code>NULL</code> if it has none
616 astnode *astnode_get_parent(const astnode *n)
618 return n ? n->parent : NULL;
622 * Adds child(ren) to a node.
623 * @param n The parent-to-be
624 * @param new_child List of children-to-be
626 void astnode_add_child(astnode *n, astnode *new_child)
628 if (n && new_child) {
629 if (n->first_child == NULL) {
630 /* This node has no children, add this as the first one */
631 n->first_child = new_child;
632 astnode_set_parent(new_child, n);
634 else {
635 astnode_add_sibling(n->first_child, new_child);
641 * Adds any number of children to a node.
642 * @param n The parent-to-be
644 void astnode_add_children(astnode *n, int count, ...)
646 int i;
647 va_list ap;
648 astnode *c;
650 va_start(ap, count);
651 for (i=0; i<count; i++) {
652 c = va_arg(ap, astnode*);
653 astnode_add_child(n, c);
655 va_end(ap);
659 * Adds sibling(s) to a node.
660 * @param brother List of existing siblings
661 * @param sister List of new siblings
663 void astnode_add_sibling(astnode *brother, astnode *sister)
665 astnode *n;
666 astnode *p;
667 if (brother && sister) {
668 /* Add to end of list */
669 n = astnode_get_last_sibling(brother);
670 n->next_sibling = sister;
671 sister->prev_sibling = n;
672 p = astnode_get_parent(brother);
673 astnode_set_parent(sister, p);
678 * Gets the child node at the specified index.
679 * @param n The parent node
680 * @param index The index of the desired child node
682 astnode *astnode_get_child(const astnode *n, int index)
684 int i;
685 astnode *c;
686 if (n) {
687 c = n->first_child;
688 for (i = 0; i != index; i++) {
689 if (c == NULL) {
690 /* No child at that index. */
691 break;
693 c = c->next_sibling;
695 return c;
697 /* Node is NULL, so return NULL */
698 return NULL;
702 * Gets a node's first child.
703 * @param n The node
705 astnode *astnode_get_first_child(const astnode *n)
707 return (n == NULL) ? NULL : n->first_child;
711 * Gets the index of a child node.
712 * @param p Parent node
713 * @param c Child node
714 * @return Index of c >= 0, or -1 if invalid input
716 int astnode_get_child_index(const astnode *p, const astnode *c)
718 int i;
719 astnode *n;
720 if (p && c) {
721 for (i=0, n=p->first_child; (n != c) && (n != NULL); i++, n=n->next_sibling);
722 return n ? i : -1;
724 return -1;
728 * Gets the number of children a node has.
729 * @param p Node whose children count to get
731 int astnode_get_child_count(const astnode *p)
733 astnode *c;
734 int count = 0;
735 if (p != NULL) {
736 for (c = p->first_child; c != NULL; count++, c = c->next_sibling);
738 return count;
742 * Clones a node and all its children.
743 * @param n The node to clone
744 * @param loc File location
746 astnode *astnode_clone(const astnode *n, location loc)
748 astnode *c;
749 astnode *n_c;
750 if (n == NULL) { return NULL; }
751 /* Create node */
752 c = astnode_create(astnode_get_type(n), loc);
753 /* Copy attributes */
754 switch (astnode_get_type(n)) {
755 case INTEGER_NODE:
756 c->integer = n->integer;
757 break;
759 case STRING_NODE:
760 case IDENTIFIER_NODE:
761 case FILE_PATH_NODE:
762 case LABEL_NODE:
763 case LOCAL_LABEL_NODE:
764 case LOCAL_ID_NODE:
765 c->string = (char *)malloc(strlen(n->string)+1);
766 if (c->string != NULL) {
767 strcpy(c->string, n->string);
769 break;
771 case ARITHMETIC_NODE:
772 c->oper = n->oper;
773 break;
775 case INSTRUCTION_NODE:
776 c->instr = n->instr;
777 break;
779 case BINARY_NODE:
780 c->binary = n->binary;
781 break;
783 case DATATYPE_NODE:
784 c->datatype = n->datatype;
785 break;
787 default:
788 c->param = n->param;
790 /* Clone children (TODO: OPTIMIZE THIS) */
791 for (n_c=n->first_child; n_c != NULL; n_c=n_c->next_sibling) {
792 astnode_add_child(c, astnode_clone(n_c, loc));
794 /* Return the clone */
795 return c;
799 * Tests if two nodes are equal.
801 int astnode_equal(const astnode *n1, const astnode *n2)
803 int i;
804 /* Verify that types are the same */
805 if (astnode_get_type(n1) != astnode_get_type(n2)) {
806 return 0; /* Types don't match -- not equal */
808 /* Verify that internal data is the same */
809 switch (astnode_get_type(n1)) {
810 case ARITHMETIC_NODE: if (n1->oper != n2->oper) return 0; break;
811 case INTEGER_NODE: if (n1->integer != n2->integer) return 0; break;
812 case STRING_NODE: if (strcmp(n1->string, n2->string)) return 0; break;
813 case IDENTIFIER_NODE: if (strcmp(n1->ident, n2->ident)) return 0; break;
814 case LOCAL_ID_NODE: if (strcmp(n1->ident, n2->ident)) return 0; break;
815 case FILE_PATH_NODE: if (strcmp(n1->file_path, n2->file_path)) return 0; break;
816 case LABEL_NODE: if (strcmp(n1->label, n2->label)) return 0; break;
817 case LOCAL_LABEL_NODE: if (strcmp(n1->label, n2->label)) return 0; break;
818 case BINARY_NODE: if (n1->binary.size != n2->binary.size) return 0; break;
819 case DATATYPE_NODE: if (n1->datatype != n2->datatype) return 0; break;
820 case TOMBSTONE_NODE: if (n1->param != n2->param) return 0; break;
821 case INSTRUCTION_NODE: if ( (n1->instr.mnemonic != n2->instr.mnemonic) || (n1->instr.mode != n2->instr.mode) ) return 0; break;
822 default:
823 /* Has no internal attributes */
824 break;
826 /* Verify that they have the same number of children */
827 if (astnode_get_child_count(n1) != astnode_get_child_count(n2)) {
828 return 0;
830 /* Verify that children are equal */
831 for (i=0; i<astnode_get_child_count(n1); i++) {
832 if (!astnode_equal(astnode_get_child(n1, i), astnode_get_child(n2, i))) {
833 return 0;
836 /* Equal. */
837 return 1;
841 * Gets the ancestor of a node.
842 * @param n Node whose ancestor to get
843 * @param back How many generations to go back (0=father, 1=grandfather etc.)
845 astnode *astnode_get_ancestor(const astnode *n, int back)
847 int i;
848 astnode *a = astnode_get_parent(n);
849 for (i=0; i<back; i++) {
850 a = astnode_get_parent(a);
852 return a;
856 * Tests if a node is a descendant of a node of a particular type.
857 * @param n Node
858 * @param type Ancestor's type
859 * @return 0 if no such ancestor, 1 otherwise
861 int astnode_has_ancestor_of_type(const astnode *n, astnode_type type)
863 astnode *a;
864 for (a = astnode_get_parent(n); a != NULL; a = astnode_get_parent(a) ) {
865 if (astnode_is_type(a, type)) {
866 return 1;
869 return 0;
873 * Gets the next sibling of a node.
874 * @param n Node
876 astnode *astnode_get_next_sibling(const astnode *n)
878 if (n == NULL) { return NULL; }
879 return n->next_sibling;
883 * Gets the previous sibling of a node.
884 * @param n Node
886 astnode *astnode_get_prev_sibling(const astnode *n)
888 if (n == NULL) { return NULL; }
889 return n->prev_sibling;
893 * Tests if a node is a literal.
894 * @param n Node to test
896 int astnode_is_literal(const astnode *n)
898 switch (astnode_get_type(n)) {
899 case INTEGER_NODE:
900 case STRING_NODE:
901 /* A literal */
902 return 1;
904 default:
905 /* Not a literal */
906 break;
908 /* Not a literal */
909 return 0;
912 /*---------------------------------------------------------------------------*/
913 /* Functions for creating AST nodes of specific type.
914 1:1 correspondence between astnode_create_* and *_INSTRUCTION.
915 Each takes the operands required for that node type,
916 calls astnode_create() and then fills in fields and adds children (if any).
919 astnode *astnode_create_null(location loc)
921 /* Create the node */
922 astnode *n = astnode_create(NULL_NODE, loc);
923 /* Return the newly created node */
924 return n;
928 * Creates a CPU instruction node.
929 * @param mnemonic The instruction mnemonic
930 * @param mode The addressing mode used
931 * @param operand The instruction operand (an expression) (can be <code>NULL</code>)
932 * @param loc File location
934 astnode *astnode_create_instruction(int mnemonic, addressing_mode mode, astnode *operand, location loc)
936 /* Create the node */
937 astnode *n = astnode_create(INSTRUCTION_NODE, loc);
938 /* Store the mnemonic and addressing mode */
939 n->instr.mnemonic = mnemonic;
940 n->instr.mode = mode;
941 /* This node has one child: The operand, which is an expression */
942 astnode_add_child(n, operand);
943 /* Return the newly created node */
944 return n;
948 * Creates an identifier node.
949 * @param ident The identifier (a string)
950 * @param loc File location
952 astnode *astnode_create_identifier(const char *ident, location loc)
954 /* Create the node */
955 astnode *n = astnode_create(IDENTIFIER_NODE, loc);
956 /* Allocate and store text */
957 n->ident = (char *)malloc(strlen(ident)+1);
958 if (n->ident != NULL) {
959 strcpy(n->ident, ident);
961 /* Return the newly created node */
962 return n;
966 * Creates an integer literal node.
967 * @param value The integer literal
968 * @param loc File location
970 astnode *astnode_create_integer(int value, location loc)
972 /* Create the node */
973 astnode *n = astnode_create(INTEGER_NODE, loc);
974 /* Store the integer which this node represents */
975 n->integer = value;
976 /* Return the newly created node */
977 return n;
981 * Creates a string literal node.
982 * @param value The string literal
983 * @param loc File location
985 astnode *astnode_create_string(const char *value, location loc)
987 /* Create the node */
988 astnode *n = astnode_create(STRING_NODE, loc);
989 /* Allocate and store text */
990 n->string = (char *)malloc(strlen(value)+1);
991 if (n->string != NULL) {
992 strcpy(n->string, value);
994 /* Return the newly created node */
995 return n;
999 * Creates an expression node (unary or binary).
1000 * @param oper The operator
1001 * @param left Left operand
1002 * @param right Right operand (can be <code>NULL</code>)
1003 * @param loc File location
1005 astnode *astnode_create_arithmetic(arithmetic_operator oper, astnode *left, astnode *right, location loc)
1007 /* Create the node */
1008 astnode *n = astnode_create(ARITHMETIC_NODE, loc);
1009 /* Store the operator, which describes the type of expression */
1010 n->oper = oper;
1011 /* This node has two children: left-hand side and right-hand side expression */
1012 /* For unary operators right-hand side should be <code>NULL</code> */
1013 astnode_add_children(n, 2, left, right);
1014 /* Return the newly created node */
1015 return n;
1019 * Creates an if node.
1020 * @param expr The expression involved in the if
1021 * @param then The statement(s) to assemble when expr is non-zero
1022 * @param elif List of CASE nodes (may be <code>NULL</code>)
1023 * @param els The final else-part (DEFAULT node) (may be <code>NULL</code>)
1024 * @param loc File location
1026 astnode *astnode_create_if(astnode *expr, astnode *then, astnode *elif, astnode *els, location loc)
1028 /* Create the node */
1029 astnode *n = astnode_create(IF_NODE, loc);
1030 /* This node has several children: List of CASE nodes, possibly ended by DEFAULT node */
1031 astnode_add_child(n, astnode_create_case(expr, then, loc) );
1032 astnode_add_child(n, elif);
1033 if (els != NULL) {
1034 astnode_add_child(n, astnode_create_default(els, loc));
1036 /* Return the newly created node */
1037 return n;
1041 * Creates a CASE node.
1042 * @param expr Expression
1043 * @param then List of statement to assemble when expr is non-zero (true)
1044 * @param loc File location
1046 astnode *astnode_create_case(astnode *expr, astnode *then, location loc)
1048 /* Create the node */
1049 astnode *n = astnode_create(CASE_NODE, loc);
1050 /* This node has two children: expression to test and list of statements. */
1051 astnode_add_children(
1054 expr,
1055 astnode_create_list(then)
1057 /* Return the newly created node */
1058 return n;
1062 * Creates a DEFAULT node.
1063 * @param stmts List of statements
1064 * @param loc File location
1066 astnode *astnode_create_default(astnode *stmts, location loc)
1068 /* Create the node */
1069 astnode *n = astnode_create(DEFAULT_NODE, loc);
1070 /* This node has list of statements as children. */
1071 astnode_add_child(
1073 stmts
1075 /* Return the newly created node */
1076 return n;
1080 * Creates an ifdef node.
1081 * @param ident The identifier to check
1082 * @param then The statement(s) to assemble when ident is defined
1083 * @param els The statement(s) to assemble when ident is not defined (can be <code>NULL</code>)
1084 * @param loc File location
1086 astnode *astnode_create_ifdef(astnode *ident, astnode *then, astnode *els, location loc)
1088 /* Create the node */
1089 astnode *n = astnode_create(IFDEF_NODE, loc);
1090 /* This node has three children: identifier to test, then-part, else-part */
1091 astnode_add_children(
1094 ident,
1095 astnode_create_list(then),
1096 astnode_create_list(els)
1098 /* Return the newly created node */
1099 return n;
1103 * Creates an ifndef node.
1104 * @param ident The identifier to check
1105 * @param then The statement(s) to assemble when ident is not defined
1106 * @param els The statement(s) to assemble when ident is defined (can be <code>NULL</code>)
1107 * @param loc File location
1109 astnode *astnode_create_ifndef(astnode *ident, astnode *then, astnode *els, location loc)
1111 /* Create the node */
1112 astnode *n = astnode_create(IFNDEF_NODE, loc);
1113 /* This node has three children: identifier to test, then-part, else-part */
1114 astnode_add_children(
1117 ident,
1118 astnode_create_list(then),
1119 astnode_create_list(els)
1121 /* Return the newly created node */
1122 return n;
1126 * Creates a macro declaration node.
1127 * @param ident Name of macro
1128 * @param params List of parameters (can be <code>NULL</code>)
1129 * @param body Macro body
1130 * @param loc File location
1132 astnode *astnode_create_macro_decl(astnode *ident, astnode *params, astnode *body, location loc)
1134 /* Create the node */
1135 astnode *n = astnode_create(MACRO_DECL_NODE, loc);
1136 /* This node has three children:
1137 1) An identifier, which is the name of the macro
1138 2) List of parameters
1139 3) List of statements, which is the macro body */
1140 astnode_add_children(
1143 ident,
1144 astnode_create_list(params),
1145 astnode_create_list(body)
1147 /* Return the newly created node */
1148 return n;
1152 * Creates a macro node.
1153 * @param ident Name of macro
1154 * @param args List of arguments (can be <code>NULL</code>)
1155 * @param loc File location
1157 astnode *astnode_create_macro(astnode *ident, astnode *args, location loc)
1159 /* Create the node */
1160 astnode *n = astnode_create(MACRO_NODE, loc);
1161 /* Add the children */
1162 astnode_add_children(
1165 ident,
1166 astnode_create_list(args)
1168 /* Return the newly created node */
1169 return n;
1173 * Creates an equ node.
1174 * @param ident Identifier
1175 * @param expr Expression
1176 * @param loc File location
1178 astnode *astnode_create_equ(astnode *ident, astnode *expr, location loc)
1180 /* Create the node */
1181 astnode *n = astnode_create(EQU_NODE, loc);
1182 /* Add the children */
1183 astnode_add_children(n, 2, ident, expr);
1184 /* Return the newly created node */
1185 return n;
1189 * Creates an assign node.
1190 * @param ident Identifier
1191 * @param expr Expression
1192 * @param loc File location
1194 astnode *astnode_create_assign(astnode *ident, astnode *expr, location loc)
1196 /* Create the node */
1197 astnode *n = astnode_create(ASSIGN_NODE, loc);
1198 /* Add the children */
1199 astnode_add_children(n, 2, ident, expr);
1200 /* Return the newly created node */
1201 return n;
1205 * Creates a storage node.
1206 * @param type Type of storage
1207 * @param count Expression with contains count
1208 * @param loc File location
1210 astnode *astnode_create_storage(astnode *type, astnode *count, location loc)
1212 /* Create the node */
1213 astnode *n = astnode_create(STORAGE_NODE, loc);
1214 /* Add the type of data (enumerated or identifier) */
1215 astnode_add_child(n, type);
1216 /* Second child: Count */
1217 if (count == NULL) {
1218 /* No count given, default=1 */
1219 count = astnode_create_integer(1, loc);
1221 astnode_add_child(n, count);
1222 /* Return the newly created node */
1223 return n;
1227 * Creates an incsrc node.
1228 * @param file File specifier
1229 * @param loc File location
1231 astnode *astnode_create_incsrc(astnode *file, location loc)
1233 /* Create the node */
1234 astnode *n = astnode_create(INCSRC_NODE, loc);
1235 /* One child: Path to file */
1236 astnode_add_child(n, file);
1237 /* Return the newly created node */
1238 return n;
1242 * Creates an incbin node.
1243 * @param file File specifier
1244 * @param loc File location
1246 astnode *astnode_create_incbin(astnode *file, location loc)
1248 /* Create the node */
1249 astnode *n = astnode_create(INCBIN_NODE, loc);
1250 /* One child: Path to file */
1251 astnode_add_child(n, file);
1252 /* Return the newly created node */
1253 return n;
1257 * Creates a charmap node.
1258 * @param file File specifier
1259 * @param loc File location
1261 astnode *astnode_create_charmap(astnode *file, location loc)
1263 /* Create the node */
1264 astnode *n = astnode_create(CHARMAP_NODE, loc);
1265 /* One child: Path to file */
1266 astnode_add_child(n, file);
1267 /* Return the newly created node */
1268 return n;
1272 * Creates a structure (STRUC) instance node.
1273 * @param vals Values for the structure fields
1274 * @param loc File location
1276 astnode *astnode_create_struc(astnode *vals, location loc)
1278 /* Create the node */
1279 astnode *n = astnode_create(STRUC_NODE, loc);
1280 /* Children: value list */
1281 astnode_add_child(n, vals);
1282 /* Return the newly created node */
1283 return n;
1286 * Creates a structure (STRUC) declaration node.
1287 * @param id Structure identifier
1288 * @param stmts Statements of the structure declaration
1289 * @param loc File location
1291 astnode *astnode_create_struc_decl(astnode *id, astnode *stmts, location loc)
1293 /* Create the node */
1294 astnode *n = astnode_create(STRUC_DECL_NODE, loc);
1295 /* Two children: Identifier, statement list */
1296 astnode_add_child(n, id);
1297 astnode_add_child(n, stmts);
1298 /* Return the newly created node */
1299 return n;
1303 * Creates a union declaration node.
1304 * @param id Union identifier
1305 * @param stmts Statements of the union declaration
1306 * @param loc File location
1308 astnode *astnode_create_union_decl(astnode *id, astnode *stmts, location loc)
1310 /* Create the node */
1311 astnode *n = astnode_create(UNION_DECL_NODE, loc);
1312 /* Two children: Identifier, statement list */
1313 astnode_add_child(n, id);
1314 astnode_add_child(n, stmts);
1315 /* Return the newly created node */
1316 return n;
1320 * Creates an enum declaration node.
1321 * @param id Enum identifier
1322 * @param stmts Statements of the enum declaration
1323 * @param loc File location
1325 astnode *astnode_create_enum_decl(astnode *id, astnode *stmts, location loc)
1327 /* Create the node */
1328 astnode *n = astnode_create(ENUM_DECL_NODE, loc);
1329 /* Two children: Identifier, statement list */
1330 astnode_add_child(n, id);
1331 astnode_add_child(n, stmts);
1332 /* Return the newly created node */
1333 return n;
1337 * Creates a record declaration node.
1338 * @param id Record identifier
1339 * @param fields Fields of the record
1340 * @param loc File location
1342 astnode *astnode_create_record_decl(astnode *id, astnode *fields, location loc)
1344 /* Create the node */
1345 astnode *n = astnode_create(RECORD_DECL_NODE, loc);
1346 /* Two children: Identifier, field list */
1347 astnode_add_child(n, id);
1348 astnode_add_child(n, fields);
1349 /* Return the newly created node */
1350 return n;
1354 * Creates a bitfield declaration node.
1355 * @param id Identifier
1356 * @param width Width of field
1357 * @param loc Location
1359 astnode *astnode_create_bitfield_decl(astnode *id, astnode *width, location loc)
1361 /* Create the node */
1362 astnode *n = astnode_create(BITFIELD_DECL_NODE, loc);
1363 /* Two children: Identifier and width */
1364 astnode_add_child(n, id);
1365 astnode_add_child(n, width);
1366 /* Return the newly created node */
1367 return n;
1371 * Creates a public node.
1373 astnode *astnode_create_public(astnode *l, location loc)
1375 /* Create the node */
1376 astnode *n = astnode_create(PUBLIC_NODE, loc);
1377 /* Add list of identifiers as child */
1378 astnode_add_child(n, l);
1379 /* Return the newly created node */
1380 return n;
1384 * Creates an extrn node.
1385 * @param l List of identifiers
1386 * @param t Symbol type specifier
1387 * @param f From unit (identifier, may be <code>NULL</code>)
1389 astnode *astnode_create_extrn(astnode *l, astnode *t, astnode *f, location loc)
1391 /* Create the node */
1392 astnode *n = astnode_create(EXTRN_NODE, loc);
1393 /* Add type specifier as child */
1394 astnode_add_child(n, t);
1395 /* Add list of identifiers as child */
1396 astnode_add_child(n, astnode_create_list(l));
1397 /* Add from unit identifier */
1398 astnode_add_child(n, f);
1399 /* Return the newly created node */
1400 return n;
1404 * Creates a dataseg node.
1406 astnode *astnode_create_dataseg(int modifiers, location loc)
1408 /* Create the node */
1409 astnode *n = astnode_create(DATASEG_NODE, loc);
1410 /* Set modifiers */
1411 n->modifiers = modifiers;
1412 /* Return the newly created node */
1413 return n;
1417 * Creates a codeseg node.
1419 astnode *astnode_create_codeseg(location loc)
1421 /* Create the node */
1422 astnode *n = astnode_create(CODESEG_NODE, loc);
1423 /* Return the newly created node */
1424 return n;
1428 * Creates a data node.
1429 * @param type Type specifier
1430 * @param data List of values
1431 * @param loc File location
1433 astnode *astnode_create_data(astnode *type, astnode *data, location loc)
1435 /* Create the node */
1436 astnode *n = astnode_create(DATA_NODE, loc);
1437 /* Add the type of data (enumerated or identifier) */
1438 astnode_add_child(n, type);
1439 /* Add list of values */
1440 astnode_add_child(n, data);
1441 /* Return the newly created node */
1442 return n;
1446 * Creates a file path node.
1447 * This is similar to a string literal node, the only difference is semantics.
1448 * A file path node implies that the path can be relative to both current
1449 * directory and any of the directories in the search path.
1450 * @param path The path this node represents
1451 * @param loc File location
1453 astnode *astnode_create_file_path(const char *path, location loc)
1455 /* Create the node */
1456 astnode *n = astnode_create(FILE_PATH_NODE, loc);
1457 /* Allocate and store text */
1458 n->file_path = (char *)malloc(strlen(path)+1);
1459 if (n->file_path != NULL) {
1460 strcpy(n->file_path, path);
1462 /* Return the newly created node */
1463 return n;
1467 * Creates a (global) label node.
1468 * @param s Name of label
1469 * @param addr Address
1470 * @param type Datatype (may be <code>NULL</code>)
1471 * @param loc Location
1473 astnode *astnode_create_label(const char *s, astnode *addr, astnode *type, location loc)
1475 /* Create the node */
1476 astnode *n = astnode_create(LABEL_NODE, loc);
1477 /* Allocate and store text */
1478 n->label = (char *)malloc(strlen(s)+1);
1479 if (n->label != NULL) {
1480 strcpy(n->label, s);
1482 /* Two children: Datatype and address */
1483 if (addr == NULL) {
1484 addr = astnode_create_pc(loc);
1486 if (type == NULL) {
1487 type = astnode_create_datatype(BYTE_DATATYPE, NULL, loc);
1489 astnode_add_child(n, type);
1490 astnode_add_child(n, addr);
1491 /* Return the newly created node */
1492 return n;
1496 * Creates a local label node.
1497 * @param s Name of label
1498 * @param loc Location
1500 astnode *astnode_create_local_label(const char *s, location loc)
1502 /* Create the node */
1503 astnode *n = astnode_create(LOCAL_LABEL_NODE, loc);
1504 /* Allocate and store text */
1505 n->label = (char *)malloc(strlen(s)+1);
1506 if (n->label != NULL) {
1507 strcpy(n->label, s);
1509 /* Return the newly created node */
1510 return n;
1514 * Creates a local identifier node.
1515 * @param s Identifier
1516 * @param loc Location
1518 astnode *astnode_create_local_id(const char *s, location loc)
1520 /* Create the node */
1521 astnode *n = astnode_create(LOCAL_ID_NODE, loc);
1522 /* Allocate and store text */
1523 n->ident = (char *)malloc(strlen(s)+1);
1524 if (n->ident != NULL) {
1525 strcpy(n->ident, s);
1527 /* Return the newly created node */
1528 return n;
1532 * Creates a list node.
1533 * This is a way to group a list of nodes in a parent node.
1534 * @param l List of nodes to group in list node
1536 astnode *astnode_create_list(astnode *l)
1538 astnode *n;
1539 /* Create the node */
1540 if (l != NULL) {
1541 n = astnode_create(LIST_NODE, l->loc);
1542 /* Add list of values */
1543 astnode_add_child(n, l);
1545 else {
1546 /* Make a node with zero children */
1547 location dummyloc;
1548 dummyloc.file = 0;
1549 n = astnode_create(LIST_NODE, dummyloc);
1551 /* Return the newly created node (or NULL) */
1552 return n;
1556 * Creates a PC node.
1557 * @param loc File location
1559 astnode *astnode_create_pc(location loc)
1561 return astnode_create(CURRENT_PC_NODE, loc);
1565 * Creates a binary node.
1566 * @param bin Dynamically allocated (malloc() ) data that this node wraps. Will be freed automatically by astnode_finalize()
1567 * @param size Size of bin
1568 * @param loc File location
1570 astnode *astnode_create_binary(unsigned char *bin, int size, location loc)
1572 /* Create the node */
1573 astnode *n = astnode_create(BINARY_NODE, loc);
1574 /* Set data */
1575 n->binary.data = bin;
1576 n->binary.size = size;
1577 /* Return the newly created node */
1578 return n;
1582 * Creates a tombstone node, which is a marker node that says that another node
1583 * once lived here.
1584 * @param type The type of node that used to live here
1585 * @param loc File location
1587 astnode *astnode_create_tombstone(astnode_type type, location loc)
1589 /* Create the node */
1590 astnode *n = astnode_create(TOMBSTONE_NODE, loc);
1591 /* Store the type of the old node */
1592 n->param = (long)type;
1593 /* Return the newly created node */
1594 return n;
1598 * Creates a dot operator node.
1599 * Represents a structure field access of the form 'before.after'.
1600 * @param before Structure identifier
1601 * @param after Field identifier (can be another dot op, or an identifier)
1603 astnode *astnode_create_dot(astnode *before, astnode *after, location loc)
1605 /* Create the node */
1606 astnode *n = astnode_create(DOT_NODE, loc);
1607 /* Two children: 'before' . 'after' */
1608 astnode_add_child(n, before);
1609 astnode_add_child(n, after);
1610 /* Return the newly created node */
1611 return n;
1615 * Creates a sizeof operator node.
1616 * @param expr Expression (datatype?)
1617 * @param loc Location
1619 astnode *astnode_create_sizeof(astnode *expr, location loc)
1621 /* Create the node */
1622 astnode *n = astnode_create(SIZEOF_NODE, loc);
1623 /* One child: expression */
1624 astnode_add_child(n, expr);
1625 /* Return the newly created node */
1626 return n;
1630 * Creates a datatype node.
1631 * @param t The datatype this node represents
1632 * @param id If the datatype is a custom one, this is its name
1633 * @param loc Location
1635 astnode *astnode_create_datatype(datatype t, astnode *id, location loc)
1637 /* Create the node */
1638 astnode *n = astnode_create(DATATYPE_NODE, loc);
1639 /* Set the datatype */
1640 n->datatype = t;
1641 /* Possibly one child: identifier */
1642 if (id != NULL) {
1643 astnode_add_child(n, id);
1645 /* Return the newly created node */
1646 return n;
1650 * Creates a variable declaration node.
1651 * @param modifiers PUBLIC_FLAG | ZEROPAGE_FLAG
1652 * @param id Identifier
1653 * @param data Datatype+initializer
1654 * @param loc Location
1656 astnode *astnode_create_var_decl(int modifiers, astnode *id, astnode *data, location loc)
1658 /* Create the node */
1659 astnode *n = astnode_create(VAR_DECL_NODE, loc);
1660 /* Set modifiers */
1661 n->modifiers = modifiers;
1662 /* Two children: Identifier and datatype+initializer */
1663 astnode_add_child(n, id);
1664 astnode_add_child(n, data);
1665 /* Return the newly created node */
1666 return n;
1672 astnode *astnode_create_scope(astnode *left, astnode *right, location loc)
1674 /* Create the node */
1675 astnode *n = astnode_create(SCOPE_NODE, loc);
1676 /* Two children: left and right */
1677 astnode_add_child(n, left);
1678 astnode_add_child(n, right);
1679 /* Return the newly created node */
1680 return n;
1684 * Creates a procedure (PROC) node.
1685 * @param ident Name of procedure
1686 * @param stmts Procedure statements
1687 * @param loc File location
1689 astnode *astnode_create_proc(astnode *ident, astnode *stmts, location loc)
1691 /* Create the node */
1692 astnode *n = astnode_create(PROC_NODE, loc);
1693 /* This node has two children:
1694 1) An identifier, which is the name of the procedure
1695 2) List of statements, which is the procedure body */
1696 astnode_add_children(
1699 ident,
1700 astnode_create_list(stmts)
1702 /* Return the newly created node */
1703 return n;
1707 * Creates a REPT node.
1708 * @param expr Number of times to repeat statements
1709 * @param stmts Statement list
1710 * @param loc File location
1712 astnode *astnode_create_rept(astnode *expr, astnode *stmts, location loc)
1714 /* Create the node */
1715 astnode *n = astnode_create(REPT_NODE, loc);
1716 /* This node has two children:
1717 1) An expression, which is the repeat count
1718 2) List of statements, which is the (anonymous) macro body */
1719 astnode_add_children(
1722 expr,
1723 astnode_create_list(stmts)
1725 /* Return the newly created node */
1726 return n;
1730 * Creates a WHILE node.
1731 * @param expr Boolean expression
1732 * @param stmts Statement list
1733 * @param loc File location
1735 astnode *astnode_create_while(astnode *expr, astnode *stmts, location loc)
1737 /* Create the node */
1738 astnode *n = astnode_create(WHILE_NODE, loc);
1739 /* This node has two children:
1740 1) A boolean expression
1741 2) List of statements, which is the (anonymous) macro body */
1742 astnode_add_children(
1745 expr,
1746 astnode_create_list(stmts)
1748 /* Return the newly created node */
1749 return n;
1753 * Creates a MESSAGE node.
1754 * @param expr Message to print.
1755 * @param loc File location
1757 astnode *astnode_create_message(astnode *expr, location loc)
1759 /* Create the node */
1760 astnode *n = astnode_create(MESSAGE_NODE, loc);
1761 /* This node has one children: An expression, which is the message to print */
1762 astnode_add_child(n, expr);
1763 /* Return the newly created node */
1764 return n;
1768 * Creates a WARNING node.
1769 * @param str Warning to print.
1770 * @param loc File location
1772 astnode *astnode_create_warning(astnode *str, location loc)
1774 /* Create the node */
1775 astnode *n = astnode_create(WARNING_NODE, loc);
1776 /* This node has one child: A string, which is the warning to print */
1777 astnode_add_child(n, str);
1778 /* Return the newly created node */
1779 return n;
1783 * Creates an ERROR node.
1784 * @param str Error to print.
1785 * @param loc File location
1787 astnode *astnode_create_error(astnode *str, location loc)
1789 /* Create the node */
1790 astnode *n = astnode_create(ERROR_NODE, loc);
1791 /* This node has one child: A string, which is the error to print */
1792 astnode_add_child(n, str);
1793 /* Return the newly created node */
1794 return n;
1798 * Creates a forward branch declaration node.
1799 * @param ident Branch name
1800 * @param loc File location
1802 astnode *astnode_create_forward_branch_decl(const char *ident, location loc)
1804 /* Create the node */
1805 astnode *n = astnode_create(FORWARD_BRANCH_DECL_NODE, loc);
1806 /* Allocate and store text */
1807 n->ident = (char *)malloc(strlen(ident)+1);
1808 if (n->ident != NULL) {
1809 strcpy(n->ident, ident);
1811 /* Return the newly created node */
1812 return n;
1816 * Creates a backward branch declaration node.
1817 * @param ident Branch name
1818 * @param loc File location
1820 astnode *astnode_create_backward_branch_decl(const char *ident, location loc)
1822 /* Create the node */
1823 astnode *n = astnode_create(BACKWARD_BRANCH_DECL_NODE, loc);
1824 /* Allocate and store text */
1825 n->ident = (char *)malloc(strlen(ident)+1);
1826 if (n->ident != NULL) {
1827 strcpy(n->ident, ident);
1829 /* Return the newly created node */
1830 return n;
1834 * Creates a forward branch reference node.
1835 * @param ident Branch name
1836 * @param loc File location
1838 astnode *astnode_create_forward_branch(const char *ident, location loc)
1840 /* Create the node */
1841 astnode *n = astnode_create(FORWARD_BRANCH_NODE, loc);
1842 /* Allocate and store text */
1843 n->ident = (char *)malloc(strlen(ident)+1);
1844 if (n->ident != NULL) {
1845 strcpy(n->ident, ident);
1847 /* Return the newly created node */
1848 return n;
1852 * Creates a backward branch reference node.
1853 * @param ident Branch name
1854 * @param loc File location
1856 astnode *astnode_create_backward_branch(const char *ident, location loc)
1858 /* Create the node */
1859 astnode *n = astnode_create(BACKWARD_BRANCH_NODE, loc);
1860 /* Allocate and store text */
1861 n->ident = (char *)malloc(strlen(ident)+1);
1862 if (n->ident != NULL) {
1863 strcpy(n->ident, ident);
1865 /* Return the newly created node */
1866 return n;
1870 * Creates a mask operator node.
1871 * @param expr Expression
1872 * @param loc Location
1874 astnode *astnode_create_mask(astnode *expr, location loc)
1876 /* Create the node */
1877 astnode *n = astnode_create(MASK_NODE, loc);
1878 /* One child: expression */
1879 astnode_add_child(n, expr);
1880 /* Return the newly created node */
1881 return n;
1885 * Creates an ALIGN node.
1886 * @param idents List of identifiers
1887 * @param expr Expression
1888 * @param loc File location
1890 astnode *astnode_create_align(astnode *idents, astnode *expr, location loc)
1892 /* Create the node */
1893 astnode *n = astnode_create(ALIGN_NODE, loc);
1894 /* This node has two children: List of identifiers and alignment constraint */
1895 astnode_add_child(n, astnode_create_list(idents) );
1896 astnode_add_child(n, expr);
1897 /* Return the newly created node */
1898 return n;
1902 * Creates an INDEX node.
1903 * @param ident Identifier being indexed
1904 * @param expr Index expression
1905 * @param loc File location
1907 astnode *astnode_create_index(astnode *ident, astnode *expr, location loc)
1909 /* Create the node */
1910 astnode *n = astnode_create(INDEX_NODE, loc);
1911 /* This node has two children: Identifier and expression */
1912 astnode_add_child(n, ident);
1913 astnode_add_child(n, expr);
1914 /* Return the newly created node */
1915 return n;
1919 * Creates an ORG node.
1920 * @param addr Address
1921 * @param loc File location
1923 astnode *astnode_create_org(astnode *addr, location loc)
1925 /* Create the node */
1926 astnode *n = astnode_create(ORG_NODE, loc);
1927 /* This node has one child: The address */
1928 astnode_add_child(n, addr);
1929 /* Return the newly created node */
1930 return n;
1933 /*---------------------------------------------------------------------------*/
1934 /* Functions for (de)serializing a node; probably not complete since it didn't
1935 end up being used by any program.
1938 #define put_byte(f, b) { fputc((unsigned char)(b), f); }
1939 #define put_short(f, w) { put_byte(f, w >> 8); put_byte(f, w); }
1940 #define put_int(f, q) { put_short(f, q >> 16); put_short(f, q); }
1943 * Serializes a node.
1944 * @param n The node to serialize
1945 * @param f The file to write to
1947 void astnode_serialize(const astnode *n, FILE *f)
1949 int i;
1950 /* Node type: 1 byte */
1951 put_byte(f, astnode_get_type(n));
1952 /* Internal node data */
1953 switch (astnode_get_type(n)) {
1954 case INTEGER_NODE:
1955 /* Assumes that sizeof(long) is same as for int */
1956 put_int(f, n->integer);
1957 break;
1959 case STRING_NODE:
1960 case IDENTIFIER_NODE:
1961 case LOCAL_ID_NODE:
1962 case FILE_PATH_NODE:
1963 case LABEL_NODE:
1964 case LOCAL_LABEL_NODE:
1965 /* Put length first */
1966 put_int(f, strlen(n->string));
1967 /* Put characters */
1968 for (i=0; i<strlen(n->string); i++) {
1969 put_byte(f, n->string[i]);
1971 break;
1973 case DATA_NODE:
1974 /* Datatype: 1 byte */
1975 put_byte(f, n->datatype);
1976 break;
1978 case BINARY_NODE:
1979 /* Size: 4 bytes */
1980 put_int(f, n->binary.size);
1981 /* Put data bytes */
1982 for (i=0; i<n->binary.size; i++) {
1983 put_byte(f, n->binary.data[i]);
1985 break;
1987 case ARITHMETIC_NODE:
1988 // TODO
1989 break;
1991 case INSTRUCTION_NODE:
1992 // TODO
1993 break;
1995 default:
1996 /* No internal attributes */
1997 break;
1999 /* Child count */
2000 put_int(f, astnode_get_child_count(n));
2001 /* Serialize children */
2002 for (i=0; i<astnode_get_child_count(n); i++) {
2003 astnode_serialize(astnode_get_child(n, i), f);
2007 #define get_byte(f) 0
2008 #define get_short(f) 0
2009 #define get_int(f) 0
2012 * Deserializes a node.
2013 * @param f The file to read from
2015 astnode *astnode_deserialize(FILE *f)
2017 int i;
2018 int len;
2019 astnode *n;
2020 astnode_type t;
2021 location loc;
2022 /* Node type: 1 byte */
2023 t = (astnode_type)get_byte(f);
2024 /* Create the node */
2025 n = astnode_create(t, loc);
2026 /* Internal node data */
2027 switch (astnode_get_type(n)) {
2028 case INTEGER_NODE:
2029 /* Assumes that sizeof(long) is same as for int */
2030 n->integer = get_int(f);
2031 break;
2033 case STRING_NODE:
2034 case IDENTIFIER_NODE:
2035 case LOCAL_ID_NODE:
2036 case FILE_PATH_NODE:
2037 case LABEL_NODE:
2038 case LOCAL_LABEL_NODE:
2039 /* Get length */
2040 len = get_int(f);
2041 /* Create the character array */
2042 n->string = malloc(len+1);
2043 if (n->string != NULL) {
2044 /* Get characters */
2045 for (i=0; i<len; i++) {
2046 n->string[i] = get_byte(f);
2049 break;
2051 case DATA_NODE:
2052 /* Datatype: 1 byte */
2053 n->datatype = get_byte(f);
2054 break;
2056 case BINARY_NODE:
2057 /* Size: 4 bytes */
2058 n->binary.size = get_int(f);
2059 /* Allocate storage */
2060 n->binary.data = (unsigned char *)malloc(n->binary.size);
2061 if (n->binary.data != NULL) {
2062 /* Get data bytes */
2063 for (i=0; i<n->param; i++) {
2064 n->binary.data[i] = get_byte(f);
2067 break;
2069 case ARITHMETIC_NODE:
2070 // TODO
2071 break;
2073 case INSTRUCTION_NODE:
2074 // TODO
2075 break;
2077 default:
2078 /* No internal attributes */
2079 break;
2081 /* Child count */
2082 len = get_int(f);
2083 /* Deserialize children */
2084 for (i=0; i<len; i++) {
2085 astnode_add_child(n, astnode_deserialize(f));
2088 /* Return the deserialized node */
2089 return n;