ccScript 5.1.0
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
checks.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 #include <ctype.h>
26 
27 namespace ucommon {
28 
29 static const char *getArgument(Script::line_t *line, unsigned *index)
30 {
31  const char *cp;
32 
33  for(;;) {
34  if(*index >= line->argc)
35  return NULL;
36  cp = line->argv[*index];
37  ++*index;
38  if(*cp == '=') {
39  ++*index;
40  continue;
41  }
42  return cp;
43  }
44 }
45 
46 static const char *getKeyword(const char *kw, Script::line_t *line)
47 {
48  unsigned index = 0;
49  const char *cp;
50 
51  while(index < line->argc) {
52  cp = line->argv[index++];
53  if(*cp == '=' && eq(kw, ++cp))
54  return line->argv[index];
55  }
56  return NULL;
57 }
58 
59 static unsigned getArguments(Script::line_t *line)
60 {
61  unsigned count = 0;
62  unsigned index = 0;
63  const char *cp;
64 
65  while(index < line->argc) {
66  cp = line->argv[index++];
67  if(*cp == '=') {
68  ++index;
69  continue;
70  }
71  ++count;
72  }
73  return count;
74 }
75 
76 static unsigned getRequired(Script::line_t *line)
77 {
78  unsigned count = 0;
79  unsigned index = 0;
80  const char *cp;
81 
82  while(index < line->argc) {
83  cp = line->argv[index++];
84  if(*cp == '=') {
85  ++index;
86  continue;
87  }
88  if(eq(cp, "required"))
89  ++count;
90  }
91  return count;
92 }
93 
94 bool Script::checks::isText(const char *text)
95 {
96  while(*text) {
97  if(!isalnum(*text))
98  return false;
99  ++text;
100  }
101  return true;
102 }
103 
104 bool Script::checks::isValue(const char *text)
105 {
106  switch(*text)
107  {
108  case '-':
109  case '+':
110  if(text[1] == '.')
111  return true;
112  case '.':
113  if(isdigit(text[1]))
114  return true;
115  return false;
116  case '0':
117  case '1':
118  case '2':
119  case '3':
120  case '4':
121  case '5':
122  case '6':
123  case '7':
124  case '8':
125  case '9':
126  case '&':
127  case '%':
128  case '$':
129  return true;
130  default:
131  return false;
132  }
133 }
134 
136 {
137  if(line->argc < 1)
138  return "template define script required";
139 
140  if(line->argc > 1)
141  return "only one template define can be applied";
142 
143  if(scr->first)
144  return "apply must be first statement of a new script";
145 
146  if(scr->events)
147  return "only one apply statement can be used";
148 
149  if(!isalnum(line->argv[0][0]))
150  return "must apply using valid name of a defined script";
151 
152  Script::header *tmp = Script::find(img, line->argv[0]);
153  if(!tmp)
154  return "invalid or unknown script applied";
155 
156  scr->methods = tmp->methods;
157  scr->events = tmp->events;
158  return NULL;
159 }
160 
162 {
163  method_t method = img->looping();
164 
165  if(method == (method_t)NULL)
166  return "cannot be called outside loop";
167 
168  if(method == (method_t)&Script::methods::scrForeach)
169  goto valid;
170 
171  return "cannot be called outside for or foreach block";
172 
173 valid:
174  if(line->argc)
175  return "command has no arguments";
176 
177  return NULL;
178 }
179 
181 {
182  method_t method = img->looping();
183 
184  if(method == (method_t)NULL)
185  return "cannot be called outside loop";
186 
187  if(method == (method_t)&Script::methods::scrDo)
188  goto valid;
189 
190  if(method == (method_t)&Script::methods::scrWhile)
191  goto valid;
192 
193  if(method == (method_t)&Script::methods::scrForeach)
194  goto valid;
195 
196  return "cannot be called from conditional block";
197 
198 valid:
199  if(line->argc)
200  return "command has no arguments";
201 
202  return NULL;
203 }
204 
206 {
207  unsigned index = 0;
208  const char *cp;
209 
210  if(!eq(scr->name, "_init_"))
211  return "strict can only be used in initialization section";
212 
213  if(scr->first)
214  return "strict must be defined at start of initialization section";
215 
216  if(!line->argc) {
217  Script::strict::createGlobal(img, "error");
218  Script::strict::createGlobal(img, "index");
219  return NULL;
220  }
221 
222  while(index < line->argc) {
223  cp = line->argv[index++];
224  if(!isalpha(*cp))
225  return "strict must only declare names of defined internal global vars";
227  }
228  return NULL;
229 }
230 
232 {
233  method_t method = img->looping();
234 
235  if(method == (method_t)NULL)
236  return "cannot be called outside loop";
237 
238  if(line->argc)
239  return "command has no arguments";
240 
241  return NULL;
242 }
243 
245 {
246  if(line->argc != 1)
247  return "one symbol argument for referencing";
248 
249  const char *cp = line->argv[0];
250  if(*cp != '$')
251  return "only field operations can be referenced alone";
252 
253  return NULL;
254 }
255 
257 {
258  if(!line->argc)
259  return "missing conditional expression";
260 
261  return chkConditional(img, scr, line);
262 }
263 
265 {
266  if(!img->push(line))
267  return "analysis overflow for if command";
268 
269  if(img->thencheck)
270  return "cannot nest if in if-then clause";
271 
272  return chkConditional(img, scr, line);
273 }
274 
276 {
277  if(eq(scr->name, "_init_"))
278  return "this command cannot be used to initialize";
279 
280  if(img->thencheck)
281  return "cannot use while in if-then clause";
282 
283  if(!img->push(line))
284  return "stack overflow for while command";
285 
286  return chkConditional(img, scr, line);
287 }
288 
290 {
291  unsigned index = 1;
292  const char *cp;
293 
294  if(line->argc < 1)
295  return "no value to expand";
296 
297  if(line->argc < 2)
298  return "no symbols to assign";
299 
300  if(!isValue(line->argv[0]))
301  return "cannot expand non-value";
302 
303  while(line->argv[index]) {
304  cp = line->argv[0];
305  switch(*cp) {
306  case '&':
307  return "cannot assign literal";
308  case '=':
309  return "no keywords are used in this command";
310  case '$':
311  return "cannot assign to format";
312  case '@':
313  return "cannot assign to label";
314  case '^':
315  return "cannot assign to event";
316  case '?':
317  return "cannot assign to expression";
318  }
319  strict::createAny(img, scr, line->argv[index++]);
320  }
321  return NULL;
322 }
323 
325 {
326  const char *cp;
327 
328  if(eq(scr->name, "_init_"))
329  return "this command cannot be used to initialize";
330 
331  if(img->thencheck)
332  return "cannot use for in if-then clause";
333 
334  if(!img->push(line))
335  return "stack overflow for do command";
336 
337  if(!line->argc)
338  return "no symbols to assign";
339 
340  if(line->argc < 2 || line->argc > 3)
341  return "assign from only one source";
342 
343  cp = line->argv[0];
344  switch(*cp) {
345  case '&':
346  return "cannot assign literal";
347  case '=':
348  return "no keywords are used in this command";
349  case '$':
350  return "cannot assign to format";
351  case '@':
352  return "cannot assign to label";
353  case '^':
354  return "cannot assign to event";
355  case '?':
356  return "cannot assign to expression";
357  }
358  strict::createAny(img, scr, line->argv[0]);
359 
360  if(!isValue(line->argv[1]))
361  return "cannot assign from label or expression";
362 
363  if(line->argc == 3 && !isValue(line->argv[2]))
364  return "skip must be a value or symbol";
365 
366  return NULL;
367 }
368 
370 {
371  if(eq(scr->name, "_init_"))
372  return "this command cannot be used to initialize";
373 
374  if(img->thencheck)
375  return "cannot use do in if-then clause";
376 
377  if(line->argc)
378  return "no arguments for do command";
379 
380  if(!img->push(line))
381  return "stack overflow for do command";
382 
383  return NULL;
384 }
385 
387 {
388  Script::method_t method = img->pull();
389 
390  if(img->thencheck)
391  return "cannot endif in if-then clause";
392 
394  return "endif not within an if block";
395 
396  if(line->argc)
397  return "endif has no arguments";
398 
399  return NULL;
400 }
401 
403 {
404  Script::method_t method = img->pull();
405 
406  if(img->thencheck)
407  return "cannot endcase in if-then clause";
408 
409  if(eq(scr->name, "_init_"))
410  return "this command cannot be used to initialize";
411 
413  return "endcase not within a case block";
414 
415  if(line->argc)
416  return "endcase has no arguments";
417 
418  --line->loop;
419  return NULL;
420 }
421 
423 {
424  Script::method_t method = img->pull();
425 
426  if(img->thencheck)
427  return "can not end loop in if-then clause";
428 
429  if(eq(scr->name, "_init_"))
430  return "this command cannot be used to initialize";
431 
432  if(method == (method_t)&Script::methods::scrWhile)
433  goto valid;
434 
435  if(method == (method_t)&Script::methods::scrDo)
436  goto valid;
437 
438  if(method == (method_t)&Script::methods::scrForeach)
439  goto valid;
440 
441  if(method == (method_t)NULL)
442  return "not called from within loop";
443 
444  return "not called from valid loop";
445 
446 valid:
447  if(line->argc)
448  return "loop has no arguments";
449 
450  return NULL;
451 }
452 
454 {
455  Script::method_t method = img->looping();
456 
457  if(img->thencheck)
458  return "cannot create case in if-then clause";
459 
460  if(eq(scr->name, "_init_"))
461  return "this command cannot be used to initialize";
462 
464  return "cannot have case after otherwise";
465 
466  if(method != (method_t)&Script::methods::scrCase) {
467  if(!img->push(line))
468  return "stack overflow for do command";
469  }
470  else {
471  img->pull();
472  img->push(line);
473  --line->loop;
474  }
475 
476  return chkConditional(img, scr, line);
477 }
478 
480 {
481  Script::method_t method = img->looping();
482 
483  if(img->thencheck)
484  return "cannot have elif in if-then clause";
485 
486  if(method == (method_t)&Script::methods::scrElse) {
487  return "cannot have more if conditions after else";
488  }
489 
490  if(method != (method_t)&Script::methods::scrIf) {
491  return "cannot have elif outside of if block";
492  }
493 
494  return chkConditional(img, scr, line);
495 }
496 
498 {
499  Script::method_t method = img->looping();
500 
501  if(img->thencheck)
502  return "cannot have else in if-then clause";
503 
504  if(method == (method_t)&Script::methods::scrElse) {
505  return "cannot have multiple else statements";
506  }
507 
508  if(method != (method_t)&Script::methods::scrIf) {
509  return "cannot have else outside of if block";
510  }
511 
512  // replace loop with else member to prevent duplication...
513  img->pull();
514  img->push(line);
515 
516  if(line->argc)
517  return "otherwise has no arguments";
518 
519  return NULL;
520 }
521 
523 {
524  Script::method_t method = img->looping();
525 
526  if(img->thencheck)
527  return "cannot have otherwise if-then clause";
528 
529  if(eq(scr->name, "_init_"))
530  return "this command cannot be used to initialize";
531 
532  if(method != (method_t)&Script::methods::scrCase) {
533  return "cannot have otherwise outside of case block";
534  }
535 
536  // replace loop with otherwise member to prevent duplication...
537  img->pull();
538  img->push(line);
539  --line->loop;
540 
541  if(line->argc)
542  return "otherwise has no arguments";
543 
544  return NULL;
545 }
546 
548 {
549  Script::method_t method = img->pull();
550 
551  if(img->thencheck)
552  return "cannot have until in if-then clause";
553 
554  if(eq(scr->name, "_init_"))
555  return "this command cannot be used to initialize";
556 
557  if(method == (method_t)NULL || method != (method_t)&Script::methods::scrDo)
558  return "not called from within do loop";
559 
560  return chkConditional(img, scr, line);
561 }
562 
564 {
565  if(line->argc)
566  return "arguments are not used for this command";
567 
568  return NULL;
569 }
570 
572 {
573  if(line->argc)
574  return "arguments are not used for this command";
575 
576  if(eq(scr->name, "_init_"))
577  return "this command cannot be used to initialize";
578 
579  return NULL;
580 }
581 
583 {
584  Script::line_t *sub = line->sub->first;
585  unsigned required = getRequired(sub);
586  unsigned limit = getArguments(sub);
587  unsigned count = getArguments(line);
588  unsigned index = 0;
589  const char *cp, *kw;
590 
591  if(eq(scr->name, "_init_"))
592  return "this command cannot be used to initialize";
593 
594  if(count < required)
595  return "too few arguments for invoked command";
596 
597  if(count > limit)
598  return "too many arguments for invoked command";
599 
600  index = 0;
601  while(index < sub->argc) {
602  kw = sub->argv[index++];
603  if(*kw == '=') {
604  cp = sub->argv[index++];
605  if(eq(cp, "required") && !getKeyword(++kw, line))
606  return "required keyword missing";
607  }
608  }
609  index = 0;
610  while(index < line->argc) {
611  kw = line->argv[index++];
612  if(*kw == '=') {
613  if(!getKeyword(++kw, sub))
614  return "unknown or invalid keyword used";
615  ++index;
616  }
617  }
618  return NULL;
619 }
620 
622 {
623  unsigned count = 0;
624  unsigned index = 0;
625  const char *cp;
626  char idbuf[8];
627 
628  if(img->thencheck)
629  return "cannot define in if-then clause";
630 
631  if(!line->argc)
632  return NULL;
633 
634  while(index < line->argc) {
635  cp = line->argv[index++];
636  if(*cp == '=') {
637  if(strchr(cp, ':'))
638  return "no size or type set for referencing";
639  strict::createVar(img, scr, cp);
640  continue;
641  }
642 
643  if(isalpha(*cp)) {
644  if(eq(cp, "optional"))
645  line->argv[index - 1] = (char *)"&"; // rewrite to null
646  else if(!eq(cp, "required"))
647  return "invalid keyword used in prototype";
648  }
649  else if(!isValue(cp))
650  return "cannot assign from label or expression";
651 
652  if(img->isStrict()) {
653  snprintf(idbuf, sizeof(idbuf), "%d", ++count);
654  strict::createVar(img, scr, img->dup(idbuf));
655  }
656  }
657 
658  return NULL;
659 }
660 
662 {
663  unsigned index = 1;
664  const char *cp;
665 
666  if(!line->argc)
667  return "no symbols to assign";
668 
669  if(line->argc < 2)
670  return "no values to assign";
671 
672  cp = line->argv[0];
673  switch(*cp) {
674  case '&':
675  return "cannot assign literal";
676  case '=':
677  return "cannot assign members before symbol name";
678  case '$':
679  return "cannot assign to format";
680  case '@':
681  return "cannot assign to label";
682  case '^':
683  return "cannot assign to event";
684  case '?':
685  return "cannot assign to expression";
686  }
687 
688  Script::strict::createAny(img, scr, cp);
689 
690  while(index < line->argc) {
691  cp = line->argv[index++];
692  if(*cp == '=')
693  continue;
694  if(!isValue(cp))
695  return "cannot assign from label or expression";
696  }
697 
698  return NULL;
699 }
700 
702 {
703  const char *cp;
704 
705  if(line->argc < 1)
706  return "no symbol to push";
707 
708  if(line->argc > 3)
709  return "only use value or key and value";
710 
711  cp = line->argv[0];
712  switch(*cp) {
713  case '&':
714  return "cannot assign literal";
715  case '=':
716  return "no keywords are used in this command";
717  case '$':
718  return "cannot assign to format";
719  case '@':
720  return "cannot assign to label";
721  case '^':
722  return "cannot assign to event";
723  case '?':
724  return "cannot assign to expression";
725  }
726  Script::strict::createSym(img, scr, cp);
727  if(!isValue(line->argv[1]) && !isText(line->argv[1]))
728  return "cannot push from label or expression";
729 
730  if(line->argv[2] && !isValue(line->argv[2]) && !isText(line->argv[1]))
731  return "cannot push value from label or expression";
732 
733  return NULL;
734 }
735 
737 {
738  unsigned pos = 0;
739 
740  if(!line->argc)
741  return "no events listed";
742 
743  while(pos < line->argc) {
744  if(line->argv[pos][0] == '^')
745  ++line->argv[pos];
746  ++pos;
747  }
748 
749  return NULL;
750 }
751 
753 {
754  unsigned drop = 0;
755  unsigned index = 1;
756  const char *cp;
757 
758  if(!line->argc)
759  return "no symbols to assign";
760 
761  if(line->argc > 2) {
762  if(eq(line->argv[1], ":="))
763  drop = 1;
764  else if(eq(line->argv[1], "+=")) {
765  drop = 1;
766  line->method = (method_t)&methods::scrAdd;
767  }
768  }
769 
770  if(drop) {
771  --line->argc;
772  while(drop && drop < line->argc) {
773  line->argv[drop] = line->argv[drop + 1];
774  ++drop;
775  }
776  line->argv[drop] = NULL;
777  }
778 
779  if(line->argc < 2)
780  return "no values to assign";
781 
782  cp = line->argv[0];
783  switch(*cp) {
784  case '&':
785  return "cannot assign literal";
786  case '=':
787  return "no keywords are used in this command";
788  case '$':
789  return "cannot assign to format";
790  case '@':
791  return "cannot assign to label";
792  case '^':
793  return "cannot assign to event";
794  case '?':
795  return "cannot assign to expression";
796  }
797 
798  Script::strict::createSym(img, scr, cp);
799 
800  while(index < line->argc) {
801  cp = line->argv[index++];
802  if(*cp == '=')
803  return "no keywords are used in this command";
804  if(!isValue(cp))
805  return "cannot assign to format";
806  }
807  return NULL;
808 }
809 
811 {
812  unsigned index = 0;
813  const char *cp;
814 
815  if(!line->argc)
816  return "no symbols to clear";
817 
818  while(index < line->argc) {
819  cp = line->argv[index++];
820  if(*cp != '%')
821  return "invalid symbol reference or syntax";
822  if(strchr(cp, ':'))
823  return "invalid size usage for symbol";
824  }
825  return NULL;
826 }
827 
829 {
830  unsigned index = 0;
831  const char *cp;
832 
833  if(!line->argc)
834  return "no error message";
835 
836  while(index < line->argc) {
837  cp = line->argv[index++];
838  if(*cp == '=')
839  return "no keywords used in error";
840 
841  if(*cp == '^' || *cp == '@')
842  return "cannot use label for error";
843  }
844  return NULL;
845 }
846 
848 {
849  unsigned index = 0;
850  const char *cp;
851 
852  if(!line->argc)
853  return "no constants to assign";
854 
855  while(index < line->argc) {
856  cp = line->argv[index++];
857  if(*cp != '=')
858  return "cannot assign data or use uninitialized symbol as const";
859 
860  if(strchr(cp, ':'))
861  return "cannot alter size of const symbol";
862 
863  Script::strict::createVar(img, scr, cp);
864 
865  cp = line->argv[index++];
866  if(*cp == '=')
867  return "invalid assignment of const";
868  if(!isValue(cp))
869  return "cannot use label or expression for const";
870  }
871  return NULL;
872 }
873 
875 {
876  unsigned index = 0;
877  const char *cp;
878 
879  if(eq(scr->name, "_init_"))
880  return "this command cannot be used to initialize";
881 
882  if(line->argc < 1)
883  return "goto requires at least one label or event handler";
884 
885  while(index < line->argc) {
886  cp = line->argv[index++];
887  if(*cp != '@' && *cp != '^')
888  return "goto only allows scripts and handlers";
889  }
890  return NULL;
891 }
892 
894 {
895  unsigned index = 0;
896  const char *cp;
897 
898  if(eq(scr->name, "_init_"))
899  return "this command cannot be used to initialize";
900 
901  if(line->argc < 1)
902  return "gosub requires at least one label";
903 
904  while(index < line->argc) {
905  cp = line->argv[index++];
906  if(*cp != '@' && !isalnum(*cp))
907  return "gosub only allows script sections and named methods";
908  }
909 
910  return NULL;
911 }
912 
914 {
915  unsigned index = 0;
916  const char *cp;
917 
918  while(index < line->argc) {
919  cp = line->argv[index++];
920  if((*cp == '-' || *cp == '!') && isalpha(cp[1])) {
921  if(index >= line->argc)
922  return "missing test value";
923  cp = line->argv[index++];
924  if(*cp == '?')
925  return "cannot test operator";
926  }
927  else {
928  if(*cp == '?')
929  return "cannot use operator as element of expression";
930 
931  if(index >= line->argc)
932  return "missing operator in expression";
933 
934  cp = line->argv[index++];
935 
936  if(*cp != '?' && !eq(cp, "eq") && !eq(cp, "ne") && !eq(cp, "lt") && !eq(cp, "gt") && !eq(cp, "le") && !eq(cp, "ge") && !eq(cp, "is") && !eq(cp, "isnot") && !eq(cp, "in") && !eq(cp, "notin"))
937  return "invalid operator in expression";
938 
939  if(index >= line->argc)
940  return "missing value from expression";
941 
942  cp = line->argv[index++];
943  if(*cp == '?')
944  return "cannot use operator as element of expression";
945  }
946  if(index == line->argc)
947  return NULL;
948 
949  cp = line->argv[index++];
950  if(eq("?&&", cp) || eq("?||", cp) || eq("and", cp) || eq("or", cp))
951  continue;
952 
953  return "invalid expression joiner statement";
954  }
955  return "conditional expression missing";
956 }
957 
959 {
960  unsigned index = 0;
961  const char *cp;
962  method_t method = img->looping();
963 
964  if(method == (method_t)NULL)
965  return "cannot be called outside loop";
966 
967  if(method == (method_t)&Script::methods::scrForeach)
968  goto valid;
969 
970  return "cannot be called outside for or foreach block";
971 
972 valid:
973  if(!line->argc)
974  return "requires at least position";
975 
976  while(index < line->argc) {
977  cp = getArgument(line, &index);
978  if(!isValue(cp))
979  return "malformed expression";
980 
981  cp = getArgument(line, &index);
982  if(!cp)
983  break;
984  if(!eq(cp, "*") && !eq(cp, "/") && !eq(cp, "+") && !eq(cp, "-") && !eq(cp, "#"))
985  return "invalid expression used";
986  if(index == line->argc)
987  return "incomplete expression";
988  }
989 
990  return NULL;
991 }
992 
994 {
995  unsigned index = 0;
996  const char *cp;
997 
998  if(line->argc < 3)
999  return "no variable to assign";
1000 
1001  while(index < line->argc) {
1002  cp = line->argv[index++];
1003  if(*cp == '=') {
1004  if(!eq(cp, "=decimals"))
1005  return "invalid keyword for expression";
1006  ++index;
1007  }
1008  }
1009 
1010  index = 0;
1011  cp = getArgument(line, &index);
1012  if(!cp)
1013  return "no assignment";
1014 
1015  if(*cp == '&')
1016  return "cannot assign literal as symbol";
1017 
1018  if(*cp == '$')
1019  return "cannot assign format as symbol";
1020 
1021  if(*cp == '@' || *cp == '^')
1022  return "cannot assign label as symbol";
1023 
1024  if(*cp == '?')
1025  return "cannot assign expression as symbol";
1026 
1027  Script::strict::createVar(img, scr, cp);
1028 
1029  cp = getArgument(line, &index);
1030  if(!cp)
1031  return "expression incomplete";
1032 
1033  if(!eq(cp, ":=") && !eq(cp, "?=") && !eq(cp, "+=") && !eq(cp, "-=") && !eq(cp, "*=") && !eq(cp, "/="))
1034  return "expression must start with assignment expression";
1035 
1036  while(index < line->argc) {
1037  cp = getArgument(line, &index);
1038  if(!isValue(cp))
1039  return "malformed expression";
1040 
1041  cp = getArgument(line, &index);
1042  if(!cp)
1043  break;
1044  if(!eq(cp, "*") && !eq(cp, "/") && !eq(cp, "+") && !eq(cp, "-") && !eq(cp, "#"))
1045  return "invalid expression used";
1046  if(index == line->argc)
1047  return "incomplete expression";
1048  }
1049  return NULL;
1050 }
1051 
1053 {
1054  unsigned index = 0;
1055  const char *cp;
1056 
1057  if(!line->argc)
1058  return "no variables to assign";
1059 
1060  while(index < line->argc) {
1061  cp = line->argv[index++];
1062  if(*cp == '&')
1063  return "cannot assign literal as symbol";
1064 
1065  if(*cp == '$')
1066  return "cannot assign format as symbol";
1067 
1068  if(*cp == '@' || *cp == '^')
1069  return "cannot assign label as symbol";
1070 
1071  if(*cp == '?')
1072  return "cannot assign expression as symbol";
1073 
1074  if(*cp != '=')
1075  continue;
1076 
1077  Script::strict::createVar(img, scr, cp);
1078  cp = line->argv[index++];
1079  if(*cp == '=')
1080  return "invalid assignment of variables";
1081  if(!isValue(cp))
1082  return "cannot assign from label or expression";
1083  }
1084  return NULL;
1085 }
1086 
1088 {
1089  return NULL;
1090 }
1091 
1092 } // namespace ucommon
static void createVar(Script *img, header *scr, const char *id)
Definition: script.cpp:985
static const char * chkDefine(Script *img, header *scr, line_t *line)
Definition: checks.cpp:621
static const char * chkConst(Script *img, header *scr, line_t *line)
Definition: checks.cpp:847
static const char * chkEndif(Script *img, header *scr, line_t *line)
Definition: checks.cpp:386
static const char * chkExit(Script *img, header *scr, line_t *line)
Definition: checks.cpp:571
static const char * chkIf(Script *img, header *scr, line_t *line)
Definition: checks.cpp:264
static const char * chkLoop(Script *img, header *scr, line_t *line)
Definition: checks.cpp:422
static const char * chkPrevious(Script *img, header *scr, line_t *line)
Definition: checks.cpp:161
static const char * chkClear(Script *img, header *scr, line_t *line)
Definition: checks.cpp:810
line_t * first
first line of section or define
Definition: ccscript.h:159
static const char * chkCase(Script *img, header *scr, line_t *line)
Definition: checks.cpp:453
static const char * chkForeach(Script *img, header *scr, line_t *line)
Definition: checks.cpp:324
static const char * chkStrict(Script *img, header *scr, line_t *line)
Definition: checks.cpp:205
static const char * chkConditional(Script *img, header *scr, line_t *line)
Definition: checks.cpp:913
static const char * chkExpr(Script *img, header *scr, line_t *line)
Definition: checks.cpp:993
static void createGlobal(Script *img, const char *id)
Definition: script.cpp:1094
static const char * chkBreak(Script *img, header *scr, line_t *line)
Definition: checks.cpp:231
unsigned short argc
Definition: ccscript.h:56
static const char * chkVar(Script *img, header *scr, line_t *line)
Definition: checks.cpp:1052
static const char * chkExpand(Script *img, header *scr, line_t *line)
Definition: checks.cpp:289
static const char * chkUntil(Script *img, header *scr, line_t *line)
Definition: checks.cpp:547
Basic compiled statement.
Definition: ccscript.h:49
static const char * chkWhile(Script *ing, header *scr, line_t *line)
Definition: checks.cpp:275
bool isStrict(void)
Definition: ccscript.h:514
static const char * chkContinue(Script *img, header *scr, line_t *line)
Definition: checks.cpp:180
static const char * chkEndcase(Script *img, header *scr, line_t *line)
Definition: checks.cpp:402
static void createAny(Script *img, header *scr, const char *id)
Definition: script.cpp:1057
static const char * chkWhen(Script *img, header *scr, line_t *line)
Definition: checks.cpp:256
static const char * chkNop(Script *img, header *scr, line_t *line)
Definition: checks.cpp:563
static bool isValue(const char *text)
Definition: checks.cpp:104
static const char * chkElse(Script *img, header *scr, line_t *line)
Definition: checks.cpp:497
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
static const char * chkRef(Script *img, header *scr, line_t *line)
Definition: checks.cpp:244
const char * name
name of script section or define
Definition: ccscript.h:161
method_t pull(void)
Definition: script.cpp:969
struct ucommon::Script::line line_t
Basic compiled statement.
static const char * chkGoto(Script *img, header *scr, line_t *line)
Definition: checks.cpp:874
Compiled script container.
Definition: ccscript.h:31
static const char * chkElif(Script *img, header *scr, line_t *line)
Definition: checks.cpp:479
static const char * chkError(Script *img, header *scr, line_t *line)
Definition: checks.cpp:828
static const char * chkPush(Script *img, header *scr, line_t *line)
Definition: checks.cpp:701
static const char * chkPack(Script *img, header *scr, line_t *line)
Definition: checks.cpp:661
Header describes a script section.
Definition: ccscript.h:150
static const char * chkGosub(Script *img, header *src, line_t *line)
Definition: checks.cpp:893
unsigned short loop
Definition: ccscript.h:56
static const char * chkInvoke(Script *img, header *scr, line_t *line)
Definition: checks.cpp:582
static const char * chkOtherwise(Script *img, header *scr, line_t *line)
Definition: checks.cpp:522
LinkedObject * methods
named members
Definition: ccscript.h:158
LinkedObject * events
named events
Definition: ccscript.h:157
static bool isText(const char *text)
Definition: checks.cpp:94
method_t looping(void)
Definition: script.cpp:977
bool push(line_t *line)
Definition: script.cpp:960
static const char * chkIgnmask(Script *img, header *scr, line_t *line)
Definition: checks.cpp:736
static const char * chkIgnore(Script *img, header *scr, line_t *line)
Definition: checks.cpp:1087
static const char * chkIndex(Script *img, header *scr, line_t *line)
Definition: checks.cpp:958
static const char * chkSet(Script *img, header *scr, line_t *line)
Definition: checks.cpp:752
static const char * chkApply(Script *img, header *scr, line_t *line)
Definition: checks.cpp:135
static const char * chkDo(Script *img, header *scr, line_t *line)
Definition: checks.cpp:369
static void createSym(Script *img, header *scr, const char *id)
Definition: script.cpp:1023