From 95ab2826ecdf4db25bf19d9348ff334f9304a201 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Dec 2014 23:53:00 +0100 Subject: [PATCH 01/21] avoid running over the array of locales in order.c when re-creating locales for tests. --- src/kernel/order.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/kernel/order.c b/src/kernel/order.c index d98853127..98d7919d6 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -40,8 +40,7 @@ typedef struct locale_data { const struct locale *lang; } locale_data; -static struct locale_data *locale_array[16]; -static int nlocales = 0; +static struct locale_data *locale_array[MAXLOCALES]; typedef struct order_data { const char *_str; @@ -272,15 +271,10 @@ static order *create_order_i(keyword_t kwd, const char *sptr, int persistent, } } - for (lindex = 0; lindex != nlocales; ++lindex) { - if (locale_array[lindex]->lang == lang) - break; - } - if (lindex == nlocales) { - locale_array[nlocales] = (locale_data *)calloc(1, sizeof(locale_data)); - locale_array[nlocales]->lang = lang; - ++nlocales; - } + lindex = locale_index(lang); + assert(lindex < MAXLOCALES); + locale_array[lindex] = (locale_data *)calloc(1, sizeof(locale_data)); + locale_array[lindex]->lang = lang; ord = (order *)malloc(sizeof(order)); ord->_persistent = persistent; From 077a0aeeef41d94eb4a549cb445043f381ecc59e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Dec 2014 00:00:57 +0100 Subject: [PATCH 02/21] plug some new memory leaks --- src/kernel/order.c | 5 +---- src/util/language.c | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/kernel/order.c b/src/kernel/order.c index 98d7919d6..4126c4a03 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -563,10 +563,7 @@ void push_order(order ** ordp, order * ord) keyword_t init_order(const struct order *ord) { - char *cmd = 0; - assert(ord && ord->data); - if (ord->data->_str) cmd = _strdup(ord->data->_str); - init_tokens_str(cmd); + init_tokens_str(ord->data->_str); return ord->data->_keyword; } diff --git a/src/util/language.c b/src/util/language.c index 3899a533b..b55afd5eb 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -319,6 +319,7 @@ void free_locales(void) { free(strings); } } + free(locales->name); free(locales); locales = next; } From 89ce04a6c33dc082720d9bde0f7a6fd856ca63d7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Dec 2014 00:02:27 +0100 Subject: [PATCH 03/21] this obviously cannot be const, then. fix the build. --- src/util/language_struct.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/language_struct.h b/src/util/language_struct.h index 14f331710..84932532e 100644 --- a/src/util/language_struct.h +++ b/src/util/language_struct.h @@ -14,7 +14,7 @@ typedef struct locale_str { } locale_str; typedef struct locale { - const char *name; + char *name; unsigned int index; struct locale *next; unsigned int hashkey; From 49a77cdcdedaf77e807e0cb74a68c96b9df99a6b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Dec 2014 01:44:28 +0100 Subject: [PATCH 04/21] plug some more memory leaks. --- src/kernel/race.c | 2 ++ src/kernel/race.h | 4 ++-- src/kernel/ship.c | 7 ++++++- src/kernel/ship.h | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/kernel/race.c b/src/kernel/race.c index 627882d8b..14541346e 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -141,6 +141,8 @@ void racelist_insert(struct race_list **rl, const struct race *r) void free_races(void) { while (races) { race * rc = races->next; + free(races->_name); + free(races->def_damage); free(races); races = rc; } diff --git a/src/kernel/race.h b/src/kernel/race.h index b0801e5e5..6882af222 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -119,7 +119,7 @@ extern "C" { typedef struct race { struct param *parameters; - const char *_name; + char *_name; float magres; float maxaura; /* Faktor auf Maximale Aura */ float regaura; /* Faktor auf Regeneration */ @@ -133,7 +133,7 @@ extern "C" { float speed; float aggression; /* chance that a monster will attack */ int hitpoints; - const char *def_damage; + char *def_damage; int armor; int at_default; /* Angriffsskill Unbewaffnet (default: -2) */ int df_default; /* Verteidigungsskill Unbewaffnet (default: -2) */ diff --git a/src/kernel/ship.c b/src/kernel/ship.c index afd3dc9f3..b0fc8e06c 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -238,8 +238,13 @@ void free_ship(ship * s) free(s); } +static void free_shiptype(ship_type *stype) { + free(stype->_name); + free(stype); +} + void free_shiptypes(void) { - ql_foreach(shiptypes, free); + ql_foreach(shiptypes, free_shiptype); ql_free(shiptypes); shiptypes = 0; } diff --git a/src/kernel/ship.h b/src/kernel/ship.h index d879837d8..b493693de 100644 --- a/src/kernel/ship.h +++ b/src/kernel/ship.h @@ -33,7 +33,7 @@ extern "C" { #define SFL_NOCOAST 0x04 typedef struct ship_type { - const char *_name; + char *_name; int range; /* range in regions */ int flags; /* flags */ From a55cb139248781f4319bd25f4afe98e242a9fd36 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Dec 2014 02:02:10 +0100 Subject: [PATCH 05/21] make valgrind happy when running tests (cleanup) --- src/kernel/building.test.c | 10 ++++++++++ src/kernel/terrain.c | 4 +--- src/kernel/terrain.h | 5 +---- src/tests.c | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index cd29601eb..edbcce98b 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -22,6 +22,7 @@ static void test_register_building(CuTest * tc) bt_register(btype); CuAssertPtrNotNull(tc, bt_find("herp")); + test_cleanup(); } static void test_building_set_owner(CuTest * tc) @@ -51,6 +52,7 @@ static void test_building_set_owner(CuTest * tc) CuAssertPtrEquals(tc, u1, building_owner(bld)); building_set_owner(u2); CuAssertPtrEquals(tc, u2, building_owner(bld)); + test_cleanup(); } static void test_buildingowner_goes_to_next_when_empty(CuTest * tc) @@ -85,6 +87,7 @@ static void test_buildingowner_goes_to_next_when_empty(CuTest * tc) CuAssertPtrEquals(tc, u, building_owner(bld)); u->number = 0; CuAssertPtrEquals(tc, u2, building_owner(bld)); + test_cleanup(); } static void test_buildingowner_goes_to_other_when_empty(CuTest * tc) @@ -120,6 +123,7 @@ static void test_buildingowner_goes_to_other_when_empty(CuTest * tc) CuAssertPtrEquals(tc, u, building_owner(bld)); u->number = 0; CuAssertPtrEquals(tc, u2, building_owner(bld)); + test_cleanup(); } static void test_buildingowner_goes_to_same_faction_when_empty(CuTest * tc) @@ -159,6 +163,7 @@ static void test_buildingowner_goes_to_same_faction_when_empty(CuTest * tc) CuAssertPtrEquals(tc, u3, building_owner(bld)); u3->number = 0; CuAssertPtrEquals(tc, u2, building_owner(bld)); + test_cleanup(); } static void test_buildingowner_goes_to_next_after_leave(CuTest * tc) @@ -193,6 +198,7 @@ static void test_buildingowner_goes_to_next_after_leave(CuTest * tc) CuAssertPtrEquals(tc, u, building_owner(bld)); leave_building(u); CuAssertPtrEquals(tc, u2, building_owner(bld)); + test_cleanup(); } static void test_buildingowner_goes_to_other_after_leave(CuTest * tc) @@ -227,6 +233,7 @@ static void test_buildingowner_goes_to_other_after_leave(CuTest * tc) CuAssertPtrEquals(tc, u, building_owner(bld)); leave_building(u); CuAssertPtrEquals(tc, u2, building_owner(bld)); + test_cleanup(); } static void test_buildingowner_goes_to_same_faction_after_leave(CuTest * tc) @@ -268,6 +275,7 @@ static void test_buildingowner_goes_to_same_faction_after_leave(CuTest * tc) CuAssertPtrEquals(tc, u2, building_owner(bld)); leave_building(u2); CuAssertPtrEquals(tc, 0, building_owner(bld)); + test_cleanup(); } static void test_buildingowner_resets_when_empty(CuTest * tc) @@ -302,6 +310,7 @@ static void test_buildingowner_resets_when_empty(CuTest * tc) CuAssertPtrEquals(tc, 0, building_owner(bld)); u->number = 1; CuAssertPtrEquals(tc, u, building_owner(bld)); + test_cleanup(); } void test_buildingowner_goes_to_empty_unit_after_leave(CuTest * tc) @@ -343,6 +352,7 @@ void test_buildingowner_goes_to_empty_unit_after_leave(CuTest * tc) CuAssertPtrEquals(tc, 0, building_owner(bld)); u2->number = 1; CuAssertPtrEquals(tc, u2, building_owner(bld)); + test_cleanup(); } CuSuite *get_building_suite(void) diff --git a/src/kernel/terrain.c b/src/kernel/terrain.c index 4728d7b2b..076e64da6 100644 --- a/src/kernel/terrain.c +++ b/src/kernel/terrain.c @@ -63,8 +63,7 @@ const char *terraindata[MAXTERRAINS] = { static terrain_type *registered_terrains; -#ifndef DISABLE_TESTS -void test_clear_terrains(void) +void free_terrains(void) { while (registered_terrains) { terrain_type * t = registered_terrains; @@ -74,7 +73,6 @@ void test_clear_terrains(void) free(t); } } -#endif const terrain_type *terrains(void) { diff --git a/src/kernel/terrain.h b/src/kernel/terrain.h index 15e0318a9..3630a2e7b 100644 --- a/src/kernel/terrain.h +++ b/src/kernel/terrain.h @@ -75,10 +75,7 @@ extern "C" { extern const char *terrain_name(const struct region *r); extern void init_terrains(void); - -#ifndef DISABLE_TESTS - void test_clear_terrains(void); -#endif + void free_terrains(void); #ifdef __cplusplus } diff --git a/src/tests.c b/src/tests.c index 7f7b73d75..1de72b768 100644 --- a/src/tests.c +++ b/src/tests.c @@ -57,7 +57,7 @@ struct unit *test_create_unit(struct faction *f, struct region *r) void test_cleanup(void) { - test_clear_terrains(); + free_terrains(); test_clear_resources(); global.functions.maintenance = NULL; global.functions.wage = NULL; From 9f09b9b915a9efcca6d273534a0e9eeeb91b375d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Dec 2014 23:34:24 +0100 Subject: [PATCH 06/21] fixed memory leaks in tests, thanks to valgrind --- src/json.test.c | 4 ++++ src/kernel/build.test.c | 8 ++++++++ src/kernel/building.c | 8 +++++++- src/kernel/building.h | 2 +- src/kernel/building.test.c | 2 ++ src/kernel/ship.c | 3 ++- src/market.test.c | 3 ++- src/tests.test.c | 5 +++++ src/vortex.c | 4 +++- 9 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/json.test.c b/src/json.test.c index 5b3f9813e..53e7cf336 100644 --- a/src/json.test.c +++ b/src/json.test.c @@ -45,6 +45,7 @@ static void test_export_no_regions(CuTest * tc) { buf[len] = '\0'; CuAssertStrEquals(tc, "{}", strip(buf)); mstream_done(&out); + test_cleanup(); } static cJSON *export_a_region(CuTest * tc, const struct terrain_type *terrain, region **_r) { @@ -93,6 +94,7 @@ static void test_export_land_region(CuTest * tc) { CuAssertPtrNotNull(tc, attr = cJSON_GetObjectItem(json, "name")); CuAssertStrEquals(tc, r->land->name, attr->valuestring); cJSON_Delete(json); + test_cleanup(); } static void test_export_ocean_region(CuTest * tc) { @@ -103,6 +105,7 @@ static void test_export_ocean_region(CuTest * tc) { json = export_a_region(tc, terrain, 0); CuAssertPtrEquals(tc, 0, cJSON_GetObjectItem(json, "name")); cJSON_Delete(json); + test_cleanup(); } static void test_export_no_factions(CuTest * tc) { @@ -119,6 +122,7 @@ static void test_export_no_factions(CuTest * tc) { buf[len]=0; CuAssertStrEquals(tc, "{}", strip(buf)); mstream_done(&out); + test_cleanup(); } CuSuite *get_json_suite(void) { diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 1dc8e86e8..7e74c5cbb 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -57,6 +57,7 @@ static void test_build_requires_materials(CuTest *tc) { i_change(&u->items, itype, 2); CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1)); CuAssertIntEquals(tc, 1, i_get(u->items, itype)); + test_cleanup(); } static void test_build_requires_building(CuTest *tc) { @@ -78,6 +79,7 @@ static void test_build_requires_building(CuTest *tc) { CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1)); btype->maxcapacity = 0; CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1)); + test_cleanup(); } static void test_build_failure_missing_skill(CuTest *tc) { @@ -89,6 +91,7 @@ static void test_build_failure_missing_skill(CuTest *tc) { rtype = bf.cons.materials[0].rtype; i_change(&u->items, rtype->itype, 1); CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1)); + test_cleanup(); } static void test_build_failure_low_skill(CuTest *tc) { @@ -101,6 +104,7 @@ static void test_build_failure_low_skill(CuTest *tc) { i_change(&u->items, rtype->itype, 1); set_level(u, SK_ARMORER, bf.cons.minskill-1); CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10)); + test_cleanup(); } static void test_build_failure_completed(CuTest *tc) { @@ -115,6 +119,7 @@ static void test_build_failure_completed(CuTest *tc) { bf.cons.maxsize = 1; CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10)); CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype)); + test_cleanup(); } static void test_build_limits(CuTest *tc) { @@ -202,6 +207,7 @@ static void test_build_building_no_materials(CuTest *tc) { CuAssertIntEquals(tc, ENOMATERIALS, build_building(u, btype, 0, 4, 0)); CuAssertPtrEquals(tc, 0, u->region->buildings); CuAssertPtrEquals(tc, 0, u->building); + test_cleanup(); } static void test_build_building_with_golem(CuTest *tc) { @@ -220,6 +226,7 @@ static void test_build_building_with_golem(CuTest *tc) { CuAssertPtrNotNull(tc, u->region->buildings); CuAssertIntEquals(tc, 1, u->region->buildings->size); CuAssertIntEquals(tc, 0, u->number); + test_cleanup(); } static void test_build_building_success(CuTest *tc) { @@ -243,6 +250,7 @@ static void test_build_building_success(CuTest *tc) { CuAssertPtrEquals(tc, u->region->buildings, u->building); CuAssertIntEquals(tc, 1, u->building->size); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); + test_cleanup(); } CuSuite *get_build_suite(void) diff --git a/src/kernel/building.c b/src/kernel/building.c index ca45d85a9..bd3463744 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -92,8 +92,14 @@ void bt_register(building_type * type) ql_push(&buildingtypes, (void *)type); } +void free_buildingtype(void *ptr) { + building_type *btype =(building_type *)ptr; + free(btype->_name); + free(btype); +} + void free_buildingtypes(void) { - ql_foreach(buildingtypes, free); + ql_foreach(buildingtypes, free_buildingtype); ql_free(buildingtypes); buildingtypes = 0; } diff --git a/src/kernel/building.h b/src/kernel/building.h index 488e8f691..cf80de84f 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -49,7 +49,7 @@ extern "C" { #define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */ typedef struct building_type { - const char *_name; + char *_name; int flags; /* flags */ int capacity; /* Kapazität pro Größenpunkt */ diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index edbcce98b..2295c8193 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -22,6 +22,8 @@ static void test_register_building(CuTest * tc) bt_register(btype); CuAssertPtrNotNull(tc, bt_find("herp")); +// free(btype->_name); +// free(btype); test_cleanup(); } diff --git a/src/kernel/ship.c b/src/kernel/ship.c index b0fc8e06c..ad2ff7541 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -238,7 +238,8 @@ void free_ship(ship * s) free(s); } -static void free_shiptype(ship_type *stype) { +static void free_shiptype(void *ptr) { + ship_type *stype = (ship_type *)ptr; free(stype->_name); free(stype); } diff --git a/src/market.test.c b/src/market.test.c index bb2c682ba..781577ff0 100644 --- a/src/market.test.c +++ b/src/market.test.c @@ -17,6 +17,7 @@ #include #include +#include static void test_market_curse(CuTest * tc) { @@ -45,7 +46,7 @@ static void test_market_curse(CuTest * tc) set_param(&global.parameters, "rules.region_owners", "1"); btype = (building_type *)calloc(1, sizeof(building_type)); - btype->_name = "market"; + btype->_name = _strdup("market"); bt_register(btype); terrain = get_terrain("plain"); diff --git a/src/tests.test.c b/src/tests.test.c index 7e36b193e..fc2097516 100644 --- a/src/tests.test.c +++ b/src/tests.test.c @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -45,6 +46,8 @@ static void test_recreate_world(CuTest * tc) CuAssertPtrEquals(tc, default_locale, get_locale("de")); CuAssertPtrNotNull(tc, default_locale); CuAssertPtrNotNull(tc, findregion(0, 0)); + CuAssertPtrNotNull(tc, get_terrain("plain")); + CuAssertPtrNotNull(tc, get_terrain("ocean")); CuAssertPtrNotNull(tc, (void *)rt_find("horse")); CuAssertPtrNotNull(tc, get_resourcetype(R_HORSE)); CuAssertPtrNotNull(tc, (void *)rt_find("money")); @@ -56,6 +59,8 @@ static void test_recreate_world(CuTest * tc) test_cleanup(); CuAssertPtrEquals(tc, 0, get_locale("de")); + CuAssertPtrEquals(tc, 0, (void*)get_terrain("plain")); + CuAssertPtrEquals(tc, 0, (void*)get_terrain("ocean")); CuAssertPtrEquals(tc, 0, (void*)rt_find("horse")); CuAssertPtrEquals(tc, 0, (void*)get_resourcetype(R_HORSE)); CuAssertPtrNotNull(tc, (void *)rt_find("money")); diff --git a/src/vortex.c b/src/vortex.c index a44b90172..e01dcd1d2 100644 --- a/src/vortex.c +++ b/src/vortex.c @@ -61,7 +61,9 @@ static void a_initdirection(attrib * a) static void a_freedirection(attrib * a) { - free(a->data.v); + spec_direction *d = (spec_direction *)(a->data.v); + free(d->desc); + free(d); } static int a_agedirection(attrib * a) From 228983202d53b0de24ff5c34fef1f59d9714fda1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Dec 2014 23:49:50 +0100 Subject: [PATCH 07/21] properly free items at cleanup. --- src/json.test.c | 4 ++++ src/kernel/item.c | 11 +++++------ src/kernel/item.h | 4 +--- src/kernel/spellbook.c | 1 + src/tests.c | 3 +-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/json.test.c b/src/json.test.c index 5b3f9813e..53e7cf336 100644 --- a/src/json.test.c +++ b/src/json.test.c @@ -45,6 +45,7 @@ static void test_export_no_regions(CuTest * tc) { buf[len] = '\0'; CuAssertStrEquals(tc, "{}", strip(buf)); mstream_done(&out); + test_cleanup(); } static cJSON *export_a_region(CuTest * tc, const struct terrain_type *terrain, region **_r) { @@ -93,6 +94,7 @@ static void test_export_land_region(CuTest * tc) { CuAssertPtrNotNull(tc, attr = cJSON_GetObjectItem(json, "name")); CuAssertStrEquals(tc, r->land->name, attr->valuestring); cJSON_Delete(json); + test_cleanup(); } static void test_export_ocean_region(CuTest * tc) { @@ -103,6 +105,7 @@ static void test_export_ocean_region(CuTest * tc) { json = export_a_region(tc, terrain, 0); CuAssertPtrEquals(tc, 0, cJSON_GetObjectItem(json, "name")); cJSON_Delete(json); + test_cleanup(); } static void test_export_no_factions(CuTest * tc) { @@ -119,6 +122,7 @@ static void test_export_no_factions(CuTest * tc) { buf[len]=0; CuAssertStrEquals(tc, "{}", strip(buf)); mstream_done(&out); + test_cleanup(); } CuSuite *get_json_suite(void) { diff --git a/src/kernel/item.c b/src/kernel/item.c index 320864122..7fe07c18b 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -1167,10 +1167,7 @@ static item *default_spoil(const struct race *rc, int size) return itm; } -#ifndef DISABLE_TESTS -int free_itype_cb(const void * match, const void * key, size_t keylen, void *cbdata) { - item_type *itype; - cb_get_kv(match, &itype, sizeof(itype)); +int free_itype(item_type *itype) { free(itype->construction); free(itype->_appearance[0]); free(itype->_appearance[1]); @@ -1182,11 +1179,14 @@ int free_rtype_cb(const void * match, const void * key, size_t keylen, void *cbd resource_type *rtype; cb_get_kv(match, &rtype, sizeof(rtype)); free(rtype->_name); + if (rtype->itype) { + free_itype(rtype->itype); + } free(rtype); return 0; } -void test_clear_resources(void) +void free_resources(void) { int i; @@ -1201,7 +1201,6 @@ void test_clear_resources(void) cb_clear(rnames + i); } } -#endif void register_resources(void) { diff --git a/src/kernel/item.h b/src/kernel/item.h index b3ea13bfc..afccf8ba9 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -324,9 +324,7 @@ extern "C" { extern void register_item_useonother(int (*foo) (struct unit *, int, const struct item_type *, int, struct order *), const char *name); -#ifndef DISABLE_TESTS - void test_clear_resources(void); -#endif + void free_resources(void); #ifdef __cplusplus } diff --git a/src/kernel/spellbook.c b/src/kernel/spellbook.c index 6634e04f6..6e31f2a79 100644 --- a/src/kernel/spellbook.c +++ b/src/kernel/spellbook.c @@ -45,6 +45,7 @@ void spellbook_clear(spellbook *sb) free(sbe); } ql_free(sb->spells); + free(sb->name); } int spellbook_foreach(spellbook *sb, int (*callback)(spellbook_entry *, void *), void * data) diff --git a/src/tests.c b/src/tests.c index 1de72b768..79ff5ad38 100644 --- a/src/tests.c +++ b/src/tests.c @@ -58,7 +58,7 @@ struct unit *test_create_unit(struct faction *f, struct region *r) void test_cleanup(void) { free_terrains(); - test_clear_resources(); + free_resources(); global.functions.maintenance = NULL; global.functions.wage = NULL; default_locale = 0; @@ -75,7 +75,6 @@ terrain_type * test_create_terrain(const char * name, unsigned int flags) { terrain_type * t = get_or_create_terrain(name); - t->_name = _strdup(name); t->flags = flags; return t; } From e04a541167f0ab602d9fda21c97f7157afbf7fe0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 00:16:24 +0100 Subject: [PATCH 08/21] do not initialize resources in test_cleanup, that makes no sense. --- src/kernel/config.c | 2 -- src/tests.test.c | 18 ++++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/kernel/config.c b/src/kernel/config.c index c7fa16fff..4e42f4e0c 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1759,8 +1759,6 @@ void free_gamedata(void) a_remove(&global.attribs, global.attribs); } ++global.cookie; /* readgame() already does this, but sjust in case */ - - init_resources(); } const char * game_name(void) { diff --git a/src/tests.test.c b/src/tests.test.c index fc2097516..06b59b175 100644 --- a/src/tests.test.c +++ b/src/tests.test.c @@ -13,6 +13,7 @@ static void test_resources(CuTest *tc) { resource_type *rtype; test_cleanup(); + init_resources(); CuAssertPtrNotNull(tc, rt_find("hp")); CuAssertPtrEquals(tc, rt_find("hp"), (void *)get_resourcetype(R_LIFE)); CuAssertPtrNotNull(tc, rt_find("peasant")); @@ -28,6 +29,7 @@ static void test_resources(CuTest *tc) { CuAssertPtrEquals(tc, (void *)rtype, (void *)get_resourcetype(R_STONE)); test_cleanup(); CuAssertPtrEquals(tc, 0, rt_find("stone")); + CuAssertPtrEquals(tc, 0, rt_find("peasant")); rtype = rt_get_or_create("stone"); CuAssertPtrEquals(tc, (void *)rtype, (void *)get_resourcetype(R_STONE)); } @@ -37,10 +39,6 @@ static void test_recreate_world(CuTest * tc) test_cleanup(); CuAssertPtrEquals(tc, 0, get_locale("de")); CuAssertPtrEquals(tc, 0, (void *)rt_find("horse")); - CuAssertPtrNotNull(tc, get_resourcetype(R_LIFE)); - CuAssertPtrNotNull(tc, get_resourcetype(R_PERMAURA)); - CuAssertPtrNotNull(tc, get_resourcetype(R_AURA)); - CuAssertPtrNotNull(tc, (void *)rt_find("money")); test_create_world(); CuAssertPtrEquals(tc, default_locale, get_locale("de")); @@ -63,12 +61,12 @@ static void test_recreate_world(CuTest * tc) CuAssertPtrEquals(tc, 0, (void*)get_terrain("ocean")); CuAssertPtrEquals(tc, 0, (void*)rt_find("horse")); CuAssertPtrEquals(tc, 0, (void*)get_resourcetype(R_HORSE)); - CuAssertPtrNotNull(tc, (void *)rt_find("money")); - CuAssertPtrNotNull(tc, get_resourcetype(R_LIFE)); - CuAssertPtrNotNull(tc, get_resourcetype(R_SILVER)); - CuAssertPtrNotNull(tc, get_resourcetype(R_AURA)); - CuAssertPtrNotNull(tc, get_resourcetype(R_PERMAURA)); - CuAssertPtrNotNull(tc, get_resourcetype(R_PEASANT)); + CuAssertPtrEquals(tc, 0, (void *)rt_find("money")); + CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_LIFE)); + CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_SILVER)); + CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_AURA)); + CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_PERMAURA)); + CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_PEASANT)); CuAssertPtrEquals(tc, 0, findregion(0, 0)); } From 80be0a8e89513220aa391d78c40d9c50a18bd272 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 00:20:19 +0100 Subject: [PATCH 09/21] I broke the Lua tests, must initialize resources in eressea.free_game binding --- src/bind_eressea.c | 2 ++ src/kernel/item.h | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bind_eressea.c b/src/bind_eressea.c index a345f6c19..170a8cb08 100755 --- a/src/bind_eressea.c +++ b/src/bind_eressea.c @@ -5,6 +5,7 @@ #include "json.h" #include +#include #include #include @@ -14,6 +15,7 @@ void eressea_free_game(void) { free_gamedata(); + init_resources(); } int eressea_read_game(const char * filename) { diff --git a/src/kernel/item.h b/src/kernel/item.h index afccf8ba9..d40e2d90c 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -313,9 +313,9 @@ extern "C" { extern struct attrib_type at_showitem; /* show this potion's description */ - extern void register_resources(void); - extern void init_resources(void); - extern void init_itemtypes(void); + void register_resources(void); + void init_resources(void); + void init_itemtypes(void); extern void register_item_give(int (*foo) (struct unit *, struct unit *, const struct item_type *, int, struct order *), const char *name); From c39be8d5998069ac88fdf90e91ba086c9596378e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 01:00:10 +0100 Subject: [PATCH 10/21] more casual leak removal. --- src/kernel/config.c | 13 +- src/kernel/jsonconf.c | 2 +- src/kernel/order.test.c | 7 +- src/kernel/ship.c | 1 + src/kernel/ship.h | 128 +- src/kernel/spellbook.test.c | 2 + src/kernel/xmlreader.c | 3748 ++++++++++++++++++----------------- src/kernel/xmlreader.h | 6 +- src/move.test.c | 2 +- src/test_eressea.c | 1 + 10 files changed, 1979 insertions(+), 1931 deletions(-) diff --git a/src/kernel/config.c b/src/kernel/config.c index 4e42f4e0c..1de8c8c5f 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1047,23 +1047,24 @@ int get_param_int(const struct param *p, const char *key, int def) int check_param(const struct param *p, const char *key, const char *searchvalue) { + int result = 0; const char *value = get_param(p, key); if (!value) { return 0; } - char *p_value = malloc(sizeof(char)* (strlen(value) + 1)); - strcpy(p_value, value); + char *p_value = _strdup(value); const char *delimiter = " ,;"; char *v = strtok(p_value, delimiter); while (v != NULL) { - if (strcmp(v, searchvalue) == 0) - { - return 1; + if (strcmp(v, searchvalue) == 0) { + result = 1; + break; } v = strtok(NULL, delimiter); } - return 0; + free(p_value); + return result; } static const char *g_datadir; diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index d09aaf6ff..1a25d1465 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -304,7 +304,7 @@ static void json_ship(cJSON *json, ship_type *st) { } break; case cJSON_Array: - st->coasts = (const terrain_type **) + st->coasts = (terrain_type **) malloc(sizeof(terrain_type *) * (1+cJSON_GetArraySize(child))); for (i=0,iter=child->child;iter;iter=iter->next) { if (iter->type==cJSON_String) { diff --git a/src/kernel/order.test.c b/src/kernel/order.test.c index a45752c95..2ff7d8a4e 100644 --- a/src/kernel/order.test.c +++ b/src/kernel/order.test.c @@ -9,7 +9,6 @@ #include #include #include -#include static void test_create_order(CuTest *tc) { char cmd[32]; @@ -127,8 +126,7 @@ static void test_init_order(CuTest *tc) { } static void test_getstrtoken(CuTest *tc) { - char *cmd = _strdup("hurr \"durr\" \"\" \'\'"); - init_tokens_str(cmd); + init_tokens_str("hurr \"durr\" \"\" \'\'"); CuAssertStrEquals(tc, "hurr", getstrtoken()); CuAssertStrEquals(tc, "durr", getstrtoken()); CuAssertStrEquals(tc, "", getstrtoken()); @@ -139,8 +137,7 @@ static void test_getstrtoken(CuTest *tc) { } static void test_skip_token(CuTest *tc) { - char *cmd = _strdup("hurr \"durr\""); - init_tokens_str(cmd); + init_tokens_str("hurr \"durr\""); skip_token(); CuAssertStrEquals(tc, "durr", getstrtoken()); CuAssertStrEquals(tc, 0, getstrtoken()); diff --git a/src/kernel/ship.c b/src/kernel/ship.c index ad2ff7541..0cf04918c 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -241,6 +241,7 @@ void free_ship(ship * s) static void free_shiptype(void *ptr) { ship_type *stype = (ship_type *)ptr; free(stype->_name); + free(stype->coasts); free(stype); } diff --git a/src/kernel/ship.h b/src/kernel/ship.h index b493693de..ac132cc35 100644 --- a/src/kernel/ship.h +++ b/src/kernel/ship.h @@ -1,7 +1,7 @@ /* Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -27,46 +27,46 @@ extern "C" { #define DAMAGE_SCALE 100 /* multiplier for sh->damage */ -/* ship_type::flags */ + /* ship_type::flags */ #define SFL_OPENSEA 0x01 #define SFL_FLY 0x02 #define SFL_NOCOAST 0x04 - typedef struct ship_type { - char *_name; + typedef struct ship_type { + char *_name; - int range; /* range in regions */ - int flags; /* flags */ - int combat; /* modifier for combat */ + int range; /* range in regions */ + int flags; /* flags */ + int combat; /* modifier for combat */ - double storm; /* multiplier for chance to drift in storm */ - double damage; /* multiplier for damage taken by the ship */ + double storm; /* multiplier for chance to drift in storm */ + double damage; /* multiplier for damage taken by the ship */ - int cabins; /* max. cabins (weight) */ - int cargo; /* max. cargo (weight) */ + int cabins; /* max. cabins (weight) */ + int cargo; /* max. cargo (weight) */ - int cptskill; /* min. skill of captain */ - int minskill; /* min. skill to sail this (crew) */ - int sumskill; /* min. sum of crew+captain */ + int cptskill; /* min. skill of captain */ + int minskill; /* min. skill to sail this (crew) */ + int sumskill; /* min. sum of crew+captain */ - int fishing; /* weekly income from fishing */ + int fishing; /* weekly income from fishing */ - int at_bonus; /* Verändert den Angriffsskill (default: 0) */ - int df_bonus; /* Verändert den Verteidigungskill (default: 0) */ - float tac_bonus; + int at_bonus; /* Verändert den Angriffsskill (default: 0) */ + int df_bonus; /* Verändert den Verteidigungskill (default: 0) */ + float tac_bonus; - const struct terrain_type **coasts; /* coast that this ship can land on */ + struct terrain_type ** coasts; /* coast that this ship can land on */ - struct construction *construction; /* how to build a ship */ - } ship_type; + struct construction *construction; /* how to build a ship */ + } ship_type; - extern struct quicklist *shiptypes; + extern struct quicklist *shiptypes; -/* Alte Schiffstypen: */ + /* Alte Schiffstypen: */ - const ship_type *st_find(const char *name); - ship_type *st_get_or_create(const char *name); - void free_shiptypes(void); + const ship_type *st_find(const char *name); + ship_type *st_get_or_create(const char *name); + void free_shiptypes(void); #define NOSHIP NULL @@ -80,51 +80,51 @@ extern "C" { #define SFL_SAVEMASK (SF_FLYING) #define INCOME_FISHING 10 - typedef struct ship { - struct ship *next; - struct ship *nexthash; - struct unit * _owner; /* never use directly, always use ship_owner() */ - int no; - struct region *region; - char *name; - char *display; - struct attrib *attribs; - int size; - int damage; /* damage in 100th of a point of size */ - int flags; - const struct ship_type *type; - direction_t coast; - } ship; + typedef struct ship { + struct ship *next; + struct ship *nexthash; + struct unit * _owner; /* never use directly, always use ship_owner() */ + int no; + struct region *region; + char *name; + char *display; + struct attrib *attribs; + int size; + int damage; /* damage in 100th of a point of size */ + int flags; + const struct ship_type *type; + direction_t coast; + } ship; - void damage_ship(struct ship * sh, double percent); - void ship_set_owner(struct unit * u); - struct unit *ship_owner(const struct ship *sh); - void ship_update_owner(struct ship * sh); + void damage_ship(struct ship * sh, double percent); + void ship_set_owner(struct unit * u); + struct unit *ship_owner(const struct ship *sh); + void ship_update_owner(struct ship * sh); - extern const char *shipname(const struct ship *self); - extern int shipcapacity(const struct ship *sh); - extern void getshipweight(const struct ship *sh, int *weight, int *cabins); + extern const char *shipname(const struct ship *self); + extern int shipcapacity(const struct ship *sh); + extern void getshipweight(const struct ship *sh, int *weight, int *cabins); - extern ship *new_ship(const struct ship_type *stype, struct region *r, - const struct locale *lang); - extern const char *write_shipname(const struct ship *sh, char *buffer, - size_t size); - extern struct ship *findship(int n); - extern struct ship *findshipr(const struct region *r, int n); + extern ship *new_ship(const struct ship_type *stype, struct region *r, + const struct locale *lang); + extern const char *write_shipname(const struct ship *sh, char *buffer, + size_t size); + extern struct ship *findship(int n); + extern struct ship *findshipr(const struct region *r, int n); - extern const struct ship_type *findshiptype(const char *s, - const struct locale *lang); + extern const struct ship_type *findshiptype(const char *s, + const struct locale *lang); - extern void write_ship_reference(const struct ship *sh, + extern void write_ship_reference(const struct ship *sh, struct storage *store); - extern void remove_ship(struct ship **slist, struct ship *s); - extern void free_ship(struct ship *s); - extern void free_ships(void); + extern void remove_ship(struct ship **slist, struct ship *s); + extern void free_ship(struct ship *s); + extern void free_ships(void); - extern const char *ship_getname(const struct ship *self); - extern void ship_setname(struct ship *self, const char *name); - int shipspeed(const struct ship *sh, const struct unit *u); + extern const char *ship_getname(const struct ship *self); + extern void ship_setname(struct ship *self, const char *name); + int shipspeed(const struct ship *sh, const struct unit *u); #ifdef __cplusplus } diff --git a/src/kernel/spellbook.test.c b/src/kernel/spellbook.test.c index f11f77c75..64514101f 100644 --- a/src/kernel/spellbook.test.c +++ b/src/kernel/spellbook.test.c @@ -27,6 +27,8 @@ void test_named_spellbooks(CuTest * tc) sb = create_spellbook(0); CuAssertPtrNotNull(tc, sb); CuAssertPtrEquals(tc, 0, sb->name); + spellbook_clear(sb); + free(sb); sb = create_spellbook("spells"); CuAssertPtrNotNull(tc, sb); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 16c1dbdfb..77d2270e1 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -58,2192 +58,2238 @@ without prior permission by the authors of Eressea. #ifdef USE_LIBXML2 static void xml_readtext(xmlNodePtr node, struct locale **lang, xmlChar ** text) { - xmlChar *propValue = xmlGetProp(node, BAD_CAST "locale"); - assert(propValue != NULL); - *lang = get_locale((const char *)propValue); + xmlChar *propValue = xmlGetProp(node, BAD_CAST "locale"); + assert(propValue != NULL); + *lang = get_locale((const char *)propValue); #ifdef MAKE_LOCALES - if (*lang == NULL) - *lang = get_or_create_locale((const char *)propValue); + if (*lang == NULL) + *lang = get_or_create_locale((const char *)propValue); #endif - xmlFree(propValue); + xmlFree(propValue); - *text = xmlNodeListGetString(node->doc, node->children, 1); + *text = xmlNodeListGetString(node->doc, node->children, 1); } static const spell *xml_spell(xmlNode * node, const char *name) { - const spell *sp = NULL; - xmlChar *propValue = xmlGetProp(node, BAD_CAST name); - if (propValue != NULL) { - sp = find_spell((const char *)propValue); - assert(sp); - xmlFree(propValue); - } - return sp; + const spell *sp = NULL; + xmlChar *propValue = xmlGetProp(node, BAD_CAST name); + if (propValue != NULL) { + sp = find_spell((const char *)propValue); + assert(sp); + xmlFree(propValue); + } + return sp; } static xmlChar *xml_cleanup_string(xmlChar * str) { - xmlChar *read = str; - xmlChar *write = str; + xmlChar *read = str; + xmlChar *write = str; - while (*read) { - /* eat leading whitespace */ - if (*read && isxspace(*read)) { - while (*read && isxspace(*read)) { - ++read; - } - *write++ = ' '; - } while (*read) { - if (*read == '\n') - break; - if (*read == '\r') - break; - *write++ = *read++; + /* eat leading whitespace */ + if (*read && isxspace(*read)) { + while (*read && isxspace(*read)) { + ++read; + } + *write++ = ' '; + } + while (*read) { + if (*read == '\n') + break; + if (*read == '\r') + break; + *write++ = *read++; + } } - } - *write = 0; - return str; + *write = 0; + return str; } static void xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray) { - int req; - requirement *radd = *reqArray; + int req; + requirement *radd = *reqArray; - assert(radd == NULL); - if (nodeNr == 0) - return; + assert(radd == NULL); + if (nodeNr == 0) + return; - radd = *reqArray = calloc(sizeof(requirement), nodeNr + 1); + radd = *reqArray = calloc(sizeof(requirement), nodeNr + 1); - for (req = 0; req != nodeNr; ++req) { - xmlNodePtr node = nodeTab[req]; - xmlChar *propValue; + for (req = 0; req != nodeNr; ++req) { + xmlNodePtr node = nodeTab[req]; + xmlChar *propValue; - radd->number = xml_ivalue(node, "quantity", 1); + radd->number = xml_ivalue(node, "quantity", 1); - propValue = xmlGetProp(node, BAD_CAST "type"); - radd->rtype = rt_get_or_create((const char *)propValue); - xmlFree(propValue); + propValue = xmlGetProp(node, BAD_CAST "type"); + radd->rtype = rt_get_or_create((const char *)propValue); + xmlFree(propValue); - ++radd; - } + ++radd; + } } void xml_readconstruction(xmlXPathContextPtr xpath, xmlNodeSetPtr nodeSet, - construction ** consPtr) +construction ** consPtr) { - xmlNodePtr pushNode = xpath->node; - int k; - for (k = 0; k != nodeSet->nodeNr; ++k) { - xmlNodePtr node = nodeSet->nodeTab[k]; - xmlChar *propValue; - construction *con; - xmlXPathObjectPtr req; - int m; - skill_t sk = NOSKILL; + xmlNodePtr pushNode = xpath->node; + int k; + for (k = 0; k != nodeSet->nodeNr; ++k) { + xmlNodePtr node = nodeSet->nodeTab[k]; + xmlChar *propValue; + construction *con; + xmlXPathObjectPtr req; + int m; + skill_t sk = NOSKILL; - propValue = xmlGetProp(node, BAD_CAST "skill"); - if (propValue != NULL) { - sk = findskill((const char *)propValue); - if (sk == NOSKILL) { - log_error("construction requires skill '%s' that does not exist.\n", (const char *)propValue); - xmlFree(propValue); - continue; - } - xmlFree(propValue); + propValue = xmlGetProp(node, BAD_CAST "skill"); + if (propValue != NULL) { + sk = findskill((const char *)propValue); + if (sk == NOSKILL) { + log_error("construction requires skill '%s' that does not exist.\n", (const char *)propValue); + xmlFree(propValue); + continue; + } + xmlFree(propValue); + } + + assert(*consPtr == NULL); + + *consPtr = con = (construction *)calloc(sizeof(construction), 1); + consPtr = &con->improvement; + + con->skill = sk; + con->maxsize = xml_ivalue(node, "maxsize", -1); + con->minskill = xml_ivalue(node, "minskill", -1); + con->reqsize = xml_ivalue(node, "reqsize", -1); + + propValue = xmlGetProp(node, BAD_CAST "building"); + if (propValue != NULL) { + con->btype = bt_get_or_create((const char *)propValue); + xmlFree(propValue); + } + + /* read construction/requirement */ + xpath->node = node; + req = xmlXPathEvalExpression(BAD_CAST "requirement", xpath); + xml_readrequirements(req->nodesetval->nodeTab, + req->nodesetval->nodeNr, &con->materials); + xmlXPathFreeObject(req); + + /* read construction/modifier */ + xpath->node = node; + req = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); + for (m = 0; m != req->nodesetval->nodeNr; ++m) { + xmlNodePtr node = req->nodesetval->nodeTab[m]; + + propValue = xmlGetProp(node, BAD_CAST "function"); + if (propValue != NULL) { + pf_generic foo = get_function((const char *)propValue); + a_add(&con->attribs, make_skillmod(NOSKILL, SMF_PRODUCTION, + (skillmod_fun)foo, 1.0, 0)); + xmlFree(propValue); + } + + } + xmlXPathFreeObject(req); } - - assert(*consPtr == NULL); - - *consPtr = con = (construction *)calloc(sizeof(construction), 1); - consPtr = &con->improvement; - - con->skill = sk; - con->maxsize = xml_ivalue(node, "maxsize", -1); - con->minskill = xml_ivalue(node, "minskill", -1); - con->reqsize = xml_ivalue(node, "reqsize", -1); - - propValue = xmlGetProp(node, BAD_CAST "building"); - if (propValue != NULL) { - con->btype = bt_get_or_create((const char *)propValue); - xmlFree(propValue); - } - - /* read construction/requirement */ - xpath->node = node; - req = xmlXPathEvalExpression(BAD_CAST "requirement", xpath); - xml_readrequirements(req->nodesetval->nodeTab, - req->nodesetval->nodeNr, &con->materials); - xmlXPathFreeObject(req); - - /* read construction/modifier */ - xpath->node = node; - req = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); - for (m = 0; m != req->nodesetval->nodeNr; ++m) { - xmlNodePtr node = req->nodesetval->nodeTab[m]; - - propValue = xmlGetProp(node, BAD_CAST "function"); - if (propValue != NULL) { - pf_generic foo = get_function((const char *)propValue); - a_add(&con->attribs, make_skillmod(NOSKILL, SMF_PRODUCTION, - (skillmod_fun) foo, 1.0, 0)); - xmlFree(propValue); - } - - } - xmlXPathFreeObject(req); - } - xpath->node = pushNode; + xpath->node = pushNode; } static int parse_function(xmlNodePtr node, pf_generic * funPtr, xmlChar ** namePtr) { - pf_generic fun; - xmlChar *propValue = xmlGetProp(node, BAD_CAST "value"); - assert(propValue != NULL); - fun = get_function((const char *)propValue); - if (fun != NULL) { - xmlFree(propValue); + pf_generic fun; + xmlChar *propValue = xmlGetProp(node, BAD_CAST "value"); + assert(propValue != NULL); + fun = get_function((const char *)propValue); + if (fun != NULL) { + xmlFree(propValue); - propValue = xmlGetProp(node, BAD_CAST "name"); - } - *namePtr = propValue; - *funPtr = fun; - return 0; + propValue = xmlGetProp(node, BAD_CAST "name"); + } + *namePtr = propValue; + *funPtr = fun; + return 0; } static int parse_buildings(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr buildings; - int i; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr buildings; + int i; - /* reading eressea/buildings/building */ - buildings = - xmlXPathEvalExpression(BAD_CAST "/eressea/buildings/building", xpath); - if (buildings->nodesetval != NULL) { - xmlNodeSetPtr nodes = buildings->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - xmlChar *propValue; - building_type *btype; - xmlXPathObjectPtr result; - int k; + /* reading eressea/buildings/building */ + buildings = + xmlXPathEvalExpression(BAD_CAST "/eressea/buildings/building", xpath); + if (buildings->nodesetval != NULL) { + xmlNodeSetPtr nodes = buildings->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar *propValue; + building_type *btype; + xmlXPathObjectPtr result; + int k; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - btype = bt_get_or_create((const char *)propValue); - xmlFree(propValue); - - btype->capacity = xml_ivalue(node, "capacity", -1); - btype->maxcapacity = xml_ivalue(node, "maxcapacity", -1); - btype->maxsize = xml_ivalue(node, "maxsize", -1); - - btype->magres = xml_ivalue(node, "magres", 0); - btype->magresbonus = xml_ivalue(node, "magresbonus", 0); - btype->fumblebonus = xml_ivalue(node, "fumblebonus", 0); - btype->auraregen = xml_fvalue(node, "auraregen", 1.0); - - if (xml_bvalue(node, "nodestroy", false)) - btype->flags |= BTF_INDESTRUCTIBLE; - if (xml_bvalue(node, "oneperturn", false)) - btype->flags |= BTF_ONEPERTURN; - if (xml_bvalue(node, "nobuild", false)) - btype->flags |= BTF_NOBUILD; - if (xml_bvalue(node, "namechange", true)) - btype->flags |= BTF_NAMECHANGE; - if (xml_bvalue(node, "unique", false)) - btype->flags |= BTF_UNIQUE; - if (xml_bvalue(node, "decay", false)) - btype->flags |= BTF_DECAY; - if (xml_bvalue(node, "magic", false)) - btype->flags |= BTF_MAGIC; - - /* reading eressea/buildings/building/construction */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); - xml_readconstruction(xpath, result->nodesetval, &btype->construction); - xmlXPathFreeObject(result); - - /* reading eressea/buildings/building/function */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - pf_generic fun; - parse_function(node, &fun, &propValue); - - if (fun == NULL) { - log_error("unknown function name '%s' for building %s\n", (const char *)propValue, btype->_name); + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue != NULL); + btype = bt_get_or_create((const char *)propValue); xmlFree(propValue); - continue; - } - assert(propValue != NULL); - if (strcmp((const char *)propValue, "name") == 0) { - btype->name = - (const char *(*)(const struct building_type *, - const struct building *, int))fun; - } else if (strcmp((const char *)propValue, "init") == 0) { - btype->init = (void (*)(struct building_type *))fun; - } else if (strcmp((const char *)propValue, "age") == 0) { - btype->age = (void (*)(struct building *))fun; - } else if (strcmp((const char *)propValue, "protection") == 0) { - btype->protection = (int (*)(struct building *, struct unit *))fun; - } else if (strcmp((const char *)propValue, "taxes") == 0) { - btype->taxes = (double (*)(const struct building *, int))fun; - } else if (strcmp((const char *)propValue, "age") == 0) { - btype->age = (void (*)(struct building *))fun; - } else { - log_error("unknown function type '%s' for building %s\n", (const char *)propValue, btype->_name); - } - xmlFree(propValue); - } - xmlXPathFreeObject(result); - /* reading eressea/buildings/building/maintenance */ - result = xmlXPathEvalExpression(BAD_CAST "maintenance", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - maintenance *mt; + btype->capacity = xml_ivalue(node, "capacity", -1); + btype->maxcapacity = xml_ivalue(node, "maxcapacity", -1); + btype->maxsize = xml_ivalue(node, "maxsize", -1); - if (btype->maintenance == NULL) { - btype->maintenance = (struct maintenance *) - calloc(sizeof(struct maintenance), result->nodesetval->nodeNr + 1); + btype->magres = xml_ivalue(node, "magres", 0); + btype->magresbonus = xml_ivalue(node, "magresbonus", 0); + btype->fumblebonus = xml_ivalue(node, "fumblebonus", 0); + btype->auraregen = xml_fvalue(node, "auraregen", 1.0); + + if (xml_bvalue(node, "nodestroy", false)) + btype->flags |= BTF_INDESTRUCTIBLE; + if (xml_bvalue(node, "oneperturn", false)) + btype->flags |= BTF_ONEPERTURN; + if (xml_bvalue(node, "nobuild", false)) + btype->flags |= BTF_NOBUILD; + if (xml_bvalue(node, "namechange", true)) + btype->flags |= BTF_NAMECHANGE; + if (xml_bvalue(node, "unique", false)) + btype->flags |= BTF_UNIQUE; + if (xml_bvalue(node, "decay", false)) + btype->flags |= BTF_DECAY; + if (xml_bvalue(node, "magic", false)) + btype->flags |= BTF_MAGIC; + + /* reading eressea/buildings/building/construction */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); + xml_readconstruction(xpath, result->nodesetval, &btype->construction); + xmlXPathFreeObject(result); + + /* reading eressea/buildings/building/function */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "function", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + pf_generic fun; + parse_function(node, &fun, &propValue); + + if (fun == NULL) { + log_error("unknown function name '%s' for building %s\n", (const char *)propValue, btype->_name); + xmlFree(propValue); + continue; + } + assert(propValue != NULL); + if (strcmp((const char *)propValue, "name") == 0) { + btype->name = + (const char *(*)(const struct building_type *, + const struct building *, int))fun; + } + else if (strcmp((const char *)propValue, "init") == 0) { + btype->init = (void(*)(struct building_type *))fun; + } + else if (strcmp((const char *)propValue, "age") == 0) { + btype->age = (void(*)(struct building *))fun; + } + else if (strcmp((const char *)propValue, "protection") == 0) { + btype->protection = (int(*)(struct building *, struct unit *))fun; + } + else if (strcmp((const char *)propValue, "taxes") == 0) { + btype->taxes = (double(*)(const struct building *, int))fun; + } + else if (strcmp((const char *)propValue, "age") == 0) { + btype->age = (void(*)(struct building *))fun; + } + else { + log_error("unknown function type '%s' for building %s\n", (const char *)propValue, btype->_name); + } + xmlFree(propValue); + } + xmlXPathFreeObject(result); + + /* reading eressea/buildings/building/maintenance */ + result = xmlXPathEvalExpression(BAD_CAST "maintenance", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + maintenance *mt; + + if (btype->maintenance == NULL) { + btype->maintenance = (struct maintenance *) + calloc(sizeof(struct maintenance), result->nodesetval->nodeNr + 1); + } + mt = btype->maintenance + k; + mt->number = xml_ivalue(node, "amount", 0); + + propValue = xmlGetProp(node, BAD_CAST "type"); + assert(propValue != NULL); + mt->rtype = rt_find((const char *)propValue); + assert(mt->rtype != NULL); + xmlFree(propValue); + + if (xml_bvalue(node, "variable", false)) + mt->flags |= MTF_VARIABLE; + if (xml_bvalue(node, "vital", false)) + mt->flags |= MTF_VITAL; + + } + xmlXPathFreeObject(result); + + /* finally, initialize the new building type */ + if (btype->init) + btype->init(btype); } - mt = btype->maintenance + k; - mt->number = xml_ivalue(node, "amount", 0); - - propValue = xmlGetProp(node, BAD_CAST "type"); - assert(propValue != NULL); - mt->rtype = rt_find((const char *)propValue); - assert(mt->rtype != NULL); - xmlFree(propValue); - - if (xml_bvalue(node, "variable", false)) - mt->flags |= MTF_VARIABLE; - if (xml_bvalue(node, "vital", false)) - mt->flags |= MTF_VITAL; - - } - xmlXPathFreeObject(result); - - /* finally, initialize the new building type */ - if (btype->init) - btype->init(btype); } - } - xmlXPathFreeObject(buildings); + xmlXPathFreeObject(buildings); - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeContext(xpath); + return 0; } static int parse_calendar(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr xpathCalendars; - xmlNodeSetPtr nsetCalendars; - int c, rv = 0; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr xpathCalendars; + xmlNodeSetPtr nsetCalendars; + int c, rv = 0; - /* reading eressea/buildings/building */ - xpathCalendars = xmlXPathEvalExpression(BAD_CAST "/eressea/calendar", xpath); - nsetCalendars = xpathCalendars->nodesetval; - months_per_year = 0; - if (nsetCalendars == NULL || nsetCalendars->nodeNr == 0) { - rv = -1; - } else - for (c = 0; c != nsetCalendars->nodeNr; ++c) { - xmlNodePtr calendar = nsetCalendars->nodeTab[c]; - xmlXPathObjectPtr xpathWeeks, xpathMonths, xpathSeasons; - xmlNodeSetPtr nsetWeeks, nsetMonths, nsetSeasons; - xmlChar *propValue = xmlGetProp(calendar, BAD_CAST "name"); - xmlChar *newyear = xmlGetProp(calendar, BAD_CAST "newyear"); - - first_turn = xml_ivalue(calendar, "start", first_turn); - if (propValue) { - free(agename); - agename = _strdup(mkname("calendar", (const char *)propValue)); - xmlFree(propValue); - } - - xpath->node = calendar; - xpathWeeks = xmlXPathEvalExpression(BAD_CAST "week", xpath); - nsetWeeks = xpathWeeks->nodesetval; - if (nsetWeeks != NULL && nsetWeeks->nodeNr) { - int i; - - weeks_per_month = nsetWeeks->nodeNr; - assert(!weeknames); - weeknames = malloc(sizeof(char *) * weeks_per_month); - weeknames2 = malloc(sizeof(char *) * weeks_per_month); - for (i = 0; i != nsetWeeks->nodeNr; ++i) { - xmlNodePtr week = nsetWeeks->nodeTab[i]; - xmlChar *propValue = xmlGetProp(week, BAD_CAST "name"); - if (propValue) { - weeknames[i] = _strdup(mkname("calendar", (const char *)propValue)); - weeknames2[i] = malloc(strlen(weeknames[i]) + 3); - sprintf(weeknames2[i], "%s_d", weeknames[i]); - xmlFree(propValue); - } - } - } - xmlXPathFreeObject(xpathWeeks); - - xpathSeasons = xmlXPathEvalExpression(BAD_CAST "season", xpath); - nsetSeasons = xpathSeasons->nodesetval; - if (nsetSeasons != NULL && nsetSeasons->nodeNr) { - int i; - - seasons = nsetSeasons->nodeNr; - assert(!seasonnames); - seasonnames = malloc(sizeof(char *) * seasons); - - for (i = 0; i != nsetSeasons->nodeNr; ++i) { - xmlNodePtr season = nsetSeasons->nodeTab[i]; - xmlChar *propValue = xmlGetProp(season, BAD_CAST "name"); - if (propValue) { - seasonnames[i] = - _strdup(mkname("calendar", (const char *)propValue)); - xmlFree(propValue); - } - } - } - - xpathMonths = xmlXPathEvalExpression(BAD_CAST "season/month", xpath); - nsetMonths = xpathMonths->nodesetval; - if (nsetMonths != NULL && nsetMonths->nodeNr) { - int i; - - months_per_year = nsetMonths->nodeNr; - assert(!monthnames); - monthnames = malloc(sizeof(char *) * months_per_year); - month_season = malloc(sizeof(int) * months_per_year); - storms = malloc(sizeof(int) * months_per_year); - - for (i = 0; i != nsetMonths->nodeNr; ++i) { - xmlNodePtr month = nsetMonths->nodeTab[i]; - xmlChar *propValue = xmlGetProp(month, BAD_CAST "name"); - int j; - - if (propValue) { - if (newyear - && strcmp((const char *)newyear, (const char *)propValue) == 0) { - first_month = i; - xmlFree(newyear); - newyear = NULL; - } - monthnames[i] = _strdup(mkname("calendar", (const char *)propValue)); - xmlFree(propValue); - } - for (j = 0; j != seasons; ++j) { - xmlNodePtr season = month->parent; - if (season == nsetSeasons->nodeTab[j]) { - month_season[i] = j; - break; - } - } - assert(j != seasons); - storms[i] = xml_ivalue(nsetMonths->nodeTab[i], "storm", 0); - } - } - xmlXPathFreeObject(xpathMonths); - xmlXPathFreeObject(xpathSeasons); + /* reading eressea/buildings/building */ + xpathCalendars = xmlXPathEvalExpression(BAD_CAST "/eressea/calendar", xpath); + nsetCalendars = xpathCalendars->nodesetval; + months_per_year = 0; + if (nsetCalendars == NULL || nsetCalendars->nodeNr == 0) { + rv = -1; } - xmlXPathFreeObject(xpathCalendars); - xmlXPathFreeContext(xpath); + else + for (c = 0; c != nsetCalendars->nodeNr; ++c) { + xmlNodePtr calendar = nsetCalendars->nodeTab[c]; + xmlXPathObjectPtr xpathWeeks, xpathMonths, xpathSeasons; + xmlNodeSetPtr nsetWeeks, nsetMonths, nsetSeasons; + xmlChar *propValue = xmlGetProp(calendar, BAD_CAST "name"); + xmlChar *newyear = xmlGetProp(calendar, BAD_CAST "newyear"); - return rv; + first_turn = xml_ivalue(calendar, "start", first_turn); + if (propValue) { + free(agename); + agename = _strdup(mkname("calendar", (const char *)propValue)); + xmlFree(propValue); + } + + xpath->node = calendar; + xpathWeeks = xmlXPathEvalExpression(BAD_CAST "week", xpath); + nsetWeeks = xpathWeeks->nodesetval; + if (nsetWeeks != NULL && nsetWeeks->nodeNr) { + int i; + + weeks_per_month = nsetWeeks->nodeNr; + assert(!weeknames); + weeknames = malloc(sizeof(char *) * weeks_per_month); + weeknames2 = malloc(sizeof(char *) * weeks_per_month); + for (i = 0; i != nsetWeeks->nodeNr; ++i) { + xmlNodePtr week = nsetWeeks->nodeTab[i]; + xmlChar *propValue = xmlGetProp(week, BAD_CAST "name"); + if (propValue) { + weeknames[i] = _strdup(mkname("calendar", (const char *)propValue)); + weeknames2[i] = malloc(strlen(weeknames[i]) + 3); + sprintf(weeknames2[i], "%s_d", weeknames[i]); + xmlFree(propValue); + } + } + } + xmlXPathFreeObject(xpathWeeks); + + xpathSeasons = xmlXPathEvalExpression(BAD_CAST "season", xpath); + nsetSeasons = xpathSeasons->nodesetval; + if (nsetSeasons != NULL && nsetSeasons->nodeNr) { + int i; + + seasons = nsetSeasons->nodeNr; + assert(!seasonnames); + seasonnames = malloc(sizeof(char *) * seasons); + + for (i = 0; i != nsetSeasons->nodeNr; ++i) { + xmlNodePtr season = nsetSeasons->nodeTab[i]; + xmlChar *propValue = xmlGetProp(season, BAD_CAST "name"); + if (propValue) { + seasonnames[i] = + _strdup(mkname("calendar", (const char *)propValue)); + xmlFree(propValue); + } + } + } + + xpathMonths = xmlXPathEvalExpression(BAD_CAST "season/month", xpath); + nsetMonths = xpathMonths->nodesetval; + if (nsetMonths != NULL && nsetMonths->nodeNr) { + int i; + + months_per_year = nsetMonths->nodeNr; + assert(!monthnames); + monthnames = malloc(sizeof(char *) * months_per_year); + month_season = malloc(sizeof(int) * months_per_year); + storms = malloc(sizeof(int) * months_per_year); + + for (i = 0; i != nsetMonths->nodeNr; ++i) { + xmlNodePtr month = nsetMonths->nodeTab[i]; + xmlChar *propValue = xmlGetProp(month, BAD_CAST "name"); + int j; + + if (propValue) { + if (newyear + && strcmp((const char *)newyear, (const char *)propValue) == 0) { + first_month = i; + xmlFree(newyear); + newyear = NULL; + } + monthnames[i] = _strdup(mkname("calendar", (const char *)propValue)); + xmlFree(propValue); + } + for (j = 0; j != seasons; ++j) { + xmlNodePtr season = month->parent; + if (season == nsetSeasons->nodeTab[j]) { + month_season[i] = j; + break; + } + } + assert(j != seasons); + storms[i] = xml_ivalue(nsetMonths->nodeTab[i], "storm", 0); + } + } + xmlXPathFreeObject(xpathMonths); + xmlXPathFreeObject(xpathSeasons); + } + xmlXPathFreeObject(xpathCalendars); + xmlXPathFreeContext(xpath); + + return rv; } static int parse_ships(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr ships; - int i; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr ships; + int i; - /* reading eressea/ships/ship */ - ships = xmlXPathEvalExpression(BAD_CAST "/eressea/ships/ship", xpath); - if (ships->nodesetval != NULL) { - xmlNodeSetPtr nodes = ships->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr child, node = nodes->nodeTab[i]; - xmlChar *propValue; - ship_type *st; - xmlXPathObjectPtr result; - int k, c; + /* reading eressea/ships/ship */ + ships = xmlXPathEvalExpression(BAD_CAST "/eressea/ships/ship", xpath); + if (ships->nodesetval != NULL) { + xmlNodeSetPtr nodes = ships->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr child, node = nodes->nodeTab[i]; + xmlChar *propValue; + ship_type *st; + xmlXPathObjectPtr result; + int k, c; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - st = st_get_or_create((const char *)propValue); - xmlFree(propValue); + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue != NULL); + st = st_get_or_create((const char *)propValue); + xmlFree(propValue); - st->cabins = xml_ivalue(node, "cabins", 0) * PERSON_WEIGHT; - st->cargo = xml_ivalue(node, "cargo", 0); - st->combat = xml_ivalue(node, "combat", 0); - st->cptskill = xml_ivalue(node, "cptskill", 0); - st->damage = xml_fvalue(node, "damage", 0.0); - if (xml_bvalue(node, "nocoast", false)) - st->flags |= SFL_NOCOAST; - if (xml_bvalue(node, "fly", false)) - st->flags |= SFL_FLY; - if (xml_bvalue(node, "opensea", false)) - st->flags |= SFL_OPENSEA; - st->fishing = xml_ivalue(node, "fishing", 0); - st->minskill = xml_ivalue(node, "minskill", 0); - st->range = xml_ivalue(node, "range", 0); - st->storm = xml_fvalue(node, "storm", 1.0); - st->sumskill = xml_ivalue(node, "sumskill", 0); + st->cabins = xml_ivalue(node, "cabins", 0) * PERSON_WEIGHT; + st->cargo = xml_ivalue(node, "cargo", 0); + st->combat = xml_ivalue(node, "combat", 0); + st->cptskill = xml_ivalue(node, "cptskill", 0); + st->damage = xml_fvalue(node, "damage", 0.0); + if (xml_bvalue(node, "nocoast", false)) + st->flags |= SFL_NOCOAST; + if (xml_bvalue(node, "fly", false)) + st->flags |= SFL_FLY; + if (xml_bvalue(node, "opensea", false)) + st->flags |= SFL_OPENSEA; + st->fishing = xml_ivalue(node, "fishing", 0); + st->minskill = xml_ivalue(node, "minskill", 0); + st->range = xml_ivalue(node, "range", 0); + st->storm = xml_fvalue(node, "storm", 1.0); + st->sumskill = xml_ivalue(node, "sumskill", 0); - /* reading eressea/ships/ship/construction */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); - xml_readconstruction(xpath, result->nodesetval, &st->construction); - xmlXPathFreeObject(result); + /* reading eressea/ships/ship/construction */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); + xml_readconstruction(xpath, result->nodesetval, &st->construction); + xmlXPathFreeObject(result); - for (child = node->children; child; child = child->next) { - if (strcmp((const char *)child->name, "modifier") == 0) { - double value = xml_fvalue(child, "value", 0.0); - propValue = xmlGetProp(child, BAD_CAST "type"); - if (strcmp((const char *)propValue, "tactics") == 0) - st->tac_bonus = (float)value; - else if (strcmp((const char *)propValue, "attack") == 0) - st->at_bonus = (int)value; - else if (strcmp((const char *)propValue, "defense") == 0) - st->df_bonus = (int)value; - xmlFree(propValue); + for (child = node->children; child; child = child->next) { + if (strcmp((const char *)child->name, "modifier") == 0) { + double value = xml_fvalue(child, "value", 0.0); + propValue = xmlGetProp(child, BAD_CAST "type"); + if (strcmp((const char *)propValue, "tactics") == 0) + st->tac_bonus = (float)value; + else if (strcmp((const char *)propValue, "attack") == 0) + st->at_bonus = (int)value; + else if (strcmp((const char *)propValue, "defense") == 0) + st->df_bonus = (int)value; + xmlFree(propValue); + } + } + /* reading eressea/ships/ship/coast */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "coast", xpath); + for (c = 0, k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + + if (k == 0) { + assert(st->coasts == NULL); + st->coasts = + (terrain_type **)malloc(sizeof(terrain_type *) * + (result->nodesetval->nodeNr + 1)); + st->coasts[result->nodesetval->nodeNr] = NULL; + } + + propValue = xmlGetProp(node, BAD_CAST "terrain"); + assert(propValue != NULL); + st->coasts[c] = get_or_create_terrain((const char *)propValue); + if (st->coasts[c] != NULL) + ++c; + else { + log_warning("ship %s mentions a non-existing terrain %s.\n", st->_name, propValue); + } + xmlFree(propValue); + } + xmlXPathFreeObject(result); } - } - /* reading eressea/ships/ship/coast */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "coast", xpath); - for (c = 0, k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - - if (k == 0) { - assert(st->coasts == NULL); - st->coasts = - (const terrain_type **)malloc(sizeof(const terrain_type *) * - (result->nodesetval->nodeNr + 1)); - st->coasts[result->nodesetval->nodeNr] = NULL; - } - - propValue = xmlGetProp(node, BAD_CAST "terrain"); - assert(propValue != NULL); - st->coasts[c] = get_terrain((const char *)propValue); - if (st->coasts[c] != NULL) - ++c; - else { - log_warning("ship %s mentions a non-existing terrain %s.\n", st->_name, propValue); - } - xmlFree(propValue); - } - xmlXPathFreeObject(result); } - } - xmlXPathFreeObject(ships); + xmlXPathFreeObject(ships); - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeContext(xpath); + return 0; } static potion_type *xml_readpotion(xmlXPathContextPtr xpath, item_type * itype) { - int level = xml_ivalue(xpath->node, "level", 0); + int level = xml_ivalue(xpath->node, "level", 0); - assert(level > 0); - return new_potiontype(itype, level); + assert(level > 0); + return new_potiontype(itype, level); } static luxury_type *xml_readluxury(xmlXPathContextPtr xpath, item_type * itype) { - int price = xml_ivalue(xpath->node, "price", 0); - return new_luxurytype(itype, price); + int price = xml_ivalue(xpath->node, "price", 0); + return new_luxurytype(itype, price); } static armor_type *xml_readarmor(xmlXPathContextPtr xpath, item_type * itype) { - xmlNodePtr node = xpath->node; - armor_type *atype = NULL; - unsigned int flags = ATF_NONE; - int ac = xml_ivalue(node, "ac", 0); - double penalty = xml_fvalue(node, "penalty", 0.0); - double magres = xml_fvalue(node, "magres", 0.0); + xmlNodePtr node = xpath->node; + armor_type *atype = NULL; + unsigned int flags = ATF_NONE; + int ac = xml_ivalue(node, "ac", 0); + double penalty = xml_fvalue(node, "penalty", 0.0); + double magres = xml_fvalue(node, "magres", 0.0); - if (xml_bvalue(node, "laen", false)) - flags |= ATF_LAEN; - if (xml_bvalue(node, "shield", false)) - flags |= ATF_SHIELD; + if (xml_bvalue(node, "laen", false)) + flags |= ATF_LAEN; + if (xml_bvalue(node, "shield", false)) + flags |= ATF_SHIELD; - atype = new_armortype(itype, penalty, magres, ac, flags); - atype->projectile = (float)xml_fvalue(node, "projectile", 0.0); - return atype; + atype = new_armortype(itype, penalty, magres, ac, flags); + atype->projectile = (float)xml_fvalue(node, "projectile", 0.0); + return atype; } static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) { - xmlNodePtr node = xpath->node; - weapon_type *wtype = NULL; - unsigned int flags = WTF_NONE; - xmlXPathObjectPtr result; - xmlChar *propValue; - int k; - skill_t sk; - int minskill = xml_ivalue(node, "minskill", 1); - int offmod = xml_ivalue(node, "offmod", 0); - int defmod = xml_ivalue(node, "defmod", 0); - int reload = xml_ivalue(node, "reload", 0); - double magres = xml_fvalue(node, "magres", 0.0); + xmlNodePtr node = xpath->node; + weapon_type *wtype = NULL; + unsigned int flags = WTF_NONE; + xmlXPathObjectPtr result; + xmlChar *propValue; + int k; + skill_t sk; + int minskill = xml_ivalue(node, "minskill", 1); + int offmod = xml_ivalue(node, "offmod", 0); + int defmod = xml_ivalue(node, "defmod", 0); + int reload = xml_ivalue(node, "reload", 0); + double magres = xml_fvalue(node, "magres", 0.0); - if (xml_bvalue(node, "armorpiercing", false)) - flags |= WTF_ARMORPIERCING; - if (xml_bvalue(node, "magical", false)) - flags |= WTF_MAGICAL; - if (xml_bvalue(node, "missile", false)) - flags |= WTF_MISSILE; - if (xml_bvalue(node, "pierce", false)) - flags |= WTF_PIERCE; - if (xml_bvalue(node, "cut", false)) - flags |= WTF_CUT; - if (xml_bvalue(node, "blunt", false)) - flags |= WTF_BLUNT; - if (xml_bvalue(node, "siege", false)) - flags |= WTF_SIEGE; - if (xml_bvalue(node, "horse", (flags & WTF_MISSILE) == 0)) - flags |= WTF_HORSEBONUS; - if (xml_bvalue(node, "useshield", true)) - flags |= WTF_USESHIELD; + if (xml_bvalue(node, "armorpiercing", false)) + flags |= WTF_ARMORPIERCING; + if (xml_bvalue(node, "magical", false)) + flags |= WTF_MAGICAL; + if (xml_bvalue(node, "missile", false)) + flags |= WTF_MISSILE; + if (xml_bvalue(node, "pierce", false)) + flags |= WTF_PIERCE; + if (xml_bvalue(node, "cut", false)) + flags |= WTF_CUT; + if (xml_bvalue(node, "blunt", false)) + flags |= WTF_BLUNT; + if (xml_bvalue(node, "siege", false)) + flags |= WTF_SIEGE; + if (xml_bvalue(node, "horse", (flags & WTF_MISSILE) == 0)) + flags |= WTF_HORSEBONUS; + if (xml_bvalue(node, "useshield", true)) + flags |= WTF_USESHIELD; - propValue = xmlGetProp(node, BAD_CAST "skill"); - assert(propValue != NULL); - sk = findskill((const char *)propValue); - assert(sk != NOSKILL); - xmlFree(propValue); + propValue = xmlGetProp(node, BAD_CAST "skill"); + assert(propValue != NULL); + sk = findskill((const char *)propValue); + assert(sk != NOSKILL); + xmlFree(propValue); - wtype = - new_weapontype(itype, flags, magres, NULL, offmod, defmod, reload, sk, - minskill); + wtype = + new_weapontype(itype, flags, magres, NULL, offmod, defmod, reload, sk, + minskill); - /* reading weapon/damage */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "damage", xpath); - assert(result->nodesetval->nodeNr <= 2); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - int pos = 0; + /* reading weapon/damage */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "damage", xpath); + assert(result->nodesetval->nodeNr <= 2); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + int pos = 0; - propValue = xmlGetProp(node, BAD_CAST "type"); - if (strcmp((const char *)propValue, "footman") != 0) { - pos = 1; + propValue = xmlGetProp(node, BAD_CAST "type"); + if (strcmp((const char *)propValue, "footman") != 0) { + pos = 1; + } + xmlFree(propValue); + + propValue = xmlGetProp(node, BAD_CAST "value"); + wtype->damage[pos] = _strdup((const char *)propValue); // TODO: this is a memory leak + if (k == 0) + wtype->damage[1 - pos] = wtype->damage[pos]; + xmlFree(propValue); } - xmlFree(propValue); + xmlXPathFreeObject(result); - propValue = xmlGetProp(node, BAD_CAST "value"); - wtype->damage[pos] = _strdup((const char *)propValue); // TODO: this is a memory leak - if (k == 0) - wtype->damage[1 - pos] = wtype->damage[pos]; - xmlFree(propValue); - } - xmlXPathFreeObject(result); + /* reading weapon/modifier */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); + assert(wtype->modifiers == NULL); + wtype->modifiers = calloc(result->nodesetval->nodeNr + 1, sizeof(weapon_mod)); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + xmlXPathObjectPtr races; + int r, flags = 0; - /* reading weapon/modifier */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); - assert(wtype->modifiers == NULL); - wtype->modifiers = calloc(result->nodesetval->nodeNr + 1, sizeof(weapon_mod)); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - xmlXPathObjectPtr races; - int r, flags = 0; + if (xml_bvalue(node, "walking", false)) + flags |= WMF_WALKING; + if (xml_bvalue(node, "riding", false)) + flags |= WMF_RIDING; + if (xml_bvalue(node, "against_walking", false)) + flags |= WMF_AGAINST_WALKING; + if (xml_bvalue(node, "against_riding", false)) + flags |= WMF_AGAINST_RIDING; + if (xml_bvalue(node, "offensive", false)) + flags |= WMF_OFFENSIVE; + if (xml_bvalue(node, "defensive", false)) + flags |= WMF_DEFENSIVE; - if (xml_bvalue(node, "walking", false)) - flags |= WMF_WALKING; - if (xml_bvalue(node, "riding", false)) - flags |= WMF_RIDING; - if (xml_bvalue(node, "against_walking", false)) - flags |= WMF_AGAINST_WALKING; - if (xml_bvalue(node, "against_riding", false)) - flags |= WMF_AGAINST_RIDING; - if (xml_bvalue(node, "offensive", false)) - flags |= WMF_OFFENSIVE; - if (xml_bvalue(node, "defensive", false)) - flags |= WMF_DEFENSIVE; + propValue = xmlGetProp(node, BAD_CAST "type"); + if (strcmp((const char *)propValue, "damage") == 0) + flags |= WMF_DAMAGE; + else if (strcmp((const char *)propValue, "skill") == 0) + flags |= WMF_SKILL; + else if (strcmp((const char *)propValue, "missile_target") == 0) + flags |= WMF_MISSILE_TARGET; + xmlFree(propValue); - propValue = xmlGetProp(node, BAD_CAST "type"); - if (strcmp((const char *)propValue, "damage") == 0) - flags |= WMF_DAMAGE; - else if (strcmp((const char *)propValue, "skill") == 0) - flags |= WMF_SKILL; - else if (strcmp((const char *)propValue, "missile_target") == 0) - flags |= WMF_MISSILE_TARGET; - xmlFree(propValue); + wtype->modifiers[k].flags = flags; + wtype->modifiers[k].value = xml_ivalue(node, "value", 0); - wtype->modifiers[k].flags = flags; - wtype->modifiers[k].value = xml_ivalue(node, "value", 0); + xpath->node = node; + races = xmlXPathEvalExpression(BAD_CAST "race", xpath); + for (r = 0; r != races->nodesetval->nodeNr; ++r) { + xmlNodePtr node = races->nodesetval->nodeTab[r]; + + propValue = xmlGetProp(node, BAD_CAST "name"); + if (propValue != NULL) { + const race *rc = rc_find((const char *)propValue); + if (rc == NULL) + rc = rc_get_or_create((const char *)propValue); + racelist_insert(&wtype->modifiers[k].races, rc); + xmlFree(propValue); + } + } + xmlXPathFreeObject(races); + } + xmlXPathFreeObject(result); + + /* reading weapon/function */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "function", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + xmlChar *propValue; + pf_generic fun; + + parse_function(node, &fun, &propValue); + if (fun == NULL) { + log_error("unknown function name '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name); + xmlFree(propValue); + continue; + } + assert(propValue != NULL); + if (strcmp((const char *)propValue, "attack") == 0) { + wtype->attack = + (bool(*)(const struct troop *, const struct weapon_type *, + int *))fun; + } + else { + log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name); + } + xmlFree(propValue); + } + xmlXPathFreeObject(result); xpath->node = node; - races = xmlXPathEvalExpression(BAD_CAST "race", xpath); - for (r = 0; r != races->nodesetval->nodeNr; ++r) { - xmlNodePtr node = races->nodesetval->nodeTab[r]; - - propValue = xmlGetProp(node, BAD_CAST "name"); - if (propValue != NULL) { - const race *rc = rc_find((const char *)propValue); - if (rc == NULL) - rc = rc_get_or_create((const char *)propValue); - racelist_insert(&wtype->modifiers[k].races, rc); - xmlFree(propValue); - } - } - xmlXPathFreeObject(races); - } - xmlXPathFreeObject(result); - - /* reading weapon/function */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - xmlChar *propValue; - pf_generic fun; - - parse_function(node, &fun, &propValue); - if (fun == NULL) { - log_error("unknown function name '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name); - xmlFree(propValue); - continue; - } - assert(propValue != NULL); - if (strcmp((const char *)propValue, "attack") == 0) { - wtype->attack = - (bool(*)(const struct troop *, const struct weapon_type *, - int *))fun; - } else { - log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name); - } - xmlFree(propValue); - } - xmlXPathFreeObject(result); - - xpath->node = node; - return wtype; + return wtype; } static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype) { - xmlNodePtr node = xpath->node; - item_type *itype = NULL; - unsigned int flags = ITF_NONE; - xmlXPathObjectPtr result; - int k; + xmlNodePtr node = xpath->node; + item_type *itype = NULL; + unsigned int flags = ITF_NONE; + xmlXPathObjectPtr result; + int k; - if (xml_bvalue(node, "cursed", false)) - flags |= ITF_CURSED; - if (xml_bvalue(node, "notlost", false)) - flags |= ITF_NOTLOST; - if (xml_bvalue(node, "herb", false)) - flags |= ITF_HERB; - if (xml_bvalue(node, "big", false)) - flags |= ITF_BIG; - if (xml_bvalue(node, "animal", false)) - flags |= ITF_ANIMAL; - if (xml_bvalue(node, "vehicle", false)) - flags |= ITF_VEHICLE; - itype = rtype->itype ? rtype->itype : it_get_or_create(rtype); - itype->weight = xml_ivalue(node, "weight", 0); - itype->capacity = xml_ivalue(node, "capacity", 0); - itype->flags |= flags; + if (xml_bvalue(node, "cursed", false)) + flags |= ITF_CURSED; + if (xml_bvalue(node, "notlost", false)) + flags |= ITF_NOTLOST; + if (xml_bvalue(node, "herb", false)) + flags |= ITF_HERB; + if (xml_bvalue(node, "big", false)) + flags |= ITF_BIG; + if (xml_bvalue(node, "animal", false)) + flags |= ITF_ANIMAL; + if (xml_bvalue(node, "vehicle", false)) + flags |= ITF_VEHICLE; + itype = rtype->itype ? rtype->itype : it_get_or_create(rtype); + itype->weight = xml_ivalue(node, "weight", 0); + itype->capacity = xml_ivalue(node, "capacity", 0); + itype->flags |= flags; #if SCORE_MODULE - itype->score = xml_ivalue(node, "score", 0); + itype->score = xml_ivalue(node, "score", 0); #endif - /* reading item/construction */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); - xml_readconstruction(xpath, result->nodesetval, &itype->construction); - xmlXPathFreeObject(result); + /* reading item/construction */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); + xml_readconstruction(xpath, result->nodesetval, &itype->construction); + xmlXPathFreeObject(result); - /* reading item/weapon */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "weapon", xpath); - assert(result->nodesetval->nodeNr <= 1); - if (result->nodesetval->nodeNr != 0) { - xpath->node = result->nodesetval->nodeTab[0]; - rtype->wtype = xml_readweapon(xpath, itype); - } - xmlXPathFreeObject(result); + /* reading item/weapon */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "weapon", xpath); + assert(result->nodesetval->nodeNr <= 1); + if (result->nodesetval->nodeNr != 0) { + xpath->node = result->nodesetval->nodeTab[0]; + rtype->wtype = xml_readweapon(xpath, itype); + } + xmlXPathFreeObject(result); - /* reading item/potion */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "potion", xpath); - assert(result->nodesetval->nodeNr <= 1); - if (result->nodesetval->nodeNr != 0) { - xpath->node = result->nodesetval->nodeTab[0]; - rtype->ptype = xml_readpotion(xpath, itype); - } - xmlXPathFreeObject(result); + /* reading item/potion */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "potion", xpath); + assert(result->nodesetval->nodeNr <= 1); + if (result->nodesetval->nodeNr != 0) { + xpath->node = result->nodesetval->nodeTab[0]; + rtype->ptype = xml_readpotion(xpath, itype); + } + xmlXPathFreeObject(result); - /* reading item/luxury */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "luxury", xpath); - assert(result->nodesetval->nodeNr <= 1); - if (result->nodesetval->nodeNr != 0) { - xpath->node = result->nodesetval->nodeTab[0]; - rtype->ltype = xml_readluxury(xpath, itype); - } - xmlXPathFreeObject(result); + /* reading item/luxury */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "luxury", xpath); + assert(result->nodesetval->nodeNr <= 1); + if (result->nodesetval->nodeNr != 0) { + xpath->node = result->nodesetval->nodeTab[0]; + rtype->ltype = xml_readluxury(xpath, itype); + } + xmlXPathFreeObject(result); - /* reading item/armor */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "armor", xpath); - assert(result->nodesetval->nodeNr <= 1); - if (result->nodesetval->nodeNr != 0) { - xpath->node = result->nodesetval->nodeTab[0]; - rtype->atype = xml_readarmor(xpath, itype); - } - xmlXPathFreeObject(result); + /* reading item/armor */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "armor", xpath); + assert(result->nodesetval->nodeNr <= 1); + if (result->nodesetval->nodeNr != 0) { + xpath->node = result->nodesetval->nodeTab[0]; + rtype->atype = xml_readarmor(xpath, itype); + } + xmlXPathFreeObject(result); - /* reading item/function */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - xmlChar *propValue; - pf_generic fun; + /* reading item/function */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "function", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + xmlChar *propValue; + pf_generic fun; - parse_function(node, &fun, &propValue); - if (fun == NULL) { - log_error("unknown function name '%s' for item '%s'\n", (const char *)propValue, rtype->_name); + parse_function(node, &fun, &propValue); + if (fun == NULL) { + log_error("unknown function name '%s' for item '%s'\n", (const char *)propValue, rtype->_name); + xmlFree(propValue); + continue; + } + assert(propValue != NULL); + if (strcmp((const char *)propValue, "give") == 0) { + itype->give = + (int(*)(struct unit *, struct unit *, const struct item_type *, int, + struct order *))fun; + } + else if (strcmp((const char *)propValue, "use") == 0) { + itype->use = + (int(*)(struct unit *, const struct item_type *, int, + struct order *))fun; + } + else if (strcmp((const char *)propValue, "canuse") == 0) { + itype->canuse = + (bool(*)(const struct unit *, const struct item_type *))fun; + } + else if (strcmp((const char *)propValue, "useonother") == 0) { + itype->useonother = + (int(*)(struct unit *, int, const struct item_type *, int, + struct order *))fun; + } + else { + log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, rtype->_name); + } xmlFree(propValue); - continue; - } - assert(propValue != NULL); - if (strcmp((const char *)propValue, "give") == 0) { - itype->give = - (int (*)(struct unit *, struct unit *, const struct item_type *, int, - struct order *))fun; - } else if (strcmp((const char *)propValue, "use") == 0) { - itype->use = - (int (*)(struct unit *, const struct item_type *, int, - struct order *))fun; - } else if (strcmp((const char *)propValue, "canuse") == 0) { - itype->canuse = - (bool(*)(const struct unit *, const struct item_type *))fun; - } else if (strcmp((const char *)propValue, "useonother") == 0) { - itype->useonother = - (int (*)(struct unit *, int, const struct item_type *, int, - struct order *))fun; - } else { - log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, rtype->_name); - } - xmlFree(propValue); - } - xmlXPathFreeObject(result); + } + xmlXPathFreeObject(result); - return itype; + return itype; } static int parse_rules(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr functions; - xmlNodeSetPtr nodes; - int i; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr functions; + xmlNodeSetPtr nodes; + int i; - /* reading eressea/resources/resource */ - functions = xmlXPathEvalExpression(BAD_CAST "/eressea/rules/function", xpath); - nodes = functions->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - xmlChar *propValue; - pf_generic fun; + /* reading eressea/resources/resource */ + functions = xmlXPathEvalExpression(BAD_CAST "/eressea/rules/function", xpath); + nodes = functions->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar *propValue; + pf_generic fun; - parse_function(node, &fun, &propValue); + parse_function(node, &fun, &propValue); - if (fun == NULL) { - log_error("unknown function for rule '%s' %s\n", (const char *)propValue); - xmlFree(propValue); - continue; + if (fun == NULL) { + log_error("unknown function for rule '%s' %s\n", (const char *)propValue); + xmlFree(propValue); + continue; + } + assert(propValue != NULL); + if (strcmp((const char *)propValue, "wage") == 0) { + global.functions.wage = + (int(*)(const struct region *, const struct faction *, + const struct race *, int))fun; + } + else if (strcmp((const char *)propValue, "maintenance") == 0) { + global.functions.maintenance = (int(*)(const struct unit *))fun; + } + else { + log_error("unknown function for rule '%s'\n", (const char *)propValue); + } + xmlFree(propValue); } - assert(propValue != NULL); - if (strcmp((const char *)propValue, "wage") == 0) { - global.functions.wage = - (int (*)(const struct region *, const struct faction *, - const struct race *, int))fun; - } else if (strcmp((const char *)propValue, "maintenance") == 0) { - global.functions.maintenance = (int (*)(const struct unit *))fun; - } else { - log_error("unknown function for rule '%s'\n", (const char *)propValue); - } - xmlFree(propValue); - } - xmlXPathFreeObject(functions); - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeObject(functions); + xmlXPathFreeContext(xpath); + return 0; } static int parse_resources(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr resources; - xmlNodeSetPtr nodes; - int i; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr resources; + xmlNodeSetPtr nodes; + int i; - /* reading eressea/resources/resource */ - resources = - xmlXPathEvalExpression(BAD_CAST "/eressea/resources/resource", xpath); - nodes = resources->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - xmlChar *propValue, *name, *appearance; - resource_type *rtype; - unsigned int flags = RTF_NONE; - xmlXPathObjectPtr result; - int k; + /* reading eressea/resources/resource */ + resources = + xmlXPathEvalExpression(BAD_CAST "/eressea/resources/resource", xpath); + nodes = resources->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar *propValue, *name, *appearance; + resource_type *rtype; + unsigned int flags = RTF_NONE; + xmlXPathObjectPtr result; + int k; - if (xml_bvalue(node, "pooled", true)) - flags |= RTF_POOLED; - if (xml_bvalue(node, "limited", false)) - flags |= RTF_LIMITED; + if (xml_bvalue(node, "pooled", true)) + flags |= RTF_POOLED; + if (xml_bvalue(node, "limited", false)) + flags |= RTF_LIMITED; - name = xmlGetProp(node, BAD_CAST "name"); - assert(name != NULL); + name = xmlGetProp(node, BAD_CAST "name"); + assert(name != NULL); - rtype = rt_get_or_create((const char *)name); - rtype->flags |= flags; + rtype = rt_get_or_create((const char *)name); + rtype->flags |= flags; - if (name) xmlFree(name); + if (name) xmlFree(name); - name = xmlGetProp(node, BAD_CAST "material"); - if (name) { - rmt_create(rtype, (const char *)name); - xmlFree(name); - } - - /* reading eressea/resources/resource/function */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - if (result->nodesetval != NULL) - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - pf_generic fun; - - parse_function(node, &fun, &propValue); - if (fun == NULL) { - log_error("unknown function name '%s' for resource %s\n", (const char *)propValue, rtype->_name); - xmlFree(propValue); - continue; - } - - assert(propValue != NULL); - if (strcmp((const char *)propValue, "change") == 0) { - rtype->uchange = (rtype_uchange) fun; - } else if (strcmp((const char *)propValue, "get") == 0) { - rtype->uget = (rtype_uget) fun; - } else if (strcmp((const char *)propValue, "name") == 0) { - rtype->name = (rtype_name) fun; - } else { - log_error("unknown function type '%s' for resource %s\n", (const char *)propValue, rtype->_name); - } - xmlFree(propValue); + name = xmlGetProp(node, BAD_CAST "material"); + if (name) { + rmt_create(rtype, (const char *)name); + xmlFree(name); } - xmlXPathFreeObject(result); - /* reading eressea/resources/resource/resourcelimit */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "resourcelimit", xpath); - assert(result->nodesetval->nodeNr <= 1); - if (result->nodesetval->nodeNr != 0) { - resource_limit *rdata; - attrib *a = a_find(rtype->attribs, &at_resourcelimit); - xmlNodePtr limit = result->nodesetval->nodeTab[0]; + /* reading eressea/resources/resource/function */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "function", xpath); + if (result->nodesetval != NULL) + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + pf_generic fun; - if (a == NULL) - a = a_add(&rtype->attribs, a_new(&at_resourcelimit)); - rdata = (resource_limit *) a->data.v; - rtype->flags |= RTF_LIMITED; - xpath->node = limit; - xmlXPathFreeObject(result); + parse_function(node, &fun, &propValue); + if (fun == NULL) { + log_error("unknown function name '%s' for resource %s\n", (const char *)propValue, rtype->_name); + xmlFree(propValue); + continue; + } - result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); - if (result->nodesetval != NULL) { - rdata->modifiers = - calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod)); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - building_type *btype = NULL; - const race *rc = NULL; - - propValue = xmlGetProp(node, BAD_CAST "race"); - if (propValue != NULL) { - rc = rc_find((const char *)propValue); - if (rc == NULL) - rc = rc_get_or_create((const char *)propValue); - xmlFree(propValue); - } - rdata->modifiers[k].race = rc; - - propValue = xmlGetProp(node, BAD_CAST "building"); - if (propValue != NULL) { - btype = bt_get_or_create((const char *)propValue); - xmlFree(propValue); - } - rdata->modifiers[k].btype = btype; - - propValue = xmlGetProp(node, BAD_CAST "type"); - assert(propValue != NULL); - if (strcmp((const char *)propValue, "skill") == 0) { - rdata->modifiers[k].value.i = xml_ivalue(node, "value", 0); - rdata->modifiers[k].flags = RMF_SKILL; - } else if (strcmp((const char *)propValue, "material") == 0) { - rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0); - rdata->modifiers[k].flags = RMF_SAVEMATERIAL; - } else if (strcmp((const char *)propValue, "resource") == 0) { - rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0); - rdata->modifiers[k].flags = RMF_SAVERESOURCE; - } else if (strcmp((const char *)propValue, "require") == 0) { - xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building"); - if (propBldg != NULL) { - btype = bt_get_or_create((const char *)propBldg); - rdata->modifiers[k].btype = btype; - rdata->modifiers[k].flags = RMF_REQUIREDBUILDING; - xmlFree(propBldg); + assert(propValue != NULL); + if (strcmp((const char *)propValue, "change") == 0) { + rtype->uchange = (rtype_uchange)fun; + } + else if (strcmp((const char *)propValue, "get") == 0) { + rtype->uget = (rtype_uget)fun; + } + else if (strcmp((const char *)propValue, "name") == 0) { + rtype->name = (rtype_name)fun; + } + else { + log_error("unknown function type '%s' for resource %s\n", (const char *)propValue, rtype->_name); + } + xmlFree(propValue); } - } else { - log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name); - } - xmlFree(propValue); - } - } - xmlXPathFreeObject(result); + xmlXPathFreeObject(result); - result = xmlXPathEvalExpression(BAD_CAST "guard", xpath); - if (result->nodesetval != NULL) - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - xmlChar *propFlag = xmlGetProp(node, BAD_CAST "flag"); + /* reading eressea/resources/resource/resourcelimit */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "resourcelimit", xpath); + assert(result->nodesetval->nodeNr <= 1); + if (result->nodesetval->nodeNr != 0) { + resource_limit *rdata; + attrib *a = a_find(rtype->attribs, &at_resourcelimit); + xmlNodePtr limit = result->nodesetval->nodeTab[0]; - if (propFlag != NULL) { - if (strcmp((const char *)propFlag, "logging") == 0) { - rdata->guard |= GUARD_TREES; - } else if (strcmp((const char *)propFlag, "mining") == 0) { - rdata->guard |= GUARD_MINING; + if (a == NULL) + a = a_add(&rtype->attribs, a_new(&at_resourcelimit)); + rdata = (resource_limit *)a->data.v; + rtype->flags |= RTF_LIMITED; + xpath->node = limit; + xmlXPathFreeObject(result); + + result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); + if (result->nodesetval != NULL) { + rdata->modifiers = + calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod)); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + building_type *btype = NULL; + const race *rc = NULL; + + propValue = xmlGetProp(node, BAD_CAST "race"); + if (propValue != NULL) { + rc = rc_find((const char *)propValue); + if (rc == NULL) + rc = rc_get_or_create((const char *)propValue); + xmlFree(propValue); + } + rdata->modifiers[k].race = rc; + + propValue = xmlGetProp(node, BAD_CAST "building"); + if (propValue != NULL) { + btype = bt_get_or_create((const char *)propValue); + xmlFree(propValue); + } + rdata->modifiers[k].btype = btype; + + propValue = xmlGetProp(node, BAD_CAST "type"); + assert(propValue != NULL); + if (strcmp((const char *)propValue, "skill") == 0) { + rdata->modifiers[k].value.i = xml_ivalue(node, "value", 0); + rdata->modifiers[k].flags = RMF_SKILL; + } + else if (strcmp((const char *)propValue, "material") == 0) { + rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0); + rdata->modifiers[k].flags = RMF_SAVEMATERIAL; + } + else if (strcmp((const char *)propValue, "resource") == 0) { + rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0); + rdata->modifiers[k].flags = RMF_SAVERESOURCE; + } + else if (strcmp((const char *)propValue, "require") == 0) { + xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building"); + if (propBldg != NULL) { + btype = bt_get_or_create((const char *)propBldg); + rdata->modifiers[k].btype = btype; + rdata->modifiers[k].flags = RMF_REQUIREDBUILDING; + xmlFree(propBldg); + } + } + else { + log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name); + } + xmlFree(propValue); + } } - xmlFree(propFlag); - } + xmlXPathFreeObject(result); + + result = xmlXPathEvalExpression(BAD_CAST "guard", xpath); + if (result->nodesetval != NULL) + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + xmlChar *propFlag = xmlGetProp(node, BAD_CAST "flag"); + + if (propFlag != NULL) { + if (strcmp((const char *)propFlag, "logging") == 0) { + rdata->guard |= GUARD_TREES; + } + else if (strcmp((const char *)propFlag, "mining") == 0) { + rdata->guard |= GUARD_MINING; + } + xmlFree(propFlag); + } + } + xmlXPathFreeObject(result); + + /* reading eressea/resources/resource/resourcelimit/function */ + result = xmlXPathEvalExpression(BAD_CAST "function", xpath); + if (result->nodesetval != NULL) + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + pf_generic fun; + + propValue = xmlGetProp(node, BAD_CAST "value"); + assert(propValue != NULL); + fun = get_function((const char *)propValue); + if (fun == NULL) { + log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name); + xmlFree(propValue); + continue; + } + xmlFree(propValue); + + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue != NULL); + if (strcmp((const char *)propValue, "produce") == 0) { + rdata->produce = (rlimit_produce)fun; + } + else if (strcmp((const char *)propValue, "limit") == 0) { + rdata->limit = (rlimit_limit)fun; + } + else { + log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name); + } + xmlFree(propValue); + } } - xmlXPathFreeObject(result); + xmlXPathFreeObject(result); - /* reading eressea/resources/resource/resourcelimit/function */ - result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - if (result->nodesetval != NULL) - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - pf_generic fun; + /* reading eressea/resources/resource/resourcelimit/function */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "resourcelimit/function", xpath); + xmlXPathFreeObject(result); - propValue = xmlGetProp(node, BAD_CAST "value"); - assert(propValue != NULL); - fun = get_function((const char *)propValue); - if (fun == NULL) { - log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name); - xmlFree(propValue); - continue; - } - xmlFree(propValue); - - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - if (strcmp((const char *)propValue, "produce") == 0) { - rdata->produce = (rlimit_produce) fun; - } else if (strcmp((const char *)propValue, "limit") == 0) { - rdata->limit = (rlimit_limit) fun; - } else { - log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name); - } - xmlFree(propValue); + /* reading eressea/resources/resource/item */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "item", xpath); + assert(result->nodesetval->nodeNr <= 1); + if (result->nodesetval->nodeNr != 0) { + rtype->flags |= RTF_ITEM; + xpath->node = result->nodesetval->nodeTab[0]; + rtype->itype = xml_readitem(xpath, rtype); + appearance = xmlGetProp(node, BAD_CAST "appearance"); + if (appearance) { + it_set_appearance(rtype->itype, (const char *)appearance); + xmlFree(appearance); + } } + xmlXPathFreeObject(result); } - xmlXPathFreeObject(result); + xmlXPathFreeObject(resources); - /* reading eressea/resources/resource/resourcelimit/function */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "resourcelimit/function", xpath); - xmlXPathFreeObject(result); + xmlXPathFreeContext(xpath); - /* reading eressea/resources/resource/item */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "item", xpath); - assert(result->nodesetval->nodeNr <= 1); - if (result->nodesetval->nodeNr != 0) { - rtype->flags |= RTF_ITEM; - xpath->node = result->nodesetval->nodeTab[0]; - rtype->itype = xml_readitem(xpath, rtype); - appearance = xmlGetProp(node, BAD_CAST "appearance"); - if (appearance) { - it_set_appearance(rtype->itype, (const char *)appearance); - xmlFree(appearance); - } - } - xmlXPathFreeObject(result); - } - xmlXPathFreeObject(resources); + /* make sure old items (used in requirements) are available */ + init_resources(); + init_itemtypes(); - xmlXPathFreeContext(xpath); - - /* make sure old items (used in requirements) are available */ - init_resources(); - init_itemtypes(); - - return 0; + return 0; } static void add_items(equipment * eq, xmlNodeSetPtr nsetItems) { - if (nsetItems != NULL && nsetItems->nodeNr > 0) { - int i; - for (i = 0; i != nsetItems->nodeNr; ++i) { - xmlNodePtr node = nsetItems->nodeTab[i]; - xmlChar *propValue; - const struct item_type *itype; + if (nsetItems != NULL && nsetItems->nodeNr > 0) { + int i; + for (i = 0; i != nsetItems->nodeNr; ++i) { + xmlNodePtr node = nsetItems->nodeTab[i]; + xmlChar *propValue; + const struct item_type *itype; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - itype = it_find((const char *)propValue); - xmlFree(propValue); - if (itype != NULL) { - propValue = xmlGetProp(node, BAD_CAST "amount"); - if (propValue != NULL) { - equipment_setitem(eq, itype, (const char *)propValue); - xmlFree(propValue); + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue != NULL); + itype = it_find((const char *)propValue); + xmlFree(propValue); + if (itype != NULL) { + propValue = xmlGetProp(node, BAD_CAST "amount"); + if (propValue != NULL) { + equipment_setitem(eq, itype, (const char *)propValue); + xmlFree(propValue); + } + } } - } } - } } static void add_callbacks(equipment * eq, xmlNodeSetPtr nsetItems) { - if (nsetItems != NULL && nsetItems->nodeNr > 0) { - int i; - for (i = 0; i != nsetItems->nodeNr; ++i) { - xmlNodePtr node = nsetItems->nodeTab[i]; - xmlChar *propValue; - pf_generic fun; + if (nsetItems != NULL && nsetItems->nodeNr > 0) { + int i; + for (i = 0; i != nsetItems->nodeNr; ++i) { + xmlNodePtr node = nsetItems->nodeTab[i]; + xmlChar *propValue; + pf_generic fun; - propValue = xmlGetProp(node, BAD_CAST "name"); - if (propValue != NULL) { - fun = get_function((const char *)propValue); - if (fun) { - equipment_setcallback(eq, (void (*)(const struct equipment *, - struct unit *))fun); + propValue = xmlGetProp(node, BAD_CAST "name"); + if (propValue != NULL) { + fun = get_function((const char *)propValue); + if (fun) { + equipment_setcallback(eq, (void(*)(const struct equipment *, + struct unit *))fun); + } + xmlFree(propValue); + } } - xmlFree(propValue); - } } - } } static void add_spells(equipment * eq, xmlNodeSetPtr nsetItems) { - if (nsetItems != NULL && nsetItems->nodeNr > 0) { - int i; - for (i = 0; i != nsetItems->nodeNr; ++i) { - xmlNodePtr node = nsetItems->nodeTab[i]; - xmlChar *propValue; - struct spell *sp; + if (nsetItems != NULL && nsetItems->nodeNr > 0) { + int i; + for (i = 0; i != nsetItems->nodeNr; ++i) { + xmlNodePtr node = nsetItems->nodeTab[i]; + xmlChar *propValue; + struct spell *sp; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - sp = find_spell((const char *)propValue); - if (!sp) { - log_error("no spell '%s' for equipment-set '%s'\n", (const char *)propValue, eq->name); - } else { - int level = xml_ivalue(node, "level", 0); - if (level>0) { - equipment_addspell(eq, sp, level); - } else { - log_error("spell '%s' for equipment-set '%s' has no level\n", sp->sname, eq->name); + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue != NULL); + sp = find_spell((const char *)propValue); + if (!sp) { + log_error("no spell '%s' for equipment-set '%s'\n", (const char *)propValue, eq->name); + } + else { + int level = xml_ivalue(node, "level", 0); + if (level > 0) { + equipment_addspell(eq, sp, level); + } + else { + log_error("spell '%s' for equipment-set '%s' has no level\n", sp->sname, eq->name); + } + } + xmlFree(propValue); } - } - xmlFree(propValue); } - } } static void add_skills(equipment * eq, xmlNodeSetPtr nsetSkills) { - if (nsetSkills != NULL && nsetSkills->nodeNr > 0) { - int i; - for (i = 0; i != nsetSkills->nodeNr; ++i) { - xmlNodePtr node = nsetSkills->nodeTab[i]; - xmlChar *propValue; - skill_t sk; + if (nsetSkills != NULL && nsetSkills->nodeNr > 0) { + int i; + for (i = 0; i != nsetSkills->nodeNr; ++i) { + xmlNodePtr node = nsetSkills->nodeTab[i]; + xmlChar *propValue; + skill_t sk; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - sk = findskill((const char *)propValue); - if (sk == NOSKILL) { - log_error("unknown skill '%s' in equipment-set %s\n", (const char *)propValue, eq->name); - xmlFree(propValue); - } else { - xmlFree(propValue); - propValue = xmlGetProp(node, BAD_CAST "level"); - if (propValue != NULL) { - equipment_setskill(eq, sk, (const char *)propValue); - xmlFree(propValue); + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue != NULL); + sk = findskill((const char *)propValue); + if (sk == NOSKILL) { + log_error("unknown skill '%s' in equipment-set %s\n", (const char *)propValue, eq->name); + xmlFree(propValue); + } + else { + xmlFree(propValue); + propValue = xmlGetProp(node, BAD_CAST "level"); + if (propValue != NULL) { + equipment_setskill(eq, sk, (const char *)propValue); + xmlFree(propValue); + } + } } - } } - } } static void add_subsets(xmlDocPtr doc, equipment * eq, xmlNodeSetPtr nsetSubsets) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - if (nsetSubsets != NULL && nsetSubsets->nodeNr > 0) { - int i; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + if (nsetSubsets != NULL && nsetSubsets->nodeNr > 0) { + int i; - eq->subsets = calloc(nsetSubsets->nodeNr + 1, sizeof(subset)); - for (i = 0; i != nsetSubsets->nodeNr; ++i) { - xmlXPathObjectPtr xpathResult; - xmlNodePtr node = nsetSubsets->nodeTab[i]; - xmlChar *propValue; + eq->subsets = calloc(nsetSubsets->nodeNr + 1, sizeof(subset)); + for (i = 0; i != nsetSubsets->nodeNr; ++i) { + xmlXPathObjectPtr xpathResult; + xmlNodePtr node = nsetSubsets->nodeTab[i]; + xmlChar *propValue; - eq->subsets[i].chance = 1.0f; - propValue = xmlGetProp(node, BAD_CAST "chance"); - if (propValue != NULL) { - eq->subsets[i].chance = (float)atof((const char *)propValue); - xmlFree(propValue); - } - xpath->node = node; - xpathResult = xmlXPathEvalExpression(BAD_CAST "set", xpath); - if (xpathResult->nodesetval) { - xmlNodeSetPtr nsetSets = xpathResult->nodesetval; - float totalChance = 0.0f; - - if (nsetSets->nodeNr > 0) { - int set; - eq->subsets[i].sets = - calloc(nsetSets->nodeNr + 1, sizeof(subsetitem)); - for (set = 0; set != nsetSets->nodeNr; ++set) { - xmlNodePtr nodeSet = nsetSets->nodeTab[set]; - float chance = 1.0f; - - propValue = xmlGetProp(nodeSet, BAD_CAST "chance"); + eq->subsets[i].chance = 1.0f; + propValue = xmlGetProp(node, BAD_CAST "chance"); if (propValue != NULL) { - chance = (float)atof((const char *)propValue); - xmlFree(propValue); + eq->subsets[i].chance = (float)atof((const char *)propValue); + xmlFree(propValue); } - totalChance += chance; + xpath->node = node; + xpathResult = xmlXPathEvalExpression(BAD_CAST "set", xpath); + if (xpathResult->nodesetval) { + xmlNodeSetPtr nsetSets = xpathResult->nodesetval; + float totalChance = 0.0f; - propValue = xmlGetProp(nodeSet, BAD_CAST "name"); - assert(propValue != NULL); - eq->subsets[i].sets[set].chance = chance; - eq->subsets[i].sets[set].set = - create_equipment((const char *)propValue); - xmlFree(propValue); - } + if (nsetSets->nodeNr > 0) { + int set; + eq->subsets[i].sets = + calloc(nsetSets->nodeNr + 1, sizeof(subsetitem)); + for (set = 0; set != nsetSets->nodeNr; ++set) { + xmlNodePtr nodeSet = nsetSets->nodeTab[set]; + float chance = 1.0f; + + propValue = xmlGetProp(nodeSet, BAD_CAST "chance"); + if (propValue != NULL) { + chance = (float)atof((const char *)propValue); + xmlFree(propValue); + } + totalChance += chance; + + propValue = xmlGetProp(nodeSet, BAD_CAST "name"); + assert(propValue != NULL); + eq->subsets[i].sets[set].chance = chance; + eq->subsets[i].sets[set].set = + create_equipment((const char *)propValue); + xmlFree(propValue); + } + } + if (totalChance > 1.0f) { + log_error("total chance exceeds 1.0: %f in equipment set %s.\n", totalChance, eq->name); + } + } + xmlXPathFreeObject(xpathResult); } - if (totalChance > 1.0f) { - log_error("total chance exceeds 1.0: %f in equipment set %s.\n", totalChance, eq->name); - } - } - xmlXPathFreeObject(xpathResult); } - } - xmlXPathFreeContext(xpath); + xmlXPathFreeContext(xpath); } static int parse_equipment(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr xpathRaces; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr xpathRaces; - /* reading eressea/equipment/set */ - xpathRaces = xmlXPathEvalExpression(BAD_CAST "/eressea/equipment/set", xpath); - if (xpathRaces->nodesetval) { - xmlNodeSetPtr nsetRaces = xpathRaces->nodesetval; - int i; + /* reading eressea/equipment/set */ + xpathRaces = xmlXPathEvalExpression(BAD_CAST "/eressea/equipment/set", xpath); + if (xpathRaces->nodesetval) { + xmlNodeSetPtr nsetRaces = xpathRaces->nodesetval; + int i; - for (i = 0; i != nsetRaces->nodeNr; ++i) { - xmlNodePtr node = nsetRaces->nodeTab[i]; - xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); + for (i = 0; i != nsetRaces->nodeNr; ++i) { + xmlNodePtr node = nsetRaces->nodeTab[i]; + xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); - if (propName != NULL) { - equipment *eq = create_equipment((const char *)propName); - xmlXPathObjectPtr xpathResult; + if (propName != NULL) { + equipment *eq = create_equipment((const char *)propName); + xmlXPathObjectPtr xpathResult; - xpath->node = node; + xpath->node = node; - xpathResult = xmlXPathEvalExpression(BAD_CAST "callback", xpath); - assert(!eq->callback); - add_callbacks(eq, xpathResult->nodesetval); - xmlXPathFreeObject(xpathResult); + xpathResult = xmlXPathEvalExpression(BAD_CAST "callback", xpath); + assert(!eq->callback); + add_callbacks(eq, xpathResult->nodesetval); + xmlXPathFreeObject(xpathResult); - xpathResult = xmlXPathEvalExpression(BAD_CAST "item", xpath); - assert(!eq->items); - add_items(eq, xpathResult->nodesetval); - xmlXPathFreeObject(xpathResult); + xpathResult = xmlXPathEvalExpression(BAD_CAST "item", xpath); + assert(!eq->items); + add_items(eq, xpathResult->nodesetval); + xmlXPathFreeObject(xpathResult); - xpathResult = xmlXPathEvalExpression(BAD_CAST "spell", xpath); - assert(!eq->spellbook); - add_spells(eq, xpathResult->nodesetval); - xmlXPathFreeObject(xpathResult); + xpathResult = xmlXPathEvalExpression(BAD_CAST "spell", xpath); + assert(!eq->spellbook); + add_spells(eq, xpathResult->nodesetval); + xmlXPathFreeObject(xpathResult); - xpathResult = xmlXPathEvalExpression(BAD_CAST "skill", xpath); - add_skills(eq, xpathResult->nodesetval); - xmlXPathFreeObject(xpathResult); + xpathResult = xmlXPathEvalExpression(BAD_CAST "skill", xpath); + add_skills(eq, xpathResult->nodesetval); + xmlXPathFreeObject(xpathResult); - xpathResult = xmlXPathEvalExpression(BAD_CAST "subset", xpath); - assert(!eq->subsets); - add_subsets(doc, eq, xpathResult->nodesetval); - xmlXPathFreeObject(xpathResult); + xpathResult = xmlXPathEvalExpression(BAD_CAST "subset", xpath); + assert(!eq->subsets); + add_subsets(doc, eq, xpathResult->nodesetval); + xmlXPathFreeObject(xpathResult); - xmlFree(propName); - } + xmlFree(propName); + } + } } - } - xmlXPathFreeObject(xpathRaces); - xmlXPathFreeContext(xpath); + xmlXPathFreeObject(xpathRaces); + xmlXPathFreeContext(xpath); - return 0; + return 0; } static int parse_spellbooks(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr spellbooks; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr spellbooks; - /* reading eressea/spells/spell */ - spellbooks = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spellbook", xpath); + /* reading eressea/spells/spell */ + spellbooks = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spellbook", xpath); - if (spellbooks->nodesetval != NULL) { - xmlNodeSetPtr nodes = spellbooks->nodesetval; - int i, k; + if (spellbooks->nodesetval != NULL) { + xmlNodeSetPtr nodes = spellbooks->nodesetval; + int i, k; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlXPathObjectPtr result; - xmlNodePtr node = nodes->nodeTab[i]; - xmlChar *propValue; - spellbook * sb; - - propValue = xmlGetProp(node, BAD_CAST "name"); - if (propValue) { - sb = get_spellbook((const char *)propValue); - xmlFree(propValue); - } else { - log_error("spellbook at index '%d' has n name\n", i); - continue; - } + for (i = 0; i != nodes->nodeNr; ++i) { + xmlXPathObjectPtr result; + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar *propValue; + spellbook * sb; - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "entry", xpath); + propValue = xmlGetProp(node, BAD_CAST "name"); + if (propValue) { + sb = get_spellbook((const char *)propValue); + xmlFree(propValue); + } + else { + log_error("spellbook at index '%d' has n name\n", i); + continue; + } - if (result->nodesetval->nodeNr > 0) { - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - spell * sp = 0; - int level = xml_ivalue(node, "level", -1); + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "entry", xpath); - propValue = xmlGetProp(node, BAD_CAST "spell"); - if (propValue) { - sp = find_spell((const char *)propValue); - xmlFree(propValue); - } - if (sp && level>0) { - spellbook_add(sb, sp, level); - } else { - log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name); - } + if (result->nodesetval->nodeNr > 0) { + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + spell * sp = 0; + int level = xml_ivalue(node, "level", -1); + + propValue = xmlGetProp(node, BAD_CAST "spell"); + if (propValue) { + sp = find_spell((const char *)propValue); + xmlFree(propValue); + } + if (sp && level > 0) { + spellbook_add(sb, sp, level); + } + else { + log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name); + } + } + } + xmlXPathFreeObject(result); } - } - xmlXPathFreeObject(result); } - } - xmlXPathFreeObject(spellbooks); - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeObject(spellbooks); + xmlXPathFreeContext(xpath); + return 0; } static int parse_spells(xmlDocPtr doc) { - pf_generic cast = 0; - pf_generic fumble = 0; - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr spells; - char zText[32]; - strcpy(zText, "fumble_"); + pf_generic cast = 0; + pf_generic fumble = 0; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr spells; + char zText[32]; + strcpy(zText, "fumble_"); - /* reading eressea/spells/spell */ - spells = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spell", xpath); - if (spells->nodesetval != NULL) { - xmlNodeSetPtr nodes = spells->nodesetval; - int i; + /* reading eressea/spells/spell */ + spells = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spell", xpath); + if (spells->nodesetval != NULL) { + xmlNodeSetPtr nodes = spells->nodesetval; + int i; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlXPathObjectPtr result; - xmlNodePtr node = nodes->nodeTab[i]; - xmlChar *propValue; - int k; - spell_component *component; - spell *sp; - unsigned int index; - static int modes[] = { 0, PRECOMBATSPELL, COMBATSPELL, POSTCOMBATSPELL }; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlXPathObjectPtr result; + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar *propValue; + int k; + spell_component *component; + spell *sp; + unsigned int index; + static int modes[] = { 0, PRECOMBATSPELL, COMBATSPELL, POSTCOMBATSPELL }; - /* spellname */ - index = xml_ivalue(node, "index", 0); - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - sp = create_spell((const char *)propValue, index); - xmlFree(propValue); - if (!sp) { - continue; - } - - propValue = xmlGetProp(node, BAD_CAST "parameters"); - if (propValue) { - sp->parameter = _strdup((const char *)propValue); - xmlFree(propValue); - } - - propValue = xmlGetProp(node, BAD_CAST "syntax"); - if (propValue) { - sp->syntax = _strdup((const char *)propValue); - xmlFree(propValue); - } -#ifdef TODO /* no longer need it, spellbooks! */ - /* magic type */ - propValue = xmlGetProp(node, BAD_CAST "type"); - assert(propValue != NULL); - for (sp->magietyp = 0; sp->magietyp != MAXMAGIETYP; ++sp->magietyp) { - if (strcmp(magic_school[sp->magietyp], (const char *)propValue) == 0) - break; - } - assert(sp->magietyp != MAXMAGIETYP); - xmlFree(propValue); - /* level, rank and flags */ -#endif - sp->rank = (char)xml_ivalue(node, "rank", -1); - if (xml_bvalue(node, "los", false)) - sp->sptyp |= TESTCANSEE; /* must see or have contact */ - if (!xml_bvalue(node, "target_global", false)) - sp->sptyp |= SEARCHLOCAL; /* must be in same region */ - if (xml_bvalue(node, "ship", false)) - sp->sptyp |= ONSHIPCAST; - if (xml_bvalue(node, "ocean", false)) - sp->sptyp |= OCEANCASTABLE; - if (xml_bvalue(node, "far", false)) - sp->sptyp |= FARCASTING; - if (xml_bvalue(node, "variable", false)) - sp->sptyp |= SPELLLEVEL; - k = xml_ivalue(node, "combat", 0); - if (k >= 0 && k <= 3) - sp->sptyp |= modes[k]; - - /* reading eressea/spells/spell/function */ - - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - - if (result->nodesetval->nodeNr == 0) { - cast = get_function(sp->sname); - if (!cast) { - log_error("no spell cast function registered for '%s'\n", sp->sname); - } - strlcpy(zText+7, sp->sname, sizeof(zText)-7); - fumble = get_function(zText); - } else { - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - pf_generic fun; - - parse_function(node, &fun, &propValue); + /* spellname */ + index = xml_ivalue(node, "index", 0); + propValue = xmlGetProp(node, BAD_CAST "name"); assert(propValue != NULL); - if (strcmp((const char *)propValue, "cast") == 0) { - if (fun) { - cast = fun; - } else { - log_error("unknown function name '%s' for spell '%s'\n", (const char *)propValue, sp->sname); - } - } else if (fun && strcmp((const char *)propValue, "fumble") == 0) { - fumble = fun; - } else { - log_error("unknown function type '%s' for spell '%s'\n", (const char *)propValue, sp->sname); - } + sp = create_spell((const char *)propValue, index); xmlFree(propValue); - } - } - sp->cast = (spell_f)cast; - sp->fumble = (fumble_f)fumble; - xmlXPathFreeObject(result); + if (!sp) { + continue; + } - /* reading eressea/spells/spell/resource */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "resource", xpath); - if (result->nodesetval->nodeNr) { - sp->components = - (spell_component *) malloc(sizeof(spell_component) * - (result->nodesetval->nodeNr + 1)); - sp->components[result->nodesetval->nodeNr].type = 0; - } - for (component = sp->components, k = 0; k != result->nodesetval->nodeNr; - ++k) { - const resource_type *rtype; - xmlNodePtr node = result->nodesetval->nodeTab[k]; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue); - rtype = rt_find((const char *)propValue); - if (!rtype) { - log_error("spell %s uses unknown component %s.\n", sp->sname, (const char *)propValue); - xmlFree(propValue); - continue; - } - component->type = rtype; - xmlFree(propValue); - component->amount = xml_ivalue(node, "amount", 1); - component->cost = SPC_FIX; - propValue = xmlGetProp(node, BAD_CAST "cost"); - if (propValue != NULL) { - if (strcmp((const char *)propValue, "linear") == 0) { - if ((sp->sptyp&SPELLLEVEL)==0) { - log_error("spell '%s' has linear cost but fixed level\n", sp->sname); + propValue = xmlGetProp(node, BAD_CAST "parameters"); + if (propValue) { + sp->parameter = _strdup((const char *)propValue); + xmlFree(propValue); } - component->cost = SPC_LINEAR; - } else if (strcmp((const char *)propValue, "level") == 0) { - if ((sp->sptyp&SPELLLEVEL)==0) { - log_error("spell '%s' has levelled cost but fixed level\n", sp->sname); + + propValue = xmlGetProp(node, BAD_CAST "syntax"); + if (propValue) { + sp->syntax = _strdup((const char *)propValue); + xmlFree(propValue); } - component->cost = SPC_LEVEL; - } - xmlFree(propValue); +#ifdef TODO /* no longer need it, spellbooks! */ + /* magic type */ + propValue = xmlGetProp(node, BAD_CAST "type"); + assert(propValue != NULL); + for (sp->magietyp = 0; sp->magietyp != MAXMAGIETYP; ++sp->magietyp) { + if (strcmp(magic_school[sp->magietyp], (const char *)propValue) == 0) + break; + } + assert(sp->magietyp != MAXMAGIETYP); + xmlFree(propValue); + /* level, rank and flags */ +#endif + sp->rank = (char)xml_ivalue(node, "rank", -1); + if (xml_bvalue(node, "los", false)) + sp->sptyp |= TESTCANSEE; /* must see or have contact */ + if (!xml_bvalue(node, "target_global", false)) + sp->sptyp |= SEARCHLOCAL; /* must be in same region */ + if (xml_bvalue(node, "ship", false)) + sp->sptyp |= ONSHIPCAST; + if (xml_bvalue(node, "ocean", false)) + sp->sptyp |= OCEANCASTABLE; + if (xml_bvalue(node, "far", false)) + sp->sptyp |= FARCASTING; + if (xml_bvalue(node, "variable", false)) + sp->sptyp |= SPELLLEVEL; + k = xml_ivalue(node, "combat", 0); + if (k >= 0 && k <= 3) + sp->sptyp |= modes[k]; + + /* reading eressea/spells/spell/function */ + + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "function", xpath); + + if (result->nodesetval->nodeNr == 0) { + cast = get_function(sp->sname); + if (!cast) { + log_error("no spell cast function registered for '%s'\n", sp->sname); + } + strlcpy(zText + 7, sp->sname, sizeof(zText) - 7); + fumble = get_function(zText); + } + else { + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + pf_generic fun; + + parse_function(node, &fun, &propValue); + assert(propValue != NULL); + if (strcmp((const char *)propValue, "cast") == 0) { + if (fun) { + cast = fun; + } + else { + log_error("unknown function name '%s' for spell '%s'\n", (const char *)propValue, sp->sname); + } + } + else if (fun && strcmp((const char *)propValue, "fumble") == 0) { + fumble = fun; + } + else { + log_error("unknown function type '%s' for spell '%s'\n", (const char *)propValue, sp->sname); + } + xmlFree(propValue); + } + } + sp->cast = (spell_f)cast; + sp->fumble = (fumble_f)fumble; + xmlXPathFreeObject(result); + + /* reading eressea/spells/spell/resource */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "resource", xpath); + if (result->nodesetval->nodeNr) { + sp->components = + (spell_component *)malloc(sizeof(spell_component) * + (result->nodesetval->nodeNr + 1)); + sp->components[result->nodesetval->nodeNr].type = 0; + } + for (component = sp->components, k = 0; k != result->nodesetval->nodeNr; + ++k) { + const resource_type *rtype; + xmlNodePtr node = result->nodesetval->nodeTab[k]; + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue); + rtype = rt_find((const char *)propValue); + if (!rtype) { + log_error("spell %s uses unknown component %s.\n", sp->sname, (const char *)propValue); + xmlFree(propValue); + continue; + } + component->type = rtype; + xmlFree(propValue); + component->amount = xml_ivalue(node, "amount", 1); + component->cost = SPC_FIX; + propValue = xmlGetProp(node, BAD_CAST "cost"); + if (propValue != NULL) { + if (strcmp((const char *)propValue, "linear") == 0) { + if ((sp->sptyp&SPELLLEVEL) == 0) { + log_error("spell '%s' has linear cost but fixed level\n", sp->sname); + } + component->cost = SPC_LINEAR; + } + else if (strcmp((const char *)propValue, "level") == 0) { + if ((sp->sptyp&SPELLLEVEL) == 0) { + log_error("spell '%s' has levelled cost but fixed level\n", sp->sname); + } + component->cost = SPC_LEVEL; + } + xmlFree(propValue); + } + component++; + } + xmlXPathFreeObject(result); } - component++; - } - xmlXPathFreeObject(result); } - } - xmlXPathFreeObject(spells); + xmlXPathFreeObject(spells); - xmlXPathFreeContext(xpath); + xmlXPathFreeContext(xpath); - return 0; + return 0; } static void parse_param(struct param **params, xmlNodePtr node) { - xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); - xmlChar *propValue = xmlGetProp(node, BAD_CAST "value"); + xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); + xmlChar *propValue = xmlGetProp(node, BAD_CAST "value"); - set_param(params, (const char *)propName, (const char *)propValue); + set_param(params, (const char *)propName, (const char *)propValue); - xmlFree(propName); - xmlFree(propValue); + xmlFree(propName); + xmlFree(propValue); } static void parse_ai(race * rc, xmlNodePtr node) { - rc->splitsize = xml_ivalue(node, "splitsize", 0); - rc->aggression = (float)xml_fvalue(node, "aggression", 0.04); - if (xml_bvalue(node, "killpeasants", false)) - rc->flags |= RCF_KILLPEASANTS; - if (xml_bvalue(node, "moverandom", false)) - rc->flags |= RCF_MOVERANDOM; - if (xml_bvalue(node, "learn", false)) - rc->flags |= RCF_LEARN; + rc->splitsize = xml_ivalue(node, "splitsize", 0); + rc->aggression = (float)xml_fvalue(node, "aggression", 0.04); + if (xml_bvalue(node, "killpeasants", false)) + rc->flags |= RCF_KILLPEASANTS; + if (xml_bvalue(node, "moverandom", false)) + rc->flags |= RCF_MOVERANDOM; + if (xml_bvalue(node, "learn", false)) + rc->flags |= RCF_LEARN; } static int parse_races(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr races; - xmlNodeSetPtr nodes; - int i; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr races; + xmlNodeSetPtr nodes; + int i; - /* reading eressea/races/race */ - races = xmlXPathEvalExpression(BAD_CAST "/eressea/races/race", xpath); - nodes = races->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - xmlNodePtr child; - xmlChar *propValue; - race *rc; - xmlXPathObjectPtr result; - int k, study_speed_base; - struct att *attack; + /* reading eressea/races/race */ + races = xmlXPathEvalExpression(BAD_CAST "/eressea/races/race", xpath); + nodes = races->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + xmlNodePtr child; + xmlChar *propValue; + race *rc; + xmlXPathObjectPtr result; + int k, study_speed_base; + struct att *attack; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - rc = rc_get_or_create((const char *)propValue); - xmlFree(propValue); - - propValue = xmlGetProp(node, BAD_CAST "damage"); - assert(propValue != NULL); - rc->def_damage = _strdup((const char *)propValue); - xmlFree(propValue); - - rc->magres = (float)xml_fvalue(node, "magres", 0.0); - rc->maxaura = (float)xml_fvalue(node, "maxaura", 0.0); - rc->regaura = (float)xml_fvalue(node, "regaura", 1.0); - rc->recruitcost = xml_ivalue(node, "recruitcost", 0); - rc->maintenance = xml_ivalue(node, "maintenance", 0); - rc->weight = xml_ivalue(node, "weight", PERSON_WEIGHT); - rc->capacity = xml_ivalue(node, "capacity", 540); - rc->speed = (float)xml_fvalue(node, "speed", 1.0F); - rc->hitpoints = xml_ivalue(node, "hp", 0); - rc->armor = (char)xml_ivalue(node, "ac", 0); - study_speed_base = xml_ivalue(node, "studyspeed", 0); - - rc->at_default = (char)xml_ivalue(node, "unarmedattack", -2); - rc->df_default = (char)xml_ivalue(node, "unarmeddefense", -2); - rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", 0); - rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", 0); - - if (!xml_bvalue(node, "playerrace", false)) - rc->flags |= RCF_NPC; - if (xml_bvalue(node, "scarepeasants", false)) - rc->flags |= RCF_SCAREPEASANTS; - if (!xml_bvalue(node, "cansteal", true)) - rc->flags |= RCF_NOSTEAL; - if (xml_bvalue(node, "cansail", true)) - rc->flags |= RCF_CANSAIL; - if (xml_bvalue(node, "cannotmove", false)) - rc->flags |= RCF_CANNOTMOVE; - if (xml_bvalue(node, "fly", false)) - rc->flags |= RCF_FLY; - if (xml_bvalue(node, "invisible", false)) - rc->flags |= RCF_INVISIBLE; - if (xml_bvalue(node, "coastal", false)) - rc->flags |= RCF_COASTAL; - if (xml_bvalue(node, "unarmedguard", false)) - rc->flags |= RCF_UNARMEDGUARD; - if (xml_bvalue(node, "swim", false)) - rc->flags |= RCF_SWIM; - if (xml_bvalue(node, "walk", false)) - rc->flags |= RCF_WALK; - if (!xml_bvalue(node, "canlearn", true)) - rc->flags |= RCF_NOLEARN; - if (!xml_bvalue(node, "canteach", true)) - rc->flags |= RCF_NOTEACH; - if (xml_bvalue(node, "horse", false)) - rc->flags |= RCF_HORSE; - if (xml_bvalue(node, "desert", false)) - rc->flags |= RCF_DESERT; - if (xml_bvalue(node, "absorbpeasants", false)) - rc->flags |= RCF_ABSORBPEASANTS; - if (xml_bvalue(node, "noheal", false)) - rc->flags |= RCF_NOHEAL; - if (xml_bvalue(node, "noweapons", false)) - rc->flags |= RCF_NOWEAPONS; - if (xml_bvalue(node, "shapeshift", false)) - rc->flags |= RCF_SHAPESHIFT; - if (xml_bvalue(node, "shapeshiftany", false)) - rc->flags |= RCF_SHAPESHIFTANY; - if (xml_bvalue(node, "illusionary", false)) - rc->flags |= RCF_ILLUSIONARY; - if (xml_bvalue(node, "undead", false)) - rc->flags |= RCF_UNDEAD; - if (xml_bvalue(node, "dragon", false)) - rc->flags |= RCF_DRAGON; - if (xml_bvalue(node, "shipspeed", false)) - rc->flags |= RCF_SHIPSPEED; - if (xml_bvalue(node, "stonegolem", false)) - rc->flags |= RCF_STONEGOLEM; - if (xml_bvalue(node, "irongolem", false)) - rc->flags |= RCF_IRONGOLEM; - - if (xml_bvalue(node, "giveitem", false)) - rc->ec_flags |= GIVEITEM; - if (xml_bvalue(node, "giveperson", false)) - rc->ec_flags |= GIVEPERSON; - if (xml_bvalue(node, "giveunit", false)) - rc->ec_flags |= GIVEUNIT; - if (xml_bvalue(node, "getitem", false)) - rc->ec_flags |= GETITEM; - if (xml_bvalue(node, "recruithorses", false)) - rc->ec_flags |= ECF_REC_HORSES; - if (xml_bvalue(node, "recruitethereal", false)) - rc->ec_flags |= ECF_REC_ETHEREAL; - if (xml_bvalue(node, "recruitunlimited", false)) - rc->ec_flags |= ECF_REC_UNLIMITED; - - if (xml_bvalue(node, "equipment", false)) - rc->battle_flags |= BF_EQUIPMENT; - if (xml_bvalue(node, "noblock", false)) - rc->battle_flags |= BF_NOBLOCK; - if (xml_bvalue(node, "invinciblenonmagic", false)) - rc->battle_flags |= BF_INV_NONMAGIC; - if (xml_bvalue(node, "resistbash", false)) - rc->battle_flags |= BF_RES_BASH; - if (xml_bvalue(node, "resistcut", false)) - rc->battle_flags |= BF_RES_CUT; - if (xml_bvalue(node, "resistpierce", false)) - rc->battle_flags |= BF_RES_PIERCE; - if (xml_bvalue(node, "canattack", true)) - rc->battle_flags |= BF_CANATTACK; - - for (child = node->children; child; child = child->next) { - if (strcmp((const char *)child->name, "ai") == 0) { - parse_ai(rc, child); - } else if (strcmp((const char *)child->name, "param") == 0) { - parse_param(&rc->parameters, child); - } - } - rc->recruit_multi = get_param_flt(rc->parameters, "recruit_multi", 1.0); - - /* reading eressea/races/race/skill */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "skill", xpath); - memset(rc->bonus, 0, sizeof(rc->bonus)); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - int mod = xml_ivalue(node, "modifier", 0); - int speed = xml_ivalue(node, "speed", study_speed_base); - skill_t sk; - - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - sk = findskill((const char *)propValue); - if (sk != NOSKILL) { - rc->bonus[sk] = (char)mod; - if (speed) { - if (!rc->study_speed) - rc->study_speed = calloc(1, MAXSKILLS); - rc->study_speed[sk] = (char)speed; - } - } else { - log_error("unknown skill '%s' in race '%s'\n", (const char *)propValue, rc->_name); - } - xmlFree(propValue); - } - xmlXPathFreeObject(result); - - /* reading eressea/races/race/function */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - pf_generic fun; - - parse_function(node, &fun, &propValue); - if (fun == NULL) { - log_error("unknown function name '%s' for race %s\n", (const char *)propValue, rc->_name); - xmlFree(propValue); - continue; - } + propValue = xmlGetProp(node, BAD_CAST "name"); assert(propValue != NULL); - if (strcmp((const char *)propValue, "name") == 0) { - rc->generate_name = (const char *(*)(const struct unit *))fun; - } else if (strcmp((const char *)propValue, "describe") == 0) { - rc->describe = - (const char *(*)(const struct unit *, const struct locale *))fun; - } else if (strcmp((const char *)propValue, "age") == 0) { - rc->age = (void (*)(struct unit *))fun; - } else if (strcmp((const char *)propValue, "move") == 0) { - rc->move_allowed = - (bool(*)(const struct region *, const struct region *))fun; - } else if (strcmp((const char *)propValue, "itemdrop") == 0) { - rc->itemdrop = (struct item * (*)(const struct race *, int))fun; - } else if (strcmp((const char *)propValue, "initfamiliar") == 0) { - rc->init_familiar = (void (*)(struct unit *))fun; - } else { - log_error("unknown function type '%s' for race %s\n", (const char *)propValue, rc->_name); - } + rc = rc_get_or_create((const char *)propValue); xmlFree(propValue); - } - xmlXPathFreeObject(result); - /* reading eressea/races/race/familiar */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "familiar", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - race *frc; - - propValue = xmlGetProp(node, BAD_CAST "race"); - assert(propValue != NULL); - frc = rc_get_or_create((const char *)propValue); - if (xml_bvalue(node, "default", false)) { - rc->familiars[k] = rc->familiars[0]; - rc->familiars[0] = frc; - } else { - rc->familiars[k] = frc; - } - xmlFree(propValue); - } - xmlXPathFreeObject(result); - - /* reading eressea/races/race/precombatspell */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "precombatspell", xpath); - assert(rc->precombatspell == NULL - || !"precombatspell is already initialized"); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - rc->precombatspell = xml_spell(node, "spell"); - } - xmlXPathFreeObject(result); - - /* reading eressea/races/race/attack */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "attack", xpath); - attack = rc->attack; - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - while (attack->type != AT_NONE) - ++attack; - - propValue = xmlGetProp(node, BAD_CAST "damage"); - if (propValue != NULL) { - attack->data.dice = _strdup((const char *)propValue); + propValue = xmlGetProp(node, BAD_CAST "damage"); + assert(propValue != NULL); + rc->def_damage = _strdup((const char *)propValue); xmlFree(propValue); - } else { - attack->data.sp = xml_spell(node, "spell"); - if (attack->data.sp) { - attack->level = xml_ivalue(node, "level", 0); - if (attack->level <= 0) { - log_error("magical attack '%s' for race '%s' needs a level: %d\n", attack->data.sp->sname, rc->_name, attack->level); - } + + rc->magres = (float)xml_fvalue(node, "magres", 0.0); + rc->maxaura = (float)xml_fvalue(node, "maxaura", 0.0); + rc->regaura = (float)xml_fvalue(node, "regaura", 1.0); + rc->recruitcost = xml_ivalue(node, "recruitcost", 0); + rc->maintenance = xml_ivalue(node, "maintenance", 0); + rc->weight = xml_ivalue(node, "weight", PERSON_WEIGHT); + rc->capacity = xml_ivalue(node, "capacity", 540); + rc->speed = (float)xml_fvalue(node, "speed", 1.0F); + rc->hitpoints = xml_ivalue(node, "hp", 0); + rc->armor = (char)xml_ivalue(node, "ac", 0); + study_speed_base = xml_ivalue(node, "studyspeed", 0); + + rc->at_default = (char)xml_ivalue(node, "unarmedattack", -2); + rc->df_default = (char)xml_ivalue(node, "unarmeddefense", -2); + rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", 0); + rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", 0); + + if (!xml_bvalue(node, "playerrace", false)) + rc->flags |= RCF_NPC; + if (xml_bvalue(node, "scarepeasants", false)) + rc->flags |= RCF_SCAREPEASANTS; + if (!xml_bvalue(node, "cansteal", true)) + rc->flags |= RCF_NOSTEAL; + if (xml_bvalue(node, "cansail", true)) + rc->flags |= RCF_CANSAIL; + if (xml_bvalue(node, "cannotmove", false)) + rc->flags |= RCF_CANNOTMOVE; + if (xml_bvalue(node, "fly", false)) + rc->flags |= RCF_FLY; + if (xml_bvalue(node, "invisible", false)) + rc->flags |= RCF_INVISIBLE; + if (xml_bvalue(node, "coastal", false)) + rc->flags |= RCF_COASTAL; + if (xml_bvalue(node, "unarmedguard", false)) + rc->flags |= RCF_UNARMEDGUARD; + if (xml_bvalue(node, "swim", false)) + rc->flags |= RCF_SWIM; + if (xml_bvalue(node, "walk", false)) + rc->flags |= RCF_WALK; + if (!xml_bvalue(node, "canlearn", true)) + rc->flags |= RCF_NOLEARN; + if (!xml_bvalue(node, "canteach", true)) + rc->flags |= RCF_NOTEACH; + if (xml_bvalue(node, "horse", false)) + rc->flags |= RCF_HORSE; + if (xml_bvalue(node, "desert", false)) + rc->flags |= RCF_DESERT; + if (xml_bvalue(node, "absorbpeasants", false)) + rc->flags |= RCF_ABSORBPEASANTS; + if (xml_bvalue(node, "noheal", false)) + rc->flags |= RCF_NOHEAL; + if (xml_bvalue(node, "noweapons", false)) + rc->flags |= RCF_NOWEAPONS; + if (xml_bvalue(node, "shapeshift", false)) + rc->flags |= RCF_SHAPESHIFT; + if (xml_bvalue(node, "shapeshiftany", false)) + rc->flags |= RCF_SHAPESHIFTANY; + if (xml_bvalue(node, "illusionary", false)) + rc->flags |= RCF_ILLUSIONARY; + if (xml_bvalue(node, "undead", false)) + rc->flags |= RCF_UNDEAD; + if (xml_bvalue(node, "dragon", false)) + rc->flags |= RCF_DRAGON; + if (xml_bvalue(node, "shipspeed", false)) + rc->flags |= RCF_SHIPSPEED; + if (xml_bvalue(node, "stonegolem", false)) + rc->flags |= RCF_STONEGOLEM; + if (xml_bvalue(node, "irongolem", false)) + rc->flags |= RCF_IRONGOLEM; + + if (xml_bvalue(node, "giveitem", false)) + rc->ec_flags |= GIVEITEM; + if (xml_bvalue(node, "giveperson", false)) + rc->ec_flags |= GIVEPERSON; + if (xml_bvalue(node, "giveunit", false)) + rc->ec_flags |= GIVEUNIT; + if (xml_bvalue(node, "getitem", false)) + rc->ec_flags |= GETITEM; + if (xml_bvalue(node, "recruithorses", false)) + rc->ec_flags |= ECF_REC_HORSES; + if (xml_bvalue(node, "recruitethereal", false)) + rc->ec_flags |= ECF_REC_ETHEREAL; + if (xml_bvalue(node, "recruitunlimited", false)) + rc->ec_flags |= ECF_REC_UNLIMITED; + + if (xml_bvalue(node, "equipment", false)) + rc->battle_flags |= BF_EQUIPMENT; + if (xml_bvalue(node, "noblock", false)) + rc->battle_flags |= BF_NOBLOCK; + if (xml_bvalue(node, "invinciblenonmagic", false)) + rc->battle_flags |= BF_INV_NONMAGIC; + if (xml_bvalue(node, "resistbash", false)) + rc->battle_flags |= BF_RES_BASH; + if (xml_bvalue(node, "resistcut", false)) + rc->battle_flags |= BF_RES_CUT; + if (xml_bvalue(node, "resistpierce", false)) + rc->battle_flags |= BF_RES_PIERCE; + if (xml_bvalue(node, "canattack", true)) + rc->battle_flags |= BF_CANATTACK; + + for (child = node->children; child; child = child->next) { + if (strcmp((const char *)child->name, "ai") == 0) { + parse_ai(rc, child); + } + else if (strcmp((const char *)child->name, "param") == 0) { + parse_param(&rc->parameters, child); + } } - } - attack->type = xml_ivalue(node, "type", 0); - attack->flags = xml_ivalue(node, "flags", 0); + rc->recruit_multi = get_param_flt(rc->parameters, "recruit_multi", 1.0); + + /* reading eressea/races/race/skill */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "skill", xpath); + memset(rc->bonus, 0, sizeof(rc->bonus)); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + int mod = xml_ivalue(node, "modifier", 0); + int speed = xml_ivalue(node, "speed", study_speed_base); + skill_t sk; + + propValue = xmlGetProp(node, BAD_CAST "name"); + assert(propValue != NULL); + sk = findskill((const char *)propValue); + if (sk != NOSKILL) { + rc->bonus[sk] = (char)mod; + if (speed) { + if (!rc->study_speed) + rc->study_speed = calloc(1, MAXSKILLS); + rc->study_speed[sk] = (char)speed; + } + } + else { + log_error("unknown skill '%s' in race '%s'\n", (const char *)propValue, rc->_name); + } + xmlFree(propValue); + } + xmlXPathFreeObject(result); + + /* reading eressea/races/race/function */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "function", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + pf_generic fun; + + parse_function(node, &fun, &propValue); + if (fun == NULL) { + log_error("unknown function name '%s' for race %s\n", (const char *)propValue, rc->_name); + xmlFree(propValue); + continue; + } + assert(propValue != NULL); + if (strcmp((const char *)propValue, "name") == 0) { + rc->generate_name = (const char *(*)(const struct unit *))fun; + } + else if (strcmp((const char *)propValue, "describe") == 0) { + rc->describe = + (const char *(*)(const struct unit *, const struct locale *))fun; + } + else if (strcmp((const char *)propValue, "age") == 0) { + rc->age = (void(*)(struct unit *))fun; + } + else if (strcmp((const char *)propValue, "move") == 0) { + rc->move_allowed = + (bool(*)(const struct region *, const struct region *))fun; + } + else if (strcmp((const char *)propValue, "itemdrop") == 0) { + rc->itemdrop = (struct item * (*)(const struct race *, int))fun; + } + else if (strcmp((const char *)propValue, "initfamiliar") == 0) { + rc->init_familiar = (void(*)(struct unit *))fun; + } + else { + log_error("unknown function type '%s' for race %s\n", (const char *)propValue, rc->_name); + } + xmlFree(propValue); + } + xmlXPathFreeObject(result); + + /* reading eressea/races/race/familiar */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "familiar", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + race *frc; + + propValue = xmlGetProp(node, BAD_CAST "race"); + assert(propValue != NULL); + frc = rc_get_or_create((const char *)propValue); + if (xml_bvalue(node, "default", false)) { + rc->familiars[k] = rc->familiars[0]; + rc->familiars[0] = frc; + } + else { + rc->familiars[k] = frc; + } + xmlFree(propValue); + } + xmlXPathFreeObject(result); + + /* reading eressea/races/race/precombatspell */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "precombatspell", xpath); + assert(rc->precombatspell == NULL + || !"precombatspell is already initialized"); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + rc->precombatspell = xml_spell(node, "spell"); + } + xmlXPathFreeObject(result); + + /* reading eressea/races/race/attack */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "attack", xpath); + attack = rc->attack; + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + while (attack->type != AT_NONE) + ++attack; + + propValue = xmlGetProp(node, BAD_CAST "damage"); + if (propValue != NULL) { + attack->data.dice = _strdup((const char *)propValue); + xmlFree(propValue); + } + else { + attack->data.sp = xml_spell(node, "spell"); + if (attack->data.sp) { + attack->level = xml_ivalue(node, "level", 0); + if (attack->level <= 0) { + log_error("magical attack '%s' for race '%s' needs a level: %d\n", attack->data.sp->sname, rc->_name, attack->level); + } + } + } + attack->type = xml_ivalue(node, "type", 0); + attack->flags = xml_ivalue(node, "flags", 0); + } + xmlXPathFreeObject(result); } - xmlXPathFreeObject(result); - } - xmlXPathFreeObject(races); + xmlXPathFreeObject(races); - xmlXPathFreeContext(xpath); + xmlXPathFreeContext(xpath); - return 0; + return 0; } static int parse_terrains(xmlDocPtr doc) { - xmlXPathContextPtr xpath; - xmlXPathObjectPtr terrains; - xmlNodeSetPtr nodes; - int i; + xmlXPathContextPtr xpath; + xmlXPathObjectPtr terrains; + xmlNodeSetPtr nodes; + int i; - xpath = xmlXPathNewContext(doc); + xpath = xmlXPathNewContext(doc); - /* reading eressea/terrains/terrain */ - terrains = - xmlXPathEvalExpression(BAD_CAST "/eressea/terrains/terrain", xpath); - nodes = terrains->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - terrain_type *terrain; - xmlChar *propValue; - xmlXPathObjectPtr xpathChildren; - xmlNodeSetPtr children; + /* reading eressea/terrains/terrain */ + terrains = + xmlXPathEvalExpression(BAD_CAST "/eressea/terrains/terrain", xpath); + nodes = terrains->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + terrain_type *terrain; + xmlChar *propValue; + xmlXPathObjectPtr xpathChildren; + xmlNodeSetPtr children; - propValue = xmlGetProp(node, BAD_CAST "name"); - assert(propValue != NULL); - terrain = get_or_create_terrain((const char *)propValue); - xmlFree(propValue); - - terrain->max_road = (short)xml_ivalue(node, "road", 0); - assert(terrain->max_road >= 0); - terrain->size = xml_ivalue(node, "size", 0); - - if (xml_bvalue(node, "forbidden", false)) - terrain->flags |= FORBIDDEN_REGION; - else { - if (xml_bvalue(node, "fly", true)) - terrain->flags |= FLY_INTO; - if (xml_bvalue(node, "sail", true)) - terrain->flags |= SAIL_INTO; - if (xml_bvalue(node, "walk", true)) - terrain->flags |= WALK_INTO; - if (xml_bvalue(node, "swim", false)) - terrain->flags |= SWIM_INTO; - if (xml_bvalue(node, "cavalry", false)) - terrain->flags |= CAVALRY_REGION; - } - if (xml_bvalue(node, "sea", false)) - terrain->flags |= SEA_REGION; - if (xml_bvalue(node, "arctic", false)) - terrain->flags |= ARCTIC_REGION; - if (xml_bvalue(node, "land", true)) - terrain->flags |= LAND_REGION; - if (xml_bvalue(node, "forest", false)) - terrain->flags |= FOREST_REGION; - - terrain->distribution = (short)xml_ivalue(node, "seed", 0); - - xpath->node = node; - xpathChildren = xmlXPathEvalExpression(BAD_CAST "herb", xpath); - children = xpathChildren->nodesetval; - if (children->nodeNr > 0) { - int k; - - terrain->herbs = malloc((children->nodeNr + 1) * sizeof(item_type *)); - terrain->herbs[children->nodeNr] = NULL; - for (k = 0; k != children->nodeNr; ++k) { - xmlNodePtr nodeHerb = children->nodeTab[k]; - const struct resource_type *rtype; - - propValue = xmlGetProp(nodeHerb, BAD_CAST "name"); + propValue = xmlGetProp(node, BAD_CAST "name"); assert(propValue != NULL); - rtype = rt_find((const char *)propValue); - assert(rtype != NULL && rtype->itype != NULL - && fval(rtype->itype, ITF_HERB)); - terrain->herbs[k] = rtype->itype; + terrain = get_or_create_terrain((const char *)propValue); xmlFree(propValue); - } + + terrain->max_road = (short)xml_ivalue(node, "road", 0); + assert(terrain->max_road >= 0); + terrain->size = xml_ivalue(node, "size", 0); + + if (xml_bvalue(node, "forbidden", false)) + terrain->flags |= FORBIDDEN_REGION; + else { + if (xml_bvalue(node, "fly", true)) + terrain->flags |= FLY_INTO; + if (xml_bvalue(node, "sail", true)) + terrain->flags |= SAIL_INTO; + if (xml_bvalue(node, "walk", true)) + terrain->flags |= WALK_INTO; + if (xml_bvalue(node, "swim", false)) + terrain->flags |= SWIM_INTO; + if (xml_bvalue(node, "cavalry", false)) + terrain->flags |= CAVALRY_REGION; + } + if (xml_bvalue(node, "sea", false)) + terrain->flags |= SEA_REGION; + if (xml_bvalue(node, "arctic", false)) + terrain->flags |= ARCTIC_REGION; + if (xml_bvalue(node, "land", true)) + terrain->flags |= LAND_REGION; + if (xml_bvalue(node, "forest", false)) + terrain->flags |= FOREST_REGION; + + terrain->distribution = (short)xml_ivalue(node, "seed", 0); + + xpath->node = node; + xpathChildren = xmlXPathEvalExpression(BAD_CAST "herb", xpath); + children = xpathChildren->nodesetval; + if (children->nodeNr > 0) { + int k; + + terrain->herbs = malloc((children->nodeNr + 1) * sizeof(item_type *)); + terrain->herbs[children->nodeNr] = NULL; + for (k = 0; k != children->nodeNr; ++k) { + xmlNodePtr nodeHerb = children->nodeTab[k]; + const struct resource_type *rtype; + + propValue = xmlGetProp(nodeHerb, BAD_CAST "name"); + assert(propValue != NULL); + rtype = rt_find((const char *)propValue); + assert(rtype != NULL && rtype->itype != NULL + && fval(rtype->itype, ITF_HERB)); + terrain->herbs[k] = rtype->itype; + xmlFree(propValue); + } + } + xmlXPathFreeObject(xpathChildren); + + xpath->node = node; + xpathChildren = xmlXPathEvalExpression(BAD_CAST "resource", xpath); + children = xpathChildren->nodesetval; + if (children->nodeNr > 0) { + int k; + + terrain->production = + malloc((children->nodeNr + 1) * sizeof(terrain_production)); + terrain->production[children->nodeNr].type = NULL; + for (k = 0; k != children->nodeNr; ++k) { + xmlNodePtr nodeProd = children->nodeTab[k]; + + propValue = xmlGetProp(nodeProd, BAD_CAST "name"); + assert(propValue != NULL); + terrain->production[k].type = rt_find((const char *)propValue); + assert(terrain->production[k].type); + xmlFree(propValue); + + propValue = xmlGetProp(nodeProd, BAD_CAST "level"); + assert(propValue); + terrain->production[k].startlevel = _strdup((const char *)propValue); + xmlFree(propValue); + + propValue = xmlGetProp(nodeProd, BAD_CAST "base"); + assert(propValue); + terrain->production[k].base = _strdup((const char *)propValue); + xmlFree(propValue); + + propValue = xmlGetProp(nodeProd, BAD_CAST "div"); + assert(propValue); + terrain->production[k].divisor = _strdup((const char *)propValue); + xmlFree(propValue); + + terrain->production[k].chance = + (float)xml_fvalue(nodeProd, "chance", 1.0); + } + } + xmlXPathFreeObject(xpathChildren); + } - xmlXPathFreeObject(xpathChildren); + xmlXPathFreeObject(terrains); - xpath->node = node; - xpathChildren = xmlXPathEvalExpression(BAD_CAST "resource", xpath); - children = xpathChildren->nodesetval; - if (children->nodeNr > 0) { - int k; + xmlXPathFreeContext(xpath); - terrain->production = - malloc((children->nodeNr + 1) * sizeof(terrain_production)); - terrain->production[children->nodeNr].type = NULL; - for (k = 0; k != children->nodeNr; ++k) { - xmlNodePtr nodeProd = children->nodeTab[k]; - - propValue = xmlGetProp(nodeProd, BAD_CAST "name"); - assert(propValue != NULL); - terrain->production[k].type = rt_find((const char *)propValue); - assert(terrain->production[k].type); - xmlFree(propValue); - - propValue = xmlGetProp(nodeProd, BAD_CAST "level"); - assert(propValue); - terrain->production[k].startlevel = _strdup((const char *)propValue); - xmlFree(propValue); - - propValue = xmlGetProp(nodeProd, BAD_CAST "base"); - assert(propValue); - terrain->production[k].base = _strdup((const char *)propValue); - xmlFree(propValue); - - propValue = xmlGetProp(nodeProd, BAD_CAST "div"); - assert(propValue); - terrain->production[k].divisor = _strdup((const char *)propValue); - xmlFree(propValue); - - terrain->production[k].chance = - (float)xml_fvalue(nodeProd, "chance", 1.0); - } - } - xmlXPathFreeObject(xpathChildren); - - } - xmlXPathFreeObject(terrains); - - xmlXPathFreeContext(xpath); - - init_terrains(); - return 0; + init_terrains(); + return 0; } static int parse_messages(xmlDocPtr doc) { - xmlXPathContextPtr xpath; - xmlXPathObjectPtr messages; - xmlNodeSetPtr nodes; - int i; + xmlXPathContextPtr xpath; + xmlXPathObjectPtr messages; + xmlNodeSetPtr nodes; + int i; - xpath = xmlXPathNewContext(doc); + xpath = xmlXPathNewContext(doc); - /* reading eressea/messages/message */ - messages = - xmlXPathEvalExpression(BAD_CAST "/eressea/messages/message", xpath); - nodes = messages->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - const char *default_section = "events"; - xmlChar *propSection; - xmlChar *propValue; - xmlXPathObjectPtr result; - int k; - char **argv = NULL; - const message_type *mtype; + /* reading eressea/messages/message */ + messages = + xmlXPathEvalExpression(BAD_CAST "/eressea/messages/message", xpath); + nodes = messages->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + const char *default_section = "events"; + xmlChar *propSection; + xmlChar *propValue; + xmlXPathObjectPtr result; + int k; + char **argv = NULL; + const message_type *mtype; - /* arguments */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "type/arg", xpath); - if (result->nodesetval && result->nodesetval->nodeNr > 0) { - argv = malloc(sizeof(char *) * (result->nodesetval->nodeNr + 1)); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - char zBuffer[128]; - xmlChar *propName, *propType; + /* arguments */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "type/arg", xpath); + if (result->nodesetval && result->nodesetval->nodeNr > 0) { + argv = malloc(sizeof(char *) * (result->nodesetval->nodeNr + 1)); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + char zBuffer[128]; + xmlChar *propName, *propType; - propName = xmlGetProp(node, BAD_CAST "name"); - propType = xmlGetProp(node, BAD_CAST "type"); - sprintf(zBuffer, "%s:%s", (const char *)propName, - (const char *)propType); - xmlFree(propName); - xmlFree(propType); - argv[k] = _strdup(zBuffer); - } - argv[result->nodesetval->nodeNr] = NULL; - } - xmlXPathFreeObject(result); + propName = xmlGetProp(node, BAD_CAST "name"); + propType = xmlGetProp(node, BAD_CAST "type"); + sprintf(zBuffer, "%s:%s", (const char *)propName, + (const char *)propType); + xmlFree(propName); + xmlFree(propType); + argv[k] = _strdup(zBuffer); + } + argv[result->nodesetval->nodeNr] = NULL; + } + xmlXPathFreeObject(result); - /* add the messagetype */ - propValue = xmlGetProp(node, BAD_CAST "name"); - mtype = mt_find((const char *)propValue); - if (mtype == NULL) { - mtype = mt_register(mt_new((const char *)propValue, (const char **)argv)); - } else { - assert(argv != NULL || !"cannot redefine arguments of message now"); - } - xmlFree(propValue); + /* add the messagetype */ + propValue = xmlGetProp(node, BAD_CAST "name"); + mtype = mt_find((const char *)propValue); + if (mtype == NULL) { + mtype = mt_register(mt_new((const char *)propValue, (const char **)argv)); + } + else { + assert(argv != NULL || !"cannot redefine arguments of message now"); + } + xmlFree(propValue); - /* register the type for the CR */ - crt_register(mtype); + /* register the type for the CR */ + crt_register(mtype); - /* let's clean up the mess */ - if (argv != NULL) { - for (k = 0; argv[k] != NULL; ++k) - free(argv[k]); - free(argv); + /* let's clean up the mess */ + if (argv != NULL) { + for (k = 0; argv[k] != NULL; ++k) + free(argv[k]); + free(argv); + } + + propSection = xmlGetProp(node, BAD_CAST "section"); + if (propSection == NULL) + propSection = BAD_CAST default_section; + + /* strings */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "text", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + struct locale *lang; + xmlChar *propText; + + xml_readtext(node, &lang, &propText); + if (lang) { + xml_cleanup_string(propText); + nrt_register(mtype, lang, (const char *)propText, 0, + (const char *)propSection); + } + xmlFree(propText); + + } + xmlXPathFreeObject(result); + + if (propSection != BAD_CAST default_section) + xmlFree(propSection); } - propSection = xmlGetProp(node, BAD_CAST "section"); - if (propSection == NULL) - propSection = BAD_CAST default_section; + xmlXPathFreeObject(messages); - /* strings */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "text", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - struct locale *lang; - xmlChar *propText; - - xml_readtext(node, &lang, &propText); - if (lang) { - xml_cleanup_string(propText); - nrt_register(mtype, lang, (const char *)propText, 0, - (const char *)propSection); - } - xmlFree(propText); - - } - xmlXPathFreeObject(result); - - if (propSection != BAD_CAST default_section) - xmlFree(propSection); - } - - xmlXPathFreeObject(messages); - - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeContext(xpath); + return 0; } static void xml_readstrings(xmlXPathContextPtr xpath, xmlNodePtr * nodeTab, int nodeNr, - bool names) +bool names) { - int i; + int i; - for (i = 0; i != nodeNr; ++i) { - xmlNodePtr stringNode = nodeTab[i]; - xmlChar *propName = xmlGetProp(stringNode, BAD_CAST "name"); - xmlChar *propNamespace = NULL; - xmlXPathObjectPtr result; - int k; - char zName[128]; + for (i = 0; i != nodeNr; ++i) { + xmlNodePtr stringNode = nodeTab[i]; + xmlChar *propName = xmlGetProp(stringNode, BAD_CAST "name"); + xmlChar *propNamespace = NULL; + xmlXPathObjectPtr result; + int k; + char zName[128]; - assert(propName != NULL); - if (names) - propNamespace = xmlGetProp(stringNode->parent, BAD_CAST "name"); - mkname_buf((const char *)propNamespace, (const char *)propName, zName); - if (propNamespace != NULL) - xmlFree(propNamespace); - xmlFree(propName); + assert(propName != NULL); + if (names) + propNamespace = xmlGetProp(stringNode->parent, BAD_CAST "name"); + mkname_buf((const char *)propNamespace, (const char *)propName, zName); + if (propNamespace != NULL) + xmlFree(propNamespace); + xmlFree(propName); - /* strings */ - xpath->node = stringNode; - result = xmlXPathEvalExpression(BAD_CAST "text", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr textNode = result->nodesetval->nodeTab[k]; - struct locale *lang; - xmlChar *propText; + /* strings */ + xpath->node = stringNode; + result = xmlXPathEvalExpression(BAD_CAST "text", xpath); + for (k = 0; k != result->nodesetval->nodeNr; ++k) { + xmlNodePtr textNode = result->nodesetval->nodeTab[k]; + struct locale *lang; + xmlChar *propText; - xml_readtext(textNode, &lang, &propText); - if (propText != NULL) { - assert(strcmp(zName, - (const char *)xml_cleanup_string(BAD_CAST zName)) == 0); - if (lang) { - xml_cleanup_string(propText); - locale_setstring(lang, zName, (const char *)propText); + xml_readtext(textNode, &lang, &propText); + if (propText != NULL) { + assert(strcmp(zName, + (const char *)xml_cleanup_string(BAD_CAST zName)) == 0); + if (lang) { + xml_cleanup_string(propText); + locale_setstring(lang, zName, (const char *)propText); + } + xmlFree(propText); + } + else { + log_warning("string %s has no text in locale %s\n", zName, locale_name(lang)); + } } - xmlFree(propText); - } else { - log_warning("string %s has no text in locale %s\n", zName, locale_name(lang)); - } + xmlXPathFreeObject(result); } - xmlXPathFreeObject(result); - } } static int parse_strings(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr strings; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr strings; - /* reading eressea/strings/string */ - strings = xmlXPathEvalExpression(BAD_CAST "/eressea/strings/string", xpath); - xml_readstrings(xpath, strings->nodesetval->nodeTab, - strings->nodesetval->nodeNr, false); - xmlXPathFreeObject(strings); + /* reading eressea/strings/string */ + strings = xmlXPathEvalExpression(BAD_CAST "/eressea/strings/string", xpath); + xml_readstrings(xpath, strings->nodesetval->nodeTab, + strings->nodesetval->nodeNr, false); + xmlXPathFreeObject(strings); - strings = - xmlXPathEvalExpression(BAD_CAST "/eressea/strings/namespace/string", xpath); - xml_readstrings(xpath, strings->nodesetval->nodeTab, - strings->nodesetval->nodeNr, true); - xmlXPathFreeObject(strings); + strings = + xmlXPathEvalExpression(BAD_CAST "/eressea/strings/namespace/string", xpath); + xml_readstrings(xpath, strings->nodesetval->nodeTab, + strings->nodesetval->nodeNr, true); + xmlXPathFreeObject(strings); - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeContext(xpath); + return 0; } static void xml_readprefixes(xmlXPathContextPtr xpath, xmlNodePtr * nodeTab, int nodeNr, - bool names) +bool names) { - int i; + int i; - for (i = 0; i != nodeNr; ++i) { - xmlNodePtr node = nodeTab[i]; - xmlChar *propText = xmlNodeListGetString(node->doc, node->children, 1); + for (i = 0; i != nodeNr; ++i) { + xmlNodePtr node = nodeTab[i]; + xmlChar *propText = xmlNodeListGetString(node->doc, node->children, 1); - if (propText != NULL) { - add_raceprefix((const char *)propText); - xmlFree(propText); + if (propText != NULL) { + add_raceprefix((const char *)propText); + xmlFree(propText); + } } - } } static int parse_prefixes(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr strings; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr strings; - /* reading eressea/strings/string */ - strings = xmlXPathEvalExpression(BAD_CAST "/eressea/prefixes/prefix", xpath); - xml_readprefixes(xpath, strings->nodesetval->nodeTab, - strings->nodesetval->nodeNr, false); - xmlXPathFreeObject(strings); + /* reading eressea/strings/string */ + strings = xmlXPathEvalExpression(BAD_CAST "/eressea/prefixes/prefix", xpath); + xml_readprefixes(xpath, strings->nodesetval->nodeTab, + strings->nodesetval->nodeNr, false); + xmlXPathFreeObject(strings); - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeContext(xpath); + return 0; } static int parse_main(xmlDocPtr doc) { - xmlXPathContextPtr xpath = xmlXPathNewContext(doc); - xmlXPathObjectPtr result = - xmlXPathEvalExpression(BAD_CAST "/eressea/game", xpath); - xmlNodeSetPtr nodes = result->nodesetval; - int i; + xmlXPathContextPtr xpath = xmlXPathNewContext(doc); + xmlXPathObjectPtr result = + xmlXPathEvalExpression(BAD_CAST "/eressea/game", xpath); + xmlNodeSetPtr nodes = result->nodesetval; + int i; - xmlChar *propValue; - if (nodes->nodeNr > 0) { - xmlNodePtr node = nodes->nodeTab[0]; + xmlChar *propValue; + if (nodes->nodeNr > 0) { + xmlNodePtr node = nodes->nodeTab[0]; - global.producexpchance = - (float)xml_fvalue(node, "learningbydoing", 1.0 / 3); + global.producexpchance = + (float)xml_fvalue(node, "learningbydoing", 1.0 / 3); - propValue = xmlGetProp(node, BAD_CAST "name"); - if (propValue != NULL) { - global.gamename = _strdup((const char *)propValue); - xmlFree(propValue); - } - - xmlXPathFreeObject(result); - - /* reading eressea/game/param */ - xpath->node = node; - result = xmlXPathEvalExpression(BAD_CAST "param", xpath); - nodes = result->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - parse_param(&global.parameters, node); - } - - xmlXPathFreeObject(result); - - /* reading eressea/game/order */ - result = xmlXPathEvalExpression(BAD_CAST "order", xpath); - nodes = result->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); - bool disable = xml_bvalue(node, "disable", false); - - if (disable) { - int k; - for (k = 0; k != MAXKEYWORDS; ++k) { - if (strcmp(keywords[k], (const char *)propName) == 0) { - enable_keyword(k, false); - break; - } + propValue = xmlGetProp(node, BAD_CAST "name"); + if (propValue != NULL) { + global.gamename = _strdup((const char *)propValue); + xmlFree(propValue); } - if (k == MAXKEYWORDS) { - log_error("trying to disable unknown command %s\n", (const char *)propName); - } - } - xmlFree(propName); - } + xmlXPathFreeObject(result); + + /* reading eressea/game/param */ + xpath->node = node; + result = xmlXPathEvalExpression(BAD_CAST "param", xpath); + nodes = result->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + parse_param(&global.parameters, node); + } + + xmlXPathFreeObject(result); + + /* reading eressea/game/order */ + result = xmlXPathEvalExpression(BAD_CAST "order", xpath); + nodes = result->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); + bool disable = xml_bvalue(node, "disable", false); + + if (disable) { + int k; + for (k = 0; k != MAXKEYWORDS; ++k) { + if (strcmp(keywords[k], (const char *)propName) == 0) { + enable_keyword(k, false); + break; + } + } + if (k == MAXKEYWORDS) { + log_error("trying to disable unknown command %s\n", (const char *)propName); + } + } + xmlFree(propName); + } + + xmlXPathFreeObject(result); + + /* reading eressea/game/skill */ + result = xmlXPathEvalExpression(BAD_CAST "skill", xpath); + nodes = result->nodesetval; + for (i = 0; i != nodes->nodeNr; ++i) { + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); + skill_t sk = findskill((const char *)propName); + if (sk != NOSKILL) { + bool enable = xml_bvalue(node, "enable", true); + enable_skill(sk, enable); + } + xmlFree(propName); + } + } xmlXPathFreeObject(result); - /* reading eressea/game/skill */ - result = xmlXPathEvalExpression(BAD_CAST "skill", xpath); - nodes = result->nodesetval; - for (i = 0; i != nodes->nodeNr; ++i) { - xmlNodePtr node = nodes->nodeTab[i]; - xmlChar *propName = xmlGetProp(node, BAD_CAST "name"); - skill_t sk = findskill((const char *)propName); - if (sk!=NOSKILL) { - bool enable = xml_bvalue(node, "enable", true); - enable_skill(sk, enable); - } - xmlFree(propName); - } - } - xmlXPathFreeObject(result); - - xmlXPathFreeContext(xpath); - return 0; + xmlXPathFreeContext(xpath); + return 0; } void register_xmlreader(void) { - xml_register_callback(parse_main); + xml_register_callback(parse_main); - xml_register_callback(parse_strings); - xml_register_callback(parse_prefixes); - xml_register_callback(parse_messages); - xml_register_callback(parse_resources); - xml_register_callback(parse_rules); + xml_register_callback(parse_strings); + xml_register_callback(parse_prefixes); + xml_register_callback(parse_messages); + xml_register_callback(parse_resources); + xml_register_callback(parse_rules); - xml_register_callback(parse_terrains); /* requires resources */ - xml_register_callback(parse_buildings); /* requires resources */ - xml_register_callback(parse_ships); /* requires terrains */ - xml_register_callback(parse_spells); /* requires resources */ - xml_register_callback(parse_spellbooks); /* requires spells */ - xml_register_callback(parse_equipment); /* requires spells */ - xml_register_callback(parse_races); /* requires spells */ - xml_register_callback(parse_calendar); + xml_register_callback(parse_terrains); /* requires resources */ + xml_register_callback(parse_buildings); /* requires resources */ + xml_register_callback(parse_ships); /* requires terrains */ + xml_register_callback(parse_spells); /* requires resources */ + xml_register_callback(parse_spellbooks); /* requires spells */ + xml_register_callback(parse_equipment); /* requires spells */ + xml_register_callback(parse_races); /* requires spells */ + xml_register_callback(parse_calendar); } #endif diff --git a/src/kernel/xmlreader.h b/src/kernel/xmlreader.h index 304046512..acf18f12a 100644 --- a/src/kernel/xmlreader.h +++ b/src/kernel/xmlreader.h @@ -15,10 +15,10 @@ without prior permission by the authors of Eressea. #ifdef __cplusplus extern "C" { #endif - extern void register_xmlreader(void); + extern void register_xmlreader(void); - /* game-specific callbacks */ - extern void (*set_spelldata_cb) (struct spell * sp); + /* game-specific callbacks */ + extern void(*set_spelldata_cb) (struct spell * sp); #ifdef __cplusplus } #endif diff --git a/src/move.test.c b/src/move.test.c index cc2571f7b..dbb82e571 100644 --- a/src/move.test.c +++ b/src/move.test.c @@ -28,7 +28,7 @@ static void test_ship_not_allowed_in_coast(CuTest * tc) ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO | SAIL_INTO); otype = test_create_terrain("ocean", SEA_REGION | SAIL_INTO); stype = test_create_shiptype("derp"); - stype->coasts = (const struct terrain_type **)calloc(2, sizeof(const struct terrain_type *)); + stype->coasts = (struct terrain_type **)calloc(2, sizeof(struct terrain_type *)); r1 = test_create_region(0, 0, ttype); r2 = test_create_region(1, 0, otype); diff --git a/src/test_eressea.c b/src/test_eressea.c index caa54b067..d33f75fe8 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -86,6 +86,7 @@ int RunAllTests(void) log_flags = flags; fail_count = suite->failCount; CuSuiteDelete(suite); + kernel_done(); return fail_count; } From 2fbb04140c4ac31baac4dc0b67cb9291383ab63a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 01:17:49 +0100 Subject: [PATCH 11/21] at_deprecated was causing a small memory leak. --- src/kernel/config.c | 1 + src/util/attrib.c | 4 ++++ src/util/attrib.h | 2 ++ 3 files changed, 7 insertions(+) diff --git a/src/kernel/config.c b/src/kernel/config.c index 1de8c8c5f..0e3d9802e 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1144,6 +1144,7 @@ void kernel_done(void) * calling it is optional, e.g. a release server will most likely not do it. */ translation_done(); + free_attribs(); } attrib_type at_germs = { diff --git a/src/util/attrib.c b/src/util/attrib.c index d344cdc07..5cf9957c6 100644 --- a/src/util/attrib.c +++ b/src/util/attrib.c @@ -355,3 +355,7 @@ void a_write(struct storage *store, const attrib * attribs, const void *owner) } WRITE_TOK(store, "end"); } + +void free_attribs(void) { + cb_clear(&cb_deprecated); +} diff --git a/src/util/attrib.h b/src/util/attrib.h index 7dc3e1a3d..4c71f36f6 100644 --- a/src/util/attrib.h +++ b/src/util/attrib.h @@ -79,6 +79,8 @@ extern "C" { extern void a_write(struct storage *store, const attrib * attribs, const void *owner); + void free_attribs(void); + #define DEFAULT_AGE NULL #define DEFAULT_INIT NULL #define DEFAULT_FINALIZE NULL From e9c3a00f7dd2dd50c7a86de889ef3552023153c3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 01:29:10 +0100 Subject: [PATCH 12/21] it sucks that get_translations sometimes returns tokens, and sometimes critbit_trees. How is anyone supposed to free that correctly? --- src/magic.test.c | 10 ++++++++-- src/util/language.c | 1 + src/util/umlaut.c | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/magic.test.c b/src/magic.test.c index 300f8cd88..35202cd69 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -39,6 +39,7 @@ void test_updatespells(CuTest * tc) CuAssertPtrNotNull(tc, f->spellbook); CuAssertIntEquals(tc, 1, ql_length(f->spellbook->spells)); CuAssertPtrNotNull(tc, spellbook_get(f->spellbook, sp)); + test_cleanup(); } void test_spellbooks(CuTest * tc) @@ -63,12 +64,11 @@ void test_spellbooks(CuTest * tc) entry = spellbook_get(herp, sp); CuAssertPtrNotNull(tc, entry); CuAssertPtrEquals(tc, sp, entry->sp); - /* CuAssertPtrEquals(tc, 0, spellbook_get(derp, sname)); */ test_cleanup(); herp = get_spellbook("herp"); CuAssertPtrNotNull(tc, herp); - /* CuAssertPtrEquals(tc, 0, spellbook_get(herp, sname)); */ + test_cleanup(); } static spell * test_magic_create_spell(void) @@ -215,6 +215,7 @@ void test_getspell_faction(CuTest * tc) f->spellbook = create_spellbook(0); spellbook_add(f->spellbook, sp, 1); CuAssertPtrEquals(tc, sp, unit_getspell(u, "Herp-a-derp", lang)); + test_cleanup(); } void test_getspell_school(CuTest * tc) @@ -246,6 +247,7 @@ void test_getspell_school(CuTest * tc) CuAssertPtrNotNull(tc, book); spellbook_add(book, sp, 1); CuAssertPtrEquals(tc, sp, unit_getspell(u, "Herp-a-derp", lang)); + test_cleanup(); } void test_set_pre_combatspell(CuTest * tc) @@ -278,6 +280,7 @@ void test_set_pre_combatspell(CuTest * tc) unset_combatspell(u, sp); CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index)); CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); + test_cleanup(); } void test_set_main_combatspell(CuTest * tc) @@ -310,6 +313,7 @@ void test_set_main_combatspell(CuTest * tc) unset_combatspell(u, sp); CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index)); CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); + test_cleanup(); } void test_set_post_combatspell(CuTest * tc) @@ -342,6 +346,7 @@ void test_set_post_combatspell(CuTest * tc) unset_combatspell(u, sp); CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index)); CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); + test_cleanup(); } void test_hasspell(CuTest * tc) @@ -371,6 +376,7 @@ void test_hasspell(CuTest * tc) set_level(u, SK_MAGIC, 1); CuAssertTrue(tc, !u_hasspell(u, sp)); + test_cleanup(); } CuSuite *get_magic_suite(void) diff --git a/src/util/language.c b/src/util/language.c index b55afd5eb..58ad78555 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -242,6 +242,7 @@ void add_translation(struct critbit_tree **cbp, const char *key, int i) { if (str) { size_t len = strlen(str); if (!cb) { + // TODO: this will leak, because we do not know how to clean it up */ *cbp = cb = (struct critbit_tree *)calloc(1, sizeof(struct critbit_tree *)); } len = cb_new_kv(str, len, &i, sizeof(int), buffer); diff --git a/src/util/umlaut.c b/src/util/umlaut.c index 61dc06ba1..6917960cc 100644 --- a/src/util/umlaut.c +++ b/src/util/umlaut.c @@ -212,6 +212,7 @@ void freetokens(void * root) for (i = 0; node && i != NODEHASHSIZE; ++i) { if (node->next[i]) { freetokens(node->next[i]->node); + free(node->next[i]); } } free(node); From 6abe180f68376cfa490aa0389dc146e68cc60fd6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 01:38:49 +0100 Subject: [PATCH 13/21] free spellbooks correctly. --- src/magic.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/magic.c b/src/magic.c index 4afd3cf61..073f1e405 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2979,7 +2979,16 @@ spellbook * get_spellbook(const char * name) return result; } +int free_spellbook_cb(const void *match, const void *key, size_t keylen, void *data) { + spellbook *sb; + cb_get_kv(match, &sb, sizeof(sb)); + spellbook_clear(sb); + free(sb); + return 0; +} + void free_spellbooks(void) { + cb_foreach(&cb_spellbooks, "", 0, free_spellbook_cb, NULL); cb_clear(&cb_spellbooks); } From 3b5653b3533510735402467ac9e76125c0412acd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 01:40:46 +0100 Subject: [PATCH 14/21] all good tests cleanup after themselves. --- src/magic.test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/magic.test.c b/src/magic.test.c index 35202cd69..a78a16753 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -120,6 +120,7 @@ void test_pay_spell(CuTest * tc) CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_SILVER))); CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_AURA))); CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_HORSE))); + test_cleanup(); } void test_pay_spell_failure(CuTest * tc) @@ -157,6 +158,7 @@ void test_pay_spell_failure(CuTest * tc) CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 3, 1)); CuAssertIntEquals(tc, 0, change_resource(u, get_resourcetype(R_SILVER), -1)); CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 2, 1)); + test_cleanup(); } void test_getspell_unit(CuTest * tc) @@ -185,6 +187,7 @@ void test_getspell_unit(CuTest * tc) unit_add_spell(u, 0, sp, 1); CuAssertPtrNotNull(tc, unit_getspell(u, "Herp-a-derp", lang)); + test_cleanup(); } void test_getspell_faction(CuTest * tc) From e8ad5424307862b4a01f1ea723a66d62ebe91b1e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 01:50:54 +0100 Subject: [PATCH 15/21] more thorough cleanup of tokens. --- src/util/umlaut.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/util/umlaut.c b/src/util/umlaut.c index 6917960cc..c7072987c 100644 --- a/src/util/umlaut.c +++ b/src/util/umlaut.c @@ -211,8 +211,13 @@ void freetokens(void * root) int i; for (i = 0; node && i != NODEHASHSIZE; ++i) { if (node->next[i]) { + tref ** refs = &node->next[i]; freetokens(node->next[i]->node); - free(node->next[i]); + while (*refs) { + tref * ref = *refs; + *refs = ref->nexthash; + free(ref); + } } } free(node); From f524f23cd42edf8dc37b843d20a8b7b9c092f57c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 13:17:54 +0100 Subject: [PATCH 16/21] superfluous semicolons and other small stuff. missing strings are an error, not a warning. --- scripts/tests/init.lua | 1 - scripts/tests/pool.lua | 2 +- src/kernel/jsonconf.c | 4 ++-- src/util/language.c | 15 +++++++-------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/tests/init.lua b/scripts/tests/init.lua index 258c8b082..deb3e1a89 100644 --- a/scripts/tests/init.lua +++ b/scripts/tests/init.lua @@ -7,4 +7,3 @@ require 'tests.locale' require 'tests.regions' require 'tests.study' require 'tests.movement' - diff --git a/scripts/tests/pool.lua b/scripts/tests/pool.lua index 311d3171d..2ac9c87f2 100644 --- a/scripts/tests/pool.lua +++ b/scripts/tests/pool.lua @@ -4,7 +4,7 @@ module("tests.eressea.pool", package.seeall, lunit.testcase ) function setup() eressea.game.reset() - eressea.config.reset(); + eressea.config.reset() eressea.settings.set("rules.economy.food", "0") eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 1a25d1465..cf2a988e7 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -155,7 +155,7 @@ static void json_construction(cJSON *json, construction **consp) { return; } if (json->type != cJSON_Object) { - log_error("building %s is not a json object: %d", json->string, json->type); + log_error("construction %s is not a json object: %d", json->string, json->type); return; } construction * cons = (construction *)calloc(sizeof(construction), 1); @@ -178,7 +178,7 @@ static void json_construction(cJSON *json, construction **consp) { } break; default: - log_error("building %s contains unknown attribute %s", json->string, child->string); + log_error("construction %s contains unknown attribute %s", json->string, child->string); } } *consp = cons; diff --git a/src/util/language.c b/src/util/language.c index 58ad78555..f23ba404e 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -147,16 +147,15 @@ const char *locale_string(const locale * lang, const char *key) } find = find->nexthash; } - if (!find) { - log_warning("missing translation for \"%s\" in locale %s\n", key, lang->name); - if (lang->fallback) { - return locale_string(lang->fallback, key); - } - return 0; + if (find) { + return find->str; + } + log_error("missing translation for \"%s\" in locale %s\n", key, lang->name); + if (lang->fallback) { + return locale_string(lang->fallback, key); } - return find->str; } - return 0; + return key; } void locale_setstring(locale * lang, const char *key, const char *value) From 5e10bc40935974545fd6b7def4987f114a079756 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 13:19:44 +0100 Subject: [PATCH 17/21] wait, no. tests did not pass when that change was made (for good reason, I assume). --- src/util/language.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/language.c b/src/util/language.c index f23ba404e..564ade080 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -155,7 +155,7 @@ const char *locale_string(const locale * lang, const char *key) return locale_string(lang->fallback, key); } } - return key; + return 0; } void locale_setstring(locale * lang, const char *key, const char *value) From db083389c731b81dd210bdacd00e4939417b891b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 20:01:01 +0100 Subject: [PATCH 18/21] avoid fix_demand hitting an endless loop, kill bad use of static variables. --- src/kernel/item.c | 6 ++- src/kernel/item.test.c | 29 +++++++++++++ src/kernel/region.c | 10 ++--- src/modules/autoseed.c | 94 ++++++++---------------------------------- 4 files changed, 56 insertions(+), 83 deletions(-) diff --git a/src/kernel/item.c b/src/kernel/item.c index 7fe07c18b..b09ea1b67 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -1191,7 +1191,11 @@ void free_resources(void) int i; memset((void *)oldpotiontype, 0, sizeof(oldpotiontype)); - + while (luxurytypes) { + luxury_type * next = luxurytypes->next; + free(luxurytypes); + luxurytypes = next; + } cb_foreach(&cb_resources, "", 0, free_rtype_cb, 0); cb_clear(&cb_resources); ++num_resources; diff --git a/src/kernel/item.test.c b/src/kernel/item.test.c index 5afc55b32..56fd83e8b 100644 --- a/src/kernel/item.test.c +++ b/src/kernel/item.test.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -116,6 +118,32 @@ void test_findresourcetype(CuTest * tc) CuAssertPtrNotNull(tc, findresourcetype("Bauer", lang)); } +#include +static void test_fix_demand(CuTest *tc) { + region *r; + terrain_type *tplain; + item_type *ltype; + luxury_type *lux; + + test_cleanup(); + ltype = test_create_itemtype("balm"); + ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED); + lux = new_luxurytype(ltype, 0); + ltype = test_create_itemtype("oint"); + ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED); + lux = new_luxurytype(ltype, 0); + tplain = test_create_terrain("plain", LAND_REGION); + r = new_region(0, 0, NULL, 0); + CuAssertPtrNotNull(tc, r); + terraform_region(r, tplain); + CuAssertPtrNotNull(tc, r->land); + CuAssertIntEquals(tc, 0, fix_demand(r)); + CuAssertPtrNotNull(tc, r->land->demands); + CuAssertPtrNotNull(tc, r->land->demands->next); + CuAssertPtrNotNull(tc, r_luxury(r)); + test_cleanup(); +} + CuSuite *get_item_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -125,5 +153,6 @@ CuSuite *get_item_suite(void) SUITE_ADD_TEST(suite, test_resource_type); SUITE_ADD_TEST(suite, test_finditemtype); SUITE_ADD_TEST(suite, test_findresourcetype); + SUITE_ADD_TEST(suite, test_fix_demand); return suite; } diff --git a/src/kernel/region.c b/src/kernel/region.c index be75a9098..21bc7e819 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -69,12 +69,10 @@ region *regions; int get_maxluxuries(void) { - static int maxluxuries = -1; - if (maxluxuries == -1) { - const luxury_type *ltype; - maxluxuries = 0; - for (ltype = luxurytypes; ltype; ltype = ltype->next) - ++maxluxuries; + const luxury_type *ltype; + int maxluxuries = 0; + for (ltype = luxurytypes; ltype; ltype = ltype->next) { + ++maxluxuries; } return maxluxuries; } diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index 8840da8d2..70daf5c1e 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -127,90 +127,32 @@ bool(*fun) (const region * r)) static bool f_nolux(const region * r) { - if (r->land && count_demand(r) != get_maxluxuries()) - return true; - return false; + return (r->land && count_demand(r) != get_maxluxuries()); } -int fix_demand(region * rd) -{ - region_list *rl, *rlist = NULL; - static const luxury_type *mlux[MAXLUXURIES]; - const luxury_type *ltypes[MAXLUXURIES]; - const luxury_type *sale = NULL; - int maxlux = 0; - static int maxluxuries = -1; +int fix_demand(region * rd) { + luxury_type * ltype; + int maxluxuries = get_maxluxuries(); + if (maxluxuries > 0) { + int sale = rng_int() % maxluxuries; + for (ltype = luxurytypes; sale != 0 && ltype; ltype = ltype->next) { + --sale; + } + setluxuries(rd, ltype); + return 0; + } + return -1; +} - // TODO: this entire function is impossible to understand +int fix_all_demand(region *rd) { + region_list *rl, *rlist = NULL; recurse_regions(rd, &rlist, f_nolux); - if (maxluxuries < 0) { - int i = 0; - for (sale = luxurytypes; sale; sale = sale->next) { - ltypes[i++] = sale; - } - maxluxuries = i; - } - if (maxluxuries == 0) { - return -1; - } - else { - int i; - for (i = 0; i != maxluxuries; ++i) { - mlux[i] = 0; - } - } for (rl = rlist; rl; rl = rl->next) { region *r = rl->data; - direction_t d; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *nr = rconnect(r, d); - if (nr && nr->land && nr->land->demands) { - struct demand *dmd; - for (dmd = nr->land->demands; dmd; dmd = dmd->next) { - if (dmd->value == 0) { - int i; - for (i = 0; i != maxluxuries; ++i) { - if (mlux[i] == NULL) { - maxlux = i; - mlux[i] = dmd->type; - break; - } - else if (mlux[i] == dmd->type) { - break; - } - } - break; - } - } - } - } freset(r, RF_MARK); /* undo recursive marker */ - } - if (maxlux < 2) { - int i; - for (i = maxlux; i != 2; ++i) { - int j; - do { - int k = rng_int() % maxluxuries; - mlux[i] = ltypes[k]; - for (j = 0; j != i; ++j) { - if (mlux[j] == mlux[i]) - break; - } - } while (j != i); + if (!fix_demand(r)) { + return -1; } - maxlux = 2; - } - for (rl = rlist; rl; rl = rl->next) { - region *r = rl->data; - sale = mlux[rng_int() % maxlux]; - if (sale) - setluxuries(r, sale); - } - while (rlist) { - rl = rlist->next; - free(rlist); - rlist = rl; } return 0; } From 9453aff7f5c14b9242b55077c3af3c5670248c79 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 21:07:42 +0100 Subject: [PATCH 19/21] fix running game-specific tests for E3, add them to the test suite. --- s/runtests | 1 + scripts/run-tests-e3.lua | 19 +++++++++++++++++++ scripts/tests/e3/castles.lua | 32 ++++++++++++++++---------------- scripts/tests/e3/init.lua | 3 +++ scripts/tests/e3/spells.lua | 3 +-- scripts/tests/e3/stealth.lua | 20 ++++++++++---------- src/bindings.c | 1 + src/spy.c | 13 +++++++------ 8 files changed, 58 insertions(+), 34 deletions(-) create mode 100644 scripts/run-tests-e3.lua create mode 100644 scripts/tests/e3/init.lua diff --git a/s/runtests b/s/runtests index 7b55cda78..ea192b98b 100755 --- a/s/runtests +++ b/s/runtests @@ -19,4 +19,5 @@ $ROOT/$BIN_DIR/eressea/test_eressea cd $ROOT [ -e eressea.ini ] || ln -sf conf/eressea.ini $ROOT/$BIN_DIR/eressea/eressea -v0 scripts/run-tests.lua +$ROOT/$BIN_DIR/eressea/eressea -v0 scripts/run-tests-e3.lua cd $OLDWPD diff --git a/scripts/run-tests-e3.lua b/scripts/run-tests-e3.lua new file mode 100644 index 000000000..3e5ecdcb2 --- /dev/null +++ b/scripts/run-tests-e3.lua @@ -0,0 +1,19 @@ +-- new tests 2014-06-11 + +path = 'scripts' +if config.source_dir ~= nil then + path = config.source_dir .. '/' .. path +end +package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' + +config.rules = 'e3' + +require 'eressea' +require 'eressea.path' +require 'eressea.xmlconf' +require 'tests.e3' +require 'lunit' + +eressea.settings.set("rules.alliances", "0") +rules = require('eressea.' .. config.rules) +lunit.main() diff --git a/scripts/tests/e3/castles.lua b/scripts/tests/e3/castles.lua index c8c1bc83b..1aa2bb17c 100644 --- a/scripts/tests/e3/castles.lua +++ b/scripts/tests/e3/castles.lua @@ -3,25 +3,25 @@ require "lunit" module("tests.e3.castles", package.seeall, lunit.testcase ) function setup() - eressea.free_game() + eressea.game.reset() end function test_small_castles() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - local f2 = faction.create("noreply@eressea.de", "halfling", "de") - local u2 = unit.create(f2, r, 1) - u1:add_item("money", 10000) + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + local f2 = faction.create("noreply@eressea.de", "halfling", "de") + local u2 = unit.create(f2, r, 1) + u1:add_item("money", 10000) - local b = building.create(r, "castle") - u2.building = b - u1.building = b + local b = building.create(r, "castle") + u2.building = b + u1.building = b - b.owner = u2 - assert_equal("site", b:get_typename(7)) - assert_equal("fortification", b:get_typename(8)) - b.owner = u1 - assert_equal("site", b:get_typename(9)) - assert_equal("fortification", b:get_typename(10)) + b.owner = u2 + assert_equal("site", b:get_typename(7)) + assert_equal("fortification", b:get_typename(8)) + b.owner = u1 + assert_equal("site", b:get_typename(9)) + assert_equal("fortification", b:get_typename(10)) end diff --git a/scripts/tests/e3/init.lua b/scripts/tests/e3/init.lua new file mode 100644 index 000000000..03d5ded81 --- /dev/null +++ b/scripts/tests/e3/init.lua @@ -0,0 +1,3 @@ +require 'tests.e3.castles' +require 'tests.e3.stealth' +require 'tests.e3.spells' diff --git a/scripts/tests/e3/spells.lua b/scripts/tests/e3/spells.lua index a96607a96..21a743646 100644 --- a/scripts/tests/e3/spells.lua +++ b/scripts/tests/e3/spells.lua @@ -3,7 +3,7 @@ require "lunit" module("tests.e3.spells", package.seeall, lunit.testcase) function setup() - eressea.free_game() + eressea.game.reset() eressea.settings.set("magic.fumble.enable", "0") eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") @@ -11,7 +11,6 @@ function setup() end function test_blessedharvest_lasts_n_turn() - eressea.free_game() local r = region.create(0, 0, "plain") local f = faction.create("noreply@eressea.de", "halfling", "de") local u = unit.create(f, r) diff --git a/scripts/tests/e3/stealth.lua b/scripts/tests/e3/stealth.lua index a5f8cdcb5..687e2bfe4 100644 --- a/scripts/tests/e3/stealth.lua +++ b/scripts/tests/e3/stealth.lua @@ -6,20 +6,20 @@ local f local u function setup() - eressea.free_game() - eressea.settings.set("rules.economy.food", "4") + eressea.game.reset() + eressea.settings.set("rules.economy.food", "4") - local r = region.create(0,0, "plain") - f = faction.create("stealthy@eressea.de", "human", "de") - u = unit.create(f, r, 1) - f = faction.create("stealth@eressea.de", "human", "de") + local r = region.create(0,0, "plain") + f = faction.create("stealth1@eressea.de", "human", "de") + u = unit.create(f, r, 1) + f = faction.create("stealth2@eressea.de", "human", "de") end function test_stealth_faction_on() u:clear_orders() - u:add_order("TARNEN PARTEI") + u:add_order("TARNE PARTEI") - eressea.settings.set("rules.stealth.faction", 1) + eressea.settings.set("rules.stealth.faction", 1) process_orders() assert_not_match("Partei", report.report_unit(u, f)) assert_match("anonym", report.report_unit(u, f)) @@ -27,9 +27,9 @@ end function test_stealth_faction_off() u:clear_orders() - u:add_order("TARNEN PARTEI") + u:add_order("TARNE PARTEI") - eressea.settings.set("rules.stealth.faction", 0) + eressea.settings.set("rules.stealth.faction", 0) process_orders() assert_match("Partei", report.report_unit(u, f)) assert_not_match("anonym", report.report_unit(u, f)) diff --git a/src/bindings.c b/src/bindings.c index 87eab4c34..6021339fd 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -514,6 +514,7 @@ static void reset_game(void) for (f = factions; f; f = f->next) { f->flags &= FFL_SAVEMASK; } + init_locales(); } static int tolua_process_orders(lua_State * L) diff --git a/src/spy.c b/src/spy.c index 5b96849c5..5531eb684 100644 --- a/src/spy.c +++ b/src/spy.c @@ -210,12 +210,13 @@ void set_factionstealth(unit * u, faction * f) int setstealth_cmd(unit * u, struct order *ord) { + char token[64]; const char *s; int level, rule; const race *trace; init_order(ord); - s = getstrtoken(); + s = gettoken(token, sizeof(token)); /* Tarne ohne Parameter: Setzt maximale Tarnung */ @@ -286,7 +287,7 @@ int setstealth_cmd(unit * u, struct order *ord) /* TARNE PARTEI is disabled */ break; } - s = getstrtoken(); + s = gettoken(token, sizeof(token)); if (rule & 1) { if (!s || *s == 0) { fset(u, UFL_ANON_FACTION); @@ -299,13 +300,13 @@ int setstealth_cmd(unit * u, struct order *ord) } if (rule & 2) { if (get_keyword(s, u->faction->locale) == K_NUMBER) { - const char *s2 = getstrtoken(); + s = gettoken(token, sizeof(token)); int nr = -1; - if (s2) { - nr = atoi36(s2); + if (s) { + nr = atoi36(s); } - if (!s2 || *s2 == 0 || nr == u->faction->no) { + if (!s || *s == 0 || nr == u->faction->no) { a_removeall(&u->attribs, &at_otherfaction); break; } From f1c6d35fdf5b4ef18402fd9fa1633a48ae7805bd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 21:08:59 +0100 Subject: [PATCH 20/21] unused variable, gcc complains --- src/kernel/item.test.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/kernel/item.test.c b/src/kernel/item.test.c index 56fd83e8b..dcb7ca878 100644 --- a/src/kernel/item.test.c +++ b/src/kernel/item.test.c @@ -123,15 +123,14 @@ static void test_fix_demand(CuTest *tc) { region *r; terrain_type *tplain; item_type *ltype; - luxury_type *lux; test_cleanup(); ltype = test_create_itemtype("balm"); ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED); - lux = new_luxurytype(ltype, 0); + new_luxurytype(ltype, 0); ltype = test_create_itemtype("oint"); ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED); - lux = new_luxurytype(ltype, 0); + new_luxurytype(ltype, 0); tplain = test_create_terrain("plain", LAND_REGION); r = new_region(0, 0, NULL, 0); CuAssertPtrNotNull(tc, r); From b29a99f9ce22e02d8aa12ff891ba89d1584e19d8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Dec 2014 21:14:21 +0100 Subject: [PATCH 21/21] memory leak in special_directions. --- src/vortex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vortex.c b/src/vortex.c index e01dcd1d2..c9cea4649 100644 --- a/src/vortex.c +++ b/src/vortex.c @@ -63,6 +63,7 @@ static void a_freedirection(attrib * a) { spec_direction *d = (spec_direction *)(a->data.v); free(d->desc); + free(d->keyword); free(d); }