summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec>2010-12-11 21:52:27 +0000
committerai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec>2010-12-11 21:52:27 +0000
commit7f52e01fda112cf0fe42a72bd577ab2de938ee5b (patch)
tree39d6d59b88ff54162699c078577411ac3ac7762a /src
parent61913f7c7688300d783ee5836d50e44048728e28 (diff)
downloadhercules-7f52e01fda112cf0fe42a72bd577ab2de938ee5b.tar.gz
hercules-7f52e01fda112cf0fe42a72bd577ab2de938ee5b.tar.bz2
hercules-7f52e01fda112cf0fe42a72bd577ab2de938ee5b.tar.xz
hercules-7f52e01fda112cf0fe42a72bd577ab2de938ee5b.zip
* Added support for checking argument data type of built-in script functions (bugreport:1701, topic:261833, related r14573).
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@14577 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/map/script.c97
-rw-r--r--src/map/script.h1
2 files changed, 98 insertions, 0 deletions
diff --git a/src/map/script.c b/src/map/script.c
index e50867905..f1f73bbb7 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -210,6 +210,7 @@ DBMap* script_get_userfunc_db(){ return userfunc_db; }
static DBMap* autobonus_db=NULL; // char* script -> char* bytecode
struct Script_Config script_config = {
+ 1, // warn_func_mismatch_argtypes
1, 65535, 2048, //warn_func_mismatch_paramnum/check_cmdcount/check_gotocount
0, INT_MAX, // input_min_value/input_max_value
"OnPCDieEvent", //die_event_name
@@ -2981,6 +2982,94 @@ void op_1(struct script_state* st, int op)
}
+/// Checks the type of all arguments passed to a built-in function.
+///
+/// @param st Script state whose stack arguments should be inspected.
+/// @param func Built-in function for which the arguments are intended.
+static void script_check_buildin_argtype(struct script_state* st, int func)
+{
+ char type;
+ int idx, invalid = 0;
+ script_function* sf = &buildin_func[str_data[func].val];
+
+ for( idx = 2; script_hasdata(st, idx); idx++ )
+ {
+ struct script_data* data = script_getdata(st, idx);
+
+ type = sf->arg[idx-2];
+
+ if( type == '?' || type == '*' )
+ {// optional argument or unknown number of optional parameters ( no types are after this )
+ break;
+ }
+ else if( type == 0 )
+ {// more arguments than necessary ( should not happen, as it is checked before )
+ ShowWarning("Found more arguments than necessary.\n");
+ invalid++;
+ break;
+ }
+ else
+ {
+ const char* name = NULL;
+
+ if( data_isreference(data) )
+ {// get name for variables to determine the type they refer to
+ name = reference_getname(data);
+ }
+
+ switch( type )
+ {
+ case 'v':
+ if( !data_isstring(data) && !data_isint(data) && !data_isreference(data) )
+ {// variant
+ ShowWarning("Unexpected type for argument %d. Expected string, number or variable.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 's':
+ if( !data_isstring(data) && !( data_isreference(data) && is_string_variable(name) ) )
+ {// string
+ ShowWarning("Unexpected type for argument %d. Expected string.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 'i':
+ if( !data_isint(data) && !( data_isreference(data) && ( reference_toparam(data) || reference_toconstant(data) || !is_string_variable(name) ) ) )
+ {// int ( params and constants are always int )
+ ShowWarning("Unexpected type for argument %d. Expected number.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 'r':
+ if( !data_isreference(data) )
+ {// variables
+ ShowWarning("Unexpected type for argument %d. Expected variable.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 'l':
+ if( !data_islabel(data) && !data_isfunclabel(data) )
+ {// label
+ ShowWarning("Unexpected type for argument %d. Expected label.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ }
+ }
+ }
+
+ if(invalid)
+ {
+ ShowDebug("Function: %s\n", get_str(func));
+ script_reportsrc(st);
+ }
+}
+
/// Executes a buildin command.
/// Stack: C_NAME(<command>) C_ARG <arg0> <arg1> ... <argN>
@@ -3016,6 +3105,11 @@ int run_func(struct script_state *st)
return 1;
}
+ if( script_config.warn_func_mismatch_argtypes )
+ {
+ script_check_buildin_argtype(st, func);
+ }
+
if(str_data[func].func){
if (str_data[func].func(st)) //Report error
script_reportsrc(st);
@@ -3383,6 +3477,9 @@ int script_config_read(char *cfgName)
else if(strcmpi(w1,"input_max_value")==0) {
script_config.input_max_value = config_switch(w2);
}
+ else if(strcmpi(w1,"warn_func_mismatch_argtypes")==0) {
+ script_config.warn_func_mismatch_argtypes = config_switch(w2);
+ }
else if(strcmpi(w1,"import")==0){
script_config_read(w2);
}
diff --git a/src/map/script.h b/src/map/script.h
index 8e9acabaf..9bc697e98 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -11,6 +11,7 @@ extern int potion_hp, potion_per_hp, potion_sp, potion_per_sp;
extern int potion_target;
extern struct Script_Config {
+ unsigned warn_func_mismatch_argtypes : 1;
unsigned warn_func_mismatch_paramnum : 1;
int check_cmdcount;
int check_gotocount;