summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-05-09 07:37:53 +0200
committerHaru <haru@dotalux.com>2014-05-09 07:40:43 +0200
commit5f1529083ad1f35a3ac66cc041ee74d6db2f3552 (patch)
tree32c4d73a7f68cd7a1a963e14e3972333758bb541
parent581ff22b9bad7567a27980df31636f0c75ba5fc2 (diff)
downloadhercules-5f1529083ad1f35a3ac66cc041ee74d6db2f3552.tar.gz
hercules-5f1529083ad1f35a3ac66cc041ee74d6db2f3552.tar.bz2
hercules-5f1529083ad1f35a3ac66cc041ee74d6db2f3552.tar.xz
hercules-5f1529083ad1f35a3ac66cc041ee74d6db2f3552.zip
Return EXIT_FAILURE if a script parse error occurred.
- This affects normal execution as well as ./script-checker runs. Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/map/itemdb.c14
-rw-r--r--src/map/map.c10
-rw-r--r--src/map/npc.c239
-rw-r--r--src/map/npc.h16
-rw-r--r--src/map/pet.c4
-rw-r--r--src/map/script.c19
-rw-r--r--src/map/script.h2
7 files changed, 178 insertions, 126 deletions
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 1bbe87a20..5eeb90be5 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1478,7 +1478,7 @@ void itemdb_read_combos() {
CREATE(combo, struct item_combo, 1);
combo->count = retcount;
- combo->script = script->parse(str[1], filepath, lines, 0);
+ combo->script = script->parse(str[1], filepath, lines, 0, NULL);
combo->id = itemdb->combo_count - 1;
/* populate ->nameid field */
for( v = 0; v < retcount; v++ ) {
@@ -1707,9 +1707,9 @@ int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) {
SQL->GetData(handle, 19, &data, NULL); id.flag.no_refine = data && atoi(data) ? 0 : 1;
SQL->GetData(handle, 20, &data, NULL); id.look = data ? atoi(data) : 0;
SQL->GetData(handle, 21, &data, NULL); id.flag.bindonequip = data && atoi(data) ? 1 : 0;
- SQL->GetData(handle, 22, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL;
- SQL->GetData(handle, 23, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL;
- SQL->GetData(handle, 24, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL;
+ SQL->GetData(handle, 22, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ SQL->GetData(handle, 23, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ SQL->GetData(handle, 24, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
return itemdb->validate_entry(&id, n, source);
}
@@ -1875,13 +1875,13 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
id.flag.bindonequip = libconfig->setting_get_bool(t) ? 1 : 0;
if( libconfig->setting_lookup_string(it, "Script", &str) )
- id.script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL;
+ id.script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
if( libconfig->setting_lookup_string(it, "OnEquipScript", &str) )
- id.equip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL;
+ id.equip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
if( libconfig->setting_lookup_string(it, "OnUnequipScript", &str) )
- id.unequip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL;
+ id.unequip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
return itemdb->validate_entry(&id, n, source);
}
diff --git a/src/map/map.c b/src/map/map.c
index a5ec6d83b..24a07699f 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3841,7 +3841,7 @@ void map_zone_remove(int m) {
}
}
- npc->parse_mapflag(map->list[m].name,empty,flag,params,empty,empty,empty);
+ npc->parse_mapflag(map->list[m].name,empty,flag,params,empty,empty,empty, NULL);
aFree(map->list[m].zone_mf[k]);
map->list[m].zone_mf[k] = NULL;
}
@@ -4573,7 +4573,7 @@ void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const
if( map->zone_mf_cache(m,flag,params) )
continue;
- npc->parse_mapflag(map->list[m].name,empty,flag,params,start,buffer,filepath);
+ npc->parse_mapflag(map->list[m].name, empty, flag, params, start, buffer, filepath, NULL);
}
}
/* used on npc load and reload to apply all "Normal" and "PK Mode" zones */
@@ -4601,7 +4601,7 @@ void map_zone_init(void) {
if( map->list[j].zone == zone ) {
if( map->zone_mf_cache(j,flag,params) )
break;
- npc->parse_mapflag(map->list[j].name,empty,flag,params,empty,empty,empty);
+ npc->parse_mapflag(map->list[j].name, empty, flag, params, empty, empty, empty, NULL);
}
}
}
@@ -4623,7 +4623,7 @@ void map_zone_init(void) {
if( map->list[j].zone == zone ) {
if( map->zone_mf_cache(j,flag,params) )
break;
- npc->parse_mapflag(map->list[j].name,empty,flag,params,empty,empty,empty);
+ npc->parse_mapflag(map->list[j].name, empty, flag, params, empty, empty, empty, NULL);
}
}
}
@@ -5810,7 +5810,7 @@ int do_init(int argc, char *argv[])
if (scriptcheck) {
bool failed = load_extras_count > 0 ? false : true;
for (i = 0; i < load_extras_count; i++) {
- if (npc->parsesrcfile(load_extras[i], false) != 0)
+ if (npc->parsesrcfile(load_extras[i], false) != EXIT_SUCCESS)
failed = true;
}
if (failed)
diff --git a/src/map/npc.c b/src/map/npc.c
index 43e4bcc88..27759d185 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2532,8 +2532,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
}
/// Parses a warp npc.
-const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
int x, y, xs, ys, to_x, to_y, m;
unsigned short i;
char mapname[32], to_mapname[32];
@@ -2542,22 +2541,24 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s
// w1=<from map name>,<fromX>,<fromY>,<facing>
// w4=<spanx>,<spany>,<to map name>,<toX>,<toY>
if( sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3
- || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5 )
- {
+ || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5
+ ) {
ShowError("npc_parse_warp: Invalid warp definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
m = map->mapname2mapid(mapname);
i = mapindex->name2id(to_mapname);
- if( i == 0 )
- {
+ if( i == 0 ) {
ShowError("npc_parse_warp: Unknown destination map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), to_mapname, w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) {
ShowError("npc_parse_warp: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');;//try next
}
@@ -2597,25 +2598,27 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s
}
/// Parses a shop/cashshop npc.
-const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
//TODO: could be rewritten to NOT need this temp array [ultramage]
- #define MAX_SHOPITEM 100
+#define MAX_SHOPITEM 100
struct npc_item_list items[MAX_SHOPITEM];
+#undef MAX_SHOPITEM
char *p;
int x, y, dir, m, i;
struct npc_data *nd;
enum npc_subtype type;
- if( strcmp(w1,"-") == 0 ) {// 'floating' shop?
+ if( strcmp(w1,"-") == 0 ) {
+ // 'floating' shop?
x = y = dir = 0;
m = -1;
} else {// w1=<map name>,<x>,<y>,<facing>
char mapname[32];
if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4
- || strchr(w4, ',') == NULL )
- {
+ || strchr(w4, ',') == NULL
+ ) {
ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
@@ -2624,6 +2627,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) {
ShowError("npc_parse_shop: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');;//try next
}
@@ -2633,38 +2637,38 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
type = SHOP;
p = strchr(w4,',');
- for( i = 0; i < ARRAYLENGTH(items) && p; ++i )
- {
+ for( i = 0; i < ARRAYLENGTH(items) && p; ++i ) {
int nameid, value;
struct item_data* id;
- if( sscanf(p, ",%d:%d", &nameid, &value) != 2 )
- {
+ if( sscanf(p, ",%d:%d", &nameid, &value) != 2 ) {
ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
break;
}
- if( (id = itemdb->exists(nameid)) == NULL )
- {
+ if( (id = itemdb->exists(nameid)) == NULL ) {
ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid);
p = strchr(p+1,',');
+ if (retval) *retval = EXIT_FAILURE;
continue;
}
- if( value < 0 )
- {
+ if( value < 0 ) {
if( type == SHOP ) value = id->value_buy;
else value = 0; // Cashshop doesn't have a "buy price" in the item_db
}
- if( type == SHOP && value == 0 )
- { // NPC selling items for free!
+ if( type == SHOP && value == 0 ) {
+ // NPC selling items for free!
ShowWarning("npc_parse_shop: Item %s [%d] is being sold for FREE in file '%s', line '%d'.\n",
id->name, nameid, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
- if( type == SHOP && value*0.75 < id->value_sell*1.24 )
- {// Exploit possible: you can buy and sell back with profit
+ if( type == SHOP && value*0.75 < id->value_sell*1.24 ) {
+ // Exploit possible: you can buy and sell back with profit
ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) in file '%s', line '%d'.\n",
id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
//for logs filters, atcommands and iteminfo script command
if( id->maxchance == 0 )
@@ -2674,9 +2678,9 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
items[i].value = value;
p = strchr(p+1,',');
}
- if( i == 0 )
- {
+ if( i == 0 ) {
ShowWarning("npc_parse_shop: Ignoring empty shop in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// continue
}
@@ -2743,8 +2747,7 @@ void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath
}
// Skip the contents of a script.
-const char* npc_skip_script(const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_skip_script(const char* start, const char* buffer, const char* filepath, int *retval) {
const char* p;
int curly_count;
@@ -2753,9 +2756,9 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
// initial bracket (assumes the previous part is ok)
p = strchr(start,'{');
- if( p == NULL )
- {
+ if( p == NULL ) {
ShowError("npc_skip_script: Missing left curly in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
@@ -2775,16 +2778,15 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
{// string
for( ++p; *p != '"' ; ++p )
{
- if( *p == '\\' && (unsigned char)p[-1] <= 0x7e )
+ if( *p == '\\' && (unsigned char)p[-1] <= 0x7e ) {
++p;// escape sequence (not part of a multibyte character)
- else if( *p == '\0' )
- {
+ } else if( *p == '\0' ) {
script->error(buffer, filepath, 0, "Unexpected end of string.", p);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
- }
- else if( *p == '\n' )
- {
+ } else if( *p == '\n' ) {
script->error(buffer, filepath, 0, "Unexpected newline at string.", p);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
}
@@ -2792,6 +2794,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
else if( *p == '\0' )
{// end of buffer
ShowError("Missing %d right curlys in file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
}
@@ -2804,7 +2807,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
/// -%TAB%script%TAB%<NPC Name>%TAB%-1,{<code>}
/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>}
-const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options) {
+const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) {
int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov
char mapname[32];
struct script_code *scriptroot;
@@ -2824,6 +2827,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
} else {// npc in a map
if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ) {
ShowError("npc_parse_script: Invalid placement format for a script in file '%s', line '%d'. Skipping the rest of file...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// unknown format, don't continue
}
m = map->mapname2mapid(mapname);
@@ -2834,15 +2838,16 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
if( strstr(w4,",{") == NULL || script_start == NULL || (end != NULL && script_start > end) )
{
ShowError("npc_parse_script: Missing left curly ',{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
++script_start;
- end = npc->skip_script(script_start, buffer, filepath);
+ end = npc->skip_script(script_start, buffer, filepath, retval);
if( end == NULL )
return NULL;// (simple) parse error, don't continue
- scriptroot = script->parse(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB);
+ scriptroot = script->parse(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB, retval);
label_list = NULL;
label_list_num = 0;
if( script->label_count ) {
@@ -2906,6 +2911,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
if (npc->event_export(nd, i)) {
ShowWarning("npc_parse_script: duplicate event %s::%s in file '%s'.\n",
nd->exname, nd->u.scr.label_list[i].name, filepath);
+ if (retval) *retval = EXIT_FAILURE;
}
npc->timerevent_export(nd, i);
}
@@ -2936,8 +2942,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
/// npc: -%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
/// npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
/// !!Only NPO_ONINIT is available trough options!!
-const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options)
-{
+const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) {
int x, y, dir, m, xs = -1, ys = -1;
char mapname[32];
char srcname[128];
@@ -2957,6 +2962,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
if( w2[length-1] != ')' || length <= 11 || length-11 >= sizeof(srcname) )
{// does not match 'duplicate(%127s)', name is empty or too long
ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), w2);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
safestrncpy(srcname, w2+10, length-10);
@@ -2964,6 +2970,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
dnd = npc->name2id(srcname);
if( dnd == NULL) {
ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), srcname);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
src_id = dnd->bl.id;
@@ -2979,6 +2986,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
dir = 0;
} else if( fields != 4 ) {// <map name>,<x>,<y>,<facing>
ShowError("npc_parse_duplicate: Invalid placement format for duplicate in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
m = map->mapname2mapid(mapname);
@@ -2986,6 +2994,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) {
ShowError("npc_parse_duplicate: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return end;//try next
}
@@ -2993,6 +3002,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
else if( type == SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2);// <sprite id>,<triggerX>,<triggerY>
else if( type == WARP ) {
ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
@@ -3069,6 +3079,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
if (npc->event_export(nd, i)) {
ShowWarning("npc_parse_duplicate: duplicate event %s::%s in file '%s'.\n",
nd->exname, nd->u.scr.label_list[i].name, filepath);
+ if (retval) *retval = EXIT_FAILURE;
}
npc->timerevent_export(nd, i);
}
@@ -3152,7 +3163,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
else
snprintf(w4, sizeof(w4), "%d", snd->class_);
- npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING", NPO_NONE);
+ npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING", NPO_NONE, NULL);
}
return 0;
@@ -3339,8 +3350,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
/// Parses a function.
/// function%TAB%script%TAB%<function name>%TAB%{<code>}
-const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
DBMap* func_db;
DBData old_data;
struct script_code *scriptroot;
@@ -3349,18 +3359,18 @@ const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const cha
script_start = strstr(start,"\t{");
end = strchr(start,'\n');
- if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) )
- {
+ if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) {
ShowError("npc_parse_function: Missing left curly '%%TAB%%{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
++script_start;
- end = npc->skip_script(script_start,buffer,filepath);
+ end = npc->skip_script(script_start,buffer,filepath, retval);
if( end == NULL )
return NULL;// (simple) parse error, don't continue
- scriptroot = script->parse(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT);
+ scriptroot = script->parse(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT, retval);
if( scriptroot == NULL )// parse error, continue
return end;
@@ -3394,7 +3404,7 @@ void npc_parse_mob2(struct spawn_data* mobspawn)
}
}
-const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) {
+const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
int num, class_, m,x,y,xs,ys, i,j;
int mob_lv = -1, ai = -1, size = -1;
char mapname[32], mobname[NAME_LENGTH];
@@ -3413,10 +3423,12 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
|| sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2
) {
ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
if( mapindex->name2id(mapname) == 0 ) {
ShowError("npc_parse_mob: Unknown map '%s' in file '%s', line '%d'.\n", mapname, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
m = map->mapname2mapid(mapname);
@@ -3426,32 +3438,38 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
if( x < 0 || x >= map->list[mobspawn.m].xs || y < 0 || y >= map->list[mobspawn.m].ys ) {
ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s in file '%s', line '%d'.\n", map->list[mobspawn.m].name, x, y, (map->list[mobspawn.m].xs-1), (map->list[mobspawn.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
// check monster ID if exists!
if( mob->db_checkid(class_) == 0 ) {
ShowError("npc_parse_mob: Unknown mob ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
if( num < 1 || num > 1000 ) {
ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] in file '%s', line '%d'.\n", num, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
if( (mobspawn.state.size < 0 || mobspawn.state.size > 2) && size != -1 ) {
ShowError("npc_parse_mob: Invalid size number %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.size, class_, filepath, strline(buffer, start - buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start, '\n');
}
if( (mobspawn.state.ai < 0 || mobspawn.state.ai > 4) && ai != -1 ) {
ShowError("npc_parse_mob: Invalid ai %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.ai, class_, filepath, strline(buffer, start - buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start, '\n');
}
if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 ) {
ShowError("npc_parse_mob: Invalid level %d for mob ID %d in file '%s', line '%d'.\n", mob_lv, class_, filepath, strline(buffer, start - buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start, '\n');
}
@@ -3482,6 +3500,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
if(mobspawn.delay1>0xfffffff || mobspawn.delay2>0xfffffff) {
ShowError("npc_parse_mob: Invalid spawn delays %u %u in file '%s', line '%d'.\n", mobspawn.delay1, mobspawn.delay2, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
@@ -3496,6 +3515,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
//Verify dataset.
if( !mob->parse_dataset(&mobspawn) ) {
ShowError("npc_parse_mob: Invalid dataset for monster ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
@@ -3555,7 +3575,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
* eg : bat_c01 mapflag battleground 2
* also chking if mapflag conflict with another
*------------------------------------------*/
-const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) {
+const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
int16 m;
char mapname[32];
int state = 1;
@@ -3564,11 +3584,13 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( sscanf(w1, "%31[^,]", mapname) != 1 )
{
ShowError("npc_parse_mapflag: Invalid mapflag definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
m = map->mapname2mapid(mapname);
if( m < 0 ) {
ShowWarning("npc_parse_mapflag: Unknown map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", mapname, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
@@ -3590,6 +3612,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
map->list[m].save.y = savey;
if (!map->list[m].save.map) {
ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found in file '%s', line '%d', using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
map->list[m].save.x = -1;
map->list[m].save.y = -1;
}
@@ -3628,10 +3651,12 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
map->list[m].flag.gvg_dungeon = 0;
map->list[m].flag.gvg_castle = 0;
ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
if( state && map->list[m].flag.battleground ) {
map->list[m].flag.battleground = 0;
ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) && map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
@@ -3678,10 +3703,12 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( state && map->list[m].flag.pvp ) {
map->list[m].flag.pvp = 0;
ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
if( state && map->list[m].flag.battleground ) {
map->list[m].flag.battleground = 0;
ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) && map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
@@ -3710,12 +3737,14 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( map->list[m].flag.battleground && map->list[m].flag.pvp ) {
map->list[m].flag.pvp = 0;
ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
if( map->list[m].flag.battleground && (map->list[m].flag.gvg || map->list[m].flag.gvg_dungeon || map->list[m].flag.gvg_castle) ) {
map->list[m].flag.gvg = 0;
map->list[m].flag.gvg_dungeon = 0;
map->list[m].flag.gvg_castle = 0;
ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) && map->list[m].zone != zone ) {
@@ -3818,10 +3847,13 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( modifier[0] == '\0' ) {
ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if( !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) ) {
ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n",skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else {
int idx = map->list[m].unit_count;
@@ -3874,10 +3906,13 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( modifier[0] == '\0' ) {
ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if( !( skill_id = skill->name2id(skill_name) ) ) {
ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else {
int idx = map->list[m].skill_count;
@@ -3916,6 +3951,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( !(zone = strdb_get(map->zone_db, w4)) ) {
ShowWarning("npc_parse_mapflag: Invalid zone '%s'! removing flag from %s in file '%s', line '%d'.\n", w4, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if( map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
}
@@ -3939,15 +3975,25 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
map->list[m].flag.src4instance = (state) ? 1 : 0;
} else if ( !strcmpi(w3,"nocashshop") ) {
map->list[m].flag.nocashshop = (state) ? 1 : 0;
- } else
+ } else {
ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
+ }
return strchr(start,'\n');// continue
}
-//Read file and create npc/func/mapflag/monster... accordingly.
-//@runOnInit should we exec OnInit when it's done ?
+/**
+ * Parses a script file and creates NPCs/functions/mapflags/monsters/etc
+ * accordingly.
+ *
+ * @param filepath File name and path.
+ * @param runOnInit Whether the OnInit label should be called.
+ * @retval EXIT_SUCCESS if filepath was loaded correctly.
+ * @retval EXIT_FAILURE if there were errors/warnings when loading filepath.
+ */
int npc_parsesrcfile(const char* filepath, bool runOnInit) {
+ int success = EXIT_SUCCESS;
int16 m, x, y;
int lines = 0;
FILE* fp;
@@ -3957,10 +4003,9 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
// read whole file to buffer
fp = fopen(filepath, "rb");
- if( fp == NULL )
- {
+ if( fp == NULL ) {
ShowError("npc_parsesrcfile: File not found '%s'.\n", filepath);
- return -1;
+ return EXIT_FAILURE;
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
@@ -3968,12 +4013,11 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
fseek(fp, 0, SEEK_SET);
len = fread(buffer, sizeof(char), len, fp);
buffer[len] = '\0';
- if( ferror(fp) )
- {
+ if( ferror(fp) ) {
ShowError("npc_parsesrcfile: Failed to read file '%s' - %s\n", filepath, strerror(errno));
aFree(buffer);
fclose(fp);
- return -1;
+ return EXIT_FAILURE;
}
fclose(fp);
@@ -3986,12 +4030,11 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
ShowError("npc_parsesrcfile: Detected unsupported UTF-8 BOM in file '%s'. Stopping (please consider using another character set.)\n", filepath);
aFree(buffer);
fclose(fp);
- return -1;
+ return EXIT_FAILURE;
}
// parse buffer
- for( p = script->skip_space(buffer); p && *p ; p = script->skip_space(p) )
- {
+ for( p = script->skip_space(buffer); p && *p ; p = script->skip_space(p) ) {
int pos[9];
char w1[2048], w2[2048], w3[2048], w4[2048];
int i, count;
@@ -4002,41 +4045,50 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
if( count < 0 )
{
ShowError("npc_parsesrcfile: Parse error in file '%s', line '%d'. Stopping...\n", filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
break;
}
// fill w1
- if( pos[3]-pos[2] > ARRAYLENGTH(w1)-1 )
+ if( pos[3]-pos[2] > ARRAYLENGTH(w1)-1 ) {
ShowWarning("npc_parsesrcfile: w1 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[3]-pos[2], filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
+ }
i = min(pos[3]-pos[2], ARRAYLENGTH(w1)-1);
memcpy(w1, p+pos[2], i*sizeof(char));
w1[i] = '\0';
// fill w2
- if( pos[5]-pos[4] > ARRAYLENGTH(w2)-1 )
+ if( pos[5]-pos[4] > ARRAYLENGTH(w2)-1 ) {
ShowWarning("npc_parsesrcfile: w2 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[5]-pos[4], filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
+ }
i = min(pos[5]-pos[4], ARRAYLENGTH(w2)-1);
memcpy(w2, p+pos[4], i*sizeof(char));
w2[i] = '\0';
// fill w3
- if( pos[7]-pos[6] > ARRAYLENGTH(w3)-1 )
+ if( pos[7]-pos[6] > ARRAYLENGTH(w3)-1 ) {
ShowWarning("npc_parsesrcfile: w3 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[7]-pos[6], filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
+ }
i = min(pos[7]-pos[6], ARRAYLENGTH(w3)-1);
memcpy(w3, p+pos[6], i*sizeof(char));
w3[i] = '\0';
// fill w4 (to end of line)
- if( pos[1]-pos[8] > ARRAYLENGTH(w4)-1 )
+ if( pos[1]-pos[8] > ARRAYLENGTH(w4)-1 ) {
ShowWarning("npc_parsesrcfile: w4 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[1]-pos[8], filepath, strline(buffer,p-buffer));
- if( pos[8] != -1 )
- {
+ success = EXIT_FAILURE;
+ }
+ if( pos[8] != -1 ) {
i = min(pos[1]-pos[8], ARRAYLENGTH(w4)-1);
memcpy(w4, p+pos[8], i*sizeof(char));
w4[i] = '\0';
- }
- else
+ } else {
w4[0] = '\0';
+ }
- if( count < 3 )
- {// Unknown syntax
+ if( count < 3 ) {
+ // Unknown syntax
ShowError("npc_parsesrcfile: Unknown syntax in file '%s', line '%d'. Stopping...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
+ success = EXIT_FAILURE;
break;
}
@@ -4045,13 +4097,12 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
char mapname[MAP_NAME_LENGTH*2];
x = y = 0;
sscanf(w1,"%23[^,],%hd,%hd[^,]",mapname,&x,&y);
- if( !mapindex->name2id(mapname) )
- {// Incorrect map, we must skip the script info...
+ if( !mapindex->name2id(mapname) ) {
+ // Incorrect map, we must skip the script info...
ShowError("npc_parsesrcfile: Unknown map '%s' in file '%s', line '%d'. Skipping line...\n", mapname, filepath, strline(buffer,p-buffer));
- if( strcmp(w2,"script") == 0 && count > 3 )
- {
- if((p = npc->skip_script(p,buffer,filepath)) == NULL)
- {
+ success = EXIT_FAILURE;
+ if( strcmp(w2,"script") == 0 && count > 3 ) {
+ if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) {
break;
}
}
@@ -4061,10 +4112,8 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
m = map->mapname2mapid(mapname);
if( m < 0 ) {
// "mapname" is not assigned to this server, we must skip the script info...
- if( strcmp(w2,"script") == 0 && count > 3 )
- {
- if((p = npc->skip_script(p,buffer,filepath)) == NULL)
- {
+ if( strcmp(w2,"script") == 0 && count > 3 ) {
+ if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) {
break;
}
}
@@ -4073,10 +4122,9 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
}
if (x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys) {
ShowError("npc_parsesrcfile: Unknown coordinates ('%d', '%d') for map '%s' in file '%s', line '%d'. Skipping line...\n", x, y, mapname, filepath, strline(buffer,p-buffer));
- if( strcmp(w2,"script") == 0 && count > 3 )
- {
- if((p = npc->skip_script(p,buffer,filepath)) == NULL)
- {
+ success = EXIT_FAILURE;
+ if( strcmp(w2,"script") == 0 && count > 3 ) {
+ if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) {
break;
}
}
@@ -4087,37 +4135,37 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
if( strcmp(w2,"warp") == 0 && count > 3 )
{
- p = npc->parse_warp(w1,w2,w3,w4, p, buffer, filepath);
+ p = npc->parse_warp(w1,w2,w3,w4, p, buffer, filepath, &success);
}
else if( (strcmp(w2,"shop") == 0 || strcmp(w2,"cashshop") == 0) && count > 3 )
{
- p = npc->parse_shop(w1,w2,w3,w4, p, buffer, filepath);
+ p = npc->parse_shop(w1,w2,w3,w4, p, buffer, filepath, &success);
}
else if( strcmp(w2,"script") == 0 && count > 3 )
{
if( strcmp(w1,"function") == 0 ) {
- p = npc->parse_function(w1, w2, w3, w4, p, buffer, filepath);
+ p = npc->parse_function(w1, w2, w3, w4, p, buffer, filepath, &success);
} else {
#ifdef ENABLE_CASE_CHECK
if( strcasecmp(w1, "function") == 0 ) DeprecationWarning("npc_parsesrcfile", w1, "function", filepath, strline(buffer, p-buffer)); // TODO
#endif // ENABLE_CASE_CHECK
- p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE);
+ p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE, &success);
}
}
else if( strcmp(w2,"trader") == 0 && count > 3 ) {
- p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,(runOnInit?NPO_ONINIT:NPO_NONE)|NPO_TRADER);
+ p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,(runOnInit?NPO_ONINIT:NPO_NONE)|NPO_TRADER, &success);
}
else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3 )
{
- p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath, (runOnInit?NPO_ONINIT:NPO_NONE));
+ p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath, (runOnInit?NPO_ONINIT:NPO_NONE), &success);
}
else if( (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0) && count > 3 )
{
- p = npc->parse_mob(w1, w2, w3, w4, p, buffer, filepath);
+ p = npc->parse_mob(w1, w2, w3, w4, p, buffer, filepath, &success);
}
else if( strcmp(w2,"mapflag") == 0 && count >= 3 )
{
- p = npc->parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath);
+ p = npc->parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath, &success);
}
else
{
@@ -4139,11 +4187,12 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
#endif // ENABLE_CASE_CHECK
ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
p = strchr(p,'\n');// skip and continue
+ success = EXIT_FAILURE;
}
}
aFree(buffer);
- return 0;
+ return success;
}
int npc_script_event(struct map_session_data* sd, enum npce_event type)
diff --git a/src/map/npc.h b/src/map/npc.h
index d1e060a39..d11db0164 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -232,12 +232,12 @@ struct npc_interface {
int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath);
bool (*viewisid) (const char *viewid);
struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);
- const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
- const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
+ const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath);
- const char* (*skip_script) (const char *start, const char *buffer, const char *filepath);
- const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options);
- const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options);
+ const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval);
+ const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval);
int (*duplicate4instance) (struct npc_data *snd, int16 m);
void (*setcells) (struct npc_data *nd);
int (*unsetcells_sub) (struct block_list *bl, va_list ap);
@@ -246,10 +246,10 @@ struct npc_interface {
void (*setdisplayname) (struct npc_data *nd, const char *newname);
void (*setclass) (struct npc_data *nd, short class_);
int (*do_atcmd_event) (struct map_session_data *sd, const char *command, const char *message, const char *eventname);
- const char* (*parse_function) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
+ const char* (*parse_function) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
void (*parse_mob2) (struct spawn_data *mobspawn);
- const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
- const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
+ const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
int (*parsesrcfile) (const char *filepath, bool runOnInit);
int (*script_event) (struct map_session_data *sd, enum npce_event type);
void (*read_event_script) (void);
diff --git a/src/map/pet.c b/src/map/pet.c
index b5870a858..993497434 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -1327,9 +1327,9 @@ int read_petdb()
pet->db[j].equip_script = NULL;
if( *str[20] )
- pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0);
+ pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL);
if( *str[21] )
- pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0);
+ pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL);
j++;
entries++;
diff --git a/src/map/script.c b/src/map/script.c
index aea4d978f..aecdf9b28 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2242,8 +2242,7 @@ void script_warning(const char* src, const char* file, int start_line, const cha
/*==========================================
* Analysis of the script
*------------------------------------------*/
-struct script_code* parse_script(const char *src,const char *file,int line,int options)
-{
+struct script_code* parse_script(const char *src,const char *file,int line,int options, int *retval) {
const char *p,*tmpp;
int i;
struct script_code* code = NULL;
@@ -2289,6 +2288,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
script->parser_current_file = NULL;
script->parser_current_line = 0;
#endif // ENABLE_CASE_CHECK
+ if (retval) *retval = EXIT_FAILURE;
return NULL;
}
@@ -2315,8 +2315,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
}
else
{// requires brackets around the script
- if( *p != '{' )
+ if( *p != '{' ) {
disp_error_message("not found '{'",p);
+ if (retval) *retval = EXIT_FAILURE;
+ }
p = script->skip_space(p+1);
if( *p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) )
{// empty script and can return NULL
@@ -2391,13 +2393,14 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
else if( script->str_data[i].type == C_USERFUNC )
{// 'function name;' without follow-up code
ShowError("parse_script: function '%s' declared but not defined.\n", script->str_buf+script->str_data[i].str);
+ if (retval) *retval = EXIT_FAILURE;
unresolved_names = true;
}
}
- if( unresolved_names )
- {
+ if( unresolved_names ) {
disp_error_message("parse_script: unresolved function references", p);
+ if (retval) *retval = EXIT_FAILURE;
}
#ifdef SCRIPT_DEBUG_DISP
@@ -4203,7 +4206,7 @@ void script_run_autobonus(const char *autobonus, int id, int pos)
void script_add_autobonus(const char *autobonus)
{
if( strdb_get(script->autobonus_db, autobonus) == NULL ) {
- struct script_code *scriptroot = script->parse(autobonus, "autobonus", 0, 0);
+ struct script_code *scriptroot = script->parse(autobonus, "autobonus", 0, 0, NULL);
if( scriptroot )
strdb_put(script->autobonus_db, autobonus, scriptroot);
@@ -11041,7 +11044,7 @@ BUILDIN(setmapflag) {
char empty[1] = "\0";
char params[MAP_ZONE_MAPFLAG_LENGTH];
memcpy(params, val2, MAP_ZONE_MAPFLAG_LENGTH);
- npc->parse_mapflag(map->list[m].name, empty, zone, params, empty, empty, empty);
+ npc->parse_mapflag(map->list[m].name, empty, zone, params, empty, empty, empty, NULL);
}
break;
case MF_NOCOMMAND: map->list[m].nocommand = (val <= 0) ? 100 : val; break;
@@ -15100,7 +15103,7 @@ BUILDIN(setitemscript)
if(*dstscript)
script->free_code(*dstscript);
- *dstscript = new_bonus_script[0] ? script->parse(new_bonus_script, "script_setitemscript", 0, 0) : NULL;
+ *dstscript = new_bonus_script[0] ? script->parse(new_bonus_script, "script_setitemscript", 0, 0, NULL) : NULL;
script_pushint(st,1);
return true;
}
diff --git a/src/map/script.h b/src/map/script.h
index eed0dbf1d..90b18d87f 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -564,7 +564,7 @@ struct script_interface {
void (*final) (void);
int (*reload) (void);
/* parse */
- struct script_code* (*parse) (const char* src,const char* file,int line,int options);
+ struct script_code* (*parse) (const char* src,const char* file,int line,int options, int *retval);
bool (*add_builtin) (const struct script_function *buildin, bool override);
void (*parse_builtin) (void);
const char* (*parse_subexpr) (const char* p,int limit);