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
25 struct node *
newelement(const char * name)26 newelement(const char *name)
27 {
28 struct element *element = memalloc(sizeof(struct element));
29 element->n.type = NODE_ELEMENT;
30 element->name = name;
31 return &element->n;
32 }
33
34 struct node *
newattr(const char * name,const char * val)35 newattr(const char *name, const char *val)
36 {
37 struct attr *attr = memalloc(sizeof(struct attr));
38 attr->n.type = NODE_ATTR;
39 attr->name = name;
40 attr->value = val;
41 return &attr->n;
42 }
43
44 struct node *
newattrlist(void)45 newattrlist(void)
46 {
47 struct attrlist *attrlist = memalloc(sizeof(struct attrlist));
48 attrlist->n.type = NODE_ATTRLIST;
49 return &attrlist->n;
50 }
51
52 /***********************************************************************
53 * addnode : add node as child of another node
54 *
55 * Enter: parent node
56 * child node
57 *
58 * The children list is constructed backwards. This is fixed later with
59 * a call to reversechildren.
60 *
61 * If child is an attrlist, its children are added to parent and the
62 * attrlist is freed.
63 */
64 void
addnode(struct node * parent,struct node * child)65 addnode(struct node *parent, struct node *child)
66 {
67 if (!child)
68 return;
69 if (child->type == NODE_ATTRLIST) {
70 /* Add the attrs in the attrlist to parent. */
71 struct node *child2;
72 reversechildren(child);
73 child2 = child->children;
74 memfree(child);
75 while (child2) {
76 struct node *next = child2->next;
77 addnode(parent, child2);
78 child2 = next;
79 }
80 } else {
81 child->next = parent->children;
82 parent->children = child;
83 child->parent = parent;
84 }
85 }
86
87 /***********************************************************************
88 * reversechildren : recursively reverse child lists
89 *
90 * Also sets parent field on each node.
91 */
92 void
reversechildren(struct node * node)93 reversechildren(struct node *node)
94 {
95 struct node *newlist = 0;
96 struct node *child = node->children;
97 while (child) {
98 struct node *next = child->next;
99 child->parent = node;
100 child->next = newlist;
101 newlist = child;
102 reversechildren(child);
103 child = next;
104 }
105 node->children = newlist;
106 }
107
108 /***********************************************************************
109 * nodeisempty : test if node is empty (has no children)
110 */
111 int
nodeisempty(struct node * node)112 nodeisempty(struct node *node)
113 {
114 return !node->children;
115 }
116
117 /***********************************************************************
118 * nodewalk : single step of depth last traversal of node tree
119 *
120 * Return: next node in walk, 0 if finished
121 */
122 struct node *
nodewalk(struct node * node)123 nodewalk(struct node *node)
124 {
125 if (node->children)
126 return node->children;
127 if (node->next)
128 return node->next;
129 do {
130 node = node->parent;
131 if (!node)
132 return 0;
133 } while (!node->next);
134 return node->next;
135 }
136
137 /***********************************************************************
138 * findchildelement : find child element of a particular name
139 *
140 * Enter: node = element
141 * name = name to find
142 *
143 * Return: 0 else child element of that name
144 */
145 static struct node *
findchildelement(struct node * node,const char * name)146 findchildelement(struct node *node, const char *name)
147 {
148 node = node->children;
149 while (node) {
150 if (node->type == NODE_ELEMENT) {
151 struct element *element = (void *)node;
152 if (!strcmp(element->name, name))
153 break;
154 }
155 node = node->next;
156 }
157 return node;
158 }
159
160 /***********************************************************************
161 * getattr : get value of attribute
162 *
163 * Enter: node = element to find attribute in
164 * name = name of attribute
165 *
166 * Return: 0 if not found, else 0-terminated string value
167 */
168 const char *
getattr(struct node * node,const char * name)169 getattr(struct node *node, const char *name)
170 {
171 node = node->children;
172 while (node) {
173 if (node->type == NODE_ATTR) {
174 struct attr *attr = (void *)node;
175 if (!strcmp(attr->name, name))
176 return attr->value;
177 }
178 node = node->next;
179 }
180 return 0;
181 }
182
183 /***********************************************************************
184 * findchildelementwithnameattr : find child element with a name attribute
185 * of a particular value
186 *
187 * Enter: node = element
188 * name = name to find
189 *
190 * Return: 0 else child element with name attr of that value
191 */
192 static struct node *
findchildelementwithnameattr(struct node * node,const char * name)193 findchildelementwithnameattr(struct node *node, const char *name)
194 {
195 node = node->children;
196 while (node) {
197 if (node->type == NODE_ELEMENT) {
198 const char *s = getattr(node, "name");
199 if (s && !strcmp(s, name))
200 break;
201 }
202 node = node->next;
203 }
204 return node;
205 }
206
207 /***********************************************************************
208 * findreturntype : find Type parse node for return type
209 *
210 * Enter: node = Operation element
211 *
212 * Return: 0 if not found, else Type parse node for return type
213 */
214 struct node *
findreturntype(struct node * node)215 findreturntype(struct node *node)
216 {
217 return findchildelement(node, "Type");
218 }
219
220 /***********************************************************************
221 * findparamidentifier : find identifier parse node for parameter
222 *
223 * Enter: node = Operation element
224 * name = parameter name to find
225 *
226 * Return: 0 if not found, else node struct for parameter identifier
227 */
228 struct node *
findparamidentifier(struct node * node,const char * name)229 findparamidentifier(struct node *node, const char *name)
230 {
231 node = findchildelement(node, "ArgumentList");
232 if (node)
233 node = findchildelementwithnameattr(node, name);
234 return node;
235 }
236
237 /***********************************************************************
238 * findthrowidentifier : find identifier parse node for exception name
239 *
240 * Enter: node = Operation element
241 * name = exception name to find
242 *
243 * Return: 0 if not found, else node for Name element, child of Raises
244 * or SetRaises
245 */
246 struct node *
findthrowidentifier(struct node * node,const char * name)247 findthrowidentifier(struct node *node, const char *name)
248 {
249 struct node *node2 = findchildelement(node, "Raises");
250 if (node2)
251 node2 = findchildelementwithnameattr(node2, name);
252 if (!node2) {
253 node2 = findchildelement(node, "SetRaises");
254 if (node2)
255 node2 = findchildelementwithnameattr(node2, name);
256 }
257 return node2;
258 }
259
260 /***********************************************************************
261 * outputid : output the id of a node
262 */
263 static void
outputid(struct node * node)264 outputid(struct node *node)
265 {
266 if (node->parent)
267 outputid(node->parent);
268 if (node->id) {
269 fputs("::", stdout);
270 printtext(node->id, strlen(node->id), 1);
271 }
272 }
273
274 /***********************************************************************
275 * outputnode : output node and its children
276 *
277 * Enter: node = node to output, assumed to be an element
278 * indent
279 */
280 void
outputnode(struct node * node,unsigned int indent)281 outputnode(struct node *node, unsigned int indent)
282 {
283 struct element *element = (void *)node;
284 struct node *child;
285 int empty = 1;
286 printf("%*s<%s", indent, "", element->name);
287 child = element->n.children;
288 while (child) {
289 switch(child->type) {
290 case NODE_ELEMENT:
291 empty = 0;
292 break;
293 case NODE_ATTR:
294 {
295 struct attr *attr = (void *)child;
296 printf(" %s=\"", attr->name);
297 printtext(attr->value, strlen(attr->value), 1);
298 printf("\"");
299 }
300 break;
301 }
302 child = child->next;
303 }
304 if (node->id) {
305 printf(" id=\"");
306 outputid(node);
307 printf("\"");
308 }
309 if (!empty || node->comments || node->wsstart) {
310 printf(">\n");
311 if (node->wsstart) {
312 printf("%*s <webidl>", indent, "");
313 outputwidl(node);
314 printf("</webidl>\n");
315 }
316 outputdescriptive(node, indent + 2);
317 child = element->n.children;
318 while (child) {
319 switch(child->type) {
320 case NODE_ELEMENT:
321 outputnode(child, indent + 2);
322 break;
323 }
324 child = child->next;
325 }
326 printf("%*s</%s>\n", indent, "", element->name);
327 } else
328 printf("/>\n");
329 }
330
331
332