summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgreenboxal2 <greenboxal2@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-06-15 00:30:20 +0000
committergreenboxal2 <greenboxal2@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-06-15 00:30:20 +0000
commit22d2718db209b1d75a75b4976b882ed659d22ee5 (patch)
treee5450a75b4d9feb15534e08799b5dad3902610b0
parent7b1562b07d55a2712021803eab923200d6891494 (diff)
downloadhercules-22d2718db209b1d75a75b4976b882ed659d22ee5.tar.gz
hercules-22d2718db209b1d75a75b4976b882ed659d22ee5.tar.bz2
hercules-22d2718db209b1d75a75b4976b882ed659d22ee5.tar.xz
hercules-22d2718db209b1d75a75b4976b882ed659d22ee5.zip
Fixed bugreport:5740 var reference was not being restored to call buildin_set on assignment statements.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16300 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--src/map/script.c32
-rw-r--r--src/map/script.h2
2 files changed, 31 insertions, 3 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 9d683850c..8c3ce0e1f 100644
--- a/src/map/script.c
+++ b/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:
diff --git a/src/map/script.h b/src/map/script.h
index 4d7754241..eed4c20c8 100644
--- a/src/map/script.h
+++ b/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 {