Browse Source

- Replaced our fix for "mes ();" crashing by jA's version. see trunk[8867] and stable[8927]
- Merged the fix for & having the same precedence as << and >> from jA.
- Merged the C_OP3 operator from jA: test ? if_true : if_false

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

FlavioJS 18 years ago
parent
commit
78b52bbb4b
2 changed files with 100 additions and 59 deletions
  1. 3 0
      Changelog-Trunk.txt
  2. 97 59
      src/map/script.c

+ 3 - 0
Changelog-Trunk.txt

@@ -4,6 +4,9 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2006/12/20
+	* Replaced our fix for "mes ();" crashing by jA's version.
+	* Merged the fix for & having the same precedence as << and >> from jA.
+	* Merged the C_OP3 operator from jA: test ? if_true : if_false
 	* Changed the script source from unsigned char* to const char*.
 	* Updated plugins Makefile. [FlavioJS]
 2006/12/19

+ 97 - 59
src/map/script.c

@@ -163,7 +163,7 @@ enum {
 	C_NAME,C_EOL, C_RETINFO,
 	C_USERFUNC, C_USERFUNC_POS, // user defined functions
 
-	C_LOR,C_LAND,C_LE,C_LT,C_GE,C_GT,C_EQ,C_NE,   //operator
+	C_OP3,C_LOR,C_LAND,C_LE,C_LT,C_GE,C_GT,C_EQ,C_NE,   //operator
 	C_XOR,C_OR,C_AND,C_ADD,C_SUB,C_MUL,C_DIV,C_MOD,C_NEG,C_LNOT,C_NOT,C_R_SHIFT,C_L_SHIFT
 };
 
@@ -344,7 +344,7 @@ static void check_script_buf(int size)
 {
 	if(script_pos+size>=script_size){
 		script_size+=SCRIPT_BLOCK_SIZE;
-		script_buf=(unsigned char *)aRealloc(script_buf,script_size);
+		RECREATE(script_buf,unsigned char,script_size);
 		malloc_tsetdword(script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0',
 			SCRIPT_BLOCK_SIZE);
 	}
@@ -355,7 +355,7 @@ static void check_script_buf(int size)
  *------------------------------------------
  */
  
-#define add_scriptb(a) if( script_pos+1>=script_size ) check_script_buf(1); script_buf[script_pos++]=(uint8)(a);
+#define add_scriptb(a) if( script_pos+1>=script_size ) check_script_buf(1); script_buf[script_pos++]=(uint8)(a)
 
 #if 0
 static void add_scriptb(int a)
@@ -479,7 +479,7 @@ static const char *skip_space(const char *p)
 			if(*p)
 				++p;
 			else
-				disp_error_message("reached end of streams while matching \"*/\"",p);
+				disp_error_message("unexpected eof @ block comment",p);
 		} else
 			break;
 	}
@@ -646,35 +646,39 @@ const char* parse_subexpr(const char* p,int limit)
 	}
 	tmpp=p;
 	if((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')){
-		p=parse_subexpr(p+1,8);
+		p=parse_subexpr(p+1,10);
 		add_scriptc(op);
 	} else
 		p=parse_simpleexpr(p);
 	p=skip_space(p);
 	while((
-			(op=C_ADD,opl=6,len=1,*p=='+') ||
-		   (op=C_SUB,opl=6,len=1,*p=='-') ||
-		   (op=C_MUL,opl=7,len=1,*p=='*') ||
-		   (op=C_DIV,opl=7,len=1,*p=='/') ||
-		   (op=C_MOD,opl=7,len=1,*p=='%') ||
-		   (op=C_FUNC,opl=9,len=1,*p=='(') ||
-		   (op=C_LAND,opl=1,len=2,*p=='&' && p[1]=='&') ||
-		   (op=C_AND,opl=5,len=1,*p=='&') ||
-		   (op=C_LOR,opl=0,len=2,*p=='|' && p[1]=='|') ||
-		   (op=C_OR,opl=4,len=1,*p=='|') ||
-		   (op=C_XOR,opl=3,len=1,*p=='^') ||
-		   (op=C_EQ,opl=2,len=2,*p=='=' && p[1]=='=') ||
-		   (op=C_NE,opl=2,len=2,*p=='!' && p[1]=='=') ||
-		   (op=C_R_SHIFT,opl=5,len=2,*p=='>' && p[1]=='>') ||
-		   (op=C_GE,opl=2,len=2,*p=='>' && p[1]=='=') ||
-		   (op=C_GT,opl=2,len=1,*p=='>') ||
-		   (op=C_L_SHIFT,opl=5,len=2,*p=='<' && p[1]=='<') ||
-		   (op=C_LE,opl=2,len=2,*p=='<' && p[1]=='=') ||
-		   (op=C_LT,opl=2,len=1,*p=='<')) && opl>limit){
+			(op=C_OP3,opl=0,len=1,*p=='?') ||
+			(op=C_ADD,opl=8,len=1,*p=='+') ||
+			(op=C_SUB,opl=8,len=1,*p=='-') ||
+			(op=C_MUL,opl=9,len=1,*p=='*') ||
+			(op=C_DIV,opl=9,len=1,*p=='/') ||
+			(op=C_MOD,opl=9,len=1,*p=='%') ||
+			(op=C_FUNC,opl=11,len=1,*p=='(') ||
+			(op=C_LAND,opl=2,len=2,*p=='&' && p[1]=='&') ||
+			(op=C_AND,opl=6,len=1,*p=='&') ||
+			(op=C_LOR,opl=1,len=2,*p=='|' && p[1]=='|') ||
+			(op=C_OR,opl=5,len=1,*p=='|') ||
+			(op=C_XOR,opl=4,len=1,*p=='^') ||
+			(op=C_EQ,opl=3,len=2,*p=='=' && p[1]=='=') ||
+			(op=C_NE,opl=3,len=2,*p=='!' && p[1]=='=') ||
+			(op=C_R_SHIFT,opl=7,len=2,*p=='>' && p[1]=='>') ||
+			(op=C_GE,opl=3,len=2,*p=='>' && p[1]=='=') ||
+			(op=C_GT,opl=3,len=1,*p=='>') ||
+			(op=C_L_SHIFT,opl=7,len=2,*p=='<' && p[1]=='<') ||
+			(op=C_LE,opl=3,len=2,*p=='<' && p[1]=='=') ||
+			(op=C_LT,opl=3,len=1,*p=='<')) && opl>limit){
 		p+=len;
 		if(op==C_FUNC){
-			int i=0,func=parse_cmd;
+			int i=0;
+			int j=0;
+			int func=parse_cmd;
 			const char *plist[128];
+			const char *arg = NULL;
 
 			if(str_data[parse_cmd].type == C_FUNC){
 				// 通常の関数
@@ -686,35 +690,46 @@ const char* parse_subexpr(const char* p,int limit)
 			} else
 				disp_error_message("expect command, missing function name or calling undeclared function",tmpp);
 			func=parse_cmd;
-			if( *p == '(' && *(plist[i]=skip_space(p+1)) == ')' ){
-				p=plist[i]+1; // empty argument list
-			} else
+			p=skip_space(p);
+
+			// check number of arguments of the function
+			if( str_data[func].type == C_FUNC && script_config.warn_cmd_mismatch_paramnum) {
+				arg = buildin_func[str_data[func].val].arg;
+				for(j=0; arg[j]; j++) {
+					if(arg[j] == '*')
+						break;
+				}
+			}
+
 			while(*p && *p!=')' && i<128) {
 				plist[i]=p;
 				p=parse_subexpr(p,-1);
 				p=skip_space(p);
-				if(*p==',') p++;
+				if(*p==',') {
+					if(arg == NULL || arg[j] == '*' || i+1 < j)
+						p++; // the next argument is valid, skip the comma
+				}
 				else if(*p!=')' && script_config.warn_func_no_comma){
 					disp_error_message("expect ',' or ')' at func params",p);
 				}
 				p=skip_space(p);
 				i++;
-			};
+			}
 			plist[i]=p;
 			if(*(p++)!=')'){
 				disp_error_message("func request '(' ')'",p);
-				exit(1);
+				//exit(1);
 			}
-
-			if( str_data[func].type==C_FUNC && script_config.warn_func_mismatch_paramnum){
-				const char *arg = buildin_func[str_data[func].val].arg;
-				int j = 0;
-				for (; arg[j]; j++)
-					if (arg[j] == '*')
-						break;
-				if (!(i <= 1 && j == 0) && ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j)))
+			if(arg) {
+				if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) )
 					disp_error_message("illegal number of parameters",plist[min(i,j)]);
 			}
+		} else if(op == C_OP3) {
+			p=parse_subexpr(p,-1);
+			p=skip_space(p);
+			if( *(p++) != ':')
+				disp_error_message("need ':'", p);
+			p=parse_subexpr(p,-1);
 		} else {
 			p=parse_subexpr(p,opl);
 		}
@@ -744,14 +759,6 @@ const char* parse_expr(const char *p)
 		disp_error_message("unexpected char",p);
 		exit(1);
 	}
-	/*
-	if(*p == '(') {
-		const char *p2 = skip_space(p + 1);
-		if(*p2 == ')') {
-			return p2 + 1;
-		}
-	}
-	*/
 	p=parse_subexpr(p,-1);
 #ifdef DEBUG_FUNCIN
 	if(battle_config.etc_log)
@@ -767,9 +774,11 @@ const char* parse_expr(const char *p)
 const char* parse_line(const char* p)
 {
 	int i=0;
+	int j=0;
 	int cmd;
 	const char* plist[128];
 	const char* p2;
+	const char *arg=NULL;
 	char end;
 
 	p=skip_space(p);
@@ -820,17 +829,26 @@ const char* parse_line(const char* p)
 		end = ';';
 	}
 
-	if( p && *p == '(' && *(p2=(char *)skip_space(p+1)) == ')' ){
-		p= p2+1; // empty argument list
-	} else
+	// Check number of arguments of the function
+	if( str_data[cmd].type == C_FUNC && script_config.warn_cmd_mismatch_paramnum) {
+		arg = buildin_func[str_data[cmd].val].arg;
+		for(j=0; arg[j]; j++) {
+			if(arg[j] == '*')
+				break;
+		}
+	}
+
 	while(p && *p && *p != end && i<128){
 		plist[i]=p;
 
 		p=parse_expr(p);
 		p=skip_space(p);
 		// 引数区切りの,処理
-		if(*p==',') p++;
-		else if(*p!=end && script_config.warn_cmd_no_comma && 0 <= i ){
+		if(*p==',') {
+			if(arg == NULL || arg[j] == '*' || i+1 < j)
+				p++; // the next argument is valid, skip the comma
+		}
+		else if(*p!=end && script_config.warn_cmd_no_comma){
 			if(parse_syntax_for_flag) {
 				disp_error_message("expect ',' or ')' at cmd params",p);
 			} else {
@@ -840,7 +858,7 @@ const char* parse_line(const char* p)
 		p=skip_space(p);
 		i++;
 	}
-	plist[i]=(char *) p;
+	plist[i]=p;
 	if(!p || *(p++)!=end){
 		if(parse_syntax_for_flag) {
 			disp_error_message("need ')'",p);
@@ -853,12 +871,7 @@ const char* parse_line(const char* p)
 	// if, for , while の閉じ判定
 	p = parse_syntax_close(p);
 
-	if( str_data[cmd].type==C_FUNC && script_config.warn_cmd_mismatch_paramnum){
-		const char *arg=buildin_func[str_data[cmd].val].arg;
-		int j;
-		for(j=0;arg[j];j++)
-			if(arg[j]=='*')
-				break;
+	if(arg) {
 		if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) )
 			disp_error_message("illegal number of parameters",plist[min(i,j)]);
 	}
@@ -2172,6 +2185,27 @@ int isstr(struct script_data *c) {
 	return 0;
 }
 
+/*==========================================
+ * Three-section operator
+ * test ? if_true : if_false
+ *------------------------------------------
+ */
+void op_3(struct script_state *st) {
+	int flag = 0;
+	if( isstr(&st->stack->stack_data[st->stack->sp-3])) {
+		char *str = conv_str(st,& (st->stack->stack_data[st->stack->sp-3]));
+		flag = str[0];
+	} else {
+		flag = conv_num(st,& (st->stack->stack_data[st->stack->sp-3]));
+	}
+	if( flag ) {
+		push_copy(st->stack, st->stack->sp-2 );
+	} else {
+		push_copy(st->stack, st->stack->sp-1 );
+	}
+	pop_stack(st->stack,st->stack->sp-4,st->stack->sp-1);
+}
+
 /*==========================================
  * 加算演算子
  *------------------------------------------
@@ -2687,6 +2721,10 @@ void run_script_main(struct script_state *st)
 			op_1num(st,c);
 			break;
 
+		case C_OP3:
+			op_3(st);
+			break;
+
 		case C_NOP:
 			st->state=END;
 			break;