ccScript 5.1.0
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
methods.cpp
Go to the documentation of this file.
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>
24 #include <ccscript.h>
25 
26 namespace ucommon {
27 
29 {
30  push();
31  skip();
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;
50  Script::line_t *line = stack[frame].line;
51  const char *tuples = getContent(line->argv[0]);
52  unsigned tcount = Script::count(tuples);
53  Script::symbol *sym;
54  const char *cp;
55 
56  while(line->argv[index]) {
57  sym = find(line->argv[index]);
58 
59  if(!sym)
60  sym = getVar(line->argv[index]);
61 
62  if(!sym)
63  return error("symbol not found");
64 
65  if(!sym->size)
66  return error("symbol not writable");
67 
68  if(index > tcount)
69  String::set(sym->data, sym->size + 1, "");
70  else {
71  cp = Script::get(tuples, index - 1);
72  Script::copy(cp, sym->data, sym->size + 1);
73  }
74  ++index;
75  }
76  skip();
77  return true;
78 }
79 
81 {
82  Script::line_t *line = stack[frame].line;
83  Script::symbol *sym = find(line->argv[0]);
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 
93  if(!sym->size)
94  return error("symbol not writable");
95 
96  if(!index) {
97  cp = line->argv[2];
98  if(cp && (*cp == '%' || *cp == '&')) {
99  Script::symbol *skip = find(cp);
100  if(!skip)
101  skip = getVar(cp);
102  if(skip) {
103  index = atoi(skip->data);
104  if(skip->size)
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 
115  cp = Script::get(getContent(line->argv[1]), index);
116  if(cp == NULL) {
117  stack[frame].index = 0;
118  skip();
119  return scrBreak();
120  }
121 
122  Script::copy(cp, sym->data, sym->size + 1);
123  stack[frame].index = ++index;
124  push();
125  skip();
126  return true;
127 }
128 
130 {
131  if(isConditional(0)) {
132  push();
133  skip();
134  return true;
135  }
136  skip();
137  return scrBreak();
138 }
139 
141 {
142  pullLoop();
143  return true;
144 }
145 
147 {
148  Script::method_t method = getLooping();
149  Script::line_t *line = stack[frame].line;
150 
151  if(method == (method_t)&Script::methods::scrCase) {
152  skip();
153  while(stack[frame].line && stack[frame].line->loop > line->loop)
154  skip();
155  return true;
156  }
157 
158  if(isConditional(0)) {
159  push();
160  skip();
161  return true;
162  }
163 
164  return scrOtherwise();
165 
166  if(stack[frame].line->method == (method_t)&Script::methods::scrOtherwise) {
167  push();
168  skip();
169  return false;
170  }
171  return false;
172 }
173 
175 {
176  Script::line_t *line = stack[frame].line;
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 {
217  Script::line_t *line = stack[frame].line;
218  unsigned mask;
219 
220  getParams(line->sub, line->sub->first);
221  getParams(line->sub, line);
222 
223  skip(); // return to next line
224  push(); // push where we are
225  stack[frame].scope = line->sub;
226  stack[frame].line = line->sub->first->next;
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)) {
244  if(line->method == (method_t)&Script::methods::scrIf)
245  ++loop;
246  else if(line->method == (method_t)&Script::methods::scrEndif) {
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)) {
270  if(line->method == (method_t)&Script::methods::scrIf)
271  ++loop;
272  else if(line->method == (method_t)&Script::methods::scrEndif) {
273  if(!loop) {
274  skip();
275  return true;
276  }
277  --loop;
278  }
279  else if(!loop && line->method == (method_t)&Script::methods::scrElse) {
280  skip();
281  return true;
282  }
283  else if(!loop && line->method == (method_t)&Script::methods::scrElif) {
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 {
301  Script::line_t *line = stack[frame].line;
302  Script::method_t method = getLooping();
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 {
338  Script::line_t *line = stack[frame].line;
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 {
377  Script::line_t *line = stack[frame].line;
378  const char *cp;
379  Script::header *scr = NULL;
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
390  scr = Script::find(*image, line->argv[0]);
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;
406  Script::line_t *line = stack[frame].line;
407  Script::header *scr = NULL;
408  const char *cp;
409  unsigned mask = stack[frame].resmask;
410  Script::event *ev = NULL;
411 
412  while(ev == NULL && scr == NULL && index < line->argc) {
413  cp = line->argv[index++];
414  if(*cp == '@') {
415  scr = Script::find(*image, cp);
416  if(!scr && image->shared.get())
417  scr = Script::find(image->shared.get(), cp);
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...
433  push();
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 {
515  unsigned exdecimals = Script::decimals;
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;
593  Script::line_t *line = stack[frame].line;
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;
614  Script::line_t *line = stack[frame].line;
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;
632  Script::line_t *line = stack[frame].line;
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  }
647  return error(msg);
648 }
649 
651 {
652  unsigned index = 0;
653  Script::line_t *line = stack[frame].line;
654  const char *id;
655  Script::symbol *sym;
656 
657  while(index < line->argc) {
658  id = line->argv[index++];
659  sym = find(id);
660 
661  if(!sym || !sym->size)
662  return error("symbol not found");
663 
664  sym->data[0] = 0;
665  }
666  skip();
667  return true;
668 }
669 
671 {
672  unsigned index = 1;
673  Script::line_t *line = stack[frame].line;
674  Script::symbol *sym = find(line->argv[0]);
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 
683  if(!sym->size)
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;
697  Script::line_t *line = stack[frame].line;
698  Script::symbol *sym = find(line->argv[0]);
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 
708  if(!sym->size)
709  return error("symbol not writable");
710 
711  while(index < line->argc) {
712  cp = line->argv[index++];
713  if(*cp == '=') {
714  if(sym->data[0])
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:
727  if(sym->data[0])
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 {
752  Script::line_t *line = stack[frame].line;
753  Script::symbol *sym = createSymbol(line->argv[0]);
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 
761  if(!sym->size)
762  return error("symbol not writable");
763 
764  if(line->argv[2]) {
765  key = line->argv[1];
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;
781  if(line->argv[2])
782  size += strlen(line->argv[2]);
783 
784  if(strlen(sym->data) + size > sym->size)
785  return error("symbol too small");
786 
787  if(sym->data[0])
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;
806  Script::line_t *line = stack[frame].line;
807  Script::symbol *sym = createSymbol(line->argv[0]);
808  const char *cp;
809 
810  if(!sym)
811  return error("invalid symbol id");
812 
813  if(!sym->size)
814  return error("symbol not writable");
815 
816  sym->data[0] = 0;
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
unsigned resmask
post-compile processing resource mask
Definition: ccscript.h:162
struct line * next
Definition: ccscript.h:50
line_t * first
first line of section or define
Definition: ccscript.h:159
static const char * get(const char *list, unsigned offset)
Definition: script.cpp:1273
static void copy(const char *list, char *item, unsigned size)
Definition: script.cpp:1213
char * data
content of symbol
Definition: ccscript.h:117
unsigned short argc
Definition: ccscript.h:56
Basic compiled statement.
Definition: ccscript.h:49
Contains instance of a runtime symbol.
Definition: ccscript.h:110
static unsigned count(const char *list)
Definition: script.cpp:1187
static unsigned decimals
default decimal places
Definition: ccscript.h:454
static keyword_t * find(const char *id)
Find a keyword from internal command table.
Definition: script.cpp:345
bool(Script::interp::* method_t)(void)
A type for runtime script method invokation.
Definition: ccscript.h:41
friend class error
Definition: ccscript.h:523
Header describes a script section.
Definition: ccscript.h:150
An event block for a script.
Definition: ccscript.h:127
unsigned size
size of data buffer or 0 if const
Definition: ccscript.h:118
unsigned short loop
Definition: ccscript.h:56
bool scrPrevious(void)
Definition: methods.cpp:35
bool push(line_t *line)
Definition: script.cpp:960