1 /***********************************************************************
2 * $Id$
3 * Copyright 2009 Aplix Corporation. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 *
14 * Node-specific functions
15 ***********************************************************************/
16 #include <assert.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include "comment.h"
20 #include "lex.h"
21 #include "misc.h"
22 #include "node.h"
23 #include "process.h"
24
newelement(const char * name)25 struct node *newelement(const char *name) {
26 struct element *element = memalloc(sizeof(struct element));
27 element->n.type = NODE_ELEMENT;
28 element->name = name;
29 return &element->n;
30 }
31
newattr(const char * name,const char * val)32 struct node *newattr(const char *name, const char *val) {
33 struct attr *attr = memalloc(sizeof(struct attr));
34 attr->n.type = NODE_ATTR;
35 attr->name = name;
36 attr->value = val;
37 return &attr->n;
38 }
39
newattrlist(void)40 struct node *newattrlist(void) {
41 struct attrlist *attrlist = memalloc(sizeof(struct attrlist));
42 attrlist->n.type = NODE_ATTRLIST;
43 return &attrlist->n;
44 }
45
46 /***********************************************************************
47 * addnode : add node as child of another node
48 *
49 * Enter: parent node
50 * child node
51 *
52 * The children list is constructed backwards. This is fixed later with
53 * a call to reversechildren.
54 *
55 * If child is an attrlist, its children are added to parent and the
56 * attrlist is freed.
57 */
addnode(struct node * parent,struct node * child)58 void addnode(struct node *parent, struct node *child) {
59 if (!child) return;
60 if (child->type == NODE_ATTRLIST) {
61 /* Add the attrs in the attrlist to parent. */
62 struct node *child2;
63 reversechildren(child);
64 child2 = child->children;
65 memfree(child);
66 while (child2) {
67 struct node *next = child2->next;
68 addnode(parent, child2);
69 child2 = next;
70 }
71 } else {
72 child->next = parent->children;
73 parent->children = child;
74 child->parent = parent;
75 }
76 }
77
78 /***********************************************************************
79 * reversechildren : recursively reverse child lists
80 *
81 * Also sets parent field on each node.
82 */
reversechildren(struct node * node)83 void reversechildren(struct node *node) {
84 struct node *newlist = 0;
85 struct node *child = node->children;
86 while (child) {
87 struct node *next = child->next;
88 child->parent = node;
89 child->next = newlist;
90 newlist = child;
91 reversechildren(child);
92 child = next;
93 }
94 node->children = newlist;
95 }
96
97 /***********************************************************************
98 * nodeisempty : test if node is empty (has no children)
99 */
nodeisempty(struct node * node)100 int nodeisempty(struct node *node) { return !node->children; }
101
102 /***********************************************************************
103 * nodewalk : single step of depth last traversal of node tree
104 *
105 * Return: next node in walk, 0 if finished
106 */
nodewalk(struct node * node)107 struct node *nodewalk(struct node *node) {
108 if (node->children) return node->children;
109 if (node->next) return node->next;
110 do {
111 node = node->parent;
112 if (!node) return 0;
113 } while (!node->next);
114 return node->next;
115 }
116
117 /***********************************************************************
118 * findchildelement : find child element of a particular name
119 *
120 * Enter: node = element
121 * name = name to find
122 *
123 * Return: 0 else child element of that name
124 */
findchildelement(struct node * node,const char * name)125 static struct node *findchildelement(struct node *node, const char *name) {
126 node = node->children;
127 while (node) {
128 if (node->type == NODE_ELEMENT) {
129 struct element *element = (void *)node;
130 if (!strcmp(element->name, name)) break;
131 }
132 node = node->next;
133 }
134 return node;
135 }
136
137 /***********************************************************************
138 * getattr : get value of attribute
139 *
140 * Enter: node = element to find attribute in
141 * name = name of attribute
142 *
143 * Return: 0 if not found, else 0-terminated string value
144 */
getattr(struct node * node,const char * name)145 const char *getattr(struct node *node, const char *name) {
146 node = node->children;
147 while (node) {
148 if (node->type == NODE_ATTR) {
149 struct attr *attr = (void *)node;
150 if (!strcmp(attr->name, name)) return attr->value;
151 }
152 node = node->next;
153 }
154 return 0;
155 }
156
157 /***********************************************************************
158 * findchildelementwithnameattr : find child element with a name attribute
159 * of a particular value
160 *
161 * Enter: node = element
162 * name = name to find
163 *
164 * Return: 0 else child element with name attr of that value
165 */
findchildelementwithnameattr(struct node * node,const char * name)166 static struct node *findchildelementwithnameattr(struct node *node,
167 const char *name) {
168 node = node->children;
169 while (node) {
170 if (node->type == NODE_ELEMENT) {
171 const char *s = getattr(node, "name");
172 if (s && !strcmp(s, name)) break;
173 }
174 node = node->next;
175 }
176 return node;
177 }
178
179 /***********************************************************************
180 * findreturntype : find Type parse node for return type
181 *
182 * Enter: node = Operation element
183 *
184 * Return: 0 if not found, else Type parse node for return type
185 */
findreturntype(struct node * node)186 struct node *findreturntype(struct node *node) {
187 return findchildelement(node, "Type");
188 }
189
190 /***********************************************************************
191 * findparamidentifier : find identifier parse node for parameter
192 *
193 * Enter: node = Operation element
194 * name = parameter name to find
195 *
196 * Return: 0 if not found, else node struct for parameter identifier
197 */
findparamidentifier(struct node * node,const char * name)198 struct node *findparamidentifier(struct node *node, const char *name) {
199 node = findchildelement(node, "ArgumentList");
200 if (node) node = findchildelementwithnameattr(node, name);
201 return node;
202 }
203
204 /***********************************************************************
205 * findthrowidentifier : find identifier parse node for exception name
206 *
207 * Enter: node = Operation element
208 * name = exception name to find
209 *
210 * Return: 0 if not found, else node for Name element, child of Raises
211 * or SetRaises
212 */
findthrowidentifier(struct node * node,const char * name)213 struct node *findthrowidentifier(struct node *node, const char *name) {
214 struct node *node2 = findchildelement(node, "Raises");
215 if (node2) node2 = findchildelementwithnameattr(node2, name);
216 if (!node2) {
217 node2 = findchildelement(node, "SetRaises");
218 if (node2) node2 = findchildelementwithnameattr(node2, name);
219 }
220 return node2;
221 }
222
223 /***********************************************************************
224 * outputid : output the id of a node
225 */
outputid(struct node * node)226 static void outputid(struct node *node) {
227 if (node->parent) outputid(node->parent);
228 if (node->id) {
229 fputs("::", stdout);
230 printtext(node->id, strlen(node->id), 1);
231 }
232 }
233
234 /***********************************************************************
235 * outputnode : output node and its children
236 *
237 * Enter: node = node to output, assumed to be an element
238 * indent
239 */
outputnode(struct node * node,unsigned int indent)240 void outputnode(struct node *node, unsigned int indent) {
241 struct element *element = (void *)node;
242 struct node *child;
243 int empty = 1;
244 printf("%*s<%s", indent, "", element->name);
245 child = element->n.children;
246 while (child) {
247 switch (child->type) {
248 case NODE_ELEMENT:
249 empty = 0;
250 break;
251 case NODE_ATTR: {
252 struct attr *attr = (void *)child;
253 printf(" %s=\"", attr->name);
254 printtext(attr->value, strlen(attr->value), 1);
255 printf("\"");
256 } break;
257 }
258 child = child->next;
259 }
260 if (node->id) {
261 printf(" id=\"");
262 outputid(node);
263 printf("\"");
264 }
265 if (!empty || node->comments || node->wsstart) {
266 printf(">\n");
267 if (node->wsstart) {
268 printf("%*s <webidl>", indent, "");
269 outputwidl(node);
270 printf("</webidl>\n");
271 }
272 outputdescriptive(node, indent + 2);
273 child = element->n.children;
274 while (child) {
275 switch (child->type) {
276 case NODE_ELEMENT:
277 outputnode(child, indent + 2);
278 break;
279 }
280 child = child->next;
281 }
282 printf("%*s</%s>\n", indent, "", element->name);
283 } else
284 printf("/>\n");
285 }
286