1 /* sswf_node.c -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2009 */
2 
3 /*
4 
5 Copyright (c) 2002-2009 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 #define	SSWF_NEED_ASSERT
35 #include	"sswf.h"
36 
37 
38 
39 
40 
41 
42 /* TODO: create an array of nodes we can allocate very quickly from */
43 
44 
45 /* a global list of all the objects we find while parsing all the source files */
46 static	struct node_t *		all_objects;
47 
48 
49 /* allocate a node */
node_init(struct node_t * n,enum node_type_t type,enum node_type_t sub_type)50 struct node_t *node_init(struct node_t *n, enum node_type_t type, enum node_type_t sub_type)
51 {
52 	const char	*filename;
53 	unsigned long	line;
54 
55 	if(n != NULL) {
56 		filename = n->filename;
57 		line = n->line;
58 		memset(n, 0, sizeof(struct node_t));
59 		n->line = line;
60 		n->filename = filename;
61 
62 		n->type = type;
63 		n->sub_type = sub_type;
64 		n->head = n;
65 		n->tail = n;
66 
67 #if DEBUG
68 		n->serial = 0;
69 
70 /*printf("*** Initialized node 0x%08lX\n", (long) n);*/
71 #endif
72 	}
73 
74 	return n;
75 }
76 
77 
node_alloc(enum node_type_t type,enum node_type_t sub_type,unsigned long line)78 struct node_t *node_alloc(enum node_type_t type, enum node_type_t sub_type, unsigned long line)
79 {
80 	struct node_t	*n;
81 
82 	n = sswf_malloc(sizeof(struct node_t), "node_alloc()");
83 
84 	/*
85 	 * At the time the node is allocated we are certainly working
86 	 * on a file and we save that info in that node - we also
87 	 * save the line # specified by the caller; note that the
88 	 * init won't modify these info later.
89 	 */
90 	n->filename = lex_filename;
91 	n->line = line;
92 
93 	return node_init(n, type, sub_type);
94 }
95 
96 
97 
node_unparent(struct node_t * p,struct node_t * n,struct node_t * h)98 void node_unparent(struct node_t *p, struct node_t *n, struct node_t *h)
99 {
100 	int		idx, pos;
101 
102 	/* if we have a parent node, we need to unlink ourself from there too */
103 	if(p != NULL /* && n->previous == NULL */ ) {
104 		/*
105 		 * note that only head nodes should be unlinked from their parent
106 		 * node since none other should be linked there!
107 		 */
108 		if(p->left == n) {
109 #if DEBUG
110 if(debug_memory > 5) printf("    Left 0x%08lX, header 0x%08lX\n", (long) p->left, (long) h);
111 #endif
112 			p->left = h;
113 		}
114 		if(p->right == n) {
115 #if DEBUG
116 if(debug_memory > 5) printf("    Right 0x%08lX, header 0x%08lX\n", (long) p->right, (long) h);
117 #endif
118 			p->right = h;
119 		}
120 		if(p->select == n) {
121 #if DEBUG
122 if(debug_memory > 5) printf("    Select 0x%08lX, header 0x%08lX\n", (long) p->select, (long) h);
123 #endif
124 			p->select = h;
125 		}
126 		if(p->list != NULL) {
127 			idx = p->cnt;
128 #if DEBUG
129 if(debug_memory > 5) printf("    List with %d items, header 0x%08lX\n", idx, (long) h);
130 #endif
131 			while(idx > 0) {
132 				idx--;
133 				if(p->list[idx] == n) {
134 					/*
135 					 * we must make sure that the
136 					 * header isn't already present
137 					 * in the list, if it is, we just
138 					 * remove 'n' instead of replacing
139 					 * 'n' by 'h'!
140 					 */
141 					pos = p->cnt;
142 					while(pos > 0) {
143 						pos--;
144 						if(p->list[pos] == h) {
145 							h = NULL;
146 							break;
147 						}
148 					}
149 					if(h != NULL) {		/* other node(s) there? */
150 						p->list[idx] = h;
151 #if 0 && DEBUG
152 if(debug_memory > 15) printf("        replaced at position %d (0x%08lX)\n", idx, (long) h);
153 #endif
154 					}
155 					else {
156 						p->cnt--;
157 #if 0 && DEBUG
158 if(debug_memory > 15) printf("        removed from position %d\n", idx);
159 #endif
160 						if(idx < p->cnt) {		/* anything needs to be moved? */
161 							/* move the following pointers down by one entry */
162 							memmove(p->list + idx, p->list + idx + 1,
163 								(p->cnt - idx) * sizeof(struct node_t *));
164 						}
165 					}
166 					/* there should be only one reference... */
167 					break;
168 				}
169 			}
170 		}
171 	}
172 }
173 
174 
175 #if 0
176 void node_reparent(struct node_t *n, struct node_t *p)
177 {
178 	if(n == NULL) {
179 		return;
180 	}
181 
182 	assert(n->previous == NULL, "can't reparent a node which isn't a head node");
183 	node_unparent(n->parent, n, NULL);
184 
185 	do {
186 		n->parent = p;
187 		n = n->next;
188 	} while(n != NULL);
189 }
190 #endif
191 
192 
node_unlink(struct node_t * n)193 void node_unlink(struct node_t *n)
194 {
195 	struct node_t	*q, *h;
196 
197 	if(n == NULL) {
198 		return;
199 	}
200 
201 #if 0 && DEBUG
202 if(debug_memory > 14) {
203 	char		*path;
204 	int		idx;
205 
206 	q = n;
207 	while(q->previous != NULL) q = q->previous;
208 	idx = 0;
209 	while(q != NULL) idx++, q = q->next;
210 	path = node_path(n, 1);
211 	printf("+++ Found %d nodes on \"%s\"\n", idx, path);
212 	sswf_free(path);
213 }
214 #endif
215 
216 	/* are we unlinking the head? */
217 	if(n->previous == NULL) {
218 		q = h = n->next;
219 		while(q != NULL) {
220 			q->head = h;
221 			q = q->next;
222 		}
223 	}
224 	else {
225 		h = n->head;
226 		n->previous->next = n->next;
227 	}
228 
229 	/* are we unlinking the tail? */
230 	if(n->next == NULL) {
231 		q = n->previous;
232 		if(q != NULL) {
233 			q->next = NULL;
234 			while(q != NULL) {
235 				q->tail = n->previous;
236 				q = q->previous;
237 			}
238 		}
239 	}
240 	else {
241 		n->next->previous = n->previous;
242 	}
243 
244 	node_unparent(n->parent,  n, h);
245 	node_unparent(n->parent2, n, h);
246 
247 	/* reset the pointers */
248 	n->head     = n;
249 	n->tail     = n;
250 	n->parent   = NULL;
251 	n->parent2  = NULL;
252 	n->next     = NULL;
253 	n->previous = NULL;
254 }
255 
256 
257 /* free all the data defined in a node including sub-nodes
258  * please, keep sub-nodes and put NULL instead if you wish
259  * to keep some of the sub-nodes.
260  */
node_clean(struct node_t * n,const char * spaces)261 void node_clean(struct node_t *n, const char *spaces)
262 {
263 	if(n == NULL) {
264 		return;
265 	}
266 #if DEBUG
267 if(debug_memory > 0 && spaces == NULL) spaces = "";
268 #endif
269 
270 /* remove myself from my parent so it doesn't point to me anymore */
271 	node_unlink(n);
272 
273 #if 0
274 /* the following was put in the node_unlink() entry */
275 	p = n->parent;
276 	if(p != NULL) {
277 		/* if we are in our parent we are the head, so just put the "new" head there (i.e. the next node) */
278 		if(p->left == n) {
279 			p->left = n->next;
280 		}
281 		if(p->right == n) {
282 			p->right = n->next;
283 		}
284 		if(p->select == n) {
285 			p->select = n->next;
286 		}
287 		/* should we also do that in the p->list? probably! */
288 		if(p->list != NULL) {
289 			idx = p->cnt;
290 			while(idx > 0) {
291 				idx--;
292 				if(p->list[idx] == n) {
293 					if(n->next != NULL) {
294 						p->list[idx] = n->next;
295 					}
296 					else {
297 						p->cnt--;
298 						if(idx < p->cnt) {		/* anything needs to be moved? */
299 							/* move the following pointers down by one entry */
300 							memmove(p->list + idx, p->list + idx + 1,
301 								(p->cnt - idx) * sizeof(struct node_t *));
302 						}
303 					}
304 					break;
305 				}
306 			}
307 		}
308 	}
309 	/* unlink! */
310 	if(n->next != NULL) {
311 		n->next->previous = n->previous;
312 	}
313 	else if(n->previous != NULL) {
314 		/* Ha! The tail is changing */
315 		l = n->previous;
316 		l->next = NULL;
317 		while(l != NULL) {
318 			l->tail = n->previous;
319 			l = l->previous;
320 		}
321 	}
322 	if(n->previous != NULL) {
323 		n->previous->next = n->next;
324 	}
325 	else if(n->next != NULL) {
326 		/* Ha! The head is changing! */
327 		l = n->next;
328 		l->previous = NULL;
329 		while(l != NULL) {
330 			l->tail = n->tail;
331 			l->head = n->next;
332 			l = l->next;
333 		}
334 	}
335 #endif
336 
337 /* remove the string & data if there are any */
338 	if(n->string != NULL) {
339 #if DEBUG
340 if(debug_memory > 2) {
341 printf("%s*** Free string 0x%08lX\n", spaces, (long) n->string);
342 printf("%s*** The string to be freed is [%s]\n", spaces, n->string);
343 }
344 #endif
345 		sswf_clean(&n->string);
346 	}
347 	if(n->data != NULL) {
348 #if DEBUG
349 if(debug_memory > 2) printf("%s*** Free data 0x%08lX\n", spaces, (long) n->data);
350 #endif
351 		sswf_clean(&n->data);
352 	}
353 
354 /* free all of our children -- we expect that all children were allocated */
355 	if((n->flags & NODE_FLAG_SOFTLINK) == 0) {
356 		/* this is not a reference, so do really delete chidren */
357 		while(n->left != NULL) {
358 #if DEBUG
359 if(debug_memory > 2) printf("%s*** Free left 0x%08lX (parent: 0x%08lX)\n", spaces, (long) n->left, (long) n->left->parent);
360 #endif
361 			assert(n->left->parent == n, "one of my left children doesn't have me as parent");
362 			node_free(n->left);
363 		}
364 		while(n->right != NULL) {
365 #if DEBUG
366 if(debug_memory > 2) printf("%s*** Free right 0x%08lX (parent: 0x%08lX)\n", spaces, (long) n->right, (long) n->right->parent);
367 #endif
368 			assert(n->right->parent == n, "one of my right children doesn't have me as parent");
369 			node_free(n->right);
370 		}
371 		while(n->select != NULL) {
372 #if DEBUG
373 if(debug_memory > 2) printf("%s*** Free select 0x%08lX (parent: 0x%08lX)\n", spaces, (long) n->select, (long) n->select->parent);
374 #endif
375 			assert(n->select->parent == n, "one of my select children doesn't have me as parent");
376 			node_free(n->select);
377 		}
378 		if(n->list != NULL) {
379 			while(n->cnt > 0) {
380 #if DEBUG
381 if(debug_memory > 2) printf("%s*** Free list item 0x%08lX from 0x%08lX (parent: 0x%08lX/0x%08lX)\n",
382 		spaces, (long) n->list[n->cnt - 1],
383 		(long) n,
384 		(long) n->list[n->cnt - 1]->parent,
385 		(long) n->list[n->cnt - 1]->parent2);
386 #endif
387 				assert(n->list[n->cnt - 1]->parent == n, "one of my list children doesn't have me as parent");
388 				node_free(n->list[n->cnt - 1]);
389 			}
390 			sswf_clean(&n->list);
391 		}
392 	}
393 
394 #if DEBUG
395 	/*
396 	 * We do that to make sure we're not re-using the same structure after it was cleaned up.
397 	 * It is useless if not in DEBUG mode
398 	 */
399 	memset(n, 0xAB, sizeof(struct node_t));
400 #endif
401 }
402 
403 
node_free(struct node_t * n)404 void node_free(struct node_t *n)
405 {
406 	if(n != NULL) {
407 #if DEBUG
408 if(debug_memory > 0) {
409 		static long	indent = 0;
410 		char		spaces[256];
411 		long		max;
412 
413 		max = indent > sizeof(spaces) - 1 ? sizeof(spaces) - 1 : indent;
414 		memset(spaces, ' ', max);
415 		spaces[max] = '\0';
416 		if(debug_memory > 1) {
417 			printf("%s*** Freeing node 0x%08lX\n", spaces, (long) n);
418 		}
419 		indent += 2;
420 		node_clean(n, spaces);
421 		indent -= 2;
422 		if(debug_memory > 1) {
423 			printf("%s*** Node 0x%08lX freed\n", spaces, (long) n);
424 		}
425 		sswf_free(n);
426 		return;
427 }
428 #endif
429 		node_clean(n, 0);
430 		sswf_free(n);
431 	}
432 }
433 
434 
node_free_list(struct node_t * node)435 void node_free_list(struct node_t *node)
436 {
437 	if(node != NULL) {
438 		while(node->previous != NULL) {
439 			node_free(node->previous);
440 		}
441 		while(node->next != NULL) {
442 			node_free(node->next);
443 		}
444 		node_free(node);
445 	}
446 }
447 
448 
node_link_tail(struct node_t * p,struct node_t * q)449 void node_link_tail(struct node_t *p, struct node_t *q)
450 {
451 	assert(p != NULL, "invalid node pointer to node_link_tail()");
452 
453 	/* anything to link? */
454 	if(q == NULL) {
455 		return;
456 	}
457 	/* we could also do q = q->head maybe? */
458 	assert(q->head == q && q->previous == NULL, "invalid 'q' node in node_link_tail() - not the head");
459 
460 	/* quick link - watch out, only the head has a proper tail definition! */
461 	p = p->head;
462 	p->tail->next = q;
463 	q->previous = p->tail;
464 	p->tail = q->tail;		/* q may be a list too */
465 
466 	/* we've got a new head now */
467 	while(q != NULL) {
468 		q->head = p;
469 		q = q->next;
470 	}
471 }
472 
473 
474 
475 /* while parsing the source we must link all the objects in one large global list
476  * later we place these objects where they belong so we can search for them
477  */
node_link_object(struct node_t * object)478 void node_link_object(struct node_t *object)
479 {
480 	if(all_objects == NULL) {
481 		/*lex_filename = "*object link node*"; -- use whatever is current... */
482 		all_objects = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_LIST, 0);
483 
484 #if 0 && DEBUG
485 printf("The 'all objects' list is at: 0x%08lX\n", (unsigned long) all_objects);
486 #endif
487 
488 		/*
489 		 * just in case, we name this object so we can easilly
490 		 * recognize it in the debug output
491 		 */
492 		all_objects->left = node_alloc(NODE_TYPE_STRING, NODE_SUBTYPE_UNKNOWN, 0);
493 		all_objects->left->string = "objects";
494 		all_objects->left->parent = all_objects;
495 	}
496 
497 	node_link_list(all_objects, object);
498 }
499 
500 
node_done_object(void)501 void node_done_object(void)
502 {
503 	/* when this is called, we're done with all the objects
504 	 * thus we can remove the all_objects node.
505 	 * Note that the list is "emptied" here since the nodes
506 	 * present in that list are not children of the all_objects
507 	 * node (and also they should already have been freed).
508 	 */
509 	all_objects->cnt = 0;			/* empty list */
510 	all_objects->left->string = NULL;	/* remove static string pointer */
511 	node_free(all_objects);
512 	all_objects = NULL;
513 }
514 
515 
516 
517 
node_link_parent(struct node_t * parent,struct node_t * child)518 void node_link_parent(struct node_t *parent, struct node_t *child)
519 {
520 	assert(child == NULL || child->previous == NULL, "node_link_parent() called with a child which isn't the header");
521 	while(child != NULL) {
522 		assert(child->parent == NULL, "parenting a child which already has a parent (new: 0x%08lX, old: 0x%08lX)",
523 					(long) parent, (long) child->parent);
524 		child->parent = parent;
525 		child = child->next;
526 	}
527 }
528 
529 
530 #if 0
531 void node_link_parent2(struct node_t *parent2, struct node_t *child)
532 {
533 	assert(child->previous == NULL, "node_link_parent2() called with a child which isn't the header");
534 	while(child != NULL) {
535 		child->parent2 = parent2;
536 		child = child->next;
537 	}
538 }
539 #endif
540 
541 
node_link_list(struct node_t * list,struct node_t * item)542 void node_link_list(struct node_t *list, struct node_t *item)
543 {
544 	assert((list->flags & NODE_FLAG_SOFTLINK) == 0, "can't link in the list of a softlink node");
545 
546 	if(list->list == NULL) {
547 		list->max = 0;
548 		list->cnt = 0;
549 	}
550 	if(list->cnt >= list->max || list->list == NULL) {
551 		list->max += 256;
552 		list->list = sswf_remalloc(list->list, list->max * sizeof(struct node_t *), "node_link_list() - enlarge");
553 	}
554 
555 	/* should we have item->parent = list ? */
556 	/* Answer:
557 	 * at this time that would break the parents of objects
558 	 * put in the all_objects list
559 	 */
560 
561 	list->list[list->cnt] = item;
562 	list->cnt++;
563 }
564 
565 
node_append_list(struct node_t * list,struct node_t * add)566 void node_append_list(struct node_t *list, struct node_t *add)
567 {
568 	long		cnt;
569 
570 	assert((list->flags & NODE_FLAG_SOFTLINK) == 0, "can't link in the list of a softlink node");
571 
572 	if(add == NULL) {
573 		return;
574 	}
575 
576 	/* anything to happen? */
577 	if(add->list == NULL) {
578 		return;
579 	}
580 
581 	if(list->list == NULL) {
582 		list->max = 0;
583 		list->cnt = 0;
584 	}
585 
586 	cnt = list->cnt + add->cnt;
587 	if(cnt > list->max) {
588 		list->max = (cnt + 255) & -256;
589 		list->list = sswf_remalloc(list->list, list->max * sizeof(struct node_t *), "node_append_list() - enlarge");
590 	}
591 
592 	memcpy(list->list + list->cnt, add->list, add->cnt * sizeof(struct node_t *));
593 	list->cnt = cnt;
594 }
595 
596 
597 
node_search_list(struct node_t * obj,const char * name)598 struct node_t *node_search_list(struct node_t *obj, const char *name)
599 {
600 	struct node_t	*o;
601 	int		idx;
602 
603 	if(obj->list != NULL) {
604 		idx = obj->cnt;
605 		while(idx > 0) {
606 			idx--;
607 			assert(obj->list[idx]->type == NODE_TYPE_OBJECT, "an object in a list of objects within an object is not an object");
608 			o = obj->list[idx]->left;
609 			if(o != NULL) {		/* named object at least? */
610 
611 /*printf("    compare [%s] vs [%s]\n", o->string, name); fflush(stdout);*/
612 
613 				if(strcasecmp(o->string, name) == 0) {
614 					/* we found it! */
615 					return obj->list[idx];
616 				}
617 			}
618 		}
619 	}
620 
621 	return NULL;
622 }
623 
624 
625 
node_find_object(struct node_t * obj,const char * name)626 struct node_t *node_find_object(struct node_t *obj, const char *name)
627 {
628 	struct node_t	*r;
629 
630 	/* find an object with a specific name */
631 	while(obj != NULL) {
632 		if(obj->type == NODE_TYPE_OBJECT) {
633 			r = node_search_list(obj, name);
634 			if(r != NULL) {
635 				return r;
636 			}
637 		}
638 		obj = obj->parent;
639 	}
640 
641 	/* can't find it! */
642 	return NULL;
643 }
644 
645 
646 
node_find_block(struct node_t * expr)647 struct node_t *node_find_block(struct node_t *expr)
648 {
649 	while(expr != NULL) {
650 		if(expr->type == NODE_TYPE_OBJECT) {
651 			return expr;
652 		}
653 		expr = expr->parent;
654 	}
655 
656 	return NULL;
657 }
658 
659 
node_path(struct node_t * n,int include_empty)660 char *node_path(struct node_t *n, int include_empty)
661 {
662 	char		*path, *s;
663 	const char	*name;
664 
665 	path = NULL;
666 	while(n != NULL) {
667 		if(n->left != NULL && n->left->string != NULL && *n->left->string != '\0') {
668 			name = n->left->string;
669 		}
670 		else if(n->data != NULL && n->data->label != NULL && *n->data->label != '\0') {
671 			name = n->data->label;
672 		}
673 		else if(include_empty) {
674 			name = "<no name>";
675 		}
676 		else {
677 			name = NULL;
678 		}
679 		if(name != NULL) {
680 			/* except for the first time, add a field separator */
681 			if(path != NULL) {
682 				s = sswf_strcat3(name, ".", path);
683 			}
684 			else {
685 				s = sswf_strcat(name, path);
686 			}
687 			sswf_free(path);
688 			path = s;
689 		}
690 		n = n->parent;
691 	}
692 
693 	return path;
694 }
695 
696 
697 /* which is one of NODE_UNIT_... */
698 /* TODO: in order to know which unit to use we need to have
699  * the destination field! that means we can't compute anything
700  * until we know what to do with the final value!
701  * I think we will forget about the units at this time...
702  */
node_find_unit(struct node_t * n,long which)703 enum node_type_t node_find_unit(struct node_t *n, long which)
704 {
705 	static enum node_type_t def_units[NODE_UNIT_MAX] = {
706 		/* angle */	NODE_SUBTYPE_RAD,
707 		/* boolean */	NODE_SUBTYPE_OTHER,
708 		/* color */	NODE_SUBTYPE_FC,
709 		/* ratio */	NODE_SUBTYPE_RT,
710 		/* size */	NODE_SUBTYPE_PX,
711 		/* speed */	NODE_SUBTYPE_FPS,
712 		/* time */	NODE_SUBTYPE_SEC
713 	};
714 
715 	while(n != NULL) {
716 		if(n->unit[which] >= NODE_TYPE_UNIT) {
717 			return n->unit[which];
718 		}
719 		n = n->next;
720 	}
721 
722 	return def_units[which];
723 }
724 
725 
link_sub_object(struct node_t * p,struct node_t * obj)726 void link_sub_object(struct node_t *p, struct node_t *obj)
727 {
728 	struct node_t	**o, *same, *sub_item;
729 	int		idx /*, cnt*/;
730 	char		*on, *sn;
731 
732 /* Unnamed objects are simply linked as is... */
733 	if(obj->left == NULL) {
734 		node_link_list(p, obj);
735 		assert(obj->parent2 == NULL, "parent2 defined twice");
736 		obj->parent2 = p;
737 		return;
738 	}
739 
740 /*
741  * When there is a name we MUST check for another object named the same way.
742  *
743  * At this time, only lists and actions can bear the same name (lists are
744  * merged and actions are named after what they do, so in the latter it's
745  * not really a name).
746  */
747 	same = node_search_list(p, obj->left->string);
748 	if(same == NULL) {
749 		/* first object with this name, just link it as is */
750 		node_link_list(p, obj);
751 		assert(obj->parent2 == NULL, "parent2 defined twice");
752 		obj->parent2 = p;
753 		return;
754 	}
755 
756 /* if both are actions, simply link them one after another, that's fine */
757 	if(same->sub_type == NODE_SUBTYPE_ACTION
758 	&& obj->sub_type == NODE_SUBTYPE_ACTION) {
759 		node_link_list(p, obj);
760 		assert(obj->parent2 == NULL, "parent2 defined twice");
761 		obj->parent2 = p;
762 		return;
763 	}
764 
765 /* check if we have lists, if not, generate an error and ignore this 2nd definition */
766 	if(same->sub_type != NODE_SUBTYPE_LIST
767 	|| obj->sub_type != NODE_SUBTYPE_LIST) {
768 		on = node_path(obj, 0);
769 		sn = node_path(same, 0);
770 fprintf(stderr, "ERROR at line #%ld in file \"%s\": two objects (which are not both lists nor actions) are named the same (\"%s\" and \"%s\", 1st instance at line #%ld in file \"%s\").\n",
771 				obj->line, obj->filename,
772 				on, sn,
773 				same->line, same->filename);
774 		sswf_free(on);
775 		sswf_free(sn);
776 		errcnt++;
777 		return;
778 	}
779 
780 	assert(same->right != NULL, "no definition in a list -- we can't merge anything here");
781 
782 /* merge lists silently (thus we can have libraries type of things!) */
783 	/*
784 	 * Watch out! the lists may have multiple levels with the same name!!!
785 	 * (such as sswf.fnt.<name1> and sswf.fnt.<name2>)
786 	 * We have to append <name2> to sswf.fnt instead of the sswf.fnt(.<name2>)
787 	 * to the 1st sswf list!!!
788 	 */
789 #if 0
790 fprintf(stderr, "merging two lists named \"%s\" and \"%s\" now.\n",
791 		obj->left->string, same->left->string);
792 #endif
793 
794 	/* first make sure the units are exactly the same (or set to "default"?!?) */
795 	for(idx = 0; idx < NODE_UNIT_MAX; idx++) {
796 		if(same->unit[idx] != obj->unit[idx]
797 		/*&& same->unit[idx] != 0 && obj->unit[idx] != 0*/) {
798 			on = node_path(obj, 0);
799 			sn = node_path(same, 0);
800 fprintf(stderr, "ERROR at line #%ld in file \"%s\": can't merge the two lists named \"%s\" and \"%s\" since they use different units (1st list at line #%ld in file \"%s\").\n",
801 					obj->line, obj->filename,
802 					on, sn,
803 					same->line, same->filename);
804 			sswf_free(on);
805 			sswf_free(sn);
806 			errcnt++;
807 			return;
808 		}
809 	}
810 
811 #if 0
812 printf("------------------------------ MERGING LISTS\n");
813 if(0) {
814 extern struct node_t *top_object;
815 node_print(top_object);
816 }
817 #endif
818 
819 #if DEBUG
820 {
821 	struct node_t		**data;
822 	struct node_t		*last;
823 
824 	data = obj->list;
825 	last = NULL;
826 #endif
827 	//for(o = obj->list, cnt = obj->cnt; cnt > 0; cnt--, o++) {
828 	o = obj->list;
829 	idx = 0;
830 	while(idx < obj->cnt) {
831 
832 #if 0
833 {
834 char *on, *l1, *l2, *r;
835 on = node_path(o[idx], 1);
836 l1 = node_path(o[idx]->parent, 1);
837 l2 = node_path(o[idx]->parent2, 1);
838 r = node_path(obj, 1);
839 printf("0x%08lX [%s]: Linking lists [%s] (parent: 0x%08lX \"%s\" and 0x%08lX \"%s\", should be 0x%08lX \"%s\")\n",
840 		(long) o[idx], on,
841 		obj->left->string,
842 		(long) o[idx]->parent, l1,
843 		(long) o[idx]->parent2, l2,
844 		(long) obj, r);
845 sswf_free(on);
846 sswf_free(l1);
847 sswf_free(l2);
848 sswf_free(r);
849 }
850 assert(last != o[idx], "last object still in the list");
851 last = o[idx];
852 #endif
853 
854 		assert(o[idx]->parent == obj || o[idx]->parent2 == obj,
855 			"a child object doesn't have the proper parent (while merging lists)");
856 
857 		/* is this item (to be inserted) duplicated in the "same" list? */
858 		if(o[idx]->left != NULL) {
859 #if 0
860 { char *a, *b; a = node_path(o[idx], 1); b = node_path(same, 1);
861 printf("  Compare items [%s] & [(%s)]\n", a, b);
862 }
863 #endif
864 			sub_item = node_search_list(same, o[idx]->left->string);
865 			if(sub_item != NULL) {
866 				/*
867 				 * When duplicated, we have better to call
868 				 * this function recursively
869 				 */
870 				link_sub_object(same, o[idx]);
871 #if DEBUG
872 				assert(data == obj->list, "the obj->list pointer changed when we called the link_sub_object() function recursively");
873 #endif
874 				/* here we can't unlink o[idx]
875 				 * instead we increment idx */
876 				idx++;
877 				continue;
878 			}
879 		}
880 
881 		/* if there is no name or no duplicates, link the sub-object as is in this list */
882 #if 0
883 { char *a, *b; a = node_path(o[idx], 1); b = node_path(same, 1);
884 printf("  Appending item [%s] in [(%s)]\n", a, b);
885 }
886 #endif
887 		node_unlink(o[idx]);
888 		o[idx]->parent = same->right;
889 		if(same->right->right == NULL) {
890 			same->right->right = o[idx];
891 		}
892 		else {
893 			node_link_tail(same->right->right, o[idx]);
894 		}
895 		node_link_list(same, o[idx]);
896 		o[idx]->parent2 = same;
897 	}
898 #if DEBUG
899 }
900 #endif
901 
902 #if 0
903 	/* this is code from the old days... */
904 	if(obj != NULL) {
905 		sub_item = same;	/* avoid warnings */
906 		/* First link the objects (really necessary?!) */
907 		/* This was turned off and everything still worked.
908 		 * However, with multiple lists levels it could be
909 		 * that it would be necessary...
910 		if(same->right == NULL) {
911 			same->right = obj->right;
912 		}
913 		else {
914 			node_link_tail(same->right, obj->right);
915 		}
916 		*/
917 		/*
918 		 * Append items of 2nd list to 1st
919 		 * and now we can forget about the 1st list
920 		 */
921 		node_append_list(same, obj);
922 	}
923 #endif
924 
925 	return;
926 }
927 
928 
929 /*
930  * Call this function once all the parsing of the source files is done, it will
931  * re-organize the objects properly.
932  */
node_setup_objects(void)933 int node_setup_objects(void)
934 {
935 	struct node_t		**o , *obj, *p;
936 	int			cnt;
937 
938 	if(all_objects == NULL) {
939 		fprintf(stderr, "ERROR: no object found. There is nothing we can do with this script.\n");
940 		return -1;
941 	}
942 
943 	o = all_objects->list;
944 	cnt = all_objects->cnt;
945 	while(cnt > 0) {
946 		cnt--;
947 		obj = p = *o++;
948 
949 #if 0
950 printf("Parent object [%s]\n", obj->left == NULL ? "<noname>" : obj->left->string);
951 #endif
952 
953 		for(;;) {
954 			p = p->parent;
955 			assert(p != NULL, "found an object without a parent object");
956 			if(p->type == NODE_TYPE_OBJECT) {
957 				/*
958 				 * put the object 'obj' in the parent 'p' as
959 				 * required (i.e. lists and actions are special cases)
960 				 */
961 				link_sub_object(p, obj);
962 				break;
963 			}
964 		}
965 	}
966 
967 #if 0 && DEBUG
968 	node_print(all_objects);
969 #endif
970 
971 	return 0;
972 }
973 
974 
975 
976 
977 #if DEBUG
978 /*
979  * Use the following function in order to print out the complete
980  * tree of node from any given node.
981  */
982 static unsigned long		print_serial;
983 
984 static void node_print_all(struct node_t *n, long indent);
node_print_info(struct node_t * n,long indent)985 static void node_print_info(struct node_t *n, long indent)
986 {
987 	char		spaces[256], *nn;
988 	int		idx;
989 
990 	if(n == NULL) {
991 		return;
992 	}
993 	if(n->serial == print_serial) {
994 		fflush(stdout);
995 		fprintf(stderr, "WARNING: node 0x%08lX printed twice.\n", (long) n);
996 		return;
997 	}
998 	n->serial = print_serial;
999 
1000 	sprintf(spaces, "0x%08lX  ", (long) n);
1001 	if(indent > sizeof(spaces) - 2 - 12) {
1002 		indent = sizeof(spaces) - 1 - 12;
1003 	}
1004 	memset(spaces + 12, ' ', indent);
1005 	spaces[indent + 12] = '\0';
1006 
1007 	/* print info about this node */
1008 	nn = node_path(n, 1);
1009 	printf("%sNode 0x%08lX: \"%s\" (From \"%s\" at line #%ld)\n",
1010 				spaces,
1011 				(long) n, nn,
1012 				n->filename, n->line);
1013 	sswf_free(nn);
1014 	printf("%sParent: 0x%08lX/0x%08lX, head: 0x%08lX, tail: 0x%08lX, next: 0x%08lX, previous: 0x%08lX\n",
1015 				spaces,
1016 				(long) n->parent, (long) n->parent2,
1017 				(long) n->head, (long) n->tail,
1018 				(long) n->next, (long) n->previous);
1019 	printf("%sType: %s (%d), sub-type: %s (%d), data: 0x%08lX\n", spaces,
1020 				node_type_names[n->type].name, n->type,
1021 				node_type_names[n->sub_type].name, n->sub_type,
1022 				(long) n->data);
1023 	if(n->string != NULL) {
1024 		printf("%sString: [%s]\n", spaces, n->string);
1025 	}
1026 	switch(n->type) {
1027 	case NODE_TYPE_INTEGER:
1028 		printf("%sInteger: %ld\n", spaces, n->integer);
1029 		break;
1030 
1031 	case NODE_TYPE_RANGE_INTEGER:
1032 		printf("%sInteger: %ld..%ld\n", spaces, n->integer, n->integer2);
1033 		break;
1034 
1035 	case NODE_TYPE_FLOAT:
1036 		printf("%sFloat: %g\n", spaces, n->floating_point);
1037 		break;
1038 
1039 	case NODE_TYPE_RANGE_FLOAT:
1040 		printf("%sFloat: %g..%g\n", spaces, n->floating_point, n->floating_point2);
1041 		break;
1042 
1043 	default:
1044 		/* other types are too complex or a bit useless to print out */
1045 		break;
1046 
1047 	}
1048 
1049 	if(n->left != NULL) {
1050 		if(n->left->parent != n
1051 		&& n->left->parent2 != n) {
1052 			printf("WARNING: no valid parent for the Left node.\n");
1053 		}
1054 		printf("%sLeft:\n", spaces);
1055 		node_print_all(n->left,   indent + 2);
1056 	}
1057 	if(n->right != NULL) {
1058 		if(n->right->parent != n
1059 		&& n->right->parent2 != n) {
1060 			printf("WARNING: no valid parent for the Right node.\n");
1061 		}
1062 		printf("%sRight:\n", spaces);
1063 		node_print_all(n->right,  indent + 2);
1064 	}
1065 	if(n->select != NULL) {
1066 		if(n->select->parent != n
1067 		&& n->select->parent2 != n) {
1068 			printf("WARNING: no valid parent for the Select node.\n");
1069 		}
1070 		printf("%sSelect:\n", spaces);
1071 		node_print_all(n->select, indent + 2);
1072 	}
1073 
1074 	/* now, if there is a list, print it out */
1075 	if(n->list != NULL) {
1076 		printf("%sList with %ld items: (only items which weren't listed before will be here)\n", spaces, n->cnt);
1077 		for(idx = 0; idx < n->cnt; idx++) {
1078 			if(n->list[idx]->parent != n
1079 			&& n->list[idx]->parent2 != n) {
1080 				printf("WARNING: no valid parent for the following List item.\n");
1081 			}
1082 			if(n->list[idx]->serial == print_serial) {
1083 				printf("%s  o Item #%d (0x%08lX already printed)\n", spaces, idx, (long) n->list[idx]);
1084 			}
1085 			else {
1086 				printf("%s  o Item #%d\n", spaces, idx);
1087 				node_print_all(n->list[idx], indent + 2);
1088 			}
1089 		}
1090 	}
1091 }
1092 
1093 
node_print_all(struct node_t * n,long indent)1094 static void node_print_all(struct node_t *n, long indent)
1095 {
1096 	while(n->previous != NULL) {
1097 		n = n->previous;
1098 	}
1099 
1100 	while(n != NULL) {
1101 		printf("------------------\n");
1102 		node_print_info(n, indent);
1103 		n = n->next;
1104 	}
1105 }
1106 
1107 
node_print(struct node_t * n)1108 void node_print(struct node_t *n)
1109 {
1110 	print_serial++;
1111 	node_print_all(n, 0);
1112 	fflush(stdout);
1113 }
1114 #endif
1115 
1116 
1117 
1118 
1119 
1120 
1121 
1122 
1123 
1124 
1125 /*
1126  * node_execute()
1127  *
1128  * Low level expression evaluation.
1129  * When an expression is being evaluated it can't include an object.
1130  * Thus if we do find an object, an error is generated.
1131  */
1132 typedef	int	(*node_exec_func)(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status);
1133 
1134 #define	NODE_EXEC_FUNC_INTEGERS		0	/* integer <op> integer and also default when flags != EXEC_LR */
1135 #define	NODE_EXEC_FUNC_FLOATS		1	/* float <op> float, integer <op> float, float <op> integer */
1136 #define	NODE_EXEC_FUNC_STRINGS		2	/* string <op> string */
1137 #define	NODE_EXEC_FUNC_STRINT		3	/* string <op> integer */
1138 #define	NODE_EXEC_FUNC_STRFLT		4	/* string <op> float */
1139 #define	NODE_EXEC_FUNC_max		5
1140 
1141 /* define a quick switch macro to directly access two parameters */
1142 #define	EXEC_STRING		0x001
1143 #define	EXEC_INTEGER		0x002
1144 #define	EXEC_FLOAT		0x004
1145 #define	EXEC_LEFT		0x008
1146 #define	EXEC_RIGHT		0x010
1147 #define	EXEC_BOOLEAN_LEFT	0x020		/* the value is first converted to a boolean value */
1148 #define	EXEC_BOOLEAN_RIGHT	0x040
1149 #define	EXEC_SELECT		0x080
1150 #define	EXEC_DEFINITIONS	0x100
1151 #define	EXEC_LR			(EXEC_LEFT | EXEC_RIGHT)
1152 #define	EXEC_BOOLEAN_LR		(EXEC_BOOLEAN_LEFT | EXEC_BOOLEAN_RIGHT)
1153 
1154 #define	qs(a, b)		((a) + ((b) << 16))
1155 
1156 struct node_exec_types {
1157 	enum node_type_t	type;
1158 	enum node_type_t	sub_type;
1159 	const char *		name;
1160 	int			flags;
1161 	node_exec_func		func[NODE_EXEC_FUNC_max];
1162 };
1163 
1164 
1165 
1166 
1167 /* TODO: my point of view is that the current node_exec_field() doesn't make
1168  * sense - it isn't straight forward and I don't like it. It needs to be fixed.
1169  */
1170 
1171 /*
1172  * All of the following reduces <name>{.<name>} in an object reference.
1173  */
node_exec_field_name(struct node_t ** expr,struct node_t * name,struct node_exec_status_t * status)1174 static int node_exec_field_name(struct node_t **expr, struct node_t *name, struct node_exec_status_t *status)
1175 {
1176 	int		ec;
1177 
1178 	/*
1179 	 * We expect a name, but in case someone writes a whole complex
1180 	 * expression for this name, we have to execute it...
1181 	 */
1182 	if(expr[0]->type != NODE_TYPE_IDENTIFIER && expr[0]->type != NODE_TYPE_STRING) {
1183 		/*
1184 		 * TODO: this is actually wrong, but we keep it for now...
1185 		 * (it needs to return the reference, but it will in fact
1186 		 * execute it and return the contents of that object!!!)
1187 		 * On the other hand, at this time, it should anyway return
1188 		 * an identifier or a string!
1189 		 */
1190 		ec = node_eval(expr[0], name, status);
1191 		if(ec != 0) {
1192 			return ec;
1193 		}
1194 		if(name->type != NODE_TYPE_IDENTIFIER && name->type != NODE_TYPE_STRING) {
1195 			fprintf(stderr, "ERROR: invalid field reference; a name was expected in $(...), got a type %d instead.\n", name->type);
1196 			return 1;
1197 		}
1198 		expr[0] = name;
1199 	}
1200 
1201 	return 0;
1202 }
1203 
1204 
1205 // generate a path determining the name of each field
node_exec_complete_field(struct node_t * parent,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1206 static long node_exec_complete_field(struct node_t *parent, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1207 {
1208 	struct node_t	*n, name;
1209 	char		*path, *old;
1210 	int		ec;
1211 
1212 	// path to the parent object
1213 	path = node_path(parent, 0);
1214 
1215 	while(r->type == NODE_TYPE_OPERATOR && r->sub_type == NODE_SUBTYPE_FIELD) {
1216 		n = r->left;
1217 		ec = node_exec_field_name(&n, &name, status);
1218 		if(ec != 0) {
1219 			sswf_free(path);
1220 			return ec;
1221 		}
1222 		old = path;
1223 		path = sswf_strcat3(path, ".", n->string);
1224 		sswf_free(old);
1225 		r = r->right;
1226 	}
1227 
1228 	ec = node_exec_field_name(&r, &name, status);
1229 	if(ec != 0) {
1230 		return ec;
1231 	}
1232 
1233 	old = path;
1234 	path = sswf_strcat3(path, ".", r->string);
1235 	sswf_free(old);
1236 
1237 	assert(result->string == NULL, "about to leak memory in result->string");
1238 
1239 	result->type =     NODE_TYPE_OBJECT;
1240 	result->sub_type = NODE_SUBTYPE_REFERENCE;
1241 	result->string =   path;
1242 
1243 	return 0;
1244 }
1245 
1246 
1247 /* the return value of the following defines count + 1 or 0 (0 = stop) */
node_exec_field_subname(struct node_t * parent,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1248 static long node_exec_field_subname(struct node_t *parent, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1249 {
1250 	struct node_t			name, *obj, *n;
1251 	int				ec;
1252 	char				*s;
1253 
1254 	if(r->type == NODE_TYPE_OPERATOR && r->sub_type == NODE_SUBTYPE_FIELD) {
1255 		/* this is likely to happen! */
1256 		n = r->left;
1257 		ec = node_exec_field_name(&n, &name, status);
1258 		if(ec != 0) {
1259 			return ec;
1260 		}
1261 		obj = node_search_list(parent, n->string);
1262 		if(obj == NULL) {
1263 			if(status->ref) {
1264 				return node_exec_complete_field(parent, r, result, status);
1265 			}
1266 			if(parent->left != 0) {
1267 fprintf(stderr, "ERROR: sub-object named \"%s\" not found in \"%s\" (1).\n", n->string, parent->left->string);
1268 			}
1269 			else {
1270 fprintf(stderr, "ERROR: sub-object named \"%s\" not found (1).\n", n->string);
1271 			}
1272 			errcnt++;
1273 			return 2;
1274 		}
1275 		/* in case there are some more! */
1276 		return node_exec_field_subname(obj, r->right, result, status);
1277 	}
1278 
1279 	/* here we certainly have yet another name in r */
1280 	ec = node_exec_field_name(&r, &name, status);
1281 	if(ec != 0) {
1282 		return ec;
1283 	}
1284 	/*
1285 	 * Watch out, with the IMPORT keyword, the parent object may not
1286 	 * include any children, but it still includes references the user
1287 	 * can name.
1288 	 */
1289 	if(parent->type == NODE_TYPE_OBJECT && parent->sub_type == NODE_SUBTYPE_IMPORT) {
1290 		/* in this case we can't just search the list of children */
1291 		if(!status->ref) {
1292 fprintf(stderr, "ERROR: a name (%s) declared in an IMPORT object (%s) can only be used as a reference.\n", r->string, parent->left == NULL ? "<noname>" : parent->left->string);
1293 			errcnt++;
1294 			return 2;
1295 		}
1296 		/*
1297 		 * at the time we arrive here we would have to go through
1298 		 * the list of nodes in parent and compute each expression
1299 		 * to know which one matches the given name; the easiest
1300 		 * way out of this is to accept the IMPORT object even if
1301 		 * the sub-name isn't part of it; the save function will
1302 		 * then come back to this and fix the possible problems;
1303 		 */
1304 		result->type = NODE_TYPE_OBJECT;
1305 		result->sub_type = NODE_SUBTYPE_REFERENCE;
1306 		s = node_path(parent, 0);
1307 		assert(result->string == NULL, "about to leak memory in result->string (0x%08lX)", (long) result);
1308 		result->string = sswf_strcat3(s, ".", r->string);
1309 		sswf_free(s);
1310 		return 0;
1311 
1312 		/*
1313 		const struct data_list_t	*list;
1314 		const struct data_common_t	*cd, *str, *type;
1315 		int				max, idx;
1316 
1317 		if(parent->data == NULL) {
1318 fprintf(stderr, "ERROR: the IMPORT object \"%s\" has no data definition (invalid?).\n", parent->left == NULL ? "<noname>" : parent->left->string);
1319 			return 2;
1320 		}
1321 
1322 		obj = NULL;
1323 		list = dc_list(parent->data);
1324 		max = list->count;
1325 		for(idx = 0; idx < max; idx++) {
1326 			cd = dc_item(list, idx);
1327 			if(list->offset[idx] < 0)
1328 			if(((const struct data_import_t *) cd)->type == IMPORT_TYPE_NAME) {
1329 					idx++;
1330 					assert(idx < max, "expected a string with the external name reference");
1331 					str = dc_item(list, idx);
1332 					assert(str->type == NODE_TYPE_STRING, "expected a string item");
1333 					assert(str->name_len != 0 || str->name[0] == '\0', "a reference name can't be empty in an IMPORT");
1334 
1335 					// if there is a 2nd string, that's the type of the item
1336 					if(idx + 1 < max && list->offset[idx + 1] >= 0) {
1337 						type = dc_item(list, idx + 1);
1338 						if(type->type == NODE_TYPE_STRING) {
1339 							idx++;
1340 							assert(type->name_len != 0 || type->name[0] == '\0', "a reference type can't be empty in an IMPORT");
1341 						}
1342 					}
1343 
1344 					if(strcasecmp(str->name, r->string) == 0) {
1345 						// that's a reference to the IMPORT
1346 						// object itself when it succeeds
1347 						obj = parent;
1348 						break;
1349 					}
1350 			}
1351 		}
1352 		*/
1353 	}
1354 	else {
1355 		obj = node_search_list(parent, r->string);
1356 	}
1357 	if(obj == NULL) {
1358 		if(status->ref) {
1359 			return node_exec_complete_field(parent, r, result, status);
1360 		}
1361 		if(parent->left != 0) {
1362 fprintf(stderr, "ERROR: sub-object named \"%s\" not found in \"%s\" (2).\n", r->string, parent->left->string);
1363 		}
1364 		else {
1365 fprintf(stderr, "ERROR: sub-object named \"%s\" not found (2).\n", r->string);
1366 		}
1367 		errcnt++;
1368 		return 2;
1369 	}
1370 
1371 	/* whatever it is, we need to evaluate it */
1372 	if(obj->sub_type == NODE_SUBTYPE_VARIABLE) {
1373 		/* in case of a variable, we just want the result of the right hand-side */
1374 		return node_eval(obj->right, result, status);
1375 	}
1376 
1377 	if(status->ref) {
1378 		/* in this case we only want a reference so we return the object as is! */
1379 		result->type = NODE_TYPE_OBJECT;
1380 		result->sub_type = NODE_SUBTYPE_REFERENCE;
1381 		//result->string = sswf_strdup(r->string);
1382 		assert(result->string == NULL, "about to leak memory in result->string");
1383 		result->string = node_path(obj, 0);
1384 		return 0;
1385 	}
1386 
1387 	/* we found the object "execute" it like an inline reference */
1388 	return node_execute(obj, result, status);
1389 }
1390 
1391 
1392 
node_exec_field(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1393 static int node_exec_field(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1394 {
1395 	struct node_t	name, *obj;
1396 	int		ec;
1397 
1398 #if 0
1399 /* the following prints out the field being searched (i.e. "sswf.fnt.fotinos.insert") */
1400 	l = expr->left;
1401 	r = expr->right;
1402 	printf("Search for \"%s", l->string);
1403 	while(r->type == NODE_TYPE_OPERATOR && r->sub_type == NODE_SUBTYPE_FIELD) {
1404 		l = r->left;
1405 		ec = node_exec_field_name(&l, &name, status);
1406 		if(ec == 0) {
1407 			printf(".%s", l->string);
1408 		}
1409 		r = r->right;
1410 	}
1411 	ec = node_exec_field_name(&r, &name, status);
1412 	if(ec == 0) {
1413 		printf(".%s", r->string);
1414 	}
1415 	printf("\".\n");
1416 	fflush(stdout);
1417 #endif
1418 
1419 	l = expr->left;
1420 	r = expr->right;
1421 
1422 /* NOTE: at the first level we can search the object anywhere, after that it has to be
1423  * a child of whatever we found at the previous level
1424  */
1425 	ec = node_exec_field_name(&l, &name, status);
1426 	if(ec != 0) {
1427 		return ec;
1428 	}
1429 	/* use the name to find the object from where we currently are */
1430 	obj = node_find_object(expr, l->string);
1431 	if(obj != NULL) {
1432 		ec = node_exec_field_subname(obj, r, result, status);
1433 	}
1434 
1435 	if((obj == NULL && ec == 0) || ec == 2) {
1436 		/* print out the "whole name" - i.e. <name>{.<name>} */
1437 		fprintf(stderr, "ERROR: can't find object or variable \"%s", l->string);
1438 
1439 		while(r->type == NODE_TYPE_OPERATOR && r->sub_type == NODE_SUBTYPE_FIELD) {
1440 			l = r->left;
1441 			ec = node_exec_field_name(&l, &name, status);
1442 			if(ec == 0) {
1443 				fprintf(stderr, ".%s", l->string);
1444 			}
1445 			r = r->right;
1446 		}
1447 		ec = node_exec_field_name(&r, &name, status);
1448 		if(ec == 0) {
1449 			fprintf(stderr, ".%s", r->string);
1450 		}
1451 		fprintf(stderr, "\".\n");
1452 
1453 		errcnt++;
1454 		ec = 1;
1455 	}
1456 
1457 	return ec;
1458 }
1459 
1460 
node_exec_subscript(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1461 static int node_exec_subscript(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1462 {
1463 	int		from, to, length, idx;
1464 
1465 	/*l = expr->left;*/
1466 	/*r = expr->right;*/
1467 
1468 printf("l/r->type = %d/%d\n", l->type, r->type); fflush(stdout);
1469 
1470 /* the left hand can be either an object or a string */
1471 	if(l->type == NODE_TYPE_STRING) {
1472 		switch(r->type) {
1473 		case NODE_TYPE_INTEGER:
1474 			from = to = r->integer;
1475 			break;
1476 
1477 		case NODE_TYPE_RANGE_INTEGER:
1478 			from = r->integer;
1479 			to = r->integer2;
1480 			break;
1481 
1482 		case NODE_TYPE_FLOAT:
1483 			from = to = (int) rint(r->floating_point);
1484 			break;
1485 
1486 		case NODE_TYPE_RANGE_FLOAT:
1487 			from = (int) rint(r->floating_point);
1488 			to = (int) rint(r->floating_point2);
1489 			break;
1490 
1491 		default:
1492 			fprintf(stderr, "ERROR: can't subscript width an index of that type.\n");
1493 			return 1;
1494 
1495 		}
1496 		length = strlen(l->string);
1497 		if(from < 0) {
1498 			from += length;
1499 		}
1500 		if(to < 0) {
1501 			to += length;
1502 		}
1503 		if(from >= length || to >= length) {
1504 			fprintf(stderr, "ERROR: subscript out of bounds (%d or %d > %d).\n", from, to, length);
1505 			return 1;
1506 		}
1507 		if(from > to) {
1508 			from++;
1509 			length = from - to;
1510 		}
1511 		else {
1512 			to++;
1513 			length = to - from;
1514 		}
1515 		result->type = NODE_TYPE_STRING;
1516 		result->sub_type = NODE_SUBTYPE_UNKNOWN;
1517 		result->string = sswf_malloc(length + 1, "node_exec_subscript() - string which is the subscript of another string");
1518 		result->string[length] = '\0';
1519 		if(from > to) {
1520 			idx = 0;
1521 			while(from != to) {
1522 				from--;
1523 				result->string[idx] = l->string[from];
1524 				idx++;
1525 			}
1526 printf("\"%s\"[%d..%d] => \"%s\".\n", l->string, to + length - 1, to, result->string); fflush(stdout);
1527 		}
1528 		else {
1529 			memcpy(result->string, l->string + from, length);
1530 printf("\"%s\"[%d..%d] => \"%s\".\n", l->string, from, to - 1, result->string); fflush(stdout);
1531 		}
1532 	}
1533 	else {
1534 		fprintf(stderr, "ERROR: can't subscript this type at this time.\n");
1535 		return 1;
1536 	}
1537 
1538 	return 0;
1539 }
1540 
1541 
node_find_reference(struct node_t * expr,const char * name,struct node_exec_status_t * status)1542 static struct node_t *node_find_reference(struct node_t *expr, const char *name, struct node_exec_status_t *status)
1543 {
1544 	struct node_t		*ref;
1545 
1546 	assert(name != NULL, "node_find_reference() was called with a null pointer as the name of an object");
1547 
1548 	ref = node_find_object(expr, name);
1549 	if(ref != NULL) {
1550 		return (ref);
1551 	}
1552 
1553 	/* if we couldn't find it, try in the status object and the parent, etc. */
1554 	do {
1555 		assert(status->obj != 0, "the 'obj' field of the status is NULL");
1556 		ref = node_find_object(status->obj, name);
1557 		if(ref != NULL) {
1558 			return ref;
1559 		}
1560 		status = status->parent;
1561 	} while(status != 0);
1562 
1563 	return NULL;
1564 }
1565 
1566 
node_exec_reference(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1567 static int node_exec_reference(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1568 {
1569 	struct node_t			*ref;
1570 
1571 	/* fix the EXPAND vs direct reference */
1572 	if(expr->type == NODE_TYPE_IDENTIFIER) {
1573 		l = expr;
1574 	}
1575 
1576 	/* first look for the object in all of our parents */
1577 	ref = node_find_reference(expr, l->string, status);
1578 	if(ref == NULL) {
1579 		fprintf(stderr, "ERROR: can't find object or variable \"%s\".\n", l->string);
1580 		errcnt++;
1581 		return 1;
1582 	}
1583 
1584 	/* whatever it is, we need to evaluate it */
1585 	if(ref->sub_type == NODE_SUBTYPE_VARIABLE) {
1586 		/* in case of a variable, we just want the result of the right hand-side */
1587 		return node_eval(ref->right, result, status);
1588 	}
1589 
1590 	if(status->ref) {
1591 		/* in this case we only want a reference so we return the object as is! */
1592 		result->type = NODE_TYPE_OBJECT;
1593 		result->sub_type = NODE_SUBTYPE_REFERENCE;
1594 		//result->string = sswf_strdup(l->string);
1595 		assert(result->string == NULL, "about to leak memory in result->string");
1596 		result->string = node_path(ref, 0);
1597 		return 0;
1598 	}
1599 
1600 	/* in case of an object, we need to actually execute that object */
1601 	/* we can't use node_eval() here otherwise all the objects would be evaluated! */
1602 	return node_execute(ref, result, status);
1603 }
1604 
1605 
1606 
node_exec_identity_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1607 static int node_exec_identity_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1608 {
1609 	result->integer = l->integer;
1610 
1611 	return 0;
1612 }
1613 
node_exec_identity_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1614 static int node_exec_identity_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1615 {
1616 	result->floating_point = l->floating_point;
1617 
1618 	return 0;
1619 }
1620 
1621 
1622 
node_exec_identity_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1623 static int node_exec_identity_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1624 {
1625 	char		*s;
1626 
1627 	result->string = sswf_strdup(l->string);
1628 	s = result->string;
1629 	while(*s != '\0') {
1630 		*s = toupper((unsigned char) *s);
1631 		s++;
1632 	}
1633 
1634 	return 0;
1635 }
1636 
node_exec_negate_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1637 static int node_exec_negate_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1638 {
1639 	result->integer = -l->integer;
1640 
1641 	return 0;
1642 }
1643 
node_exec_negate_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1644 static int node_exec_negate_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1645 {
1646 	result->floating_point = -l->floating_point;
1647 
1648 	return 0;
1649 }
1650 
1651 
1652 
node_exec_negate_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1653 static int node_exec_negate_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1654 {
1655 	char		*s;
1656 
1657 	result->string = sswf_strdup(l->string);
1658 	s = result->string;
1659 	while(*s != '\0') {
1660 		*s = tolower((unsigned char) *s);
1661 		s++;
1662 	}
1663 
1664 	return 0;
1665 }
1666 
1667 
node_exec_logical_not_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1668 static int node_exec_logical_not_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1669 {
1670 	result->integer = !l->integer;
1671 
1672 	return 0;
1673 }
1674 
1675 
1676 
1677 
1678 
node_exec_not_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1679 static int node_exec_not_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1680 {
1681 	result->integer = ~l->integer;
1682 
1683 	return 0;
1684 }
1685 
node_exec_not_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1686 static int node_exec_not_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1687 {
1688 	char		*s;
1689 
1690 	result->string = sswf_strdup(l->string);
1691 	s = result->string;
1692 	while(*s != '\0') {
1693 		if(isupper((unsigned char) *s)) {
1694 			*s = tolower((unsigned char) *s);
1695 		}
1696 		else {
1697 			*s = toupper((unsigned char) *s);
1698 		}
1699 		s++;
1700 	}
1701 
1702 	return 0;
1703 }
1704 
1705 
1706 
node_exec_group_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1707 static int node_exec_group_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1708 {
1709 	result->string = sswf_strdup(l->string);
1710 
1711 	return 0;
1712 }
1713 
1714 
1715 
1716 struct node_exec_funcinfo {
1717 	const char	*name;		/* return type + name + parameters (prototype if you wish) */
1718 	node_exec_func	func;		/* l = list of parameters */
1719 };
1720 
1721 
1722 
node_exec_func_abs(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1723 static int node_exec_func_abs(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1724 {
1725 	result->floating_point = fabs(l->list[0]->floating_point);
1726 
1727 	return 0;
1728 }
1729 
1730 
node_exec_func_acos(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1731 static int node_exec_func_acos(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1732 {
1733 	result->floating_point = acos(l->list[0]->floating_point);
1734 
1735 	return 0;
1736 }
1737 
1738 
node_exec_func_asin(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1739 static int node_exec_func_asin(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1740 {
1741 	result->floating_point = asin(l->list[0]->floating_point);
1742 
1743 	return 0;
1744 }
1745 
1746 
node_exec_func_atan(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1747 static int node_exec_func_atan(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1748 {
1749 	result->floating_point = atan(l->list[0]->floating_point);
1750 
1751 	return 0;
1752 }
1753 
1754 
node_exec_func_atan2(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1755 static int node_exec_func_atan2(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1756 {
1757 	result->floating_point = atan2(l->list[0]->floating_point, l->list[1]->floating_point);
1758 
1759 	return 0;
1760 }
1761 
1762 
1763 #if HAS_CBRT
node_exec_func_cbrt(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1764 static int node_exec_func_cbrt(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1765 {
1766 	result->floating_point = cbrt(l->list[0]->floating_point);
1767 
1768 	return 0;
1769 }
1770 #endif
1771 
1772 
node_exec_func_ceil(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1773 static int node_exec_func_ceil(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1774 {
1775 	result->integer = (long) ceil(l->list[0]->floating_point);
1776 
1777 	return 0;
1778 }
1779 
1780 
node_exec_func_cos(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1781 static int node_exec_func_cos(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1782 {
1783 	result->floating_point = cos(l->list[0]->floating_point);
1784 
1785 	return 0;
1786 }
1787 
1788 
node_exec_func_debug_s(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1789 static int node_exec_func_debug_s(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1790 {
1791 	fprintf(stderr, "DEBUG: string - [%s]\n", l->list[0]->string);
1792 	result->integer = 0;
1793 
1794 	return 0;
1795 }
1796 
1797 
node_exec_func_debug_i(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1798 static int node_exec_func_debug_i(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1799 {
1800 	fprintf(stderr, "DEBUG: integer - [%ld]\n", l->list[0]->integer);
1801 	result->integer = 0;
1802 
1803 	return 0;
1804 }
1805 
1806 
node_exec_func_debug_f(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1807 static int node_exec_func_debug_f(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1808 {
1809 	fprintf(stderr, "DEBUG: floating point - [%g]\n", l->list[0]->floating_point);
1810 	result->integer = 0;
1811 
1812 	return 0;
1813 }
1814 
1815 
node_exec_func_defined(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1816 static int node_exec_func_defined(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1817 {
1818 	result->integer = node_find_reference(expr, l->list[0]->string, status) != NULL;
1819 
1820 	return 0;
1821 }
1822 
1823 
node_exec_func_exp(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1824 static int node_exec_func_exp(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1825 {
1826 	result->floating_point = exp(l->list[0]->floating_point);
1827 
1828 	return 0;
1829 }
1830 
1831 
node_exec_func_floor(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1832 static int node_exec_func_floor(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1833 {
1834 	result->integer = (long) floor(l->list[0]->floating_point);
1835 
1836 	return 0;
1837 }
1838 
1839 
node_exec_func_log(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1840 static int node_exec_func_log(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1841 {
1842 	result->floating_point = log(l->list[0]->floating_point);
1843 
1844 	return 0;
1845 }
1846 
1847 
node_exec_func_log10(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1848 static int node_exec_func_log10(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1849 {
1850 	result->floating_point = log10(l->list[0]->floating_point);
1851 
1852 	return 0;
1853 }
1854 
1855 
node_exec_func_rint(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1856 static int node_exec_func_rint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1857 {
1858 	result->integer = (long) rint(l->list[0]->floating_point);
1859 
1860 	return 0;
1861 }
1862 
1863 
node_exec_func_rnd(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1864 static int node_exec_func_rnd(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1865 {
1866 	result->floating_point = (double) rand() / (double) RAND_MAX;
1867 
1868 	return 0;
1869 }
1870 
1871 
node_exec_func_select(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1872 static int node_exec_func_select(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1873 {
1874 	long		idx;
1875 
1876 	idx = l->list[0]->integer;
1877 	if(idx < 0 || idx >= l->cnt) {
1878 		fprintf(stderr, "ERROR: select() index out of bounds (%ld not in [0..%ld) range)\n", idx, l->cnt);
1879 		return -1;
1880 	}
1881 	result->type = l->list[idx]->type;
1882 	switch(result->type) {
1883 	case NODE_TYPE_INTEGER:
1884 		result->integer = l->list[idx]->integer;
1885 		break;
1886 
1887 	case NODE_TYPE_FLOAT:
1888 		result->floating_point = l->list[idx]->floating_point;
1889 		break;
1890 
1891 	case NODE_TYPE_STRING:
1892 		result->string = sswf_strdup(l->list[idx]->string);
1893 		break;
1894 
1895 	case NODE_TYPE_OBJECT:
1896 		fprintf(stderr, "TODO: can't select objects yet...\n");
1897 		abort();
1898 
1899 	default:
1900 		fprintf(stderr, "ERROR: trying to select() an object of an unknown type.\n");
1901 		return -1;
1902 
1903 	}
1904 
1905 	return 0;
1906 }
1907 
1908 
node_exec_func_sin(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1909 static int node_exec_func_sin(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1910 {
1911 	result->floating_point = sin(l->list[0]->floating_point);
1912 
1913 	return 0;
1914 }
1915 
1916 
node_exec_func_sqrt(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1917 static int node_exec_func_sqrt(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1918 {
1919 	result->floating_point = sqrt(l->list[0]->floating_point);
1920 
1921 	return 0;
1922 }
1923 
1924 
node_exec_func_tan(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1925 static int node_exec_func_tan(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1926 {
1927 	result->floating_point = tan(l->list[0]->floating_point);
1928 
1929 	return 0;
1930 }
1931 
1932 
node_exec_func_strlen(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1933 static int node_exec_func_strlen(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1934 {
1935 	result->integer = strlen(l->list[0]->string);
1936 
1937 	return 0;
1938 }
1939 
1940 
1941 
1942 
1943 
1944 struct fmt_info {
1945 	char		*fmt;			/* input format */
1946 	int		cnt;			/* current number of valid characters */
1947 	int		max;			/* max. number of char. before we need to resize the buffer */
1948 	char		*result;		/* dynamically allocated result */
1949 };
1950 
1951 
strf_put(struct fmt_info * info,char c)1952 static void strf_put(struct fmt_info *info, char c)
1953 {
1954 	if(info->cnt >= info->max) {
1955 		info->max += 256;
1956 		info->result = sswf_remalloc(info->result, info->max, "node_exec_func_strf() - string");
1957 	}
1958 
1959 	info->result[info->cnt] = c;
1960 	info->cnt++;
1961 }
1962 
1963 
1964 
1965 
1966 
node_exec_func_strf(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)1967 static int node_exec_func_strf(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
1968 {
1969 	char		tmp[256], buf[256];
1970 	char		*d;
1971 	int		idx, c;
1972 	struct fmt_info	info;
1973 
1974 	idx = 1;
1975 	buf[0] = '%';
1976 	tmp[sizeof(tmp) - 1] = '\0';
1977 	memset(&info, 0, sizeof(info));
1978 	info.fmt = l->list[0]->string;
1979 	while(*info.fmt != '\0') {
1980 		if(*info.fmt++ == '%') {
1981 			/* we have a format, read chars up to a valid format character */
1982 			/* TODO: the following misses the %<value>$... possibilities! */
1983 			d = buf + 1;
1984 			while(strchr("%diouxXeEfFgGaAcCsSpn", (c = *info.fmt++)) == NULL && c != '\0' && d - buf < sizeof(buf) - 2) {
1985 				*d++ = c;
1986 			}
1987 			if(c == '\0') {
1988 				/* we moved ahead of the null termintor!!! */
1989 				info.fmt--;
1990 				c = 'i';	/* define a default format - certainly wrong! */
1991 			}
1992 			/* we've got to save the format now */
1993 			*d++ = c;
1994 			*d = '\0';
1995 			/* we need to check the index AFTER we parsed the <value>$ entry */
1996 			if(idx < 1 || idx >= l->cnt) {
1997 				fprintf(stderr, "ERROR: invalid strf() format string (%s) - not enough parameters.\n",
1998 						l->list[0]->string);
1999 				sswf_free(info.result);
2000 				return -1;
2001 			}
2002 			switch(d[-1]) {
2003 			case 'd':
2004 			case 'i':
2005 			case 'o':
2006 			case 'u':
2007 			case 'x':
2008 			case 'X':
2009 				if(l->list[idx]->type != NODE_TYPE_INTEGER) {
2010 					fprintf(stderr, "ERROR: invalid type, parameter #%d was expected to be an integer.\n", idx);
2011 					sswf_free(info.result);
2012 					return -1;
2013 				}
2014 				snprintf(tmp, sizeof(tmp) - 1, buf, l->list[idx]->integer);
2015 				break;
2016 
2017 			case 'e':
2018 			case 'E':
2019 			case 'f':
2020 			case 'F':
2021 			case 'g':
2022 			case 'G':
2023 			case 'a':
2024 			case 'A':
2025 				if(l->list[idx]->type != NODE_TYPE_FLOAT) {
2026 					fprintf(stderr, "ERROR: invalid type, parameter #%d was expected to be a floating point.\n", idx);
2027 					sswf_free(info.result);
2028 					return -1;
2029 				}
2030 				snprintf(tmp, sizeof(tmp) - 1, buf, l->list[idx]->floating_point);
2031 				break;
2032 
2033 			case 'c':
2034 			case 'C':
2035 				if(l->list[idx]->type != NODE_TYPE_STRING) {
2036 					fprintf(stderr, "ERROR: invalid type, parameter #%d was expected to be a string.\n", idx);
2037 					sswf_free(info.result);
2038 					return -1;
2039 				}
2040 				snprintf(tmp, sizeof(tmp) - 1, buf, *l->list[idx]->string);
2041 				break;
2042 
2043 			case 's':
2044 			case 'S':
2045 				if(l->list[idx]->type != NODE_TYPE_STRING) {
2046 					fprintf(stderr, "ERROR: invalid type, parameter #%d was expected to be a string.\n", idx);
2047 					sswf_free(info.result);
2048 					return -1;
2049 				}
2050 				snprintf(tmp, sizeof(tmp) - 1, buf, l->list[idx]->string);
2051 				break;
2052 
2053 			case 'p':
2054 			case 'n':
2055 				/* ignore these */
2056 				tmp[0] = '\0';
2057 				break;
2058 
2059 			}
2060 			idx++;
2061 			d = tmp;
2062 			while(*d != '\0') {
2063 				strf_put(&info, *d++);
2064 			}
2065 		}
2066 		else {
2067 			strf_put(&info, info.fmt[-1]);
2068 		}
2069 	}
2070 	/* insert the null terminator */
2071 	strf_put(&info, '\0');
2072 
2073 	result->string = info.result;
2074 
2075 	return 0;
2076 }
2077 
2078 
cmp_func_names(const char * format,const char * func)2079 static int cmp_func_names(const char *format, const char *func)
2080 {
2081 	do {
2082 		if(*format == '*') {
2083 			return 1;
2084 		}
2085 		if(*func != *format) {
2086 			return 0;
2087 		}
2088 		format++;
2089 		func++;
2090 	} while(format[-1] != '\0');
2091 
2092 	return 1;
2093 }
2094 
2095 
node_exec_function(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2096 static int node_exec_function(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2097 {
2098 	static const struct node_exec_funcinfo	functions[] = {
2099 		/* MATH */
2100 		{ "fabs/f",		node_exec_func_abs	},
2101 		{ "facos/f",		node_exec_func_acos	},
2102 		{ "fasin/f",		node_exec_func_asin	},
2103 		{ "fatan/f",		node_exec_func_atan	},
2104 		{ "fatan/ff",		node_exec_func_atan2	},
2105 		{ "fatan2/ff",		node_exec_func_atan2	},
2106 #if HAS_CBRT
2107 		{ "fcbrt/f",		node_exec_func_cbrt	},
2108 #endif
2109 		{ "iceil/f",		node_exec_func_ceil	},
2110 		{ "fcos/f",		node_exec_func_cos	},
2111 		{ "fexp/f",		node_exec_func_exp	},
2112 		{ "ifloor/f",		node_exec_func_floor	},
2113 		{ "flog/f",		node_exec_func_log	},
2114 		{ "flog10/f",		node_exec_func_log10	},
2115 		{ "irint/f",		node_exec_func_rint	},
2116 		{ "frnd/",		node_exec_func_rnd	},
2117 		{ "fsin/f",		node_exec_func_sin	},
2118 		{ "fsqrt/f",		node_exec_func_sqrt	},
2119 		{ "ftan/f",		node_exec_func_tan	},
2120 
2121 		/* STRING */
2122 		{ "sstrf/s*",		node_exec_func_strf	},
2123 		{ "istrlen/s",		node_exec_func_strlen	},
2124 
2125 		/* OTHER */
2126 		{ "idebug/s",		node_exec_func_debug_s	},
2127 		{ "idebug/i",		node_exec_func_debug_i	},
2128 		{ "idebug/f",		node_exec_func_debug_f	},
2129 		{ "idefined/s",		node_exec_func_defined	},
2130 		{ "iselect/i*",		node_exec_func_select	},	/* the return value varies */
2131 
2132 		{ NULL, NULL }		/* end of table */
2133 	};
2134 	const struct node_exec_funcinfo	*f;
2135 	char				name[256], *n;
2136 	struct node_t			*p, *e, params;
2137 	int				cnt, ec;
2138 
2139 /* no parameters to start with */
2140 	n = name + snprintf(name, sizeof(name) - 1, "%s/", expr->left->string);
2141 
2142 /* evaluate the parameters (when there are some!) */
2143 	node_init(&params, NODE_TYPE_OBJECT, NODE_SUBTYPE_LIST);
2144 	cnt = 1;
2145 	p = expr->right;
2146 	while(p != NULL) {
2147 		/* evaluate this expression */
2148 		if(n >= name + sizeof(name) - 1) {
2149 			fprintf(stderr, "ERROR: too many parameters for function call \"%s()\".\n",
2150 					expr->left->string);
2151 			node_clean(&params, 0);
2152 			return -1;
2153 		}
2154 		lex_filename = p->filename;
2155 		e = node_alloc(NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN, p->line);
2156 		node_link_list(&params, e);
2157 		e->parent = &params;
2158 		/* we can't use node_eval() here otherwise we would get only one result */
2159 		ec = node_execute(p, e, status);
2160 		if(ec != 0) {
2161 			node_clean(&params, 0);
2162 			return -1;
2163 		}
2164 		switch(e->type) {
2165 		case NODE_TYPE_INTEGER:
2166 			*n++ = 'i';
2167 			break;
2168 
2169 		case NODE_TYPE_FLOAT:
2170 			*n++ = 'f';
2171 			break;
2172 
2173 		case NODE_TYPE_STRING:
2174 			*n++ = 's';
2175 			break;
2176 
2177 		case NODE_TYPE_OBJECT:
2178 			*n++ = 'o';
2179 			break;
2180 
2181 		default:
2182 			fprintf(stderr, "ERROR: can't properly evaluate parameter #%d for function call \"%s()\".\n",
2183 					cnt, expr->left->string);
2184 			node_clean(&params, 0);
2185 			return -1;
2186 
2187 		}
2188 		p = p->next;
2189 		cnt++;
2190 	}
2191 	*n = '\0';
2192 
2193 /* name is the function name + parameters -- search our table for a corresponding function */
2194 	ec = -1;
2195 	f = functions;
2196 	while(f->name != NULL) {
2197 		/* TODO: ameliorate this following by accepting: f (in f->name) == i (in name) */
2198 		if(cmp_func_names(f->name + 1, name)) {
2199 			/* we found the function! set the default type of the result for this function call */
2200 			switch(*f->name) {
2201 			case 'i':
2202 				result->type = NODE_TYPE_INTEGER;
2203 				break;
2204 
2205 			case 'f':
2206 				result->type = NODE_TYPE_FLOAT;
2207 				break;
2208 
2209 			case 'o':
2210 				result->type = NODE_TYPE_OBJECT;
2211 				break;
2212 
2213 			case 's':
2214 				result->type = NODE_TYPE_STRING;
2215 				break;
2216 
2217 #if DEBUG
2218 			default:
2219 				assert(0, "unknown function return type (%c)", *f->name);
2220 				/*NOTREACHED*/
2221 #endif
2222 
2223 			}
2224 			ec = (*f->func)(expr, &params, NULL, result, status);
2225 			break;
2226 		}
2227 		f++;
2228 	}
2229 	if(f->name == NULL) {
2230 		fprintf(stderr, "ERROR: unknown function \"%s\".\n", expr->left->string);
2231 	}
2232 
2233 	/* TODO: bugs will most probably be in there in regard to functions until the node_free() works perfectly */
2234 	/*node_clean(&params, 0);*/
2235 
2236 	return ec;
2237 }
2238 
2239 
2240 
node_exec_power_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2241 static int node_exec_power_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2242 {
2243 	/* we could also use a loop? */
2244 	result->integer = (long) pow((double) l->integer, (double) r->integer);
2245 
2246 	return 0;
2247 }
2248 
2249 
node_exec_power_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2250 static int node_exec_power_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2251 {
2252 	result->floating_point = pow(l->floating_point, r->floating_point);
2253 
2254 	return 0;
2255 }
2256 
2257 
2258 
node_exec_mul_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2259 static int node_exec_mul_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2260 {
2261 	result->integer = l->integer * r->integer;
2262 
2263 	return 0;
2264 }
2265 
2266 
node_exec_mul_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2267 static int node_exec_mul_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2268 {
2269 	result->floating_point = l->floating_point * r->floating_point;
2270 
2271 	return 0;
2272 }
2273 
2274 
node_exec_div_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2275 static int node_exec_div_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2276 {
2277 	result->integer = l->integer / r->integer;
2278 
2279 	return 0;
2280 }
2281 
2282 
node_exec_div_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2283 static int node_exec_div_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2284 {
2285 	result->floating_point = l->floating_point / r->floating_point;
2286 
2287 	return 0;
2288 }
2289 
2290 
node_exec_mod_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2291 static int node_exec_mod_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2292 {
2293 	result->integer = l->integer % r->integer;
2294 
2295 	return 0;
2296 }
2297 
2298 
node_exec_mod_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2299 static int node_exec_mod_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2300 {
2301 	result->floating_point = fmod(l->floating_point, r->floating_point);
2302 
2303 	return 0;
2304 }
2305 
2306 
2307 
2308 
2309 
node_exec_add_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2310 static int node_exec_add_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2311 {
2312 	result->integer = l->integer + r->integer;
2313 
2314 	return 0;
2315 }
2316 
2317 
node_exec_add_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2318 static int node_exec_add_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2319 {
2320 	result->floating_point = l->floating_point + r->floating_point;
2321 
2322 	return 0;
2323 }
2324 
2325 
2326 
node_exec_add_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2327 static int node_exec_add_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2328 {
2329 	assert(l->type == NODE_TYPE_STRING && r->type == NODE_TYPE_STRING, "one of the nodes in node_exec_add_strings() isn't a string");
2330 	assert(l->string != NULL && r->string != NULL, "one of the nodes in node_exec_add_strings() has a NULL string pointer");
2331 	result->string = sswf_malloc(strlen(l->string) + strlen(r->string) + 1, "node_exec_add_strings()");
2332 	sprintf(result->string, "%s%s", l->string, r->string);
2333 
2334 	return 0;
2335 }
2336 
2337 
2338 
node_exec_add_strint(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2339 static int node_exec_add_strint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2340 {
2341 	char		buffer[16];
2342 
2343 	sprintf(buffer, "%ld", r->integer);
2344 	result->string = sswf_malloc(strlen(l->string) + strlen(buffer) + 1, "node_exec_add_strint()");
2345 	sprintf(result->string, "%s%s", l->string, buffer);
2346 
2347 	return 0;
2348 }
2349 
2350 
2351 
node_exec_sub_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2352 static int node_exec_sub_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2353 {
2354 	result->integer = l->integer - r->integer;
2355 
2356 	return 0;
2357 }
2358 
2359 
node_exec_sub_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2360 static int node_exec_sub_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2361 {
2362 	result->floating_point = l->floating_point - r->floating_point;
2363 
2364 	return 0;
2365 }
2366 
2367 
2368 
2369 
node_exec_min_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2370 static int node_exec_min_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2371 {
2372 	result->integer = l->integer < r->integer ? l->integer : r->integer;
2373 
2374 	return 0;
2375 }
2376 
2377 
node_exec_min_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2378 static int node_exec_min_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2379 {
2380 	result->floating_point = l->floating_point < r->floating_point ? l->floating_point : r->floating_point;
2381 
2382 	return 0;
2383 }
2384 
2385 
node_exec_min_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2386 static int node_exec_min_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2387 {
2388 	int		len;
2389 
2390 	assert(l->type == NODE_TYPE_STRING && r->type == NODE_TYPE_STRING, "one of the nodes in node_exec_add_strings() isn't a string");
2391 	assert(l->string != NULL && r->string != NULL, "one of the nodes in node_exec_add_strings() has a NULL string pointer");
2392 	if(strcmp(l->string, r->string) > 0) {
2393 		l = r;
2394 	}
2395 	len = strlen(l->string) + 1;
2396 	result->string = sswf_malloc(len, "node_exec_min_strings()");
2397 	memcpy(result->string, l->string, len);
2398 
2399 	return 0;
2400 }
2401 
2402 
2403 
2404 
2405 
2406 
node_exec_max_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2407 static int node_exec_max_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2408 {
2409 	result->integer = l->integer > r->integer ? l->integer : r->integer;
2410 
2411 	return 0;
2412 }
2413 
2414 
node_exec_max_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2415 static int node_exec_max_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2416 {
2417 	result->floating_point = l->floating_point > r->floating_point ? l->floating_point : r->floating_point;
2418 
2419 	return 0;
2420 }
2421 
2422 
node_exec_max_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2423 static int node_exec_max_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2424 {
2425 	int		len;
2426 
2427 	assert(l->type == NODE_TYPE_STRING && r->type == NODE_TYPE_STRING, "one of the nodes in node_exec_add_strings() isn't a string");
2428 	assert(l->string != NULL && r->string != NULL, "one of the nodes in node_exec_add_strings() has a NULL string pointer");
2429 	if(strcmp(l->string, r->string) < 0) {
2430 		l = r;
2431 	}
2432 	len = strlen(l->string) + 1;
2433 	result->string = sswf_malloc(len, "node_exec_max_strings()");
2434 	memcpy(result->string, l->string, len);
2435 
2436 	return 0;
2437 }
2438 
2439 
2440 
2441 
2442 
2443 
node_exec_shift_right_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2444 static int node_exec_shift_right_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2445 {
2446 	if(r->integer < 0) {
2447 		result->integer = l->integer << -r->integer;
2448 	}
2449 	else {
2450 		result->integer = l->integer >> r->integer;
2451 	}
2452 
2453 	return 0;
2454 }
2455 
2456 
2457 static int node_exec_shift_left_strint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status);
node_exec_shift_right_strint(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2458 static int node_exec_shift_right_strint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2459 {
2460 	int		len;
2461 
2462 	if(r->integer > 0) {
2463 		result->string = sswf_strdup(l->string);
2464 		len = strlen(result->string);
2465 		if(r->integer >= len) {
2466 			if(len > 0) {
2467 				memset(result->string + 1, *result->string, len - 1);
2468 			}
2469 		}
2470 		else if(len > 1) {
2471 			memmove(result->string + r->integer, result->string, len - r->integer);
2472 			memset(result->string + 1, *result->string, r->integer - 1);
2473 		}
2474 	}
2475 	else if(r->integer < 0) {
2476 		r->integer = -r->integer;
2477 		node_exec_shift_left_strint(expr, l, r, result, status);
2478 		r->integer = -r->integer;		/* restore - most probably useless */
2479 	}
2480 	else {
2481 		result->string = sswf_strdup(l->string);
2482 	}
2483 
2484 	return 0;
2485 }
2486 
2487 
2488 
2489 
2490 
node_exec_shift_left_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2491 static int node_exec_shift_left_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2492 {
2493 	if(r->integer < 0) {
2494 		result->integer = l->integer >> -r->integer;
2495 	}
2496 	else {
2497 		result->integer = l->integer << r->integer;
2498 	}
2499 
2500 	return 0;
2501 }
2502 
2503 
node_exec_shift_left_strint(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2504 static int node_exec_shift_left_strint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2505 {
2506 	int		ec, len;
2507 
2508 	if(r->integer > 0) {
2509 		result->string = sswf_strdup(l->string);
2510 		len = strlen(result->string);
2511 		if(r->integer >= len) {
2512 			memset(result->string, ' ', len);
2513 		}
2514 		else if(len == 1) {
2515 			*result->string = ' ';
2516 		}
2517 		else if(len > 1) {
2518 			memmove(result->string, result->string + r->integer, len - r->integer);
2519 			memset(result->string + r->integer, ' ', r->integer);
2520 		}
2521 	}
2522 	else if(r->integer < 0) {
2523 		r->integer = -r->integer;
2524 		ec = node_exec_shift_right_strint(expr, l, r, result, status);
2525 		r->integer = -r->integer;		/* restore - most probably useless */
2526 		return ec;
2527 	}
2528 	else {
2529 		result->string = sswf_strdup(l->string);
2530 	}
2531 
2532 	return 0;
2533 }
2534 
2535 
2536 
2537 
node_exec_shift_right_unsigned_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2538 static int node_exec_shift_right_unsigned_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2539 {
2540 	if(r->integer < 0) {
2541 		result->integer = l->integer << -r->integer;
2542 	}
2543 	else {
2544 		result->integer = (unsigned long) l->integer >> r->integer;
2545 	}
2546 
2547 	return 0;
2548 }
2549 
2550 
node_exec_shift_right_unsigned_strint(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2551 static int node_exec_shift_right_unsigned_strint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2552 {
2553 	int		ec, len;
2554 
2555 	if(r->integer > 0) {
2556 		result->string = sswf_strdup(l->string);
2557 		len = strlen(result->string);
2558 		if(r->integer >= len) {
2559 			memset(result->string, ' ', len);
2560 		}
2561 		else if(len == 1) {
2562 			*result->string = ' ';
2563 		}
2564 		else if(len > 1) {
2565 			memmove(result->string + r->integer, result->string, len - r->integer);
2566 			memset(result->string, ' ', r->integer);
2567 		}
2568 	}
2569 	else if(r->integer < 0) {
2570 		r->integer = -r->integer;
2571 		ec = node_exec_shift_left_strint(expr, l, r, result, status);
2572 		r->integer = -r->integer;		/* restore - most probably useless */
2573 		return ec;
2574 	}
2575 	else {
2576 		result->string = sswf_strdup(l->string);
2577 	}
2578 
2579 	return 0;
2580 }
2581 
2582 
2583 
2584 
node_exec_rotate_right_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2585 static int node_exec_rotate_right_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2586 {
2587 	if(r->integer < 0) {
2588 		result->integer = (l->integer << -r->integer)
2589 			+ ((unsigned long) l->integer >> (sizeof(long) * CHAR_BIT + r->integer));
2590 	}
2591 	else {
2592 		result->integer = (l->integer >> r->integer)
2593 			+ ((unsigned long) l->integer << (sizeof(long) * CHAR_BIT - r->integer));
2594 	}
2595 
2596 	return 0;
2597 }
2598 
2599 
node_exec_rotate_right_strint(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2600 static int node_exec_rotate_right_strint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2601 {
2602 	int		len;
2603 
2604 	len = strlen(l->string);
2605 	result->string = sswf_malloc(len, "node_exec_rotate_right_strint()");
2606 	if(r->integer < 0) {
2607 		r->integer = len - (-r->integer % len);
2608 	}
2609 	else {
2610 		r->integer %= len;
2611 	}
2612 	if(r->integer > 0) {		/* i.e. not zero */
2613 		memcpy(result->string + r->integer, l->string, len - r->integer);
2614 		memcpy(result->string, l->string + len - r->integer, r->integer);
2615 	}
2616 
2617 	return 0;
2618 }
2619 
2620 
2621 
2622 
2623 
node_exec_rotate_left_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2624 static int node_exec_rotate_left_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2625 {
2626 	if(r->integer < 0) {
2627 		result->integer = (l->integer >> -r->integer)
2628 			+ ((unsigned long) l->integer << (sizeof(long) * CHAR_BIT + r->integer));
2629 	}
2630 	else {
2631 		result->integer = (l->integer << r->integer)
2632 			+ ((unsigned long) l->integer >> (sizeof(long) * CHAR_BIT - r->integer));
2633 	}
2634 
2635 	return 0;
2636 }
2637 
2638 
node_exec_rotate_left_strint(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2639 static int node_exec_rotate_left_strint(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2640 {
2641 	int	ec;
2642 
2643 	r->integer = -r->integer;
2644 	ec = node_exec_rotate_right_strint(expr, l, r, result, status);
2645 	r->integer = -r->integer;
2646 
2647 	return ec;
2648 }
2649 
2650 
2651 
node_exec_and_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2652 static int node_exec_and_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2653 {
2654 	result->integer = l->integer & r->integer;
2655 
2656 	return 0;
2657 }
2658 
2659 
node_exec_or_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2660 static int node_exec_or_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2661 {
2662 	result->integer = l->integer | r->integer;
2663 
2664 	return 0;
2665 }
2666 
2667 
2668 
node_exec_xor_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2669 static int node_exec_xor_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2670 {
2671 	result->integer = l->integer ^ r->integer;
2672 
2673 	return 0;
2674 }
2675 
2676 
node_exec_equal_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2677 static int node_exec_equal_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2678 {
2679 	result->integer = l->integer == r->integer;
2680 
2681 	return 0;
2682 }
2683 
2684 
2685 
node_exec_equal_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2686 static int node_exec_equal_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2687 {
2688 	result->integer = l->floating_point == r->floating_point;
2689 	result->type = NODE_TYPE_INTEGER;
2690 
2691 	return 0;
2692 }
2693 
2694 
2695 
node_exec_equal_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2696 static int node_exec_equal_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2697 {
2698 	result->integer = strcmp(l->string, r->string) == 0;
2699 	result->type = NODE_TYPE_INTEGER;
2700 
2701 	return 0;
2702 }
2703 
2704 
2705 
node_exec_not_equal_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2706 static int node_exec_not_equal_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2707 {
2708 	result->integer = l->integer != r->integer;
2709 
2710 	return 0;
2711 }
2712 
2713 
node_exec_not_equal_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2714 static int node_exec_not_equal_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2715 {
2716 	result->integer = l->floating_point != r->floating_point;
2717 	result->type = NODE_TYPE_INTEGER;
2718 
2719 	return 0;
2720 }
2721 
2722 
2723 
node_exec_not_equal_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2724 static int node_exec_not_equal_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2725 {
2726 	result->integer = strcmp(l->string, r->string) != 0;
2727 	result->type = NODE_TYPE_INTEGER;
2728 
2729 	return 0;
2730 }
2731 
2732 
2733 
node_exec_less_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2734 static int node_exec_less_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2735 {
2736 	result->integer = l->integer < r->integer;
2737 
2738 	return 0;
2739 }
2740 
2741 
node_exec_less_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2742 static int node_exec_less_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2743 {
2744 	result->integer = l->floating_point < r->floating_point;
2745 	result->type = NODE_TYPE_INTEGER;
2746 
2747 	return 0;
2748 }
2749 
2750 
2751 
node_exec_less_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2752 static int node_exec_less_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2753 {
2754 	result->integer = strcmp(l->string, r->string) < 0;
2755 	result->type = NODE_TYPE_INTEGER;
2756 
2757 	return 0;
2758 }
2759 
2760 
node_exec_less_equal_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2761 static int node_exec_less_equal_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2762 {
2763 	result->integer = l->integer <= r->integer;
2764 
2765 	return 0;
2766 }
2767 
2768 
node_exec_less_equal_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2769 static int node_exec_less_equal_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2770 {
2771 	result->integer = l->floating_point <= r->floating_point;
2772 	result->type = NODE_TYPE_INTEGER;
2773 
2774 	return 0;
2775 }
2776 
2777 
2778 
node_exec_less_equal_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2779 static int node_exec_less_equal_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2780 {
2781 	result->integer = strcmp(l->string, r->string) <= 0;
2782 	result->type = NODE_TYPE_INTEGER;
2783 
2784 	return 0;
2785 }
2786 
2787 
2788 
node_exec_greater_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2789 static int node_exec_greater_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2790 {
2791 	result->integer = l->integer > r->integer;
2792 
2793 	return 0;
2794 }
2795 
2796 
node_exec_greater_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2797 static int node_exec_greater_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2798 {
2799 	result->integer = l->floating_point > r->floating_point;
2800 	result->type = NODE_TYPE_INTEGER;
2801 
2802 	return 0;
2803 }
2804 
2805 
2806 
node_exec_greater_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2807 static int node_exec_greater_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2808 {
2809 	result->integer = strcmp(l->string, r->string) > 0;
2810 	result->type = NODE_TYPE_INTEGER;
2811 
2812 	return 0;
2813 }
2814 
2815 
node_exec_greater_equal_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2816 static int node_exec_greater_equal_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2817 {
2818 	result->integer = l->integer >= r->integer;
2819 
2820 	return 0;
2821 }
2822 
2823 
node_exec_greater_equal_floats(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2824 static int node_exec_greater_equal_floats(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2825 {
2826 	result->integer = l->floating_point >= r->floating_point;
2827 	result->type = NODE_TYPE_INTEGER;
2828 
2829 	return 0;
2830 }
2831 
2832 
2833 
node_exec_greater_equal_strings(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2834 static int node_exec_greater_equal_strings(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2835 {
2836 	result->integer = strcmp(l->string, r->string) >= 0;
2837 	result->type = NODE_TYPE_INTEGER;
2838 
2839 	return 0;
2840 }
2841 
2842 
2843 
node_exec_select_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2844 static int node_exec_select_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2845 {
2846 	return node_eval(l->integer ? expr->left : expr->right, result, status);
2847 }
2848 
2849 
node_exec_let(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)2850 static int node_exec_let(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
2851 {
2852 	struct node_t	*block, *var;
2853 
2854 	/* create a new variable */
2855 	block = node_find_block(expr);
2856 	if(block != NULL) {		/* should always be true! */
2857 		lex_filename = l->filename;
2858 		var = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_VARIABLE, l->line);
2859 		var->left = node_alloc(NODE_TYPE_IDENTIFIER, NODE_SUBTYPE_UNKNOWN, l->line);
2860 		var->left->string = sswf_strdup(l->string);
2861 		var->left->parent = var;
2862 
2863 		/*
2864 		 * we need to duplicate this node because the variable node can't be a soft link,
2865 		 * (the right node can however be a softlink)
2866 		 */
2867 		lex_filename = expr->filename;
2868 		var->right = node_alloc(expr->right->type, expr->right->sub_type, expr->line);
2869 		memcpy(var->right->unit, expr->right->unit, sizeof(expr->unit));
2870 		var->right->parent         = var;
2871 		var->right->flags         |= NODE_FLAG_SOFTLINK;
2872 		var->right->left           = expr->right->left;
2873 		var->right->right          = expr->right->right;
2874 		var->right->select         = expr->right->select;
2875 #if 0
2876 /* Do we need this? It really doesn't seem to me that we would since the lists have
2877  * to be emptied whenever an object is exited.
2878  * Anyway, if we need it, make sure cnt field remains synchronized.
2879  */
2880 		var->right->list           = expr->right->list;
2881 		var->right->cnt            = expr->right->cnt;	/* XXX: if it changes in the referenced object, this is wrong then! */
2882 		var->right->max            = expr->right->max;
2883 #endif
2884 		var->right->string         = expr->right->string;
2885 		var->right->integer        = expr->right->integer;
2886 		var->right->floating_point = expr->right->floating_point;
2887 
2888 		node_link_list(block, var);
2889 		var->parent = block;
2890 	}
2891 
2892 	return node_eval(expr->right, result, status);
2893 }
2894 
2895 
2896 
2897 
2898 
2899 
2900 
2901 enum def_param_t {
2902 	DEF_PARAM_END = 0,		/* mark the end of a definition */
2903 	DEF_PARAM_NAME,			/* the name of this object type as a string */
2904 	DEF_PARAM_LABEL,		/* a string defining a label */
2905 	DEF_PARAM_TYPE,			/* a NODE_TYPE_... - also marks a new entry */
2906 	DEF_PARAM_UNIT,			/* a NODE_UNIT_... */
2907 	DEF_PARAM_SUBTYPE,		/* a NODE_SUBTYPE_... */
2908 	DEF_PARAM_OFFSET,		/* offset in destination structure (-1 - append dynamically) */
2909 	DEF_PARAM_SIZE,			/* define the size of the structure */
2910 	DEF_PARAM_DEFAULT,		/* default value (always in a string) */
2911 	DEF_PARAM_OPTIONAL,		/* the following offset is optional */
2912 	DEF_PARAM_REPEAT,		/* if right after the LABEL, repeat with ';' as separator */
2913 					/* if right after an entry, repeat with ',' as separator */
2914 	DEF_PARAM_EMPTY,		/* refuse such an object if nothing is defined within */
2915 	DEF_PARAM_SET,			/* forces a value if label was found (that's like a flag!) */
2916 	/*DEF_PARAM_SEPARATOR,		-- add a NODE_SUBTYPE_DEFINITION between each definition */
2917 
2918 	DEF_PARAM_max			/* never used - practical to close the enum */
2919 };
2920 
2921 
2922 union def_data_t {
2923 	long			ignored;
2924 	size_t			size;		/* size of the structure (when there is one) */
2925 	unsigned long		offset;		/* offset where the data is saved in the destination structure */
2926 	long			set;		/* used with the DEF_PARAM_SET */
2927 	double			def_value;	/* default value to reset structure at start */
2928 	enum node_type_t	type;		/* type or sub-type */
2929 	enum node_unit_t	unit;		/* a unit entry */
2930 	const char *		string;		/* the default value, a label... */
2931 };
2932 
2933 
2934 struct definition_t {
2935 	enum def_param_t	param;
2936 	union def_data_t	data;
2937 };
2938 
2939 
2940 /* enlarge the following if you find yourself with a HUGE object accepting more than 50 different entries (?!?!) */
2941 struct def_entry_t {
2942 	long			flags;		/* different type of flags - see below */
2943 	enum node_type_t	type;		/* main type: FLOAT, STRING or OBJECT */
2944 	enum node_type_t	sub_type;	/* UNKNOWN or the object sub-type */
2945 	enum node_unit_t	unit;		/* the 'which' parameter, not a specific unit */
2946 	unsigned long		offset;		/* offset to save data in structure (only for FLOAT) */
2947 	double			def_value;	/* the default value used to initialize the structure */
2948 };
2949 #define	DEF_ENTRY_FLAG_REPEAT		0x00000001	/* repeat only this specific type many times, not the whole entry */
2950 #define	DEF_ENTRY_FLAG_DEFINED		0x00000002	/* this entry was defined */
2951 #define	DEF_ENTRY_FLAG_OPTIONAL		0x00000004	/* this entry is optional */
2952 #define	DEF_ENTRY_FLAG_HAS_OFFSET	0x00000008	/* this entry has an offset, use default to reset */
2953 #define	DEF_ENTRY_FLAG_HAS_DEFAULT	0x00000010	/* we can use the def_value field */
2954 #define	DEF_ENTRY_FLAG_REFERENCE	0x00000020	/* we only want a reference to that object - not a copy of the object */
2955 
2956 struct def_label_t {
2957 	const char *		label;
2958 	long			flags;
2959 	size_t			size;		/* total size of the structure (one structure per label - require the REPEAT or multiple labels) */
2960 	unsigned long		offset;		/* offset to save the "set" value */
2961 	long			set;		/* forces a value on a label, requires an offset */
2962 	long			count;		/* number of entries in this label */
2963 	struct def_entry_t *	entries;	/* a pointer to the entries */
2964 };
2965 
2966 #define	DEF_LABEL_FLAG_REPEAT		0x00000001	/* we accept to repeat this entry many times */
2967 #define	DEF_LABEL_FLAG_DEFINED		0x00000002	/* this label was defined */
2968 #define	DEF_LABEL_FLAG_HAS_SET		0x00000004	/* this entry has a "SET" member, use it */
2969 #define	DEF_LABEL_FLAG_HAS_OFFSET	0x00000008	/* this entry has an offset, use default to reset */
2970 
2971 
2972 #define	DEF_ENTRY_MAX		50
2973 #define	DEF_LABEL_MAX		25
2974 struct def_object_t {
2975 	const char *		name;			/* name of this object type */
2976 	long			flags;			/* see below */
2977 	enum node_unit_t	default_unit;		/* the default unit for this object */
2978 	long			count;			/* number of labels in use */
2979 	size_t			size;			/* total size of the structure (one structure per object) */
2980 	struct def_label_t	labels[DEF_LABEL_MAX];	/* the list of labels */
2981 	struct def_entry_t	entries[DEF_ENTRY_MAX];	/* all the entries of all the labels */
2982 };
2983 
2984 /*#define DEF_OBJECT_FLAG_DEFINITION	0x00000001	-- if set, insert a NEW DEFINITION for each new definition entry */
2985 #define	DEF_OBJECT_FLAG_HAS_LIST	0x00000002	/* if any entry is an object */
2986 #define	DEF_OBJECT_FLAG_EMPTY		0x00000004	/* accepts empty entries */
2987 
2988 
2989 #ifndef _MSVC
2990 #define	DEF_PARAM(prm, value)		{ .param = DEF_PARAM_##prm, { value } }
2991 
2992 #define	DEF_START(name)			const struct definition_t node_def_##name[] = {	\
2993 						DEF_PARAM(NAME, .string = #name),
2994 
2995 #define	DEF_END()			DEF_PARAM(END, .ignored = 0) };
2996 #define	DEF_LABEL(label)		DEF_PARAM(LABEL, .string = label ),
2997 #define	DEF_NOLABEL()			DEF_PARAM(LABEL, .string = NULL ),
2998 #define	DEF_REPEAT()			DEF_PARAM(REPEAT, .ignored = 0),
2999 #define	DEF_EMPTY()			DEF_PARAM(EMPTY, .ignored = 0),
3000 
3001 #define	DEF_OBJECT_REF()								\
3002 	DEF_PARAM(TYPE, .type = NODE_TYPE_OBJECT),					\
3003 	DEF_PARAM(SUBTYPE, .type = NODE_SUBTYPE_REFERENCE),
3004 
3005 #define	DEF_OBJECT(sub_type)								\
3006 	DEF_PARAM(TYPE, .type = NODE_TYPE_DATA),						\
3007 	DEF_PARAM(SUBTYPE, .type = NODE_SUBTYPE_##sub_type),
3008 
3009 #define	DEF_OBJECT_OPT(sub_type)							\
3010 	DEF_OBJECT(sub_type)								\
3011 	DEF_PARAM(OPTIONAL, .ignored = 0),
3012 
3013 #define	DEF_VALUE0(unit_nm, structure, end_t, field, defval)				\
3014 	DEF_PARAM(TYPE, .type = NODE_TYPE_FLOAT),						\
3015 	DEF_PARAM(OFFSET, .offset = offsetof(struct data_##structure##end_t, field)),	\
3016 	DEF_PARAM(UNIT, .unit = NODE_UNIT_##unit_nm),					\
3017 	DEF_PARAM(DEFAULT, .def_value = defval),
3018 
3019 #define	DEF_VALUE(unit, structure, field, def_value)					\
3020 	DEF_VALUE0(unit, structure, _t, field, def_value)
3021 
3022 #define	DEF_VALUE_OPT(unit, structure, field, def_value)				\
3023 	DEF_VALUE0(unit, structure, _t, field, def_value)				\
3024 	DEF_PARAM(OPTIONAL, .ignored = 0),
3025 
3026 #define	DEF_STRING()									\
3027 	DEF_PARAM(TYPE, .type = NODE_TYPE_STRING),
3028 
3029 #define	DEF_STRING_OPT()								\
3030 	DEF_PARAM(TYPE, .type = NODE_TYPE_STRING),					\
3031 	DEF_PARAM(OPTIONAL, .ignored = 0),
3032 
3033 #define	DEF_SET0(structure, end_t, field, value)					\
3034 	DEF_PARAM(SET, .set = value),							\
3035 	DEF_PARAM(OFFSET, .offset = offsetof(struct data_##structure##end_t, field)),
3036 
3037 #define	DEF_SET(structure, field, value)						\
3038 	DEF_SET0(structure, _t, field, value)
3039 
3040 #define	DEF_SIZE0(structure, end_t)							\
3041 	DEF_PARAM(SIZE, .size =  sizeof(struct data_##structure##end_t)),
3042 
3043 #define	DEF_SIZE(structure)								\
3044 	DEF_SIZE0(structure, _t)
3045 
3046 /*
3047 #define	DEF_SEPARATOR()									\
3048 	DEF_PARAM(SEPARATOR, .ignored = 0),
3049 */
3050 #else
3051 
3052 
3053 struct def_ignore_t {
3054 	enum def_param_t	param;
3055 	long			pad;
3056 	long			ignored;
3057 	long			align;
3058 };
3059 struct def_size_t {
3060 	enum def_param_t	param;
3061 	long			pad;
3062 	size_t			size;
3063 	long			align;
3064 };
3065 struct def_offset_t {
3066 	enum def_param_t	param;
3067 	long			pad;
3068 	unsigned long		offset;
3069 	long			align;
3070 };
3071 struct def_set_t {
3072 	enum def_param_t	param;
3073 	long			pad;
3074 	long			set;
3075 	long			align;
3076 };
3077 struct def_def_value_t {
3078 	enum def_param_t	param;
3079 	long			pad;
3080 	double			def_value;
3081 };
3082 struct def_type_t {
3083 	enum def_param_t	param;
3084 	long			pad;
3085 	enum node_type_t	type;
3086 	long			align;
3087 };
3088 struct def_unit_t {
3089 	enum def_param_t	param;
3090 	long			pad;
3091 	enum node_unit_t	unit;
3092 	long			align;
3093 };
3094 struct def_string_t {
3095 	enum def_param_t	param;
3096 	long			pad;
3097 	const char *		string;
3098 	long			align;
3099 };
3100 
3101 
3102 #define	DEF_PARAM(t, name, prm, value)		const struct def_##t##_t name[1] = { DEF_PARAM_##prm, 0, value };
3103 #define	DEF_PARAM_SUB(t, line, prm, value)	DEF_PARAM(t, node_def_line_##line, prm, value)
3104 #define	DEF_PARAM_SUB1(t, line, prm, value)	DEF_PARAM_SUB(t, line, prm, value)
3105 #define	DEF_PARAM_AN(t, prm, value)		DEF_PARAM_SUB1(t, __LINE__, prm, value)
3106 #define	DEF_PARAM_IGNORE(prm)			DEF_PARAM_AN(ignore, prm, 0)
3107 
3108 #define	DEF_PARAM_SB(n, t, line, prm, value)	DEF_PARAM(t, node_def_line_##line##n, prm, value)
3109 #define	DEF_PARAM_SB1(n, t, line, prm, value)	DEF_PARAM_SB(n, t, line, prm, value)
3110 #define	DEF_PARAM_AM(n, t, prm, value)		DEF_PARAM_SB1(n, t, __LINE__, prm, value)
3111 
3112 #define	DEF_START(name)				DEF_PARAM(string, node_def_##name, NAME, #name)
3113 
3114 //const struct definition_t node_def_##name[] = { DEF_PARAM(NAME, .string = #name),
3115 
3116 #define	DEF_END()			DEF_PARAM_IGNORE(END)
3117 #define	DEF_LABEL(label)		DEF_PARAM_AN(string, LABEL, label)
3118 #define	DEF_NOLABEL()			DEF_PARAM_AN(string, LABEL, NULL)
3119 #define	DEF_REPEAT()			DEF_PARAM_IGNORE(REPEAT)
3120 #define	DEF_EMPTY()			DEF_PARAM_IGNORE(EMPTY)
3121 
3122 #define	DEF_OBJECT_REF()								\
3123 	DEF_PARAM_AM(a, type, TYPE, NODE_TYPE_OBJECT)					\
3124 	DEF_PARAM_AM(b, type, SUBTYPE, NODE_SUBTYPE_REFERENCE)
3125 
3126 #define	DEF_OBJECT(sub_type)								\
3127 	DEF_PARAM_AM(a, type, TYPE, NODE_TYPE_DATA)					\
3128 	DEF_PARAM_AM(b, type, SUBTYPE, NODE_SUBTYPE_##sub_type)
3129 
3130 #define	DEF_OBJECT_OPT(sub_type)							\
3131 	DEF_OBJECT(sub_type)								\
3132 	DEF_PARAM_IGNORE(OPTIONAL)
3133 
3134 #define	DEF_VALUE0(unit_nm, structure, end_t, field, defval)				\
3135 	DEF_PARAM_AM(a, type, TYPE, NODE_TYPE_FLOAT)					\
3136 	DEF_PARAM_AM(b, offset, OFFSET, offsetof(struct data_##structure##end_t, field))\
3137 	DEF_PARAM_AM(c, unit, UNIT, NODE_UNIT_##unit_nm)				\
3138 	DEF_PARAM_AM(d, def_value, DEFAULT, defval)
3139 
3140 #define	DEF_VALUE(unit, structure, field, def_value)					\
3141 	DEF_VALUE0(unit, structure, _t, field, def_value)
3142 
3143 #define	DEF_VALUE_OPT(unit, structure, field, def_value)				\
3144 	DEF_VALUE0(unit, structure, _t, field, def_value)				\
3145 	DEF_PARAM_IGNORE(OPTIONAL)
3146 
3147 #define	DEF_STRING()									\
3148 	DEF_PARAM_AN(type, TYPE, NODE_TYPE_STRING)
3149 
3150 #define	DEF_STRING_OPT()								\
3151 	DEF_PARAM_AM(a, type, TYPE, NODE_TYPE_STRING)					\
3152 	DEF_PARAM_IGNORE(OPTIONAL)
3153 
3154 #define	DEF_SET0(structure, end_t, field, value)					\
3155 	DEF_PARAM_AM(a, set, SET, value)						\
3156 	DEF_PARAM_AM(b, offset, OFFSET, offsetof(struct data_##structure##end_t, field))
3157 
3158 #define	DEF_SET(structure, field, value)						\
3159 	DEF_SET0(structure, _t, field, value)
3160 
3161 #define	DEF_SIZE0(structure, end_t)							\
3162 	DEF_PARAM_AN(size, SIZE, sizeof(struct data_##structure##end_t))
3163 
3164 #define	DEF_SIZE(structure)								\
3165 	DEF_SIZE0(structure, _t)
3166 
3167 /*
3168 #define	DEF_SEPARATOR()									\
3169 	DEF_PARAM(SEPARATOR, .ignored = 0),
3170 */
3171 #endif
3172 
3173 
3174   DEF_START(action_branch)
3175 	DEF_LABEL("[LABEL|GOTO]")
DEF_STRING()3176 	DEF_STRING	()
3177   DEF_END()
3178 
3179   DEF_START(action_dictionary)
3180 	DEF_LABEL("[STRING]")
3181 	DEF_REPEAT()
3182 	DEF_STRING	()
3183   DEF_END()
3184 
3185   DEF_START(action_goto)
3186 	DEF_SIZE(goto_play)
3187 	DEF_LABEL("[PLAY]")
3188 	DEF_VALUE	(BOOLEAN, goto_play, play, 1.0)
3189 	DEF_LABEL("[FRAME]")
3190 	DEF_STRING	()
3191   DEF_END()
3192 
3193   DEF_START(action_push_data)
3194 	DEF_LABEL("STRING")
3195 	DEF_REPEAT()
3196 	DEF_SIZE(push_data)
3197 	DEF_SET		(push_data, type, PUSHDATA_STRING)
3198 	DEF_STRING	()
3199 	DEF_LABEL("PROPERTY")
3200 	DEF_REPEAT()
3201 	DEF_SIZE(push_data)
3202 	DEF_SET		(push_data, type, PUSHDATA_PROPERTY)
3203 	DEF_STRING	()
3204 	DEF_LABEL("BOOLEAN")
3205 	DEF_REPEAT()
3206 	DEF_SIZE(push_data)
3207 	DEF_SET		(push_data, type, PUSHDATA_BOOLEAN)
3208 	DEF_VALUE	(BOOLEAN, push_data, value, 0.0)
3209 	DEF_LABEL("INTEGER")
3210 	DEF_REPEAT()
3211 	DEF_SIZE(push_data)
3212 	DEF_SET		(push_data, type, PUSHDATA_INTEGER)
3213 	DEF_VALUE	(UNKNOWN, push_data, value, 0.0)
3214 	DEF_LABEL("FLOAT")
3215 	DEF_REPEAT()
3216 	DEF_SIZE(push_data)
3217 	DEF_SET		(push_data, type, PUSHDATA_FLOAT)
3218 	DEF_VALUE	(UNKNOWN, push_data, value, 0.0)
3219 	DEF_LABEL("DOUBLE")
3220 	DEF_REPEAT()
3221 	DEF_SIZE(push_data)
3222 	DEF_SET		(push_data, type, PUSHDATA_DOUBLE)
3223 	DEF_VALUE	(UNKNOWN, push_data, value, 0.0)
3224 	DEF_LABEL("UNDEFINED")
3225 	DEF_REPEAT()
3226 	DEF_SIZE(push_data)
3227 	DEF_SET		(push_data, type, PUSHDATA_UNDEFINED)
3228 	DEF_VALUE	(UNKNOWN, push_data, value, 0.0)
3229 	DEF_LABEL("NULL")
3230 	DEF_REPEAT()
3231 	DEF_SIZE(push_data)
3232 	DEF_SET		(push_data, type, PUSHDATA_NULL)
3233 	DEF_VALUE	(UNKNOWN, push_data, value, 0.0)
3234 	DEF_LABEL("LOOKUP")
3235 	DEF_REPEAT()
3236 	DEF_SIZE(push_data)
3237 	DEF_SET		(push_data, type, PUSHDATA_LOOKUP)
3238 	DEF_VALUE	(UNKNOWN, push_data, value, 0.0)
3239 	DEF_LABEL("REGISTER")
3240 	DEF_REPEAT()
3241 	DEF_SIZE(push_data)
3242 	DEF_SET		(push_data, type, PUSHDATA_REGISTER)
3243 	DEF_VALUE	(UNKNOWN, push_data, value, 0.0)
3244   DEF_END()
3245 
3246   DEF_START(action_set_target)
3247 	DEF_EMPTY()
3248 	DEF_LABEL("[TARGET]")
3249 	DEF_STRING	()
3250   DEF_END()
3251 
3252   DEF_START(action_url)
3253 	DEF_EMPTY()
3254 	/* NOTE: METHOD should really be seperated, but what's the point here?!? */
3255 	DEF_LABEL("[URL|TARGET|METHOD]")
3256 	DEF_STRING	()
3257 	DEF_STRING_OPT	()
3258   DEF_END()
3259 
3260   DEF_START(action_store_register)
3261 	DEF_SIZE(register)
3262 	DEF_LABEL("[REGISTER]")
3263 	DEF_VALUE	(UNKNOWN, register, reg, 0.0)
3264 	/* the following ensures we get a list so it's easy to parse in the save
3265 	 * maybe we will have named registers later also!
3266 	 */
3267 	DEF_LABEL("[NAME]")		/* DON'T USE -- THAT'S FORBIDDEN STILL */
3268 	DEF_STRING	()
3269   DEF_END()
3270 
3271   DEF_START(action_wait_for_frame)
3272 	DEF_LABEL("[FRAME]")
3273 	DEF_STRING	()
3274 	DEF_NOLABEL()
3275 	DEF_REPEAT()
3276 	DEF_OBJECT	(ACTION)
3277 	DEF_NOLABEL()
3278 	DEF_REPEAT()
3279 	DEF_OBJECT	(LABEL)
3280 	DEF_NOLABEL()
3281 	DEF_REPEAT()
3282 	DEF_OBJECT	(FUNCTION)
3283 	DEF_NOLABEL()
3284 	DEF_REPEAT()
3285 	DEF_OBJECT	(WITH)
3286   DEF_END()
3287 
3288   DEF_START(action_simple)
3289   DEF_END()
3290 
3291   DEF_START(action_script)
3292 	DEF_NOLABEL()
3293 	DEF_STRING	()
3294   DEF_END()
3295 
3296   DEF_START(button)
3297 	DEF_SIZE(button_flag)
3298 	DEF_NOLABEL()
3299 	DEF_REPEAT()
3300 	DEF_OBJECT	(STATE)			/* turtle like points */
3301 	DEF_NOLABEL()
3302 	DEF_REPEAT()
3303 	DEF_OBJECT	(ACTION)		/* all points are zero based */
3304 	DEF_NOLABEL()
3305 	DEF_REPEAT()
3306 	DEF_OBJECT	(ACTION_SCRIPT)
3307 	DEF_NOLABEL()
3308 	DEF_REPEAT()
3309 	DEF_OBJECT	(LABEL)
3310 	DEF_NOLABEL()
3311 	DEF_REPEAT()
3312 	DEF_OBJECT	(FUNCTION)
3313 	DEF_NOLABEL()
3314 	DEF_REPEAT()
3315 	DEF_OBJECT	(WITH)
3316 	DEF_NOLABEL()
3317 	DEF_OBJECT	(ON_EVENT)
3318 	DEF_LABEL("[MENU|TRACK_AS_MENU|TRACK_MENU]")
3319 	DEF_VALUE	(BOOLEAN, button_flag, menu, 0.0)
3320 	DEF_LABEL("[GRID|SCALING_GRID]")
3321 	DEF_OBJECT	(RECT)
3322   DEF_END()
3323 
3324   DEF_START(color)
3325 	DEF_SIZE(color)
3326 	DEF_NOLABEL()
3327 	DEF_VALUE	(COLOR, color, red,	0.0)
3328 	DEF_VALUE	(COLOR, color, green,	0.0)
3329 	DEF_VALUE	(COLOR, color, blue,	0.0)
3330 	DEF_VALUE_OPT	(COLOR, color, alpha,	1.0)
3331   DEF_END()
3332 
3333   DEF_START(color_transform)
3334 	DEF_SIZE(color_transform)
3335 	DEF_LABEL("ADD")
3336 	DEF_VALUE	(COLOR, color_transform, add_red,	0.0)
3337 	DEF_VALUE	(COLOR, color_transform, add_green,	0.0)
3338 	DEF_VALUE	(COLOR, color_transform, add_blue,	0.0)
3339 	DEF_VALUE_OPT	(COLOR, color_transform, add_alpha,	0.0)
3340 	DEF_LABEL("SCALE|MULT|MULTIPLY")
3341 	DEF_VALUE	(RATIO, color_transform, mult_red,	1.0)
3342 	DEF_VALUE	(RATIO, color_transform, mult_green,	1.0)
3343 	DEF_VALUE	(RATIO, color_transform, mult_blue,	1.0)
3344 	DEF_VALUE_OPT	(RATIO, color_transform, mult_alpha,	1.0)
3345   DEF_END()
3346 
3347   DEF_START(do_action)
3348 	DEF_LABEL("ID|INIT|INITIALIZE|INITIALIZATION")
3349 	DEF_OBJECT_REF	()
3350 	DEF_NOLABEL()
3351 	DEF_REPEAT()
3352 	DEF_OBJECT	(ACTION)
3353 	DEF_NOLABEL()
3354 	DEF_REPEAT()
3355 	DEF_OBJECT	(ACTION_SCRIPT)
3356 	DEF_NOLABEL()
3357 	DEF_REPEAT()
3358 	DEF_OBJECT	(LABEL)
3359 	DEF_NOLABEL()
3360 	DEF_REPEAT()
3361 	DEF_OBJECT	(FUNCTION)
3362 	DEF_NOLABEL()
3363 	DEF_REPEAT()
3364 	DEF_OBJECT	(WITH)
3365 	DEF_NOLABEL()
3366 	DEF_REPEAT()
3367 	DEF_OBJECT	(TRY)
3368 	DEF_NOLABEL()
3369 	DEF_REPEAT()
3370 	DEF_OBJECT	(CATCH)
3371 	DEF_NOLABEL()
3372 	DEF_REPEAT()
3373 	DEF_OBJECT	(FINALLY)
3374 	DEF_NOLABEL()
3375 	DEF_REPEAT()
3376 	DEF_OBJECT	(LIST)
3377   DEF_END()
3378 
3379   DEF_START(edges)
3380 	DEF_LABEL("ROTATE")
3381 	DEF_SIZE(edges)
3382 	DEF_SET		(edges, type, EDGE_TYPE_ROTATE)
3383 	DEF_VALUE	(ANGLE, edges, delta_x1, 0.0)
3384 	DEF_NOLABEL()
3385 	DEF_REPEAT()
3386 	DEF_SIZE(edges)
3387 	DEF_SET		(edges, type, EDGE_TYPE_INTERMEDIATE)
3388 	DEF_VALUE	(SIZE, edges, delta_x1,	0.0)
3389 	DEF_VALUE	(SIZE, edges, delta_y1,	0.0)
3390 	DEF_VALUE_OPT	(SIZE, edges, delta_x2,	-1E+128)
3391 	DEF_VALUE	(SIZE, edges, delta_y2,	-1E+128)
3392 	DEF_LABEL("CLOSE")
3393 	DEF_REPEAT()
3394 	DEF_SIZE(edges)
3395 	DEF_SET		(edges, type, EDGE_TYPE_CLOSE)
3396 	DEF_VALUE	(SIZE, edges, delta_x1,	0.0)
3397 	DEF_VALUE	(SIZE, edges, delta_y1,	0.0)
3398 	DEF_VALUE_OPT	(SIZE, edges, delta_x2,	-1E+128)
3399 	DEF_VALUE	(SIZE, edges, delta_y2,	-1E+128)
3400   DEF_END()
3401 
3402   DEF_START(edit_text)
3403 	DEF_SIZE(edit_text)
3404 	DEF_LABEL("WORD_WRAP")
3405 	DEF_VALUE	(UNKNOWN, edit_text, word_wrap,    1.0)
3406 	DEF_LABEL("MULTILINE")
3407 	DEF_VALUE	(UNKNOWN, edit_text, multiline,    0.0)
3408 	DEF_LABEL("PASSWORD")
3409 	DEF_VALUE	(UNKNOWN, edit_text, password,     0.0)
3410 	DEF_LABEL("READ_ONLY")
3411 	DEF_VALUE	(UNKNOWN, edit_text, readonly,     0.0)
3412 	DEF_LABEL("NO_SELECT")
3413 	DEF_VALUE	(UNKNOWN, edit_text, no_select,    0.0)
3414 	DEF_LABEL("BORDER")
3415 	DEF_VALUE	(UNKNOWN, edit_text, border,       1.0)
3416 	DEF_LABEL("OUTLINE|OUTLINES")
3417 	DEF_VALUE	(UNKNOWN, edit_text, outline,      0.0)
3418 	DEF_LABEL("HTML")
3419 	DEF_VALUE	(UNKNOWN, edit_text, html,         0.0)
3420 	DEF_LABEL("AUTO_SIZE")
3421 	DEF_VALUE	(UNKNOWN, edit_text, auto_size,    0.0)
3422 	DEF_LABEL("MAX|LENGTH|MAX_LENGTH")
3423 	DEF_VALUE	(UNKNOWN, edit_text, max_length,   -1E+128)
3424 	DEF_LABEL("MARGIN|LAYOUT")
3425 	DEF_VALUE	(SIZE,    edit_text, margin_left,  -1E+128)
3426 	DEF_VALUE	(SIZE,    edit_text, margin_right, -1E+128)
3427 	DEF_VALUE_OPT	(SIZE,    edit_text, indent,       -1E+128)
3428 	DEF_VALUE	(SIZE,    edit_text, leading,      -1E+128)
3429 	DEF_LABEL("ALIASING|THICKNESS_SHARPNESS")
3430 	DEF_VALUE	(SIZE,    edit_text, thickness,    -1E+128)
3431 	DEF_VALUE	(SIZE,    edit_text, sharpness,    -1E+128)
3432 	DEF_LABEL("RENDERER|FONT_ENGINE")
3433 	DEF_VALUE	(SIZE,    edit_text, renderer,     -1E+128)
3434 	DEF_LABEL("GRID|GRID_FIT")
3435 	DEF_VALUE	(SIZE,    edit_text, grid_fit,     -1E+128)
3436 	DEF_LABEL("VAR|VARIABLE")
3437 	DEF_SIZE(edit_text)
3438 	DEF_SET		(edit_text, type, EDIT_TEXT_TYPE_VARIABLE)
3439 	DEF_STRING	()
3440 	DEF_STRING_OPT	()
3441 	DEF_LABEL("INIT|START")
3442 	DEF_SIZE(edit_text)
3443 	DEF_SET		(edit_text, type, EDIT_TEXT_TYPE_INITIAL_TEXT)
3444 	DEF_STRING	()
3445 	DEF_LABEL("ALIGN|ALIGNMENT")
3446 	DEF_SIZE(edit_text)
3447 	DEF_SET		(edit_text, type, EDIT_TEXT_TYPE_ALIGNMENT)
3448 	DEF_STRING	()
3449 	DEF_LABEL("USED_GLYPHS")
3450 	DEF_SIZE(edit_text)
3451 	DEF_SET		(edit_text, type, EDIT_TEXT_TYPE_USED_GLYPHS)
3452 	DEF_STRING	()
3453 	DEF_LABEL("USED_STRING")
3454 	DEF_REPEAT()
3455 	DEF_SIZE(edit_text)
3456 	DEF_SET		(edit_text, type, EDIT_TEXT_TYPE_USED_STRING)
3457 	DEF_STRING	()
3458 	DEF_NOLABEL()
3459 	DEF_OBJECT	(TEXT_SETUP)		/* we don't use positions here */
3460 	DEF_NOLABEL()
3461 	DEF_OBJECT	(RECT)
3462   DEF_END()
3463 
3464   DEF_START(end)
3465   DEF_END()
3466 
3467   DEF_START(envelope)
3468 	DEF_LABEL("[VOLUME]")
3469 	DEF_REPEAT	()
3470 	DEF_SIZE(envelope)
3471 	DEF_VALUE	(TIME,  envelope, position, 0.0)
3472 	DEF_VALUE	(RATIO, envelope, left,     -1E+128)
3473 	DEF_VALUE_OPT	(RATIO, envelope, right,    -1E+128)	// if not present use left
3474   DEF_END()
3475 
3476   DEF_START(export)
3477 	DEF_LABEL("ID|OBJ")
3478 	DEF_REPEAT	()
3479 	DEF_OBJECT_REF	()
3480 	DEF_STRING	()
3481 	DEF_STRING_OPT	()
3482   DEF_END()
3483 
3484   DEF_START(fill_style)
3485 	DEF_EMPTY()
3486 	DEF_LABEL("[TYPE]")
3487 	DEF_STRING      ()
3488 	DEF_NOLABEL()
3489 	DEF_OBJECT	(COLOR)
3490 	DEF_OBJECT_OPT	(COLOR)
3491 	DEF_NOLABEL()
3492 	DEF_OBJECT	(GRADIENT)
3493 	DEF_LABEL("ID|IMG")
3494 	DEF_OBJECT_REF	()
3495 	DEF_NOLABEL()
3496 	DEF_OBJECT	(MATRIX)
3497 	DEF_OBJECT_OPT	(MATRIX)
3498   DEF_END()
3499 
3500   DEF_START(font)
3501 	DEF_SIZE(font)
3502 	/*
3503 	 * DEF_SET(font, type, FONT_TYPE_FONT) -- that's the default!
3504 	 * (lucky us because that's an invalid DEF_SET()!!! well - maybe
3505 	 * I've done it on purpose, who knows?)
3506 	 */
3507 	DEF_LABEL("ID|CHAR")
3508 	DEF_REPEAT()
3509 	DEF_SIZE(font_advance)
3510 	DEF_SET		(font_advance, type, FONT_TYPE_ADVANCE)
3511 	DEF_STRING	()
3512 	DEF_OBJECT_REF	()
3513 	DEF_VALUE_OPT	(SIZE, font_advance, x, -1E+128)
3514 	DEF_LABEL("LANGUAGE")
3515 	DEF_SIZE(font_name)
3516 	DEF_SET		(font_name, type, FONT_TYPE_LANGUAGE)
3517 	DEF_STRING	()
3518 	DEF_LABEL("[NAME]")
3519 	DEF_SIZE(font_name)
3520 	DEF_SET		(font_name, type, FONT_TYPE_NAME)
3521 	DEF_STRING	()
3522 	DEF_LABEL("DISPLAY_NAME")
3523 	DEF_SIZE(font_name)
3524 	DEF_SET		(font_name, type, FONT_TYPE_DISPLAY_NAME)
3525 	DEF_STRING	()
3526 	DEF_LABEL("COPYRIGHT")
3527 	DEF_SIZE(font_name)
3528 	DEF_SET		(font_name, type, FONT_TYPE_COPYRIGHT)
3529 	DEF_STRING	()
3530 	DEF_LABEL("TYPE")
3531 	DEF_SIZE(font_name)
3532 	DEF_SET		(font_name, type, FONT_TYPE_TYPE)
3533 	DEF_STRING	()
3534 	DEF_STRING_OPT	()
3535 	DEF_STRING_OPT	()
3536 	DEF_STRING_OPT	()
3537 	DEF_STRING_OPT	()
3538 	DEF_LABEL("[LAYOUT]")
3539 	DEF_VALUE	(SIZE, font, ascent,         -1E+128)
3540 	DEF_VALUE	(SIZE, font, descent,        -1E+128)
3541 	DEF_VALUE	(SIZE, font, leading_height, -1E+128)
3542 	DEF_VALUE_OPT	(SIZE, font, advance,        -1E+128)
3543 	DEF_LABEL("ADVANCE")
3544 	DEF_VALUE	(SIZE, font, advance,        -1E+128)
3545 	DEF_LABEL("SPACE")
3546 	DEF_VALUE	(SIZE, font, space,          -1E+128)
3547 	DEF_LABEL("[KERNING]")
3548 	DEF_REPEAT()
3549 	DEF_SIZE(font_kerning)
3550 	DEF_SET		(font_kerning, type, FONT_TYPE_KERNING)
3551 	DEF_STRING	()
3552 	DEF_VALUE	(SIZE, font_kerning, x, 0.0)
3553   DEF_END()
3554 
3555   DEF_START(frame_label)
3556   DEF_END()
3557 
3558   DEF_START(function)
3559 	DEF_NOLABEL()
3560 	DEF_REPEAT()
3561 	DEF_OBJECT	(ACTION)
3562 	DEF_NOLABEL()
3563 	DEF_REPEAT()
3564 	DEF_OBJECT	(LABEL)
3565 	DEF_NOLABEL()
3566 	DEF_REPEAT()
3567 	DEF_OBJECT	(WITH)
3568 	DEF_NOLABEL()
3569 	DEF_REPEAT()
3570 	DEF_OBJECT	(TRY)
3571 	DEF_NOLABEL()
3572 	DEF_REPEAT()
3573 	DEF_OBJECT	(CATCH)
3574 	DEF_NOLABEL()
3575 	DEF_REPEAT()
3576 	DEF_OBJECT	(FINALLY)
3577 	DEF_NOLABEL()
3578 	DEF_REPEAT()
3579 	DEF_OBJECT	(FUNCTION)
3580 	DEF_NOLABEL()
3581 	DEF_REPEAT()
3582 	DEF_OBJECT	(LIST)
3583   DEF_END()
3584 
3585   DEF_START(glyph)
3586 	DEF_LABEL("[MOVE|OFFSET]")
3587 	DEF_REPEAT()
3588 	DEF_SIZE(move)
3589 	DEF_SET		(move, type, 3)
3590 	DEF_VALUE	(SIZE, move, tx, 0.0)		/* we could use a MATRIX object for this? */
3591 	DEF_VALUE	(SIZE, move, ty, 0.0)
3592 	DEF_NOLABEL()
3593 	DEF_REPEAT()
3594 	DEF_OBJECT	(RECT)
3595 	DEF_LABEL("FILL0")
3596 	DEF_REPEAT()
3597 	DEF_SIZE(fill_style)
3598 	DEF_SET		(fill_style, select, 0)
3599 	DEF_OBJECT	(FILL_STYLE)
3600 	DEF_NOLABEL()					/* FILL0 when unspecified */
3601 	DEF_REPEAT()
3602 	DEF_OBJECT	(FILL_STYLE)
3603 	DEF_NOLABEL()
3604 	DEF_REPEAT()
3605 	DEF_OBJECT	(EDGES)				/* turtle like points */
3606 	DEF_NOLABEL()
3607 	DEF_REPEAT()
3608 	DEF_OBJECT	(POINTS)			/* all points are zero based */
3609   DEF_END()
3610 
3611   DEF_START(gradient)
3612 	DEF_NOLABEL()
3613 	DEF_OBJECT	(MATRIX)
3614 	DEF_OBJECT_OPT	(MATRIX)
3615 	DEF_NOLABEL()
3616 	DEF_SIZE(gradient)
3617 	DEF_SET		(gradient, type, GRADIENT_TYPE_POSITION)
3618 	DEF_REPEAT()
3619 	DEF_VALUE	(RATIO, gradient, position,     0.0)
3620 	DEF_OBJECT	(COLOR)
3621 	DEF_VALUE_OPT	(RATIO, gradient, to_pos,       -1E+128)
3622 	DEF_OBJECT	(COLOR)
3623 	DEF_NOLABEL()
3624 	DEF_SIZE(gradient)
3625 	DEF_SET		(gradient, type, GRADIENT_TYPE_POSITION)
3626 	DEF_REPEAT()
3627 	DEF_OBJECT	(COLOR)
3628 	DEF_VALUE	(RATIO, gradient, position,     0.0)
3629 	DEF_OBJECT_OPT	(COLOR)
3630 	DEF_VALUE	(RATIO, gradient, to_pos,       -1E+128)
3631 	DEF_LABEL("FOCAL")
3632 	DEF_SIZE(gradient)
3633 	DEF_SET		(gradient, type, GRADIENT_TYPE_FOCAL)
3634 	DEF_VALUE	(SIZE, gradient, position,	0.0)
3635   DEF_END()
3636 
3637   DEF_START(image)
3638 	DEF_SIZE(image)
3639 	DEF_LABEL("LOSSLESS")
3640 	DEF_SET		(image, format, IMAGE_FORMAT_LOSSLESS)
3641 	DEF_STRING	()
3642 	DEF_STRING_OPT	()
3643 	DEF_LABEL("LOSSLESS8")
3644 	DEF_SET		(image, format, IMAGE_FORMAT_LOSSLESS_8)
3645 	DEF_STRING	()
3646 	DEF_STRING_OPT	()
3647 	DEF_LABEL("LOSSLESS16")
3648 	DEF_SET		(image, format, IMAGE_FORMAT_LOSSLESS_16)
3649 	DEF_STRING	()
3650 	DEF_STRING_OPT	()
3651 	DEF_LABEL("LOSSLESS32")
3652 	DEF_SET		(image, format, IMAGE_FORMAT_LOSSLESS_32)
3653 	DEF_STRING	()
3654 	DEF_STRING_OPT	()
3655 	DEF_LABEL("JPEG")
3656 	DEF_SET		(image, format, IMAGE_FORMAT_JPEG)
3657 	DEF_STRING	()
3658 	DEF_STRING_OPT	()
3659 	DEF_LABEL("QUALITY")
3660 	DEF_VALUE	(RATIO, image, quality, -1E+128)
3661   DEF_END()
3662 
3663   DEF_START(import)
3664 	DEF_LABEL("URL")
3665 	DEF_SIZE(import)
3666 	DEF_SET		(import, type, IMPORT_TYPE_URL)
3667 	DEF_STRING	()
3668 	DEF_LABEL("FILENAME")
3669 	DEF_SIZE(import)
3670 	DEF_SET		(import, type, IMPORT_TYPE_FILENAME)
3671 	DEF_STRING	()
3672 	DEF_LABEL("[NAME]")
3673 	DEF_SIZE(import)
3674 	DEF_SET		(import, type, IMPORT_TYPE_NAME)
3675 	DEF_REPEAT	()
3676 	DEF_STRING	()
3677 	DEF_STRING_OPT	()
3678   DEF_END()
3679 
3680   DEF_START(label)
3681 	DEF_NOLABEL()
3682 	DEF_STRING	()
3683   DEF_END()
3684 
3685   DEF_START(line_style)
3686 	DEF_EMPTY()
3687 	DEF_SIZE(line_style)
3688 	DEF_LABEL("[WIDTH]")
3689 	DEF_VALUE	(SIZE, line_style, width,	      1.0)
3690 	DEF_VALUE_OPT	(SIZE, line_style, to_width,	     -1.0)
3691 	DEF_NOLABEL()
3692 	DEF_OBJECT	(COLOR)
3693 	DEF_OBJECT_OPT	(COLOR)
3694 	DEF_NOLABEL()
3695 	DEF_OBJECT	(FILL_STYLE)
3696 	DEF_LABEL("CAPS")
3697 	DEF_VALUE	(UNKNOWN, line_style, cap_start,     -1.0)
3698 	DEF_VALUE_OPT	(UNKNOWN, line_style, cap_end,       -1.0)
3699 	DEF_LABEL("JOIN")
3700 	DEF_VALUE	(UNKNOWN, line_style, join,          -1.0)
3701 	DEF_VALUE_OPT	(UNKNOWN, line_style, miter,          0.0)
3702 	DEF_LABEL("SCALE")
3703 	DEF_VALUE	(UNKNOWN, line_style, hscale,        -1.0)
3704 	DEF_VALUE_OPT	(UNKNOWN, line_style, vscale,        -1.0)
3705 	DEF_LABEL("PIXEL_HINTING")
3706 	DEF_VALUE	(UNKNOWN, line_style, pixel_hinting, -1.0)
3707 	DEF_LABEL("NO_CLOSE")
3708 	DEF_VALUE	(UNKNOWN, line_style, no_close,      -1.0)
3709   DEF_END()
3710 
3711   DEF_START(list)
3712 	DEF_NOLABEL()
3713 	DEF_REPEAT()
3714 	DEF_OBJECT(UNKNOWN)
3715   DEF_END()
3716 
3717   DEF_START(matrix)
3718 	DEF_SIZE(matrix)
3719 	DEF_LABEL("SCALE")
3720 	DEF_VALUE	(RATIO, matrix, sx,    1.0)
3721 	DEF_VALUE_OPT	(RATIO, matrix, sy,    -1E+128)
3722 	DEF_LABEL("ROTATE")
3723 	DEF_VALUE	(ANGLE, matrix, angle, 0.0)
3724 	DEF_LABEL("TRANSLATE")
3725 	DEF_VALUE	(SIZE,  matrix, tx,    0.0)
3726 	DEF_VALUE	(SIZE,  matrix, ty,    0.0)
3727 	DEF_LABEL("SKEW")
3728 	DEF_VALUE	(SIZE,  matrix, skew0, 0.0)
3729 	DEF_VALUE	(SIZE,  matrix, skew1, 0.0)
3730   DEF_END()
3731 
3732   DEF_START(metadata)
3733 	DEF_EMPTY()
3734 	DEF_LABEL("FILENAME")
3735 	DEF_SIZE(metadata)
3736 	DEF_SET		(metadata, type, METADATA_TYPE_FILENAME)
3737 	DEF_STRING	()
3738 	DEF_LABEL("XML")
3739 	DEF_SIZE(metadata)
3740 	DEF_SET		(metadata, type, METADATA_TYPE_METADATA)
3741 	DEF_STRING	()
3742 	DEF_LABEL("TITLE")
3743 	DEF_SIZE(metadata)
3744 	DEF_SET		(metadata, type, METADATA_TYPE_TITLE)
3745 	DEF_STRING	()
3746 	DEF_LABEL("DESCRIPTION")
3747 	DEF_SIZE(metadata)
3748 	DEF_SET		(metadata, type, METADATA_TYPE_DESCRIPTION)
3749 	DEF_STRING	()
3750 	DEF_LABEL("AUTHOR")
3751 	DEF_SIZE(metadata)
3752 	DEF_SET		(metadata, type, METADATA_TYPE_AUTHOR)
3753 	DEF_STRING	()
3754 	DEF_LABEL("PUBLISHER")
3755 	DEF_SIZE(metadata)
3756 	DEF_SET		(metadata, type, METADATA_TYPE_PUBLISHER)
3757 	DEF_STRING	()
3758 	DEF_LABEL("COPYRIGHT")
3759 	DEF_SIZE(metadata)
3760 	DEF_SET		(metadata, type, METADATA_TYPE_COPYRIGHT)
3761 	DEF_STRING	()
3762 	DEF_LABEL("URL")
3763 	DEF_SIZE(metadata)
3764 	DEF_SET		(metadata, type, METADATA_TYPE_URL)
3765 	DEF_STRING	()
3766   DEF_END()
3767 
3768   DEF_START(on_event)
3769 	DEF_LABEL("EVENT|EVENTS")
3770 	DEF_SIZE(on_event)
3771 	DEF_SET		(on_event, type, ON_EVENT_TYPE_EVENT)
3772 	DEF_STRING	()
3773 	DEF_LABEL("KEY|KEY_CODE")
3774 	DEF_SIZE(on_event)
3775 	DEF_SET		(on_event, type, ON_EVENT_TYPE_KEY)
3776 	DEF_STRING	()
3777 	DEF_NOLABEL()
3778 	DEF_REPEAT()
3779 	DEF_OBJECT	(ACTION)
3780 	DEF_NOLABEL()
3781 	DEF_REPEAT()
3782 	DEF_OBJECT	(LABEL)
3783 	DEF_NOLABEL()
3784 	DEF_REPEAT()
3785 	DEF_OBJECT	(FUNCTION)
3786 	DEF_NOLABEL()
3787 	DEF_REPEAT()
3788 	DEF_OBJECT	(WITH)
3789 	DEF_NOLABEL()
3790 	DEF_REPEAT()
3791 	DEF_OBJECT	(TRY)
3792 	DEF_NOLABEL()
3793 	DEF_REPEAT()
3794 	DEF_OBJECT	(CATCH)
3795 	DEF_NOLABEL()
3796 	DEF_REPEAT()
3797 	DEF_OBJECT	(FINALLY)
3798   DEF_END()
3799 
3800   DEF_START(place_object)
3801 	DEF_SIZE(place_object)
3802 	DEF_LABEL("MORPH|POSITION")
3803 	DEF_VALUE	(RATIO,		place_object, position,	-1.0)
3804 	DEF_LABEL("DEPTH|LAYER")
3805 	DEF_VALUE	(UNKNOWN,	place_object, depth,	-1.0)
3806 	DEF_LABEL("CLIP|CLIPPING")
3807 	DEF_VALUE	(UNKNOWN,	place_object, clip,	-1E+128)
3808 	DEF_LABEL("TAB_INDEX")
3809 	DEF_VALUE	(UNKNOWN,	place_object, tab_index,-1E+128)
3810 	DEF_LABEL("CACHE_BITMAP")
3811 	DEF_VALUE	(BOOLEAN,	place_object, bitmap_caching, 0.0)
3812 	DEF_LABEL("ID|OBJ")
3813 	DEF_OBJECT_REF	()
3814 	DEF_NOLABEL()
3815 	DEF_OBJECT	(COLOR)
3816 	DEF_NOLABEL()
3817 	DEF_OBJECT	(COLOR_TRANSFORM)
3818 	DEF_NOLABEL()
3819 	DEF_OBJECT	(MATRIX)
3820 	DEF_NOLABEL()
3821 	DEF_OBJECT	(ON_EVENT)
3822 	DEF_LABEL("[NAME]")
3823 	DEF_SIZE(place_object)
3824 	DEF_SET		(place_object, type, PLACE_OBJECT_TYPE_NAME)
3825 	DEF_STRING	()
3826 	DEF_LABEL("BLEND_MODE")
3827 	DEF_SIZE(place_object)
3828 	DEF_SET		(place_object, type, PLACE_OBJECT_TYPE_BLEND_MODE)
3829 	DEF_STRING	()
3830   DEF_END()
3831 
3832   DEF_START(points)
3833 	DEF_LABEL("ROTATE")
3834 	DEF_SIZE(edges)
3835 	DEF_SET		(edges, type, EDGE_TYPE_ROTATE)
3836 	DEF_VALUE	(ANGLE, points, x1, 0.0)
3837 	DEF_NOLABEL()
3838 	DEF_REPEAT()
3839 	DEF_SIZE(points)
3840 	DEF_SET		(points, type, EDGE_TYPE_INTERMEDIATE)
3841 	DEF_VALUE	(SIZE, points, x1,	0.0)
3842 	DEF_VALUE	(SIZE, points, y1,	0.0)
3843 	DEF_VALUE_OPT	(SIZE, points, x2,	-1E+128)
3844 	DEF_VALUE	(SIZE, points, y2,	-1E+128)
3845 	DEF_LABEL("CLOSE")
3846 	DEF_REPEAT()
3847 	DEF_SIZE(points)
3848 	DEF_SET		(points, type, EDGE_TYPE_CLOSE)
3849 	DEF_VALUE	(SIZE, points, x1,	0.0)
3850 	DEF_VALUE	(SIZE, points, y1,	0.0)
3851 	DEF_VALUE_OPT	(SIZE, points, x2,	-1E+128)
3852 	DEF_VALUE	(SIZE, points, y2,	-1E+128)
3853   DEF_END()
3854 
3855   DEF_START(rect)
3856 	DEF_SIZE(rect)
3857 	DEF_NOLABEL()
3858 	DEF_VALUE	(SIZE, rect, min_x,	0.0)
3859 	DEF_VALUE	(SIZE, rect, min_y,	0.0)
3860 	DEF_VALUE	(SIZE, rect, max_x,	0.0)
3861 	DEF_VALUE	(SIZE, rect, max_y,	0.0)
3862   DEF_END()
3863 
3864   DEF_START(remove)
3865 	DEF_SIZE(remove)
3866 	DEF_LABEL("[DEPTH|LAYER]")
3867 	DEF_VALUE	(UNKNOWN, remove, depth, -1.0)
3868 	DEF_LABEL("ID|OBJ")
3869 	DEF_REPEAT()
3870 	DEF_OBJECT_REF	()
3871   DEF_END()
3872 
3873   DEF_START(sceneframedata)
3874 	DEF_LABEL("[FILENAME|DATA]")
3875 	DEF_STRING	()
3876   DEF_END()
3877 
3878   DEF_START(script_limits)
3879 	DEF_SIZE(script_limits)
3880 	DEF_LABEL("MAX_RECURSION_DEPTH|MAX|RECURSION|DEPTH")
3881 	DEF_VALUE	(UNKNOWN, script_limits, max_recursion_depth, 0)
3882 	DEF_LABEL("TIMEOUT_SECONDS|TIMEOUT|SECONDS")
3883 	DEF_VALUE	(TIME, script_limits, timeout_seconds, 0)
3884   DEF_END()
3885 
3886   DEF_START(sequence)
3887 	DEF_NOLABEL()
3888 	DEF_REPEAT()
3889 	DEF_OBJECT	(UNKNOWN)
3890   DEF_END()
3891 
3892   DEF_START(set_background_color)
3893 	DEF_NOLABEL()
3894 	DEF_OBJECT	(COLOR)
3895 	DEF_NOLABEL()
3896 	DEF_SIZE(color)
3897 	DEF_VALUE	(COLOR, color, red,   0.0)
3898 	DEF_VALUE	(COLOR, color, green, 0.0)
3899 	DEF_VALUE	(COLOR, color, blue,  0.0)
3900   DEF_END()
3901 
3902   DEF_START(set_tab_index)
3903 	DEF_SIZE(set_tab_index)
3904 	DEF_LABEL("DEPTH")
3905 	DEF_VALUE	(UNKNOWN, set_tab_index, depth, 0)
3906 	DEF_LABEL("TAB_INDEX")
3907 	DEF_VALUE	(UNKNOWN, set_tab_index, index, 0)
3908   DEF_END()
3909 
3910   DEF_START(shape)
3911 	DEF_LABEL("[MOVE|OFFSET]")
3912 	DEF_REPEAT()
3913 	DEF_SIZE(move)
3914 	DEF_SET		(move, type, 3)
3915 	DEF_VALUE	(SIZE, move, tx, 0.0)		/* we could use a MATRIX object for this? */
3916 	DEF_VALUE	(SIZE, move, ty, 0.0)
3917 	DEF_LABEL("MORPH|MODE|MORPH_MODE")
3918 	DEF_REPEAT()
3919 	DEF_SIZE(morph)
3920 	DEF_SET		(morph, type, 5)
3921 	DEF_VALUE	(UNKNOWN, morph, mode, 0.0)
3922 	DEF_NOLABEL()
3923 	DEF_REPEAT()
3924 	DEF_OBJECT	(RECT)
3925 	DEF_LABEL("SHOW_BOUNDS")
3926 	DEF_SIZE(shape)
3927 	DEF_SET		(shape, type, 2)
3928 	DEF_VALUE	(BOOLEAN, shape, show, 0.0)
3929 	DEF_LABEL("SHOW_ORIGIN")
3930 	DEF_SIZE(shape)
3931 	DEF_SET		(shape, type, 4)
3932 	DEF_VALUE	(BOOLEAN, shape, show, 0.0)
3933 	DEF_LABEL("FILL0")
3934 	DEF_REPEAT()
3935 	DEF_SIZE(fill_style)
3936 	DEF_SET		(fill_style, select, 0)
3937 	DEF_OBJECT	(FILL_STYLE)
3938 	DEF_LABEL("FILL1")
3939 	DEF_REPEAT()
3940 	DEF_SIZE(fill_style)
3941 	DEF_SET		(fill_style, select, 1)
3942 	DEF_OBJECT	(FILL_STYLE)
3943 	DEF_NOLABEL()					/* FILL0 when unspecified */
3944 	DEF_REPEAT()
3945 	DEF_OBJECT	(FILL_STYLE)
3946 	DEF_NOLABEL()
3947 	DEF_REPEAT()
3948 	DEF_OBJECT	(LINE_STYLE)
3949 	DEF_NOLABEL()
3950 	DEF_REPEAT()
3951 	DEF_OBJECT	(EDGES)				/* turtle like points */
3952 	DEF_NOLABEL()
3953 	DEF_REPEAT()
3954 	DEF_OBJECT	(POINTS)			/* all points are zero based */
3955 	DEF_NOLABEL()
3956 	DEF_REPEAT()
3957 	DEF_OBJECT	(LIST)
3958   DEF_END()
3959 
3960   DEF_START(show_frame)
3961 	DEF_SIZE(show_frame)
3962 	DEF_LABEL("[COUNT]")
3963 	DEF_VALUE	(TIME, show_frame, wait, 1)
3964   DEF_END()
3965 
3966   DEF_START(sound)
3967 	DEF_SIZE(sound)
3968 	DEF_LABEL("[FILENAME]")
3969 	DEF_SIZE(sound)
3970 	DEF_SET		(sound, type, SOUND_TYPE_FILENAME)
3971 	DEF_STRING	()
3972 	DEF_LABEL("FORMAT")
3973 	DEF_SIZE(sound)
3974 	DEF_SET		(sound, type, SOUND_TYPE_FORMAT)
3975 	DEF_STRING	()
3976 	DEF_LABEL("MONO")
3977 	DEF_VALUE	(BOOLEAN, sound, mono, 0.0)
3978 	DEF_LABEL("SET_8_BITS")
3979 	DEF_VALUE	(BOOLEAN, sound, set_8bits, 0.0)
3980   DEF_END()
3981 
3982   DEF_START(sound_info)
3983 	DEF_SIZE(sound_info)
3984 	DEF_LABEL("ID|OBJ")
3985 	DEF_OBJECT_REF	()
3986 	DEF_LABEL("STOP")
3987 	DEF_VALUE	(BOOLEAN, sound_info, stop, 0.0)
3988 	DEF_LABEL("NO_MULTIPLE")
3989 	DEF_VALUE	(BOOLEAN, sound_info, no_multiple, 0.0)
3990 	DEF_LABEL("RANGE")
3991 	DEF_VALUE	(TIME, sound_info, start, 0.0)
3992 	DEF_VALUE_OPT	(TIME, sound_info, end,   0.0)
3993 	DEF_LABEL("LOOP")
3994 	DEF_VALUE	(UNKNOWN, sound_info, loop, -1E+128)
3995 	DEF_LABEL("[ENVELOPE|ENVELOP|ENVELLOPE|ENVELLOP|ENVELOPPE|ENVELOPP]")	// accept some wrong syntaces for people like me
3996 	DEF_OBJECT	(ENVELOPE)
3997   DEF_END()
3998 
3999   DEF_START(sprite)
4000 	DEF_NOLABEL()
4001 	DEF_REPEAT()
4002 	DEF_OBJECT	(DO_ACTION)
4003 	DEF_NOLABEL()
4004 	DEF_REPEAT()
4005 	DEF_OBJECT	(PLACE_OBJECT)
4006 	DEF_NOLABEL()
4007 	DEF_REPEAT()
4008 	DEF_OBJECT	(REPLACE_OBJECT)
4009 	DEF_NOLABEL()
4010 	DEF_REPEAT()
4011 	DEF_OBJECT	(REMOVE)
4012 	DEF_NOLABEL()
4013 	DEF_REPEAT()
4014 	DEF_OBJECT	(SHOW_FRAME)
4015 	DEF_NOLABEL()
4016 	DEF_REPEAT()
4017 	DEF_OBJECT	(SOUND_INFO)
4018 	DEF_NOLABEL()
4019 	DEF_REPEAT()
4020 	DEF_OBJECT	(FRAME_LABEL)
4021 	DEF_NOLABEL()
4022 	DEF_REPEAT()
4023 	DEF_OBJECT	(LIST)		/* accepts insertion of lists */
4024 /* Elements still missing
4025         SoundStreamBlock
4026         SoundStreamHead
4027 */
4028   DEF_END()
4029 
4030   DEF_START(state)
4031 	DEF_SIZE(button)
4032 	DEF_LABEL("FLAGS")
4033 	DEF_VALUE	(UNKNOWN, button, state, 0)
4034 	DEF_LABEL("DEPTH|LAYER")
4035 	DEF_VALUE	(UNKNOWN, button, layer, 0)
4036 	DEF_LABEL("[MATRIX]")
4037 	DEF_OBJECT	(MATRIX)
4038 	DEF_LABEL("ID|OBJ")
4039 	DEF_OBJECT_REF	()
4040   DEF_END()
4041 
4042   DEF_START(text)
4043 	DEF_SIZE(text)
4044 	DEF_LABEL("ALIASING|THICKNESS_SHARPNESS")
4045 	DEF_VALUE	(SIZE, text, thickness,    -1E+128)
4046 	DEF_VALUE	(SIZE, text, sharpness,    -1E+128)
4047 	DEF_LABEL("RENDERER|FONT_ENGINE")
4048 	DEF_VALUE	(SIZE, text, renderer,     -1E+128)
4049 	DEF_LABEL("GRID|GRID_FIT")
4050 	DEF_VALUE	(SIZE, text, grid_fit,     -1E+128)
4051 	DEF_LABEL("[ADVANCE]")
4052 	DEF_SIZE(text)
4053 	DEF_REPEAT()
4054 	DEF_SET		(text, type, TEXT_TYPE_ADVANCE)
4055 	DEF_STRING	()
4056 	DEF_VALUE_OPT	(SIZE, text, advance, -1E+128)
4057 	DEF_NOLABEL()
4058 	DEF_REPEAT()
4059 	DEF_OBJECT	(TEXT_SETUP)
4060 	DEF_NOLABEL()
4061 	DEF_OBJECT	(MATRIX)
4062 	DEF_NOLABEL()
4063 	DEF_OBJECT	(RECT)
4064   DEF_END()
4065 
4066   DEF_START(text_setup)
4067   	DEF_SIZE(text_setup)
4068 	DEF_NOLABEL()
4069 	DEF_OBJECT	(COLOR)
4070 	DEF_LABEL("ID")
4071 	DEF_OBJECT_REF	()
4072 	DEF_VALUE_OPT	(SIZE, text_setup, height, 1024.0 / 20.0)
4073 	DEF_LABEL("[MOVE|OFFSET]")
4074 	DEF_VALUE	(SIZE, text_setup, x,      0)
4075 	DEF_VALUE_OPT	(SIZE, text_setup, y,      0)
4076   DEF_END()
4077 
4078   DEF_START(with)
4079 	DEF_NOLABEL()
4080 	DEF_REPEAT()
4081 	DEF_OBJECT	(ACTION)
4082 	DEF_NOLABEL()
4083 	DEF_REPEAT()
4084 	DEF_OBJECT	(LABEL)
4085 	DEF_NOLABEL()
4086 	DEF_REPEAT()
4087 	DEF_OBJECT	(WITH)
4088 	DEF_NOLABEL()
4089 	DEF_REPEAT()
4090 	DEF_OBJECT	(LIST)
4091   DEF_END()
4092 
4093 
4094 
4095 
4096 
4097 
4098 
4099 static int node_exec_nothing(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
4100 {
4101 	/* copy the result pointer quickly (avoid duplicating the buffer for nothing!) */
4102 	result->type = NODE_TYPE_DATA;
4103 	result->sub_type = r->sub_type;
4104 	assert(result->data == NULL, "result data pointer not NULL");
4105 	result->data = r->data;
4106 	r->data = NULL;
4107 
4108 	return 0;
4109 }
4110 
4111 
4112 
4113 
4114 
4115 
4116 
node_def_find_label(struct def_object_t * defobj,const char * name)4117 static struct def_label_t *node_def_find_label(struct def_object_t *defobj, const char *name)
4118 {
4119 	const char		*s, *d;
4120 	int			skip, cnt;
4121 	struct def_label_t	*label;
4122 
4123 	label = defobj->labels;
4124 	cnt = defobj->count;
4125 	while(cnt > 0) {
4126 		s = label->label;
4127 		if(s != NULL) {
4128 			d = name;
4129 			skip = 0;
4130 			while(*s != '\0') {
4131 				/* make _ in the label optional in the user name */
4132 				if(*s == '_' && *d != '_') {
4133 					s++;
4134 					continue;
4135 				}
4136 				/* mandatory label, just skip the [ and ] here */
4137 				if(*s != '[' && *s != ']') {
4138 					if(*s == '|') {
4139 						if(*d == '\0') {
4140 							/* we found a matching label! */
4141 							return label;
4142 						}
4143 						/* just a label separator, check the next label if necessary */
4144 						skip = 0;
4145 						d = name;
4146 					}
4147 					else if(!skip) {
4148 						if(toupper((unsigned char) *s) != toupper((unsigned char) *d)) {
4149 							skip = 1;
4150 						}
4151 						else {
4152 							d++;
4153 						}
4154 					}
4155 				}
4156 				s++;
4157 			}
4158 			if(*d == '\0') {
4159 				/* we found a matching label! */
4160 				return label;
4161 			}
4162 		}
4163 		cnt--;
4164 		label++;
4165 	}
4166 
4167 	fprintf(stderr, "ERROR: label \"%s\" not found for this object.\n", name);
4168 	errcnt++;
4169 
4170 	return NULL;
4171 }
4172 
4173 
4174 
node_def_print_entries(struct def_object_t * defobj,const char * indent)4175 static struct def_label_t *node_def_print_entries(struct def_object_t *defobj, const char *indent)
4176 {
4177 	struct def_label_t	*label;
4178 	struct def_entry_t	*entry;
4179 	enum node_type_t	type;
4180 	int			cnt, idx;
4181 
4182 	label = defobj->labels;
4183 	cnt = defobj->count;
4184 	while(cnt > 0) {
4185 		/* in this case we can't accept labelled entries */
4186 		if(label->label != NULL) {
4187 			fprintf(stderr, "%sLabel(s): %s\n", indent, label->label);
4188 		}
4189 		else {
4190 			fprintf(stderr, "%sNo label:\n", indent);
4191 		}
4192 		entry = label->entries;
4193 		idx = label->count;
4194 		while(idx > 0) {
4195 			type = entry->type;
4196 			fprintf(stderr, "%s  Type: %s [%d]", indent,
4197 					node_type_names[entry->type].name, entry->type);
4198 			if(entry->sub_type != NODE_SUBTYPE_UNKNOWN) {
4199 				fprintf(stderr, " (%s [%d])",
4200 					node_type_names[entry->sub_type].name, entry->sub_type);
4201 			}
4202 			fprintf(stderr, "\n");
4203 			entry++;
4204 			idx--;
4205 		}
4206 		label++;
4207 		cnt--;
4208 	}
4209 
4210 	return NULL;
4211 }
4212 
4213 
4214 
node_def_find_entry(struct def_object_t * defobj,struct node_t * result)4215 static struct def_label_t *node_def_find_entry(struct def_object_t *defobj, struct node_t *result)
4216 {
4217 	struct def_label_t	*label;
4218 	struct def_entry_t	*entry;
4219 	struct node_t		*n;
4220 	enum node_type_t	type;
4221 	int			cnt, idx;
4222 
4223 	label = defobj->labels;
4224 	cnt = defobj->count;
4225 	while(cnt > 0) {
4226 		/* in this case we can't accept labelled entries */
4227 		if(label->label == NULL || *label->label == '[') {
4228 			entry = label->entries;
4229 			idx = label->count;
4230 			n = result;
4231 			while(idx > 0 && n != NULL) {
4232 				type = n->type;
4233 				if(type == NODE_TYPE_INTEGER) {
4234 					/* we keep all the values as floating points in these data structures */
4235 					type = NODE_TYPE_FLOAT;
4236 				}
4237 				if(entry->type != type) {
4238 					/* incorrect type... */
4239 					break;
4240 				}
4241 				if(entry->sub_type != NODE_SUBTYPE_UNKNOWN) {
4242 					type = n->sub_type;
4243 					if(type == NODE_SUBTYPE_BLOCK) {
4244 						/* blocks and lists are equivalent! */
4245 						type = NODE_SUBTYPE_LIST;
4246 					}
4247 					if(entry->sub_type != type) {
4248 						/* incorrect sub-type */
4249 						break;
4250 					}
4251 				}
4252 				n = n->next;
4253 				entry++;
4254 				idx--;
4255 			}
4256 			if(n == NULL) {
4257 				if(idx > 0) {
4258 					/* if the current entry is optional, it worked */
4259 					if((entry->flags & DEF_ENTRY_FLAG_OPTIONAL) != 0) {
4260 						idx = 0;
4261 					}
4262 				}
4263 				if(idx == 0) {
4264 					/* we got it! */
4265 					return label;
4266 				}
4267 			}
4268 		}
4269 		label++;
4270 		cnt--;
4271 	}
4272 
4273 	return NULL;
4274 }
4275 
4276 
4277 
4278 
4279 
4280 
node_init_entry(struct def_entry_t * entry)4281 static void node_init_entry(struct def_entry_t *entry)
4282 {
4283 	entry->type     = NODE_TYPE_UNKNOWN;
4284 	entry->sub_type = NODE_SUBTYPE_UNKNOWN;
4285 	entry->unit     = NODE_UNIT_UNKNOWN;
4286 }
4287 
4288 
node_def2entry(const struct definition_t * p,struct def_object_t * defobj)4289 static int node_def2entry(const struct definition_t *p, struct def_object_t *defobj)
4290 {
4291 	int			label_idx, entry_idx, state, first_unit;
4292 	struct def_label_t	*label;
4293 	struct def_entry_t	*entry;
4294 
4295 #if _MSVC
4296 	assert(sizeof(struct def_ignore_t) == sizeof(struct definition_t)
4297 		&& sizeof(struct def_size_t) == sizeof(struct definition_t)
4298 		&& sizeof(struct def_offset_t) == sizeof(struct definition_t)
4299 		&& sizeof(struct def_set_t) == sizeof(struct definition_t)
4300 		&& sizeof(struct def_def_value_t) == sizeof(struct definition_t)
4301 		&& sizeof(struct def_type_t) == sizeof(struct definition_t)
4302 		&& sizeof(struct def_unit_t) == sizeof(struct definition_t)
4303 		&& sizeof(struct def_string_t) == sizeof(struct definition_t),
4304 				"a sub-structure used to define the node entries has an invalid size");
4305 	// we should also assert each offset!
4306 	assert(offsetof(struct def_ignore_t, ignored) == offsetof(struct definition_t, data.ignored)
4307 		&& offsetof(struct def_size_t, size) == offsetof(struct definition_t, data.size)
4308 		&& offsetof(struct def_offset_t, offset) == offsetof(struct definition_t, data.offset)
4309 		&& offsetof(struct def_set_t, set) == offsetof(struct definition_t, data.set),
4310 				"a sub-structure used to define the node entries has data at an invalid offset");
4311 #endif
4312 
4313 	/* by default all zeroes! */
4314 	memset(defobj, 0, sizeof(struct def_object_t));
4315 
4316 	label = defobj->labels;
4317 	entry = defobj->entries;
4318 
4319 	first_unit = 1;
4320 	state = 0;
4321 	label_idx = -1;
4322 	entry_idx = -1;
4323 	for(;;) {
4324 #if DEBUG
4325 		switch(p->param) {
4326 		case DEF_PARAM_END:
4327 		case DEF_PARAM_NAME:
4328 		case DEF_PARAM_LABEL:
4329 		case DEF_PARAM_UNIT:
4330 		case DEF_PARAM_SIZE:
4331 		/*case DEF_PARAM_SEPARATOR:*/
4332 		case DEF_PARAM_EMPTY:
4333 			break;
4334 
4335 		default:
4336 			assert(state != 0, "a DEF_PARAM_TYPE found without a DEF_PARAM_LABEL");
4337 			break;
4338 
4339 		}
4340 #endif
4341 		switch(p->param) {
4342 		case DEF_PARAM_END:
4343 			return 0;
4344 
4345 		/*
4346 		case DEF_PARAM_SEPARATOR:
4347 			defobj->flags |= DEF_OBJECT_FLAG_DEFINITION;
4348 			break;
4349 		*/
4350 
4351 		case DEF_PARAM_NAME:
4352 			defobj->name = p->data.string;
4353 			break;
4354 
4355 		case DEF_PARAM_LABEL:
4356 			/* a new labelled entry */
4357 			label_idx++;
4358 			assert(label_idx < DEF_LABEL_MAX, "too many labels; please enlarge DEF_LABEL_MAX in node.c");
4359 			defobj->count++;
4360 			label[label_idx].label = p->data.string;
4361 			/* no entry required first, we add 1 anyway */
4362 			label[label_idx].entries = entry + entry_idx + 1;
4363 			state = 1;
4364 			break;
4365 
4366 		case DEF_PARAM_TYPE:
4367 			entry_idx++;
4368 			// if we have a label, increment the counter
4369 			if(label_idx >= 0) {
4370 				label[label_idx].count++;
4371 			}
4372 			assert(entry_idx < DEF_ENTRY_MAX, "too many entries; please enlarge DEF_ENTRY_MAX in node.c");
4373 			node_init_entry(entry + entry_idx);
4374 			entry[entry_idx].type = p->data.type;
4375 			state = 2;
4376 			switch(p->data.type) {
4377 			case NODE_TYPE_INTEGER:		/* this can't be used at this time... but for the sake of completeness we have it here */
4378 			case NODE_TYPE_FLOAT:
4379 				break;
4380 
4381 			/* anything else requires us to have a list */
4382 			case NODE_TYPE_OBJECT:		/* request for an object reference */
4383 				assert(label_idx >= 0 && label[label_idx].label != NULL && strlen(label[label_idx].label) > 0,
4384 							"cannot have an object reference without a label");
4385 				entry[entry_idx].flags |= DEF_ENTRY_FLAG_REFERENCE;
4386 				/*FALLTHROUGH*/
4387 			default:
4388 				defobj->flags |= DEF_OBJECT_FLAG_HAS_LIST;
4389 				break;
4390 
4391 			}
4392 			break;
4393 
4394 		case DEF_PARAM_SUBTYPE:
4395 			assert(entry_idx >= 0, "cannot define a sub-type without first defining a type");
4396 			entry[entry_idx].sub_type = p->data.type;
4397 			break;
4398 
4399 		case DEF_PARAM_UNIT:
4400 			if(first_unit) {
4401 				defobj->default_unit = p->data.unit;
4402 				first_unit = 0;
4403 			}
4404 			assert(entry_idx >= 0, "cannot define a unit without first defining a type");
4405 			entry[entry_idx].unit = p->data.unit;
4406 			break;
4407 
4408 		case DEF_PARAM_OFFSET:
4409 			if(state == 1) {
4410 				label[label_idx].offset = p->data.offset;
4411 				label[label_idx].flags |= DEF_LABEL_FLAG_HAS_OFFSET;
4412 			}
4413 			else {
4414 				assert(entry_idx >= 0, "cannot define an offset without first defining a label or a type");
4415 				entry[entry_idx].offset = p->data.offset;
4416 				entry[entry_idx].flags |= DEF_ENTRY_FLAG_HAS_OFFSET;
4417 			}
4418 			break;
4419 
4420 		case DEF_PARAM_SIZE:
4421 			if(state == 0) {
4422 				defobj->size = p->data.size;
4423 			}
4424 			else {
4425 				assert(label_idx >= 0, "cannot have a size without a label unless it appears first");
4426 				label[label_idx].size = p->data.size;
4427 			}
4428 			break;
4429 
4430 		case DEF_PARAM_SET:
4431 			assert(label_idx >= 0, "cannot set a value without first having a label");
4432 			label[label_idx].set = p->data.set;
4433 			label[label_idx].flags |= DEF_LABEL_FLAG_HAS_SET;
4434 			break;
4435 
4436 		case DEF_PARAM_DEFAULT:
4437 			assert(entry_idx >= 0, "cannot define a default value without first defining a type");
4438 			entry[entry_idx].def_value = p->data.def_value;
4439 			entry[entry_idx].flags |= DEF_ENTRY_FLAG_HAS_DEFAULT;
4440 			break;
4441 
4442 		case DEF_PARAM_REPEAT:
4443 			if(state == 1) {
4444 				/* the entry as a whole can be repeated */
4445 				label[label_idx].flags |= DEF_LABEL_FLAG_REPEAT;
4446 			}
4447 			else {
4448 				assert(entry_idx >= 0, "cannot define repeatition without first defining a label or a type");
4449 				entry[entry_idx].flags |= DEF_ENTRY_FLAG_REPEAT;
4450 			}
4451 			break;
4452 
4453 		case DEF_PARAM_OPTIONAL:
4454 			assert(entry_idx >= 0, "cannot mark a type as optional without first defining said type");
4455 			entry[entry_idx].flags |= DEF_ENTRY_FLAG_OPTIONAL;
4456 			break;
4457 
4458 		case DEF_PARAM_EMPTY:
4459 			/* accept empty entry if this flag is set or
4460 			 * defobj->count is zero
4461 			 */
4462 			defobj->flags |= DEF_OBJECT_FLAG_EMPTY;
4463 			break;
4464 
4465 		default:
4466 			assert(0, "unsupported DEF_PARAM_... (%d)", p->param);
4467 			/*NOTREACHED*/
4468 
4469 		}
4470 		p++;
4471 	}
4472 	/*NOTREACHED*/
4473 }
4474 
4475 
node_label_defaults(const struct def_label_t * label,char * data)4476 static void node_label_defaults(const struct def_label_t *label, char *data)
4477 {
4478 	const struct def_entry_t	*entry;
4479 	int				cnt;
4480 
4481 	entry = label->entries;
4482 	cnt = label->count;
4483 	while(cnt > 0) {
4484 		cnt--;
4485 		/* if we have a default value and an offset we can save that! */
4486 		if((entry->flags & (DEF_ENTRY_FLAG_HAS_OFFSET | DEF_ENTRY_FLAG_HAS_DEFAULT)) == (DEF_ENTRY_FLAG_HAS_OFFSET | DEF_ENTRY_FLAG_HAS_DEFAULT)) {
4487 			* (double *) (data + entry->offset) = entry->def_value;
4488 		}
4489 		entry++;
4490 	}
4491 }
4492 
4493 
node_alloc_data(int length,struct node_t * name,const char * nm,enum node_type_t type,struct node_t * node,const char * info)4494 static struct data_common_t *node_alloc_data(int length, struct node_t *name, const char *nm, enum node_type_t type, struct node_t *node, const char *info)
4495 {
4496 	struct data_common_t	*data;
4497 	int			l;
4498 
4499 	if(nm == NULL && name != NULL && name->left != NULL) {
4500 		nm = name->left->string;
4501 	}
4502 
4503 	if(nm == NULL || *nm == '\0') {
4504 		l = 0;
4505 	}
4506 	else {
4507 		l = strlen(nm);
4508 		if(l > 0) {
4509 			l = SSWF_MEM_ALIGN(l + 1);
4510 		}
4511 	}
4512 	length += sizeof(struct data_common_t) + l;
4513 	data = sswf_malloc(length, info);
4514 	data->length = length;
4515 	data->type = type;
4516 	data->label = NULL;
4517 	data->node = node;
4518 	data->name_len = l;
4519 	if(l > 0) {
4520 		strcpy(data->name, nm);
4521 	}
4522 
4523 	return data;
4524 }
4525 
4526 
node_def_to_data(struct node_t * expr,const struct def_label_t * label,struct node_t * result,char * data)4527 static struct data_common_t *node_def_to_data(struct node_t *expr, const struct def_label_t *label, struct node_t *result, char *data)
4528 {
4529 	const struct def_entry_t	*entry;
4530 	enum node_type_t		type;
4531 	struct data_common_t		*buf;
4532 	struct data_list_t		*list;
4533 	struct node_t			*n;
4534 	char				*dst, *str;
4535 	struct data_common_t		**array, *quick_array[DEF_ENTRY_MAX + 1];
4536 	int				idx, l, length, max, total_size;
4537 
4538 	n = result;
4539 	max = 1;
4540 	while(n != NULL) {
4541 		max++;
4542 		n = n->next;
4543 	}
4544 
4545 	if(max > DEF_ENTRY_MAX + 1) {
4546 		array = sswf_malloc(max * sizeof(struct data_common_t *), "node_def_to_data() - large array");
4547 	}
4548 	else {
4549 		array = quick_array;
4550 	}
4551 
4552 	total_size = 0;
4553 
4554 	if(label->size != 0) {
4555 		/* got to allocate one buffer per label for this one! */
4556 		data = sswf_malloc(label->size, "node_def_to_data() - label specific sub-buffer");
4557 		memset(data, 0, label->size);
4558 		node_label_defaults(label, data);
4559 		total_size += SSWF_MEM_ALIGN(label->size);
4560 		array[0] = (struct data_common_t *) data;
4561 		idx = 1;
4562 	}
4563 	else {
4564 		idx = 0;
4565 	}
4566 
4567 	if((label->flags & (DEF_LABEL_FLAG_HAS_SET | DEF_LABEL_FLAG_HAS_OFFSET)) == (DEF_LABEL_FLAG_HAS_SET | DEF_LABEL_FLAG_HAS_OFFSET)) {
4568 		/* we have a value SET */
4569 		assert(data != NULL, "DEF_PARAM_SET without a SIZE parameter");
4570 		* (long *) (data + label->offset) = label->set;
4571 	}
4572 
4573 	entry = label->entries;
4574 	while(result != NULL) {		/* we don't check the entry counter since that was already done */
4575 		buf = NULL;
4576 		switch(result->type) {
4577 		case NODE_TYPE_OBJECT:
4578 			if(result->sub_type != NODE_SUBTYPE_REFERENCE) {
4579 				goto unknown;
4580 			}
4581 			type = result->sub_type;
4582 			str = result->string;
4583 			goto save_string;
4584 
4585 		case NODE_TYPE_FLOAT:
4586 			assert(data != NULL, "DEF_PARAM_VALUE without a SIZE parameter");
4587 			* (double *) (data + entry->offset) = result->floating_point;
4588 			break;
4589 
4590 		case NODE_TYPE_INTEGER:
4591 			assert(data != NULL, "DEF_PARAM_VALUE without a SIZE parameter");
4592 			* (double *) (data + entry->offset) = (double) result->integer;
4593 			break;
4594 
4595 		case NODE_TYPE_STRING:
4596 			type = NODE_TYPE_STRING;
4597 			str = result->string;
4598 save_string:
4599 			/* save this data in the result so it gets freed once
4600 			 * the result node is being cleaned up */
4601 			assert(result->data == NULL, "result->data isn't null here -- memory leak");
4602 			result->data = node_alloc_data(0, NULL, str, type, expr, "node_def_to_data() - sub-buffer for a string");
4603 			sswf_clean(&result->string);
4604 			result->type = NODE_TYPE_DATA;
4605 			result->sub_type = type;
4606 			/*FALLTHROUGH*/
4607 		case NODE_TYPE_DATA:
4608 			assert(result->data != NULL, "a DATA node without data was found");
4609 			array[idx] = result->data;
4610 			idx++;
4611 			total_size += result->data->length;
4612 			assert(total_size == (int) SSWF_MEM_ALIGN(total_size), "node_def_to_data(): invalid total_size alignment - a result->data->length has an invalid size (label: \"%s\")", result->data->name_len > 0 ? result->data->name : "<no name>");
4613 			break;
4614 
4615 		default:
4616 unknown:
4617 			assert(0, "unrecognized type in result for object definition");
4618 			/*NOTREACHED*/
4619 
4620 		}
4621 		entry++;
4622 		result = result->next;
4623 	}
4624 
4625 	/* it all worked, now we can merge all the buffers in the resulting array */
4626 	if(total_size > 0 || data == NULL) {
4627 		length =
4628 			/* header included in node_alloc_data() (no name) */
4629 			  /*sizeof(struct data_common_t)*/
4630 			/* list header + offsets */
4631 			  SSWF_MEM_ALIGN(sizeof(struct data_list_t) + idx * sizeof(long))
4632 			/* the contents of the list */
4633 			+ total_size;
4634 		buf = node_alloc_data(length, NULL, NULL, NODE_SUBTYPE_DEFINITION, expr, "node_def_to_data() -- list of sub-buffers");
4635 		list = (struct data_list_t *) (buf + 1);	/* == dc_list(buf) */
4636 		list->count = idx;
4637 		dst = (char *) list + SSWF_MEM_ALIGN(sizeof(struct data_list_t) + idx * sizeof(long));
4638 
4639 #if 0
4640 printf("  We are creating a sub_data here! (total_size = %d, list->count = %d) %p -> %p\n", total_size, idx,
4641 				array[0], buf);
4642 #endif
4643 
4644 		if(label->size != 0) {
4645 			/* the first entry is the label specific data when there is one */
4646 			/* WARNING: negative offset to specify that this entry doesn't have a data_commont_t structure */
4647 			list->offset[0] = (char *) list - dst;
4648 			memcpy(dst, data, label->size);
4649 			sswf_free(data);
4650 			dst += SSWF_MEM_ALIGN(label->size);
4651 			l = 1;
4652 		}
4653 		else {
4654 			l = 0;
4655 		}
4656 		while(l < idx) {
4657 			length = array[l]->length;
4658 			list->offset[l] = dst - (char *) list;
4659 			memcpy(dst, array[l], length);
4660 			dst += length;
4661 			l++;
4662 		}
4663 	}
4664 	else {
4665 		buf = NULL;
4666 	}
4667 
4668 	if(array != quick_array) {
4669 		sswf_free(array);
4670 	}
4671 
4672 	return buf;
4673 }
4674 
4675 
4676 /* WARNING: this function frees the sub_data buffer as required */
node_def_merge_data(struct node_t * expr,const struct def_object_t * defobj,struct data_common_t * data,struct data_common_t * sub_data)4677 static struct data_common_t *node_def_merge_data(struct node_t *expr, const struct def_object_t *defobj, struct data_common_t *data, struct data_common_t *sub_data)
4678 {
4679 	struct data_list_t	*src_list, *dst_list;
4680 	struct node_t		*name;
4681 	int			idx, l, l1, l2, length, length1, length2;
4682 	char			*src, *dst, *ptr;
4683 
4684 	if(sub_data == NULL) {
4685 		return data;
4686 	}
4687 
4688 	/*
4689 	 * NOTE: the sub_data is ALWAYS a NODE_SUBTYPE_DEFINITION so the following works
4690 	 *	 don't call this function otherwise!
4691 	 */
4692 	assert(sub_data->type == NODE_SUBTYPE_DEFINITION, "invalid sub_data type; not a NODE_SUBTYPE_DEFINITION");
4693 
4694 	if(data == NULL) {
4695 		/*
4696 		 * No data yet, just return the sub_data with the NODE_SUBTYPE_DEFINITION header
4697 		 * transform in this object entry
4698 		 */
4699 		name = expr->left;
4700 		if(name != NULL) {
4701 			l = strlen(name->string);
4702 			if(l > 0) {
4703 #if 0
4704 fflush(stdout);
4705 fprintf(stderr, "    Merge adding name [%s] to sub_data.\n", name->string);
4706 #endif
4707 				/* we have to add the name! */
4708 				l = SSWF_MEM_ALIGN(l + 1);
4709 				sub_data->name_len = l;
4710 				length = sub_data->length + l;
4711 				sub_data = sswf_remalloc(sub_data, length, "node_def_merge_data() -- name the data buffer");
4712 				memmove((char *) (sub_data + 1) + l, sub_data + 1, sub_data->length - sizeof(struct data_common_t));
4713 				strcpy(sub_data->name, name->string);
4714 				sub_data->length = length;
4715 			}
4716 		}
4717 		sub_data->type = expr->sub_type;
4718 		data = sub_data;
4719 	}
4720 	else {
4721 		/* ha! there is an existing entry, we have to append each sub_data entries in it */
4722 		src_list = dc_list(sub_data);
4723 		dst_list = dc_list(data);
4724 		l1 = src_list->count * sizeof(long);
4725 		l2 = dst_list->count * sizeof(long);
4726 		src = (char *) src_list + SSWF_MEM_ALIGN(l1 + sizeof(struct data_list_t));
4727 								// src point to the 1st entry in the sub_data list
4728 		dst = (char *) dst_list + SSWF_MEM_ALIGN(l2 + sizeof(struct data_list_t));
4729 								// dst points to the 1st entry in the data list
4730 		length1 = sub_data->length - (src - (char *) sub_data);
4731 		length2 = data->length     - (dst - (char *) data);
4732 
4733 		assert(length1 == (int) SSWF_MEM_ALIGN(length1), "node_def_merge_data(): length of sub_data not properly aligned");
4734 		assert(length2 == (int) SSWF_MEM_ALIGN(length2), "node_def_merge_data(): length of data not properly aligned");
4735 
4736 		/*
4737 		 * The new length is the length of the data & sub_data contents and
4738 		 * a new list we have to properly align plus the usual common and
4739 		 * list headers.
4740 		 */
4741 		length =
4742 			/* common header + name */
4743 			   sizeof(struct data_common_t)
4744 			 + data->name_len
4745 			/* list header + space for offsets */
4746 			 + SSWF_MEM_ALIGN(sizeof(struct data_list_t) + l1 + l2)
4747 			/* size of the data of both lists */
4748 			 + length1 + length2;
4749 
4750 		/*length = data->length + sub_data->length - ((char *) (src_list + 1) - (char *) sub_data);*/
4751 
4752 		data = sswf_remalloc(data, length, "node_def_merge_data() -- append sub_data to data buffer");
4753 		data->length = length;
4754 
4755 		/*
4756 		 * the dst_list pointer certainly changed with the remalloc() -- we need to fix
4757 		 * all the pointers depending on data (the sizes are still valid!)
4758 		 */
4759 		dst_list = dc_list(data);
4760 		dst = (char *) dst_list + SSWF_MEM_ALIGN(l2 + sizeof(struct data_list_t));
4761 
4762 
4763 		/* move the existing data and adjust their offsets */
4764 		ptr = (char *) dst_list + SSWF_MEM_ALIGN(l1 + l2 + sizeof(struct data_list_t));
4765 		memmove(ptr, dst, length2);
4766 
4767 		l = ptr - dst;
4768 		idx = dst_list->count;
4769 		while(idx > 0) {
4770 			idx--;
4771 			if(dst_list->offset[idx] < 0) {
4772 				dst_list->offset[idx] -= l;
4773 			}
4774 			else {
4775 				dst_list->offset[idx] += l;
4776 			}
4777 		}
4778 
4779 		/* copy the sub_data offsets */
4780 		memcpy(dst_list->offset + dst_list->count, src_list->offset, l1);
4781 
4782 		/* compute the position where the sub_data contents needs to be copied, copy it & save the new length of data */
4783 		ptr += length2;
4784 		memcpy(ptr, src, length1);
4785 
4786 		/* adjust the copied sub_data offsets */
4787 		l = (ptr - (char *) dst_list) - labs(src_list->offset[0]);
4788 		l2 = dst_list->count;
4789 		idx = l2 + src_list->count;
4790 		while(idx > l2) {
4791 			idx--;
4792 			if(dst_list->offset[idx] < 0) {
4793 				dst_list->offset[idx] -= l;
4794 			}
4795 			else {
4796 				dst_list->offset[idx] += l;
4797 			}
4798 		}
4799 		dst_list->count += src_list->count;	/* now that's inserted! */
4800 
4801 		/* we're done with sub_data, get rid of it */
4802 		sswf_free(sub_data);
4803 	}
4804 
4805 	assert(data->node == expr, "node_def_merge_data() -- node != expr");
4806 
4807 	return data;
4808 }
4809 
4810 
4811 
node_def_data(struct node_t * expr,char * obj_struct,size_t size)4812 static struct data_common_t *node_def_data(struct node_t *expr, char *obj_struct, size_t size)
4813 {
4814 	struct data_common_t	*data;
4815 
4816 	data = node_alloc_data(SSWF_MEM_ALIGN(size), expr, NULL, expr->sub_type, expr, "node_def_data() -- simple object data");
4817 	if(size > 0) {
4818 		memcpy((char *) (data + 1) + data->name_len, obj_struct, size);
4819 	}
4820 
4821 	return data;
4822 }
4823 
4824 
node_def_insertdata(struct node_t * expr,struct data_common_t * data,char * obj_struct,size_t size)4825 static struct data_common_t *node_def_insertdata(struct node_t *expr, struct data_common_t *data, char *obj_struct, size_t size)
4826 {
4827 	struct data_list_t	*list;
4828 	char			*d, *p;
4829 	int			l, ld, length;
4830 
4831 	/* in this case the data is the very first entry in the data list */
4832 	if(data == NULL) {
4833 		/* no data yet, create the whole thing at once */
4834 		length = SSWF_MEM_ALIGN(sizeof(struct data_list_t) + sizeof(long)) + SSWF_MEM_ALIGN(size);
4835 		data = node_alloc_data(length, expr, NULL, expr->sub_type, expr, "node_def_insertdata() -- new data buffer");
4836 		list = dc_list(data);
4837 		d = (char *) list + SSWF_MEM_ALIGN(sizeof(struct data_list_t) + sizeof(long));
4838 		list->count = 1;
4839 		list->offset[0] = (char *) list - d;	/* a negative result! */
4840 		memcpy(d, obj_struct, size);
4841 	}
4842 	else {
4843 		/* in this case we have to actually insert the data within the existing list */
4844 		list = dc_list(data);
4845 		l = (list->count + 1) * sizeof(long);
4846 		ld = (((char *) data + data->length) - ((char *) list + labs(list->offset[0])));
4847 		assert(ld == (int) SSWF_MEM_ALIGN(ld), "node_def_insertdata(): length of sub_data not properly aligned");
4848 		length =
4849 			/* common header + name */
4850 			  sizeof(struct data_common_t)
4851 			+ data->name_len
4852 			/* the list including the new item */
4853 			+ SSWF_MEM_ALIGN(sizeof(struct data_list_t) + l)
4854 			/* the old data */
4855 			+ ld
4856 			/* the new data */
4857 			+ SSWF_MEM_ALIGN(size);
4858 
4859 		data = sswf_remalloc(data, length, "node_def_insertdata() -- insert data buffer");
4860 		data->length = length;
4861 
4862 		/* the remalloc() most probably changed the data pointer */
4863 		list = dc_list(data);
4864 
4865 		/* move the old data to make room for the new one
4866 		 * copy the new data
4867 		 * move the old offsets
4868 		 * compute the new offset
4869 		 */
4870 		d = (char *) list + SSWF_MEM_ALIGN(sizeof(struct data_list_t) + l);
4871 		p = (char *) list + SSWF_MEM_ALIGN(sizeof(struct data_list_t) + l - sizeof(long));
4872 		memmove(d + SSWF_MEM_ALIGN(size), p, ld);
4873 		memcpy(d, obj_struct, size);
4874 		memmove(list->offset + 1, list->offset, sizeof(long) * list->count);
4875 		list->offset[0] = (char *) list - d;		/* a negative result! */
4876 
4877 		/* adjust the "old" offsets now */
4878 		ld = (d + SSWF_MEM_ALIGN(size)) - (char *) list - labs(list->offset[1]);
4879 		l = list->count;
4880 		while(l > 0) {
4881 			if(list->offset[l] < 0) {
4882 				list->offset[l] -= ld;
4883 			}
4884 			else {
4885 				list->offset[l] += ld;
4886 			}
4887 			l--;
4888 		}
4889 		list->count++;
4890 	}
4891 
4892 	return data;
4893 }
4894 
4895 
node_def_empty(struct node_t * expr)4896 static struct data_common_t *node_def_empty(struct node_t *expr)
4897 {
4898 	return node_alloc_data(0, expr, NULL, expr->sub_type, expr, "node_def_empty() -- empty entry");
4899 }
4900 
4901 
4902 
node_print_data0(const struct data_common_t * data,int indent)4903 void node_print_data0(const struct data_common_t *data, int indent)
4904 {
4905 	struct data_type_t {
4906 		enum node_type_t	type;
4907 		const char *		name;
4908 		int			flags;
4909 	};
4910 
4911 #define	DATA_TYPE_MASK_DATA		0x000000FF
4912 	enum data_type_struct_t {
4913 		DATA_TYPE_STRUCT_UNKNOWN = 0,
4914 		DATA_TYPE_STRUCT_COLOR,
4915 		DATA_TYPE_STRUCT_COLOR_TRANSFORM,
4916 		DATA_TYPE_STRUCT_EDGES,
4917 		DATA_TYPE_STRUCT_EDIT_TEXT,
4918 		DATA_TYPE_STRUCT_EMPTY,
4919 		DATA_TYPE_STRUCT_FONT,
4920 		DATA_TYPE_STRUCT_GRADIENT,
4921 		DATA_TYPE_STRUCT_IMAGE,
4922 		DATA_TYPE_STRUCT_LINE_STYLE,
4923 		DATA_TYPE_STRUCT_MATRIX,
4924 		DATA_TYPE_STRUCT_ACTION_SCRIPT,
4925 		DATA_TYPE_STRUCT_PLACE_OBJECT,
4926 		DATA_TYPE_STRUCT_POINTS,
4927 		DATA_TYPE_STRUCT_RECT,
4928 		DATA_TYPE_STRUCT_SHAPE_MOVE,
4929 		DATA_TYPE_STRUCT_SHOW_FRAME,
4930 		DATA_TYPE_STRUCT_STATE,
4931 		DATA_TYPE_STRUCT_TEXT,
4932 		DATA_TYPE_STRUCT_TEXT_SETUP,
4933 
4934 		DATA_TYPE_STRUCT_max
4935 	};
4936 
4937 #define	DATA_TYPE_FLAG_LIST		0x00000100
4938 #define	DATA_TYPE_FLAG_STRING		0x00000200
4939 
4940 	static const struct data_type_t		data_names[] = {
4941 		{
4942 			NODE_TYPE_STRING,		/* a special case - the "name" is the actual string */
4943 			"string",
4944 			DATA_TYPE_FLAG_STRING
4945 		},
4946 		{
4947 			NODE_SUBTYPE_ACTION,
4948 			"action",
4949 			0
4950 		},
4951 		{
4952 			NODE_SUBTYPE_ACTION_SCRIPT,
4953 			"action_script",
4954 			DATA_TYPE_STRUCT_ACTION_SCRIPT
4955 		},
4956 		{
4957 			NODE_SUBTYPE_BLOCK,
4958 			"block",
4959 			DATA_TYPE_FLAG_LIST
4960 		},
4961 		{
4962 			NODE_SUBTYPE_BUTTON,
4963 			"button",
4964 			DATA_TYPE_FLAG_LIST
4965 		},
4966 		{
4967 			NODE_SUBTYPE_CATCH,
4968 			"catch",
4969 			DATA_TYPE_FLAG_LIST
4970 		},
4971 		{
4972 			NODE_SUBTYPE_COLOR,
4973 			"color",
4974 			DATA_TYPE_STRUCT_COLOR
4975 		},
4976 		{
4977 			NODE_SUBTYPE_COLOR_TRANSFORM,
4978 			"color transform",
4979 			DATA_TYPE_STRUCT_COLOR_TRANSFORM
4980 		},
4981 		{
4982 			NODE_SUBTYPE_DO_ACTION,
4983 			"do action",
4984 			DATA_TYPE_FLAG_LIST
4985 		},
4986 		{
4987 			NODE_SUBTYPE_EDGES,
4988 			"edges",
4989 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_EDGES
4990 		},
4991 		{
4992 			NODE_SUBTYPE_EDIT_TEXT,
4993 			"edit text",
4994 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_EDIT_TEXT
4995 		},
4996 		{
4997 			NODE_SUBTYPE_FILL_STYLE,
4998 			"fill style",
4999 			DATA_TYPE_FLAG_LIST
5000 		},
5001 		{
5002 			NODE_SUBTYPE_FINALLY,
5003 			"finally",
5004 			DATA_TYPE_FLAG_LIST
5005 		},
5006 		{
5007 			NODE_SUBTYPE_FONT,
5008 			"font",
5009 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_FONT
5010 		},
5011 		{
5012 			NODE_SUBTYPE_FUNCTION,
5013 			"function",
5014 			DATA_TYPE_FLAG_LIST
5015 		},
5016 		{
5017 			NODE_SUBTYPE_GRADIENT,
5018 			"gradient",
5019 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_GRADIENT
5020 		},
5021 		{
5022 			NODE_SUBTYPE_IMAGE,
5023 			"image",
5024 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_IMAGE
5025 		},
5026 		{
5027 			NODE_SUBTYPE_LINE_STYLE,
5028 			"line style",
5029 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_LINE_STYLE
5030 		},
5031 		{
5032 			NODE_SUBTYPE_LIST,
5033 			"list",
5034 			DATA_TYPE_FLAG_LIST
5035 		},
5036 		{
5037 			NODE_SUBTYPE_MATRIX,
5038 			"matrix",
5039 			DATA_TYPE_STRUCT_MATRIX
5040 		},
5041 		{
5042 			NODE_SUBTYPE_PLACE_OBJECT,
5043 			"place object",
5044 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_PLACE_OBJECT
5045 		},
5046 		{
5047 			NODE_SUBTYPE_POINTS,
5048 			"points",
5049 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_POINTS
5050 		},
5051 		{
5052 			NODE_SUBTYPE_RECT,
5053 			"rect",
5054 			DATA_TYPE_STRUCT_RECT
5055 		},
5056 		{
5057 			NODE_SUBTYPE_REFERENCE,
5058 			"reference",
5059 			DATA_TYPE_FLAG_STRING
5060 		},
5061 		{
5062 			NODE_SUBTYPE_REMOVE,
5063 			"remove",
5064 			DATA_TYPE_FLAG_LIST
5065 		},
5066 		{
5067 			NODE_SUBTYPE_REPLACE_OBJECT,
5068 			"replace object",
5069 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_PLACE_OBJECT
5070 		},
5071 		{
5072 			NODE_SUBTYPE_SCRIPT_LIMITS,
5073 			"script limits",
5074 			DATA_TYPE_FLAG_LIST
5075 		},
5076 		{
5077 			NODE_SUBTYPE_SEQUENCE,
5078 			"sequence",
5079 			DATA_TYPE_FLAG_LIST
5080 		},
5081 		{
5082 			NODE_SUBTYPE_SET_BACKGROUND_COLOR,
5083 			"set background color",
5084 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_COLOR
5085 		},
5086 		{
5087 			NODE_SUBTYPE_SET_TAB_INDEX,
5088 			"set tab index",
5089 			DATA_TYPE_FLAG_LIST
5090 		},
5091 		{
5092 			NODE_SUBTYPE_SHAPE,
5093 			"shape",
5094 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_SHAPE_MOVE
5095 		},
5096 		{
5097 			NODE_SUBTYPE_SHOW_FRAME,
5098 			"show frame",
5099 			DATA_TYPE_STRUCT_SHOW_FRAME
5100 		},
5101 		{
5102 			NODE_SUBTYPE_SPRITE,
5103 			"sprite",
5104 			DATA_TYPE_FLAG_LIST
5105 		},
5106 		{
5107 			NODE_SUBTYPE_STATE,
5108 			"state",
5109 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_STATE
5110 		},
5111 		{
5112 			NODE_SUBTYPE_TEXT,
5113 			"text",
5114 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_TEXT
5115 		},
5116 		{
5117 			NODE_SUBTYPE_TEXT_SETUP,
5118 			"text setup",
5119 			DATA_TYPE_FLAG_LIST | DATA_TYPE_STRUCT_TEXT_SETUP
5120 		},
5121 		{
5122 			NODE_SUBTYPE_TRY,
5123 			"throw",
5124 			DATA_TYPE_FLAG_LIST
5125 		},
5126 		{
5127 			NODE_SUBTYPE_WITH,
5128 			"with",
5129 			DATA_TYPE_FLAG_LIST
5130 		},
5131 
5132 		/* the following should probably not appear? */
5133 		{
5134 			NODE_SUBTYPE_REMOVE_ALL,
5135 			"??? remove all ???",
5136 			0
5137 		},
5138 		{
5139 			NODE_SUBTYPE_DEFINITION,
5140 			"??? definition ???",
5141 			0
5142 		},
5143 
5144 		/* if we reach the following, we don't know what we are dealing with! */
5145 		{
5146 			NODE_SUBTYPE_UNKNOWN,
5147 			"UNKNOWN",
5148 			0
5149 		}
5150 	};
5151 	char				spaces[256];
5152 	const char			*d, *sub_data;
5153 	const struct data_type_t	*dt;
5154 	const struct data_list_t	*list;
5155 	int				idx;
5156 
5157 	/* search the info about this type */
5158 	dt = data_names;
5159 	do {
5160 		if(dt->type == data->type) {
5161 			break;
5162 		}
5163 		dt++;
5164 	} while(dt->type != NODE_SUBTYPE_UNKNOWN);
5165 
5166 	memset(spaces, ' ', indent);
5167 	spaces[indent] = '\0';
5168 
5169 #if 0
5170 	printf("%sBuffer raw data:\n", spaces);
5171 	for(idx = 0; idx < data->length; ++idx) {
5172 		if((idx & 15) == 0) {
5173 			if(idx != 0) {
5174 				printf("\n");
5175 			}
5176 			printf("%p- ", (unsigned char *) data + idx + 1);
5177 		}
5178 		unsigned char c = ((unsigned char *) data)[idx];
5179 		printf("%02X %c ", c, c >= ' ' && c < 0x7F ? c : '.');
5180 	}
5181 	if((idx & 15) != 0) {
5182 		printf("\n");
5183 	}
5184 #endif
5185 
5186 	printf("%sPointer: %p\n", spaces, data);
5187 	printf("%sLength: %d bytes (%.02gKb, %.02gMb)\n", spaces, (int) data->length, (double) data->length / 1024.0, (double) data->length / (1024.0 * 1024.0));
5188 	printf("%sType: %d (%s)\n", spaces, data->type, dt->name);
5189 	if(data->name_len > 0) {
5190 		printf("%s%s: \"%s\"\n", spaces,
5191 			(dt->flags & DATA_TYPE_FLAG_STRING) != 0 ? "String" : "Name", data->name);
5192 	}
5193 
5194 	d = (const char *) (data + 1) + data->name_len;
5195 	if((dt->flags & DATA_TYPE_FLAG_LIST) != 0) {
5196 		/* when we have a list the data is incorporated in that list */
5197 		if(data->length - data->name_len == sizeof(struct data_common_t)) {
5198 			/* ha! no list! this is an empty item... */
5199 			return;
5200 		}
5201 		list = (const struct data_list_t *) d;
5202 		printf("%sList of %d item%s.\n", spaces, (int) list->count, list->count > 1 ? "s" : "");
5203 		for(idx = 0; idx < (int) list->count; idx++) {
5204 			printf("%s  ----- offset = %ld\n", spaces, list->offset[idx]);
5205 			sub_data = d + labs(list->offset[idx]);
5206 			if(list->offset[idx] < 0) {
5207 				printf("%s  Direct structure: %p (Type: %d)\n", spaces, sub_data, dt->flags & DATA_TYPE_MASK_DATA);
5208 				switch(dt->flags & DATA_TYPE_MASK_DATA) {
5209 				case DATA_TYPE_STRUCT_UNKNOWN:
5210 					/* this shouldn't happen... */
5211 					break;
5212 
5213 				case DATA_TYPE_STRUCT_COLOR:
5214 					printf("%s    Color: %g, %g, %g, %g\n", spaces, ((double *) sub_data)[0], ((double *) sub_data)[1], ((double *) sub_data)[2], ((double *) sub_data)[3]);
5215 					break;
5216 
5217 				case DATA_TYPE_STRUCT_EDGES:
5218 				{
5219 					struct data_edges_t *e;
5220 
5221 					e = (struct data_edges_t *) sub_data;
5222 					if(e->type == EDGE_TYPE_CLOSE) {
5223 						printf("%s    Closure curve - end point forced equal to start point\n", spaces);
5224 					}
5225 					if(e->delta_x2 != -1E+128) {
5226 						printf("%s    Curve Deltas: (%g, %g)-(%g, %g)\n", spaces,
5227 								e->delta_x1, e->delta_y1, e->delta_x2, e->delta_y2);
5228 					}
5229 					else {
5230 						printf("%s    Line Deltas: (%g, %g)\n", spaces,
5231 										e->delta_x1, e->delta_y1);
5232 					}
5233 				}
5234 					break;
5235 
5236 				case DATA_TYPE_STRUCT_EDIT_TEXT:
5237 				{
5238 					struct data_edit_text_t *e;
5239 					int			comma;
5240 
5241 					e = (struct data_edit_text_t *) sub_data;
5242 					switch(e->type) {
5243 					case EDIT_TEXT_TYPE_LAYOUT:
5244 						printf("%s    Margin: %g, %g\n", spaces, e->margin_left, e->margin_right);
5245 						printf("%s    Indent: %g, leading: %g\n", spaces, e->indent, e->leading);
5246 						printf("%s    Maximum Length: %g\n", spaces, e->max_length);
5247 						/* flags: */
5248 						printf("%s    ", spaces);
5249 						comma = 0;
5250 						if(e->word_wrap != 0.0) {
5251 							printf("WORD WRAP");
5252 							comma = 1;
5253 						}
5254 						if(e->multiline != 0.0) {
5255 							printf("%sMULTILINE", comma ? ", " : "");
5256 							comma = 1;
5257 						}
5258 						if(e->password != 0.0) {
5259 							printf("%sPASSWORD", comma ? ", " : "");
5260 							comma = 1;
5261 						}
5262 						if(e->readonly != 0.0) {
5263 							printf("%sREADONLY", comma ? ", " : "");
5264 							comma = 1;
5265 						}
5266 						if(e->no_select != 0.0) {
5267 							printf("%sNO_SELECT", comma ? ", " : "");
5268 							comma = 1;
5269 						}
5270 						if(e->border != 0.0) {
5271 							printf("%sBORDER", comma ? ", " : "");
5272 							comma = 1;
5273 						}
5274 						if(e->outline != 0.0) {
5275 							printf("%sOUTLINE", comma ? ", " : "");
5276 							comma = 1;
5277 						}
5278 						if(e->html != 0.0) {
5279 							printf("%sHTML", comma ? ", " : "");
5280 							comma = 1;
5281 						}
5282 						if(e->auto_size != 0.0) {
5283 							printf("%sAUTO-SIZE", comma ? ", " : "");
5284 							comma = 1;
5285 						}
5286 						printf("\n");
5287 						break;
5288 
5289 					case EDIT_TEXT_TYPE_VARIABLE:
5290 						printf("%s    The next strings represent the variable name and the optional initial text\n", spaces);
5291 						break;
5292 
5293 					case EDIT_TEXT_TYPE_ALIGNMENT:
5294 						printf("%s    The next string represents the justification\n", spaces);
5295 						break;
5296 
5297 					case EDIT_TEXT_TYPE_INITIAL_TEXT:
5298 						printf("%s    The next string represents the initial text\n", spaces);
5299 						break;
5300 
5301 					}
5302 				}
5303 					break;
5304 
5305 				case DATA_TYPE_STRUCT_EMPTY:
5306 					/* mainly show frame at this time */
5307 					break;
5308 
5309 				case DATA_TYPE_STRUCT_FONT:
5310 					/* all the font structures have a type */
5311 					switch(* (long *) sub_data) {
5312 					case FONT_TYPE_LAYOUT:
5313 					{
5314 						const struct data_font_t	*f;
5315 
5316 						f = (const struct data_font_t *) sub_data;
5317 						printf("%s    Font: ascent: %g, descent: %g, leading height: %g, advance: %g\n", spaces,
5318 							/* TODO: add tests about the -1E+128 - use default */
5319 							f->ascent,
5320 							f->descent,
5321 							f->leading_height,
5322 							f->advance);
5323 					}
5324 						break;
5325 
5326 					case FONT_TYPE_ADVANCE:
5327 					{
5328 						const struct data_font_advance_t	*a;
5329 
5330 						a = (const struct data_font_advance_t *) sub_data;
5331 						if(a->x != -1E+128) {
5332 							printf("%s    Character advance: %g\n", spaces, a->x);
5333 						}
5334 						else {
5335 							printf("%s    Use default Character advance.\n", spaces);
5336 						}
5337 					}
5338 						break;
5339 
5340 					case FONT_TYPE_KERNING:
5341 					{
5342 						const struct data_font_kerning_t	*k;
5343 
5344 						k = (const struct data_font_kerning_t *) sub_data;
5345 						printf("%s    Kerning advance: %g\n", spaces, k->x);
5346 					}
5347 						break;
5348 
5349 					case FONT_TYPE_NAME:
5350 						printf("%s    The following string is the font name.\n", spaces);
5351 						break;
5352 
5353 					default:
5354 						printf("%s    Unknown font type (%ld)\n", spaces, * (long *) sub_data);
5355 						break;
5356 
5357 					}
5358 					break;
5359 
5360 				case DATA_TYPE_STRUCT_GRADIENT:
5361 					if(((double *) sub_data)[1] == -1E+128) {
5362 						printf("%s    Gradient at: %g\n", spaces, ((double *) sub_data)[0]);
5363 					}
5364 					else {
5365 						printf("%s    Morph Gradient at: %g to: %g\n", spaces, ((double *) sub_data)[0], ((double *) sub_data)[1]);
5366 					}
5367 					break;
5368 
5369 				case DATA_TYPE_STRUCT_IMAGE:
5370 					printf("%s    Format: %s.\n", spaces, ((long *) sub_data)[0] == IMAGE_FORMAT_LOSSLESS ? "Lossless" : "JPEG");
5371 					break;
5372 
5373 				case DATA_TYPE_STRUCT_LINE_STYLE:
5374 					printf("%s    Width: %g\n", spaces, ((double *) sub_data)[0]);
5375 					printf("%s    To width: %g\n", spaces, ((double *) sub_data)[1]);
5376 					break;
5377 
5378 				case DATA_TYPE_STRUCT_PLACE_OBJECT:
5379 					printf("%s    Position: %g\n", spaces, ((double *) sub_data)[0]);
5380 					printf("%s    Depth: %g\n", spaces, ((double *) sub_data)[1]);
5381 					break;
5382 
5383 				case DATA_TYPE_STRUCT_POINTS:
5384 				{
5385 					struct data_points_t *p;
5386 
5387 					p = (struct data_points_t *) sub_data;
5388 					if(p->type == EDGE_TYPE_CLOSE) {
5389 						printf("%s    Closure point - end point forced equal to start point\n", spaces);
5390 					}
5391 					if(p->x2 != -1E+128) {
5392 						printf("%s    Curve Points: (%g, %g)-(%g, %g)\n", spaces,
5393 								p->x1, p->y1, p->x2, p->y2);
5394 					}
5395 					else {
5396 						printf("%s    Line Points: (%g, %g)\n", spaces, p->x1, p->y1);
5397 					}
5398 				}
5399 					break;
5400 
5401 				case DATA_TYPE_STRUCT_SHAPE_MOVE:
5402 					if(idx + 1 < (int) list->count && labs(list->offset[idx + 1]) - labs(list->offset[idx]) == sizeof(long)) {
5403 						printf("%s    Select Fill: %ld\n", spaces, ((long *) sub_data)[0]);
5404 					}
5405 					else {
5406 						printf("%s    Move: +(%g, %g)\n", spaces, ((double *) sub_data)[0], ((double *) sub_data)[1]);
5407 					}
5408 					break;
5409 
5410 				case DATA_TYPE_STRUCT_STATE:
5411 					printf("%s    State: %lX\n", spaces, (long) ((double *) sub_data)[0]);
5412 					printf("%s    Layer: %g\n", spaces, ((double *) sub_data)[1]);
5413 					break;
5414 
5415 				case DATA_TYPE_STRUCT_TEXT:
5416 				{
5417 					struct data_text_t	*t;
5418 
5419 					t = (struct data_text_t *) sub_data;
5420 					switch(t->type) {
5421 					case TEXT_TYPE_ADVANCE:
5422 						if(t->advance == -1E+128) {
5423 							printf("%s    No specific advance.\n", spaces);
5424 						}
5425 						else {
5426 							printf("%s    Specific advance: %g\n", spaces, t->advance);
5427 						}
5428 						break;
5429 
5430 					case TEXT_TYPE_INFO:
5431 						if(t->thickness == -1E+128) {
5432 							printf("%s    No specific thickness.\n", spaces);
5433 						}
5434 						else {
5435 							printf("%s    Thickness: %g\n", spaces, t->thickness);
5436 						}
5437 						if(t->sharpness == -1E+128) {
5438 							printf("%s    No specific sharpness.\n", spaces);
5439 						}
5440 						else {
5441 							printf("%s    Sharpness: %g\n", spaces, t->sharpness);
5442 						}
5443 						if(t->renderer == -1E+128) {
5444 							printf("%s    No specific renderer.\n", spaces);
5445 						}
5446 						else {
5447 							printf("%s    Renderer: %d\n", spaces, (int)t->renderer);
5448 						}
5449 						if(t->grid_fit == -1E+128) {
5450 							printf("%s    No grid fit.\n", spaces);
5451 						}
5452 						else {
5453 							printf("%s    Grid fit: %d\n", spaces, (int)t->grid_fit);
5454 						}
5455 						break;
5456 
5457 					}
5458 				}
5459 					break;
5460 
5461 				case DATA_TYPE_STRUCT_TEXT_SETUP:
5462 					printf("%s    Offset: (%g, %g)\n", spaces, ((double *) sub_data)[0], ((double *) sub_data)[1]);
5463 					printf("%s    Height: %g\n", spaces, ((double *) sub_data)[2]);
5464 					break;
5465 
5466 				default:
5467 					assert(0, "don't know the DATA_TYPE_STRUCT_... type #%d (sub-item)", dt->flags & DATA_TYPE_MASK_DATA);
5468 					/*NOTREACHED*/
5469 
5470 				}
5471 			}
5472 			else {
5473 				node_print_data0((const struct data_common_t *) sub_data, indent + 2);
5474 			}
5475 		}
5476 	}
5477 	else {
5478 		/* when we don't have a list, the data follows the header as is */
5479 		switch(dt->flags & DATA_TYPE_MASK_DATA) {
5480 		case DATA_TYPE_STRUCT_UNKNOWN:
5481 			/* this is a valid value for empty objects */
5482 			break;
5483 
5484 		case DATA_TYPE_STRUCT_COLOR:
5485 			printf("%sColor: %g, %g, %g, %g\n", spaces, ((double *) d)[0], ((double *) d)[1], ((double *) d)[2], ((double *) d)[3]);
5486 			break;
5487 
5488 		case DATA_TYPE_STRUCT_COLOR_TRANSFORM:
5489 			printf("%sColor Transform: x (%g, %g, %g, %g) + (%g, %g, %g, %g)\n", spaces,
5490 				((double *) d)[4], ((double *) d)[5], ((double *) d)[6], ((double *) d)[7],
5491 				((double *) d)[0], ((double *) d)[1], ((double *) d)[2], ((double *) d)[3]);
5492 			break;
5493 
5494 		case DATA_TYPE_STRUCT_EMPTY:
5495 			break;
5496 
5497 		case DATA_TYPE_STRUCT_MATRIX:
5498 			if(((double *) d)[1] == -1E+128) {
5499 				printf("%sScale: %g, %g\n", spaces, ((double *) d)[0], ((double *) d)[0]);
5500 			}
5501 			else {
5502 				printf("%sScale: %g, %g\n", spaces, ((double *) d)[0], ((double *) d)[1]);
5503 			}
5504 			printf("%sRotate: %g (%g degres)\n", spaces, ((double *) d)[4], ((double *) d)[4] * 180.0 / M_PI);
5505 			printf("%sTranslate: %g, %g\n", spaces, ((double *) d)[2], ((double *) d)[3]);
5506 			break;
5507 
5508 		case DATA_TYPE_STRUCT_RECT:
5509 			printf("%sRectangle: (%g, %g) - (%g, %g)\n", spaces, ((double *) d)[0], ((double *) d)[1], ((double *) d)[2], ((double *) d)[3]);
5510 			break;
5511 
5512 		case DATA_TYPE_STRUCT_SHOW_FRAME:
5513 			printf("%sWait: %g frames\n", spaces, ((double *) d)[0]);
5514 			break;
5515 
5516 		case DATA_TYPE_STRUCT_ACTION_SCRIPT:
5517 			printf("%sActioscript:\n", spaces);
5518 			//((as::NodePtr *) d)->Display(stdout);
5519 			break;
5520 
5521 		default:
5522 			assert(0, "don't know the DATA_TYPE_STRUCT_... type #%d (direct)", dt->flags & DATA_TYPE_MASK_DATA);
5523 			/*NOTREACHED*/
5524 
5525 		}
5526 	}
5527 }
5528 
5529 
node_print_data(const struct data_common_t * data)5530 void node_print_data(const struct data_common_t *data)
5531 {
5532 	printf("*******************************************\n");
5533 	if(data == NULL) {
5534 		printf("NO DATA!\n");
5535 	}
5536 	else {
5537 		node_print_data0(data, 0);
5538 	}
5539 	printf("*******************************************\n");
5540 }
5541 
5542 
node_definitions(struct node_t * expr,const struct definition_t * params,struct node_t * definitions,struct node_exec_status_t * parent)5543 static int node_definitions(struct node_t *expr, const struct definition_t *params, struct node_t *definitions, struct node_exec_status_t *parent)
5544 {
5545 	const struct def_label_t	*label;
5546 	const struct def_entry_t	*entry;
5547 	struct node_exec_status_t	status;
5548 	struct node_t			*def, *head, *d, *e;
5549 	enum node_type_t		type;
5550 	struct data_common_t		*data, *sub_data;
5551 	int				ec, bad, cnt;
5552 	struct def_object_t		defobj;
5553 	char				*obj_struct, *path;
5554 
5555 	node_init(definitions, NODE_TYPE_DATA, expr->sub_type);
5556 
5557 	/* transform the compressed parameters in a set of entries */
5558 #if 0
5559 printf(">>> Create entries for object 0x%08lX: [%s] (%d/%d) [right = %p]...\n",
5560 		(unsigned long) expr,
5561 		expr->left != NULL ? expr->left->string : "<no name>",
5562 		expr->type, expr->sub_type, expr->right);
5563 fflush(stdout);
5564 #endif
5565 
5566 	ec = node_def2entry(params, &defobj);
5567 	if(ec != 0) {
5568 		return ec;		/* there are only assert()'s at this time anyway... */
5569 	}
5570 
5571 	if(defobj.size != 0) {
5572 		/* got to allocate a structure for this object */
5573 		obj_struct = sswf_malloc(defobj.size, "node_definitions() -- object specific sub-buffer");
5574 		memset(obj_struct, 0, defobj.size);
5575 
5576 #if 0
5577 printf("Object [%s] has a struct of %d bytes\n", expr->left != NULL ? expr->left->string : "<no name>", defobj.size);
5578 #endif
5579 
5580 		/* whenever this happens we have to set the defaults so parse all the structures for them */
5581 		label = defobj.labels;
5582 		cnt = defobj.count;
5583 		while(cnt > 0) {
5584 			cnt--;
5585 			if(label->size == 0) {
5586 				node_label_defaults(label, obj_struct);
5587 			}
5588 			label++;
5589 		}
5590 	}
5591 	else {
5592 		obj_struct = NULL;
5593 	}
5594 
5595 	data = NULL;
5596 
5597 	/*
5598 	 * We have a list of definitions which include a list of expressions
5599 	 *
5600 	 * definition: { [ <name> ':' ] group_expr }
5601 	 */
5602 	bad = 0;
5603 	def = expr->right;
5604 	while(def != NULL) {
5605 		e = def->right;
5606 		/* if e == NULL then the parser balently failed!?!? */
5607 		assert(e != NULL, "no definition within a definition list");
5608 
5609 		/* skip variables since we can't execute them */
5610 		if(e->type == NODE_TYPE_OBJECT && e->sub_type == NODE_SUBTYPE_VARIABLE) {
5611 			def = def->next;
5612 			continue;
5613 		}
5614 
5615 		/* reset the status each time (should it be a copy of the status when coming in?) */
5616 		memset(&status, 0, sizeof(status));
5617 		status.parent = parent;
5618 		status.obj = expr;
5619 		head = NULL;
5620 #if 0
5621 printf("A label? [%s] (e = %p - %d/%d)\n", def->left == NULL ? "<no label>" : def->left->string, e, e->type, e->sub_type);
5622 #endif
5623 		if(def->left == NULL) {
5624 			/* no label, use the default UNIT mode and compute the list of expressions */
5625 			do {
5626 				/* make sure the status is proper on entry */
5627 				status.unit = defobj.default_unit;
5628 				status.ref = 0;
5629 				lex_filename = e->filename;
5630 				d = node_alloc(NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN, e->line);
5631 				ec = node_execute(e, d, &status);
5632 #if 0
5633 printf("  Executed %d/%d -> %d/%d (object: %s - %d/%d)\n", e->type, e->sub_type, d->type, d->sub_type,
5634 					expr->left != NULL ? expr->left->string : "<no name>",
5635 					expr->type, expr->sub_type);
5636 fflush(stdout);
5637 #endif
5638 				if(ec != 0) {
5639 					bad = 1;
5640 				}
5641 				if(d->type == NODE_TYPE_UNKNOWN) {
5642 					/* This happens when there is an IF() without an ELSE.
5643 					 * Obviously the validity will depend on the object within
5644 					 * which the IF() is included. Most of the time we will
5645 					 * expect IF()'s within lists, however, if there is an
5646 					 * ELSE statement they can be used virtually anywhere.
5647 					 */
5648 					node_free(d);
5649 				}
5650 				else {
5651 					if(head == NULL) {
5652 						head = d;
5653 					}
5654 					else {
5655 						node_link_tail(head, d);
5656 					}
5657 				}
5658 				e = e->next;
5659 			} while(e != NULL);
5660 
5661 			/* we have a valid set of results, look for a corresponding entry */
5662 			label = node_def_find_entry(&defobj, head);
5663 
5664 #if 0
5665 printf("Label = %p + head = %p (%d/%d)\n", label, head, head->type, head->sub_type);
5666 #endif
5667 
5668 			if(label == NULL) {
5669 				bad = 1;
5670 				e = def->right;
5671 				path = node_path(e, 0);
5672 fprintf(stderr, "ERROR: at line #%ld in file \"%s\": cannot determine what this entry is about.\n"
5673 		"  (Object: \"%s\" of type %s [%d] and subtype %s [%d])\n"
5674 		"  We expected one of the following for \"%s\":\n",
5675 							e->line, e->filename, path,
5676 							node_type_names[e->type].name, e->type,
5677 							node_type_names[e->sub_type].name, e->sub_type,
5678 							defobj.name);
5679 				sswf_free(path);
5680 				node_def_print_entries(&defobj, "    ");
5681 				errcnt++;
5682 			}
5683 		}
5684 		else {
5685 			/* a label, find it! */
5686 			label = node_def_find_label(&defobj, def->left->string);
5687 			if(label == NULL) {
5688 				return -1;
5689 			}
5690 			entry = label->entries;
5691 			cnt = label->count;
5692 #if 0
5693 fprintf(stderr, "Label = %p {%s} %d entries\n", label, label->label, cnt);
5694 #endif
5695 			do {
5696 				/* we got a label so the unit may change with each entry! */
5697 				status.unit = entry->unit;
5698 				status.ref = (entry->flags & DEF_ENTRY_FLAG_REFERENCE) != 0;
5699 				lex_filename = e->filename;
5700 				d = node_alloc(NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN, e->line);
5701 				ec = node_execute(e, d, &status);
5702 
5703 #if 0
5704 fprintf(stderr, "  Executed %d/%d -> %d/%d (object: %s, ec = %d)\n",
5705 		e->type, e->sub_type, d->type, d->sub_type,
5706 		expr->left != NULL ? expr->left->string : "<no name>", ec);
5707 #endif
5708 
5709 				if(ec != 0) {
5710 					bad = 1;
5711 					node_free(d);
5712 				}
5713 				else {
5714 					if(head == NULL) {
5715 						head = d;
5716 					}
5717 					else {
5718 						node_link_tail(head, d);
5719 					}
5720 					/* in this case we can straight away test the validity of arguments */
5721 					type = d->type;
5722 					if(type == NODE_TYPE_INTEGER) {
5723 						/* we keep all the values as floating points in these data structures */
5724 						type = NODE_TYPE_FLOAT;
5725 					}
5726 					if(type != entry->type) {
5727 						/* arg! that's bad... */
5728 						bad = 1;
5729 						fprintf(stderr, "ERROR: invalid parameter for the label \"%s\" in object of type \"%s\" (type %s [%d] expected, found %s [%d] instead).\n",
5730 								label->label, defobj.name,
5731 								node_type_names[entry->type].name, entry->type,
5732 								node_type_names[type].name, type);
5733 						errcnt++;
5734 					}
5735 					else if(entry->sub_type != NODE_SUBTYPE_UNKNOWN) {
5736 						type = entry->sub_type;
5737 						if(type == NODE_SUBTYPE_BLOCK) {
5738 							type = NODE_SUBTYPE_LIST;
5739 						}
5740 						if(d->sub_type != type) {
5741 							/* arg! good type but not so good on the sub-type... */
5742 							bad = 1;
5743 							fprintf(stderr, "ERROR: invalid parameter for the label \"%s\" in object of type \"%s\" (sub-type %s [%d] expected, found %s [%d] instead).\n",
5744 									label->label, defobj.name,
5745 									node_type_names[type].name, type,
5746 									node_type_names[d->sub_type].name, d->sub_type);
5747 							errcnt++;
5748 						}
5749 					}
5750 				}
5751 				entry++;
5752 				cnt--;
5753 				e = e->next;
5754 			} while(e != NULL && cnt > 0);
5755 			if(cnt > 0) {
5756 				if((entry->flags & DEF_ENTRY_FLAG_OPTIONAL) == 0) {
5757 					/* if this entry isn't optional, something's missing */
5758 					bad = 1;
5759 					fprintf(stderr, "ERROR: not enough parameters.\n");
5760 					errcnt++;
5761 				}
5762 			}
5763 			else if(e != NULL) {
5764 				/* more params but no entry... that's too much! */
5765 				bad = 1;
5766 				fprintf(stderr, "ERROR: too many parameters.\n");
5767 				errcnt++;
5768 			}
5769 		}
5770 		if(!bad) {
5771 
5772 #if 0
5773 printf("  Definition to data (label size: %d, \"%s\")\n",
5774 		label->size, label->label ? label->label : "<no label>");
5775 #endif
5776 
5777 			sub_data = node_def_to_data(expr, label, head, obj_struct);
5778 
5779 #if 0
5780 printf("==== DATA\n");
5781 if(data) node_print_data(data);
5782 printf("==== SUB-DATA\n");
5783 if(sub_data) node_print_data(sub_data);
5784 printf("  Merge now (0x%08lX, 0x%08lX)\n", (long) sub_data, (long) data);
5785 #endif
5786 
5787 			data = node_def_merge_data(expr, &defobj, data, sub_data);
5788 
5789 #if 0
5790 printf("==== MERGED DATA\n");
5791 if(data) node_print_data(data);
5792 printf("  Merged at 0x%08lX\n", (long) data);
5793 #endif
5794 
5795 		}
5796 		node_free_list(head);
5797 		def = def->next;
5798 	}
5799 
5800 	if(!bad) {
5801 		if(defobj.count == 0) {
5802 			/* special case of empty entries such as the SHOW_FRAME object */
5803 			data = node_def_empty(expr);
5804 		}
5805 		else {
5806 			if((defobj.flags & DEF_OBJECT_FLAG_HAS_LIST) == 0 && data == NULL) {
5807 				assert(obj_struct != NULL, "there is no data and no obj_struct");
5808 
5809 #if 0
5810 printf("  Create the 'data' buffer from obj_struct only!\n");
5811 #endif
5812 
5813 				/* in this case we have no list */
5814 				data = node_def_data(expr, obj_struct, defobj.size);
5815 			}
5816 			else if(obj_struct != NULL) {
5817 				/* got to add this one structure too, insert it first */
5818 
5819 #if 0
5820 printf("  Need to insert the obj_struct data too... (Data = %p)\n", data);
5821 #endif
5822 
5823 				data = node_def_insertdata(expr, data, obj_struct, defobj.size);
5824 			}
5825 			else if(data == NULL) {
5826 				/* special case of empty entries such as the FILL STYLE { }; */
5827 				if((defobj.flags & DEF_OBJECT_FLAG_EMPTY) == 0) {
5828 fprintf(stderr, "ERROR: the object \"%s\" of type \"%s\" can't be empty.\n",
5829 						expr->left == NULL ? "<no name>" : expr->left->string,
5830 						defobj.name);
5831 					errcnt++;
5832 				}
5833 				data = node_def_empty(expr);
5834 			}
5835 		}
5836 	}
5837 
5838 	sswf_free(obj_struct);
5839 
5840 	definitions->data = data;
5841 
5842 #if 0
5843 node_print_data(data);
5844 printf(">>> .......................................... <<< (%p)\n", data);
5845 //getchar();
5846 fflush(stdout);
5847 #endif
5848 
5849 	return bad ? -1 : 0;
5850 }
5851 
5852 
5853 
5854 
5855 
5856 
5857 
5858 
5859 
node_boolean(struct node_t * result,struct node_t * l)5860 static int node_boolean(struct node_t *result, struct node_t *l)
5861 {
5862 	switch(result->type) {
5863 	case NODE_TYPE_INTEGER:
5864 		result->integer = l->integer != 0;
5865 		break;
5866 
5867 	case NODE_TYPE_FLOAT:
5868 		result->integer = l->floating_point != 0.0;
5869 		break;
5870 
5871 	case NODE_TYPE_STRING:
5872 		if(l->string == NULL) {
5873 			result->integer = 0;	/* false in this case */
5874 		}
5875 		else {
5876 			result->integer = l->string != '\0';
5877 			if(result == l) {
5878 				/* save some memory quick */
5879 				sswf_clean(&l->string);
5880 			}
5881 		}
5882 		break;
5883 
5884 	default:
5885 		assert(0, "invalid node type for a boolean value check");
5886 
5887 	}
5888 
5889 	result->type = NODE_TYPE_INTEGER;
5890 
5891 	return 0;
5892 }
5893 
5894 
node_exec_if_integers(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)5895 static int node_exec_if_integers(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
5896 {
5897 	struct node_t		*e, *head;
5898 	int			ec;
5899 	struct data_common_t	*sub_data;
5900 	struct def_object_t	defobj;
5901 
5902 	node_init(result, NODE_TYPE_DATA, NODE_SUBTYPE_BLOCK);
5903 
5904 	ec = node_def2entry((const struct definition_t *) node_def_list, &defobj);
5905 	if(ec != 0) {
5906 		return ec;
5907 	}
5908 
5909 	e = l->integer ? expr->left : expr->right;
5910 
5911 	head = NULL;
5912 	while(e != NULL) {
5913 		lex_filename = e->filename;
5914 		r = node_alloc(NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN, e->line);
5915 		ec = node_execute(e, r, status);
5916 		if(ec != 0) {
5917 			node_free(r);
5918 			node_free_list(head);
5919 			return ec;
5920 		}
5921 		if(head == NULL) {
5922 			head = r;
5923 		}
5924 		else {
5925 			node_link_tail(head, r);
5926 		}
5927 		e = e->next;
5928 	}
5929 
5930 	sub_data = node_def_to_data(expr, defobj.labels, head, NULL);
5931 	result->data = node_def_merge_data(expr, &defobj, NULL, sub_data);
5932 	result->data->type = NODE_SUBTYPE_BLOCK;
5933 
5934 	node_free_list(head);
5935 
5936 	return 0;
5937 }
5938 
5939 
node_exec_for(struct node_t * expr,struct node_t * l,struct node_t * r,struct node_t * result,struct node_exec_status_t * status)5940 static int node_exec_for(struct node_t *expr, struct node_t *l, struct node_t *r, struct node_t *result, struct node_exec_status_t *status)
5941 {
5942 	struct node_t		*variable, *start_expr, *test_expr, *next_expr, *definitions_expr;
5943 	struct node_t		test, *head;
5944 	struct def_object_t	defobj;
5945 	struct data_common_t	*sub_data;
5946 	int			ec;
5947 
5948 	/* TODO: The following code is really bad in regard to memory leaks!!! fix it please! */
5949 
5950 	/*
5951 	 * TODO: At this time a for() loop generates a block which only a few objects understand.
5952 	 * This will automatically be fixed when the main loop ensures we don't make use of such
5953 	 * lists but instead copy their contents in the parent object!
5954 	 */
5955 
5956 	node_init(result, NODE_TYPE_DATA, NODE_SUBTYPE_BLOCK);
5957 
5958 	/* get the list of nodes to work with */
5959 	variable = expr->right;				/* the loop variable and it's expression */
5960 	start_expr = variable->next;			/* value used to set variable for the first loop */
5961 	test_expr = start_expr->next;			/* repeat as long as not zero */
5962 	next_expr = test_expr->next;			/* execute once after each loop */
5963 	definitions_expr = next_expr->next;		/* what we want to repeat */
5964 
5965 	/* we save the result directory in the variable! */
5966 	/*node_clean(variable->right, 0);*/
5967 	/* TODO: we need to test whether we really need the node_init() here */
5968 	node_init(variable->right, NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN);
5969 	ec = node_execute(start_expr, variable->right, status);
5970 	if(ec != 0) {
5971 		return ec;
5972 	}
5973 
5974 	ec = node_def2entry((const struct definition_t *) node_def_list, &defobj);
5975 	if(ec != 0) {
5976 		return ec;
5977 	}
5978 
5979 //printf(">>> FOR STARTED!\n");
5980 
5981 	node_init(&test, NODE_TYPE_DATA, NODE_SUBTYPE_BLOCK);
5982 
5983 	head = NULL;
5984 repeat:
5985 	/* test to see if we should continue the loop */
5986 	ec = node_execute(test_expr, &test, status);
5987 	if(ec != 0) {
5988 		node_free_list(head);
5989 		return ec;
5990 	}
5991 	switch(test.type) {
5992 	case NODE_TYPE_INTEGER:
5993 	case NODE_TYPE_FLOAT:
5994 	case NODE_TYPE_STRING:
5995 		node_boolean(&test, &test);
5996 		if(test.integer == 0) {
5997 			goto done;
5998 		}
5999 		break;
6000 
6001 	default:
6002 		fprintf(stderr, "ERROR: a test in a loop must return a boolean value. (variable: \"%s\")\n", variable->left == NULL ? "<no name>" : variable->left->string);
6003 		errcnt++;
6004 		node_free_list(head);
6005 		return -1;
6006 
6007 	}
6008 
6009 	lex_filename = definitions_expr->filename;
6010 	r = node_alloc(NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN, definitions_expr->line);
6011 	ec = node_execute(definitions_expr, r, status);
6012 	if(ec != 0) {
6013 		fprintf(stderr, "ERROR: execution failed in a for loop (%d).\n", ec);
6014 		node_free(r);
6015 		node_free_list(head);
6016 		return ec;
6017 	}
6018 	if(head == NULL) {
6019 		head = r;
6020 	}
6021 	else {
6022 		node_link_tail(head, r);
6023 	}
6024 
6025 	/*
6026 	 * because the expression next_expr may (should!) reference variable->right
6027 	 * we can't use it directly as the result
6028 	 */
6029 	lex_filename = next_expr->filename;
6030 	r = node_alloc(NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN, next_expr->line);
6031 	ec = node_execute(next_expr, r, status);
6032 	if(ec != 0) {
6033 		node_free(r);
6034 		node_free_list(head);
6035 		return ec;
6036 	}
6037 	node_free(variable->right);
6038 	variable->right = r;
6039 	goto repeat;
6040 done:
6041 
6042 	sub_data = node_def_to_data(expr, defobj.labels, head, NULL);
6043 	result->data = node_def_merge_data(expr, &defobj, NULL, sub_data);
6044 	result->data->type = NODE_SUBTYPE_BLOCK;
6045 
6046 #if 0
6047 printf(">>> FOR DONE! (%d, %d)\n", result->type, result->sub_type);
6048 #endif
6049 
6050 	node_free_list(head);
6051 
6052 	return 0;
6053 }
6054 
6055 
6056 
6057 
6058 
6059 
6060 
strcmp_action(const char * name,const char * pattern)6061 int strcmp_action(const char *name, const char *pattern)
6062 {
6063 	int		r;
6064 
6065 	while(isspace((unsigned char) *name) || *name == '_' || *name == '.') {
6066 		name++;
6067 	}
6068 
6069 	while(*pattern != '\0') {
6070 		if(*pattern == '.') {
6071 			/* we accept a word separator in this case or none */
6072 			switch(*name) {
6073 			case '-':
6074 			case ' ':
6075 			case '_':
6076 			case '.':
6077 				name++;
6078 				break;
6079 
6080 			}
6081 		}
6082 		else {
6083 			r = (unsigned char) toupper((unsigned char) *name) - (unsigned char) *pattern;
6084 			if(r != 0) {
6085 				return r;
6086 			}
6087 			name++;
6088 		}
6089 		pattern++;
6090 	}
6091 
6092 	while(isspace((unsigned char) *name) || *name == '_' || *name == '.') {
6093 		name++;
6094 	}
6095 
6096 	return (unsigned char) *name;
6097 }
6098 
6099 
6100 
6101 
6102 
6103 
6104 
node_execute(struct node_t * expr,struct node_t * result,struct node_exec_status_t * status)6105 int node_execute(struct node_t *expr, struct node_t *result, struct node_exec_status_t *status)
6106 {
6107 	static const struct node_exec_types	all_types[] = {
6108 		{		/*** field operator ***/
6109 			NODE_TYPE_OPERATOR,
6110 			NODE_SUBTYPE_FIELD,
6111 			NULL,
6112 			0,
6113 			{
6114 				node_exec_field,
6115 				NULL,
6116 				NULL,
6117 				NULL,
6118 				NULL
6119 			}
6120 		},
6121 		{		/*** subscript operator ***/
6122 			NODE_TYPE_OPERATOR,
6123 			NODE_SUBTYPE_SUBSCRIPT,
6124 			NULL,
6125 			EXEC_LR,
6126 			{
6127 				node_exec_subscript,
6128 				NULL,
6129 				NULL,
6130 				NULL,
6131 				NULL
6132 			}
6133 		},
6134 		{		/*** expand $(...) operator ***/
6135 			NODE_TYPE_OPERATOR,
6136 			NODE_SUBTYPE_EXPAND,
6137 			NULL,
6138 			EXEC_LEFT,
6139 			{
6140 				NULL,
6141 				NULL,
6142 				node_exec_reference,	/* indirect object or variable access */
6143 				NULL,
6144 				NULL
6145 			}
6146 		},
6147 		{		/*** unary + operator ***/
6148 			NODE_TYPE_OPERATOR,
6149 			NODE_SUBTYPE_IDENTITY,
6150 			NULL,
6151 			EXEC_LEFT,
6152 			{
6153 				node_exec_identity_integers,
6154 				node_exec_identity_floats,
6155 				node_exec_identity_strings,	/* uppercase */
6156 				NULL,
6157 				NULL
6158 			}
6159 		},
6160 		{		/*** unary - operator ***/
6161 			NODE_TYPE_OPERATOR,
6162 			NODE_SUBTYPE_NEGATE,
6163 			NULL,
6164 			EXEC_LEFT,
6165 			{
6166 				node_exec_negate_integers,
6167 				node_exec_negate_floats,
6168 				node_exec_negate_strings,	/* lowercase */
6169 				NULL,
6170 				NULL
6171 			}
6172 		},
6173 		{		/*** unary ! operator ***/
6174 			NODE_TYPE_OPERATOR,
6175 			NODE_SUBTYPE_LOGICAL_NOT,
6176 			NULL,
6177 			EXEC_BOOLEAN_LEFT,
6178 			{
6179 				node_exec_logical_not_integers,
6180 				NULL,
6181 				NULL,
6182 				NULL,
6183 				NULL
6184 			}
6185 		},
6186 		{		/*** unary ~ operator ***/
6187 			NODE_TYPE_OPERATOR,
6188 			NODE_SUBTYPE_NOT,
6189 			NULL,
6190 			EXEC_LEFT,
6191 			{
6192 				node_exec_not_integers,
6193 				NULL,
6194 				node_exec_not_strings,		/* swap case */
6195 				NULL,
6196 				NULL
6197 			}
6198 		},
6199 		{		/*** group () operator ***/
6200 			NODE_TYPE_OPERATOR,
6201 			NODE_SUBTYPE_GROUP,
6202 			NULL,
6203 			EXEC_LEFT,
6204 			{
6205 				node_exec_identity_integers,
6206 				node_exec_identity_floats,
6207 				node_exec_group_strings,	/* do nothing to the string */
6208 				NULL,
6209 				NULL
6210 			}
6211 		},
6212 		{		/*** function <name>(<params>) operator ***/
6213 			NODE_TYPE_OPERATOR,
6214 			NODE_SUBTYPE_FUNCTION,
6215 			NULL,
6216 			0,		/* left is an identifier, don't want to evaluate */
6217 			{		/* right is a list of parameters, need to evaluate one by one */
6218 				node_exec_function,
6219 				NULL,
6220 				NULL,
6221 				NULL,
6222 				NULL
6223 			}
6224 		},
6225 		{		/*** binary ** operator ***/
6226 			NODE_TYPE_OPERATOR,
6227 			NODE_SUBTYPE_POWER,
6228 			NULL,
6229 			EXEC_LR,
6230 			{
6231 				node_exec_power_integers,
6232 				node_exec_power_floats,
6233 				NULL,
6234 				NULL,
6235 				NULL
6236 			}
6237 		},
6238 		{		/*** binary * operator ***/
6239 			NODE_TYPE_OPERATOR,
6240 			NODE_SUBTYPE_MULTIPLY,
6241 			NULL,
6242 			EXEC_LR,
6243 			{
6244 				node_exec_mul_integers,
6245 				node_exec_mul_floats,
6246 				NULL,
6247 				NULL,
6248 				NULL
6249 			}
6250 		},
6251 		{		/*** binary / operator ***/
6252 			NODE_TYPE_OPERATOR,
6253 			NODE_SUBTYPE_DIVIDE,
6254 			NULL,
6255 			EXEC_LR,
6256 			{
6257 				node_exec_div_integers,
6258 				node_exec_div_floats,
6259 				NULL,
6260 				NULL,
6261 				NULL
6262 			}
6263 		},
6264 		{		/*** binary % operator ***/
6265 			NODE_TYPE_OPERATOR,
6266 			NODE_SUBTYPE_MODULO,
6267 			NULL,
6268 			EXEC_LR,
6269 			{
6270 				node_exec_mod_integers,
6271 				node_exec_mod_floats,		/* not a C operator! */
6272 				NULL,
6273 				NULL,
6274 				NULL
6275 			}
6276 		},
6277 		{		/*** binary + operator ***/
6278 			NODE_TYPE_OPERATOR,
6279 			NODE_SUBTYPE_ADD,
6280 			NULL,
6281 			EXEC_LR,
6282 			{
6283 				node_exec_add_integers,
6284 				node_exec_add_floats,
6285 				node_exec_add_strings,			/* not a C operator */
6286 				node_exec_add_strint,
6287 				NULL
6288 			}
6289 		},
6290 		{		/*** binary - operator ***/
6291 			NODE_TYPE_OPERATOR,
6292 			NODE_SUBTYPE_SUBTRACT,
6293 			NULL,
6294 			EXEC_LR,
6295 			{
6296 				node_exec_sub_integers,
6297 				node_exec_sub_floats,
6298 				NULL,
6299 				NULL,
6300 				NULL
6301 			}
6302 		},
6303 		{		/*** binary <? operator ***/
6304 			NODE_TYPE_OPERATOR,
6305 			NODE_SUBTYPE_MINIMUM,
6306 			NULL,
6307 			EXEC_LR,
6308 			{
6309 				node_exec_min_integers,
6310 				node_exec_min_floats,
6311 				node_exec_min_strings,
6312 				NULL,
6313 				NULL
6314 			}
6315 		},
6316 		{		/*** binary >? operator ***/
6317 			NODE_TYPE_OPERATOR,
6318 			NODE_SUBTYPE_MAXIMUM,
6319 			NULL,
6320 			EXEC_LR,
6321 			{
6322 				node_exec_max_integers,
6323 				node_exec_max_floats,
6324 				node_exec_max_strings,
6325 				NULL,
6326 				NULL
6327 			}
6328 		},
6329 		{		/*** binary >> operator ***/
6330 			NODE_TYPE_OPERATOR,
6331 			NODE_SUBTYPE_SHIFT_RIGHT,
6332 			NULL,
6333 			EXEC_LR,
6334 			{
6335 				node_exec_shift_right_integers,
6336 				NULL,
6337 				NULL,
6338 				node_exec_shift_right_strint,
6339 				NULL
6340 			}
6341 		},
6342 		{		/*** binary << operator ***/
6343 			NODE_TYPE_OPERATOR,
6344 			NODE_SUBTYPE_SHIFT_LEFT,
6345 			NULL,
6346 			EXEC_LR,
6347 			{
6348 				node_exec_shift_left_integers,
6349 				NULL,
6350 				NULL,
6351 				node_exec_shift_left_strint,
6352 				NULL
6353 			}
6354 		},
6355 		{		/*** binary >>> operator ***/
6356 			NODE_TYPE_OPERATOR,
6357 			NODE_SUBTYPE_SHIFT_RIGHT_UNSIGNED,
6358 			NULL,
6359 			EXEC_LR,
6360 			{
6361 				node_exec_shift_right_unsigned_integers,
6362 				NULL,
6363 				NULL,
6364 				node_exec_shift_right_unsigned_strint,
6365 				NULL
6366 			}
6367 		},
6368 		{		/*** binary !> operator ***/
6369 			NODE_TYPE_OPERATOR,
6370 			NODE_SUBTYPE_ROTATE_RIGHT,
6371 			NULL,
6372 			EXEC_LR,
6373 			{
6374 				node_exec_rotate_right_integers,
6375 				NULL,
6376 				NULL,
6377 				node_exec_rotate_right_strint,
6378 				NULL
6379 			}
6380 		},
6381 		{		/*** binary !< operator ***/
6382 			NODE_TYPE_OPERATOR,
6383 			NODE_SUBTYPE_ROTATE_LEFT,
6384 			NULL,
6385 			EXEC_LR,
6386 			{
6387 				node_exec_rotate_left_integers,
6388 				NULL,
6389 				NULL,
6390 				node_exec_rotate_left_strint,
6391 				NULL
6392 			}
6393 		},
6394 		{		/*** binary & operator ***/
6395 			NODE_TYPE_OPERATOR,
6396 			NODE_SUBTYPE_AND,
6397 			NULL,
6398 			EXEC_LR,
6399 			{
6400 				node_exec_and_integers,
6401 				NULL,
6402 				node_exec_add_strings,
6403 				node_exec_add_strint,
6404 				NULL
6405 			}
6406 		},
6407 		{		/*** binary | operator ***/
6408 			NODE_TYPE_OPERATOR,
6409 			NODE_SUBTYPE_OR,
6410 			NULL,
6411 			EXEC_LR,
6412 			{
6413 				node_exec_or_integers,
6414 				NULL,
6415 				NULL,
6416 				NULL,
6417 				NULL
6418 			}
6419 		},
6420 		{		/*** binary ^ operator ***/
6421 			NODE_TYPE_OPERATOR,
6422 			NODE_SUBTYPE_XOR,
6423 			NULL,
6424 			EXEC_LR,
6425 			{
6426 				node_exec_xor_integers,
6427 				NULL,
6428 				NULL,
6429 				NULL,
6430 				NULL
6431 			}
6432 		},
6433 		{		/*** binary && operator ***/
6434 			NODE_TYPE_OPERATOR,
6435 			NODE_SUBTYPE_LOGICAL_AND,
6436 			NULL,
6437 			EXEC_BOOLEAN_LR,
6438 			{
6439 				node_exec_and_integers,		/* the boolean are 0 or 1 only, the bitwise operator works as well! */
6440 				NULL,
6441 				NULL,
6442 				NULL,
6443 				NULL
6444 			}
6445 		},
6446 		{		/*** binary || operator ***/
6447 			NODE_TYPE_OPERATOR,
6448 			NODE_SUBTYPE_LOGICAL_OR,
6449 			NULL,
6450 			EXEC_BOOLEAN_LR,
6451 			{
6452 				node_exec_or_integers,		/* the boolean are 0 or 1 only, the bitwise operator works as well! */
6453 				NULL,
6454 				NULL,
6455 				NULL,
6456 				NULL
6457 			}
6458 		},
6459 		{		/*** binary ^^ operator ***/
6460 			NODE_TYPE_OPERATOR,
6461 			NODE_SUBTYPE_LOGICAL_XOR,
6462 			NULL,
6463 			EXEC_BOOLEAN_LR,
6464 			{
6465 				node_exec_xor_integers,		/* the boolean are 0 or 1 only, the bitwise operator works as well! */
6466 				NULL,
6467 				NULL,
6468 				NULL,
6469 				NULL
6470 			}
6471 		},
6472 		{		/*** binary == operator ***/
6473 			NODE_TYPE_OPERATOR,
6474 			NODE_SUBTYPE_EQUAL,
6475 			NULL,
6476 			EXEC_LR,
6477 			{
6478 				node_exec_equal_integers,
6479 				node_exec_equal_floats,
6480 				node_exec_equal_strings,
6481 				NULL,
6482 				NULL
6483 			}
6484 		},
6485 		{		/*** binary != operator ***/
6486 			NODE_TYPE_OPERATOR,
6487 			NODE_SUBTYPE_NOT_EQUAL,
6488 			NULL,
6489 			EXEC_LR,
6490 			{
6491 				node_exec_not_equal_integers,
6492 				node_exec_not_equal_floats,
6493 				node_exec_not_equal_strings,
6494 				NULL,
6495 				NULL
6496 			}
6497 		},
6498 		{		/*** binary < operator ***/
6499 			NODE_TYPE_OPERATOR,
6500 			NODE_SUBTYPE_LESS,
6501 			NULL,
6502 			EXEC_LR,
6503 			{
6504 				node_exec_less_integers,
6505 				node_exec_less_floats,
6506 				node_exec_less_strings,
6507 				NULL,
6508 				NULL
6509 			}
6510 		},
6511 		{		/*** binary <= operator ***/
6512 			NODE_TYPE_OPERATOR,
6513 			NODE_SUBTYPE_LESS_EQUAL,
6514 			NULL,
6515 			EXEC_LR,
6516 			{
6517 				node_exec_less_equal_integers,
6518 				node_exec_less_equal_floats,
6519 				node_exec_less_equal_strings,
6520 				NULL,
6521 				NULL
6522 			}
6523 		},
6524 		{		/*** binary > operator ***/
6525 			NODE_TYPE_OPERATOR,
6526 			NODE_SUBTYPE_GREATER,
6527 			NULL,
6528 			EXEC_LR,
6529 			{
6530 				node_exec_greater_integers,
6531 				node_exec_greater_floats,
6532 				node_exec_greater_strings,
6533 				NULL,
6534 				NULL
6535 			}
6536 		},
6537 		{		/*** binary >= operator ***/
6538 			NODE_TYPE_OPERATOR,
6539 			NODE_SUBTYPE_GREATER_EQUAL,
6540 			NULL,
6541 			EXEC_LR,
6542 			{
6543 				node_exec_greater_equal_integers,
6544 				node_exec_greater_equal_floats,
6545 				node_exec_greater_equal_strings,
6546 				NULL,
6547 				NULL
6548 			}
6549 		},
6550 		{		/*** trinary ?: operator ***/
6551 			NODE_TYPE_OPERATOR,
6552 			NODE_SUBTYPE_SELECT,
6553 			NULL,
6554 			EXEC_SELECT,
6555 			{
6556 				node_exec_select_integers,
6557 				NULL,
6558 				NULL,
6559 				NULL,
6560 				NULL
6561 			}
6562 		},
6563 		{		/*** binary = operator ***/
6564 			NODE_TYPE_OPERATOR,
6565 			NODE_SUBTYPE_LET,
6566 			NULL,
6567 			EXEC_LEFT,		/* determine the name, but keep the other expression as is */
6568 			{
6569 				node_exec_let,
6570 				NULL,
6571 				NULL,
6572 				NULL,
6573 				NULL
6574 			}
6575 		},
6576 		{		/*** object: ACTION "ADD" ***/
6577 			NODE_TYPE_OBJECT,
6578 			NODE_SUBTYPE_ACTION,
6579 			"ADD",
6580 			EXEC_DEFINITIONS,
6581 			{
6582 				node_exec_nothing,
6583 				(node_exec_func) node_def_action_simple,
6584 				NULL,
6585 				NULL,
6586 				NULL
6587 			}
6588 		},
6589 		{		/*** object: ACTION "ADD CAST" ***/
6590 			NODE_TYPE_OBJECT,
6591 			NODE_SUBTYPE_ACTION,
6592 			"ADD.CAST",
6593 			EXEC_DEFINITIONS,
6594 			{
6595 				node_exec_nothing,
6596 				(node_exec_func) node_def_action_simple,
6597 				NULL,
6598 				NULL,
6599 				NULL
6600 			}
6601 		},
6602 		{		/*** object: ACTION "AND" ***/
6603 			NODE_TYPE_OBJECT,
6604 			NODE_SUBTYPE_ACTION,
6605 			"AND",
6606 			EXEC_DEFINITIONS,
6607 			{
6608 				node_exec_nothing,
6609 				(node_exec_func) node_def_action_simple,
6610 				NULL,
6611 				NULL,
6612 				NULL
6613 			}
6614 		},
6615 		{		/*** object: ACTION "BRANCH" ***/
6616 			NODE_TYPE_OBJECT,
6617 			NODE_SUBTYPE_ACTION,
6618 			"BRANCH",
6619 			EXEC_DEFINITIONS,
6620 			{
6621 				node_exec_nothing,
6622 				(node_exec_func) node_def_action_branch,
6623 				NULL,
6624 				NULL,
6625 				NULL
6626 			}
6627 		},
6628 		{		/*** object: ACTION "BRANCH ALWAYS" ***/
6629 			NODE_TYPE_OBJECT,
6630 			NODE_SUBTYPE_ACTION,
6631 			"BRANCH.ALWAYS",
6632 			EXEC_DEFINITIONS,
6633 			{
6634 				node_exec_nothing,
6635 				(node_exec_func) node_def_action_branch,
6636 				NULL,
6637 				NULL,
6638 				NULL
6639 			}
6640 		},
6641 		{		/*** object: ACTION "BRANCH IF TRUE" ***/
6642 			NODE_TYPE_OBJECT,
6643 			NODE_SUBTYPE_ACTION,
6644 			"BRANCH.IF.TRUE",
6645 			EXEC_DEFINITIONS,
6646 			{
6647 				node_exec_nothing,
6648 				(node_exec_func) node_def_action_branch,
6649 				NULL,
6650 				NULL,
6651 				NULL
6652 			}
6653 		},
6654 		{		/*** object: ACTION "CALL FRAME" ***/
6655 			NODE_TYPE_OBJECT,
6656 			NODE_SUBTYPE_ACTION,
6657 			"CALL.FRAME",
6658 			EXEC_DEFINITIONS,
6659 			{
6660 				node_exec_nothing,
6661 				(node_exec_func) node_def_action_simple,
6662 				NULL,
6663 				NULL,
6664 				NULL
6665 			}
6666 		},
6667 		{		/*** object: ACTION "CALL FUNCTION" ***/
6668 			NODE_TYPE_OBJECT,
6669 			NODE_SUBTYPE_ACTION,
6670 			"CALL.FUNCTION",
6671 			EXEC_DEFINITIONS,
6672 			{
6673 				node_exec_nothing,
6674 				(node_exec_func) node_def_action_simple,
6675 				NULL,
6676 				NULL,
6677 				NULL
6678 			}
6679 		},
6680 		{		/*** object: ACTION "CALL METHOD" ***/
6681 			NODE_TYPE_OBJECT,
6682 			NODE_SUBTYPE_ACTION,
6683 			"CALL.METHOD",
6684 			EXEC_DEFINITIONS,
6685 			{
6686 				node_exec_nothing,
6687 				(node_exec_func) node_def_action_simple,
6688 				NULL,
6689 				NULL,
6690 				NULL
6691 			}
6692 		},
6693 		{		/*** object: ACTION "CAST OBJECT" ***/
6694 			NODE_TYPE_OBJECT,
6695 			NODE_SUBTYPE_ACTION,
6696 			"CAST.OBJECT",
6697 			EXEC_DEFINITIONS,
6698 			{
6699 				node_exec_nothing,
6700 				(node_exec_func) node_def_action_simple,
6701 				NULL,
6702 				NULL,
6703 				NULL
6704 			}
6705 		},
6706 		{		/*** object: ACTION "CHR" ***/
6707 			NODE_TYPE_OBJECT,
6708 			NODE_SUBTYPE_ACTION,
6709 			"CHR",
6710 			EXEC_DEFINITIONS,
6711 			{
6712 				node_exec_nothing,
6713 				(node_exec_func) node_def_action_simple,
6714 				NULL,
6715 				NULL,
6716 				NULL
6717 			}
6718 		},
6719 		{		/*** object: ACTION "CONCATENATE" ***/
6720 			NODE_TYPE_OBJECT,
6721 			NODE_SUBTYPE_ACTION,
6722 			"CONCATENATE",
6723 			EXEC_DEFINITIONS,
6724 			{
6725 				node_exec_nothing,
6726 				(node_exec_func) node_def_action_simple,
6727 				NULL,
6728 				NULL,
6729 				NULL
6730 			}
6731 		},
6732 		{		/*** object: ACTION "CONCATENATE STRING" ***/
6733 			NODE_TYPE_OBJECT,
6734 			NODE_SUBTYPE_ACTION,
6735 			"CONCATENATE.STRING",
6736 			EXEC_DEFINITIONS,
6737 			{
6738 				node_exec_nothing,
6739 				(node_exec_func) node_def_action_simple,
6740 				NULL,
6741 				NULL,
6742 				NULL
6743 			}
6744 		},
6745 		{		/*** object: ACTION "CONSTANT POOL" ***/
6746 			NODE_TYPE_OBJECT,
6747 			NODE_SUBTYPE_ACTION,
6748 			"CONSTANT.POOL",
6749 			EXEC_DEFINITIONS,
6750 			{
6751 				node_exec_nothing,
6752 				(node_exec_func) node_def_action_dictionary,
6753 				NULL,
6754 				NULL,
6755 				NULL
6756 			}
6757 		},
6758 		{		/*** object: ACTION "DECLARE ARRAY" ***/
6759 			NODE_TYPE_OBJECT,
6760 			NODE_SUBTYPE_ACTION,
6761 			"DECLARE.ARRAY",
6762 			EXEC_DEFINITIONS,
6763 			{
6764 				node_exec_nothing,
6765 				(node_exec_func) node_def_action_simple,
6766 				NULL,
6767 				NULL,
6768 				NULL
6769 			}
6770 		},
6771 		{		/*** object: ACTION "DECLARE LOCAL VARIABLE" ***/
6772 			NODE_TYPE_OBJECT,
6773 			NODE_SUBTYPE_ACTION,
6774 			"DECLARE.LOCAL.VARIABLE",
6775 			EXEC_DEFINITIONS,
6776 			{
6777 				node_exec_nothing,
6778 				(node_exec_func) node_def_action_simple,
6779 				NULL,
6780 				NULL,
6781 				NULL
6782 			}
6783 		},
6784 		{		/*** object: ACTION "DECLARE OBJECT" ***/
6785 			NODE_TYPE_OBJECT,
6786 			NODE_SUBTYPE_ACTION,
6787 			"DECLARE.OBJECT",
6788 			EXEC_DEFINITIONS,
6789 			{
6790 				node_exec_nothing,
6791 				(node_exec_func) node_def_action_simple,
6792 				NULL,
6793 				NULL,
6794 				NULL
6795 			}
6796 		},
6797 		{		/*** object: ACTION "DECREMENT" ***/
6798 			NODE_TYPE_OBJECT,
6799 			NODE_SUBTYPE_ACTION,
6800 			"DECREMENT",
6801 			EXEC_DEFINITIONS,
6802 			{
6803 				node_exec_nothing,
6804 				(node_exec_func) node_def_action_simple,
6805 				NULL,
6806 				NULL,
6807 				NULL
6808 			}
6809 		},
6810 		{		/*** object: ACTION "DELETE" ***/
6811 			NODE_TYPE_OBJECT,
6812 			NODE_SUBTYPE_ACTION,
6813 			"DELETE",
6814 			EXEC_DEFINITIONS,
6815 			{
6816 				node_exec_nothing,
6817 				(node_exec_func) node_def_action_simple,
6818 				NULL,
6819 				NULL,
6820 				NULL
6821 			}
6822 		},
6823 		{		/*** object: ACTION "DICTIONARY" ***/
6824 			NODE_TYPE_OBJECT,
6825 			NODE_SUBTYPE_ACTION,
6826 			"DICTIONARY",
6827 			EXEC_DEFINITIONS,
6828 			{
6829 				node_exec_nothing,
6830 				(node_exec_func) node_def_action_dictionary,
6831 				NULL,
6832 				NULL,
6833 				NULL
6834 			}
6835 		},
6836 		{		/*** object: ACTION "DIVIDE" ***/
6837 			NODE_TYPE_OBJECT,
6838 			NODE_SUBTYPE_ACTION,
6839 			"DIVIDE",
6840 			EXEC_DEFINITIONS,
6841 			{
6842 				node_exec_nothing,
6843 				(node_exec_func) node_def_action_simple,
6844 				NULL,
6845 				NULL,
6846 				NULL
6847 			}
6848 		},
6849 		{		/*** object: ACTION "DUPLICATE" ***/
6850 			NODE_TYPE_OBJECT,
6851 			NODE_SUBTYPE_ACTION,
6852 			"DUPLICATE",
6853 			EXEC_DEFINITIONS,
6854 			{
6855 				node_exec_nothing,
6856 				(node_exec_func) node_def_action_simple,
6857 				NULL,
6858 				NULL,
6859 				NULL
6860 			}
6861 		},
6862 		{		/*** object: ACTION "DUPLICATE SPRITE" ***/
6863 			NODE_TYPE_OBJECT,
6864 			NODE_SUBTYPE_ACTION,
6865 			"DUPLICATE.SPRITE",
6866 			EXEC_DEFINITIONS,
6867 			{
6868 				node_exec_nothing,
6869 				(node_exec_func) node_def_action_simple,
6870 				NULL,
6871 				NULL,
6872 				NULL
6873 			}
6874 		},
6875 		{		/*** object: ACTION "ENUMERATE" ***/
6876 			NODE_TYPE_OBJECT,
6877 			NODE_SUBTYPE_ACTION,
6878 			"ENUMERATE",
6879 			EXEC_DEFINITIONS,
6880 			{
6881 				node_exec_nothing,
6882 				(node_exec_func) node_def_action_simple,
6883 				NULL,
6884 				NULL,
6885 				NULL
6886 			}
6887 		},
6888 		{		/*** object: ACTION "ENUMERATE OBJECT" ***/
6889 			NODE_TYPE_OBJECT,
6890 			NODE_SUBTYPE_ACTION,
6891 			"ENUMERATE.OBJECT",
6892 			EXEC_DEFINITIONS,
6893 			{
6894 				node_exec_nothing,
6895 				(node_exec_func) node_def_action_simple,
6896 				NULL,
6897 				NULL,
6898 				NULL
6899 			}
6900 		},
6901 		{		/*** object: ACTION "EQUAL" ***/
6902 			NODE_TYPE_OBJECT,
6903 			NODE_SUBTYPE_ACTION,
6904 			"EQUAL",
6905 			EXEC_DEFINITIONS,
6906 			{
6907 				node_exec_nothing,
6908 				(node_exec_func) node_def_action_simple,
6909 				NULL,
6910 				NULL,
6911 				NULL
6912 			}
6913 		},
6914 		{		/*** object: ACTION "EQUAL CAST" ***/
6915 			NODE_TYPE_OBJECT,
6916 			NODE_SUBTYPE_ACTION,
6917 			"EQUAL.CAST",
6918 			EXEC_DEFINITIONS,
6919 			{
6920 				node_exec_nothing,
6921 				(node_exec_func) node_def_action_simple,
6922 				NULL,
6923 				NULL,
6924 				NULL
6925 			}
6926 		},
6927 		{		/*** object: ACTION "EXTENDS" ***/
6928 			NODE_TYPE_OBJECT,
6929 			NODE_SUBTYPE_ACTION,
6930 			"EXTENDS",
6931 			EXEC_DEFINITIONS,
6932 			{
6933 				node_exec_nothing,
6934 				(node_exec_func) node_def_action_simple,
6935 				NULL,
6936 				NULL,
6937 				NULL
6938 			}
6939 		},
6940 		{		/*** object: ACTION "GET MEMBER" ***/
6941 			NODE_TYPE_OBJECT,
6942 			NODE_SUBTYPE_ACTION,
6943 			"GET.MEMBER",
6944 			EXEC_DEFINITIONS,
6945 			{
6946 				node_exec_nothing,
6947 				(node_exec_func) node_def_action_simple,
6948 				NULL,
6949 				NULL,
6950 				NULL
6951 			}
6952 		},
6953 		{		/*** object: ACTION "GET PROPERTY" ***/
6954 			NODE_TYPE_OBJECT,
6955 			NODE_SUBTYPE_ACTION,
6956 			"GET.PROPERTY",
6957 			EXEC_DEFINITIONS,
6958 			{
6959 				node_exec_nothing,
6960 				(node_exec_func) node_def_action_simple,
6961 				NULL,
6962 				NULL,
6963 				NULL
6964 			}
6965 		},
6966 		{		/*** object: ACTION "GET TARGET" ***/
6967 			NODE_TYPE_OBJECT,
6968 			NODE_SUBTYPE_ACTION,
6969 			"GET.TARGET",
6970 			EXEC_DEFINITIONS,
6971 			{
6972 				node_exec_nothing,
6973 				(node_exec_func) node_def_action_simple,
6974 				NULL,
6975 				NULL,
6976 				NULL
6977 			}
6978 		},
6979 		{		/*** object: ACTION "GET TIMER" ***/
6980 			NODE_TYPE_OBJECT,
6981 			NODE_SUBTYPE_ACTION,
6982 			"GET.TIMER",
6983 			EXEC_DEFINITIONS,
6984 			{
6985 				node_exec_nothing,
6986 				(node_exec_func) node_def_action_simple,
6987 				NULL,
6988 				NULL,
6989 				NULL
6990 			}
6991 		},
6992 		{		/*** object: ACTION "GET VARIABLE" ***/
6993 			NODE_TYPE_OBJECT,
6994 			NODE_SUBTYPE_ACTION,
6995 			"GET.VARIABLE",
6996 			EXEC_DEFINITIONS,
6997 			{
6998 				node_exec_nothing,
6999 				(node_exec_func) node_def_action_simple,
7000 				NULL,
7001 				NULL,
7002 				NULL
7003 			}
7004 		},
7005 		{		/*** object: ACTION "GOTO" ***/
7006 			NODE_TYPE_OBJECT,
7007 			NODE_SUBTYPE_ACTION,
7008 			"GOTO",
7009 			EXEC_DEFINITIONS,
7010 			{
7011 				node_exec_nothing,
7012 				(node_exec_func) node_def_action_goto,
7013 				NULL,
7014 				NULL,
7015 				NULL
7016 			}
7017 		},
7018 		{		/*** object: ACTION "GOTO EXPRESSION" ***/
7019 			NODE_TYPE_OBJECT,
7020 			NODE_SUBTYPE_ACTION,
7021 			"GOTO.EXPRESSION",
7022 			EXEC_DEFINITIONS,
7023 			{
7024 				node_exec_nothing,
7025 				(node_exec_func) node_def_action_goto,
7026 				NULL,
7027 				NULL,
7028 				NULL
7029 			}
7030 		},
7031 		{		/*** object: ACTION "GOTO FRAME" ***/
7032 			NODE_TYPE_OBJECT,
7033 			NODE_SUBTYPE_ACTION,
7034 			"GOTO.FRAME",
7035 			EXEC_DEFINITIONS,
7036 			{
7037 				node_exec_nothing,
7038 				(node_exec_func) node_def_action_goto,
7039 				NULL,
7040 				NULL,
7041 				NULL
7042 			}
7043 		},
7044 		{		/*** object: ACTION "GOTO LABEL" ***/
7045 			NODE_TYPE_OBJECT,
7046 			NODE_SUBTYPE_ACTION,
7047 			"GOTO.LABEL",
7048 			EXEC_DEFINITIONS,
7049 			{
7050 				node_exec_nothing,
7051 				(node_exec_func) node_def_action_goto,
7052 				NULL,
7053 				NULL,
7054 				NULL
7055 			}
7056 		},
7057 		{		/*** object: ACTION "GREATER THAN" ***/
7058 			NODE_TYPE_OBJECT,
7059 			NODE_SUBTYPE_ACTION,
7060 			"GREATER.THAN",
7061 			EXEC_DEFINITIONS,
7062 			{
7063 				node_exec_nothing,
7064 				(node_exec_func) node_def_action_simple,
7065 				NULL,
7066 				NULL,
7067 				NULL
7068 			}
7069 		},
7070 		{		/*** object: ACTION "IF TRUE" ***/
7071 			NODE_TYPE_OBJECT,
7072 			NODE_SUBTYPE_ACTION,
7073 			"IF.TRUE",
7074 			EXEC_DEFINITIONS,
7075 			{
7076 				node_exec_nothing,
7077 				(node_exec_func) node_def_action_branch,
7078 				NULL,
7079 				NULL,
7080 				NULL
7081 			}
7082 		},
7083 		{		/*** object: ACTION "IMPLEMENTS" ***/
7084 			NODE_TYPE_OBJECT,
7085 			NODE_SUBTYPE_ACTION,
7086 			"IMPLEMENTS",
7087 			EXEC_DEFINITIONS,
7088 			{
7089 				node_exec_nothing,
7090 				(node_exec_func) node_def_action_simple,
7091 				NULL,
7092 				NULL,
7093 				NULL
7094 			}
7095 		},
7096 		{		/*** object: ACTION "INCREMENT" ***/
7097 			NODE_TYPE_OBJECT,
7098 			NODE_SUBTYPE_ACTION,
7099 			"INCREMENT",
7100 			EXEC_DEFINITIONS,
7101 			{
7102 				node_exec_nothing,
7103 				(node_exec_func) node_def_action_simple,
7104 				NULL,
7105 				NULL,
7106 				NULL
7107 			}
7108 		},
7109 		{		/*** object: ACTION "INSTANCE OF" ***/
7110 			NODE_TYPE_OBJECT,
7111 			NODE_SUBTYPE_ACTION,
7112 			"INSTANCE.OF",
7113 			EXEC_DEFINITIONS,
7114 			{
7115 				node_exec_nothing,
7116 				(node_exec_func) node_def_action_simple,
7117 				NULL,
7118 				NULL,
7119 				NULL
7120 			}
7121 		},
7122 		{		/*** object: ACTION "INT" ***/
7123 			NODE_TYPE_OBJECT,
7124 			NODE_SUBTYPE_ACTION,
7125 			"INT",
7126 			EXEC_DEFINITIONS,
7127 			{
7128 				node_exec_nothing,
7129 				(node_exec_func) node_def_action_simple,
7130 				NULL,
7131 				NULL,
7132 				NULL
7133 			}
7134 		},
7135 		{		/*** object: ACTION "INTEGRAL PART" ***/
7136 			NODE_TYPE_OBJECT,
7137 			NODE_SUBTYPE_ACTION,
7138 			"INTEGRAL.PART",
7139 			EXEC_DEFINITIONS,
7140 			{
7141 				node_exec_nothing,
7142 				(node_exec_func) node_def_action_simple,
7143 				NULL,
7144 				NULL,
7145 				NULL
7146 			}
7147 		},
7148 		{		/*** object: ACTION "LESS THAN" ***/
7149 			NODE_TYPE_OBJECT,
7150 			NODE_SUBTYPE_ACTION,
7151 			"LESS.THAN",
7152 			EXEC_DEFINITIONS,
7153 			{
7154 				node_exec_nothing,
7155 				(node_exec_func) node_def_action_simple,
7156 				NULL,
7157 				NULL,
7158 				NULL
7159 			}
7160 		},
7161 		{		/*** object: ACTION "LESS THAN CAST" ***/
7162 			NODE_TYPE_OBJECT,
7163 			NODE_SUBTYPE_ACTION,
7164 			"LESS.THAN.CAST",
7165 			EXEC_DEFINITIONS,
7166 			{
7167 				node_exec_nothing,
7168 				(node_exec_func) node_def_action_simple,
7169 				NULL,
7170 				NULL,
7171 				NULL
7172 			}
7173 		},
7174 		{		/*** object: ACTION "LOGICAL AND" ***/
7175 			NODE_TYPE_OBJECT,
7176 			NODE_SUBTYPE_ACTION,
7177 			"LOGICAL.AND",
7178 			EXEC_DEFINITIONS,
7179 			{
7180 				node_exec_nothing,
7181 				(node_exec_func) node_def_action_simple,
7182 				NULL,
7183 				NULL,
7184 				NULL
7185 			}
7186 		},
7187 		{		/*** object: ACTION "LOGICAL NOT" ***/
7188 			NODE_TYPE_OBJECT,
7189 			NODE_SUBTYPE_ACTION,
7190 			"LOGICAL.NOT",
7191 			EXEC_DEFINITIONS,
7192 			{
7193 				node_exec_nothing,
7194 				(node_exec_func) node_def_action_simple,
7195 				NULL,
7196 				NULL,
7197 				NULL
7198 			}
7199 		},
7200 		{		/*** object: ACTION "LOGICAL OR" ***/
7201 			NODE_TYPE_OBJECT,
7202 			NODE_SUBTYPE_ACTION,
7203 			"LOGICAL.OR",
7204 			EXEC_DEFINITIONS,
7205 			{
7206 				node_exec_nothing,
7207 				(node_exec_func) node_def_action_simple,
7208 				NULL,
7209 				NULL,
7210 				NULL
7211 			}
7212 		},
7213 #if 0
7214 // seems I mistakingly defined XOR instead of NOT
7215 		{		/*** object: ACTION "LOGICAL XOR" ***/
7216 			NODE_TYPE_OBJECT,
7217 			NODE_SUBTYPE_ACTION,
7218 			"LOGICAL.XOR",
7219 			EXEC_DEFINITIONS,
7220 			{
7221 				node_exec_nothing,
7222 				(node_exec_func) node_def_action_simple,
7223 				NULL,
7224 				NULL,
7225 				NULL
7226 			}
7227 		},
7228 #endif
7229 		{		/*** object: ACTION "MB CHAR" ***/
7230 			NODE_TYPE_OBJECT,
7231 			NODE_SUBTYPE_ACTION,
7232 			"MB.CHAR",
7233 			EXEC_DEFINITIONS,
7234 			{
7235 				node_exec_nothing,
7236 				(node_exec_func) node_def_action_simple,
7237 				NULL,
7238 				NULL,
7239 				NULL
7240 			}
7241 		},
7242 		{		/*** object: ACTION "MB ORD" ***/
7243 			NODE_TYPE_OBJECT,
7244 			NODE_SUBTYPE_ACTION,
7245 			"MB.ORD",
7246 			EXEC_DEFINITIONS,
7247 			{
7248 				node_exec_nothing,
7249 				(node_exec_func) node_def_action_simple,
7250 				NULL,
7251 				NULL,
7252 				NULL
7253 			}
7254 		},
7255 		{		/*** object: ACTION "MB STRING LENGTH" ***/
7256 			NODE_TYPE_OBJECT,
7257 			NODE_SUBTYPE_ACTION,
7258 			"MB.STRING.LENGTH",
7259 			EXEC_DEFINITIONS,
7260 			{
7261 				node_exec_nothing,
7262 				(node_exec_func) node_def_action_simple,
7263 				NULL,
7264 				NULL,
7265 				NULL
7266 			}
7267 		},
7268 		{		/*** object: ACTION "MODULO" ***/
7269 			NODE_TYPE_OBJECT,
7270 			NODE_SUBTYPE_ACTION,
7271 			"MODULO",
7272 			EXEC_DEFINITIONS,
7273 			{
7274 				node_exec_nothing,
7275 				(node_exec_func) node_def_action_simple,
7276 				NULL,
7277 				NULL,
7278 				NULL
7279 			}
7280 		},
7281 		{		/*** object: ACTION "MULTIPLY" ***/
7282 			NODE_TYPE_OBJECT,
7283 			NODE_SUBTYPE_ACTION,
7284 			"MULTIPLY",
7285 			EXEC_DEFINITIONS,
7286 			{
7287 				node_exec_nothing,
7288 				(node_exec_func) node_def_action_simple,
7289 				NULL,
7290 				NULL,
7291 				NULL
7292 			}
7293 		},
7294 		{		/*** object: ACTION "NEW" ***/
7295 			NODE_TYPE_OBJECT,
7296 			NODE_SUBTYPE_ACTION,
7297 			"NEW",
7298 			EXEC_DEFINITIONS,
7299 			{
7300 				node_exec_nothing,
7301 				(node_exec_func) node_def_action_simple,
7302 				NULL,
7303 				NULL,
7304 				NULL
7305 			}
7306 		},
7307 		{		/*** object: ACTION "NEW METHOD" ***/
7308 			NODE_TYPE_OBJECT,
7309 			NODE_SUBTYPE_ACTION,
7310 			"NEW.METHOD",
7311 			EXEC_DEFINITIONS,
7312 			{
7313 				node_exec_nothing,
7314 				(node_exec_func) node_def_action_simple,
7315 				NULL,
7316 				NULL,
7317 				NULL
7318 			}
7319 		},
7320 		{		/*** object: ACTION "NEXT FRAME" ***/
7321 			NODE_TYPE_OBJECT,
7322 			NODE_SUBTYPE_ACTION,
7323 			"NEXT.FRAME",
7324 			EXEC_DEFINITIONS,
7325 			{
7326 				node_exec_nothing,
7327 				(node_exec_func) node_def_action_simple,
7328 				NULL,
7329 				NULL,
7330 				NULL
7331 			}
7332 		},
7333 		{		/*** object: ACTION "NUMBER" ***/
7334 			NODE_TYPE_OBJECT,
7335 			NODE_SUBTYPE_ACTION,
7336 			"NUMBER",
7337 			EXEC_DEFINITIONS,
7338 			{
7339 				node_exec_nothing,
7340 				(node_exec_func) node_def_action_simple,
7341 				NULL,
7342 				NULL,
7343 				NULL
7344 			}
7345 		},
7346 		{		/*** object: ACTION "OR" ***/
7347 			NODE_TYPE_OBJECT,
7348 			NODE_SUBTYPE_ACTION,
7349 			"OR",
7350 			EXEC_DEFINITIONS,
7351 			{
7352 				node_exec_nothing,
7353 				(node_exec_func) node_def_action_simple,
7354 				NULL,
7355 				NULL,
7356 				NULL
7357 			}
7358 		},
7359 		{		/*** object: ACTION "ORD" ***/
7360 			NODE_TYPE_OBJECT,
7361 			NODE_SUBTYPE_ACTION,
7362 			"ORD",
7363 			EXEC_DEFINITIONS,
7364 			{
7365 				node_exec_nothing,
7366 				(node_exec_func) node_def_action_simple,
7367 				NULL,
7368 				NULL,
7369 				NULL
7370 			}
7371 		},
7372 		{		/*** object: ACTION "PLAY" ***/
7373 			NODE_TYPE_OBJECT,
7374 			NODE_SUBTYPE_ACTION,
7375 			"PLAY",
7376 			EXEC_DEFINITIONS,
7377 			{
7378 				node_exec_nothing,
7379 				(node_exec_func) node_def_action_simple,
7380 				NULL,
7381 				NULL,
7382 				NULL
7383 			}
7384 		},
7385 		{		/*** object: ACTION "POP" ***/
7386 			NODE_TYPE_OBJECT,
7387 			NODE_SUBTYPE_ACTION,
7388 			"POP",
7389 			EXEC_DEFINITIONS,
7390 			{
7391 				node_exec_nothing,
7392 				(node_exec_func) node_def_action_simple,
7393 				NULL,
7394 				NULL,
7395 				NULL
7396 			}
7397 		},
7398 		{		/*** object: ACTION "PREVIOUS FRAME" ***/
7399 			NODE_TYPE_OBJECT,
7400 			NODE_SUBTYPE_ACTION,
7401 			"PREVIOUS.FRAME",
7402 			EXEC_DEFINITIONS,
7403 			{
7404 				node_exec_nothing,
7405 				(node_exec_func) node_def_action_simple,
7406 				NULL,
7407 				NULL,
7408 				NULL
7409 			}
7410 		},
7411 		{		/*** object: ACTION "PUSH DATA" ***/
7412 			NODE_TYPE_OBJECT,
7413 			NODE_SUBTYPE_ACTION,
7414 			"PUSH.DATA",
7415 			EXEC_DEFINITIONS,
7416 			{
7417 				node_exec_nothing,
7418 				(node_exec_func) node_def_action_push_data,
7419 				NULL,
7420 				NULL,
7421 				NULL
7422 			}
7423 		},
7424 		{		/*** object: ACTION "RANDOM" ***/
7425 			NODE_TYPE_OBJECT,
7426 			NODE_SUBTYPE_ACTION,
7427 			"RANDOM",
7428 			EXEC_DEFINITIONS,
7429 			{
7430 				node_exec_nothing,
7431 				(node_exec_func) node_def_action_simple,
7432 				NULL,
7433 				NULL,
7434 				NULL
7435 			}
7436 		},
7437 		{		/*** object: ACTION "REMOVE SPRITE" ***/
7438 			NODE_TYPE_OBJECT,
7439 			NODE_SUBTYPE_ACTION,
7440 			"REMOVE.SPRITE",
7441 			EXEC_DEFINITIONS,
7442 			{
7443 				node_exec_nothing,
7444 				(node_exec_func) node_def_action_simple,
7445 				NULL,
7446 				NULL,
7447 				NULL
7448 			}
7449 		},
7450 		{		/*** object: ACTION "RETURN" ***/
7451 			NODE_TYPE_OBJECT,
7452 			NODE_SUBTYPE_ACTION,
7453 			"RETURN",
7454 			EXEC_DEFINITIONS,
7455 			{
7456 				node_exec_nothing,
7457 				(node_exec_func) node_def_action_simple,
7458 				NULL,
7459 				NULL,
7460 				NULL
7461 			}
7462 		},
7463 		{		/*** object: SCENE FRAME DATA ***/
7464 			NODE_TYPE_OBJECT,
7465 			NODE_SUBTYPE_SCENE_FRAME_DATA,
7466 			NULL,
7467 			EXEC_DEFINITIONS,
7468 			{
7469 				node_exec_nothing,
7470 				(node_exec_func) node_def_sceneframedata,
7471 				NULL,
7472 				NULL,
7473 				NULL
7474 			}
7475 		},
7476 		{		/*** object: ACTION "SET LOCAL VARIABLE" ***/
7477 			NODE_TYPE_OBJECT,
7478 			NODE_SUBTYPE_ACTION,
7479 			"SET.LOCAL.VARIABLE",
7480 			EXEC_DEFINITIONS,
7481 			{
7482 				node_exec_nothing,
7483 				(node_exec_func) node_def_action_simple,
7484 				NULL,
7485 				NULL,
7486 				NULL
7487 			}
7488 		},
7489 		{		/*** object: ACTION "SET MEMBER" ***/
7490 			NODE_TYPE_OBJECT,
7491 			NODE_SUBTYPE_ACTION,
7492 			"SET.MEMBER",
7493 			EXEC_DEFINITIONS,
7494 			{
7495 				node_exec_nothing,
7496 				(node_exec_func) node_def_action_simple,
7497 				NULL,
7498 				NULL,
7499 				NULL
7500 			}
7501 		},
7502 		{		/*** object: ACTION "SET PROPERTY" ***/
7503 			NODE_TYPE_OBJECT,
7504 			NODE_SUBTYPE_ACTION,
7505 			"SET.PROPERTY",
7506 			EXEC_DEFINITIONS,
7507 			{
7508 				node_exec_nothing,
7509 				(node_exec_func) node_def_action_simple,
7510 				NULL,
7511 				NULL,
7512 				NULL
7513 			}
7514 		},
7515 		{		/*** object: ACTION "SET TARGET" ***/
7516 			NODE_TYPE_OBJECT,
7517 			NODE_SUBTYPE_ACTION,
7518 			"SET.TARGET",
7519 			EXEC_DEFINITIONS,
7520 			{
7521 				node_exec_nothing,
7522 				(node_exec_func) node_def_action_set_target,
7523 				NULL,
7524 				NULL,
7525 				NULL
7526 			}
7527 		},
7528 		{		/*** object: ACTION "SET VARIABLE" ***/
7529 			NODE_TYPE_OBJECT,
7530 			NODE_SUBTYPE_ACTION,
7531 			"SET.VARIABLE",
7532 			EXEC_DEFINITIONS,
7533 			{
7534 				node_exec_nothing,
7535 				(node_exec_func) node_def_action_simple,
7536 				NULL,
7537 				NULL,
7538 				NULL
7539 			}
7540 		},
7541 		{		/*** object: ACTION "SHIFT LEFT" ***/
7542 			NODE_TYPE_OBJECT,
7543 			NODE_SUBTYPE_ACTION,
7544 			"SHIFT.LEFT",
7545 			EXEC_DEFINITIONS,
7546 			{
7547 				node_exec_nothing,
7548 				(node_exec_func) node_def_action_simple,
7549 				NULL,
7550 				NULL,
7551 				NULL
7552 			}
7553 		},
7554 		{		/*** object: ACTION "SHIFT RIGHT" ***/
7555 			NODE_TYPE_OBJECT,
7556 			NODE_SUBTYPE_ACTION,
7557 			"SHIFT.RIGHT",
7558 			EXEC_DEFINITIONS,
7559 			{
7560 				node_exec_nothing,
7561 				(node_exec_func) node_def_action_simple,
7562 				NULL,
7563 				NULL,
7564 				NULL
7565 			}
7566 		},
7567 		{		/*** object: ACTION "SHIFT RIGHT UNSIGNED" ***/
7568 			NODE_TYPE_OBJECT,
7569 			NODE_SUBTYPE_ACTION,
7570 			"SHIFT.RIGHT.UNSIGNED",
7571 			EXEC_DEFINITIONS,
7572 			{
7573 				node_exec_nothing,
7574 				(node_exec_func) node_def_action_simple,
7575 				NULL,
7576 				NULL,
7577 				NULL
7578 			}
7579 		},
7580 		{		/*** object: ACTION "SHL" ***/
7581 			NODE_TYPE_OBJECT,
7582 			NODE_SUBTYPE_ACTION,
7583 			"SHL",
7584 			EXEC_DEFINITIONS,
7585 			{
7586 				node_exec_nothing,
7587 				(node_exec_func) node_def_action_simple,
7588 				NULL,
7589 				NULL,
7590 				NULL
7591 			}
7592 		},
7593 		{		/*** object: ACTION "SHR" ***/
7594 			NODE_TYPE_OBJECT,
7595 			NODE_SUBTYPE_ACTION,
7596 			"SHR",
7597 			EXEC_DEFINITIONS,
7598 			{
7599 				node_exec_nothing,
7600 				(node_exec_func) node_def_action_simple,
7601 				NULL,
7602 				NULL,
7603 				NULL
7604 			}
7605 		},
7606 		{		/*** object: ACTION "START DRAG" ***/
7607 			NODE_TYPE_OBJECT,
7608 			NODE_SUBTYPE_ACTION,
7609 			"START.DRAG",
7610 			EXEC_DEFINITIONS,
7611 			{
7612 				node_exec_nothing,
7613 				(node_exec_func) node_def_action_simple,
7614 				NULL,
7615 				NULL,
7616 				NULL
7617 			}
7618 		},
7619 		{		/*** object: ACTION "STOP" ***/
7620 			NODE_TYPE_OBJECT,
7621 			NODE_SUBTYPE_ACTION,
7622 			"STOP",
7623 			EXEC_DEFINITIONS,
7624 			{
7625 				node_exec_nothing,
7626 				(node_exec_func) node_def_action_simple,
7627 				NULL,
7628 				NULL,
7629 				NULL
7630 			}
7631 		},
7632 		{		/*** object: ACTION "STOP DRAG" ***/
7633 			NODE_TYPE_OBJECT,
7634 			NODE_SUBTYPE_ACTION,
7635 			"STOP.DRAG",
7636 			EXEC_DEFINITIONS,
7637 			{
7638 				node_exec_nothing,
7639 				(node_exec_func) node_def_action_simple,
7640 				NULL,
7641 				NULL,
7642 				NULL
7643 			}
7644 		},
7645 		{		/*** object: ACTION "STOP SOUND" ***/
7646 			NODE_TYPE_OBJECT,
7647 			NODE_SUBTYPE_ACTION,
7648 			"STOP.SOUND",
7649 			EXEC_DEFINITIONS,
7650 			{
7651 				node_exec_nothing,
7652 				(node_exec_func) node_def_action_simple,
7653 				NULL,
7654 				NULL,
7655 				NULL
7656 			}
7657 		},
7658 		{		/*** object: ACTION "STORE REGISTER" ***/
7659 			NODE_TYPE_OBJECT,
7660 			NODE_SUBTYPE_ACTION,
7661 			"STORE.REGISTER",
7662 			EXEC_DEFINITIONS,
7663 			{
7664 				node_exec_nothing,
7665 				(node_exec_func) node_def_action_store_register,
7666 				NULL,
7667 				NULL,
7668 				NULL
7669 			}
7670 		},
7671 		{		/*** object: ACTION "STRICT EQUAL" ***/
7672 			NODE_TYPE_OBJECT,
7673 			NODE_SUBTYPE_ACTION,
7674 			"STRICT.EQUAL",
7675 			EXEC_DEFINITIONS,
7676 			{
7677 				node_exec_nothing,
7678 				(node_exec_func) node_def_action_simple,
7679 				NULL,
7680 				NULL,
7681 				NULL
7682 			}
7683 		},
7684 		{		/*** object: ACTION "STRING" ***/
7685 			NODE_TYPE_OBJECT,
7686 			NODE_SUBTYPE_ACTION,
7687 			"STRING",
7688 			EXEC_DEFINITIONS,
7689 			{
7690 				node_exec_nothing,
7691 				(node_exec_func) node_def_action_simple,
7692 				NULL,
7693 				NULL,
7694 				NULL
7695 			}
7696 		},
7697 		{		/*** object: ACTION "STRING EQUAL" ***/
7698 			NODE_TYPE_OBJECT,
7699 			NODE_SUBTYPE_ACTION,
7700 			"STRING.EQUAL",
7701 			EXEC_DEFINITIONS,
7702 			{
7703 				node_exec_nothing,
7704 				(node_exec_func) node_def_action_simple,
7705 				NULL,
7706 				NULL,
7707 				NULL
7708 			}
7709 		},
7710 		{		/*** object: ACTION "STRING GREATER" ***/
7711 			NODE_TYPE_OBJECT,
7712 			NODE_SUBTYPE_ACTION,
7713 			"STRING.GREATER",
7714 			EXEC_DEFINITIONS,
7715 			{
7716 				node_exec_nothing,
7717 				(node_exec_func) node_def_action_simple,
7718 				NULL,
7719 				NULL,
7720 				NULL
7721 			}
7722 		},
7723 		{		/*** object: ACTION "STRING LENGTH" ***/
7724 			NODE_TYPE_OBJECT,
7725 			NODE_SUBTYPE_ACTION,
7726 			"STRING.LENGTH",
7727 			EXEC_DEFINITIONS,
7728 			{
7729 				node_exec_nothing,
7730 				(node_exec_func) node_def_action_simple,
7731 				NULL,
7732 				NULL,
7733 				NULL
7734 			}
7735 		},
7736 		{		/*** object: ACTION "STRING LESS THAN" ***/
7737 			NODE_TYPE_OBJECT,
7738 			NODE_SUBTYPE_ACTION,
7739 			"STRING.LESS.THAN",
7740 			EXEC_DEFINITIONS,
7741 			{
7742 				node_exec_nothing,
7743 				(node_exec_func) node_def_action_simple,
7744 				NULL,
7745 				NULL,
7746 				NULL
7747 			}
7748 		},
7749 		{		/*** object: ACTION "SUB MBSTRING" ***/
7750 			NODE_TYPE_OBJECT,
7751 			NODE_SUBTYPE_ACTION,
7752 			"SUB.MBSTRING",
7753 			EXEC_DEFINITIONS,
7754 			{
7755 				node_exec_nothing,
7756 				(node_exec_func) node_def_action_simple,
7757 				NULL,
7758 				NULL,
7759 				NULL
7760 			}
7761 		},
7762 		{		/*** object: ACTION "SUB STRING" ***/
7763 			NODE_TYPE_OBJECT,
7764 			NODE_SUBTYPE_ACTION,
7765 			"SUB.STRING",
7766 			EXEC_DEFINITIONS,
7767 			{
7768 				node_exec_nothing,
7769 				(node_exec_func) node_def_action_simple,
7770 				NULL,
7771 				NULL,
7772 				NULL
7773 			}
7774 		},
7775 		/* NOTE: I'm keeping the wrong syntax, but the correct keyword is now SUBTRACT */
7776 		{		/*** object: ACTION "SUBSTRACT" ***/
7777 			NODE_TYPE_OBJECT,
7778 			NODE_SUBTYPE_ACTION,
7779 			"SUBSTRACT",
7780 			EXEC_DEFINITIONS,
7781 			{
7782 				node_exec_nothing,
7783 				(node_exec_func) node_def_action_simple,
7784 				NULL,
7785 				NULL,
7786 				NULL
7787 			}
7788 		},
7789 		{		/*** object: ACTION "SUBTRACT" ***/
7790 			NODE_TYPE_OBJECT,
7791 			NODE_SUBTYPE_ACTION,
7792 			"SUBTRACT",
7793 			EXEC_DEFINITIONS,
7794 			{
7795 				node_exec_nothing,
7796 				(node_exec_func) node_def_action_simple,
7797 				NULL,
7798 				NULL,
7799 				NULL
7800 			}
7801 		},
7802 		{		/*** object: ACTION "SWAP" ***/
7803 			NODE_TYPE_OBJECT,
7804 			NODE_SUBTYPE_ACTION,
7805 			"SWAP",
7806 			EXEC_DEFINITIONS,
7807 			{
7808 				node_exec_nothing,
7809 				(node_exec_func) node_def_action_simple,
7810 				NULL,
7811 				NULL,
7812 				NULL
7813 			}
7814 		},
7815 		{		/*** object: ACTION "THROW" ***/
7816 			NODE_TYPE_OBJECT,
7817 			NODE_SUBTYPE_ACTION,
7818 			"THROW",
7819 			EXEC_DEFINITIONS,
7820 			{
7821 				node_exec_nothing,
7822 				(node_exec_func) node_def_action_simple,
7823 				NULL,
7824 				NULL,
7825 				NULL
7826 			}
7827 		},
7828 		{		/*** object: ACTION "TOGGLE QUALITY" ***/
7829 			NODE_TYPE_OBJECT,
7830 			NODE_SUBTYPE_ACTION,
7831 			"TOGGLE.QUALITY",
7832 			EXEC_DEFINITIONS,
7833 			{
7834 				node_exec_nothing,
7835 				(node_exec_func) node_def_action_simple,
7836 				NULL,
7837 				NULL,
7838 				NULL
7839 			}
7840 		},
7841 		{		/*** object: ACTION "TRACE" ***/
7842 			NODE_TYPE_OBJECT,
7843 			NODE_SUBTYPE_ACTION,
7844 			"TRACE",
7845 			EXEC_DEFINITIONS,
7846 			{
7847 				node_exec_nothing,
7848 				(node_exec_func) node_def_action_simple,
7849 				NULL,
7850 				NULL,
7851 				NULL
7852 			}
7853 		},
7854 		{		/*** object: ACTION "TYPE OF" ***/
7855 			NODE_TYPE_OBJECT,
7856 			NODE_SUBTYPE_ACTION,
7857 			"TYPE.OF",
7858 			EXEC_DEFINITIONS,
7859 			{
7860 				node_exec_nothing,
7861 				(node_exec_func) node_def_action_simple,
7862 				NULL,
7863 				NULL,
7864 				NULL
7865 			}
7866 		},
7867 		{		/*** object: ACTION "URL" ***/
7868 			NODE_TYPE_OBJECT,
7869 			NODE_SUBTYPE_ACTION,
7870 			"URL",
7871 			EXEC_DEFINITIONS,
7872 			{
7873 				node_exec_nothing,
7874 				(node_exec_func) node_def_action_url,
7875 				NULL,
7876 				NULL,
7877 				NULL
7878 			}
7879 		},
7880 		{		/*** object: ACTION "USHR" ***/
7881 			NODE_TYPE_OBJECT,
7882 			NODE_SUBTYPE_ACTION,
7883 			"USHR",
7884 			EXEC_DEFINITIONS,
7885 			{
7886 				node_exec_nothing,
7887 				(node_exec_func) node_def_action_simple,
7888 				NULL,
7889 				NULL,
7890 				NULL
7891 			}
7892 		},
7893 		{		/*** object: ACTION "WAIT FOR FRAME" ***/
7894 			NODE_TYPE_OBJECT,
7895 			NODE_SUBTYPE_ACTION,
7896 			"WAIT.FOR.FRAME",
7897 			EXEC_DEFINITIONS,
7898 			{
7899 				node_exec_nothing,
7900 				(node_exec_func) node_def_action_wait_for_frame,
7901 				NULL,
7902 				NULL,
7903 				NULL
7904 			}
7905 		},
7906 		{		/*** object: ACTION "XOR" ***/
7907 			NODE_TYPE_OBJECT,
7908 			NODE_SUBTYPE_ACTION,
7909 			"XOR",
7910 			EXEC_DEFINITIONS,
7911 			{
7912 				node_exec_nothing,
7913 				(node_exec_func) node_def_action_simple,
7914 				NULL,
7915 				NULL,
7916 				NULL
7917 			}
7918 		},
7919 		{		/*** object: ACTION SCRIPT ***/
7920 			NODE_TYPE_OBJECT,
7921 			NODE_SUBTYPE_ACTION_SCRIPT,
7922 			NULL,
7923 			EXEC_DEFINITIONS,
7924 			{
7925 				node_exec_nothing,
7926 				(node_exec_func) node_def_action_script,
7927 				NULL,
7928 				NULL,
7929 				NULL
7930 			}
7931 		},
7932 		{		/*** object: BLOCK ***/
7933 			NODE_TYPE_OBJECT,
7934 			NODE_SUBTYPE_BLOCK,
7935 			NULL,
7936 			EXEC_DEFINITIONS,
7937 			{
7938 				node_exec_nothing,
7939 				(node_exec_func) node_def_list,
7940 				NULL,
7941 				NULL,
7942 				NULL
7943 			}
7944 		},
7945 		{		/*** object: BUTTON ***/
7946 			NODE_TYPE_OBJECT,
7947 			NODE_SUBTYPE_BUTTON,
7948 			NULL,
7949 			EXEC_DEFINITIONS,
7950 			{
7951 				node_exec_nothing,
7952 				(node_exec_func) node_def_button,
7953 				NULL,
7954 				NULL,
7955 				NULL
7956 			}
7957 		},
7958 		{		/*** object: CATCH ***/
7959 			NODE_TYPE_OBJECT,
7960 			NODE_SUBTYPE_CATCH,
7961 			NULL,
7962 			EXEC_DEFINITIONS,
7963 			{
7964 				node_exec_nothing,
7965 				(node_exec_func) node_def_function,
7966 				NULL,
7967 				NULL,
7968 				NULL
7969 			}
7970 		},
7971 		{		/*** object: COLOR ***/
7972 			NODE_TYPE_OBJECT,
7973 			NODE_SUBTYPE_COLOR,
7974 			NULL,
7975 			EXEC_DEFINITIONS,
7976 			{
7977 				node_exec_nothing,
7978 				(node_exec_func) node_def_color,
7979 				NULL,
7980 				NULL,
7981 				NULL
7982 			}
7983 		},
7984 		{		/*** object: COLOR_TRANSFORM ***/
7985 			NODE_TYPE_OBJECT,
7986 			NODE_SUBTYPE_COLOR_TRANSFORM,
7987 			NULL,
7988 			EXEC_DEFINITIONS,
7989 			{
7990 				node_exec_nothing,
7991 				(node_exec_func) node_def_color_transform,
7992 				NULL,
7993 				NULL,
7994 				NULL
7995 			}
7996 		},
7997 		{		/*** object: DO_ACTION ***/
7998 			NODE_TYPE_OBJECT,
7999 			NODE_SUBTYPE_DO_ACTION,
8000 			NULL,
8001 			EXEC_DEFINITIONS,
8002 			{
8003 				node_exec_nothing,
8004 				(node_exec_func) node_def_do_action,
8005 				NULL,
8006 				NULL,
8007 				NULL
8008 			}
8009 		},
8010 		{		/*** object: EDGES ***/
8011 			NODE_TYPE_OBJECT,
8012 			NODE_SUBTYPE_EDGES,
8013 			NULL,
8014 			EXEC_DEFINITIONS,
8015 			{
8016 				node_exec_nothing,
8017 				(node_exec_func) node_def_edges,
8018 				NULL,
8019 				NULL,
8020 				NULL
8021 			}
8022 		},
8023 		{		/*** object: EDIT_TEXT ***/
8024 			NODE_TYPE_OBJECT,
8025 			NODE_SUBTYPE_EDIT_TEXT,
8026 			NULL,
8027 			EXEC_DEFINITIONS,
8028 			{
8029 				node_exec_nothing,
8030 				(node_exec_func) node_def_edit_text,
8031 				NULL,
8032 				NULL,
8033 				NULL
8034 			}
8035 		},
8036 		{		/*** object: END ***/
8037 			NODE_TYPE_OBJECT,
8038 			NODE_SUBTYPE_END,
8039 			NULL,
8040 			EXEC_DEFINITIONS,
8041 			{
8042 				node_exec_nothing,
8043 				(node_exec_func) node_def_end,
8044 				NULL,
8045 				NULL,
8046 				NULL
8047 			}
8048 		},
8049 		{		/*** object: ENVELOPE ***/
8050 			NODE_TYPE_OBJECT,
8051 			NODE_SUBTYPE_ENVELOPE,
8052 			NULL,
8053 			EXEC_DEFINITIONS,
8054 			{
8055 				node_exec_nothing,
8056 				(node_exec_func) node_def_envelope,
8057 				NULL,
8058 				NULL,
8059 				NULL
8060 			}
8061 		},
8062 		{		/*** object: EXPORT ***/
8063 			NODE_TYPE_OBJECT,
8064 			NODE_SUBTYPE_EXPORT,
8065 			NULL,
8066 			EXEC_DEFINITIONS,
8067 			{
8068 				node_exec_nothing,
8069 				(node_exec_func) node_def_export,
8070 				NULL,
8071 				NULL,
8072 				NULL
8073 			}
8074 		},
8075 		{		/*** object: FILL_STYLE ***/
8076 			NODE_TYPE_OBJECT,
8077 			NODE_SUBTYPE_FILL_STYLE,
8078 			NULL,
8079 			EXEC_DEFINITIONS,
8080 			{
8081 				node_exec_nothing,
8082 				(node_exec_func) node_def_fill_style,
8083 				NULL,
8084 				NULL,
8085 				NULL
8086 			}
8087 		},
8088 		{		/*** object: FINALLY ***/
8089 			NODE_TYPE_OBJECT,
8090 			NODE_SUBTYPE_FINALLY,
8091 			NULL,
8092 			EXEC_DEFINITIONS,
8093 			{
8094 				node_exec_nothing,
8095 				(node_exec_func) node_def_function,
8096 				NULL,
8097 				NULL,
8098 				NULL
8099 			}
8100 		},
8101 		{		/*** object: FONT ***/
8102 			NODE_TYPE_OBJECT,
8103 			NODE_SUBTYPE_FONT,
8104 			NULL,
8105 			EXEC_DEFINITIONS,
8106 			{
8107 				node_exec_nothing,
8108 				(node_exec_func) node_def_font,
8109 				NULL,
8110 				NULL,
8111 				NULL
8112 			}
8113 		},
8114 		{		/*** object: FOR -- this actually repeats some definitions ***/
8115 			NODE_TYPE_OBJECT,
8116 			NODE_SUBTYPE_FOR,
8117 			NULL,
8118 			0,
8119 			{
8120 				node_exec_for,
8121 				NULL,
8122 				NULL,
8123 				NULL,
8124 				NULL
8125 			}
8126 		},
8127 		{		/*** object: FRAME LABEL ***/
8128 			NODE_TYPE_OBJECT,
8129 			NODE_SUBTYPE_FRAME_LABEL,
8130 			NULL,
8131 			EXEC_DEFINITIONS,
8132 			{
8133 				node_exec_nothing,
8134 				(node_exec_func) node_def_frame_label,
8135 				NULL,
8136 				NULL,
8137 				NULL
8138 			}
8139 		},
8140 		{		/*** object: FUNCTION ***/
8141 			NODE_TYPE_OBJECT,
8142 			NODE_SUBTYPE_FUNCTION,
8143 			NULL,
8144 			EXEC_DEFINITIONS,
8145 			{
8146 				node_exec_nothing,
8147 				(node_exec_func) node_def_function,
8148 				NULL,
8149 				NULL,
8150 				NULL
8151 			}
8152 		},
8153 		{		/*** object: GLYPH ***/
8154 			NODE_TYPE_OBJECT,
8155 			NODE_SUBTYPE_GLYPH,
8156 			NULL,
8157 			EXEC_DEFINITIONS,
8158 			{
8159 				node_exec_nothing,
8160 				(node_exec_func) node_def_glyph,
8161 				NULL,
8162 				NULL,
8163 				NULL
8164 			}
8165 		},
8166 		{		/*** object: GRADIENT ***/
8167 			NODE_TYPE_OBJECT,
8168 			NODE_SUBTYPE_GRADIENT,
8169 			NULL,
8170 			EXEC_DEFINITIONS,
8171 			{
8172 				node_exec_nothing,
8173 				(node_exec_func) node_def_gradient,
8174 				NULL,
8175 				NULL,
8176 				NULL
8177 			}
8178 		},
8179 		{		/*** object: IF ***/
8180 			NODE_TYPE_OPERATOR,
8181 			NODE_SUBTYPE_IF,
8182 			NULL,
8183 			EXEC_SELECT,
8184 			{
8185 				node_exec_if_integers,
8186 				NULL,
8187 				NULL,
8188 				NULL,
8189 				NULL
8190 			}
8191 		},
8192 		{		/*** object: IMAGE ***/
8193 			NODE_TYPE_OBJECT,
8194 			NODE_SUBTYPE_IMAGE,
8195 			NULL,
8196 			EXEC_DEFINITIONS,
8197 			{
8198 				node_exec_nothing,
8199 				(node_exec_func) node_def_image,
8200 				NULL,
8201 				NULL,
8202 				NULL
8203 			}
8204 		},
8205 		{		/*** object: IMPORT ***/
8206 			NODE_TYPE_OBJECT,
8207 			NODE_SUBTYPE_IMPORT,
8208 			NULL,
8209 			EXEC_DEFINITIONS,
8210 			{
8211 				node_exec_nothing,
8212 				(node_exec_func) node_def_import,
8213 				NULL,
8214 				NULL,
8215 				NULL
8216 			}
8217 		},
8218 		{		/*** object: LABEL ***/
8219 			NODE_TYPE_OBJECT,
8220 			NODE_SUBTYPE_LABEL,
8221 			NULL,
8222 			EXEC_DEFINITIONS,
8223 			{
8224 				node_exec_nothing,
8225 				(node_exec_func) node_def_label,
8226 				NULL,
8227 				NULL,
8228 				NULL
8229 			}
8230 		},
8231 		{		/*** object: LINE_STYLE ***/
8232 			NODE_TYPE_OBJECT,
8233 			NODE_SUBTYPE_LINE_STYLE,
8234 			NULL,
8235 			EXEC_DEFINITIONS,
8236 			{
8237 				node_exec_nothing,
8238 				(node_exec_func) node_def_line_style,
8239 				NULL,
8240 				NULL,
8241 				NULL
8242 			}
8243 		},
8244 		{		/*** object: LIST ***/
8245 			NODE_TYPE_OBJECT,
8246 			NODE_SUBTYPE_LIST,
8247 			NULL,
8248 			EXEC_DEFINITIONS,
8249 			{
8250 				node_exec_nothing,
8251 				(node_exec_func) node_def_list,
8252 				NULL,
8253 				NULL,
8254 				NULL
8255 			}
8256 		},
8257 		{		/*** object: MATRIX ***/
8258 			NODE_TYPE_OBJECT,
8259 			NODE_SUBTYPE_MATRIX,
8260 			NULL,
8261 			EXEC_DEFINITIONS,
8262 			{
8263 				node_exec_nothing,
8264 				(node_exec_func) node_def_matrix,
8265 				NULL,
8266 				NULL,
8267 				NULL
8268 			}
8269 		},
8270 		{		/*** object: METADATA ***/
8271 			NODE_TYPE_OBJECT,
8272 			NODE_SUBTYPE_METADATA,
8273 			NULL,
8274 			EXEC_DEFINITIONS,
8275 			{
8276 				node_exec_nothing,
8277 				(node_exec_func) node_def_metadata,
8278 				NULL,
8279 				NULL,
8280 				NULL
8281 			}
8282 		},
8283 		{		/*** object: ON EVENT ***/
8284 			NODE_TYPE_OBJECT,
8285 			NODE_SUBTYPE_ON_EVENT,
8286 			NULL,
8287 			EXEC_DEFINITIONS,
8288 			{
8289 				node_exec_nothing,
8290 				(node_exec_func) node_def_on_event,
8291 				NULL,
8292 				NULL,
8293 				NULL
8294 			}
8295 		},
8296 		{		/*** object: PLACE OBJECT ***/
8297 			NODE_TYPE_OBJECT,
8298 			NODE_SUBTYPE_PLACE_OBJECT,
8299 			NULL,
8300 			EXEC_DEFINITIONS,
8301 			{
8302 				node_exec_nothing,
8303 				(node_exec_func) node_def_place_object,
8304 				NULL,
8305 				NULL,
8306 				NULL
8307 			}
8308 		},
8309 		{		/*** object: POINTS ***/
8310 			NODE_TYPE_OBJECT,
8311 			NODE_SUBTYPE_POINTS,
8312 			NULL,
8313 			EXEC_DEFINITIONS,
8314 			{
8315 				node_exec_nothing,
8316 				(node_exec_func) node_def_points,
8317 				NULL,
8318 				NULL,
8319 				NULL
8320 			}
8321 		},
8322 		{		/*** object: RECT ***/
8323 			NODE_TYPE_OBJECT,
8324 			NODE_SUBTYPE_RECT,
8325 			NULL,
8326 			EXEC_DEFINITIONS,
8327 			{
8328 				node_exec_nothing,
8329 				(node_exec_func) node_def_rect,
8330 				NULL,
8331 				NULL,
8332 				NULL
8333 			}
8334 		},
8335 		{		/*** object: REMOVE ***/
8336 			NODE_TYPE_OBJECT,
8337 			NODE_SUBTYPE_REMOVE,
8338 			NULL,
8339 			EXEC_DEFINITIONS,
8340 			{
8341 				node_exec_nothing,
8342 				(node_exec_func) node_def_remove,
8343 				NULL,
8344 				NULL,
8345 				NULL
8346 			}
8347 		},
8348 		{		/*** object: REPLACE OBJECT ***/
8349 			NODE_TYPE_OBJECT,
8350 			NODE_SUBTYPE_REPLACE_OBJECT,
8351 			NULL,
8352 			EXEC_DEFINITIONS,
8353 			{
8354 				node_exec_nothing,
8355 				(node_exec_func) node_def_place_object,
8356 				NULL,
8357 				NULL,
8358 				NULL
8359 			}
8360 		},
8361 		{		/*** object: SCRIPT LIMITS ***/
8362 			NODE_TYPE_OBJECT,
8363 			NODE_SUBTYPE_SCRIPT_LIMITS,
8364 			NULL,
8365 			EXEC_DEFINITIONS,
8366 			{
8367 				node_exec_nothing,
8368 				(node_exec_func) node_def_script_limits,
8369 				NULL,
8370 				NULL,
8371 				NULL
8372 			}
8373 		},
8374 		{		/*** object: SEQUENCE ***/
8375 			NODE_TYPE_OBJECT,
8376 			NODE_SUBTYPE_SEQUENCE,
8377 			NULL,
8378 			EXEC_DEFINITIONS,
8379 			{
8380 				node_exec_nothing,
8381 				(node_exec_func) node_def_sequence,
8382 				NULL,
8383 				NULL,
8384 				NULL
8385 			}
8386 		},
8387 		{		/*** object: SET BACKGROUND COLOR ***/
8388 			NODE_TYPE_OBJECT,
8389 			NODE_SUBTYPE_SET_BACKGROUND_COLOR,
8390 			NULL,
8391 			EXEC_DEFINITIONS,
8392 			{
8393 				node_exec_nothing,
8394 				(node_exec_func) node_def_set_background_color,
8395 				NULL,
8396 				NULL,
8397 				NULL
8398 			}
8399 		},
8400 		{		/*** object: SET TAB INDEX ***/
8401 			NODE_TYPE_OBJECT,
8402 			NODE_SUBTYPE_SET_TAB_INDEX,
8403 			NULL,
8404 			EXEC_DEFINITIONS,
8405 			{
8406 				node_exec_nothing,
8407 				(node_exec_func) node_def_set_tab_index,
8408 				NULL,
8409 				NULL,
8410 				NULL
8411 			}
8412 		},
8413 		{		/*** object: SHAPE ***/
8414 			NODE_TYPE_OBJECT,
8415 			NODE_SUBTYPE_SHAPE,
8416 			NULL,
8417 			EXEC_DEFINITIONS,
8418 			{
8419 				node_exec_nothing,
8420 				(node_exec_func) node_def_shape,
8421 				NULL,
8422 				NULL,
8423 				NULL
8424 			}
8425 		},
8426 		{		/*** object: SHOW FRAME ***/
8427 			NODE_TYPE_OBJECT,
8428 			NODE_SUBTYPE_SHOW_FRAME,
8429 			NULL,
8430 			EXEC_DEFINITIONS,
8431 			{
8432 				node_exec_nothing,
8433 				(node_exec_func) node_def_show_frame,
8434 				NULL,
8435 				NULL,
8436 				NULL
8437 			}
8438 		},
8439 		{		/*** object: SOUND ***/
8440 			NODE_TYPE_OBJECT,
8441 			NODE_SUBTYPE_SOUND,
8442 			NULL,
8443 			EXEC_DEFINITIONS,
8444 			{
8445 				node_exec_nothing,
8446 				(node_exec_func) node_def_sound,
8447 				NULL,
8448 				NULL,
8449 				NULL
8450 			}
8451 		},
8452 		{		/*** object: SOUND INFO ***/
8453 			NODE_TYPE_OBJECT,
8454 			NODE_SUBTYPE_SOUND_INFO,
8455 			NULL,
8456 			EXEC_DEFINITIONS,
8457 			{
8458 				node_exec_nothing,
8459 				(node_exec_func) node_def_sound_info,
8460 				NULL,
8461 				NULL,
8462 				NULL
8463 			}
8464 		},
8465 		{		/*** object: SPRITE ***/
8466 			NODE_TYPE_OBJECT,
8467 			NODE_SUBTYPE_SPRITE,
8468 			NULL,
8469 			EXEC_DEFINITIONS,
8470 			{
8471 				node_exec_nothing,
8472 				(node_exec_func) node_def_sprite,
8473 				NULL,
8474 				NULL,
8475 				NULL
8476 			}
8477 		},
8478 		{		/*** object: STATE ***/
8479 			NODE_TYPE_OBJECT,
8480 			NODE_SUBTYPE_STATE,
8481 			NULL,
8482 			EXEC_DEFINITIONS,
8483 			{
8484 				node_exec_nothing,
8485 				(node_exec_func) node_def_state,
8486 				NULL,
8487 				NULL,
8488 				NULL
8489 			}
8490 		},
8491 		{		/*** object: TEXT ***/
8492 			NODE_TYPE_OBJECT,
8493 			NODE_SUBTYPE_TEXT,
8494 			NULL,
8495 			EXEC_DEFINITIONS,
8496 			{
8497 				node_exec_nothing,
8498 				(node_exec_func) node_def_text,
8499 				NULL,
8500 				NULL,
8501 				NULL
8502 			}
8503 		},
8504 		{		/*** object: TRY ***/
8505 			NODE_TYPE_OBJECT,
8506 			NODE_SUBTYPE_TRY,
8507 			NULL,
8508 			EXEC_DEFINITIONS,
8509 			{
8510 				node_exec_nothing,
8511 				(node_exec_func) node_def_function,
8512 				NULL,
8513 				NULL,
8514 				NULL
8515 			}
8516 		},
8517 		{		/*** object: TEXT SETUP ***/
8518 			NODE_TYPE_OBJECT,
8519 			NODE_SUBTYPE_TEXT_SETUP,
8520 			NULL,
8521 			EXEC_DEFINITIONS,
8522 			{
8523 				node_exec_nothing,
8524 				(node_exec_func) node_def_text_setup,
8525 				NULL,
8526 				NULL,
8527 				NULL
8528 			}
8529 		},
8530 #if 0
8531 		{		/*** object: VARIABLE -- just skip those! ***/
8532 			NODE_TYPE_OBJECT,
8533 			NODE_SUBTYPE_VARIABLE,
8534 			NULL,
8535 			0,
8536 			{
8537 				node_exec_nothing,
8538 				NULL,
8539 				NULL,
8540 				NULL,
8541 				NULL
8542 			}
8543 		},
8544 #endif
8545 		{		/*** object: WITH ***/
8546 			NODE_TYPE_OBJECT,
8547 			NODE_SUBTYPE_WITH,
8548 			NULL,
8549 			EXEC_DEFINITIONS,
8550 			{
8551 				node_exec_nothing,
8552 				(node_exec_func) node_def_with,
8553 				NULL,
8554 				NULL,
8555 				NULL
8556 			}
8557 		},
8558 		{		/*** object or variable reference ***/
8559 			NODE_TYPE_IDENTIFIER,
8560 			NODE_SUBTYPE_UNKNOWN,
8561 			NULL,
8562 			0,
8563 			{
8564 				node_exec_reference,
8565 				NULL,
8566 				NULL,
8567 				NULL,
8568 				NULL
8569 			}
8570 		},
8571 		{		/*** immediate value ***/
8572 			NODE_TYPE_INTEGER,
8573 			NODE_SUBTYPE_UNKNOWN,
8574 			NULL,
8575 			EXEC_INTEGER,
8576 			{
8577 				NULL,
8578 				NULL,
8579 				NULL,
8580 				NULL,
8581 				NULL
8582 			}
8583 		},
8584 		{		/*** immediate value ***/
8585 			NODE_TYPE_FLOAT,
8586 			NODE_SUBTYPE_UNKNOWN,
8587 			NULL,
8588 			EXEC_FLOAT,
8589 			{
8590 				NULL,
8591 				NULL,
8592 				NULL,
8593 				NULL,
8594 				NULL
8595 			}
8596 		},
8597 		{		/*** immediate string ***/
8598 			NODE_TYPE_STRING,
8599 			NODE_SUBTYPE_UNKNOWN,
8600 			NULL,
8601 			EXEC_STRING,
8602 			{
8603 				NULL,
8604 				NULL,
8605 				NULL,
8606 				NULL,
8607 				NULL
8608 			}
8609 		},
8610 
8611 
8612 
8613 
8614 		/* end of table */
8615 		{
8616 			NODE_TYPE_UNKNOWN,
8617 			NODE_SUBTYPE_UNKNOWN,
8618 			NULL,
8619 			0,
8620 			{
8621 				NULL,
8622 				NULL,
8623 				NULL,
8624 				NULL,
8625 				NULL
8626 			}
8627 		}
8628 	};
8629 	const struct node_exec_types	*t;
8630 	const struct definition_t	*def;
8631 	struct node_t			l, r;
8632 	int				ec, idx;
8633 
8634 	/* ensure the node is clean-able */
8635 	/* things changed and we don't actually want this here anymore
8636 	node_init(result, NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN);
8637 	*/
8638 
8639 	idx = 0;
8640 	t = all_types;
8641 	while(t->type != NODE_TYPE_UNKNOWN) {
8642 		if(t->type == expr->type && t->sub_type == expr->sub_type) {
8643 			if(t->name != NULL) {
8644 				/*
8645 				 * In this case we know that expr is an object
8646 				 * and expect the name on the left node
8647 				 */
8648 				assert(expr->left != NULL, "this object is expected to have a name");
8649 				if(strcmp_action(expr->left->string, t->name) != 0) {
8650 					/* not yet a valid entry */
8651 					goto skip;
8652 				}
8653 			}
8654 			/* we found a match, execute the operation */
8655 			if((t->flags & EXEC_STRING) != 0) {
8656 				/* NOTE: the sswf_strdup() can duplicate NULL pointers! */
8657 				result->type = NODE_TYPE_STRING;
8658 				result->string = sswf_strdup(expr->string);
8659 			}
8660 			else if((t->flags & EXEC_INTEGER) != 0) {
8661 				result->type = NODE_TYPE_INTEGER;
8662 				result->integer = expr->integer;
8663 			}
8664 			else if((t->flags & EXEC_FLOAT) != 0) {
8665 				result->type = NODE_TYPE_FLOAT;
8666 				result->floating_point = expr->floating_point;
8667 			}
8668 			else {
8669 				l.type = NODE_TYPE_INTEGER;	/* by default, just in case */
8670 
8671 				/* select, left or right */
8672 				if((t->flags & EXEC_SELECT) != 0) {
8673 					assert((t->flags & (EXEC_LEFT | EXEC_BOOLEAN_LEFT)) == 0, "EXEC_SELECT and EXEC_LEFT or EXEC_BOOLEAN_LEFT are incompatible");
8674 					node_init(&l, NODE_TYPE_UNKNOWN, NODE_TYPE_UNKNOWN);
8675 					ec = node_eval(expr->select, &l, status);
8676 					if(ec != 0) {
8677 						return ec;
8678 					}
8679 					node_boolean(&l, &l);
8680 				}
8681 				else if((t->flags & (EXEC_LEFT | EXEC_BOOLEAN_LEFT)) != 0) {
8682 					node_init(&l, NODE_TYPE_UNKNOWN, NODE_TYPE_UNKNOWN);
8683 					ec = node_eval(expr->left, &l, status);
8684 					if(ec != 0) {
8685 						return ec;
8686 					}
8687 					if((t->flags & EXEC_BOOLEAN_LEFT) != 0) {
8688 						node_boolean(&l, &l);
8689 					}
8690 				}
8691 				if((t->flags & (EXEC_RIGHT | EXEC_BOOLEAN_RIGHT)) != 0) {
8692 					node_init(&r, NODE_TYPE_UNKNOWN, NODE_TYPE_UNKNOWN);
8693 					ec = node_eval(expr->right, &r, status);
8694 					if(ec != 0) {
8695 						if((t->flags & (EXEC_LEFT | EXEC_BOOLEAN_LEFT | EXEC_SELECT)) != 0) {
8696 							node_clean(&l, 0);
8697 						}
8698 						return ec;
8699 					}
8700 					if((t->flags & EXEC_BOOLEAN_RIGHT) != 0) {
8701 						node_boolean(&r, &r);
8702 					}
8703 					if((t->flags & (EXEC_LEFT | EXEC_BOOLEAN_LEFT)) == 0) {
8704 						l.type = r.type;
8705 					}
8706 				}
8707 				else {
8708 					r.type = l.type;
8709 				}
8710 
8711 				/*
8712 				 * For objects, "all" of them have definitions, we have
8713 				 * a special way to parse these; we assume that EXEC_LEFT,
8714 				 * EXEC_RIGHT and the corresponding boolean flags are all
8715 				 * zero.
8716 				 */
8717 				if((t->flags & EXEC_DEFINITIONS) != 0) {
8718 					assert((t->flags & (EXEC_LR | EXEC_BOOLEAN_LR)) == 0, "flags cannot include both EXEC_[SUB_]DEFINITIONS & one or more of EXEC_LEFT, RIGHT, BOOLEAN_LEFT, BOOLEAN_RIGHT");
8719 					def = (const struct definition_t *) t->func[1];
8720 					ec = node_definitions(expr, def, &r, status);
8721 					if(ec != 0) {
8722 						goto err;
8723 					}
8724 					/* if there is something more to do, use the default function */
8725 					idx = NODE_EXEC_FUNC_INTEGERS;
8726 				}
8727 				/* when we are ready to execute a function we need to know which one to call */
8728 				else switch(qs(l.type, r.type)) {
8729 				case qs(NODE_TYPE_INTEGER, NODE_TYPE_INTEGER):
8730 					idx = NODE_EXEC_FUNC_INTEGERS;
8731 					result->type = NODE_TYPE_INTEGER;
8732 					break;
8733 
8734 				case qs(NODE_TYPE_INTEGER, NODE_TYPE_FLOAT):
8735 					/* change left handside into a floating point */
8736 					l.floating_point = (double) l.integer;
8737 					l.type = NODE_TYPE_FLOAT;
8738 					idx = NODE_EXEC_FUNC_FLOATS;
8739 					result->type = NODE_TYPE_FLOAT;
8740 					break;
8741 
8742 				case qs(NODE_TYPE_FLOAT, NODE_TYPE_INTEGER):
8743 					/* change right handside into a floating point */
8744 					r.floating_point = (double) r.integer;
8745 					r.type = NODE_TYPE_FLOAT;
8746 					idx = NODE_EXEC_FUNC_FLOATS;
8747 					result->type = NODE_TYPE_FLOAT;
8748 					break;
8749 
8750 				case qs(NODE_TYPE_FLOAT, NODE_TYPE_FLOAT):
8751 					idx = NODE_EXEC_FUNC_FLOATS;
8752 					result->type = NODE_TYPE_FLOAT;
8753 					break;
8754 
8755 				case qs(NODE_TYPE_STRING, NODE_TYPE_INTEGER):
8756 					idx = NODE_EXEC_FUNC_STRINT;
8757 					result->type = NODE_TYPE_STRING;
8758 					break;
8759 
8760 				case qs(NODE_TYPE_STRING, NODE_TYPE_FLOAT):
8761 					idx = NODE_EXEC_FUNC_STRFLT;
8762 					result->type = NODE_TYPE_STRING;
8763 					break;
8764 
8765 				case qs(NODE_TYPE_STRING, NODE_TYPE_STRING):
8766 					idx = NODE_EXEC_FUNC_STRINGS;
8767 					result->type = NODE_TYPE_STRING;
8768 					break;
8769 
8770 				default:
8771 					if((t->flags & EXEC_LR) != 0) {
8772 						fprintf(stderr, "ERROR: expression types mismatch!\n");
8773 						ec = -1;
8774 						goto err;
8775 					}
8776 					/* a default function is in this entry */
8777 					idx = NODE_EXEC_FUNC_INTEGERS;
8778 					result->type = expr->type;
8779 					break;
8780 
8781 				}
8782 				if(t->func[idx] == NULL) {
8783 					if(t->func[NODE_EXEC_FUNC_INTEGERS] == NULL
8784 					|| idx == NODE_EXEC_FUNC_STRINT) {
8785 						fprintf(stderr, "ERROR: at line #%ld in filename \"%s\": sswf doesn't know how to handle this expression.\n",
8786 								expr->line, expr->filename);
8787 						errcnt++;
8788 						/* we can't continue */
8789 						ec = -1;
8790 						goto err;
8791 					}
8792 					idx = NODE_EXEC_FUNC_INTEGERS;
8793 				}
8794 				ec = (*t->func[idx])(expr, &l, &r, result, status);
8795 err:
8796 				if((t->flags & (EXEC_LEFT | EXEC_BOOLEAN_LEFT | EXEC_SELECT)) != 0) {
8797 					node_clean(&l, 0);
8798 				}
8799 				if((t->flags & (EXEC_RIGHT | EXEC_BOOLEAN_RIGHT | EXEC_DEFINITIONS)) != 0) {
8800 					node_clean(&r, 0);
8801 				}
8802 				if(ec != 0) {
8803 					/* now the result is never cleaner here
8804 					 * the caller is responsible!
8805 					node_clean(result, 0);
8806 					 */
8807 					return ec;
8808 				}
8809 			}
8810 			return 0;
8811 		}
8812 skip:
8813 		t++;
8814 	}
8815 
8816 #if DEBUG
8817 	printf("ERROR: at line #%ld in file \"%s\": can't execute expression. (%d, %d, %s)\n",
8818 							expr->line, expr->filename,
8819 							expr->type, expr->sub_type,
8820 							expr->left == 0 ? "<no name>" : expr->left->string);
8821 	abort();
8822 #endif
8823 
8824 	return 1;
8825 }
8826 
8827 
node_eval(struct node_t * expr,struct node_t * result,struct node_exec_status_t * status)8828 int node_eval(struct node_t *expr, struct node_t *result, struct node_exec_status_t *status)
8829 {
8830 	int		ec;
8831 
8832 	if(expr == NULL) {	/* this happens in the IF statement without an ELSE */
8833 		/* should we change the result types?!?
8834 		node_init(result, NODE_TYPE_UNKNOWN, NODE_SUBTYPE_UNKNOWN);
8835 		*/
8836 		return 0;
8837 	}
8838 
8839 	/* evaluate one group of expressions and return the result of the last */
8840 	ec = node_execute(expr, result, status);
8841 
8842 	expr = expr->next;
8843 	while(expr != NULL && ec == 0) {
8844 		node_clean(result, 0);
8845 		node_init(result, NODE_TYPE_UNKNOWN, NODE_TYPE_UNKNOWN);
8846 		ec = node_execute(expr, result, status);
8847 		expr = expr->next;
8848 	}
8849 
8850 	return ec;
8851 }
8852 
8853 
8854