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(¶ms, 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(¶ms, 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(¶ms, e);
2157 e->parent = ¶ms;
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(¶ms, 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(¶ms, 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, ¶ms, 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(¶ms, 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