Ver código fonte

Fixed bugreport:5740 var reference was not being restored to call buildin_set on assignment statements.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16300 54d463be-8e91-2dee-dedb-b68131a5f0ec
greenboxal2 13 anos atrás
pai
commit
30e0f39055
2 arquivos alterados com 31 adições e 3 exclusões
  1. 29 3
      src/map/script.c
  2. 2 0
      src/map/script.h

+ 29 - 3
src/map/script.c

@@ -1174,6 +1174,8 @@ const char* parse_variable(const char* p)
 		add_scriptl(word);
 	}
 	
+	add_scriptc(C_REF);
+
 	if( type == C_ADD_PP || type == C_SUB_PP )
 	{// incremental operator for the method
 		add_scripti(1);
@@ -3209,12 +3211,22 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
 /// Binary operators
 void op_2(struct script_state *st, int op)
 {
-	struct script_data* left;
+	struct script_data* left, leftref;
 	struct script_data* right;
 
+	leftref.type = C_NOP;
+
 	left = script_getdatatop(st, -2);
 	right = script_getdatatop(st, -1);
 
+	if (st->op2ref)
+	{
+		if (data_isreference(left))
+			leftref = *left;
+
+		st->op2ref = 0;
+	}
+
 	get_val(st, left);
 	get_val(st, right);
 
@@ -3236,14 +3248,24 @@ void op_2(struct script_state *st, int op)
 	if( data_isstring(left) && data_isstring(right) )
 	{// ss => op_2str
 		op_2str(st, op, left->u.str, right->u.str);
-		script_removetop(st, -3, -1);// pop the two values before the top one
+		script_removetop(st, leftref.type == C_NOP ? -3 : -2, -1);// pop the two values before the top one
+
+		if (leftref.type != C_NOP)
+		{
+			aFree(left->u.str);
+			*left = leftref;
+		}
 	}
 	else if( data_isint(left) && data_isint(right) )
 	{// ii => op_2num
 		int i1 = left->u.num;
 		int i2 = right->u.num;
-		script_removetop(st, -2, 0);
+
+		script_removetop(st, leftref.type == C_NOP ? -2 : -1, 0);
 		op_2num(st, op, i1, i2);
+
+		if (leftref.type != C_NOP)
+			*left = leftref;
 	}
 	else
 	{// invalid argument
@@ -3685,6 +3707,10 @@ void run_script_main(struct script_state *st)
 			}
 			break;
 
+		case C_REF:
+			st->op2ref = 1;
+			break;
+
 		case C_NEG:
 		case C_NOT:
 		case C_LNOT:

+ 2 - 0
src/map/script.h

@@ -47,6 +47,7 @@ typedef enum c_op {
 	C_RETINFO,
 	C_USERFUNC, // internal script function
 	C_USERFUNC_POS, // internal script function label
+	C_REF, // the next call to c_op2 should push back a ref to the left operand
 
 	// operators
 	C_OP3, // a ? b : c
@@ -130,6 +131,7 @@ struct script_state {
 	struct script_state *bk_st;
 	int bk_npcid;
 	unsigned freeloop : 1;// used by buildin_freeloop
+	unsigned op2ref : 1;// used by op_2
 };
 
 struct script_reg {