OSDN Git Service

vram mirroring の command line mode (v) を追加
[unagi/old-svn-converted.git] / client / trunk / script_syntax.c
1 /*
2 famicom ROM cartridge utility - unagi
3 script syntax data and function
4
5 Copyright (C) 2008-2009 ±·³«È¯¶¨Æ±Áȹç
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 #include <assert.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include "type.h"
25 #include "textutil.h"
26 #include "script.h"
27 #include "script_syntax.h"
28
29 static int syntax_check_expression(char **word, int word_num, struct st_expression *e)
30 {
31         if(word_num == 0){
32                 return NG;
33         }
34         //left
35         if(value_get(word[0], &(e->left.value)) == OK){
36                 e->left.type = EXPRESSION_TYPE_VALUE;
37         }else{
38                 e->left.type = EXPRESSION_TYPE_VARIABLE;
39                 e->left.variable = word[0][0];
40         }
41         word_num--;
42         if(word_num == 0){
43                 e->operator = OPERATOR_NONE;
44                 return OK;
45         }
46         //operator
47         e->operator = operator_get(word[1]);
48         if(e->operator == OPERATOR_ERROR){
49                 return NG;
50         }
51         word_num--;
52         if(word_num == 0){
53                 return NG;
54         }
55         //right
56         if(value_get(word[2], &(e->right.value)) == OK){
57                 e->right.type = EXPRESSION_TYPE_VALUE;
58         }else{
59                 e->right.type = EXPRESSION_TYPE_VARIABLE;
60                 e->right.variable = word[2][0];
61         }
62         return OK;
63 }
64
65 static int strto_enum(const char **t, const char *word, int start, long *val)
66 {
67         long i = start;
68         while(*t != NULL){
69                 if(strcmp(*t, word) == 0){
70                         *val = i;
71                         return OK;
72                 }
73                 i++;
74                 t++;
75         }
76         return NG;
77 }
78
79 #include "syntax_data.h"
80 static const char SYNTAX_ERROR_PREFIX[] = "syntax error:";
81
82 /*
83 return: error count, ¤³¤³¤Ç¤Ï 0 or 1
84 */
85 static int syntax_check_phase(char **word, int word_num, struct script *s, const int mode)
86 {
87         int i = sizeof(SCRIPT_SYNTAX) / sizeof(SCRIPT_SYNTAX[0]);
88         const struct script_syntax *syntax;
89         const char *opword;
90         opword = word[0];
91         syntax = SCRIPT_SYNTAX;
92         while(i != 0){
93                 if(strcmp(syntax->name, opword) == 0){
94                         int j;
95                         
96                         s->opcode = syntax->script_opcode;
97                         if((mode & syntax->permittion) == 0){
98                                 printf("%d:%s opcode %s is not allowed on current mode\n", s->line, SYNTAX_ERROR_PREFIX, syntax->name);
99                                 return 1;
100                         };
101                         {
102                                 int compare = 0;
103                                 switch(syntax->compare){
104                                 case SYNTAX_COMPARE_EQ:
105                                         compare = (syntax->argc == (word_num - 1));
106                                         break;
107                                 case SYNTAX_COMPARE_GT:
108                                         compare = ((word_num - 1) >= syntax->argc);
109                                         compare &= (word_num <= 5);
110                                         break;
111                                 }
112                                 if(!compare){
113                                         printf("%d:%s parameter number not match %s\n", s->line, SYNTAX_ERROR_PREFIX, opword);
114                                         return 1;
115                                 }
116                         }
117                         //opcode pointer ¤ò¤º¤é¤·¤Æñ¸ì¤Îµ¯ÅÀ¤ò°ú¿ô¤À¤±¤Ë¤¢¤ï¤»¤ë
118                         word++;
119                         word_num--;
120                         for(j = 0; j < word_num; j++){
121                                 switch(syntax->argv_type[j]){
122                                 case SYNTAX_ARGVTYPE_NULL:
123                                         printf("%d:%s ARGV_NULL select\n", s->line, SYNTAX_ERROR_PREFIX);
124                                         return 1;
125                                 case SYNTAX_ARGVTYPE_VALUE:
126                                         if(value_get(word[j], &(s->value[j])) == NG){
127                                                 printf("%d:%s value error %s %s\n", s->line, SYNTAX_ERROR_PREFIX, opword, word[j]);
128                                                 return 1;
129                                         }
130                                         break;
131                                 case SYNTAX_ARGVTYPE_HV:
132                                         switch(word[j][0]){
133                                         case 'H':
134                                         case 'h':
135                                                 s->value[j] = MIRROR_HORIZONAL;
136                                                 break;
137                                         case 'V':
138                                         case 'v':
139                                                 s->value[j] = MIRROR_VERTICAL;
140                                                 break;
141                                         case 'A':
142                                         case 'a':
143                                                 s->value[j] = MIRROR_PROGRAMABLE;
144                                                 break;
145                                         default:
146                                                 printf("%d:%s unknown scroll mirroring type %s\n", s->line, SYNTAX_ERROR_PREFIX, word[j]);
147                                                 return 1;
148                                         }
149                                         break;
150                                 case SYNTAX_ARGVTYPE_EXPRESSION:
151                                         s->value[j] = VALUE_EXPRESSION;
152                                         //Ì¿Îá̾¤Îñ¸ì¤Èñ¸ì¿ô¤ò½ü³°¤·¤ÆÅϤ¹
153                                         if(syntax_check_expression(&word[j], word_num - 1, &s->expression) == NG){
154                                                 printf("%d:%s expression error\n", s->line, SYNTAX_ERROR_PREFIX);
155                                                 return 1;
156                                         }
157                                         //°Ü¹Ô¤Îñ¸ì¤ÏÆɤޤʤ¤¤³¤È¤Ë¤¹¤ë(¤Þ¤º¤¤¤«¤â)
158                                         return 0;
159                                 case SYNTAX_ARGVTYPE_VARIABLE:{
160                                         const char v = word[j][0];
161                                         if(v >= 'a' && v <= 'z'){
162                                                 s->value[j] = VALUE_VARIABLE;
163                                                 s->variable = v;
164                                         }else{
165                                                 printf("%d:%s variable must use [a-z] %s\n", s->line, SYNTAX_ERROR_PREFIX, word[j]);
166                                                 return 1;
167                                         }
168                                         }break;
169                                 case SYNTAX_ARGVTYPE_CONSTANT:{
170                                         if(value_get(word[j], &(s->value[j])) == OK){
171                                                 break;
172                                         }else if(strto_enum(STR_CONSTANTNAME, word[j], VALUE_CONTANT_CPU_STEP_START, &(s->value[j])) == OK){
173                                                 break;
174                                         }else{
175                                                 printf("%d:%s constant error %s %s\n", s->line, SYNTAX_ERROR_PREFIX, opword, word[j]);
176                                                 return 1;
177                                         }
178                                         }break;
179                                 case SYNTAX_ARGVTYPE_TRANSTYPE:{
180                                         if(strto_enum(STR_TRANSTYPE, word[j], VALUE_TRANSTYPE_EMPTY, &(s->value[j])) == NG){
181                                                 printf("%d:%s unknown trans type %s\n", s->line, SYNTAX_ERROR_PREFIX, word[j]);
182                                                 return 1;
183                                         }
184                                         }break;
185                                 default:
186                                         s->value[j] = VALUE_UNDEF;
187                                         break;
188                                 }
189                         }
190                         //opcode found and ÆþÎÏʸ»ú¼ïÀµ¾ï
191                         return 0;
192                 }
193                 syntax++;
194                 i--;
195         }
196         printf("%d:%s unknown opcode %s\n", s->line, SYNTAX_ERROR_PREFIX, opword);
197         return 1;
198 }
199
200 /*
201 return: error count
202 */
203 int syntax_check(char **text, int text_num, struct script *s, int mode)
204 {
205         int error = 0;
206         int i;
207         mode = 1<< mode; //permittion ¤Ï bitflag ¤Ê¤Î¤Ç¤³¤³¤ÇÊÑ´¹¤¹¤ë
208         for(i = 0; i < text_num; i++){
209                 char *word[TEXT_MAXWORD];
210                 const int n = word_load(text[i], word);
211                 s->line = i + 1;
212                 switch(word[0][0]){
213                 case '#':
214                 case '\0':
215                         s->opcode = SCRIPT_OPCODE_COMMENT;
216                         break;
217                 default:
218                         error += syntax_check_phase(word, n, s, mode);
219                         break;
220                 }
221                 s++;
222         }
223         return error;
224 }
225