OSDN Git Service

client 0.6.0 release
[unagi/old-svn-converted.git] / client / tag / 0.6.0 / script_syntax.c
diff --git a/client/tag/0.6.0/script_syntax.c b/client/tag/0.6.0/script_syntax.c
new file mode 100644 (file)
index 0000000..ac7e9d6
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+famicom ROM cartridge utility - unagi
+script syntax data and function
+
+Copyright (C) 2008-2009 ±·³«È¯¶¨Æ±Áȹç
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "type.h"
+#include "textutil.h"
+#include "script.h"
+#include "script_syntax.h"
+
+static int syntax_check_expression(char **word, int word_num, struct st_expression *e)
+{
+       if(word_num == 0){
+               return NG;
+       }
+       //left
+       if(value_get(word[0], &(e->left.value)) == OK){
+               e->left.type = EXPRESSION_TYPE_VALUE;
+       }else{
+               e->left.type = EXPRESSION_TYPE_VARIABLE;
+               e->left.variable = word[0][0];
+       }
+       word_num--;
+       if(word_num == 0){
+               e->operator = OPERATOR_NONE;
+               return OK;
+       }
+       //operator
+       e->operator = operator_get(word[1]);
+       if(e->operator == OPERATOR_ERROR){
+               return NG;
+       }
+       word_num--;
+       if(word_num == 0){
+               return NG;
+       }
+       //right
+       if(value_get(word[2], &(e->right.value)) == OK){
+               e->right.type = EXPRESSION_TYPE_VALUE;
+       }else{
+               e->right.type = EXPRESSION_TYPE_VARIABLE;
+               e->right.variable = word[2][0];
+       }
+       return OK;
+}
+
+static int strto_enum(const char **t, const char *word, int start, long *val)
+{
+       long i = start;
+       while(*t != NULL){
+               if(strcmp(*t, word) == 0){
+                       *val = i;
+                       return OK;
+               }
+               i++;
+               t++;
+       }
+       return NG;
+}
+
+#include "syntax_data.h"
+static const char SYNTAX_ERROR_PREFIX[] = "syntax error:";
+
+/*
+return: error count, ¤³¤³¤Ç¤Ï 0 or 1
+*/
+static int syntax_check_phase(char **word, int word_num, struct script *s, const int mode)
+{
+       int i = sizeof(SCRIPT_SYNTAX) / sizeof(SCRIPT_SYNTAX[0]);
+       const struct script_syntax *syntax;
+       const char *opword;
+       opword = word[0];
+       syntax = SCRIPT_SYNTAX;
+       while(i != 0){
+               if(strcmp(syntax->name, opword) == 0){
+                       int j;
+                       
+                       s->opcode = syntax->script_opcode;
+                       if((mode & syntax->permittion) == 0){
+                               printf("%d:%s opcode %s is not allowed on current mode\n", s->line, SYNTAX_ERROR_PREFIX, syntax->name);
+                               return 1;
+                       };
+                       {
+                               int compare = 0;
+                               switch(syntax->compare){
+                               case SYNTAX_COMPARE_EQ:
+                                       compare = (syntax->argc == (word_num - 1));
+                                       break;
+                               case SYNTAX_COMPARE_GT:
+                                       compare = ((word_num - 1) >= syntax->argc);
+                                       compare &= (word_num <= 5);
+                                       break;
+                               }
+                               if(!compare){
+                                       printf("%d:%s parameter number not match %s\n", s->line, SYNTAX_ERROR_PREFIX, opword);
+                                       return 1;
+                               }
+                       }
+                       //opcode pointer ¤ò¤º¤é¤·¤Æñ¸ì¤Îµ¯ÅÀ¤ò°ú¿ô¤À¤±¤Ë¤¢¤ï¤»¤ë
+                       word++;
+                       word_num--;
+                       for(j = 0; j < word_num; j++){
+                               switch(syntax->argv_type[j]){
+                               case SYNTAX_ARGVTYPE_NULL:
+                                       printf("%d:%s ARGV_NULL select\n", s->line, SYNTAX_ERROR_PREFIX);
+                                       return 1;
+                               case SYNTAX_ARGVTYPE_VALUE:
+                                       if(value_get(word[j], &(s->value[j])) == NG){
+                                               printf("%d:%s value error %s %s\n", s->line, SYNTAX_ERROR_PREFIX, opword, word[j]);
+                                               return 1;
+                                       }
+                                       break;
+                               case SYNTAX_ARGVTYPE_HV:
+                                       switch(word[j][0]){
+                                       case 'H':
+                                       case 'h':
+                                               s->value[j] = MIRROR_HORIZONAL;
+                                               break;
+                                       case 'V':
+                                       case 'v':
+                                               s->value[j] = MIRROR_VERTICAL;
+                                               break;
+                                       case 'A':
+                                       case 'a':
+                                               s->value[j] = MIRROR_PROGRAMABLE;
+                                               break;
+                                       default:
+                                               printf("%d:%s unknown scroll mirroring type %s\n", s->line, SYNTAX_ERROR_PREFIX, word[j]);
+                                               return 1;
+                                       }
+                                       break;
+                               case SYNTAX_ARGVTYPE_EXPRESSION:
+                                       s->value[j] = VALUE_EXPRESSION;
+                                       //Ì¿Îá̾¤Îñ¸ì¤Èñ¸ì¿ô¤ò½ü³°¤·¤ÆÅϤ¹
+                                       if(syntax_check_expression(&word[j], word_num - 1, &s->expression) == NG){
+                                               printf("%d:%s expression error\n", s->line, SYNTAX_ERROR_PREFIX);
+                                               return 1;
+                                       }
+                                       //°Ü¹Ô¤Îñ¸ì¤ÏÆɤޤʤ¤¤³¤È¤Ë¤¹¤ë(¤Þ¤º¤¤¤«¤â)
+                                       return 0;
+                               case SYNTAX_ARGVTYPE_VARIABLE:{
+                                       const char v = word[j][0];
+                                       if(v >= 'a' && v <= 'z'){
+                                               s->value[j] = VALUE_VARIABLE;
+                                               s->variable = v;
+                                       }else{
+                                               printf("%d:%s variable must use [a-z] %s\n", s->line, SYNTAX_ERROR_PREFIX, word[j]);
+                                               return 1;
+                                       }
+                                       }break;
+                               case SYNTAX_ARGVTYPE_CONSTANT:{
+                                       if(value_get(word[j], &(s->value[j])) == OK){
+                                               break;
+                                       }else if(strto_enum(STR_CONSTANTNAME, word[j], VALUE_CONTANT_CPU_STEP_START, &(s->value[j])) == OK){
+                                               break;
+                                       }else{
+                                               printf("%d:%s constant error %s %s\n", s->line, SYNTAX_ERROR_PREFIX, opword, word[j]);
+                                               return 1;
+                                       }
+                                       }break;
+                               case SYNTAX_ARGVTYPE_TRANSTYPE:{
+                                       if(strto_enum(STR_TRANSTYPE, word[j], VALUE_TRANSTYPE_EMPTY, &(s->value[j])) == NG){
+                                               printf("%d:%s unknown trans type %s\n", s->line, SYNTAX_ERROR_PREFIX, word[j]);
+                                               return 1;
+                                       }
+                                       }break;
+                               default:
+                                       s->value[j] = VALUE_UNDEF;
+                                       break;
+                               }
+                       }
+                       //opcode found and ÆþÎÏʸ»ú¼ïÀµ¾ï
+                       return 0;
+               }
+               syntax++;
+               i--;
+       }
+       printf("%d:%s unknown opcode %s\n", s->line, SYNTAX_ERROR_PREFIX, opword);
+       return 1;
+}
+
+/*
+return: error count
+*/
+int syntax_check(char **text, int text_num, struct script *s, int mode)
+{
+       int error = 0;
+       int i;
+       mode = 1<< mode; //permittion ¤Ï bitflag ¤Ê¤Î¤Ç¤³¤³¤ÇÊÑ´¹¤¹¤ë
+       for(i = 0; i < text_num; i++){
+               char *word[TEXT_MAXWORD];
+               const int n = word_load(text[i], word);
+               s->line = i + 1;
+               switch(word[0][0]){
+               case '#':
+               case '\0':
+                       s->opcode = SCRIPT_OPCODE_COMMENT;
+                       break;
+               default:
+                       error += syntax_check_phase(word, n, s, mode);
+                       break;
+               }
+               s++;
+       }
+       return error;
+}
+