1 // Copyright (C) 1995-1999 David Sugar, Tycho Softworks.
2 // Copyright (C) 1999-2005 Open Source Telecom Corp.
3 // Copyright (C) 2005-2014 David Sugar, Tycho Softworks.
4 // Copyright (C) 2015 Cherokees of Idaho.
5 //
6 // This file is part of GNU ccScript.
7 //
8 // GNU ccScript is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // GNU ccScript is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with GNU ccScript. If not, see <http://www.gnu.org/licenses/>.
20
21 #include <ccscript-config.h>
22 #include <ucommon/ucommon.h>
23 #include <ucommon/export.h>
25 #include <ctype.h>
26
27 #ifdef HAVE_REGEX_H
28 #include <regex.h>
29 #endif
30
31 #define NUM_FORMAT "%ld"
32
33 namespace ucommon {
34
37 {
38 }
39
41 {
42 detach();
43 }
44
46 {
47 unsigned tempcount = sizeof(temps) / sizeof(char *);
48 unsigned pos = 0;;
49
50 frame = 0;
51 tempindex = 0;
52
53 purge();
54
55 image = NULL;
59 while(pos < tempcount)
61
62 errmsg = NULL;
64 if(err)
66 }
67
69 {
70 #ifndef _MSWINDOWS_
71 if(getppid() > 1)
72 fprintf(stderr,
"*** %s(%d): %s\n", image->filename, stack[frame].line->
lnum, msg);
73 #endif
74
75 if(errmsg)
76 String::set(errmsg, 65, msg);
77
78 if(!eq(stack[frame].scr->name, "_init_")) {
79 if(scriptEvent("error"))
80 return false;
81 }
82
83 skip();
84 return true;
85 }
86
88 {
89 unsigned tempcount = sizeof(temps) / sizeof(char *);
90
91 char *ptr = temps[tempindex++];
92 if(tempindex >= tempcount)
93 tempindex = 0;
94 return ptr;
95 }
96
98 {
99 #ifdef __MINGW32__
100 long long val;
101 #else
102 long val;
103 #endif
104
105 static char null[1] = {0};
106
107 size_t dcount = 0, pos;
108 char *cp;
109 char *ep;
110 char idbuf[32];
111 unsigned len;
112 char quote = 0;
114 unsigned paren = 0;
115
117 while(isspace(*cp))
118 ++cp;
119
120 if(eq(id, "len:", 4))
122 else if(eq(id, "key:", 4)) {
124 ep = strchr(tp, '=');
125 if(ep)
126 *ep = 0;
127 else
128 String::set(tp, 2, "-");
129 }
130 else if(eq(id, "tail:", 5)) {
132 if(dcount)
134 else
135 tp[0] = 0;
136 }
137 else if(eq(id, "head:", 5)) {
141 if(dcount)
142 tp[--dcount] = 0;
143 }
144 }
145 else if(eq(id, "pull:", 5) || eq(id, "<<:", 3)) {
149 if(dcount) {
150 memcpy(sym->
data, sym->
data + dcount, strlen(sym->
data + dcount) + 1);
151 tp[--dcount] = 0;
152 }
153 }
154 }
155 else if(eq(id, "pop:", 4) || eq(id, ">>:", 3)) {
157 if(dcount) {
159 if(dcount) {
161 sym->
data[--dcount] = 0;
162 }
163 else
165 }
166 else
167 tp[0] = 0;
168 }
169 else if(eq(id, "val:", 4) && (*cp == '\'' || *cp == '\"' || *cp == '(')) {
171 if(*cp == '(')
172 ep = strrchr(tp, ')');
173 else
174 ep = strchr(tp, *cp);
175 if(ep)
176 *ep = 0;
177 }
178 else if(eq(
id,
"val:", 4) && strchr(sym->
data,
'=')) {
179 cp = strchr(sym->
data,
'=') + 1;
180 if(*cp == '\"' || *cp == '\'') {
182 ep = strchr(tp, *cp);
183 if(ep)
184 *ep = 0;
185 }
186 else {
188 ep = strchr(tp, ',');
189 if(ep)
190 *ep = 0;
191 }
192 }
193 else if(eq(
id,
"unquote:", 8) && sym->
size) {
195 while(isspace(*cp))
196 ++cp;
197 if(*cp == '(') {
198 ++cp;
199 ep = strrchr(cp, ')');
200 if(ep)
201 *ep = 0;
202 }
203 else if(*cp == '\"' || *cp == '\'') {
204 ep = strchr(cp + 1, *cp);
205 if(ep)
206 *ep = 0;
207 ++cp;
208 }
209 String::set(sym->
data, sym->
size + 1, cp);
211 }
212 else if(eq(
id,
"upper:", 6) && sym->
size) {
213 String::upper(sym->
data);
215 }
216 else if(eq(
id,
"lower:", 6) && sym->
size) {
217 String::lower(sym->
data);
219 }
220 else if((eq(
id,
"inc:", 4) || eq(
id,
"++:", 3)) && sym->
size) {
221 val = atol(cp);
224 }
225 else if(eq(id, "count:", 6))
227 else if(eq(id, "index/", 6)) {
228 id += 6;
229 pos = atoi(id);
230 if(pos)
231 --pos;
232 else
233 return "";
234 if(pos < strlen(sym->
data))
235 cp = sym->
data + pos;
236 else
237 cp = null;
239 }
240 else if(eq(id, "offset/", 7)) {
241 id += 7;
242 pos = atoi(id);
243 if(pos)
244 --pos;
245 else
246 return "";
250 }
251 else if((eq(
id,
"dec:", 4) || eq(
id,
"--:", 3)) && sym->
size) {
252 val = atoi(cp);
255 }
256 else if(eq(id, "size:", 5))
258 else if(eq(id, "val:", 4) || eq(id, "int:", 4)) {
259 val = atol(cp);
261 }
262 else if(eq(id, "num:", 4)) {
263 val = atol(cp);
267 pos = strlen(tp);
268 cp = strchr(sym->
data,
'.');
269 if(cp)
270 ++cp;
271 else
272 cp = null;
274 if(*cp && isdigit(*cp))
275 tp[pos++] = *(cp++);
276 else
277 tp[pos++] = '0';
278 }
279 tp[pos] = 0;
280 }
281 else if(eq(id, "map/", 4)) {
282 idbuf[0] = '%';
283 String::set(idbuf, sizeof(idbuf), id + 4);
284 ep = strchr(idbuf, ':');
285 if(ep)
286 *ep = 0;
288 if(!index || !index->
data[0])
289 return "";
290 pos = atoi(sym->
data);
291 if(pos)
293 snprintf(idbuf,
sizeof(idbuf),
",%s", sym->
data);
294 paren = 0;
295 goto search;
296 }
297 else if(eq(id, "find/", 5)) {
298 id += 5;
299 paren = 0;
300 dcount = 1;
301 idbuf[0] = ',';
302 while(dcount < 30 && *id && *id != ':')
303 idbuf[dcount++] = *(id++);
304 idbuf[dcount++] = '=';
305 idbuf[dcount] = 0;
306 search:
308 len = strlen(idbuf);
309 if(!strncmp(cp, idbuf + 1, len - 1))
310 cp = sym->
data + len - 1;
311 else if(NULL != (cp = strstr(sym->
data, idbuf)))
312 cp = cp + len;
313 else
314 cp = null;
315 dcount = 0;
316 if(*cp == '\"') {
317 quote = *cp;
318 ++cp;
319 }
320 else if(*cp == '(') {
321 paren = 1;
322 ++cp;
323 }
324 else
325 quote=',';
327 if(*cp == '(' && paren)
328 ++paren;
329 if(*cp == ')' && paren) {
330 if(paren-- == 1)
331 break;
332 }
333 if(*cp == '=' && quote == ',' && cp[1] == '\"') {
334 tp[dcount++] = *(cp++);
335 quote = *(cp++);
336 }
337 else
338 tp[dcount++] = *(cp++);
339 }
340 tp[dcount] = 0;
341 }
342 else if(eq(id, "bool:", 5)) {
343 if(atoi(sym->
data) > 0 || tolower(sym->
data[0]) ==
't' || tolower(sym->
data[0] ==
'y'))
345 else
347 }
348 return tp;
349 }
350
352 {
354 const char *id;
355 char *tp;
356
357 if(!cp)
358 return NULL;
359
360 switch(*cp) {
361 case '$':
362 tp = getTemp();
363 id = strchr(cp, ':');
364 if(id) {
366 if(!sym)
367 return "";
368 *tp = 0;
369 return getFormat(sym, ++cp, tp);
370 }
371 case '%':
372 if(eq(cp, "%index"))
373 return getIndex();
375 if(sym)
377 else
378 return "";
379 case '&':
380 case '=':
381 case '+':
382 if(cp[1] && cp[1] != '=')
383 return ++cp;
384 }
385 return cp;
386 }
387
389 {
391 unsigned index = 0;
392 const char *cp;
393
394 while(index < line->argc) {
395 cp = line->
argv[index++];
396 if(*cp == '=') {
397 if(eq(id, ++cp))
398 return getContent(line->
argv[index]);
399 ++index;
400 }
401 }
402 return NULL;
403 }
404
406 {
408
409 unsigned pos = frame;
410 while(pos) {
411 method = stack[--pos].line->
method;
413 char *temp = getTemp();
415 return temp;
416 }
417 }
418 return "0";
419 }
420
422 {
423 if(!frame)
425
426 return stack[frame - 1].line->
method;
427 }
428
430 {
431 const char *cp;
433 while(stack[frame].index < line->argc) {
434 cp = line->
argv[stack[frame].index++];
435 switch(*cp) {
436 case '=':
437 ++stack[frame].index;
438 break;
439 default:
440 return cp;
441 }
442 }
443 return NULL;
444 }
445
447 {
448 const char *cp;
450 while(stack[frame].index < line->argc) {
451 cp = line->
argv[stack[frame].index++];
452 switch(*cp) {
453 case '=':
454 ++stack[frame].index;
455 break;
456 default:
457 return getContent(cp);
458 }
459 }
460 return NULL;
461 }
462
464 {
465 unsigned path;
466 linked_pointer<Script::symbol> sp;
468
469 if(*id == '=' || *id == '%')
470 ++id;
471
472 if(!isalnum(*id))
473 return false;
474
476 sp = syms[path];
477
478 while(is(sp)) {
479 if(eq(sp->name, id) && sp->scope == stack[frame].scope)
480 return false;
481 sp.next();
482 }
483
485
487 var->
scope = stack[frame].scope;
489 var->
data = dup(value);
490 var->enlist(&syms[path]);
491 return true;
492 }
493
495 {
496 unsigned path;
497 linked_pointer<Script::symbol> sp;
500 char *cp;
501
502 if(*id == '=' || *id == '%')
503 ++id;
504
505 if(!isalnum(*id))
506 return NULL;
507
508 if(strchr(id, ':')) {
509 char *temp = getTemp();
510
512 cp = strchr(temp, ':');
513 if(cp) {
514 *(cp++) = 0;
515 id = temp;
516 size = atoi(cp);
517 }
518 }
519
521 sp = syms[path];
522
523 if(!size)
525
526 while(is(sp)) {
527 if(eq(sp->name, id) && sp->scope == NULL)
528 var = *sp;
529 if(eq(sp->name, id) && sp->scope == stack[frame].scope)
530 local = *sp;
531 sp.next();
532 }
533
534 if(local)
535 var = local;
536
537 if(!var) {
539
541
544 var->
data = (
char *)alloc(size + 1);
545 var->enlist(&syms[path]);
547 }
548 return var;
549 }
550
552 {
553 if(!type_id)
554 return 0;
555
556 if(eq(type_id, "int"))
557 return 10;
558
559 if(eq(type_id, "num"))
560 return 20;
561
562 if(eq(type_id, "bool"))
563 return 1;
564
565 return 0;
566 }
567
569 {
570 if(!type_id)
571 return NULL;
572
573 if(eq(type_id, "int") || eq(type_id, "num"))
574 return "0";
575
576 if(eq(type_id, "bool"))
577 return "f";
578
579 return NULL;
580 }
581
583 {
584 unsigned index = 0;
585 const char *cp;
586 const char *id;
587 unsigned param = 0;
588 char pbuf[8];
590
591 while(index < line->argc) {
592 cp = line->
argv[index++];
593 if(*cp == '=') {
594 id = ++cp;
595 cp = line->
argv[index++];
596 }
597 else {
598 snprintf(pbuf, sizeof(pbuf), "%d", ++param);
599 id = pbuf;
600 }
601 if(eq(cp, "required") || eq(cp, "optional"))
602 setRef(scope, id, const_cast<char *>(""), 0);
603 else if(*cp == '%') {
605 if(sym) {
606 setRef(scope,
id, sym->
data, sym->
size);
607 continue;
608 }
609 else
610 setRef(scope, id, const_cast<char *>(""), 0);
611
612 }
613 else {
614 cp = getContent(cp);
615 setRef(scope, id, const_cast<char *>(cp), 0);
616 }
617 }
618 }
619
621 {
622 unsigned path;
623 linked_pointer<Script::symbol> sp;
625
626 if(*id == '=' || *id == '%')
627 ++id;
628
629 if(!isalnum(*id))
630 return;
631
633 sp = syms[path];
634
635 while(is(sp)) {
636 if(eq(sp->name, id) && sp->scope == scope) {
637 var = *sp;
638 break;
639 }
640 sp.next();
641 }
642
643 if(!var) {
645
647
649 var->enlist(&syms[path]);
650 }
651
654 }
655
657 {
658 unsigned path;
659 linked_pointer<Script::symbol> sp;
662 char *cp;
663
664 if(*id == '=' || *id == '%')
665 ++id;
666
667 if(!isalnum(*id))
668 return NULL;
669
670 if(strchr(id, ':')) {
671 char *temp = getTemp();
672
674 cp = strchr(temp, ':');
675 if(cp) {
676 *(cp++) = 0;
677 id = temp;
678 size = getTypesize(cp);
679 if(!value)
680 value = getTypeinit(cp);
681 if(!size)
682 size = atoi(cp);
683 }
684 }
685
687 sp = syms[path];
688
689 if(!size)
691
692 while(is(sp)) {
693 if(eq(sp->name, id) && sp->scope == stack[frame].scope) {
694 var = *sp;
695 break;
696 }
697 sp.next();
698 }
699
700 if(!var) {
702
704
705 var->
scope = stack[frame].scope;
707 var->
data = (
char *)alloc(size + 1);
708 var->enlist(&syms[path]);
710 }
711
712 // if const, we do not re-write...
714 return var;
715
716 // assign value, whether new or exists to reset...
717 if(value && *value)
718 String::set(var->
data, var->
size + 1, value);
719 else if(value)
721 return var;
722 }
723
725 {
727 linked_pointer<Script::symbol> sp = syms[path];
729
730 while(is(sp)) {
731 if(eq(sp->name, id)) {
732 if(sp->scope == NULL)
733 global = *sp;
734 else if(sp->scope == stack[frame].scope)
735 local = *sp;
736 }
737 sp.next();
738 }
739
740 if(local)
741 return local;
742
743 return global;
744 }
745
747 {
748 image = NULL;
749 }
750
752 {
753 return stack[stack[frame].base].scr->file;
754 }
755
757 {
758 linked_pointer<Script::event> ep = scr->
events;
759
760 while(is(ep)) {
761 if(eq(ep->name, "init")) {
763 stack[frame].event = *ep;
764 stack[frame].line = ep->first;
765 return;
766 }
768 }
769 }
770
772 {
774 image = img;
775
776 if(!img)
777 return false;
778
779 if(entry && *entry == '@')
781
782 if(!main)
784
785 if(main) {
786 setStack(main);
788 setStack(img->
first);
789
790 while(frame && stack[frame].
line)
791 (this->*(stack[frame].line->
method))();
792
793 if(is(img->shared)) {
794 frame = 1;
795 setStack(img->shared->first);
796 while(frame && stack[frame].line)
797 (this->*(stack[frame].line->
method))();
798 }
799
800 frame = 0;
801 startScript(main);
802 return true;
803 }
804 image = NULL;
805 return false;
806 }
807
809 {
810 stack[frame].line = stack[frame].line->
next;
811 }
812
814 {
815 linked_pointer<Script::event> mp = stack[frame].scr->methods;
816
817 while(is(mp)) {
818 if(eq_case(mp->name, name))
819 return *mp;
821 }
822 return NULL;
823 }
824
826 {
827 assert(name != NULL);
828
829 linked_pointer<Script::event> ep;
831 const char *group = NULL;
832 unsigned stackp = frame;
834 unsigned pos = 0;
835
836 // strip out lead event if passed here...
837 if(*name == '^')
838 ++name;
839
840 // single character key is a key group event
841 if(!name[1])
842 group = "key";
843
844 // check if ignoring event...
845 while(ignore && pos < ignore->argc) {
846
847 // if entire group is ignored, drop all events of group
848 if(group && eq_case(group, ignore->
argv[pos]))
849 return false;
850
851 // if our event is ignored, then exit out
852 if(eq_case(name, ignore->
argv[pos++]))
853 return false;
854 }
855
856 for(;;) {
857 ep = stack[stackp].scr->events;
858 egrp = NULL;
859
860 while(is(ep)) {
861 if(eq_case(ep->name, name))
862 break;
863
864 if(group && eq_case(ep->name, group))
865 egrp = *ep;
866
867 ep.next();
868 }
869
870 if(!is(ep))
871 ep = egrp;
872
873 if(is(ep)) {
874
875 if(stack[stackp].
event == *ep)
876 return false;
877
878 frame = stackp;
879
880 pullScope();
881 setStack(stack[frame].scr, *ep);
882 return true;
883 }
884
885 // non-inherited test...
886 if(eq_case(name, "timeout"))
887 return false;
888
889 while(stackp > stack[stackp].base && stack[stackp].
line->
loop)
890 --stackp;
891
892 if(stackp && stackp >= stack[stackp].base)
893 --stackp;
894 else
895 return false;
896 }
897 }
898
900 {
901 stack[frame].scr = scr;
902 stack[frame].event = ev;
903 stack[frame].index = 0;
904 stack[frame].resmask = scr->
resmask;
905 stack[frame].ignore = NULL;
906
907 if(ev)
908 stack[frame].line = ev->
first;
909 else
910 stack[frame].line = scr->
first;
911 }
912
914 {
915 while(frame && stack[frame - 1].base == stack[frame].base)
916 --frame;
917 }
918
920 {
921 while(frame && stack[frame - 1].scr == stack[frame].scr)
922 --frame;
923 }
924
926 {
927 skip();
928 if(frame) {
929 stack[frame - 1].line = stack[frame].line;
930 stack[frame - 1].index = 0;
931 --frame;
932 }
933 }
934
936 {
937 if(!stack || !stack[frame].scr || (frame == 0 && !stack[frame].
line))
938 return 0;
939
940 if(stack[frame].line)
941 return stack[frame].line->
mask | stack[frame].resmask;
942
943 return stack[frame].resmask;
944 }
945
947 {
948 pullScope();
949 if(frame)
950 --frame;
951 else
952 return false;
953
954 return true;
955 }
956
958 {
960 if(!scriptEvent("stack")) {
961 frame = 0;
962 stack[frame].line = NULL;
963 return;
964 }
965 }
966
967 stack[frame + 1] = stack[frame];
968 ++frame;
969 }
970
972 {
973 if(*label != '@')
974 return false;
975
977 if(!scr || !scr->
first || stack[stack[frame].base].scr == scr)
978 return false;
979
980 frame = stack[frame].base;
981 setStack(scr, NULL);
982 return true;
983 }
984
986 {
988 return false;
989
990 if(scriptEvent("exit"))
991 return true;
992
994 frame = 0;
995
996 if(!ex || stack[frame].scr == ex)
997 return false;
998
999 setStack(ex, NULL);
1000 return true;
1001 }
1002
1004 {
1007 bool rtn = true;
1008
1009 while(line && rtn && scount--) {
1010 rtn = (this->*(line->
method))();
1011 line = stack[frame].line;
1012 }
1013
1014 if(line)
1015 return true;
1016
1017 while(stack[frame].line == NULL && frame)
1018 --frame;
1019
1020 if(!stack[frame].line && !tryexit())
1021 return false;
1022
1023 return true;
1024 }
1025
1027 {
1028 unsigned points = 0;
1030
1031 if(eq(test, "defined")) {
1032 if(!v)
1033 return false;
1034 if(*v == '%') {
1036 if(!sym)
1037 return false;
1038 return true;
1039 }
1040 v = getContent(v);
1041 if(!*v)
1042 return false;
1043 return true;
1044 }
1045
1046 if(eq(test, "const")) {
1047 if(!v)
1048 return false;
1049
1050 if(*v == '%') {
1052 if(!sym)
1053 return false;
1055 return false;
1056 return true;
1057 }
1058 else
1059 return false;
1060 }
1061
1062 if(eq(test, "modify")) {
1063 if(!v)
1064 return false;
1065
1066 if(*v == '%') {
1068 if(!sym)
1069 return false;
1071 return true;
1072 return false;
1073 }
1074 else
1075 return false;
1076 }
1077
1078 v = getContent(v);
1079 if(eq(test, "empty")) {
1080 if(v && *v)
1081 return false;
1082 return true;
1083 }
1084
1085 if(eq(test, "integer")) {
1086 if(!v || !*v)
1087 return false;
1088
1089 if(*v == '-')
1090 ++v;
1091
1092 while(*v) {
1093 if(!isdigit(*v))
1094 return false;
1095 ++v;
1096 }
1097 return true;
1098 }
1099
1100 if(eq(test, "digits")) {
1101 if(!v || !*v)
1102 return false;
1103
1104 while(*v) {
1105 if(!isdigit(*v))
1106 return false;
1107 ++v;
1108 }
1109 return true;
1110 }
1111
1112 if(eq(test, "number")) {
1113 if(!v || !*v)
1114 return false;
1115
1116 if(*v == '-')
1117 ++v;
1118
1119 while(*v) {
1120 if(*v == '.') {
1121 if(points)
1122 return false;
1123 ++points;
1124 ++v;
1125 continue;
1126 }
1127 if(!isdigit(*v))
1128 return false;
1129 ++v;
1130 }
1131
1132 return true;
1133 }
1134
1135 return false;
1136 }
1137
1139 {
1141 const char *cp;
1142 bool rtn = false;
1143
1144 while(index < line->argc) {
1145 rtn = getExpression(index);
1146 cp = line->
argv[index];
1147 if((*cp == '-' || *cp == '!') && isalpha(cp[1]))
1148 index += 2;
1149 else
1150 index += 3;
1151
1152 if(index >= line->
argc)
1153 return rtn;
1154
1155 cp = line->
argv[index++];
1156
1157 if(eq(cp, "?&&") || eq(cp, "and")) {
1158 if(!rtn)
1159 return false;
1160 rtn = false;
1161 continue;
1162 }
1163 if(eq(cp, "?||") || eq(cp, "or")) {
1164 if(rtn)
1165 return true;
1166 rtn = false;
1167 continue;
1168 }
1169 break;
1170 }
1171 return rtn;
1172 }
1173
1174 bool Script::interp::getExpression(unsigned index)
1175 {
1177 const char *v1 = "", *v2 = "", *op;
1178 const char *d1, *d2;
1179 unsigned len;
1180 char dec1[9], dec2[9];
1181 long dv1, dv2;
1182 unsigned pos = 0, pcount;
1183
1184 #ifdef __MINGW32__
1185 long long dv;
1186 #else
1187 long dv;
1188 #endif
1189
1190 if(index < line->argc) {
1191 v1 = line->
argv[index++];
1192 if((*v1 == '-' || *v1 == '!') && isalpha(v1[1])) {
1193 if(index < line->argc)
1194 v2 = line->
argv[index++];
1195 else
1196 v2 = NULL;
1197 if(*v1 == '-')
1198 return getCondition(++v1, v2);
1199 else
1200 return !getCondition(++v1, v2);
1201 }
1202 v1 = getContent(v1);
1203 }
1204 else
1205 return false;
1206
1207 if(index <= line->argc) {
1208 op = line->
argv[index++];
1209 if(*op == '?')
1210 ++op;
1211 }
1212 else if(v1 && *v1)
1213 return true;
1214 else
1215 return false;
1216
1217 if(index <= line->argc)
1218 v2 = getContent(line->
argv[index++]);
1219
1220 d1 = strchr(v1, '.');
1221 d2 = strchr(v2, '.');
1222 dec1[0] = 0;
1223 dec2[0] = 0;
1224 if(d1) {
1225 dv = atol(++d1);
1226 snprintf(dec1,
sizeof(dec1),
NUM_FORMAT, (
long)dv);
1227 }
1228 if(d2) {
1229 dv = atol(++d2);
1230 snprintf(dec2,
sizeof(dec2),
NUM_FORMAT, (
long)dv);
1231 }
1232
1233 unsigned c1 = strlen(dec1);
1234 unsigned c2 = strlen(dec2);
1235 while(c1 < 8)
1236 dec1[c1++] = '0';
1237
1238 while(c2 < 8)
1239 dec2[c2++] = '0';
1240
1241 dec1[8] = dec2[8] = 0;
1242 if(eq(op, "="))
1243 return ((atol(v1) == atol(v2)) && !strcmp(dec1, dec2));
1244
1245 if(eq(op, "<>"))
1246 return ((atol(v1) != atol(v2)) || strcmp(dec1, dec2));
1247
1248 if(eq(op, "&&"))
1249 return (*v1 && *v2);
1250
1251 if(eq(op, "||"))
1252 return (*v1 || *v2);
1253
1254 if(eq(op, "gt")) {
1255 if(strcmp(v1, v2) > 0)
1256 return true;
1257 return false;
1258 }
1259
1260 if(eq(op, "lt")) {
1261 if(strcmp(v1, v2) < 0)
1262 return true;
1263 return false;
1264 }
1265
1266 if(eq(op, "ge")) {
1267 if(strcmp(v1, v2) >= 0)
1268 return true;
1269 return false;
1270 }
1271
1272 if(eq(op, "le")) {
1273 if(strcmp(v1, v2) <= 0)
1274 return true;
1275 return false;
1276 }
1277
1278 if(eq(op, "==") || eq(op, "eq"))
1279 return eq(v1, v2);
1280
1281 if(eq(op, "!=") || eq(op, "ne"))
1282 return !eq(v1, v2);
1283
1284 if(eq(op, "<")) {
1285 dv1 = atol(dec1);
1286 dv2 = atol(dec2);
1287 if(*v1 == '-') {
1288 dv1 = -dv1;
1289 dv2 = -dv2;
1290 }
1291 return (atol(v1) < atol(v2) || (atol(v1) == atol(v2) && dv1 < dv2));
1292 }
1293
1294 if(eq(op, "<=")) {
1295 dv1 = atol(dec1);
1296 dv2 = atol(dec2);
1297 if(*v1 == '-') {
1298 dv1 = -dv1;
1299 dv2 = -dv2;
1300 }
1301 return (atoi(v1) < atoi(v2) || (atol(v1) == atol(v2) && dv1 <= dv2));
1302 }
1303
1304 if(eq(op, ">")) {
1305 dv1 = atol(dec1);
1306 dv2 = atol(dec2);
1307 if(*v1 == '-') {
1308 dv1 = -dv1;
1309 dv2 = -dv2;
1310 }
1311 return (atol(v1) > atol(v2) || (atol(v1) == atol(v2) && dv1 > dv2));
1312 }
1313
1314 if(eq(op, ">=")) {
1315 dv1 = atol(dec1);
1316 dv2 = atol(dec2);
1317 if(*v1 == '-') {
1318 dv1 = -dv1;
1319 dv2 = -dv2;
1320 }
1321 return (atol(v1) > atol(v2) || (atol(v1) == atol(v2) && dv1 >= dv2));
1322 }
1323
1324 if(eq(op, "?") || eq(op, "in")) {
1326 if(!pcount)
1327 return false;
1328
1329 len = strlen(v1);
1330 while(pos < pcount) {
1332 if(op && eq(v1, op, len) && (op[len] == ',' || op[len] == 0 || op[len] == '='))
1333 return true;
1334 }
1335 return false;
1336 }
1337
1338 if(eq(op, "!?") || eq(op, "notin")) {
1340 if(!pcount)
1341 return true;
1342
1343 len = strlen(v1);
1344 while(pos < pcount) {
1346 if(op && eq(v1, op, len) && (op[len] == ',' || op[len] == 0 || op[len] == '='))
1347 return false;
1348 }
1349 return true;
1350 }
1351
1352 if(eq(op, "!$") || eq(op, "isnot"))
1353 return !eq_case(v2, v1);
1354
1355 if(eq(op, "$") || eq(op, "is"))
1356 return eq_case(v2, v1);
1357
1358 #ifdef HAVE_REGEX_H
1359 if(eq(op, "~") || eq(op, "!~")) {
1360 bool rtn = false;
1361 regex_t *regex = new regex_t;
1362 memset(regex, 0, sizeof(regex_t));
1363
1364 if(regcomp(regex, v2, REG_ICASE|REG_NOSUB|REG_NEWLINE)) {
1365 regfree(regex);
1366 delete regex;
1367 return false;
1368 }
1369
1370 if(regexec(regex, v1, 0, NULL, 0))
1371 rtn = false;
1372 else
1373 rtn = true;
1374
1375 regfree(regex);
1376 delete regex;
1377 if(*op == '!')
1378 return !rtn;
1379 return rtn;
1380 }
1381 #endif
1382 return false;
1383 }
1384
1385 } // namespace ucommon
method_t getLooping(void)
const char * getIndex(void)
symbol * createSymbol(const char *id)
bool step(void)
Step through an instance of the interpreter.
virtual const char * getTypeinit(const char *type_id)
static unsigned stepping
default stepping increment
static unsigned indexing
default symbol indexing
virtual const char * getFormat(symbol *sym, const char *id, char *temp)
static const char * get(const char *list, unsigned offset)
static void copy(const char *list, char *item, unsigned size)
void setStack(header *scr, event *ev=NULL)
char * data
content of symbol
bool error(const char *text)
Invoke runtime interpreter error handling.
bool setConst(const char *id, const char *value)
bool scriptEvent(const char *name)
Try to branch to a named event handler.
event * scriptMethod(const char *name)
Search for an event object in the method table.
const char * name
name of symbol
const char * getContent(void)
Basic compiled statement.
static unsigned stacking
stack frames in script runtime
Contains instance of a runtime symbol.
virtual bool getCondition(const char *test, const char *value)
static unsigned count(const char *list)
static unsigned offset(const char *list, unsigned index)
symbol * getVar(const char *id, const char *value=NULL)
header * scope
scope of symbol definition
static unsigned decimals
default decimal places
static keyword_t * find(const char *id)
Find a keyword from internal command table.
bool(Script::interp::* method_t)(void)
A type for runtime script method invokation.
void initialize(void)
Used to initialize and purge the interpreter between runs.
Compiled script container.
unsigned getResource(void)
Get current dsp resource mask.
virtual unsigned getTypesize(const char *type_id)
void startScript(header *scr)
void detach(void)
Cleanup after interpreter run.
int main(int argc, char **argv)
An event block for a script.
void getParams(header *scope, line_t *line)
bool trylabel(const char *id)
unsigned size
size of data buffer or 0 if const
Runtime stack for each interpreter instance.
static unsigned sizing
default symbol size
const char * getValue(void)
bool attach(Script *image, const char *entry=NULL)
Attach a compiled image to the interpreter and start.
const char * getKeyword(const char *id)
void setRef(header *scope, const char *id, char *data, unsigned size)
const char * getFilename(void)
Get effective filename of base.
symbol * find(const char *id)
bool isConditional(unsigned index)