21 #include <ccscript-config.h>
22 #include <ucommon/ucommon.h>
23 #include <ucommon/export.h>
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];
65 while(index < line->argc) {
66 cp = line->argv[index++];
82 while(index < line->argc) {
83 cp = line->argv[index++];
88 if(eq(cp,
"required"))
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";
154 return "invalid or unknown script applied";
166 return "cannot be called outside loop";
171 return "cannot be called outside for or foreach block";
175 return "command has no arguments";
185 return "cannot be called outside loop";
196 return "cannot be called from conditional block";
200 return "command has no arguments";
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";
222 while(index < line->argc) {
223 cp = line->
argv[index++];
225 return "strict must only declare names of defined internal global vars";
236 return "cannot be called outside loop";
239 return "command has no arguments";
247 return "one symbol argument for referencing";
249 const char *cp = line->
argv[0];
251 return "only field operations can be referenced alone";
259 return "missing conditional expression";
261 return chkConditional(img, scr, line);
267 return "analysis overflow for if command";
270 return "cannot nest if in if-then clause";
272 return chkConditional(img, scr, 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);
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";
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";
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";
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";
391 return "cannot endif in if-then clause";
394 return "endif not within an if block";
397 return "endif has no arguments";
407 return "cannot endcase in if-then clause";
409 if(eq(scr->
name,
"_init_"))
410 return "this command cannot be used to initialize";
413 return "endcase not within a case block";
416 return "endcase has no arguments";
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";
442 return "not called from within loop";
444 return "not called from valid loop";
448 return "loop has no arguments";
458 return "cannot create case in if-then clause";
460 if(eq(scr->
name,
"_init_"))
461 return "this command cannot be used to initialize";
464 return "cannot have case after otherwise";
468 return "stack overflow for do command";
476 return chkConditional(img, scr, line);
484 return "cannot have elif in if-then clause";
487 return "cannot have more if conditions after else";
491 return "cannot have elif outside of if block";
494 return chkConditional(img, scr, line);
502 return "cannot have else in if-then clause";
505 return "cannot have multiple else statements";
509 return "cannot have else outside of if block";
517 return "otherwise has no arguments";
527 return "cannot have otherwise if-then clause";
529 if(eq(scr->
name,
"_init_"))
530 return "this command cannot be used to initialize";
533 return "cannot have otherwise outside of case block";
542 return "otherwise has no arguments";
552 return "cannot have until in if-then clause";
554 if(eq(scr->
name,
"_init_"))
555 return "this command cannot be used to initialize";
558 return "not called from within do loop";
560 return chkConditional(img, scr, line);
566 return "arguments are not used for this command";
574 return "arguments are not used for this command";
576 if(eq(scr->
name,
"_init_"))
577 return "this command cannot be used to initialize";
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";
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";
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";
653 snprintf(idbuf,
sizeof(idbuf),
"%d", ++count);
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";
690 while(index < line->argc) {
691 cp = line->
argv[index++];
695 return "cannot assign from label or expression";
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";
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";
741 return "no events listed";
743 while(pos < line->argc) {
744 if(line->
argv[pos][0] ==
'^')
759 return "no symbols to assign";
762 if(eq(line->
argv[1],
":="))
764 else if(eq(line->
argv[1],
"+=")) {
772 while(drop && drop < line->argc) {
773 line->
argv[drop] = line->
argv[drop + 1];
776 line->
argv[drop] = NULL;
780 return "no values to assign";
785 return "cannot assign literal";
787 return "no keywords are used in this command";
789 return "cannot assign to format";
791 return "cannot assign to label";
793 return "cannot assign to event";
795 return "cannot assign to expression";
800 while(index < line->argc) {
801 cp = line->
argv[index++];
803 return "no keywords are used in this command";
805 return "cannot assign to format";
816 return "no symbols to clear";
818 while(index < line->argc) {
819 cp = line->
argv[index++];
821 return "invalid symbol reference or syntax";
823 return "invalid size usage for symbol";
834 return "no error message";
836 while(index < line->argc) {
837 cp = line->
argv[index++];
839 return "no keywords used in error";
841 if(*cp ==
'^' || *cp ==
'@')
842 return "cannot use label for error";
853 return "no constants to assign";
855 while(index < line->argc) {
856 cp = line->
argv[index++];
858 return "cannot assign data or use uninitialized symbol as const";
861 return "cannot alter size of const symbol";
865 cp = line->
argv[index++];
867 return "invalid assignment of const";
869 return "cannot use label or expression for const";
879 if(eq(scr->
name,
"_init_"))
880 return "this command cannot be used to initialize";
883 return "goto requires at least one label or event handler";
885 while(index < line->argc) {
886 cp = line->
argv[index++];
887 if(*cp !=
'@' && *cp !=
'^')
888 return "goto only allows scripts and handlers";
898 if(eq(scr->
name,
"_init_"))
899 return "this command cannot be used to initialize";
902 return "gosub requires at least one label";
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";
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++];
925 return "cannot test operator";
929 return "cannot use operator as element of expression";
931 if(index >= line->
argc)
932 return "missing operator in expression";
934 cp = line->
argv[index++];
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";
939 if(index >= line->
argc)
940 return "missing value from expression";
942 cp = line->
argv[index++];
944 return "cannot use operator as element of expression";
946 if(index == line->
argc)
949 cp = line->
argv[index++];
950 if(eq(
"?&&", cp) || eq(
"?||", cp) || eq(
"and", cp) || eq(
"or", cp))
953 return "invalid expression joiner statement";
955 return "conditional expression missing";
965 return "cannot be called outside loop";
970 return "cannot be called outside for or foreach block";
974 return "requires at least position";
976 while(index < line->argc) {
977 cp = getArgument(line, &index);
979 return "malformed expression";
981 cp = getArgument(line, &index);
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";
999 return "no variable to assign";
1001 while(index < line->argc) {
1002 cp = line->
argv[index++];
1004 if(!eq(cp,
"=decimals"))
1005 return "invalid keyword for expression";
1011 cp = getArgument(line, &index);
1013 return "no assignment";
1016 return "cannot assign literal as symbol";
1019 return "cannot assign format as symbol";
1021 if(*cp ==
'@' || *cp ==
'^')
1022 return "cannot assign label as symbol";
1025 return "cannot assign expression as symbol";
1029 cp = getArgument(line, &index);
1031 return "expression incomplete";
1033 if(!eq(cp,
":=") && !eq(cp,
"?=") && !eq(cp,
"+=") && !eq(cp,
"-=") && !eq(cp,
"*=") && !eq(cp,
"/="))
1034 return "expression must start with assignment expression";
1036 while(index < line->argc) {
1037 cp = getArgument(line, &index);
1039 return "malformed expression";
1041 cp = getArgument(line, &index);
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";
1058 return "no variables to assign";
1060 while(index < line->argc) {
1061 cp = line->
argv[index++];
1063 return "cannot assign literal as symbol";
1066 return "cannot assign format as symbol";
1068 if(*cp ==
'@' || *cp ==
'^')
1069 return "cannot assign label as symbol";
1072 return "cannot assign expression as symbol";
1078 cp = line->
argv[index++];
1080 return "invalid assignment of variables";
1082 return "cannot assign from label or expression";
static void createVar(Script *img, header *scr, const char *id)
static const char * chkDefine(Script *img, header *scr, line_t *line)
static const char * chkConst(Script *img, header *scr, line_t *line)
static const char * chkEndif(Script *img, header *scr, line_t *line)
static const char * chkExit(Script *img, header *scr, line_t *line)
static const char * chkIf(Script *img, header *scr, line_t *line)
static const char * chkLoop(Script *img, header *scr, line_t *line)
static const char * chkPrevious(Script *img, header *scr, line_t *line)
static const char * chkClear(Script *img, header *scr, line_t *line)
static const char * chkCase(Script *img, header *scr, line_t *line)
static const char * chkForeach(Script *img, header *scr, line_t *line)
static const char * chkStrict(Script *img, header *scr, line_t *line)
static const char * chkConditional(Script *img, header *scr, line_t *line)
static const char * chkExpr(Script *img, header *scr, line_t *line)
static void createGlobal(Script *img, const char *id)
static const char * chkBreak(Script *img, header *scr, line_t *line)
static const char * chkVar(Script *img, header *scr, line_t *line)
static const char * chkExpand(Script *img, header *scr, line_t *line)
static const char * chkUntil(Script *img, header *scr, line_t *line)
Basic compiled statement.
static const char * chkWhile(Script *ing, header *scr, line_t *line)
static const char * chkContinue(Script *img, header *scr, line_t *line)
static const char * chkEndcase(Script *img, header *scr, line_t *line)
static void createAny(Script *img, header *scr, const char *id)
static const char * chkWhen(Script *img, header *scr, line_t *line)
static const char * chkNop(Script *img, header *scr, line_t *line)
static bool isValue(const char *text)
static const char * chkElse(Script *img, header *scr, line_t *line)
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.
static const char * chkRef(Script *img, header *scr, line_t *line)
struct ucommon::Script::line line_t
Basic compiled statement.
static const char * chkGoto(Script *img, header *scr, line_t *line)
Compiled script container.
static const char * chkElif(Script *img, header *scr, line_t *line)
static const char * chkError(Script *img, header *scr, line_t *line)
static const char * chkPush(Script *img, header *scr, line_t *line)
static const char * chkPack(Script *img, header *scr, line_t *line)
static const char * chkGosub(Script *img, header *src, line_t *line)
static const char * chkInvoke(Script *img, header *scr, line_t *line)
static const char * chkOtherwise(Script *img, header *scr, line_t *line)
static bool isText(const char *text)
static const char * chkIgnmask(Script *img, header *scr, line_t *line)
static const char * chkIgnore(Script *img, header *scr, line_t *line)
static const char * chkIndex(Script *img, header *scr, line_t *line)
static const char * chkSet(Script *img, header *scr, line_t *line)
static const char * chkApply(Script *img, header *scr, line_t *line)
static const char * chkDo(Script *img, header *scr, line_t *line)
static void createSym(Script *img, header *scr, const char *id)