summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-02-08 02:19:41 +0100
committerHaru <haru@dotalux.com>2014-02-08 02:33:49 +0100
commit1cf7c1ec251d6899707b0eced3bc75da2e212557 (patch)
tree54008176b1b0fca8affc1e01b1fac7b98e67df95
parente7853fa6ed991fdd7bcb4b2c842761742ae3c912 (diff)
downloadhercules-1cf7c1ec251d6899707b0eced3bc75da2e212557.tar.gz
hercules-1cf7c1ec251d6899707b0eced3bc75da2e212557.tar.bz2
hercules-1cf7c1ec251d6899707b0eced3bc75da2e212557.tar.xz
hercules-1cf7c1ec251d6899707b0eced3bc75da2e212557.zip
Improvements on the script commands sscanf, axtoi. Added strtol.
- Added script command strtol (conforming to the ISO C90 function) - Modified script command axtoi to internally use strtol instead of an unnecessary own implementation. - Fixed sscanf behavior to conform to the C specifications in case the input string is empty. It now correctly returns -1, or 0 if the format string is also empty. Fixes bugreport:8009, thanks to AnnieRuru - http://hercules.ws/board/tracker/issue-8009-sscanf-should-return-1-if-the-string-field-is-an-empty-string/ Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--doc/script_commands.txt25
-rw-r--r--src/map/script.c76
-rw-r--r--src/map/script.h1
3 files changed, 50 insertions, 52 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index c0b848663..aa8698418 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -7359,20 +7359,31 @@ setitemscript 2637,"";
---------------------------------------
-*atoi ("<string>")
-*axtoi ("<string>")
+*atoi("<string>")
+*axtoi("<string>")
+*strtol("string", base)
These commands are used to convert strings to numbers. 'atoi' will
interpret given string as a decimal number (base 10), while 'axtoi'
-interprets strings as hexadecimal numbers (base 16).
+interprets strings as hexadecimal numbers (base 16). 'strtol' lets
+the user specify a base (valid range is between 2 and 36 inclusive,
+or the special value0, which means auto-detection).
-Hexadecimal number set: {0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}
+The atoi and strtol functions conform to the C functions with the same
+names, and axtoi is the same as strtol, with a base of 16. Results are
+clamped to signed 32 bit int range (INT_MIN ~ INT_MAX)
Example:
-set @var, atoi("11"); // Sets @var to 11
-set @var, axtoi("FF"); // Sets @var to 255
-mes axtoi("11"); // Displays 17 (1 = 1, 10 = 16)
+.@var = atoi("11"); // Sets .@var to 11
+.@var = axtoi("FF"); // Sets .@var to 255
+mes axtoi("11"); // Displays 17 (1 = 1, 10 = 16)
+.@var = strtol("11", 10); // Sets .@var to 11 (11 base 10)
+.@var = strtol("11", 16); // Sets .@var to 17 (11 base 16)
+.@var = strtol("11", 0); // Sets .@var to 11 (11 base 10, auto-detected)
+.@var = strtol("0x11", 0); // Sets .@var to 17 (11 base 16, auto-detected because of the "0x" prefix)
+.@var = strtol("011", 0); // Sets .@var to 9 (11 base 8, auto-detected because of the "0" prefix)
+.@var = strtol("11", 2); // Sets .@var to 3 (binary 11)
---------------------------------------
diff --git a/src/map/script.c b/src/map/script.c
index 21d55ca77..aa3713427 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -14064,6 +14064,15 @@ BUILDIN(sscanf) {
argc = script_lastdata(st)-3;
len = strlen(format);
+
+ if (len != 0 && strlen(str) == 0) {
+ // If the source string is empty but the format string is not, we return -1
+ // according to the C specs. (if the format string is also empty, we shall
+ // continue and return 0: 0 conversions took place out of the 0 attempted.)
+ script_pushint(st, -1);
+ return true;
+ }
+
CREATE(buf, char, len*2+1);
// Issue sscanf for each parameter
@@ -14379,14 +14388,34 @@ BUILDIN(setnpcdisplay) {
return true;
}
-BUILDIN(atoi)
-{
+BUILDIN(atoi) {
const char *value;
value = script_getstr(st,2);
script_pushint(st,atoi(value));
return true;
}
+BUILDIN(axtoi) {
+ const char *hex = script_getstr(st,2);
+ long value = strtol(hex, NULL, 16);
+#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN
+ value = cap_value(value, INT_MIN, INT_MAX);
+#endif
+ script_pushint(st, (int)value);
+ return true;
+}
+
+BUILDIN(strtol) {
+ const char *string = script_getstr(st, 2);
+ int base = script_getnum(st, 3);
+ long value = strtol(string, NULL, base);
+#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN
+ value = cap_value(value, INT_MIN, INT_MAX);
+#endif
+ script_pushint(st, (int)value);
+ return true;
+}
+
// case-insensitive substring search [lordalfa]
BUILDIN(compare)
{
@@ -15112,47 +15141,6 @@ BUILDIN(searchitem)
return true;
}
-int axtoi(const char *hexStg)
-{
- int n = 0; // position in string
- int16 m = 0; // position in digit[] to shift
- int count; // loop index
- int intValue = 0; // integer value of hex string
- int digit[11]; // hold values to convert
- while (n < 10) {
- if (hexStg[n]=='\0')
- break;
- if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9
- digit[n] = hexStg[n] & 0x0f; //convert to int
- else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f
- digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
- else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F
- digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
- else break;
- n++;
- }
- count = n;
- m = n - 1;
- n = 0;
- while(n < count) {
- // digit[n] is value of hex digit at position n
- // (m << 2) is the number of positions to shift
- // OR the bits into return value
- intValue = intValue | (digit[n] << (m << 2));
- m--; // adjust the position to set
- n++; // next digit to process
- }
- return (intValue);
-}
-
-// [Lance] Hex string to integer converter
-BUILDIN(axtoi)
-{
- const char *hex = script_getstr(st,2);
- script_pushint(st,script->axtoi(hex));
- return true;
-}
-
// [zBuffer] List of player cont commands --->
BUILDIN(rid2name) {
struct block_list *bl = NULL;
@@ -18837,6 +18825,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(query_logsql,"s*"),
BUILDIN_DEF(escape_sql,"v"),
BUILDIN_DEF(atoi,"s"),
+ BUILDIN_DEF(strtol,"si"),
// [zBuffer] List of player cont commands --->
BUILDIN_DEF(rid2name,"i"),
BUILDIN_DEF(pcfollow,"ii"),
@@ -19220,7 +19209,6 @@ void script_defaults(void) {
script->playbgm_foreachpc_sub = playbgm_foreachpc_sub;
script->soundeffect_sub = soundeffect_sub;
script->buildin_query_sql_sub = buildin_query_sql_sub;
- script->axtoi = axtoi;
script->buildin_instance_warpall_sub = buildin_instance_warpall_sub;
script->buildin_mobuseskill_sub = buildin_mobuseskill_sub;
script->cleanfloor_sub = script_cleanfloor_sub;
diff --git a/src/map/script.h b/src/map/script.h
index b7e9e5741..4906d4fa8 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -665,7 +665,6 @@ struct script_interface {
int (*playbgm_foreachpc_sub) (struct map_session_data *sd, va_list args);
int (*soundeffect_sub) (struct block_list *bl, va_list ap);
int (*buildin_query_sql_sub) (struct script_state *st, Sql *handle);
- int (*axtoi) (const char *hexStg);
int (*buildin_instance_warpall_sub) (struct block_list *bl, va_list ap);
int (*buildin_mobuseskill_sub) (struct block_list *bl, va_list ap);
int (*cleanfloor_sub) (struct block_list *bl, va_list ap);