/*********************************************************************** * $Id$ * Copyright 2009 Aplix Corporation. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Node-specific functions ***********************************************************************/ #include #include #include #include "comment.h" #include "lex.h" #include "misc.h" #include "node.h" #include "process.h" struct node * newelement(const char *name) { struct element *element = memalloc(sizeof(struct element)); element->n.type = NODE_ELEMENT; element->name = name; return &element->n; } struct node * newattr(const char *name, const char *val) { struct attr *attr = memalloc(sizeof(struct attr)); attr->n.type = NODE_ATTR; attr->name = name; attr->value = val; return &attr->n; } struct node * newattrlist(void) { struct attrlist *attrlist = memalloc(sizeof(struct attrlist)); attrlist->n.type = NODE_ATTRLIST; return &attrlist->n; } /*********************************************************************** * addnode : add node as child of another node * * Enter: parent node * child node * * The children list is constructed backwards. This is fixed later with * a call to reversechildren. * * If child is an attrlist, its children are added to parent and the * attrlist is freed. */ void addnode(struct node *parent, struct node *child) { if (!child) return; if (child->type == NODE_ATTRLIST) { /* Add the attrs in the attrlist to parent. */ struct node *child2; reversechildren(child); child2 = child->children; memfree(child); while (child2) { struct node *next = child2->next; addnode(parent, child2); child2 = next; } } else { child->next = parent->children; parent->children = child; child->parent = parent; } } /*********************************************************************** * reversechildren : recursively reverse child lists * * Also sets parent field on each node. */ void reversechildren(struct node *node) { struct node *newlist = 0; struct node *child = node->children; while (child) { struct node *next = child->next; child->parent = node; child->next = newlist; newlist = child; reversechildren(child); child = next; } node->children = newlist; } /*********************************************************************** * nodeisempty : test if node is empty (has no children) */ int nodeisempty(struct node *node) { return !node->children; } /*********************************************************************** * nodewalk : single step of depth last traversal of node tree * * Return: next node in walk, 0 if finished */ struct node * nodewalk(struct node *node) { if (node->children) return node->children; if (node->next) return node->next; do { node = node->parent; if (!node) return 0; } while (!node->next); return node->next; } /*********************************************************************** * findchildelement : find child element of a particular name * * Enter: node = element * name = name to find * * Return: 0 else child element of that name */ static struct node * findchildelement(struct node *node, const char *name) { node = node->children; while (node) { if (node->type == NODE_ELEMENT) { struct element *element = (void *)node; if (!strcmp(element->name, name)) break; } node = node->next; } return node; } /*********************************************************************** * getattr : get value of attribute * * Enter: node = element to find attribute in * name = name of attribute * * Return: 0 if not found, else 0-terminated string value */ const char * getattr(struct node *node, const char *name) { node = node->children; while (node) { if (node->type == NODE_ATTR) { struct attr *attr = (void *)node; if (!strcmp(attr->name, name)) return attr->value; } node = node->next; } return 0; } /*********************************************************************** * findchildelementwithnameattr : find child element with a name attribute * of a particular value * * Enter: node = element * name = name to find * * Return: 0 else child element with name attr of that value */ static struct node * findchildelementwithnameattr(struct node *node, const char *name) { node = node->children; while (node) { if (node->type == NODE_ELEMENT) { const char *s = getattr(node, "name"); if (s && !strcmp(s, name)) break; } node = node->next; } return node; } /*********************************************************************** * findreturntype : find Type parse node for return type * * Enter: node = Operation element * * Return: 0 if not found, else Type parse node for return type */ struct node * findreturntype(struct node *node) { return findchildelement(node, "Type"); } /*********************************************************************** * findparamidentifier : find identifier parse node for parameter * * Enter: node = Operation element * name = parameter name to find * * Return: 0 if not found, else node struct for parameter identifier */ struct node * findparamidentifier(struct node *node, const char *name) { node = findchildelement(node, "ArgumentList"); if (node) node = findchildelementwithnameattr(node, name); return node; } /*********************************************************************** * findthrowidentifier : find identifier parse node for exception name * * Enter: node = Operation element * name = exception name to find * * Return: 0 if not found, else node for Name element, child of Raises * or SetRaises */ struct node * findthrowidentifier(struct node *node, const char *name) { struct node *node2 = findchildelement(node, "Raises"); if (node2) node2 = findchildelementwithnameattr(node2, name); if (!node2) { node2 = findchildelement(node, "SetRaises"); if (node2) node2 = findchildelementwithnameattr(node2, name); } return node2; } /*********************************************************************** * outputid : output the id of a node */ static void outputid(struct node *node) { if (node->parent) outputid(node->parent); if (node->id) { fputs("::", stdout); printtext(node->id, strlen(node->id), 1); } } /*********************************************************************** * outputnode : output node and its children * * Enter: node = node to output, assumed to be an element * indent */ void outputnode(struct node *node, unsigned int indent) { struct element *element = (void *)node; struct node *child; int empty = 1; printf("%*s<%s", indent, "", element->name); child = element->n.children; while (child) { switch(child->type) { case NODE_ELEMENT: empty = 0; break; case NODE_ATTR: { struct attr *attr = (void *)child; printf(" %s=\"", attr->name); printtext(attr->value, strlen(attr->value), 1); printf("\""); } break; } child = child->next; } if (node->id) { printf(" id=\""); outputid(node); printf("\""); } if (!empty || node->comments || node->wsstart) { printf(">\n"); if (node->wsstart) { printf("%*s ", indent, ""); outputwidl(node); printf("\n"); } outputdescriptive(node, indent + 2); child = element->n.children; while (child) { switch(child->type) { case NODE_ELEMENT: outputnode(child, indent + 2); break; } child = child->next; } printf("%*s\n", indent, "", element->name); } else printf("/>\n"); }