summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/strlib.c43
-rw-r--r--src/common/strlib.h3
-rw-r--r--src/map/script.c11
3 files changed, 51 insertions, 6 deletions
diff --git a/src/common/strlib.c b/src/common/strlib.c
index b6ff4b279..88de59cb9 100644
--- a/src/common/strlib.c
+++ b/src/common/strlib.c
@@ -740,20 +740,21 @@ size_t sv_unescape_c(char* out_dest, const char* src, size_t len)
ShowWarning("sv_unescape_c: hex escape sequence out of range\n");
inrange = 0;
}
- c = (c<<8)|low2hex[(unsigned char)src[i++]];// hex digit
- }while( i >= len || !ISXDIGIT(src[i]) );
+ c = (c<<4)|low2hex[(unsigned char)src[i]];// hex digit
+ ++i;
+ }while( i < len && ISXDIGIT(src[i]) );
out_dest[j++] = (char)c;
}
else if( src[i] == '0' || src[i] == '1' || src[i] == '2' || src[i] == '3' )
{// octal escape sequence (255=0377)
unsigned char c = src[i]-'0';
++i;// '0', '1', '2' or '3'
- if( i < len && src[i] >= '0' && src[i] <= '9' )
+ if( i < len && src[i] >= '0' && src[i] <= '7' )
{
c = (c<<3)|(src[i]-'0');
++i;// octal digit
}
- if( i < len && src[i] >= '0' && src[i] <= '9' )
+ if( i < len && src[i] >= '0' && src[i] <= '7' )
{
c = (c<<3)|(src[i]-'0');
++i;// octal digit
@@ -763,7 +764,7 @@ size_t sv_unescape_c(char* out_dest, const char* src, size_t len)
else
{// other escape sequence
if( strchr(SV_ESCAPE_C_SUPPORTED, src[i]) == NULL )
- ShowWarning("sv_parse: unknown escape sequence \\%c\n", src[i]);
+ ShowWarning("sv_unescape_c: unknown escape sequence \\%c\n", src[i]);
switch( src[i] )
{
case 'a': out_dest[j++] = '\a'; break;
@@ -786,6 +787,38 @@ size_t sv_unescape_c(char* out_dest, const char* src, size_t len)
return j;
}
+/// Skips a C escape sequence (starting with '\\').
+const char* skip_escaped_c(const char* p)
+{
+ if( p && *p == '\\' )
+ {
+ ++p;
+ switch( *p )
+ {
+ case 'x':// hexadecimal
+ ++p;
+ while( ISXDIGIT(*p) )
+ ++p;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':// octal
+ ++p;
+ if( *p >= '0' && *p <= '7' )
+ ++p;
+ if( *p >= '0' && *p <= '7' )
+ ++p;
+ break;
+ default:
+ if( *p && strchr(SV_ESCAPE_C_SUPPORTED, *p) )
+ ++p;
+ }
+ }
+ return p;
+}
+
+
/// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row.
/// Tracks the progress of the operation (current line number, number of successfully processed rows).
/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read.
diff --git a/src/common/strlib.h b/src/common/strlib.h
index 3c4075902..074c7eae3 100644
--- a/src/common/strlib.h
+++ b/src/common/strlib.h
@@ -91,6 +91,9 @@ size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* esca
/// out_dest should be len+1 in size and can be the same buffer as src.
size_t sv_unescape_c(char* out_dest, const char* src, size_t len);
+/// Skips a C escape sequence (starting with '\\').
+const char* skip_escaped_c(const char* p);
+
/// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row.
/// Tracks the progress of the operation (current line number, number of successfully processed rows).
/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read.
diff --git a/src/map/script.c b/src/map/script.c
index 236bcf71e..6c2f30c55 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -921,7 +921,16 @@ const char* parse_simpleexpr(const char *p)
p++;
while( *p && *p != '"' ){
if( (unsigned char)p[-1] <= 0x7e && *p == '\\' )
- p++;
+ {
+ char buf[8];
+ size_t len = skip_escaped_c(p) - p;
+ size_t n = sv_unescape_c(buf, p, len);
+ if( n != 1 )
+ ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
+ p += len;
+ add_scriptb(*buf);
+ continue;
+ }
else if( *p == '\n' )
disp_error_message("parse_simpleexpr: unexpected newline @ string",p);
add_scriptb(*p++);