--- /dev/null
+/* Abstract syntax tree manipulation functions\r
+ *\r
+ * SOFTWARE RIGHTS\r
+ *\r
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool\r
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or\r
+ * company may do whatever they wish with source code distributed with\r
+ * PCCTS or the code generated by PCCTS, including the incorporation of\r
+ * PCCTS, or its output, into commerical software.\r
+ *\r
+ * We encourage users to develop software with PCCTS. However, we do ask\r
+ * that credit is given to us for developing PCCTS. By "credit",\r
+ * we mean that if you incorporate our source code into one of your\r
+ * programs (commercial product, research project, or otherwise) that you\r
+ * acknowledge this fact somewhere in the documentation, research report,\r
+ * etc... If you like PCCTS and have developed a nice tool with the\r
+ * output, please mention that you developed it using PCCTS. In\r
+ * addition, we ask that this header remain intact in our source code.\r
+ * As long as these guidelines are kept, we expect to continue enhancing\r
+ * this system and expect to make other tools available as they are\r
+ * completed. \r
+ *\r
+ * ANTLR 1.33\r
+ * Terence Parr\r
+ * Parr Research Corporation\r
+ * with Purdue University and AHPCRC, University of Minnesota\r
+ * 1989-2000\r
+ */\r
+\r
+#include "pcctscfg.h"\r
+\r
+#ifdef PCCTS_USE_STDARG\r
+#include "pccts_stdarg.h"\r
+#else\r
+#include <varargs.h>\r
+#endif\r
+\r
+/* ensure that tree manipulation variables are current after a rule\r
+ * reference\r
+ */\r
+\r
+void\r
+#ifdef __USE_PROTOS\r
+zzlink(AST **_root, AST **_sibling, AST **_tail)\r
+#else\r
+zzlink(_root, _sibling, _tail)\r
+AST **_root, **_sibling, **_tail;\r
+#endif\r
+{\r
+ if ( *_sibling == NULL ) return;\r
+ if ( *_root == NULL ) *_root = *_sibling;\r
+ else if ( *_root != *_sibling ) (*_root)->down = *_sibling;\r
+ if ( *_tail==NULL ) *_tail = *_sibling;\r
+ while ( (*_tail)->right != NULL ) *_tail = (*_tail)->right;\r
+}\r
+\r
+AST *\r
+#ifdef __USE_PROTOS\r
+zzastnew(void)\r
+#else\r
+zzastnew()\r
+#endif\r
+{\r
+ AST *p = (AST *) calloc(1, sizeof(AST));\r
+ if ( p == NULL ) fprintf(stderr,"%s(%d): cannot allocate AST node\n",__FILE__,__LINE__);\r
+ return p;\r
+}\r
+\r
+/* add a child node to the current sibling list */\r
+void\r
+#ifdef __USE_PROTOS\r
+zzsubchild(AST **_root, AST **_sibling, AST **_tail)\r
+#else\r
+zzsubchild(_root, _sibling, _tail)\r
+AST **_root, **_sibling, **_tail;\r
+#endif\r
+{\r
+ AST *n;\r
+ zzNON_GUESS_MODE {\r
+ n = zzastnew();\r
+#ifdef DEMAND_LOOK\r
+ zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0));\r
+#else\r
+ zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1));\r
+#endif\r
+ zzastPush( n );\r
+ if ( *_tail != NULL ) (*_tail)->right = n;\r
+ else {\r
+ *_sibling = n;\r
+ if ( *_root != NULL ) (*_root)->down = *_sibling;\r
+ }\r
+ *_tail = n;\r
+ if ( *_root == NULL ) *_root = *_sibling;\r
+ }\r
+}\r
+\r
+/* make a new AST node. Make the newly-created\r
+ * node the root for the current sibling list. If a root node already\r
+ * exists, make the newly-created node the root of the current root.\r
+ */\r
+void\r
+#ifdef __USE_PROTOS\r
+zzsubroot(AST **_root, AST **_sibling, AST **_tail)\r
+#else\r
+zzsubroot(_root, _sibling, _tail)\r
+AST **_root, **_sibling, **_tail;\r
+#endif\r
+{\r
+ AST *n;\r
+ zzNON_GUESS_MODE {\r
+ n = zzastnew();\r
+#ifdef DEMAND_LOOK\r
+ zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0));\r
+#else\r
+ zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1));\r
+#endif\r
+ zzastPush( n );\r
+ if ( *_root != NULL )\r
+ if ( (*_root)->down == *_sibling ) *_sibling = *_tail = *_root;\r
+ *_root = n;\r
+ (*_root)->down = *_sibling;\r
+ }\r
+}\r
+\r
+/* Apply function to root then each sibling\r
+ * example: print tree in child-sibling LISP-format (AST has token field)\r
+ *\r
+ * void show(tree)\r
+ * AST *tree;\r
+ * {\r
+ * if ( tree == NULL ) return;\r
+ * printf(" %s", zztokens[tree->token]);\r
+ * }\r
+ *\r
+ * void before() { printf(" ("); }\r
+ * void after() { printf(" )"); }\r
+ *\r
+ * LISPdump() { zzpre_ast(tree, show, before, after); }\r
+ *\r
+ */\r
+void\r
+#ifdef __USE_PROTOS\r
+zzpre_ast(\r
+ AST *tree,\r
+ void (*func)(AST *), /* apply this to each tree node */\r
+ void (*before)(AST *), /* apply this to root of subtree before preordering it */\r
+ void (*after)(AST *)) /* apply this to root of subtree after preordering it */\r
+#else\r
+zzpre_ast(tree, func, before, after)\r
+AST *tree;\r
+void (*func)(), /* apply this to each tree node */\r
+ (*before)(), /* apply this to root of subtree before preordering it */\r
+ (*after)(); /* apply this to root of subtree after preordering it */\r
+#endif\r
+{\r
+ while ( tree!= NULL )\r
+ {\r
+ if ( tree->down != NULL ) (*before)(tree);\r
+ (*func)(tree);\r
+ zzpre_ast(tree->down, func, before, after);\r
+ if ( tree->down != NULL ) (*after)(tree);\r
+ tree = tree->right;\r
+ }\r
+}\r
+\r
+/* free all AST nodes in tree; apply func to each before freeing */\r
+\r
+#if 0\r
+////void\r
+////#ifdef __USE_PROTOS\r
+////zzfree_ast(AST *tree)\r
+////#else\r
+////zzfree_ast(tree)\r
+////AST *tree;\r
+////#endif\r
+////{\r
+//// if ( tree == NULL ) return;\r
+//// zzfree_ast( tree->down );\r
+//// zzfree_ast( tree->right );\r
+//// zztfree( tree );\r
+////}\r
+#endif\r
+\r
+/*\r
+ MR19 Optimize freeing of the following structure to limit recursion\r
+ SAKAI Kiyotaka (ksakai@isr.co.jp)\r
+*/\r
+\r
+/*\r
+ NULL o\r
+ / \\r
+ NULL o\r
+ / \\r
+ NULL NULL\r
+*/\r
+\r
+/*\r
+ MR21 Another refinement to replace recursion with iteration\r
+ NAKAJIMA Mutsuki (muc@isr.co.jp).\r
+*/\r
+\r
+void\r
+#ifdef __USE_PROTOS\r
+zzfree_ast(AST *tree)\r
+#else\r
+zzfree_ast(tree)\r
+AST *tree;\r
+#endif\r
+{\r
+\r
+ AST *otree;\r
+\r
+ if (tree == NULL) return;\r
+\r
+ while (tree->down == NULL || tree->right == NULL) {\r
+\r
+ if (tree->down == NULL && tree->right == NULL) {\r
+ zztfree(tree);\r
+ return;\r
+ }\r
+\r
+ otree = tree;\r
+ if (tree->down == NULL) {\r
+ tree = tree->right;\r
+ } else {\r
+ tree = tree->down;\r
+ }\r
+ zztfree( otree );\r
+ }\r
+\r
+ while (tree != NULL) {\r
+ zzfree_ast(tree->down);\r
+ otree = tree;\r
+ tree = otree->right;\r
+ zztfree(otree);\r
+ }\r
+}\r
+\r
+/* build a tree (root child1 child2 ... NULL)\r
+ * If root is NULL, simply make the children siblings and return ptr\r
+ * to 1st sibling (child1). If root is not single node, return NULL.\r
+ *\r
+ * Siblings that are actually siblins lists themselves are handled\r
+ * correctly. For example #( NULL, #( NULL, A, B, C), D) results\r
+ * in the tree ( NULL A B C D ).\r
+ *\r
+ * Requires at least two parameters with the last one being NULL. If\r
+ * both are NULL, return NULL.\r
+ */\r
+#ifdef PCCTS_USE_STDARG\r
+AST *zztmake(AST *rt, ...)\r
+#else\r
+AST *zztmake(va_alist)\r
+va_dcl\r
+#endif\r
+{\r
+ va_list ap;\r
+ register AST *child, *sibling=NULL, *tail=NULL /* MR20 */, *w;\r
+ AST *root;\r
+\r
+#ifdef PCCTS_USE_STDARG\r
+ va_start(ap, rt);\r
+ root = rt;\r
+#else\r
+ va_start(ap);\r
+ root = va_arg(ap, AST *);\r
+#endif\r
+\r
+ if ( root != NULL )\r
+ if ( root->down != NULL ) return NULL;\r
+ child = va_arg(ap, AST *);\r
+ while ( child != NULL )\r
+ {\r
+ for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */\r
+ if ( sibling == NULL ) {sibling = child; tail = w;}\r
+ else {tail->right = child; tail = w;}\r
+ child = va_arg(ap, AST *);\r
+ }\r
+ if ( root==NULL ) root = sibling;\r
+ else root->down = sibling;\r
+ va_end(ap);\r
+ return root;\r
+}\r
+\r
+/* tree duplicate */\r
+AST *\r
+#ifdef __USE_PROTOS\r
+zzdup_ast(AST *t)\r
+#else\r
+zzdup_ast(t)\r
+AST *t;\r
+#endif\r
+{\r
+ AST *u;\r
+ \r
+ if ( t == NULL ) return NULL;\r
+ u = zzastnew();\r
+ *u = *t;\r
+#ifdef zzAST_DOUBLE\r
+ u->up = NULL; /* set by calling invocation */\r
+ u->left = NULL;\r
+#endif\r
+ u->right = zzdup_ast(t->right);\r
+ u->down = zzdup_ast(t->down);\r
+#ifdef zzAST_DOUBLE\r
+ if ( u->right!=NULL ) u->right->left = u;\r
+ if ( u->down!=NULL ) u->down->up = u;\r
+#endif\r
+ return u;\r
+}\r
+\r
+void\r
+#ifdef __USE_PROTOS\r
+zztfree(AST *t)\r
+#else\r
+zztfree(t)\r
+AST *t;\r
+#endif\r
+{\r
+#ifdef zzd_ast\r
+ zzd_ast( t );\r
+#endif\r
+ free( t );\r
+}\r
+\r
+#ifdef zzAST_DOUBLE\r
+/*\r
+ * Set the 'up', and 'left' pointers of all nodes in 't'.\r
+ * Initial call is double_link(your_tree, NULL, NULL).\r
+ */\r
+void\r
+#ifdef __USE_PROTOS\r
+zzdouble_link(AST *t, AST *left, AST *up)\r
+#else\r
+zzdouble_link(t, left, up)\r
+AST *t, *left, *up;\r
+#endif\r
+{\r
+ if ( t==NULL ) return;\r
+ t->left = left;\r
+ t->up = up;\r
+ zzdouble_link(t->down, NULL, t);\r
+ zzdouble_link(t->right, t, up);\r
+}\r
+#endif\r