summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt11
-rw-r--r--src/common/cbasetypes.h4
-rw-r--r--src/common/db.h2
-rw-r--r--src/common/timer.c6
-rw-r--r--src/map/itemdb.c10
-rw-r--r--src/map/npc.c26
-rw-r--r--src/map/pet.c2
-rw-r--r--src/map/script.c77
-rw-r--r--src/map/script.h6
9 files changed, 83 insertions, 61 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 8f54fe8c1..6a4ea4e7d 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -3,6 +3,17 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
+2006/12/22
+ * Change strncpy to memcpy when parsing switches in the script engine
+ since it's guaranteed to be a word of that size (skip_word).
+ * Made scriptlabel_db duplicate the key. When str_buf is reallocated, the
+ keys in scriptlabel_db could become invalid, causing a crash in
+ npc_convertlabel_db.
+ * Now npc_convertlabel_db clears scriptlabel_db after using it.
+ * parse_script has an extra parameter options. At the moment it only
+ indicates if scriptlabel_db should be used or not.
+ * Fixed "UINT_MAX undeclared" on systems that don't declare it in limits.h
+ [FlavioJS]
2006/12/21
* Applied Rayce's suggestions and fixes to the script engine
(http://www.eathena.ws/board/index.php?showtopic=129185)
diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h
index c61424191..3a3bde818 100644
--- a/src/common/cbasetypes.h
+++ b/src/common/cbasetypes.h
@@ -126,6 +126,10 @@ typedef unsigned int uint32;
#define SINT16_MAX ((sint16)0x7FFF)
#define SINT32_MAX ((sint32)0x7FFFFFFF)
+// ILP64 isn't supported, so always 32 bits?
+#ifndef UINT_MAX
+#define UINT_MAX 0xFFFFFFFF
+#endif
//////////////////////////////////////////////////////////////////////////
// Integers with guaranteed _minimum_ size.
diff --git a/src/common/db.h b/src/common/db.h
index aa165acd7..a79c88822 100644
--- a/src/common/db.h
+++ b/src/common/db.h
@@ -130,7 +130,7 @@ typedef enum {
* @see #db_default_release(DBType,DBOptions)
* @see #db_alloc(const char *,int,DBType,DBOptions,unsigned short)
*/
-typedef enum {
+typedef enum db_opt {
DB_OPT_BASE = 0,
DB_OPT_DUP_KEY = 1,
DB_OPT_RELEASE_KEY = 2,
diff --git a/src/common/timer.c b/src/common/timer.c
index cf71f2ffc..63a06acc2 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -18,9 +18,11 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/showmsg.h"
#include "timer.h"
-#include "malloc.h"
-#include "showmsg.h"
// タイマー間隔の最小値。モンスターの大量召還時、多数のクライアント接続時に
// サーバーが反応しなくなる場合は、TIMER_MIN_INTERVAL を増やしてください。
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index b6626fa41..68a61724f 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1146,11 +1146,11 @@ static int itemdb_readdb(void)
np = strchr(np+1,'}'); //Jump close brackets until the next field is found.
if (!np || !np[1]) {
//Couldn't find the end of the script field.
- id->script = parse_script((unsigned char *) str[19],filename[i],lines);
+ id->script = parse_script(str[19],filename[i],lines,0);
continue;
}
np[1] = '\0'; //Set end of script
- id->script = parse_script((unsigned char *) str[19],filename[i],lines);
+ id->script = parse_script(str[19],filename[i],lines,0);
np+=2; //Skip to next field
if(!np || (p=strchr(np,'{'))==NULL)
@@ -1163,18 +1163,18 @@ static int itemdb_readdb(void)
np = strchr(np+1,'}'); //Jump close brackets until the next field is found.
if (!np || !np[1]) {
//Couldn't find the end of the script field.
- id->equip_script = parse_script((unsigned char *) str[20],filename[i],lines);
+ id->equip_script = parse_script(str[20],filename[i],lines,0);
continue;
}
np[1] = '\0'; //Set end of script
- id->equip_script = parse_script((unsigned char *) str[20],filename[i],lines);
+ id->equip_script = parse_script(str[20],filename[i],lines,0);
np+=2; //Skip comma, to next field
if(!np || (p=strchr(np,'{'))==NULL)
continue;
//Unequip script, last column.
- id->unequip_script = parse_script((unsigned char *) p,filename[i],lines);
+ id->unequip_script = parse_script(p,filename[i],lines,0);
}
fclose(fp);
if (ln > 0) {
diff --git a/src/map/npc.c b/src/map/npc.c
index 95cb4b177..4118b79ea 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1725,13 +1725,13 @@ static int npc_parse_shop (char *w1, char *w2, char *w3, char *w4)
*/
int npc_convertlabel_db (DBKey key, void *data, va_list ap)
{
- unsigned char *lname = key.str;
+ const char *lname = (const char*)key.str;
int pos = (int)data;
struct npc_data *nd;
struct npc_label_list *lst;
int num;
- char *p;
- char c;
+ const char *p;
+ int len;
nullpo_retr(0, ap);
nullpo_retr(0, nd = va_arg(ap,struct npc_data *));
@@ -1746,18 +1746,17 @@ int npc_convertlabel_db (DBKey key, void *data, va_list ap)
// In case of labels not terminated with ':', for user defined function support
p = lname;
- while(isalnum(*(unsigned char*)p) || *p == '_') { p++; }
- c = *p;
- *p='\0';
+ while( ISALNUM(*p) || *p == '_' )
+ p++;
+ len = p-lname;
// here we check if the label fit into the buffer
- if (strlen(lname) > 23) {
+ if (len > 23) {
ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, current_file);
exit(1);
}
- memcpy(lst[num].name, lname, strlen(lname)+1); //including EOS
-
- *p = c;
+ memcpy(lst[num].name, lname, len);
+ lst[num].name[len]=0;
lst[num].pos = pos;
nd->u.scr.label_list = lst;
nd->u.scr.label_list_num = num+1;
@@ -1868,7 +1867,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
unsigned char line[1024];
int i;
struct npc_data *nd, *dnd;
- struct dbt *label_db;
+ DB label_db;
char *p;
struct npc_label_list *label_dup = NULL;
int label_dupnum = 0;
@@ -1920,7 +1919,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
script = NULL;
} else {
// printf("Ok line %d\n",*lines);
- script = parse_script((unsigned char *) srcbuf, file, startline);
+ script = parse_script(srcbuf, file, startline, SCRIPT_USE_LABEL_DB);
}
if (script == NULL) {
// script parse error?
@@ -2039,6 +2038,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
// ラベルデータのコンバート
label_db = script_get_label_db();
label_db->foreach(label_db, npc_convertlabel_db, nd);
+ label_db->clear(label_db,NULL); // not needed anymore, so clear the db
// もう使わないのでバッファ解放
aFree(srcbuf);
@@ -2156,7 +2156,7 @@ static int npc_parse_function (char *w1, char *w2, char *w3, char *w4, char *fir
ShowError("Missing right curly at file %s, line %d\n",file, *lines);
script = NULL;
} else {
- script = parse_script(srcbuf, file, startline);
+ script = parse_script(srcbuf, file, startline,0);
}
if (script == NULL) {
// script parse error?
diff --git a/src/map/pet.c b/src/map/pet.c
index 035514bd1..50433aab3 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -1351,7 +1351,7 @@ int read_petdb()
pet_db[j].script = NULL;
if((np=strchr(p,'{'))==NULL)
continue;
- pet_db[j].script = parse_script((unsigned char *) np, filename[i], lines);
+ pet_db[j].script = parse_script(np, filename[i], lines, 0);
j++;
}
if (j >= MAX_PET_DB)
diff --git a/src/map/script.c b/src/map/script.c
index 5f4de13e4..8357c094d 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -88,6 +88,7 @@ char mapreg_txt[256]="save/mapreg.txt";
static struct dbt *scriptlabel_db=NULL;
static struct dbt *userfunc_db=NULL;
+static int parse_options=0;
struct dbt* script_get_label_db(){ return scriptlabel_db; }
struct dbt* script_get_userfunc_db(){ return userfunc_db; }
@@ -158,7 +159,7 @@ int mapreg_setreg(int num,int val);
int mapreg_setregstr(int num,const char *str);
static void disp_error_message(const char *mes,const char *pos);
-enum {
+enum c_op {
C_NOP,C_POS,C_INT,C_PARAM,C_FUNC,C_STR,C_CONSTSTR,C_ARG,
C_NAME,C_EOL, C_RETINFO,
C_USERFUNC, C_USERFUNC_POS, // user defined functions
@@ -502,12 +503,8 @@ static const char *skip_word(const char *p)
//# Changing from unsigned char to signed char makes p never be able to go above 0x81, but what IS 0x81 for? [Skotlex]
//# It's for multibyte encodings like Shift-JIS. Unfortunately this can be problematic for singlebyte encodings.
// Using (*p)>>7 would yield the appropriate result but it's better to restrict words to ASCII characters only. [FlavioJS]
- while( ISALNUM(*p) || *p == '_' || (*p)>>7 )
- {
- if( (*p)>>7 ) // readded the >=0x81 equivalent until I figure out where the script engine is 'being naughty' O.o [FlavioJS]
- ++p;
+ while( ISALNUM(*p) || *p == '_' )
++p;
- }
// postfix
if(*p=='$') p++; // 文字列変数
@@ -1020,12 +1017,12 @@ const char* parse_syntax(const char* p) {
p = skip_space(p);
p2 = p;
p = skip_word(p);
- len = p-p2;
+ len = p-p2; // length of word at p2
p = skip_space(p);
if(*p != ':')
disp_error_message("parse_syntax: expect ':'",p);
memcpy(label,"if(",3);
- strncpy(label+3,p2,len);
+ memcpy(label+3,p2,len);
sprintf(label+3+len," != $@__SW%x_VAL) goto __SW%x_%x;",
syntax.curly[pos].index,syntax.curly[pos].index,syntax.curly[pos].count+1);
syntax.curly[syntax.curly_count++].type = TYPE_NULL;
@@ -1254,7 +1251,8 @@ const char* parse_syntax(const char* p) {
if(str_data[l].type == C_NOP)
str_data[l].type = C_USERFUNC;
set_label(l,script_pos,p);
- strdb_put(scriptlabel_db, GETSTRING(str_data[l].str), (void*)script_pos);
+ if( parse_options&SCRIPT_USE_LABEL_DB )
+ strdb_put(scriptlabel_db, GETSTRING(str_data[l].str), (void*)script_pos);
return skip_space(p);
}
}
@@ -1562,7 +1560,22 @@ static void read_constdb(void)
*------------------------------------------
*/
-const char* script_print_line( const char *p, const char *mark, int line );
+const char* script_print_line( const char *p, const char *mark, int line ) {
+ int i;
+ if( p == NULL || !p[0] ) return NULL;
+ if( line < 0 )
+ printf("*% 5d : ", -line);
+ else
+ printf(" % 5d : ", line);
+ for(i=0;p[i] && p[i] != '\n';i++){
+ if(p + i != mark)
+ printf("%c",p[i]);
+ else
+ printf("\'%c\'",p[i]);
+ }
+ printf("\n");
+ return p+i+(p[i] == '\n' ? 1 : 0);
+}
void script_error(const char *src,const char *file,int start_line, const char *error_msg, const char *error_pos) {
// エラーが発生した行を求める
@@ -1595,29 +1608,12 @@ void script_error(const char *src,const char *file,int start_line, const char *e
}
}
-const char* script_print_line( const char *p, const char *mark, int line ) {
- int i;
- if( p == NULL || !p[0] ) return NULL;
- if( line < 0 )
- printf("*% 5d : ", -line);
- else
- printf(" % 5d : ", line);
- for(i=0;p[i] && p[i] != '\n';i++){
- if(p + i != mark)
- printf("%c",p[i]);
- else
- printf("\'%c\'",p[i]);
- }
- printf("\n");
- return p+i+(p[i] == '\n' ? 1 : 0);
-}
-
/*==========================================
* スクリプトの解析
*------------------------------------------
*/
-struct script_code* parse_script(const char *src,const char *file,int line)
+struct script_code* parse_script(const char *src,const char *file,int line,int options)
{
const char *p,*tmpp;
int i;
@@ -1648,8 +1644,11 @@ struct script_code* parse_script(const char *src,const char *file,int line)
}
}
- //Labels must be reparsed for the script....
- scriptlabel_db->clear(scriptlabel_db, NULL);
+ // who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here
+ if( options&SCRIPT_USE_LABEL_DB )
+ scriptlabel_db->clear(scriptlabel_db, NULL);
+ parse_options = options;
+
if( setjmp( error_jump ) != 0 ) {
//Restore program state when script has problems. [from jA]
script_error(src,file,line,error_msg,error_pos);
@@ -1688,7 +1687,8 @@ struct script_code* parse_script(const char *src,const char *file,int line)
if(*tmpp==':' && !(!strncmp(p,"default:",8) && p + 7 == tmpp)){
i=add_word(p);
set_label(i,script_pos,p);
- strdb_put(scriptlabel_db, GETSTRING(str_data[i].str), (void*)script_pos);
+ if( parse_options&SCRIPT_USE_LABEL_DB )
+ strdb_put(scriptlabel_db, GETSTRING(str_data[i].str), (void*)script_pos);
p=tmpp+1;
continue;
}
@@ -1955,8 +1955,9 @@ char* conv_str(struct script_state *st,struct script_data *data)
get_val(st,data);
if(data->type==C_INT){
char *buf;
- buf=(char *)aMallocA(ITEM_NAME_LENGTH*sizeof(char));
+ CREATE(buf,char,ITEM_NAME_LENGTH);
snprintf(buf,ITEM_NAME_LENGTH, "%d",data->u.num);
+ buf[ITEM_NAME_LENGTH-1]=0;
data->type=C_STR;
data->u.str=buf;
} else if(data->type==C_POS) {
@@ -3273,7 +3274,7 @@ int do_init_script()
mapreg_db= db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
mapregstr_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
userfunc_db=db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_RELEASE_BOTH,50);
- scriptlabel_db=db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_ALLOW_NULL_DATA,50);
+ scriptlabel_db=db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA,50);
script_load_mapreg();
@@ -3978,9 +3979,9 @@ struct script_function buildin_func[] = {
int buildin_mes(struct script_state *st)
{
struct map_session_data *sd = script_rid2sd(st);
- conv_str(st,& (st->stack->stack_data[st->start+2]));
+ char *mes = conv_str(st, &(st->stack->stack_data[st->start+2]));
if (sd)
- clif_scriptmes(sd,st->oid,st->stack->stack_data[st->start+2].u.str);
+ clif_scriptmes(sd, st->oid, mes);
return 0;
}
@@ -11306,9 +11307,9 @@ int buildin_setbattleflag(struct script_state *st){
value = conv_str(st,& (st->stack->stack_data[st->start+3]));
if (battle_set_value(flag, value) == 0)
- ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'",flag);
+ ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'\n",flag);
else
- ShowInfo("buildin_setbattleflag: battle_config flag '%s' is now set to '%s'.",flag,value);
+ ShowInfo("buildin_setbattleflag: battle_config flag '%s' is now set to '%s'.\n",flag,value);
return 0;
}
@@ -11800,7 +11801,7 @@ int buildin_setitemscript(struct script_state *st)
if (i_data && script!=NULL && script[0]=='{') {
if(i_data->script!=NULL)
script_free_code(i_data->script);
- i_data->script = parse_script(script, "script_setitemscript", 0);
+ i_data->script = parse_script(script, "script_setitemscript", 0, 0);
push_val(st->stack,C_INT,1);
} else
push_val(st->stack,C_INT,0);
diff --git a/src/map/script.h b/src/map/script.h
index bc142c125..7ab7e1876 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -61,7 +61,11 @@ struct script_state {
} sleep;
};
-struct script_code* parse_script(const char* src,const char* file,int line);
+enum script_parse_options {
+ SCRIPT_USE_LABEL_DB = 0x1
+};
+
+struct script_code* parse_script(const char* src,const char* file,int line,int options);
void run_script_sub(struct script_code *rootscript,int pos,int rid,int oid, char* file, int lineno);
void run_script(struct script_code*,int,int,int);