Browse Source

- Merged Rayce's cleanups of the script engine that account for duplicate labels, non-numeric labels and makes the engine case-insensitive towards keywords like if/case/switch/etc/
- Added the icons for the Food boosts (need packet version 8 to get them).


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9673 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 18 years ago
parent
commit
3b1e03537d
4 changed files with 105 additions and 70 deletions
  1. 7 0
      Changelog-Trunk.txt
  2. 83 68
      src/map/script.c
  3. 8 1
      src/map/status.c
  4. 7 1
      src/map/status.h

+ 7 - 0
Changelog-Trunk.txt

@@ -3,6 +3,13 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
+2007/01/19
+	* Merged Rayce's cleanups of the script engine that account for duplicate
+	  labels, non-numeric labels and makes the engine case-insensitive towards
+	  keywords like if/case/switch/etc/
+	* Added the icons for the Food boosts (need packet version 8 to get them,
+	  as these icons will just display Gloria, or crash you, when used on older
+	  clients).
 2007/01/18
 2007/01/18
 	* Modified the Storm Gust freeze counter code. It now takes into
 	* Modified the Storm Gust freeze counter code. It now takes into
 	  consideration the ID of the skill before increasing the counter, which
 	  consideration the ID of the skill before increasing the counter, which

+ 83 - 68
src/map/script.c

@@ -140,6 +140,7 @@ static struct {
 		int index;
 		int index;
 		int count;
 		int count;
 		int flag;
 		int flag;
+		struct linkdb_node *case_label;
 	} curly[256];		// 右カッコの情報
 	} curly[256];		// 右カッコの情報
 	int curly_count;	// 右カッコの数
 	int curly_count;	// 右カッコの数
 	int index;			// スクリプト内で使用した構文の数
 	int index;			// スクリプト内で使用した構文の数
@@ -957,7 +958,7 @@ const char* parse_curly_close(const char* p) {
 		sprintf(label,"__SW%x_FIN",syntax.curly[pos].index);
 		sprintf(label,"__SW%x_FIN",syntax.curly[pos].index);
 		l=add_str(label);
 		l=add_str(label);
 		set_label(l,script_pos, p);
 		set_label(l,script_pos, p);
-
+		linkdb_final(&syntax.curly[pos].case_label);	// free the list of case label
 		syntax.curly_count--;
 		syntax.curly_count--;
 		return p+1;
 		return p+1;
 	} else {
 	} else {
@@ -970,9 +971,12 @@ const char* parse_curly_close(const char* p) {
 //	 break, case, continue, default, do, for, function,
 //	 break, case, continue, default, do, for, function,
 //	 if, switch, while をこの内部で処理します。
 //	 if, switch, while をこの内部で処理します。
 const char* parse_syntax(const char* p) {
 const char* parse_syntax(const char* p) {
+	const char *p2 = skip_word(p);
+
 	switch(*p) {
 	switch(*p) {
+	case 'B':
 	case 'b':
 	case 'b':
-		if(!strncasecmp(p,"break",5) && !ISALPHA(p[5])) {
+		if(p2 - p == 5 && !strncasecmp(p,"break",5)) {
 			// break の処理
 			// break の処理
 			char label[256];
 			char label[256];
 			int pos = syntax.curly_count - 1;
 			int pos = syntax.curly_count - 1;
@@ -999,7 +1003,10 @@ const char* parse_syntax(const char* p) {
 				parse_line(label);
 				parse_line(label);
 				syntax.curly_count--;
 				syntax.curly_count--;
 			}
 			}
-			p = skip_word(p);
+			p = skip_space(p2);
+			if(*p != ';') {
+				disp_error_message("parse_syntax: need ';'",p);
+			}
 			p++;
 			p++;
 			// if, for , while の閉じ判定
 			// if, for , while の閉じ判定
 			p = parse_syntax_close(p + 1);
 			p = parse_syntax_close(p + 1);
@@ -1007,17 +1014,17 @@ const char* parse_syntax(const char* p) {
 		}
 		}
 		break;
 		break;
 	case 'c':
 	case 'c':
-		if(!strncasecmp(p,"case",4) && !ISALPHA(p[4])) {
+	case 'C':
+		if(p2 - p == 4 && !strncasecmp(p,"case",4)) {
 			// case の処理
 			// case の処理
-			if(syntax.curly_count <= 0 || syntax.curly[syntax.curly_count - 1].type != TYPE_SWITCH) {
+			int pos = syntax.curly_count-1;
+			if(pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) {
 				disp_error_message("parse_syntax: unexpected 'case' ",p);
 				disp_error_message("parse_syntax: unexpected 'case' ",p);
 				return p+1;
 				return p+1;
 			} else {
 			} else {
-				const char *p2;
+				char *np;
 				char label[256];
 				char label[256];
-				int  l;
-				int len;
-				int pos = syntax.curly_count-1;
+				int  l,v;
 				if(syntax.curly[pos].count != 1) {
 				if(syntax.curly[pos].count != 1) {
 					// FALLTHRU 用のジャンプ
 					// FALLTHRU 用のジャンプ
 					sprintf(label,"goto __SW%x_%xJ;",syntax.curly[pos].index,syntax.curly[pos].count);
 					sprintf(label,"goto __SW%x_%xJ;",syntax.curly[pos].index,syntax.curly[pos].count);
@@ -1031,18 +1038,24 @@ const char* parse_syntax(const char* p) {
 					set_label(l,script_pos, p);
 					set_label(l,script_pos, p);
 				}
 				}
 				// switch 判定文
 				// switch 判定文
+				p = skip_space(p2);
+				if(p == p2) {
+					disp_error_message("parse_syntax: expect space ' '",p);
+				}
+				// check whether case label is integer or not
+				v = strtol(p,&np,0);
+				if(np == p)
+					disp_error_message("parse_syntax: 'case' label not integer",p);
+				if((*p == '-' || *p == '+') && isdigit(p[1]))	// pre-skip because '-' can not skip_word
+					p++;
 				p = skip_word(p);
 				p = skip_word(p);
-				p = skip_space(p);
-				p2 = p;
-				p = skip_word(p);
-				len = p-p2; // length of word at p2
+				if(np != p)
+					disp_error_message("parse_syntax: 'case' label not integer",np);
 				p = skip_space(p);
 				p = skip_space(p);
 				if(*p != ':')
 				if(*p != ':')
 					disp_error_message("parse_syntax: expect ':'",p);
 					disp_error_message("parse_syntax: expect ':'",p);
-				memcpy(label,"if(",3);
-				memcpy(label+3,p2,len);
-				sprintf(label+3+len," != $@__SW%x_VAL) goto __SW%x_%x;",
-					syntax.curly[pos].index,syntax.curly[pos].index,syntax.curly[pos].count+1);
+				sprintf(label,"if(%d != $@__SW%x_VAL) goto __SW%x_%x;",
+					v,syntax.curly[pos].index,syntax.curly[pos].index,syntax.curly[pos].count+1);
 				syntax.curly[syntax.curly_count++].type = TYPE_NULL;
 				syntax.curly[syntax.curly_count++].type = TYPE_NULL;
 				// 2回parse しないとダメ
 				// 2回parse しないとダメ
 				p2 = parse_line(label);
 				p2 = parse_line(label);
@@ -1054,15 +1067,21 @@ const char* parse_syntax(const char* p) {
 					l=add_str(label);
 					l=add_str(label);
 					set_label(l,script_pos,p);
 					set_label(l,script_pos,p);
 				}
 				}
-				// 一時変数を消す
+
+				// check duplication of case label [Rayce]
+				if(linkdb_search(&syntax.curly[pos].case_label, (void*)v) != NULL)
+					disp_error_message("parse_syntax: dup 'case'",p);
+				linkdb_insert(&syntax.curly[pos].case_label, (void*)v, (void*)1);
+				
 				sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index);
 				sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index);
 				syntax.curly[syntax.curly_count++].type = TYPE_NULL;
 				syntax.curly[syntax.curly_count++].type = TYPE_NULL;
+			
 				parse_line(label);
 				parse_line(label);
 				syntax.curly_count--;
 				syntax.curly_count--;
 				syntax.curly[pos].count++;
 				syntax.curly[pos].count++;
 			}
 			}
 			return p + 1;
 			return p + 1;
-		} else if(!strncasecmp(p,"continue",8) && !ISALPHA(p[8])) {
+		} else if(p2 - p == 8 && !strncasecmp(p,"continue",8)) {
 			// continue の処理
 			// continue の処理
 			char label[256];
 			char label[256];
 			int pos = syntax.curly_count - 1;
 			int pos = syntax.curly_count - 1;
@@ -1087,7 +1106,9 @@ const char* parse_syntax(const char* p) {
 				parse_line(label);
 				parse_line(label);
 				syntax.curly_count--;
 				syntax.curly_count--;
 			}
 			}
-			p = skip_word(p);
+			p = skip_space(p2);
+			if(*p != ';')
+				disp_error_message("parse_syntax: need ';'",p);
 			p++;
 			p++;
 			// if, for , while の閉じ判定
 			// if, for , while の閉じ判定
 			p = parse_syntax_close(p + 1);
 			p = parse_syntax_close(p + 1);
@@ -1095,25 +1116,22 @@ const char* parse_syntax(const char* p) {
 		}
 		}
 		break;
 		break;
 	case 'd':
 	case 'd':
-		if(!strncasecmp(p,"default",7) && !ISALPHA(p[7])) {
+	case 'D':
+		if(p2 - p == 7 && !strncasecmp(p,"default",7)) {
 			// switch - default の処理
 			// switch - default の処理
-			if(syntax.curly_count <= 0 || syntax.curly[syntax.curly_count - 1].type != TYPE_SWITCH) {
+			int pos = syntax.curly_count-1;
+			if(pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) {
 				disp_error_message("parse_syntax: unexpected 'default'",p);
 				disp_error_message("parse_syntax: unexpected 'default'",p);
-				return p+1;
-			} else if(syntax.curly[syntax.curly_count - 1].flag) {
+			} else if(syntax.curly[pos].flag) {
 				disp_error_message("parse_syntax: dup 'default'",p);
 				disp_error_message("parse_syntax: dup 'default'",p);
-				return p+1;
 			} else {
 			} else {
 				char label[256];
 				char label[256];
 				int l;
 				int l;
-				int pos = syntax.curly_count-1;
 				// 現在地のラベルを付ける
 				// 現在地のラベルを付ける
-				p = skip_word(p);
-				p = skip_space(p);
+				p = skip_space(p2);
 				if(*p != ':') {
 				if(*p != ':') {
 					disp_error_message("parse_syntax: need ':'",p);
 					disp_error_message("parse_syntax: need ':'",p);
 				}
 				}
-				p++;
 				sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count);
 				sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count);
 				l=add_str(label);
 				l=add_str(label);
 				set_label(l,script_pos,p);
 				set_label(l,script_pos,p);
@@ -1131,15 +1149,12 @@ const char* parse_syntax(const char* p) {
 
 
 				syntax.curly[syntax.curly_count - 1].flag = 1;
 				syntax.curly[syntax.curly_count - 1].flag = 1;
 				syntax.curly[pos].count++;
 				syntax.curly[pos].count++;
-
-				p = skip_word(p);
-				return p + 1;
 			}
 			}
-		} else if(!strncasecmp(p,"do",2) && !ISALPHA(p[2])) {
+			return p + 1;
+		} else if(p2 - p == 2 && !strncasecmp(p,"do",2)) {
 			int l;
 			int l;
 			char label[256];
 			char label[256];
-			p=skip_word(p);
-			p=skip_space(p);
+			p=skip_space(p2);
 
 
 			syntax.curly[syntax.curly_count].type  = TYPE_DO;
 			syntax.curly[syntax.curly_count].type  = TYPE_DO;
 			syntax.curly[syntax.curly_count].count = 1;
 			syntax.curly[syntax.curly_count].count = 1;
@@ -1154,7 +1169,8 @@ const char* parse_syntax(const char* p) {
 		}
 		}
 		break;
 		break;
 	case 'f':
 	case 'f':
-		if(!strncasecmp(p,"for",3) && !ISALPHA(p[3])) {
+	case 'F':
+		if(p2 - p == 3 && !strncasecmp(p,"for",3)) {
 			int l;
 			int l;
 			char label[256];
 			char label[256];
 			int  pos = syntax.curly_count;
 			int  pos = syntax.curly_count;
@@ -1164,13 +1180,10 @@ const char* parse_syntax(const char* p) {
 			syntax.curly[syntax.curly_count].flag  = 0;
 			syntax.curly[syntax.curly_count].flag  = 0;
 			syntax.curly_count++;
 			syntax.curly_count++;
 
 
-			p=skip_word(p);
-			p=skip_space(p);
+			p=skip_space(p2);
 
 
-			if(*p != '(') {
+			if(*p != '(')
 				disp_error_message("parse_syntax: need '('",p);
 				disp_error_message("parse_syntax: need '('",p);
-				return p+1;
-			}
 			p++;
 			p++;
 
 
 			// 初期化文を実行する
 			// 初期化文を実行する
@@ -1197,10 +1210,8 @@ const char* parse_syntax(const char* p) {
 				add_scriptl(add_str(label));
 				add_scriptl(add_str(label));
 				add_scriptc(C_FUNC);
 				add_scriptc(C_FUNC);
 			}
 			}
-			if(*p != ';') {
+			if(*p != ';')
 				disp_error_message("parse_syntax: need ';'",p);
 				disp_error_message("parse_syntax: need ';'",p);
-				return p+1;
-			}
 			p++;
 			p++;
 
 
 			// ループ開始に飛ばす
 			// ループ開始に飛ばす
@@ -1233,11 +1244,12 @@ const char* parse_syntax(const char* p) {
 			l=add_str(label);
 			l=add_str(label);
 			set_label(l,script_pos,p);
 			set_label(l,script_pos,p);
 			return p;
 			return p;
-		} else if(!strncasecmp(p,"function",8) && !ISALPHA(p[8])) {
+		} else if(p2 - p == 8 && !strncasecmp(p,"function",8)) {
 			const char *func_name;
 			const char *func_name;
 			// function
 			// function
-			p=skip_word(p);
-			p=skip_space(p);
+			p=skip_space(p2);
+			if(p == p2)
+				disp_error_message("parse_syntax: expect space ' '",p);
 			// function - name
 			// function - name
 			func_name = p;
 			func_name = p;
 			p=skip_word(p);
 			p=skip_word(p);
@@ -1276,11 +1288,11 @@ const char* parse_syntax(const char* p) {
 		}
 		}
 		break;
 		break;
 	case 'i':
 	case 'i':
-		if(!strncasecmp(p,"if",2) && !ISALPHA(p[2])) {
+	case 'I':
+		if(p2 - p == 2 && !strncasecmp(p,"if",2)) {
 			// if() の処理
 			// if() の処理
 			char label[256];
 			char label[256];
-			p=skip_word(p);
-			p=skip_space(p);
+			p=skip_space(p2);
 			if(*p != '(') { //Prevent if this {} non-c syntax. from Rayce (jA)
 			if(*p != '(') { //Prevent if this {} non-c syntax. from Rayce (jA)
 				disp_error_message("need '('",p);
 				disp_error_message("need '('",p);
 			}
 			}
@@ -1300,11 +1312,11 @@ const char* parse_syntax(const char* p) {
 		}
 		}
 		break;
 		break;
 	case 's':
 	case 's':
-		if(!strncasecmp(p,"switch",6) && !ISALPHA(p[6])) {
+	case 'S':
+		if(p2 - p == 6 && !strncasecmp(p,"switch",6)) {
 			// switch() の処理
 			// switch() の処理
 			char label[256];
 			char label[256];
-			p=skip_word(p);
-			p=skip_space(p);
+			p=skip_space(p2);
 			if(*p != '(') {
 			if(*p != '(') {
 				disp_error_message("need '('",p);
 				disp_error_message("need '('",p);
 			}
 			}
@@ -1327,11 +1339,11 @@ const char* parse_syntax(const char* p) {
 		}
 		}
 		break;
 		break;
 	case 'w':
 	case 'w':
-		if(!strncasecmp(p,"while",5) && !ISALPHA(p[5])) {
+	case 'W':
+		if(p2 - p == 5 && !strncasecmp(p,"while",5)) {
 			int l;
 			int l;
 			char label[256];
 			char label[256];
-			p=skip_word(p);
-			p=skip_space(p);
+			p=skip_space(p2);
 			if(*p != '(') {
 			if(*p != '(') {
 				disp_error_message("need '('",p);
 				disp_error_message("need '('",p);
 			}
 			}
@@ -1383,7 +1395,8 @@ const char* parse_syntax_close_sub(const char* p,int* flag) {
 		*flag = 0;
 		*flag = 0;
 		return p;
 		return p;
 	} else if(syntax.curly[pos].type == TYPE_IF) {
 	} else if(syntax.curly[pos].type == TYPE_IF) {
-		const char *p2 = p;
+		const char *bp = p;
+		const char *p2;
 		// if 最終場所へ飛ばす
 		// if 最終場所へ飛ばす
 		sprintf(label,"goto __IF%x_FIN;",syntax.curly[pos].index);
 		sprintf(label,"goto __IF%x_FIN;",syntax.curly[pos].index);
 		syntax.curly[syntax.curly_count++].type = TYPE_NULL;
 		syntax.curly[syntax.curly_count++].type = TYPE_NULL;
@@ -1397,14 +1410,14 @@ const char* parse_syntax_close_sub(const char* p,int* flag) {
 
 
 		syntax.curly[pos].count++;
 		syntax.curly[pos].count++;
 		p = skip_space(p);
 		p = skip_space(p);
-		if(!syntax.curly[pos].flag && !strncasecmp(p,"else",4) && !ISALPHA(p[4])) {
+		p2 = skip_word(p);
+		if(!syntax.curly[pos].flag && p2 - p == 4 && !strncasecmp(p,"else",4)) {
 			// else  or else - if
 			// else  or else - if
-			p = skip_word(p);
-			p = skip_space(p);
-			if(!strncasecmp(p,"if",2) && !ISALPHA(p[2])) {
+			p = skip_space(p2);
+			p2 = skip_word(p);
+			if(p2 - p == 2 && !strncasecmp(p,"if",2)) {
 				// else - if
 				// else - if
-				p=skip_word(p);
-				p=skip_space(p);
+				p=skip_space(p2);
 				if(*p != '(') {
 				if(*p != '(') {
 					disp_error_message("need '('",p);
 					disp_error_message("need '('",p);
 				}
 				}
@@ -1434,7 +1447,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) {
 		set_label(l,script_pos,p);
 		set_label(l,script_pos,p);
 		if(syntax.curly[pos].flag == 1) {
 		if(syntax.curly[pos].flag == 1) {
 			// このifに対するelseじゃないのでポインタの位置は同じ
 			// このifに対するelseじゃないのでポインタの位置は同じ
-			return p2;
+			return bp;
 		}
 		}
 		return p;
 		return p;
 	} else if(syntax.curly[pos].type == TYPE_DO) {
 	} else if(syntax.curly[pos].type == TYPE_DO) {
@@ -1452,9 +1465,8 @@ const char* parse_syntax_close_sub(const char* p,int* flag) {
 		// 条件が偽なら終了地点に飛ばす
 		// 条件が偽なら終了地点に飛ばす
 		p = skip_space(p);
 		p = skip_space(p);
 		p2 = skip_word(p);
 		p2 = skip_word(p);
-		if(p2 - p != 5 || strncasecmp("while",p,5)) {
+		if(p2 - p != 5 || strncasecmp(p,"while",5))
 			disp_error_message("parse_syntax: need 'while'",p);
 			disp_error_message("parse_syntax: need 'while'",p);
-		}
 
 
 		p = skip_space(p2);
 		p = skip_space(p2);
 		if(*p != '(') {
 		if(*p != '(') {
@@ -1696,6 +1708,8 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 
 
 	if( setjmp( error_jump ) != 0 ) {
 	if( setjmp( error_jump ) != 0 ) {
 		//Restore program state when script has problems. [from jA]
 		//Restore program state when script has problems. [from jA]
+		int i;
+		const int size = sizeof(syntax.curly)/sizeof(syntax.curly[0]);
 		if( error_report )
 		if( error_report )
 			script_error(src,file,line,error_msg,error_pos);
 			script_error(src,file,line,error_msg,error_pos);
 		aFree( error_msg );
 		aFree( error_msg );
@@ -1703,9 +1717,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 		script_pos  = 0;
 		script_pos  = 0;
 		script_size = 0;
 		script_size = 0;
 		script_buf  = NULL;
 		script_buf  = NULL;
-		for(i=LABEL_START;i<str_num;i++){
+		for(i=LABEL_START;i<str_num;i++)
 			if(str_data[i].type == C_NOP) str_data[i].type = C_NAME;
 			if(str_data[i].type == C_NOP) str_data[i].type = C_NAME;
-		}
+		for(i=0; i<size; i++)
+			linkdb_final(&syntax.curly[i].case_label);
 		return NULL;
 		return NULL;
 	}
 	}
 
 

+ 8 - 1
src/map/status.c

@@ -418,7 +418,14 @@ void initChangeTables(void) {
 	StatusIconChangeTable[SC_INCSTR] = SI_INCSTR;
 	StatusIconChangeTable[SC_INCSTR] = SI_INCSTR;
 	StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT;
 	StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT;
 	StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION;
 	StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION;
-
+#if PACKETVER > 7
+	StatusIconChangeTable[SC_STRFOOD] = SI_FOODSTR;
+	StatusIconChangeTable[SC_AGIFOOD] = SI_FOODAGI;
+	StatusIconChangeTable[SC_VITFOOD] = SI_FOODVIT;
+	StatusIconChangeTable[SC_INTFOOD] = SI_FOODDEX;
+	StatusIconChangeTable[SC_DEXFOOD] = SI_FOODINT;
+	StatusIconChangeTable[SC_LUKFOOD] = SI_FOODLUK;
+#endif
 	//Other SC which are not necessarily associated to skills.
 	//Other SC which are not necessarily associated to skills.
 	StatusChangeFlagTable[SC_ASPDPOTION0] = SCB_ASPD;
 	StatusChangeFlagTable[SC_ASPDPOTION0] = SCB_ASPD;
 	StatusChangeFlagTable[SC_ASPDPOTION1] = SCB_ASPD;
 	StatusChangeFlagTable[SC_ASPDPOTION1] = SCB_ASPD;

+ 7 - 1
src/map/status.h

@@ -399,7 +399,13 @@ enum {
 	SI_BUNSINJYUTSU		= 207,
 	SI_BUNSINJYUTSU		= 207,
 	SI_NEN				= 208,
 	SI_NEN				= 208,
 	SI_ADJUSTMENT		= 209,
 	SI_ADJUSTMENT		= 209,
-	SI_ACCURACY			= 210
+	SI_ACCURACY			= 210,
+	SI_FOODSTR			= 241,
+	SI_FOODAGI			= 242,
+	SI_FOODVIT			= 243,
+	SI_FOODDEX			= 244,
+	SI_FOODINT			= 245,
+	SI_FOODLUK			= 246,
 };
 };
 
 
 // JOINTBEAT stackable ailments
 // JOINTBEAT stackable ailments