21 #include <ucommon/ucommon.h>
22 #include <ucommon/export.h>
27 using namespace UCOMMON_NAMESPACE;
29 static const char *getArgument(Script::line_t *line,
unsigned *index)
34 if(*index >= line->argc)
36 cp = line->argv[*index];
46 static const char *getKeyword(
const char *kw, Script::line_t *line)
51 while(index < line->argc) {
52 cp = line->argv[index++];
53 if(*cp ==
'=' && eq(kw, ++cp))
54 return line->argv[index];
59 static unsigned getArguments(Script::line_t *line)
65 while(index < line->argc) {
66 cp = line->argv[index++];
76 static unsigned getRequired(Script::line_t *line)
82 while(index < line->argc) {
83 cp = line->argv[index++];
88 if(eq(cp,
"required"))
94 bool Script::checks::isText(
const char *text)
104 bool Script::checks::isValue(
const char *text)
135 const char *Script::checks::chkApply(Script *img, Script::header *scr, Script::line_t *line)
138 return "template define script required";
141 return "only one template define can be applied";
144 return "apply must be first statement of a new script";
147 return "only one apply statement can be used";
149 if(!isalnum(line->argv[0][0]))
150 return "must apply using valid name of a defined script";
152 Script::header *tmp = Script::find(img, line->argv[0]);
154 return "invalid or unknown script applied";
156 scr->methods = tmp->methods;
157 scr->events = tmp->events;
161 const char *Script::checks::chkPrevious(Script *img, Script::header *scr, Script::line_t *line)
163 method_t method = img->looping();
165 if(method == (method_t)NULL)
166 return "cannot be called outside loop";
168 if(method == (method_t)&Script::methods::scrForeach)
171 return "cannot be called outside for or foreach block";
175 return "command has no arguments";
180 const char *Script::checks::chkContinue(Script *img, Script::header *scr, Script::line_t *line)
182 method_t method = img->looping();
184 if(method == (method_t)NULL)
185 return "cannot be called outside loop";
187 if(method == (method_t)&Script::methods::scrDo)
190 if(method == (method_t)&Script::methods::scrWhile)
193 if(method == (method_t)&Script::methods::scrForeach)
196 return "cannot be called from conditional block";
200 return "command has no arguments";
205 const char *Script::checks::chkStrict(Script *img, Script::header *scr, Script::line_t *line)
210 if(!eq(scr->name,
"_init_"))
211 return "strict can only be used in initialization section";
214 return "strict must be defined at start of initialization section";
217 Script::strict::createGlobal(img,
"error");
218 Script::strict::createGlobal(img,
"index");
222 while(index < line->argc) {
223 cp = line->argv[index++];
225 return "strict must only declare names of defined internal global vars";
226 Script::strict::createGlobal(img, cp);
231 const char *Script::checks::chkBreak(Script *img, Script::header *scr, Script::line_t *line)
233 method_t method = img->looping();
235 if(method == (method_t)NULL)
236 return "cannot be called outside loop";
239 return "command has no arguments";
244 const char *Script::checks::chkRef(Script *img, Script::header *scr, Script::line_t *line)
247 return "one symbol argument for referencing";
249 const char *cp = line->argv[0];
251 return "only field operations can be referenced alone";
256 const char *Script::checks::chkWhen(Script *img, Script::header *scr, Script::line_t *line)
259 return "missing conditional expression";
261 return chkConditional(img, scr, line);
264 const char *Script::checks::chkIf(Script *img, Script::header *scr, Script::line_t *line)
267 return "analysis overflow for if command";
270 return "cannot nest if in if-then clause";
272 return chkConditional(img, scr, line);
275 const char *Script::checks::chkWhile(Script *img, Script::header *scr, Script::line_t *line)
277 if(eq(scr->name,
"_init_"))
278 return "this command cannot be used to initialize";
281 return "cannot use while in if-then clause";
284 return "stack overflow for while command";
286 return chkConditional(img, scr, line);
289 const char *Script::checks::chkExpand(Script *img, Script::header *scr, Script::line_t *line)
295 return "no value to expand";
298 return "no symbols to assign";
300 if(!isValue(line->argv[0]))
301 return "cannot expand non-value";
303 while(line->argv[index]) {
307 return "cannot assign literal";
309 return "no keywords are used in this command";
311 return "cannot assign to format";
313 return "cannot assign to label";
315 return "cannot assign to event";
317 return "cannot assign to expression";
319 strict::createAny(img, scr, line->argv[index++]);
324 const char *Script::checks::chkForeach(Script *img, Script::header *scr, Script::line_t *line)
328 if(eq(scr->name,
"_init_"))
329 return "this command cannot be used to initialize";
332 return "cannot use for in if-then clause";
335 return "stack overflow for do command";
338 return "no symbols to assign";
340 if(line->argc < 2 || line->argc > 3)
341 return "assign from only one source";
346 return "cannot assign literal";
348 return "no keywords are used in this command";
350 return "cannot assign to format";
352 return "cannot assign to label";
354 return "cannot assign to event";
356 return "cannot assign to expression";
358 strict::createAny(img, scr, line->argv[0]);
360 if(!isValue(line->argv[1]))
361 return "cannot assign from label or expression";
363 if(line->argc == 3 && !isValue(line->argv[2]))
364 return "skip must be a value or symbol";
369 const char *Script::checks::chkDo(Script *img, Script::header *scr, Script::line_t *line)
371 if(eq(scr->name,
"_init_"))
372 return "this command cannot be used to initialize";
375 return "cannot use do in if-then clause";
378 return "no arguments for do command";
381 return "stack overflow for do command";
386 const char *Script::checks::chkEndif(Script *img, Script::header *scr, Script::line_t *line)
388 Script::method_t method = img->pull();
391 return "cannot endif in if-then clause";
393 if(method != (method_t)&Script::methods::scrIf && method != (method_t)&Script::methods::scrElse)
394 return "endif not within an if block";
397 return "endif has no arguments";
402 const char *Script::checks::chkEndcase(Script *img, Script::header *scr, Script::line_t *line)
404 Script::method_t method = img->pull();
407 return "cannot endcase in if-then clause";
409 if(eq(scr->name,
"_init_"))
410 return "this command cannot be used to initialize";
412 if(method != (method_t)&Script::methods::scrCase && method != (method_t)&Script::methods::scrOtherwise)
413 return "endcase not within a case block";
416 return "endcase has no arguments";
422 const char *Script::checks::chkLoop(Script *img, Script::header *scr, Script::line_t *line)
424 Script::method_t method = img->pull();
427 return "can not end loop in if-then clause";
429 if(eq(scr->name,
"_init_"))
430 return "this command cannot be used to initialize";
432 if(method == (method_t)&Script::methods::scrWhile)
435 if(method == (method_t)&Script::methods::scrDo)
438 if(method == (method_t)&Script::methods::scrForeach)
441 if(method == (method_t)NULL)
442 return "not called from within loop";
444 return "not called from valid loop";
448 return "loop has no arguments";
453 const char *Script::checks::chkCase(Script *img, Script::header *scr, Script::line_t *line)
455 Script::method_t method = img->looping();
458 return "cannot create case in if-then clause";
460 if(eq(scr->name,
"_init_"))
461 return "this command cannot be used to initialize";
463 if(method == (method_t)&Script::methods::scrOtherwise)
464 return "cannot have case after otherwise";
466 if(method != (method_t)&Script::methods::scrCase) {
468 return "stack overflow for do command";
476 return chkConditional(img, scr, line);
479 const char *Script::checks::chkElif(Script *img, Script::header *scr, Script::line_t *line)
481 Script::method_t method = img->looping();
484 return "cannot have elif in if-then clause";
486 if(method == (method_t)&Script::methods::scrElse) {
487 return "cannot have more if conditions after else";
490 if(method != (method_t)&Script::methods::scrIf) {
491 return "cannot have elif outside of if block";
494 return chkConditional(img, scr, line);
497 const char *Script::checks::chkElse(Script *img, Script::header *scr, Script::line_t *line)
499 Script::method_t method = img->looping();
502 return "cannot have else in if-then clause";
504 if(method == (method_t)&Script::methods::scrElse) {
505 return "cannot have multiple else statements";
508 if(method != (method_t)&Script::methods::scrIf) {
509 return "cannot have else outside of if block";
517 return "otherwise has no arguments";
522 const char *Script::checks::chkOtherwise(Script *img, Script::header *scr, Script::line_t *line)
524 Script::method_t method = img->looping();
527 return "cannot have otherwise if-then clause";
529 if(eq(scr->name,
"_init_"))
530 return "this command cannot be used to initialize";
532 if(method != (method_t)&Script::methods::scrCase) {
533 return "cannot have otherwise outside of case block";
542 return "otherwise has no arguments";
547 const char *Script::checks::chkUntil(Script *img, Script::header *scr, Script::line_t *line)
549 Script::method_t method = img->pull();
552 return "cannot have until in if-then clause";
554 if(eq(scr->name,
"_init_"))
555 return "this command cannot be used to initialize";
557 if(method == (method_t)NULL || method != (method_t)&Script::methods::scrDo)
558 return "not called from within do loop";
560 return chkConditional(img, scr, line);
563 const char *Script::checks::chkNop(Script *img, Script::header *scr, Script::line_t *line)
566 return "arguments are not used for this command";
571 const char *Script::checks::chkExit(Script *img, Script::header *scr, Script::line_t *line)
574 return "arguments are not used for this command";
576 if(eq(scr->name,
"_init_"))
577 return "this command cannot be used to initialize";
582 const char *Script::checks::chkInvoke(Script *img, Script::header *scr, Script::line_t *line)
584 Script::line_t *sub = line->sub->first;
585 unsigned required = getRequired(sub);
586 unsigned limit = getArguments(sub);
587 unsigned count = getArguments(line);
591 if(eq(scr->name,
"_init_"))
592 return "this command cannot be used to initialize";
595 return "too few arguments for invoked command";
598 return "too many arguments for invoked command";
601 while(index < sub->argc) {
602 kw = sub->argv[index++];
604 cp = sub->argv[index++];
605 if(eq(cp,
"required") && !getKeyword(++kw, line))
606 return "required keyword missing";
610 while(index < line->argc) {
611 kw = line->argv[index++];
613 if(!getKeyword(++kw, sub))
614 return "unknown or invalid keyword used";
621 const char *Script::checks::chkDefine(Script *img, Script::header *scr, Script::line_t *line)
629 return "cannot define in if-then clause";
634 while(index < line->argc) {
635 cp = line->argv[index++];
638 return "no size or type set for referencing";
639 strict::createVar(img, scr, cp);
644 if(eq(cp,
"optional"))
645 line->argv[index - 1] = (
char *)
"&";
646 else if(!eq(cp,
"required"))
647 return "invalid keyword used in prototype";
649 else if(!isValue(cp))
650 return "cannot assign from label or expression";
652 if(img->isStrict()) {
653 snprintf(idbuf,
sizeof(idbuf),
"%d", ++count);
654 strict::createVar(img, scr, img->dup(idbuf));
661 const char *Script::checks::chkPack(Script *img, Script::header *scr, Script::line_t *line)
667 return "no symbols to assign";
670 return "no values to assign";
675 return "cannot assign literal";
677 return "cannot assign members before symbol name";
679 return "cannot assign to format";
681 return "cannot assign to label";
683 return "cannot assign to event";
685 return "cannot assign to expression";
688 Script::strict::createAny(img, scr, cp);
690 while(index < line->argc) {
691 cp = line->argv[index++];
695 return "cannot assign from label or expression";
701 const char *Script::checks::chkPush(Script *img, Script::header *scr, Script::line_t *line)
706 return "no symbol to push";
709 return "only use value or key and value";
714 return "cannot assign literal";
716 return "no keywords are used in this command";
718 return "cannot assign to format";
720 return "cannot assign to label";
722 return "cannot assign to event";
724 return "cannot assign to expression";
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";
730 if(line->argv[2] && !isValue(line->argv[2]) && !isText(line->argv[1]))
731 return "cannot push value from label or expression";
736 const char *Script::checks::chkSet(Script *img, Script::header *scr, Script::line_t *line)
743 return "no symbols to assign";
746 if(eq(line->argv[1],
":="))
748 else if(eq(line->argv[1],
"+=")) {
750 line->method = (method_t)&methods::scrAdd;
756 while(drop && drop < line->argc) {
757 line->argv[drop] = line->argv[drop + 1];
760 line->argv[drop] = NULL;
764 return "no values to assign";
769 return "cannot assign literal";
771 return "no keywords are used in this command";
773 return "cannot assign to format";
775 return "cannot assign to label";
777 return "cannot assign to event";
779 return "cannot assign to expression";
782 Script::strict::createSym(img, scr, cp);
784 while(index < line->argc) {
785 cp = line->argv[index++];
787 return "no keywords are used in this command";
789 return "cannot assign to format";
794 const char *Script::checks::chkClear(Script *img, Script::header *scr, Script::line_t *line)
800 return "no symbols to clear";
802 while(index < line->argc) {
803 cp = line->argv[index++];
805 return "invalid symbol reference or syntax";
807 return "invalid size usage for symbol";
812 const char *Script::checks::chkError(Script *img, Script::header *scr, Script::line_t *line)
818 return "no error message";
820 while(index < line->argc) {
821 cp = line->argv[index++];
823 return "no keywords used in error";
825 if(*cp ==
'^' || *cp ==
'@')
826 return "cannot use label for error";
831 const char *Script::checks::chkConst(Script *img, Script::header *scr, Script::line_t *line)
837 return "no constants to assign";
839 while(index < line->argc) {
840 cp = line->argv[index++];
842 return "cannot assign data or use uninitialized symbol as const";
845 return "cannot alter size of const symbol";
847 Script::strict::createVar(img, scr, cp);
849 cp = line->argv[index++];
851 return "invalid assignment of const";
853 return "cannot use label or expression for const";
858 const char *Script::checks::chkGoto(Script *img, Script::header *scr, Script::line_t *line)
863 if(eq(scr->name,
"_init_"))
864 return "this command cannot be used to initialize";
867 return "goto requires at least one label or event handler";
869 while(index < line->argc) {
870 cp = line->argv[index++];
871 if(*cp !=
'@' && *cp !=
'^')
872 return "goto only allows scripts and handlers";
877 const char *Script::checks::chkGosub(Script *img, Script::header *scr, Script::line_t *line)
882 if(eq(scr->name,
"_init_"))
883 return "this command cannot be used to initialize";
886 return "gosub requires at least one label";
888 while(index < line->argc) {
889 cp = line->argv[index++];
890 if(*cp !=
'@' && !isalnum(*cp))
891 return "gosub only allows script sections and named methods";
897 const char *Script::checks::chkConditional(Script *img, Script::header *scr, Script::line_t *line)
902 while(index < line->argc) {
903 cp = line->argv[index++];
904 if((*cp ==
'-' || *cp ==
'!') && isalpha(cp[1])) {
905 if(index >= line->argc)
906 return "missing test value";
907 cp = line->argv[index++];
909 return "cannot test operator";
913 return "cannot use operator as element of expression";
915 if(index >= line->argc)
916 return "missing operator in expression";
918 cp = line->argv[index++];
920 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"))
921 return "invalid operator in expression";
923 if(index >= line->argc)
924 return "missing value from expression";
926 cp = line->argv[index++];
928 return "cannot use operator as element of expression";
930 if(index == line->argc)
933 cp = line->argv[index++];
934 if(eq(
"?&&", cp) || eq(
"?||", cp) || eq(
"and", cp) || eq(
"or", cp))
937 return "invalid expression joiner statement";
939 return "conditional expression missing";
942 const char *Script::checks::chkIndex(Script *img, Script::header *scr, Script::line_t *line)
946 method_t method = img->looping();
948 if(method == (method_t)NULL)
949 return "cannot be called outside loop";
951 if(method == (method_t)&Script::methods::scrForeach)
954 return "cannot be called outside for or foreach block";
958 return "requires at least position";
960 while(index < line->argc) {
961 cp = getArgument(line, &index);
963 return "malformed expression";
965 cp = getArgument(line, &index);
968 if(!eq(cp,
"*") && !eq(cp,
"/") && !eq(cp,
"+") && !eq(cp,
"-") && !eq(cp,
"#"))
969 return "invalid expression used";
970 if(index == line->argc)
971 return "incomplete expression";
977 const char *Script::checks::chkExpr(Script *img, Script::header *scr, Script::line_t *line)
983 return "no variable to assign";
985 while(index < line->argc) {
986 cp = line->argv[index++];
988 if(!eq(cp,
"=decimals"))
989 return "invalid keyword for expression";
995 cp = getArgument(line, &index);
997 return "no assignment";
1000 return "cannot assign literal as symbol";
1003 return "cannot assign format as symbol";
1005 if(*cp ==
'@' || *cp ==
'^')
1006 return "cannot assign label as symbol";
1009 return "cannot assign expression as symbol";
1011 Script::strict::createVar(img, scr, cp);
1013 cp = getArgument(line, &index);
1015 return "expression incomplete";
1017 if(!eq(cp,
":=") && !eq(cp,
"?=") && !eq(cp,
"+=") && !eq(cp,
"-=") && !eq(cp,
"*=") && !eq(cp,
"/="))
1018 return "expression must start with assignment expression";
1020 while(index < line->argc) {
1021 cp = getArgument(line, &index);
1023 return "malformed expression";
1025 cp = getArgument(line, &index);
1028 if(!eq(cp,
"*") && !eq(cp,
"/") && !eq(cp,
"+") && !eq(cp,
"-") && !eq(cp,
"#"))
1029 return "invalid expression used";
1030 if(index == line->argc)
1031 return "incomplete expression";
1036 const char *Script::checks::chkVar(Script *img, Script::header *scr, Script::line_t *line)
1042 return "no variables to assign";
1044 while(index < line->argc) {
1045 cp = line->argv[index++];
1047 return "cannot assign literal as symbol";
1050 return "cannot assign format as symbol";
1052 if(*cp ==
'@' || *cp ==
'^')
1053 return "cannot assign label as symbol";
1056 return "cannot assign expression as symbol";
1061 Script::strict::createVar(img, scr, cp);
1062 cp = line->argv[index++];
1064 return "invalid assignment of variables";
1066 return "cannot assign from label or expression";
1071 const char *Script::checks::chkIgnore(Script *img, Script::header *scr, Script::line_t *line)
#define BAYONNE_NAMESPACE
GNU Bayonne library namespace.