sanity checking of ram allocation (if the algorithm is correct it's not necessary...
[xorcyst.git] / astnode.c
blob677a6f66aa8d7e3aad909deeb56e30232aec9003
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 "astnode.h"
82 #define SAFE_FREE(a) if (a) { free(a); a = NULL; }
84 /*---------------------------------------------------------------------------*/
85 /* Functions to convert and print astnodes as string.
86 These are useful when debugging syntax trees.
89 /**
90 * Gets string representation of an addressing mode.
91 * @param am Addressing mode (enumerated type)
92 * @return String representation of am
94 const char *addressing_mode_to_string(addressing_mode am)
96 switch (am) {
97 case IMPLIED_MODE: return "IMPLIED_MODE";
98 case ACCUMULATOR_MODE: return "ACCUMULATOR_MODE";
99 case IMMEDIATE_MODE: return "IMMEDIATE_MODE";
100 case ZEROPAGE_MODE: return "ZEROPAGE_MODE";
101 case ZEROPAGE_X_MODE: return "ZEROPAGE_X_MODE";
102 case ZEROPAGE_Y_MODE: return "ZEROPAGE_Y_MODE";
103 case ABSOLUTE_MODE: return "ABSOLUTE_MODE";
104 case ABSOLUTE_X_MODE: return "ABSOLUTE_X_MODE";
105 case ABSOLUTE_Y_MODE: return "ABSOLUTE_Y_MODE";
106 case PREINDEXED_INDIRECT_MODE: return "PREINDEXED_INDIRECT_MODE";
107 case POSTINDEXED_INDIRECT_MODE: return "POSTINDEXED_INDIRECT_MODE";
108 case INDIRECT_MODE: return "INDIRECT_MODE";
109 case RELATIVE_MODE: return "RELATIVE_MODE";
111 return "addressing_mode_to_string: invalid addressing mode";
115 * Gets string representation of an instruction mnemonic.
116 * @param im Instruction mnemonic (enumerated type)
117 * @return String representation of im
119 const char *instr_mnemonic_to_string(instr_mnemonic im)
121 switch (im) {
122 case ADC_MNEMONIC: return "ADC_MNEMONIC";
123 case AND_MNEMONIC: return "AND_MNEMONIC";
124 case ASL_MNEMONIC: return "ASL_MNEMONIC";
125 case BCC_MNEMONIC: return "BCC_MNEMONIC";
126 case BCS_MNEMONIC: return "BCS_MNEMONIC";
127 case BEQ_MNEMONIC: return "BEQ_MNEMONIC";
128 case BIT_MNEMONIC: return "BIT_MNEMONIC";
129 case BMI_MNEMONIC: return "BMI_MNEMONIC";
130 case BNE_MNEMONIC: return "BNE_MNEMONIC";
131 case BPL_MNEMONIC: return "BPL_MNEMONIC";
132 case BRK_MNEMONIC: return "BRK_MNEMONIC";
133 case BVC_MNEMONIC: return "BVC_MNEMONIC";
134 case BVS_MNEMONIC: return "BVS_MNEMONIC";
135 case CLC_MNEMONIC: return "CLC_MNEMONIC";
136 case CLD_MNEMONIC: return "CLD_MNEMONIC";
137 case CLI_MNEMONIC: return "CLI_MNEMONIC";
138 case CLV_MNEMONIC: return "CLV_MNEMONIC";
139 case CMP_MNEMONIC: return "CMP_MNEMONIC";
140 case CPX_MNEMONIC: return "CPX_MNEMONIC";
141 case CPY_MNEMONIC: return "CPY_MNEMONIC";
142 case DEC_MNEMONIC: return "DEC_MNEMONIC";
143 case DEX_MNEMONIC: return "DEX_MNEMONIC";
144 case DEY_MNEMONIC: return "DEY_MNEMONIC";
145 case EOR_MNEMONIC: return "EOR_MNEMONIC";
146 case INC_MNEMONIC: return "INC_MNEMONIC";
147 case INX_MNEMONIC: return "INX_MNEMONIC";
148 case INY_MNEMONIC: return "INY_MNEMONIC";
149 case JMP_MNEMONIC: return "JMP_MNEMONIC";
150 case JSR_MNEMONIC: return "JSR_MNEMONIC";
151 case LDA_MNEMONIC: return "LDA_MNEMONIC";
152 case LDX_MNEMONIC: return "LDX_MNEMONIC";
153 case LDY_MNEMONIC: return "LDY_MNEMONIC";
154 case LSR_MNEMONIC: return "LSR_MNEMONIC";
155 case NOP_MNEMONIC: return "NOP_MNEMONIC";
156 case ORA_MNEMONIC: return "ORA_MNEMONIC";
157 case PHA_MNEMONIC: return "PHA_MNEMONIC";
158 case PHP_MNEMONIC: return "PHP_MNEMONIC";
159 case PLA_MNEMONIC: return "PLA_MNEMONIC";
160 case PLP_MNEMONIC: return "PLP_MNEMONIC";
161 case ROL_MNEMONIC: return "ROL_MNEMONIC";
162 case ROR_MNEMONIC: return "ROR_MNEMONIC";
163 case RTI_MNEMONIC: return "RTI_MNEMONIC";
164 case RTS_MNEMONIC: return "RTS_MNEMONIC";
165 case SBC_MNEMONIC: return "SBC_MNEMONIC";
166 case SEC_MNEMONIC: return "SEC_MNEMONIC";
167 case SED_MNEMONIC: return "SED_MNEMONIC";
168 case SEI_MNEMONIC: return "SEI_MNEMONIC";
169 case STA_MNEMONIC: return "STA_MNEMONIC";
170 case STX_MNEMONIC: return "STX_MNEMONIC";
171 case STY_MNEMONIC: return "STY_MNEMONIC";
172 case TAX_MNEMONIC: return "TAX_MNEMONIC";
173 case TAY_MNEMONIC: return "TAY_MNEMONIC";
174 case TSX_MNEMONIC: return "TSX_MNEMONIC";
175 case TXA_MNEMONIC: return "TXA_MNEMONIC";
176 case TXS_MNEMONIC: return "TXS_MNEMONIC";
177 case TYA_MNEMONIC: return "TYA_MNEMONIC";
179 return "instr_mnemonic_to_string: invalid mnemonic";
183 * Gets string representation of an astnode type.
184 * @param at Node type
185 * @return String representation of at
187 const char *astnode_type_to_string(astnode_type at) {
188 switch (at) {
189 case NULL_NODE: return "NULL_NODE";
190 case INTEGER_NODE: return "INTEGER_NODE";
191 case STRING_NODE: return "STRING_NODE";
192 case IDENTIFIER_NODE: return "IDENTIFIER_NODE";
193 case DATA_NODE: return "DATA_NODE";
194 case STORAGE_NODE: return "STORAGE_NODE";
195 case MACRO_DECL_NODE: return "MACRO_DECL_NODE";
196 case MACRO_NODE: return "MACRO_NODE";
197 case ARITHMETIC_NODE: return "ARITHMETIC_NODE";
198 case IF_NODE: return "IF_NODE";
199 case CASE_NODE: return "CASE_NODE";
200 case DEFAULT_NODE: return "DEFAULT_NODE";
201 case IFDEF_NODE: return "IFDEF_NODE";
202 case IFNDEF_NODE: return "IFNDEF_NODE";
203 case INCSRC_NODE: return "INCSRC_NODE";
204 case INCBIN_NODE: return "INCBIN_NODE";
205 case EQU_NODE: return "EQU_NODE";
206 case ASSIGN_NODE: return "ASSIGN_NODE";
207 case ALIGN_NODE: return "ALIGN_NODE";
208 case INSTRUCTION_NODE: return "INSTRUCTION_NODE";
209 case FILE_PATH_NODE: return "FILE_PATH_NODE";
210 case CURRENT_PC_NODE: return "CURRENT_PC_NODE";
211 case LIST_NODE: return "LIST_NODE";
212 case LABEL_NODE: return "LABEL_NODE";
213 case LOCAL_LABEL_NODE: return "LOCAL_LABEL_NODE";
214 case LOCAL_ID_NODE: return "LOCAL_ID_NODE";
215 case BINARY_NODE: return "BINARY_NODE";
216 case PUBLIC_NODE: return "PUBLIC_NODE";
217 case EXTRN_NODE: return "EXTRN_NODE";
218 case DATASEG_NODE: return "DATASEG_NODE";
219 case CODESEG_NODE: return "CODESEG_NODE";
220 case CHARMAP_NODE: return "CHARMAP_NODE";
221 case STRUC_NODE: return "STRUC_NODE";
222 case STRUC_DECL_NODE: return "STRUC_DECL_NODE";
223 case UNION_DECL_NODE: return "UNION_DECL_NODE";
224 case ENUM_DECL_NODE: return "ENUM_DECL_NODE";
225 case RECORD_DECL_NODE: return "RECORD_DECL_NODE";
226 case BITFIELD_DECL_NODE:return "BITFIELD_DECL_NODE";
227 case DOT_NODE: return "DOT_NODE";
228 case SIZEOF_NODE: return "SIZEOF_NODE";
229 case DATATYPE_NODE: return "DATATYPE_NODE";
230 case VAR_DECL_NODE: return "VAR_DECL_NODE";
231 case SCOPE_NODE: return "SCOPE_NODE";
232 case PROC_NODE: return "PROC_NODE";
233 case REPT_NODE: return "REPT_NODE";
234 case WHILE_NODE: return "WHILE_NODE";
235 case MESSAGE_NODE: return "MESSAGE_NODE";
236 case WARNING_NODE: return "WARNING_NODE";
237 case ERROR_NODE: return "ERROR_NODE";
238 case FORWARD_BRANCH_DECL_NODE: return "FORWARD_BRANCH_DECL_NODE";
239 case BACKWARD_BRANCH_DECL_NODE: return "BACKWARD_BRANCH_DECL_NODE";
240 case FORWARD_BRANCH_NODE: return "FORWARD_BRANCH_NODE";
241 case BACKWARD_BRANCH_NODE: return "BACKWARD_BRANCH_NODE";
242 case MASK_NODE: return "MASK_NODE";
243 case INDEX_NODE: return "INDEX_NODE";
244 case ORG_NODE: return "ORG_NODE";
245 case TOMBSTONE_NODE: return "TOMBSTONE_NODE";
247 return "astnode_type_to_string: invalid type";
251 * Gets string representation of a datatype.
252 * @param dt Datatype
253 * @return String representation of dt
255 const char *datatype_to_string(const astnode *dt)
257 switch (dt->datatype) {
258 case BYTE_DATATYPE: return "BYTE_DATATYPE";
259 case CHAR_DATATYPE: return "CHAR_DATATYPE";
260 case WORD_DATATYPE: return "WORD_DATATYPE";
261 case DWORD_DATATYPE: return "DWORD_DATATYPE";
262 case USER_DATATYPE: return "USER_DATATYPE"; // astnode_get_child(dt, 0)->ident;
264 return "datatype_to_string: invalid datatype";
268 * Gets string representation of an operator.
269 * @param op Operator
270 * @return String representation of op
272 const char *operator_to_string(int op)
274 switch (op) {
275 case PLUS_OPERATOR: return "PLUS_OPERATOR";
276 case MINUS_OPERATOR: return "MINUS_OPERATOR";
277 case MUL_OPERATOR: return "MUL_OPERATOR";
278 case DIV_OPERATOR: return "DIV_OPERATOR";
279 case MOD_OPERATOR: return "MOD_OPERATOR";
280 case AND_OPERATOR: return "AND_OPERATOR";
281 case OR_OPERATOR: return "OR_OPERATOR";
282 case XOR_OPERATOR: return "XOR_OPERATOR";
283 case SHL_OPERATOR: return "SHL_OPERATOR";
284 case SHR_OPERATOR: return "SHR_OPERATOR";
285 case LT_OPERATOR: return "LT_OPERATOR";
286 case GT_OPERATOR: return "GT_OPERATOR";
287 case EQ_OPERATOR: return "EQ_OPERATOR";
288 case NE_OPERATOR: return "NE_OPERATOR";
289 case LE_OPERATOR: return "LE_OPERATOR";
290 case GE_OPERATOR: return "GE_OPERATOR";
291 case NEG_OPERATOR: return "NEG_OPERATOR";
292 case NOT_OPERATOR: return "NOT_OPERATOR";
293 case LO_OPERATOR: return "LO_OPERATOR";
294 case HI_OPERATOR: return "HI_OPERATOR";
295 case UMINUS_OPERATOR: return "UMINUS_OPERATOR";
296 case BANK_OPERATOR: return "BANK_OPERATOR";
298 return "operator_to_string: invalid operator";
302 * Indents.
303 * @param nlevels Levels
305 void indent(int nlevels)
307 int i;
308 for (i=0; i<nlevels; i++) {
309 printf(" ");
314 * Prints a node recursively.
315 * @param n Node to print
316 * @param level Level (depth)
318 void astnode_print(const astnode *n, int level)
320 int i;
321 /* Indent so it looks pretty */
322 indent(level);
323 /* Print the node type */
324 printf(astnode_type_to_string(astnode_get_type(n)));
325 /* Print attributes for those that have */
326 switch (astnode_get_type(n)) {
327 case INTEGER_NODE: printf("(%d)", n->integer); break;
328 case STRING_NODE: printf("(\"%s\")", n->string); break;
329 case IDENTIFIER_NODE: printf("(%s)", n->ident); break;
330 case LOCAL_ID_NODE: printf("(%s)", n->ident); break;
331 case FILE_PATH_NODE: printf("(%s)", n->file_path); break;
332 case LABEL_NODE: printf("(%s)", n->label); break;
333 case LOCAL_LABEL_NODE: printf("(%s)", n->label); break;
334 case BINARY_NODE: printf("(%d)", n->binary.size); break;
336 case ARITHMETIC_NODE:
337 printf(
338 "(%s)",
339 operator_to_string(n->oper)
341 break;
343 case INSTRUCTION_NODE:
344 printf(
345 "(%s,%s,%.2X)",
346 instr_mnemonic_to_string(n->instr.mnemonic),
347 addressing_mode_to_string(n->instr.mode),
348 n->instr.opcode
350 break;
352 case DATATYPE_NODE:
353 printf(
354 "(%s)",
355 datatype_to_string(n)
357 break;
359 case FORWARD_BRANCH_DECL_NODE:
360 case BACKWARD_BRANCH_DECL_NODE:
361 case FORWARD_BRANCH_NODE:
362 case BACKWARD_BRANCH_NODE:
363 printf("(%s)", n->ident);
364 break;
366 case TOMBSTONE_NODE:
367 printf(
368 "(%s)",
369 astnode_type_to_string(n->param)
371 break;
373 default:
374 /* Has no internal attributes */
375 break;
377 printf("\n");
378 /* Print the children */
379 for (i=0; i<astnode_get_child_count(n); i++) {
380 astnode_print(astnode_get_child(n, i), level+1);
384 /*---------------------------------------------------------------------------*/
385 /* Functions for general-purpose node management:
386 Creation, destruction, children etc.
390 * Creates a new node of the given type.
391 * @param type The node's type
392 * @param loc File location
393 * @return The newly created node
395 astnode *astnode_create(astnode_type type, location loc)
397 /* Fix: Sometimes loc.file is NULL for some reason */
398 extern const char *yy_current_filename();
399 if (loc.file == NULL) {
400 loc.file = yy_current_filename();
402 /* Allocate memory for node struct */
403 astnode *n = (astnode *)malloc(sizeof(astnode));
404 /* Fill in struct only if alloc succeeded */
405 if (n != NULL) {
406 n->type = type;
407 n->loc = loc;
408 n->flags = 0;
409 n->label = NULL;
410 n->string = NULL;
411 n->parent = n->first_child = n->prev_sibling = n->next_sibling = NULL;
413 return n;
417 * Finalizes a node.
418 * Any children of the node are also finalized, recursively.
419 * @param n The node to finalize.
421 void astnode_finalize(astnode *n)
423 /* Remove the node from the tree it's in. */
424 astnode_remove(n);
425 /* Finalize all its children recursively. */
426 while (astnode_get_first_child(n) != NULL) {
427 astnode_finalize(astnode_remove_child_at(n, 0));
429 /* Free up memory. */
430 switch (astnode_get_type(n)) {
431 case LABEL_NODE: SAFE_FREE(n->label); break;
432 case LOCAL_LABEL_NODE: SAFE_FREE(n->label); break;
433 case STRING_NODE: SAFE_FREE(n->string); break;
434 case IDENTIFIER_NODE: SAFE_FREE(n->ident); break;
435 case LOCAL_ID_NODE: SAFE_FREE(n->ident); break;
436 case FILE_PATH_NODE: SAFE_FREE(n->file_path);break;
437 case BINARY_NODE: SAFE_FREE(n->binary.data); break;
438 case FORWARD_BRANCH_DECL_NODE:
439 case BACKWARD_BRANCH_DECL_NODE:
440 case FORWARD_BRANCH_NODE:
441 case BACKWARD_BRANCH_NODE:
442 SAFE_FREE(n->ident);
443 break;
444 default:
445 /* Has no internal attributes that are dynamically allocated */
446 break;
448 SAFE_FREE(n);
452 * Gets the node's type.
453 * @param n The node whose type to get
454 * @return The node's type (astnode_type)
456 astnode_type astnode_get_type(const astnode *n)
458 return (n != NULL) ? n->type : NULL_NODE;
462 * Sets the parent field of all nodes in c to p.
464 void astnode_set_parent(astnode *c, astnode *p)
466 astnode *n;
467 for (n = c; n != NULL; n = n->next_sibling) {
468 n->parent = p;
473 * Replaces a node with another.
475 void astnode_replace(astnode *old_node, astnode *new_node)
477 astnode *p;
478 int i;
479 /* Get the parent of the node to be replaced */
480 p = astnode_get_parent(old_node);
481 if (p != NULL) {
482 /* Call remove_child on parent */
483 i = astnode_remove_child(p, old_node);
484 /* Insert new child at old child's position */
485 astnode_insert_child(p, new_node, i);
490 * Removes a node from a tree.
491 * @param n The node to remove (can't be the root of the tree)
493 void astnode_remove(astnode *n)
495 astnode *p = astnode_get_parent(n);
496 if (n && p) {
497 astnode_remove_child(p, n);
502 * Removes a child node.
503 * @param p Parent node
504 * @param c Child node
505 * @return Index of the removed node
507 int astnode_remove_child(astnode *p, astnode *c)
509 int i;
510 i = astnode_get_child_index(p, c);
511 if (i == 0) {
512 /* Remove head of list. */
513 p->first_child = c->next_sibling;
514 if (p->first_child) {
515 p->first_child->prev_sibling = NULL;
517 c->parent = c->next_sibling = c->prev_sibling = NULL;
519 else if (i > 0) {
520 c->prev_sibling->next_sibling = c->next_sibling;
521 if (c->next_sibling) {
522 c->next_sibling->prev_sibling = c->prev_sibling;
524 c->parent = c->next_sibling = c->prev_sibling = NULL;
526 return i;
530 * Removes child node at specified index.
531 * @param p Parent node
532 * @param i Index >= 0
534 astnode *astnode_remove_child_at(astnode *p, int i)
536 astnode *c = astnode_get_child(p, i);
537 astnode_remove_child(p, c);
538 return c;
542 * Removes all children from a node and returns them as a list.
543 * @param p Parent node whose children to remove
545 astnode *astnode_remove_children(astnode *p)
547 astnode *c;
548 if (p == NULL) { return NULL; }
549 if (p->first_child != NULL) {
550 c = p->first_child;
551 p->first_child = NULL;
552 /* Set parent of all siblings to NULL. */
553 astnode_set_parent(c, NULL);
554 /* Return the list of children */
555 return c;
557 else {
558 /* Has no children. */
559 return NULL;
564 * Inserts a list of nodes as children.
567 void astnode_insert_child(astnode *p, astnode *c, int i)
569 astnode *n;
570 astnode *x;
571 if (p && c) {
572 x = astnode_get_child(p, i); /* Current child at that position */
573 if (x == NULL) {
574 /* There isn't a node here. Just add to end. */
575 astnode_add_child(p, c);
577 else {
578 n = astnode_get_last_sibling(c);
579 /* Make c..n precede x */
580 c->prev_sibling = x->prev_sibling;
581 if (x->prev_sibling) {
582 x->prev_sibling->next_sibling = c;
584 n->next_sibling = x;
585 x->prev_sibling = n;
587 /* Set parent */
588 astnode_set_parent(c, p);
589 /* Check if head */
590 if (i == 0) {
591 p->first_child = c;
597 * Gets the last node in a list.
599 astnode *astnode_get_last_sibling(const astnode *n)
601 astnode *s = NULL;
602 if (n) {
603 for (s = (astnode *)n; s->next_sibling != NULL; s = s->next_sibling) ;
605 return s;
609 * Gets the parent of a node.
610 * @param n The node whose parent to get
611 * @return The node's parent, or <code>NULL</code> if it has none
613 astnode *astnode_get_parent(const astnode *n)
615 return n ? n->parent : NULL;
619 * Adds child(ren) to a node.
620 * @param n The parent-to-be
621 * @param new_child List of children-to-be
623 void astnode_add_child(astnode *n, astnode *new_child)
625 if (n && new_child) {
626 if (n->first_child == NULL) {
627 /* This node has no children, add this as the first one */
628 n->first_child = new_child;
629 astnode_set_parent(new_child, n);
631 else {
632 astnode_add_sibling(n->first_child, new_child);
638 * Adds any number of children to a node.
639 * @param n The parent-to-be
641 void astnode_add_children(astnode *n, int count, ...)
643 int i;
644 va_list ap;
645 astnode *c;
647 va_start(ap, count);
648 for (i=0; i<count; i++) {
649 c = va_arg(ap, astnode*);
650 astnode_add_child(n, c);
652 va_end(ap);
656 * Adds sibling(s) to a node.
657 * @param brother List of existing siblings
658 * @param sister List of new siblings
660 void astnode_add_sibling(astnode *brother, astnode *sister)
662 astnode *n;
663 astnode *p;
664 if (brother && sister) {
665 /* Add to end of list */
666 n = astnode_get_last_sibling(brother);
667 n->next_sibling = sister;
668 sister->prev_sibling = n;
669 p = astnode_get_parent(brother);
670 astnode_set_parent(sister, p);
675 * Gets the child node at the specified index.
676 * @param n The parent node
677 * @param index The index of the desired child node
679 astnode *astnode_get_child(const astnode *n, int index)
681 int i;
682 astnode *c;
683 if (n) {
684 c = n->first_child;
685 for (i = 0; i != index; i++) {
686 if (c == NULL) {
687 /* No child at that index. */
688 break;
690 c = c->next_sibling;
692 return c;
694 /* Node is NULL, so return NULL */
695 return NULL;
699 * Gets a node's first child.
700 * @param n The node
702 astnode *astnode_get_first_child(const astnode *n)
704 return (n == NULL) ? NULL : n->first_child;
708 * Gets the index of a child node.
709 * @param p Parent node
710 * @param c Child node
711 * @return Index of c >= 0, or -1 if invalid input
713 int astnode_get_child_index(const astnode *p, const astnode *c)
715 int i;
716 astnode *n;
717 if (p && c) {
718 for (i=0, n=p->first_child; (n != c) && (n != NULL); i++, n=n->next_sibling);
719 return n ? i : -1;
721 return -1;
725 * Gets the number of children a node has.
726 * @param p Node whose children count to get
728 int astnode_get_child_count(const astnode *p)
730 astnode *c;
731 int count = 0;
732 if (p != NULL) {
733 for (c = p->first_child; c != NULL; count++, c = c->next_sibling);
735 return count;
739 * Clones a node and all its children.
740 * @param n The node to clone
741 * @param loc File location
743 astnode *astnode_clone(const astnode *n, location loc)
745 astnode *c;
746 astnode *n_c;
747 if (n == NULL) { return NULL; }
748 /* Create node */
749 c = astnode_create(astnode_get_type(n), loc);
750 /* Copy attributes */
751 switch (astnode_get_type(n)) {
752 case INTEGER_NODE:
753 c->integer = n->integer;
754 break;
756 case STRING_NODE:
757 case IDENTIFIER_NODE:
758 case FILE_PATH_NODE:
759 case LABEL_NODE:
760 case LOCAL_LABEL_NODE:
761 case LOCAL_ID_NODE:
762 c->string = (char *)malloc(strlen(n->string)+1);
763 if (c->string != NULL) {
764 strcpy(c->string, n->string);
766 break;
768 case ARITHMETIC_NODE:
769 c->oper = n->oper;
770 break;
772 case INSTRUCTION_NODE:
773 c->instr = n->instr;
774 break;
776 case BINARY_NODE:
777 c->binary = n->binary;
778 break;
780 case DATATYPE_NODE:
781 c->datatype = n->datatype;
782 break;
784 default:
785 c->param = n->param;
787 /* Clone children (TODO: OPTIMIZE THIS) */
788 for (n_c=n->first_child; n_c != NULL; n_c=n_c->next_sibling) {
789 astnode_add_child(c, astnode_clone(n_c, loc));
791 /* Return the clone */
792 return c;
796 * Tests if two nodes are equal.
798 int astnode_equal(const astnode *n1, const astnode *n2)
800 int i;
801 /* Verify that types are the same */
802 if (astnode_get_type(n1) != astnode_get_type(n2)) {
803 return 0; /* Types don't match -- not equal */
805 /* Verify that internal data is the same */
806 switch (astnode_get_type(n1)) {
807 case ARITHMETIC_NODE: if (n1->oper != n2->oper) return 0; break;
808 case INTEGER_NODE: if (n1->integer != n2->integer) return 0; break;
809 case STRING_NODE: if (strcmp(n1->string, n2->string)) return 0; break;
810 case IDENTIFIER_NODE: if (strcmp(n1->ident, n2->ident)) return 0; break;
811 case LOCAL_ID_NODE: if (strcmp(n1->ident, n2->ident)) return 0; break;
812 case FILE_PATH_NODE: if (strcmp(n1->file_path, n2->file_path)) return 0; break;
813 case LABEL_NODE: if (strcmp(n1->label, n2->label)) return 0; break;
814 case LOCAL_LABEL_NODE: if (strcmp(n1->label, n2->label)) return 0; break;
815 case BINARY_NODE: if (n1->binary.size != n2->binary.size) return 0; break;
816 case DATATYPE_NODE: if (n1->datatype != n2->datatype) return 0; break;
817 case TOMBSTONE_NODE: if (n1->param != n2->param) return 0; break;
818 case INSTRUCTION_NODE: if ( (n1->instr.mnemonic != n2->instr.mnemonic) || (n1->instr.mode != n2->instr.mode) ) return 0; break;
819 default:
820 /* Has no internal attributes */
821 break;
823 /* Verify that they have the same number of children */
824 if (astnode_get_child_count(n1) != astnode_get_child_count(n2)) {
825 return 0;
827 /* Verify that children are equal */
828 for (i=0; i<astnode_get_child_count(n1); i++) {
829 if (!astnode_equal(astnode_get_child(n1, i), astnode_get_child(n2, i))) {
830 return 0;
833 /* Equal. */
834 return 1;
838 * Gets the ancestor of a node.
839 * @param n Node whose ancestor to get
840 * @param back How many generations to go back (0=father, 1=grandfather etc.)
842 astnode *astnode_get_ancestor(const astnode *n, int back)
844 int i;
845 astnode *a = astnode_get_parent(n);
846 for (i=0; i<back; i++) {
847 a = astnode_get_parent(a);
849 return a;
853 * Tests if a node is a descendant of a node of a particular type.
854 * @param n Node
855 * @param type Ancestor's type
856 * @return 0 if no such ancestor, 1 otherwise
858 int astnode_has_ancestor_of_type(const astnode *n, astnode_type type)
860 astnode *a;
861 for (a = astnode_get_parent(n); a != NULL; a = astnode_get_parent(a) ) {
862 if (astnode_is_type(a, type)) {
863 return 1;
866 return 0;
870 * Gets the next sibling of a node.
871 * @param n Node
873 astnode *astnode_get_next_sibling(const astnode *n)
875 if (n == NULL) { return NULL; }
876 return n->next_sibling;
880 * Gets the previous sibling of a node.
881 * @param n Node
883 astnode *astnode_get_prev_sibling(const astnode *n)
885 if (n == NULL) { return NULL; }
886 return n->prev_sibling;
890 * Tests if a node is a literal.
891 * @param n Node to test
893 int astnode_is_literal(const astnode *n)
895 switch (astnode_get_type(n)) {
896 case INTEGER_NODE:
897 case STRING_NODE:
898 /* A literal */
899 return 1;
901 default:
902 /* Not a literal */
903 break;
905 /* Not a literal */
906 return 0;
909 /*---------------------------------------------------------------------------*/
910 /* Functions for creating AST nodes of specific type.
911 1:1 correspondence between astnode_create_* and *_INSTRUCTION.
912 Each takes the operands required for that node type,
913 calls astnode_create() and then fills in fields and adds children (if any).
916 astnode *astnode_create_null(location loc)
918 /* Create the node */
919 astnode *n = astnode_create(NULL_NODE, loc);
920 /* Return the newly created node */
921 return n;
925 * Creates a CPU instruction node.
926 * @param mnemonic The instruction mnemonic
927 * @param mode The addressing mode used
928 * @param operand The instruction operand (an expression) (can be <code>NULL</code>)
929 * @param loc File location
931 astnode *astnode_create_instruction(int mnemonic, addressing_mode mode, astnode *operand, location loc)
933 /* Create the node */
934 astnode *n = astnode_create(INSTRUCTION_NODE, loc);
935 /* Store the mnemonic and addressing mode */
936 n->instr.mnemonic = mnemonic;
937 n->instr.mode = mode;
938 /* This node has one child: The operand, which is an expression */
939 astnode_add_child(n, operand);
940 /* Return the newly created node */
941 return n;
945 * Creates an identifier node.
946 * @param ident The identifier (a string)
947 * @param loc File location
949 astnode *astnode_create_identifier(const char *ident, location loc)
951 /* Create the node */
952 astnode *n = astnode_create(IDENTIFIER_NODE, loc);
953 /* Allocate and store text */
954 n->ident = (char *)malloc(strlen(ident)+1);
955 if (n->ident != NULL) {
956 strcpy(n->ident, ident);
958 /* Return the newly created node */
959 return n;
963 * Creates an integer literal node.
964 * @param value The integer literal
965 * @param loc File location
967 astnode *astnode_create_integer(int value, location loc)
969 /* Create the node */
970 astnode *n = astnode_create(INTEGER_NODE, loc);
971 /* Store the integer which this node represents */
972 n->integer = value;
973 /* Return the newly created node */
974 return n;
978 * Creates a string literal node.
979 * @param value The string literal
980 * @param loc File location
982 astnode *astnode_create_string(const char *value, location loc)
984 /* Create the node */
985 astnode *n = astnode_create(STRING_NODE, loc);
986 /* Allocate and store text */
987 n->string = (char *)malloc(strlen(value)+1);
988 if (n->string != NULL) {
989 strcpy(n->string, value);
991 /* Return the newly created node */
992 return n;
996 * Creates an expression node (unary or binary).
997 * @param oper The operator
998 * @param left Left operand
999 * @param right Right operand (can be <code>NULL</code>)
1000 * @param loc File location
1002 astnode *astnode_create_arithmetic(arithmetic_operator oper, astnode *left, astnode *right, location loc)
1004 /* Create the node */
1005 astnode *n = astnode_create(ARITHMETIC_NODE, loc);
1006 /* Store the operator, which describes the type of expression */
1007 n->oper = oper;
1008 /* This node has two children: left-hand side and right-hand side expression */
1009 /* For unary operators right-hand side should be <code>NULL</code> */
1010 astnode_add_children(n, 2, left, right);
1011 /* Return the newly created node */
1012 return n;
1016 * Creates an if node.
1017 * @param expr The expression involved in the if
1018 * @param then The statement(s) to assemble when expr is non-zero
1019 * @param elif List of CASE nodes (may be <code>NULL</code>)
1020 * @param els The final else-part (DEFAULT node) (may be <code>NULL</code>)
1021 * @param loc File location
1023 astnode *astnode_create_if(astnode *expr, astnode *then, astnode *elif, astnode *els, location loc)
1025 /* Create the node */
1026 astnode *n = astnode_create(IF_NODE, loc);
1027 /* This node has several children: List of CASE nodes, possibly ended by DEFAULT node */
1028 astnode_add_child(n, astnode_create_case(expr, then, loc) );
1029 astnode_add_child(n, elif);
1030 if (els != NULL) {
1031 astnode_add_child(n, astnode_create_default(els, loc));
1033 /* Return the newly created node */
1034 return n;
1038 * Creates a CASE node.
1039 * @param expr Expression
1040 * @param then List of statement to assemble when expr is non-zero (true)
1041 * @param loc File location
1043 astnode *astnode_create_case(astnode *expr, astnode *then, location loc)
1045 /* Create the node */
1046 astnode *n = astnode_create(CASE_NODE, loc);
1047 /* This node has two children: expression to test and list of statements. */
1048 astnode_add_children(
1051 expr,
1052 astnode_create_list(then)
1054 /* Return the newly created node */
1055 return n;
1059 * Creates a DEFAULT node.
1060 * @param stmts List of statements
1061 * @param loc File location
1063 astnode *astnode_create_default(astnode *stmts, location loc)
1065 /* Create the node */
1066 astnode *n = astnode_create(DEFAULT_NODE, loc);
1067 /* This node has list of statements as children. */
1068 astnode_add_child(
1070 stmts
1072 /* Return the newly created node */
1073 return n;
1077 * Creates an ifdef node.
1078 * @param ident The identifier to check
1079 * @param then The statement(s) to assemble when ident is defined
1080 * @param els The statement(s) to assemble when ident is not defined (can be <code>NULL</code>)
1081 * @param loc File location
1083 astnode *astnode_create_ifdef(astnode *ident, astnode *then, astnode *els, location loc)
1085 /* Create the node */
1086 astnode *n = astnode_create(IFDEF_NODE, loc);
1087 /* This node has three children: identifier to test, then-part, else-part */
1088 astnode_add_children(
1091 ident,
1092 astnode_create_list(then),
1093 astnode_create_list(els)
1095 /* Return the newly created node */
1096 return n;
1100 * Creates an ifndef node.
1101 * @param ident The identifier to check
1102 * @param then The statement(s) to assemble when ident is not defined
1103 * @param els The statement(s) to assemble when ident is defined (can be <code>NULL</code>)
1104 * @param loc File location
1106 astnode *astnode_create_ifndef(astnode *ident, astnode *then, astnode *els, location loc)
1108 /* Create the node */
1109 astnode *n = astnode_create(IFNDEF_NODE, loc);
1110 /* This node has three children: identifier to test, then-part, else-part */
1111 astnode_add_children(
1114 ident,
1115 astnode_create_list(then),
1116 astnode_create_list(els)
1118 /* Return the newly created node */
1119 return n;
1123 * Creates a macro declaration node.
1124 * @param ident Name of macro
1125 * @param params List of parameters (can be <code>NULL</code>)
1126 * @param body Macro body
1127 * @param loc File location
1129 astnode *astnode_create_macro_decl(astnode *ident, astnode *params, astnode *body, location loc)
1131 /* Create the node */
1132 astnode *n = astnode_create(MACRO_DECL_NODE, loc);
1133 /* This node has three children:
1134 1) An identifier, which is the name of the macro
1135 2) List of parameters
1136 3) List of statements, which is the macro body */
1137 astnode_add_children(
1140 ident,
1141 astnode_create_list(params),
1142 astnode_create_list(body)
1144 /* Return the newly created node */
1145 return n;
1149 * Creates a macro node.
1150 * @param ident Name of macro
1151 * @param args List of arguments (can be <code>NULL</code>)
1152 * @param loc File location
1154 astnode *astnode_create_macro(astnode *ident, astnode *args, location loc)
1156 /* Create the node */
1157 astnode *n = astnode_create(MACRO_NODE, loc);
1158 /* Add the children */
1159 astnode_add_children(
1162 ident,
1163 astnode_create_list(args)
1165 /* Return the newly created node */
1166 return n;
1170 * Creates an equ node.
1171 * @param ident Identifier
1172 * @param expr Expression
1173 * @param loc File location
1175 astnode *astnode_create_equ(astnode *ident, astnode *expr, location loc)
1177 /* Create the node */
1178 astnode *n = astnode_create(EQU_NODE, loc);
1179 /* Add the children */
1180 astnode_add_children(n, 2, ident, expr);
1181 /* Return the newly created node */
1182 return n;
1186 * Creates an assign node.
1187 * @param ident Identifier
1188 * @param expr Expression
1189 * @param loc File location
1191 astnode *astnode_create_assign(astnode *ident, astnode *expr, location loc)
1193 /* Create the node */
1194 astnode *n = astnode_create(ASSIGN_NODE, loc);
1195 /* Add the children */
1196 astnode_add_children(n, 2, ident, expr);
1197 /* Return the newly created node */
1198 return n;
1202 * Creates a storage node.
1203 * @param type Type of storage
1204 * @param count Expression with contains count
1205 * @param loc File location
1207 astnode *astnode_create_storage(astnode *type, astnode *count, location loc)
1209 /* Create the node */
1210 astnode *n = astnode_create(STORAGE_NODE, loc);
1211 /* Add the type of data (enumerated or identifier) */
1212 astnode_add_child(n, type);
1213 /* Second child: Count */
1214 if (count == NULL) {
1215 /* No count given, default=1 */
1216 count = astnode_create_integer(1, loc);
1218 astnode_add_child(n, count);
1219 /* Return the newly created node */
1220 return n;
1224 * Creates an incsrc node.
1225 * @param file File specifier
1226 * @param loc File location
1228 astnode *astnode_create_incsrc(astnode *file, location loc)
1230 /* Create the node */
1231 astnode *n = astnode_create(INCSRC_NODE, loc);
1232 /* One child: Path to file */
1233 astnode_add_child(n, file);
1234 /* Return the newly created node */
1235 return n;
1239 * Creates an incbin node.
1240 * @param file File specifier
1241 * @param loc File location
1243 astnode *astnode_create_incbin(astnode *file, location loc)
1245 /* Create the node */
1246 astnode *n = astnode_create(INCBIN_NODE, loc);
1247 /* One child: Path to file */
1248 astnode_add_child(n, file);
1249 /* Return the newly created node */
1250 return n;
1254 * Creates a charmap node.
1255 * @param file File specifier
1256 * @param loc File location
1258 astnode *astnode_create_charmap(astnode *file, location loc)
1260 /* Create the node */
1261 astnode *n = astnode_create(CHARMAP_NODE, loc);
1262 /* One child: Path to file */
1263 astnode_add_child(n, file);
1264 /* Return the newly created node */
1265 return n;
1269 * Creates a structure (STRUC) instance node.
1270 * @param vals Values for the structure fields
1271 * @param loc File location
1273 astnode *astnode_create_struc(astnode *vals, location loc)
1275 /* Create the node */
1276 astnode *n = astnode_create(STRUC_NODE, loc);
1277 /* Children: value list */
1278 astnode_add_child(n, vals);
1279 /* Return the newly created node */
1280 return n;
1283 * Creates a structure (STRUC) declaration node.
1284 * @param id Structure identifier
1285 * @param stmts Statements of the structure declaration
1286 * @param loc File location
1288 astnode *astnode_create_struc_decl(astnode *id, astnode *stmts, location loc)
1290 /* Create the node */
1291 astnode *n = astnode_create(STRUC_DECL_NODE, loc);
1292 /* Two children: Identifier, statement list */
1293 astnode_add_child(n, id);
1294 astnode_add_child(n, stmts);
1295 /* Return the newly created node */
1296 return n;
1300 * Creates a union declaration node.
1301 * @param id Union identifier
1302 * @param stmts Statements of the union declaration
1303 * @param loc File location
1305 astnode *astnode_create_union_decl(astnode *id, astnode *stmts, location loc)
1307 /* Create the node */
1308 astnode *n = astnode_create(UNION_DECL_NODE, loc);
1309 /* Two children: Identifier, statement list */
1310 astnode_add_child(n, id);
1311 astnode_add_child(n, stmts);
1312 /* Return the newly created node */
1313 return n;
1317 * Creates an enum declaration node.
1318 * @param id Enum identifier
1319 * @param stmts Statements of the enum declaration
1320 * @param loc File location
1322 astnode *astnode_create_enum_decl(astnode *id, astnode *stmts, location loc)
1324 /* Create the node */
1325 astnode *n = astnode_create(ENUM_DECL_NODE, loc);
1326 /* Two children: Identifier, statement list */
1327 astnode_add_child(n, id);
1328 astnode_add_child(n, stmts);
1329 /* Return the newly created node */
1330 return n;
1334 * Creates a record declaration node.
1335 * @param id Record identifier
1336 * @param fields Fields of the record
1337 * @param loc File location
1339 astnode *astnode_create_record_decl(astnode *id, astnode *fields, location loc)
1341 /* Create the node */
1342 astnode *n = astnode_create(RECORD_DECL_NODE, loc);
1343 /* Two children: Identifier, field list */
1344 astnode_add_child(n, id);
1345 astnode_add_child(n, fields);
1346 /* Return the newly created node */
1347 return n;
1351 * Creates a bitfield declaration node.
1352 * @param id Identifier
1353 * @param width Width of field
1354 * @param loc Location
1356 astnode *astnode_create_bitfield_decl(astnode *id, astnode *width, location loc)
1358 /* Create the node */
1359 astnode *n = astnode_create(BITFIELD_DECL_NODE, loc);
1360 /* Two children: Identifier and width */
1361 astnode_add_child(n, id);
1362 astnode_add_child(n, width);
1363 /* Return the newly created node */
1364 return n;
1368 * Creates a public node.
1370 astnode *astnode_create_public(astnode *l, location loc)
1372 /* Create the node */
1373 astnode *n = astnode_create(PUBLIC_NODE, loc);
1374 /* Add list of identifiers as child */
1375 astnode_add_child(n, l);
1376 /* Return the newly created node */
1377 return n;
1381 * Creates an extrn node.
1382 * @param l List of identifiers
1383 * @param t Symbol type specifier
1384 * @param f From unit (identifier, may be <code>NULL</code>)
1386 astnode *astnode_create_extrn(astnode *l, astnode *t, astnode *f, location loc)
1388 /* Create the node */
1389 astnode *n = astnode_create(EXTRN_NODE, loc);
1390 /* Add type specifier as child */
1391 astnode_add_child(n, t);
1392 /* Add list of identifiers as child */
1393 astnode_add_child(n, astnode_create_list(l));
1394 /* Add from unit identifier */
1395 astnode_add_child(n, f);
1396 /* Return the newly created node */
1397 return n;
1401 * Creates a dataseg node.
1403 astnode *astnode_create_dataseg(int modifiers, location loc)
1405 /* Create the node */
1406 astnode *n = astnode_create(DATASEG_NODE, loc);
1407 /* Set modifiers */
1408 n->modifiers = modifiers;
1409 /* Return the newly created node */
1410 return n;
1414 * Creates a codeseg node.
1416 astnode *astnode_create_codeseg(location loc)
1418 /* Create the node */
1419 astnode *n = astnode_create(CODESEG_NODE, loc);
1420 /* Return the newly created node */
1421 return n;
1425 * Creates a data node.
1426 * @param type Type specifier
1427 * @param data List of values
1428 * @param loc File location
1430 astnode *astnode_create_data(astnode *type, astnode *data, location loc)
1432 /* Create the node */
1433 astnode *n = astnode_create(DATA_NODE, loc);
1434 /* Add the type of data (enumerated or identifier) */
1435 astnode_add_child(n, type);
1436 /* Add list of values */
1437 astnode_add_child(n, data);
1438 /* Return the newly created node */
1439 return n;
1443 * Creates a file path node.
1444 * This is similar to a string literal node, the only difference is semantics.
1445 * A file path node implies that the path can be relative to both current
1446 * directory and any of the directories in the search path.
1447 * @param path The path this node represents
1448 * @param loc File location
1450 astnode *astnode_create_file_path(const char *path, location loc)
1452 /* Create the node */
1453 astnode *n = astnode_create(FILE_PATH_NODE, loc);
1454 /* Allocate and store text */
1455 n->file_path = (char *)malloc(strlen(path)+1);
1456 if (n->file_path != NULL) {
1457 strcpy(n->file_path, path);
1459 /* Return the newly created node */
1460 return n;
1464 * Creates a (global) label node.
1465 * @param s Name of label
1466 * @param addr Address
1467 * @param type Datatype (may be <code>NULL</code>)
1468 * @param loc Location
1470 astnode *astnode_create_label(const char *s, astnode *addr, astnode *type, location loc)
1472 /* Create the node */
1473 astnode *n = astnode_create(LABEL_NODE, loc);
1474 /* Allocate and store text */
1475 n->label = (char *)malloc(strlen(s)+1);
1476 if (n->label != NULL) {
1477 strcpy(n->label, s);
1479 /* Two children: Datatype and address */
1480 if (addr == NULL) {
1481 addr = astnode_create_pc(loc);
1483 if (type == NULL) {
1484 type = astnode_create_datatype(BYTE_DATATYPE, NULL, loc);
1486 astnode_add_child(n, type);
1487 astnode_add_child(n, addr);
1488 /* Return the newly created node */
1489 return n;
1493 * Creates a local label node.
1494 * @param s Name of label
1495 * @param loc Location
1497 astnode *astnode_create_local_label(const char *s, location loc)
1499 /* Create the node */
1500 astnode *n = astnode_create(LOCAL_LABEL_NODE, loc);
1501 /* Allocate and store text */
1502 n->label = (char *)malloc(strlen(s)+1);
1503 if (n->label != NULL) {
1504 strcpy(n->label, s);
1506 /* Return the newly created node */
1507 return n;
1511 * Creates a local identifier node.
1512 * @param s Identifier
1513 * @param loc Location
1515 astnode *astnode_create_local_id(const char *s, location loc)
1517 /* Create the node */
1518 astnode *n = astnode_create(LOCAL_ID_NODE, loc);
1519 /* Allocate and store text */
1520 n->ident = (char *)malloc(strlen(s)+1);
1521 if (n->ident != NULL) {
1522 strcpy(n->ident, s);
1524 /* Return the newly created node */
1525 return n;
1529 * Creates a list node.
1530 * This is a way to group a list of nodes in a parent node.
1531 * @param l List of nodes to group in list node
1533 astnode *astnode_create_list(astnode *l)
1535 astnode *n;
1536 location dummyloc;
1537 /* Create the node */
1538 if (l != NULL) {
1539 n = astnode_create(LIST_NODE, l->loc);
1540 /* Add list of values */
1541 astnode_add_child(n, l);
1543 else {
1544 /* Make a node with zero children */
1545 n = astnode_create(LIST_NODE, dummyloc);
1547 /* Return the newly created node (or NULL) */
1548 return n;
1552 * Creates a PC node.
1553 * @param loc File location
1555 astnode *astnode_create_pc(location loc)
1557 return astnode_create(CURRENT_PC_NODE, loc);
1561 * Creates a binary node.
1562 * @param bin Dynamically allocated (malloc() ) data that this node wraps. Will be freed automatically by astnode_finalize()
1563 * @param size Size of bin
1564 * @param loc File location
1566 astnode *astnode_create_binary(unsigned char *bin, int size, location loc)
1568 /* Create the node */
1569 astnode *n = astnode_create(BINARY_NODE, loc);
1570 /* Set data */
1571 n->binary.data = bin;
1572 n->binary.size = size;
1573 /* Return the newly created node */
1574 return n;
1578 * Creates a tombstone node, which is a marker node that says that another node
1579 * once lived here.
1580 * @param type The type of node that used to live here
1581 * @param loc File location
1583 astnode *astnode_create_tombstone(astnode_type type, location loc)
1585 /* Create the node */
1586 astnode *n = astnode_create(TOMBSTONE_NODE, loc);
1587 /* Store the type of the old node */
1588 n->param = (long)type;
1589 /* Return the newly created node */
1590 return n;
1594 * Creates a dot operator node.
1595 * Represents a structure field access of the form 'before.after'.
1596 * @param before Structure identifier
1597 * @param after Field identifier (can be another dot op, or an identifier)
1599 astnode *astnode_create_dot(astnode *before, astnode *after, location loc)
1601 /* Create the node */
1602 astnode *n = astnode_create(DOT_NODE, loc);
1603 /* Two children: 'before' . 'after' */
1604 astnode_add_child(n, before);
1605 astnode_add_child(n, after);
1606 /* Return the newly created node */
1607 return n;
1611 * Creates a sizeof operator node.
1612 * @param expr Expression (datatype?)
1613 * @param loc Location
1615 astnode *astnode_create_sizeof(astnode *expr, location loc)
1617 /* Create the node */
1618 astnode *n = astnode_create(SIZEOF_NODE, loc);
1619 /* One child: expression */
1620 astnode_add_child(n, expr);
1621 /* Return the newly created node */
1622 return n;
1626 * Creates a datatype node.
1627 * @param t The datatype this node represents
1628 * @param id If the datatype is a custom one, this is its name
1629 * @param loc Location
1631 astnode *astnode_create_datatype(datatype t, astnode *id, location loc)
1633 /* Create the node */
1634 astnode *n = astnode_create(DATATYPE_NODE, loc);
1635 /* Set the datatype */
1636 n->datatype = t;
1637 /* Possibly one child: identifier */
1638 if (id != NULL) {
1639 astnode_add_child(n, id);
1641 /* Return the newly created node */
1642 return n;
1646 * Creates a variable declaration node.
1647 * @param modifiers PUBLIC_FLAG | ZEROPAGE_FLAG
1648 * @param id Identifier
1649 * @param data Datatype+initializer
1650 * @param loc Location
1652 astnode *astnode_create_var_decl(int modifiers, astnode *id, astnode *data, location loc)
1654 /* Create the node */
1655 astnode *n = astnode_create(VAR_DECL_NODE, loc);
1656 /* Set modifiers */
1657 n->modifiers = modifiers;
1658 /* Two children: Identifier and datatype+initializer */
1659 astnode_add_child(n, id);
1660 astnode_add_child(n, data);
1661 /* Return the newly created node */
1662 return n;
1668 astnode *astnode_create_scope(astnode *left, astnode *right, location loc)
1670 /* Create the node */
1671 astnode *n = astnode_create(SCOPE_NODE, loc);
1672 /* Two children: left and right */
1673 astnode_add_child(n, left);
1674 astnode_add_child(n, right);
1675 /* Return the newly created node */
1676 return n;
1680 * Creates a procedure (PROC) node.
1681 * @param ident Name of procedure
1682 * @param stmts Procedure statements
1683 * @param loc File location
1685 astnode *astnode_create_proc(astnode *ident, astnode *stmts, location loc)
1687 /* Create the node */
1688 astnode *n = astnode_create(PROC_NODE, loc);
1689 /* This node has two children:
1690 1) An identifier, which is the name of the procedure
1691 2) List of statements, which is the procedure body */
1692 astnode_add_children(
1695 ident,
1696 astnode_create_list(stmts)
1698 /* Return the newly created node */
1699 return n;
1703 * Creates a REPT node.
1704 * @param expr Number of times to repeat statements
1705 * @param stmts Statement list
1706 * @param loc File location
1708 astnode *astnode_create_rept(astnode *expr, astnode *stmts, location loc)
1710 /* Create the node */
1711 astnode *n = astnode_create(REPT_NODE, loc);
1712 /* This node has two children:
1713 1) An expression, which is the repeat count
1714 2) List of statements, which is the (anonymous) macro body */
1715 astnode_add_children(
1718 expr,
1719 astnode_create_list(stmts)
1721 /* Return the newly created node */
1722 return n;
1726 * Creates a WHILE node.
1727 * @param expr Boolean expression
1728 * @param stmts Statement list
1729 * @param loc File location
1731 astnode *astnode_create_while(astnode *expr, astnode *stmts, location loc)
1733 /* Create the node */
1734 astnode *n = astnode_create(WHILE_NODE, loc);
1735 /* This node has two children:
1736 1) A boolean expression
1737 2) List of statements, which is the (anonymous) macro body */
1738 astnode_add_children(
1741 expr,
1742 astnode_create_list(stmts)
1744 /* Return the newly created node */
1745 return n;
1749 * Creates a MESSAGE node.
1750 * @param expr Message to print.
1751 * @param loc File location
1753 astnode *astnode_create_message(astnode *expr, location loc)
1755 /* Create the node */
1756 astnode *n = astnode_create(MESSAGE_NODE, loc);
1757 /* This node has one children: An expression, which is the message to print */
1758 astnode_add_child(n, expr);
1759 /* Return the newly created node */
1760 return n;
1764 * Creates a WARNING node.
1765 * @param str Warning to print.
1766 * @param loc File location
1768 astnode *astnode_create_warning(astnode *str, location loc)
1770 /* Create the node */
1771 astnode *n = astnode_create(WARNING_NODE, loc);
1772 /* This node has one child: A string, which is the warning to print */
1773 astnode_add_child(n, str);
1774 /* Return the newly created node */
1775 return n;
1779 * Creates an ERROR node.
1780 * @param str Error to print.
1781 * @param loc File location
1783 astnode *astnode_create_error(astnode *str, location loc)
1785 /* Create the node */
1786 astnode *n = astnode_create(ERROR_NODE, loc);
1787 /* This node has one child: A string, which is the error to print */
1788 astnode_add_child(n, str);
1789 /* Return the newly created node */
1790 return n;
1794 * Creates a forward branch declaration node.
1795 * @param ident Branch name
1796 * @param loc File location
1798 astnode *astnode_create_forward_branch_decl(const char *ident, location loc)
1800 /* Create the node */
1801 astnode *n = astnode_create(FORWARD_BRANCH_DECL_NODE, loc);
1802 /* Allocate and store text */
1803 n->ident = (char *)malloc(strlen(ident)+1);
1804 if (n->ident != NULL) {
1805 strcpy(n->ident, ident);
1807 /* Return the newly created node */
1808 return n;
1812 * Creates a backward branch declaration node.
1813 * @param ident Branch name
1814 * @param loc File location
1816 astnode *astnode_create_backward_branch_decl(const char *ident, location loc)
1818 /* Create the node */
1819 astnode *n = astnode_create(BACKWARD_BRANCH_DECL_NODE, loc);
1820 /* Allocate and store text */
1821 n->ident = (char *)malloc(strlen(ident)+1);
1822 if (n->ident != NULL) {
1823 strcpy(n->ident, ident);
1825 /* Return the newly created node */
1826 return n;
1830 * Creates a forward branch reference node.
1831 * @param ident Branch name
1832 * @param loc File location
1834 astnode *astnode_create_forward_branch(const char *ident, location loc)
1836 /* Create the node */
1837 astnode *n = astnode_create(FORWARD_BRANCH_NODE, loc);
1838 /* Allocate and store text */
1839 n->ident = (char *)malloc(strlen(ident)+1);
1840 if (n->ident != NULL) {
1841 strcpy(n->ident, ident);
1843 /* Return the newly created node */
1844 return n;
1848 * Creates a backward branch reference node.
1849 * @param ident Branch name
1850 * @param loc File location
1852 astnode *astnode_create_backward_branch(const char *ident, location loc)
1854 /* Create the node */
1855 astnode *n = astnode_create(BACKWARD_BRANCH_NODE, loc);
1856 /* Allocate and store text */
1857 n->ident = (char *)malloc(strlen(ident)+1);
1858 if (n->ident != NULL) {
1859 strcpy(n->ident, ident);
1861 /* Return the newly created node */
1862 return n;
1866 * Creates a mask operator node.
1867 * @param expr Expression
1868 * @param loc Location
1870 astnode *astnode_create_mask(astnode *expr, location loc)
1872 /* Create the node */
1873 astnode *n = astnode_create(MASK_NODE, loc);
1874 /* One child: expression */
1875 astnode_add_child(n, expr);
1876 /* Return the newly created node */
1877 return n;
1881 * Creates an ALIGN node.
1882 * @param idents List of identifiers
1883 * @param expr Expression
1884 * @param loc File location
1886 astnode *astnode_create_align(astnode *idents, astnode *expr, location loc)
1888 /* Create the node */
1889 astnode *n = astnode_create(ALIGN_NODE, loc);
1890 /* This node has two children: List of identifiers and alignment constraint */
1891 astnode_add_child(n, astnode_create_list(idents) );
1892 astnode_add_child(n, expr);
1893 /* Return the newly created node */
1894 return n;
1898 * Creates an INDEX node.
1899 * @param ident Identifier being indexed
1900 * @param expr Index expression
1901 * @param loc File location
1903 astnode *astnode_create_index(astnode *ident, astnode *expr, location loc)
1905 /* Create the node */
1906 astnode *n = astnode_create(INDEX_NODE, loc);
1907 /* This node has two children: Identifier and expression */
1908 astnode_add_child(n, ident);
1909 astnode_add_child(n, expr);
1910 /* Return the newly created node */
1911 return n;
1915 * Creates an ORG node.
1916 * @param addr Address
1917 * @param loc File location
1919 astnode *astnode_create_org(astnode *addr, location loc)
1921 /* Create the node */
1922 astnode *n = astnode_create(ORG_NODE, loc);
1923 /* This node has one child: The address */
1924 astnode_add_child(n, addr);
1925 /* Return the newly created node */
1926 return n;
1929 /*---------------------------------------------------------------------------*/
1930 /* Functions for (de)serializing a node; probably not complete since it didn't
1931 end up being used by any program.
1934 #define put_byte(f, b) { fputc((unsigned char)(b), f); }
1935 #define put_short(f, w) { put_byte(f, w >> 8); put_byte(f, w); }
1936 #define put_int(f, q) { put_short(f, q >> 16); put_short(f, q); }
1939 * Serializes a node.
1940 * @param n The node to serialize
1941 * @param f The file to write to
1943 void astnode_serialize(const astnode *n, FILE *f)
1945 int i;
1946 /* Node type: 1 byte */
1947 put_byte(f, astnode_get_type(n));
1948 /* Internal node data */
1949 switch (astnode_get_type(n)) {
1950 case INTEGER_NODE:
1951 /* Assumes that sizeof(long) is same as for int */
1952 put_int(f, n->integer);
1953 break;
1955 case STRING_NODE:
1956 case IDENTIFIER_NODE:
1957 case LOCAL_ID_NODE:
1958 case FILE_PATH_NODE:
1959 case LABEL_NODE:
1960 case LOCAL_LABEL_NODE:
1961 /* Put length first */
1962 put_int(f, strlen(n->string));
1963 /* Put characters */
1964 for (i=0; i<strlen(n->string); i++) {
1965 put_byte(f, n->string[i]);
1967 break;
1969 case DATA_NODE:
1970 /* Datatype: 1 byte */
1971 put_byte(f, n->datatype);
1972 break;
1974 case BINARY_NODE:
1975 /* Size: 4 bytes */
1976 put_int(f, n->binary.size);
1977 /* Put data bytes */
1978 for (i=0; i<n->binary.size; i++) {
1979 put_byte(f, n->binary.data[i]);
1981 break;
1983 case ARITHMETIC_NODE:
1984 // TODO
1985 break;
1987 case INSTRUCTION_NODE:
1988 // TODO
1989 break;
1991 default:
1992 /* No internal attributes */
1993 break;
1995 /* Child count */
1996 put_int(f, astnode_get_child_count(n));
1997 /* Serialize children */
1998 for (i=0; i<astnode_get_child_count(n); i++) {
1999 astnode_serialize(astnode_get_child(n, i), f);
2003 #define get_byte(f) 0
2004 #define get_short(f) 0
2005 #define get_int(f) 0
2008 * Deserializes a node.
2009 * @param f The file to read from
2011 astnode *astnode_deserialize(FILE *f)
2013 int i;
2014 int len;
2015 astnode *n;
2016 astnode_type t;
2017 location loc;
2018 /* Node type: 1 byte */
2019 t = (astnode_type)get_byte(f);
2020 /* Create the node */
2021 n = astnode_create(t, loc);
2022 /* Internal node data */
2023 switch (astnode_get_type(n)) {
2024 case INTEGER_NODE:
2025 /* Assumes that sizeof(long) is same as for int */
2026 n->integer = get_int(f);
2027 break;
2029 case STRING_NODE:
2030 case IDENTIFIER_NODE:
2031 case LOCAL_ID_NODE:
2032 case FILE_PATH_NODE:
2033 case LABEL_NODE:
2034 case LOCAL_LABEL_NODE:
2035 /* Get length */
2036 len = get_int(f);
2037 /* Create the character array */
2038 n->string = malloc(len+1);
2039 if (n->string != NULL) {
2040 /* Get characters */
2041 for (i=0; i<len; i++) {
2042 n->string[i] = get_byte(f);
2045 break;
2047 case DATA_NODE:
2048 /* Datatype: 1 byte */
2049 n->datatype = get_byte(f);
2050 break;
2052 case BINARY_NODE:
2053 /* Size: 4 bytes */
2054 n->binary.size = get_int(f);
2055 /* Allocate storage */
2056 n->binary.data = (unsigned char *)malloc(n->binary.size);
2057 if (n->binary.data != NULL) {
2058 /* Get data bytes */
2059 for (i=0; i<n->param; i++) {
2060 n->binary.data[i] = get_byte(f);
2063 break;
2065 case ARITHMETIC_NODE:
2066 // TODO
2067 break;
2069 case INSTRUCTION_NODE:
2070 // TODO
2071 break;
2073 default:
2074 /* No internal attributes */
2075 break;
2077 /* Child count */
2078 len = get_int(f);
2079 /* Deserialize children */
2080 for (i=0; i<len; i++) {
2081 astnode_add_child(n, astnode_deserialize(f));
2084 /* Return the deserialized node */
2085 return n;