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
26 namespace ucommon {
27
29 {
32 return true;
33 }
34
36 {
37 --frame;
38 if(stack[frame].index < 2) {
39 stack[frame].index = 0;
40 skip();
41 return scrBreak();
42 }
43 stack[frame].index -= 2;
44 return true;
45 }
46
48 {
49 unsigned index = 1;
51 const char *tuples = getContent(line->
argv[0]);
54 const char *cp;
55
56 while(line->
argv[index]) {
58
59 if(!sym)
60 sym = getVar(line->
argv[index]);
61
62 if(!sym)
63 return error(
"symbol not found");
64
66 return error(
"symbol not writable");
67
68 if(index > tcount)
69 String::set(sym->
data, sym->
size + 1,
"");
70 else {
73 }
74 ++index;
75 }
76 skip();
77 return true;
78 }
79
81 {
84 const char *cp;
85 unsigned index = stack[frame].index;
86
87 if(!sym)
88 sym = getVar(line->
argv[0]);
89
90 if(!sym)
91 return error(
"symbol not found");
92
94 return error(
"symbol not writable");
95
96 if(!index) {
98 if(cp && (*cp == '%' || *cp == '&')) {
100 if(!skip)
101 skip = getVar(cp);
102 if(skip) {
103 index = atoi(skip->
data);
105 String::set(skip->
data, 2,
"0");
106 }
107 }
108 else if(NULL != (cp = getContent(cp))) {
109 cp = getContent(cp);
110 if(cp)
111 index = atoi(cp);
112 }
113 }
114
116 if(cp == NULL) {
117 stack[frame].index = 0;
118 skip();
119 return scrBreak();
120 }
121
123 stack[frame].index = ++index;
125 skip();
126 return true;
127 }
128
130 {
131 if(isConditional(0)) {
133 skip();
134 return true;
135 }
136 skip();
137 return scrBreak();
138 }
139
141 {
142 pullLoop();
143 return true;
144 }
145
147 {
150
152 skip();
153 while(stack[frame].line && stack[frame].line->
loop > line->
loop)
154 skip();
155 return true;
156 }
157
158 if(isConditional(0)) {
160 skip();
161 return true;
162 }
163
164 return scrOtherwise();
165
168 skip();
169 return false;
170 }
171 return false;
172 }
173
175 {
177
178 skip();
179 while(stack[frame].line && stack[frame].line->
loop > line->
loop)
180 skip();
181
182 return true;
183 }
184
186 {
187 if(isConditional(0))
188 pullLoop();
189 else
190 --frame;
191 return true;
192 }
193
195 {
196 --frame;
197 return true;
198 }
199
201 {
202 return scrElse();
203 }
204
206 {
207 return scrNop();
208 }
209
211 {
212 return scrNop();
213 }
214
216 {
218 unsigned mask;
219
221 getParams(line->
sub, line);
222
223 skip(); // return to next line
224 push();
// push where we are
225 stack[frame].scope = line->
sub;
227 startScript(line->
sub);
228
229 mask = stack[frame].resmask |= line->
sub->
resmask;
230 if(mask != stack[frame].resmask) {
231 stack[frame].resmask = mask;
232 return false;
233 }
234 return true;
235 }
236
238 {
240 unsigned loop = 0;
241
242 skip();
243 while(NULL != (line = stack[frame].line)) {
245 ++loop;
247 if(!loop) {
248 skip();
249 return true;
250 }
251 --loop;
252 }
253 skip();
254 }
255 return true;
256 }
257
259 {
261 unsigned loop = 0;
262
263 if(isConditional(0)) {
264 skip();
265 return true;
266 }
267
268 skip();
269 while(NULL != (line = stack[frame].line)) {
271 ++loop;
273 if(!loop) {
274 skip();
275 return true;
276 }
277 --loop;
278 }
280 skip();
281 return true;
282 }
284 if(isConditional(0)) {
285 skip();
286 return true;
287 }
288 }
289 skip();
290 }
291 return false;
292 }
293
295 {
296 return false;
297 }
298
300 {
303
305 skip();
306 while(stack[frame].line && stack[frame].line->
loop >= line->
loop)
307 skip();
308 return true;
309 }
310
311 pullLoop();
312 while(stack[frame].line && stack[frame].line->
loop >= line->
loop)
313 skip();
314 return true;
315 }
316
318 {
319 --frame;
320 --stack[frame].index;
321 return true;
322 }
323
325 {
326 --frame;
327 return true;
328 }
329
331 {
332 skip();
333 return true;
334 }
335
337 {
339 const char *cp = line->
argv[0];
340
341 if((line->
argc == 1) && eq(cp,
"none"))
342 stack[frame].ignore = NULL;
343 else
344 stack[frame].ignore = line;
345 skip();
346 return true;
347 }
348
350 {
351 if(!isConditional(0))
352 skip();
353
354 skip();
355 return true;
356 }
357
359 {
360 frame = 0;
361 stack[frame].line = NULL;
362 return false;
363 }
364
366 {
367 unsigned mask = stack[frame].resmask;
368 pullBase();
369 setStack(stack[frame].scr);
370 if(mask == stack[frame].resmask)
371 return true;
372 return false;
373 }
374
376 {
378 const char *cp;
380 unsigned index = 0;
381 unsigned mask = stack[frame].resmask;
382
383 while(!scr && index < line->argc) {
384 cp = line->
argv[index++];
385 if(*cp == '^') {
386 if(scriptEvent(++cp))
387 return true;
388 }
389 else
391 }
392 if(!scr)
393 return error(
"label not found");
394
395 pullBase();
396 setStack(scr);
397 startScript(scr);
398 if(mask == stack[frame].resmask)
399 return true;
400 return false;
401 }
402
404 {
405 unsigned index = stack[frame].index;
408 const char *cp;
409 unsigned mask = stack[frame].resmask;
411
412 while(ev == NULL && scr == NULL && index < line->argc) {
413 cp = line->
argv[index++];
414 if(*cp == '@') {
416 if(!scr && image->shared.get())
418 }
419 else
420 ev = scriptMethod(cp);
421 }
422
423 if(!scr && !ev) {
424 if(!stack[frame].index)
425 return error(
"label not found");
426
427 stack[frame].index = 0;
428 skip();
429 return true;
430 }
431
432 stack[frame].index = index; // save index for re-call on return...
434 if(scr) {
435 setStack(scr);
436 startScript(scr);
437 stack[frame].base = frame; // set base level to new script...
438 if(mask == stack[frame].resmask)
439 return true;
440 }
441 else {
442 stack[frame].line = ev->
first;
443 stack[frame].index = 0;
444 return true;
445 }
446 return false;
447 }
448
450 {
451 unsigned mask = stack[frame].resmask;
452 if(!pop())
453 return scrExit();
454
455 if(mask == stack[frame].resmask)
456 return true;
457 return false;
458 }
459
461 {
462 const char *op;
463 int result = 0, value;
464
465 stack[frame].index = 0;
466 result = atoi(getValue());
467
468 while(NULL != (op = getValue())) {
469 switch(*op) {
470 case '+':
471 result += atoi(getValue());
472 break;
473 case '-':
474 result -= atoi(getValue());
475 break;
476 case '*':
477 result *= atoi(getValue());
478 break;
479 case '/':
480 value = atoi(getValue());
481 if(value == 0)
482 return error(
"div by zero");
483 result /= value;
484 break;
485 case '#':
486 value = atoi(getValue());
487 if(value == 0)
488 return error(
"div by zero");
489 result %= value;
490 break;
491 }
492 }
493
494 --frame;
495 if(!result) {
496 skip();
497 return scrBreak();
498 }
499 else
500 stack[frame].index = --result;
501
502 return true;
503 }
504
506 {
507 const char *cp = stack[frame].line->
argv[0];
508 getContent(cp);
509 skip();
510 return true;
511 }
512
514 {
516 const char *id, *cp, *op, *aop;
517 double result, value;
518 long lvalue;
519 char cvt[8];
520 char buf[32];
521
522 stack[frame].index = 0;
523
524 cp = getKeyword("decimals");
525 if(cp)
526 exdecimals = atoi(cp);
527
528 id = getContent();
529 aop = getValue();
530 result = atof(getValue());
531
532 while(NULL != (op = getValue())) {
533 switch(*op) {
534 case '+':
535 result += atof(getValue());
536 break;
537 case '-':
538 result -= atof(getValue());
539 break;
540 case '*':
541 result *= atof(getValue());
542 break;
543 case '/':
544 value = atof(getValue());
545 if(value == 0.) {
546 return error(
"div by zero");
547 }
548 result /= value;
549 break;
550 case '#':
551 lvalue = atol(getValue());
552 if(lvalue == 0)
553 return error(
"div by zero");
554 result = (long)result % lvalue;
555 }
556 }
557 cp = getContent(id);
558 if(cp)
559 value = atof(cp);
560 else
561 value = 0;
562 if(eq(aop, "+="))
563 value += result;
564 else if(eq(aop, "#="))
565 value = (long)value % (long)result;
566 else if(eq(aop, "-="))
567 value -= result;
568 else if(eq(aop, "*="))
569 value *= result;
570 else if(eq(aop, "/=") && result)
571 value /= result;
572 else if(eq(aop, "?=") || eq(aop, ":="))
573 value = result;
574
575 stack[frame].index = 0;
576 cvt[0] = '%';
577 cvt[1] = '.';
578 cvt[2] = '0' + exdecimals;
579 cvt[3] = 'f';
580 cvt[4] = 0;
581 snprintf(buf, sizeof(buf), cvt, value);
582
583 if(!getVar(id, buf))
584 return error(
"invalid symbol");
585
586 skip();
587 return true;
588 }
589
591 {
592 unsigned index = 0;
594 const char *id;
595
596 while(index < line->argc) {
597 id = line->
argv[index++];
598 if(*id == '=') {
599 if(!getVar(++
id, getContent(line->
argv[index++])))
600 return error(
"invalid symbol");
601 }
602 else {
603 if(!getVar(id))
604 return error(
"invalid symbol");
605 }
606 }
607 skip();
608 return true;
609 }
610
612 {
613 unsigned index = 0;
615 const char *id;
616
617 while(index < line->argc) {
618 id = line->
argv[index++];
619 if(*id == '=') {
620 if(!setConst(++
id, getContent(line->
argv[index++])))
621 return error(
"invalid constant");
622 }
623 }
624 skip();
625 return true;
626 }
627
629 {
630 char msg[65];
631 unsigned index = 0;
633 bool space = false;
634 const char *cp;
635
636 msg[0] = 0;
637 while(index < line->argc) {
638 if(space) {
639 String::add(msg, 65, " ");
640 space = false;
641 }
642 cp = line->
argv[index++];
643 if(*cp != '&')
644 space = true;
645 String::add(msg, 65, getContent(cp));
646 }
648 }
649
651 {
652 unsigned index = 0;
654 const char *id;
656
657 while(index < line->argc) {
658 id = line->
argv[index++];
660
661 if(!sym || !sym->
size)
662 return error(
"symbol not found");
663
665 }
666 skip();
667 return true;
668 }
669
671 {
672 unsigned index = 1;
675 const char *cp;
676
677 if(!sym)
678 sym = getVar(line->
argv[0]);
679
680 if(!sym)
681 return error(
"symbol not found");
682
684 return error(
"symbol not writable");
685
686 while(index < line->argc) {
687 cp = getContent(line->
argv[index++]);
688 String::add(sym->
data, sym->
size + 1, cp);
689 }
690 skip();
691 return true;
692 }
693
695 {
696 unsigned index = 1;
699 const char *cp;
700 char quote[2] = {0,0};
701
702 if(!sym)
703 sym = getVar(line->
argv[0]);
704
705 if(!sym)
706 return error(
"symbol not found");
707
709 return error(
"symbol not writable");
710
711 while(index < line->argc) {
712 cp = line->
argv[index++];
713 if(*cp == '=') {
715 String::add(sym->
data, sym->
size + 1,
",");
716
717 String::add(sym->
data, sym->
size + 1, ++cp);
718 String::add(sym->
data, sym->
size + 1,
"=");
719 cp = getContent(line->
argv[index++]);
720 quote[0] = '\'';
721 goto add;
722 }
723 else {
724 cp = getContent(cp);
725 quote[0] = 0;
726 add:
728 String::add(sym->
data, sym->
size + 1,
",");
729
730 if(!quote[0] && strchr(cp, ',')) {
731 if(*cp != '\'' && *cp != '\"')
732 quote[0] = '\'';
733 }
734 // tuple nesting...
735 if(!quote[0] && *cp == '\'')
736 quote[0] = '(';
737 if(quote[0])
738 String::add(sym->
data, sym->
size + 1, quote);
739 String::add(sym->
data, sym->
size + 1, cp);
740 if(quote[0] == '(')
741 quote[0] = ')';
742 if(quote[0])
743 String::add(sym->
data, sym->
size + 1, quote);
744 }
745 }
746 skip();
747 return true;
748 }
749
751 {
754 unsigned size = 0;
755 bool qflag = false;
756 const char *key = NULL, *value;
757
758 if(!sym)
759 return error(
"invalid symbol id");
760
762 return error(
"symbol not writable");
763
766 value = line->
argv[2];
767 }
768 else
769 value = line->
argv[1];
770
771 if(key)
772 size = strlen(key) + 1;
773
774 if(*value != '\"' && *value != '\'') {
775 qflag = true;
776 size += 2;
777 }
778 size += strlen(value);
779
780 size = strlen(line->
argv[1]) + 3;
782 size += strlen(line->
argv[2]);
783
784 if(strlen(sym->
data) + size > sym->
size)
785 return error(
"symbol too small");
786
788 String::add(sym->
data, sym->
size + 1,
",");
789
790 size = strlen(sym->
data);
791 if(key && qflag)
792 snprintf(sym->
data + size, sym->
size + 1 - size,
"%s='%s'", key, value);
793 else if(key)
794 snprintf(sym->
data + size, sym->
size + 1 - size,
"%s=%s", key, value);
795 else if(qflag)
796 snprintf(sym->
data + size, sym->
size + 1 - size,
"'%s'", value);
797 else
798 String::set(sym->
data + size, sym->
size + 1, value);
799 skip();
800 return true;
801 }
802
804 {
805 unsigned index = 1;
808 const char *cp;
809
810 if(!sym)
811 return error(
"invalid symbol id");
812
814 return error(
"symbol not writable");
815
817 while(index < line->argc) {
818 cp = getContent(line->
argv[index++]);
819 String::add(sym->
data, sym->
size + 1, cp);
820 }
821 skip();
822 return true;
823 }
824
825 } // namespace ucommon
static const char * get(const char *list, unsigned offset)
static void copy(const char *list, char *item, unsigned size)
char * data
content of symbol
Basic compiled statement.
Contains instance of a runtime symbol.
static unsigned count(const char *list)
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.
An event block for a script.
unsigned size
size of data buffer or 0 if const