summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-02-24 17:35:23 +0100
committerHaru <haru@dotalux.com>2014-03-05 22:35:03 +0100
commit4f3156b78f807553b11f37a7d0c898f6e358495b (patch)
tree1a329c6b4b17f2b6ae4ba113f494efbd67d3c996
parentd25cc9b7dbc103cf1454db37159ffffeedaac149 (diff)
downloadhercules-4f3156b78f807553b11f37a7d0c898f6e358495b.tar.gz
hercules-4f3156b78f807553b11f37a7d0c898f6e358495b.tar.bz2
hercules-4f3156b78f807553b11f37a7d0c898f6e358495b.tar.xz
hercules-4f3156b78f807553b11f37a7d0c898f6e358495b.zip
Ref redesign, part 3
- Updated several functions to properly use the data structures defined in parts 1 and 2. - Special thanks to Ind for his help on this, as well as the previous two parts. - Fixes some crashes related to variable references passed back and forth between nested callfunc/callsub scopes (related: 2669e9a, 3259f89, 4f2de07) Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/map/mapreg_sql.c8
-rw-r--r--src/map/pc.c20
-rw-r--r--src/map/script.c253
-rw-r--r--src/map/script.h26
4 files changed, 152 insertions, 155 deletions
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index bdda652b8..61c25f24e 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -64,7 +64,7 @@ bool mapreg_setreg(int64 uid, int val) {
}
} else {
if( i )
- script->array_update(&mapreg->regs.arrays, uid, false);
+ script->array_update(&mapreg->regs, uid, false);
m = ers_alloc(mapreg->ers, struct mapreg_save);
@@ -83,7 +83,7 @@ bool mapreg_setreg(int64 uid, int val) {
}
} else { // val == 0
if( i )
- script->array_update(&mapreg->regs.arrays, uid, true);
+ script->array_update(&mapreg->regs, uid, true);
if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
ers_free(mapreg->ers, m);
}
@@ -113,7 +113,7 @@ bool mapreg_setregstr(int64 uid, const char* str) {
if( str == NULL || *str == 0 ) {
if( i )
- script->array_update(&mapreg->regs.arrays, uid, true);
+ script->array_update(&mapreg->regs, uid, true);
if(name[1] != '@') {
if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg->table, name, i) )
Sql_ShowDebug(map->mysql_handle);
@@ -135,7 +135,7 @@ bool mapreg_setregstr(int64 uid, const char* str) {
}
} else {
if( i )
- script->array_update(&mapreg->regs.arrays, uid, false);
+ script->array_update(&mapreg->regs, uid, false);
m = ers_alloc(mapreg->ers, struct mapreg_save);
diff --git a/src/map/pc.c b/src/map/pc.c
index ff152b556..87f14bcd9 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -8127,11 +8127,11 @@ void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
if( val ) {
i64db_iput(sd->regs.vars, reg, val);
if( index )
- script->array_update(&sd->regs.arrays, reg, false);
+ script->array_update(&sd->regs, reg, false);
} else {
i64db_remove(sd->regs.vars, reg);
if( index )
- script->array_update(&sd->regs.arrays, reg, true);
+ script->array_update(&sd->regs, reg, true);
}
}
@@ -8166,7 +8166,7 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
ers_free(pc->str_reg_ers, p);
} else {
if( index )
- script->array_update(&sd->regs.arrays, reg, false);
+ script->array_update(&sd->regs, reg, false);
}
} else {
if( sd->regs.vars->remove(sd->regs.vars, DB->i642key(reg), &prev) ) {
@@ -8175,7 +8175,7 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
aFree(p->value);
ers_free(pc->str_reg_ers, p);
if( index )
- script->array_update(&sd->regs.arrays, reg, true);
+ script->array_update(&sd->regs, reg, true);
}
}
}
@@ -8265,12 +8265,12 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
if( (p = i64db_get(sd->regs.vars, reg) ) ) {
if( val ) {
if( !p->value && index ) /* its a entry that was deleted, so we reset array */
- script->array_update(&sd->regs.arrays, reg, false);
+ script->array_update(&sd->regs, reg, false);
p->value = val;
} else {
p->value = 0;
if( index )
- script->array_update(&sd->regs.arrays, reg, true);
+ script->array_update(&sd->regs, reg, true);
}
if( !pc->reg_load )
p->flag.update = 1;/* either way, it will require either delete or replace */
@@ -8278,7 +8278,7 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
DBData prev;
if( index )
- script->array_update(&sd->regs.arrays, reg, false);
+ script->array_update(&sd->regs, reg, false);
p = ers_alloc(pc->num_reg_ers, struct script_reg_num);
@@ -8318,12 +8318,12 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
if( p->value )
aFree(p->value);
else if ( index ) /* a entry that was deleted, so we reset */
- script->array_update(&sd->regs.arrays, reg, false);
+ script->array_update(&sd->regs, reg, false);
p->value = aStrdup(val);
} else {
p->value = NULL;
if( index )
- script->array_update(&sd->regs.arrays, reg, true);
+ script->array_update(&sd->regs, reg, true);
}
if( !pc->reg_load )
p->flag.update = 1;/* either way, it will require either delete or replace */
@@ -8331,7 +8331,7 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
DBData prev;
if( index )
- script->array_update(&sd->regs.arrays, reg, false);
+ script->array_update(&sd->regs, reg, false);
p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
diff --git a/src/map/script.c b/src/map/script.c
index c989c06a8..bf6dd448a 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2461,9 +2461,9 @@ TBL_PC *script_rid2sd(struct script_state *st) {
/**
* Dereferences a variable/constant, replacing it with a copy of the value.
*
- * @param st Script state
- * @param data Variable/constant
- * @return pointer to data, for convenience
+ * @param st[in] script state.
+ * @param data[in,out] variable/constant.
+ * @return pointer to data, for convenience.
*/
struct script_data *get_val(struct script_state* st, struct script_data* data) {
const char* name;
@@ -2513,7 +2513,7 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
case '.':
{
struct DBMap* n = data->ref ?
- *data->ref : name[1] == '@' ?
+ data->ref->vars : name[1] == '@' ?
st->stack->scope.vars : // instance/scope variable
st->script->local.vars; // npc variable
if( n )
@@ -2568,7 +2568,7 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
case '.':
{
struct DBMap* n = data->ref ?
- *data->ref : name[1] == '@' ?
+ data->ref->vars : name[1] == '@' ?
st->stack->scope.vars : // instance/scope variable
st->script->local.vars; // npc variable
if( n )
@@ -2591,13 +2591,22 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
}
}
+ data->ref = NULL;
return data;
}
-/// Retrieves the value of a reference identified by uid (variable, constant, param)
-/// The value is left in the top of the stack and needs to be removed manually.
-void* get_val2(struct script_state* st, int64 uid, struct DBMap** ref) {
+/**
+ * Retrieves the value of a reference identified by uid (variable, constant, param)
+ *
+ * The value is left in the top of the stack and needs to be removed manually.
+ *
+ * @param st[in] script state.
+ * @param uid[in] reference identifier.
+ * @param ref[in] the container to look up the reference into.
+ * @return the retrieved value of the reference.
+ */
+void* get_val2(struct script_state* st, int64 uid, struct reg_db *ref) {
struct script_data* data;
script->push_val(st->stack, C_NAME, uid, ref);
data = script_getdatatop(st, -1);
@@ -2608,9 +2617,9 @@ void* get_val2(struct script_state* st, int64 uid, struct DBMap** ref) {
* Because, currently, array members with key 0 are indifferenciable from normal variables, we should ensure its actually in
* Will be gone as soon as undefined var feature is implemented
**/
-void script_array_ensure_zero(struct script_state *st, struct map_session_data *sd, int64 uid, struct DBMap** ref) {
+void script_array_ensure_zero(struct script_state *st, struct map_session_data *sd, int64 uid, struct reg_db *ref) {
const char *name = script->get_str(script_getvarid(uid));
- struct DBMap *src = script->array_src(st, sd ? sd : st->rid ? map->id2sd(st->rid) : NULL, name, ref);
+ struct reg_db *src = script->array_src(st, sd ? sd : st->rid ? map->id2sd(st->rid) : NULL, name, ref);
struct script_array *sa = NULL;
bool insert = false;
@@ -2630,8 +2639,8 @@ void script_array_ensure_zero(struct script_state *st, struct map_session_data *
}
}
- if( src ) {
- if( (sa = idb_get(src, script_getvarid(uid)) ) ) {
+ if( src && src->arrays ) {
+ if( (sa = idb_get(src->arrays, script_getvarid(uid)) ) ) {
unsigned int i;
ARR_FIND(0, sa->size, i, sa->members[i] == 0);
@@ -2643,36 +2652,36 @@ void script_array_ensure_zero(struct script_state *st, struct map_session_data *
script->array_add_member(sa,0);
} else if( insert ) {
- script->array_update(&src,reference_uid(script_getvarid(uid), 0),false);
+ script->array_update(src,reference_uid(script_getvarid(uid), 0),false);
}
}
}
/**
* Returns array size by ID
**/
-unsigned int script_array_size(struct script_state *st, struct map_session_data *sd, const char *name, struct DBMap **ref) {
+unsigned int script_array_size(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
struct script_array *sa = NULL;
- struct DBMap *src = script->array_src(st, sd, name, ref);
+ struct reg_db *src = script->array_src(st, sd, name, ref);
- if( src )
- sa = idb_get(src, script->search_str(name));
+ if( src && src->arrays )
+ sa = idb_get(src->arrays, script->search_str(name));
return sa ? sa->size : 0;
}
/**
* Returns array's highest key (for that awful getarraysize implementation that doesn't really gets the array size)
**/
-unsigned int script_array_highest_key(struct script_state *st, struct map_session_data *sd, const char *name, struct DBMap **ref) {
+unsigned int script_array_highest_key(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
struct script_array *sa = NULL;
- struct DBMap *src = script->array_src(st, sd, name, ref);
+ struct reg_db *src = script->array_src(st, sd, name, ref);
- if( src ) {
+ if( src && src->arrays ) {
int key = script->add_word(name);
script->array_ensure_zero(st,sd,reference_uid(key, 0),ref);
- if( ( sa = idb_get(src, key) ) ) {
+ if( ( sa = idb_get(src->arrays, key) ) ) {
unsigned int i, highest_key = 0;
for(i = 0; i < sa->size; i++) {
@@ -2695,9 +2704,9 @@ int script_free_array_db(DBKey key, DBData *data, va_list ap) {
/**
* Clears script_array and removes it from script->array_db
**/
-void script_array_delete(struct DBMap *src, struct script_array *sa) {
+void script_array_delete(struct reg_db *src, struct script_array *sa) {
aFree(sa->members);
- idb_remove(src, sa->id);
+ idb_remove(src->arrays, sa->id);
ers_free(script->array_ers, sa);
}
/**
@@ -2705,7 +2714,7 @@ void script_array_delete(struct DBMap *src, struct script_array *sa) {
*
* @param idx the index of the member in script_array struct list, not of the actual array member
**/
-void script_array_remove_member(struct DBMap *src,struct script_array *sa, unsigned int idx) {
+void script_array_remove_member(struct reg_db *src, struct script_array *sa, unsigned int idx) {
unsigned int i, cursor;
/* its the only member left, no need to do anything other than delete the array data */
@@ -2742,54 +2751,59 @@ void script_array_add_member(struct script_array *sa, unsigned int idx) {
* Obtains the source of the array database for this type and scenario
* Initializes such database when not yet initialised.
**/
-struct DBMap *script_array_src(struct script_state *st, struct map_session_data *sd, const char *name, struct DBMap **ref) {
- struct DBMap **src = NULL;
+struct reg_db *script_array_src(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
+ struct reg_db *src = NULL;
switch( name[0] ) {
/* from player */
default: /* char reg */
case '@':/* temp char reg */
case '#':/* account reg */
- src = &sd->regs.arrays;
+ src = &sd->regs;
break;
case '$':/* map reg */
- src = &mapreg->regs.arrays;
+ src = &mapreg->regs;
break;
case '.':/* npc/script */
if( ref )
- src = (struct DBMap **)((char *)ref + sizeof(struct DBMap *));
+ src = ref;
else
- src = (name[1] == '@') ? &st->stack->scope.arrays : &st->script->local.arrays;
+ src = (name[1] == '@') ? &st->stack->scope : &st->script->local;
break;
case '\'':/* instance */
if( st->instance_id >= 0 ) {
- src = &instance->list[st->instance_id].regs.arrays;
+ src = &instance->list[st->instance_id].regs;
}
break;
}
if( src ) {
- if( !*src )
- *src = idb_alloc(DB_OPT_BASE);
- return *src;
+ if( !src->arrays )
+ src->arrays = idb_alloc(DB_OPT_BASE);
+ return src;
}
return NULL;
}
+
/**
* Processes a array member modification, and update data accordingly
+ *
+ * @param src[in,out] Variable source database. If the array database doesn't exist, it is created.
+ * @param num[in] Variable ID
+ * @param empty[in] Whether the modified member is empty (needs to be removed)
**/
-void script_array_update(struct DBMap **src, int64 num, bool empty) {
+void script_array_update(struct reg_db *src, int64 num, bool empty) {
struct script_array *sa = NULL;
int id = script_getvarid(num);
unsigned int index = script_getvaridx(num);
- if( !*src ) {
- *src = idb_alloc(DB_OPT_BASE);
+ if (!src->arrays) {
+ src->arrays = idb_alloc(DB_OPT_BASE);
} else {
- sa = idb_get(*src, id);
+ sa = idb_get(src->arrays, id);
}
-
+
if( sa ) {
unsigned int i;
@@ -2803,7 +2817,7 @@ void script_array_update(struct DBMap **src, int64 num, bool empty) {
if( i != sa->size ) {
/* if empty, we gotta remove it */
if( empty ) {
- script->array_remove_member(*src,sa,i);
+ script->array_remove_member(src, sa, i);
}
} else if( !empty ) { /* new entry */
script->array_add_member(sa,index);
@@ -2815,15 +2829,25 @@ void script_array_update(struct DBMap **src, int64 num, bool empty) {
sa->members = NULL;
sa->size = 0;
script->array_add_member(sa,index);
- idb_put(*src, id, sa);
+ idb_put(src->arrays, id, sa);
}
}
-/*==========================================
+
+/**
* Stores the value of a script variable
- * Return value is 0 on fail, 1 on success.
+ *
+ * @param st current script state.
+ * @param sd current character data.
+ * @param num variable identifier.
+ * @param name variable name.
+ * @param value new value.
+ * @param ref variable container, in case of a npc/scope variable reference outside the current scope.
+ * @retval 0 failure.
+ * @retval 1 success.
+ *
* TODO: return values are screwed up, have been for some time (reaad: years), e.g. some functions return 1 failure and success.
*------------------------------------------*/
-int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, const void* value, struct DBMap** ref) {
+int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, const void* value, struct reg_db *ref) {
char prefix = name[0];
if( is_string_variable(name) ) {// string variable
@@ -2841,27 +2865,16 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co
pc_setaccountregstr(sd, num, str);
case '.':
{
- struct DBMap* n;
- n = (ref) ? *ref : (name[1] == '@') ? st->stack->scope.vars : st->script->local.vars;
+ struct reg_db *n = (ref) ? ref : (name[1] == '@') ? &st->stack->scope : &st->script->local;
if( n ) {
if (str[0]) {
- i64db_put(n, num, aStrdup(str));
+ i64db_put(n->vars, num, aStrdup(str));
if( script_getvaridx(num) )
- script->array_update(
- (name[1] == '@') ?
- &st->stack->scope.arrays :
- &st->script->local.arrays,
- num,
- false);
+ script->array_update(n, num, false);
} else {
- i64db_remove(n, num);
+ i64db_remove(n->vars, num);
if( script_getvaridx(num) )
- script->array_update(
- (name[1] == '@') ?
- &st->stack->scope.arrays :
- &st->script->local.arrays,
- num,
- true);
+ script->array_update(n, num, true);
}
}
}
@@ -2871,11 +2884,11 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co
if( str[0] ) {
i64db_put(instance->list[st->instance_id].regs.vars, num, aStrdup(str));
if( script_getvaridx(num) )
- script->array_update(&instance->list[st->instance_id].regs.arrays, num, false);
+ script->array_update(&instance->list[st->instance_id].regs, num, false);
} else {
i64db_remove(instance->list[st->instance_id].regs.vars, num);
if( script_getvaridx(num) )
- script->array_update(&instance->list[st->instance_id].regs.arrays, num, true);
+ script->array_update(&instance->list[st->instance_id].regs, num, true);
}
} else {
ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name);
@@ -2912,27 +2925,16 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co
pc_setaccountreg(sd, num, val);
case '.':
{
- struct DBMap* n;
- n = (ref) ? *ref : (name[1] == '@') ? st->stack->scope.vars : st->script->local.vars;
+ struct reg_db *n = (ref) ? ref : (name[1] == '@') ? &st->stack->scope : &st->script->local;
if( n ) {
if( val != 0 ) {
- i64db_iput(n, num, val);
+ i64db_iput(n->vars, num, val);
if( script_getvaridx(num) )
- script->array_update(
- (name[1] == '@') ?
- &st->stack->scope.arrays :
- &st->script->local.arrays,
- num,
- false);
+ script->array_update(n, num, false);
} else {
- i64db_remove(n, num);
+ i64db_remove(n->vars, num);
if( script_getvaridx(num) )
- script->array_update(
- (name[1] == '@') ?
- &st->stack->scope.arrays :
- &st->script->local.arrays,
- num,
- true);
+ script->array_update(n, num, true);
}
}
}
@@ -2942,11 +2944,11 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co
if( val != 0 ) {
i64db_iput(instance->list[st->instance_id].regs.vars, num, val);
if( script_getvaridx(num) )
- script->array_update(&instance->list[st->instance_id].regs.arrays, num, false);
+ script->array_update(&instance->list[st->instance_id].regs, num, false);
} else {
i64db_remove(instance->list[st->instance_id].regs.vars, num);
if( script_getvaridx(num) )
- script->array_update(&instance->list[st->instance_id].regs.arrays, num, true);
+ script->array_update(&instance->list[st->instance_id].regs, num, true);
}
} else {
ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name);
@@ -2963,8 +2965,7 @@ int set_var(TBL_PC* sd, char* name, void* val) {
return script->set_reg(NULL, sd, reference_uid(script->add_str(name),0), name, val, NULL);
}
-void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct DBMap **ref)
-{
+void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct reg_db *ref) {
script->set_reg(st, sd, reference_uid(script->add_str(varname),elem), varname, value, ref);
}
@@ -3071,7 +3072,7 @@ void stack_expand(struct script_stack* stack) {
}
/// Pushes a value into the stack (with reference)
-struct script_data* push_val(struct script_stack* stack, enum c_op type, int64 val, struct DBMap** ref) {
+struct script_data* push_val(struct script_stack* stack, enum c_op type, int64 val, struct reg_db *ref) {
if( stack->sp >= stack->sp_max )
script->stack_expand(stack);
stack->stack_data[stack->sp].type = type;
@@ -3094,8 +3095,7 @@ struct script_data* push_str(struct script_stack* stack, enum c_op type, char* s
}
/// Pushes a retinfo into the stack
-struct script_data* push_retinfo(struct script_stack* stack, struct script_retinfo* ri, DBMap **ref)
-{
+struct script_data* push_retinfo(struct script_stack* stack, struct script_retinfo* ri, struct reg_db *ref) {
if( stack->sp >= stack->sp_max )
script->stack_expand(stack);
stack->stack_data[stack->sp].type = C_RETINFO;
@@ -3157,7 +3157,7 @@ void pop_stack(struct script_state* st, int start, int end)
ri->scope.vars = NULL;
}
if( ri->scope.arrays ) {
- script->free_vars(ri->scope.arrays);
+ ri->scope.arrays->destroy(ri->scope.arrays,script->array_free_db);
ri->scope.arrays = NULL;
}
if( data->ref )
@@ -3275,7 +3275,7 @@ void script_free_state(struct script_state* st) {
st->script->local.vars = NULL;
}
if( st->script->local.arrays && !db_size(st->script->local.arrays) ) {
- script->free_vars(st->script->local.arrays);
+ st->script->local.arrays->destroy(st->script->local.arrays,script->array_free_db);
st->script->local.arrays = NULL;
}
}
@@ -3713,6 +3713,7 @@ int run_func(struct script_state *st)
return 1;
}
script->free_vars(st->stack->scope.vars);
+ st->stack->scope.arrays->destroy(st->stack->scope.arrays,script->array_free_db);
ri = st->stack->stack_data[st->stack->defsp-1].u.ri;
nargs = ri->nargs;
@@ -4084,7 +4085,7 @@ void script_add_autobonus(const char *autobonus)
/// resets a temporary character array variable to given value
void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value) {
struct script_array *sa = NULL;
- struct DBMap *src = NULL;
+ struct reg_db *src = NULL;
unsigned int i, *list = NULL, size = 0;
int key;
@@ -4096,7 +4097,7 @@ void script_cleararray_pc(struct map_session_data* sd, const char* varname, void
if( value )
script->array_ensure_zero(NULL,sd,reference_uid(key,0),NULL);
- if( !(sa = idb_get(src, key)) ) /* non-existent array, nothing to empty */
+ if( !(sa = idb_get(src->arrays, key)) ) /* non-existent array, nothing to empty */
return;
size = sa->size;
@@ -4838,7 +4839,7 @@ BUILDIN(callfunc)
struct script_retinfo* ri;
struct script_code* scr;
const char* str = script_getstr(st,2);
- DBMap **ref = NULL;
+ struct reg_db *ref = NULL;
scr = (struct script_code*)strdb_get(script->userfunc_db, str);
if( !scr )
@@ -4848,27 +4849,22 @@ BUILDIN(callfunc)
return false;
}
- for( i = st->start+3, j = 0; i < st->end; i++, j++ )
- {
+ ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 2);
+ ref[0].vars = st->stack->scope.vars;
+ if (!st->stack->scope.arrays)
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE); // TODO: Can this happen? when?
+ ref[0].arrays = st->stack->scope.arrays;
+ ref[1].vars = st->script->local.vars;
+ if (!st->script->local.arrays)
+ st->script->local.arrays = idb_alloc(DB_OPT_BASE); // TODO: Can this happen? when?
+ ref[1].arrays = st->script->local.arrays;
+
+ for( i = st->start+3, j = 0; i < st->end; i++, j++ ) {
struct script_data* data = script->push_copy(st->stack,i);
- if( data_isreference(data) && !data->ref )
- {
+ if( data_isreference(data) && !data->ref ) {
const char* name = reference_getname(data);
if( name[0] == '.' ) {
- if( !ref ) {
- ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 2);
- ref[0] = (name[1] == '@' ? st->stack->scope.vars : st->script->local.vars);
- if( name[1] == '@' ) {
- if( !st->stack->scope.arrays )
- st->stack->scope.arrays = idb_alloc(DB_OPT_BASE);
- ref[1] = st->stack->scope.arrays;
- } else {
- if( !st->script->local.arrays )
- st->script->local.arrays = idb_alloc(DB_OPT_BASE);
- ref[1] = st->script->local.arrays;
- }
- }
- data->ref = ref;
+ data->ref = (name[1] == '@' ? &ref[0] : &ref[1]);
}
}
}
@@ -4887,6 +4883,7 @@ BUILDIN(callfunc)
st->stack->defsp = st->stack->sp;
st->state = GOTO;
st->stack->scope.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.arrays = i64db_alloc(DB_OPT_BASE);
return true;
}
@@ -4898,7 +4895,7 @@ BUILDIN(callsub)
int i,j;
struct script_retinfo* ri;
int pos = script_getnum(st,2);
- DBMap **ref = NULL;
+ struct reg_db *ref = NULL;
if( !data_islabel(script_getdata(st,2)) && !data_isfunclabel(script_getdata(st,2)) )
{
@@ -4908,21 +4905,18 @@ BUILDIN(callsub)
return false;
}
- for( i = st->start+3, j = 0; i < st->end; i++, j++ )
- {
+ ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 1);
+ ref[0].vars = st->stack->scope.vars;
+ if (!st->stack->scope.arrays)
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE); // TODO: Can this happen? when?
+ ref[0].arrays = st->stack->scope.arrays;
+
+ for( i = st->start+3, j = 0; i < st->end; i++, j++ ) {
struct script_data* data = script->push_copy(st->stack,i);
- if( data_isreference(data) && !data->ref )
- {
+ if( data_isreference(data) && !data->ref ) {
const char* name = reference_getname(data);
if( name[0] == '.' && name[1] == '@' ) {
- if ( !ref ) {
- ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 2);
- ref[0] = st->stack->scope.vars;
- if( !st->stack->scope.arrays )
- st->stack->scope.arrays = idb_alloc(DB_OPT_BASE);
- ref[1] = st->stack->scope.arrays;
- }
- data->ref = ref;
+ data->ref = &ref[0];
}
}
}
@@ -4940,6 +4934,7 @@ BUILDIN(callsub)
st->stack->defsp = st->stack->sp;
st->state = GOTO;
st->stack->scope.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.arrays = i64db_alloc(DB_OPT_BASE);
return true;
}
@@ -4994,16 +4989,18 @@ BUILDIN(return)
const char* name = reference_getname(data);
if( name[0] == '.' && name[1] == '@' )
{// scope variable
- if( !data->ref || data->ref[0] == st->stack->scope.vars )
+ if( !data->ref || data->ref->vars == st->stack->scope.vars )
script->get_val(st, data);// current scope, convert to value
+ if( data->ref && data->ref->vars == st->stack->stack_data[st->stack->defsp-1].u.ri->scope.vars )
+ data->ref = NULL; // Reference to the parent scope, remove reference pointer
}
else if( name[0] == '.' && !data->ref )
{// script variable, link to current script
- data->ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 2);
- data->ref[0] = st->script->local.vars;
+ data->ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 1);
+ data->ref->vars = st->script->local.vars;
if( !st->script->local.arrays )
st->script->local.arrays = idb_alloc(DB_OPT_BASE);
- data->ref[1] = st->script->local.arrays;
+ data->ref->arrays = st->script->local.arrays;
}
}
}
@@ -5841,7 +5838,7 @@ BUILDIN(deletearray)
int id;
TBL_PC *sd = NULL;
struct script_array *sa = NULL;
- struct DBMap *src = NULL;
+ struct reg_db *src = NULL;
void *value;
data = script_getdata(st, 2);
@@ -5873,7 +5870,7 @@ BUILDIN(deletearray)
script->array_ensure_zero(st,NULL,data->u.num,reference_getref(data));
- if ( !(sa = idb_get(src, id)) ) { /* non-existent array, nothing to empty */
+ if ( !(sa = idb_get(src->arrays, id)) ) { /* non-existent array, nothing to empty */
return true;// not a variable
}
@@ -15671,7 +15668,7 @@ BUILDIN(getvariableofnpc)
return false;
}
- script->push_val(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->local.vars);
+ script->push_val(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->local);
return true;
}
diff --git a/src/map/script.h b/src/map/script.h
index 0121f39d8..ae851a7ec 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -355,7 +355,7 @@ struct script_data {
char *str;
struct script_retinfo* ri;
} u;
- struct DBMap** ref;
+ struct reg_db *ref;
};
// Moved defsp from script_state to script_stack since
@@ -563,9 +563,9 @@ struct script_interface {
const char* (*conv_str) (struct script_state *st,struct script_data *data);
TBL_PC *(*rid2sd) (struct script_state *st);
void (*detach_rid) (struct script_state* st);
- struct script_data* (*push_val)(struct script_stack* stack, enum c_op type, int64 val, struct DBMap** ref);
+ struct script_data* (*push_val)(struct script_stack* stack, enum c_op type, int64 val, struct reg_db *ref);
struct script_data *(*get_val) (struct script_state* st, struct script_data* data);
- void* (*get_val2) (struct script_state* st, int64 uid, struct DBMap** ref);
+ void* (*get_val2) (struct script_state* st, int64 uid, struct reg_db *ref);
struct script_data* (*push_str) (struct script_stack* stack, enum c_op type, char* str);
struct script_data* (*push_copy) (struct script_stack* stack, int pos);
void (*pop_stack) (struct script_state* st, int start, int end);
@@ -589,7 +589,7 @@ struct script_interface {
int (*add_str) (const char* p);
const char* (*get_str) (int id);
int (*search_str) (const char* p);
- void (*setd_sub) (struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct DBMap **ref);
+ void (*setd_sub) (struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct reg_db *ref);
void (*attach_state) (struct script_state* st);
/* */
struct hQueue *(*queue) (int idx);
@@ -628,9 +628,9 @@ struct script_interface {
void (*read_constdb) (void);
const char* (*print_line) (StringBuf *buf, const char *p, const char *mark, int line);
void (*errorwarning_sub) (StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos);
- int (*set_reg) (struct script_state *st, TBL_PC *sd, int64 num, const char *name, const void *value, struct DBMap **ref);
+ int (*set_reg) (struct script_state *st, TBL_PC *sd, int64 num, const char *name, const void *value, struct reg_db *ref);
void (*stack_expand) (struct script_stack *stack);
- struct script_data* (*push_retinfo) (struct script_stack *stack, struct script_retinfo *ri, DBMap **ref);
+ struct script_data* (*push_retinfo) (struct script_stack *stack, struct script_retinfo *ri, struct reg_db *ref);
void (*op_3) (struct script_state *st, int op);
void (*op_2str) (struct script_state *st, int op, const char *s1, const char *s2);
void (*op_2num) (struct script_state *st, int op, int i1, int i2);
@@ -674,15 +674,15 @@ struct script_interface {
/**
* Array Handling
**/
- struct DBMap *(*array_src) (struct script_state *st, struct map_session_data *sd, const char *name, struct DBMap **ref);
- void (*array_update) (struct DBMap **src, int64 num, bool empty);
- void (*array_delete) (struct DBMap *src, struct script_array *sa);
- void (*array_remove_member) (struct DBMap *src, struct script_array *sa, unsigned int idx);
+ struct reg_db *(*array_src) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
+ void (*array_update) (struct reg_db *src, int64 num, bool empty);
+ void (*array_delete) (struct reg_db *src, struct script_array *sa);
+ void (*array_remove_member) (struct reg_db *src, struct script_array *sa, unsigned int idx);
void (*array_add_member) (struct script_array *sa, unsigned int idx);
- unsigned int (*array_size) (struct script_state *st, struct map_session_data *sd, const char *name, struct DBMap** ref);
- unsigned int (*array_highest_key) (struct script_state *st, struct map_session_data *sd, const char *name, struct DBMap** ref);
+ unsigned int (*array_size) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
+ unsigned int (*array_highest_key) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
int (*array_free_db) (DBKey key, DBData *data, va_list ap);
- void (*array_ensure_zero) (struct script_state *st, struct map_session_data *sd, int64 uid, struct DBMap** ref);
+ void (*array_ensure_zero) (struct script_state *st, struct map_session_data *sd, int64 uid, struct reg_db *ref);
/* */
void (*reg_destroy_single) (struct map_session_data *sd, int64 reg, struct script_reg_state *data);
int (*reg_destroy) (DBKey key, DBData *data, va_list ap);