forked from github/server
Merge pull request #93 from badgerman/master
E3 Lua Tests & memory leaks removed
This commit is contained in:
commit
64ac0ae5e4
|
@ -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
|
||||
|
|
|
@ -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()
|
|
@ -3,7 +3,7 @@ require "lunit"
|
|||
module("tests.e3.castles", package.seeall, lunit.testcase )
|
||||
|
||||
function setup()
|
||||
eressea.free_game()
|
||||
eressea.game.reset()
|
||||
end
|
||||
|
||||
function test_small_castles()
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
require 'tests.e3.castles'
|
||||
require 'tests.e3.stealth'
|
||||
require 'tests.e3.spells'
|
|
@ -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)
|
||||
|
|
|
@ -6,18 +6,18 @@ local f
|
|||
local u
|
||||
|
||||
function setup()
|
||||
eressea.free_game()
|
||||
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")
|
||||
f = faction.create("stealth1@eressea.de", "human", "de")
|
||||
u = unit.create(f, r, 1)
|
||||
f = faction.create("stealth@eressea.de", "human", "de")
|
||||
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)
|
||||
process_orders()
|
||||
|
@ -27,7 +27,7 @@ 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)
|
||||
process_orders()
|
||||
|
|
|
@ -7,4 +7,3 @@ require 'tests.locale'
|
|||
require 'tests.regions'
|
||||
require 'tests.study'
|
||||
require 'tests.movement'
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "json.h"
|
||||
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/save.h>
|
||||
|
||||
|
@ -14,6 +15,7 @@
|
|||
|
||||
void eressea_free_game(void) {
|
||||
free_gamedata();
|
||||
init_resources();
|
||||
}
|
||||
|
||||
int eressea_read_game(const char * filename) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -22,6 +22,9 @@ static void test_register_building(CuTest * tc)
|
|||
bt_register(btype);
|
||||
|
||||
CuAssertPtrNotNull(tc, bt_find("herp"));
|
||||
// free(btype->_name);
|
||||
// free(btype);
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_building_set_owner(CuTest * tc)
|
||||
|
@ -51,6 +54,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 +89,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 +125,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 +165,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 +200,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 +235,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 +277,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 +312,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 +354,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)
|
||||
|
|
|
@ -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;
|
||||
|
@ -1143,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 = {
|
||||
|
@ -1759,8 +1761,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) {
|
||||
|
|
|
@ -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,16 +1179,23 @@ 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;
|
||||
|
||||
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;
|
||||
|
@ -1201,7 +1205,6 @@ void test_clear_resources(void)
|
|||
cb_clear(rnames + i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void register_resources(void)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/pool.h>
|
||||
#include <kernel/region.h>
|
||||
#include <kernel/terrain.h>
|
||||
#include <kernel/unit.h>
|
||||
#include <util/language.h>
|
||||
#include <util/functions.h>
|
||||
|
@ -116,6 +118,31 @@ void test_findresourcetype(CuTest * tc)
|
|||
CuAssertPtrNotNull(tc, findresourcetype("Bauer", lang));
|
||||
}
|
||||
|
||||
#include <modules/autoseed.h>
|
||||
static void test_fix_demand(CuTest *tc) {
|
||||
region *r;
|
||||
terrain_type *tplain;
|
||||
item_type *ltype;
|
||||
|
||||
test_cleanup();
|
||||
ltype = test_create_itemtype("balm");
|
||||
ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED);
|
||||
new_luxurytype(ltype, 0);
|
||||
ltype = test_create_itemtype("oint");
|
||||
ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED);
|
||||
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 +152,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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
@ -569,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;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <tests.h>
|
||||
#include <CuTest.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -69,11 +69,9 @@ 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)
|
||||
int maxluxuries = 0;
|
||||
for (ltype = luxurytypes; ltype; ltype = ltype->next) {
|
||||
++maxluxuries;
|
||||
}
|
||||
return maxluxuries;
|
||||
|
|
|
@ -238,8 +238,15 @@ void free_ship(ship * s)
|
|||
free(s);
|
||||
}
|
||||
|
||||
static void free_shiptype(void *ptr) {
|
||||
ship_type *stype = (ship_type *)ptr;
|
||||
free(stype->_name);
|
||||
free(stype->coasts);
|
||||
free(stype);
|
||||
}
|
||||
|
||||
void free_shiptypes(void) {
|
||||
ql_foreach(shiptypes, free);
|
||||
ql_foreach(shiptypes, free_shiptype);
|
||||
ql_free(shiptypes);
|
||||
shiptypes = 0;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
@ -55,7 +55,7 @@ extern "C" {
|
|||
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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -289,17 +289,23 @@ static int parse_buildings(xmlDocPtr doc)
|
|||
btype->name =
|
||||
(const char *(*)(const struct building_type *,
|
||||
const struct building *, int))fun;
|
||||
} else if (strcmp((const char *)propValue, "init") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "init") == 0) {
|
||||
btype->init = (void(*)(struct building_type *))fun;
|
||||
} else if (strcmp((const char *)propValue, "age") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "age") == 0) {
|
||||
btype->age = (void(*)(struct building *))fun;
|
||||
} else if (strcmp((const char *)propValue, "protection") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "protection") == 0) {
|
||||
btype->protection = (int(*)(struct building *, struct unit *))fun;
|
||||
} else if (strcmp((const char *)propValue, "taxes") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "taxes") == 0) {
|
||||
btype->taxes = (double(*)(const struct building *, int))fun;
|
||||
} else if (strcmp((const char *)propValue, "age") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "age") == 0) {
|
||||
btype->age = (void(*)(struct building *))fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown function type '%s' for building %s\n", (const char *)propValue, btype->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -357,7 +363,8 @@ static int parse_calendar(xmlDocPtr doc)
|
|||
months_per_year = 0;
|
||||
if (nsetCalendars == NULL || nsetCalendars->nodeNr == 0) {
|
||||
rv = -1;
|
||||
} else
|
||||
}
|
||||
else
|
||||
for (c = 0; c != nsetCalendars->nodeNr; ++c) {
|
||||
xmlNodePtr calendar = nsetCalendars->nodeTab[c];
|
||||
xmlXPathObjectPtr xpathWeeks, xpathMonths, xpathSeasons;
|
||||
|
@ -528,14 +535,14 @@ static int parse_ships(xmlDocPtr doc)
|
|||
if (k == 0) {
|
||||
assert(st->coasts == NULL);
|
||||
st->coasts =
|
||||
(const terrain_type **)malloc(sizeof(const terrain_type *) *
|
||||
(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_terrain((const char *)propValue);
|
||||
st->coasts[c] = get_or_create_terrain((const char *)propValue);
|
||||
if (st->coasts[c] != NULL)
|
||||
++c;
|
||||
else {
|
||||
|
@ -723,7 +730,8 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
|
|||
wtype->attack =
|
||||
(bool(*)(const struct troop *, const struct weapon_type *,
|
||||
int *))fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -827,18 +835,22 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
|
|||
itype->give =
|
||||
(int(*)(struct unit *, struct unit *, const struct item_type *, int,
|
||||
struct order *))fun;
|
||||
} else if (strcmp((const char *)propValue, "use") == 0) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "useonother") == 0) {
|
||||
itype->useonother =
|
||||
(int(*)(struct unit *, int, const struct item_type *, int,
|
||||
struct order *))fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, rtype->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -875,9 +887,11 @@ static int parse_rules(xmlDocPtr doc)
|
|||
global.functions.wage =
|
||||
(int(*)(const struct region *, const struct faction *,
|
||||
const struct race *, int))fun;
|
||||
} else if (strcmp((const char *)propValue, "maintenance") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "maintenance") == 0) {
|
||||
global.functions.maintenance = (int(*)(const struct unit *))fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown function for rule '%s'\n", (const char *)propValue);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -943,11 +957,14 @@ static int parse_resources(xmlDocPtr doc)
|
|||
assert(propValue != NULL);
|
||||
if (strcmp((const char *)propValue, "change") == 0) {
|
||||
rtype->uchange = (rtype_uchange)fun;
|
||||
} else if (strcmp((const char *)propValue, "get") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "get") == 0) {
|
||||
rtype->uget = (rtype_uget)fun;
|
||||
} else if (strcmp((const char *)propValue, "name") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "name") == 0) {
|
||||
rtype->name = (rtype_name)fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown function type '%s' for resource %s\n", (const char *)propValue, rtype->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -1000,13 +1017,16 @@ static int parse_resources(xmlDocPtr doc)
|
|||
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) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
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);
|
||||
|
@ -1014,7 +1034,8 @@ static int parse_resources(xmlDocPtr doc)
|
|||
rdata->modifiers[k].flags = RMF_REQUIREDBUILDING;
|
||||
xmlFree(propBldg);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -1031,7 +1052,8 @@ static int parse_resources(xmlDocPtr doc)
|
|||
if (propFlag != NULL) {
|
||||
if (strcmp((const char *)propFlag, "logging") == 0) {
|
||||
rdata->guard |= GUARD_TREES;
|
||||
} else if (strcmp((const char *)propFlag, "mining") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propFlag, "mining") == 0) {
|
||||
rdata->guard |= GUARD_MINING;
|
||||
}
|
||||
xmlFree(propFlag);
|
||||
|
@ -1060,9 +1082,11 @@ static int parse_resources(xmlDocPtr doc)
|
|||
assert(propValue != NULL);
|
||||
if (strcmp((const char *)propValue, "produce") == 0) {
|
||||
rdata->produce = (rlimit_produce)fun;
|
||||
} else if (strcmp((const char *)propValue, "limit") == 0) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "limit") == 0) {
|
||||
rdata->limit = (rlimit_limit)fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -1162,11 +1186,13 @@ static void add_spells(equipment * eq, xmlNodeSetPtr nsetItems)
|
|||
sp = find_spell((const char *)propValue);
|
||||
if (!sp) {
|
||||
log_error("no spell '%s' for equipment-set '%s'\n", (const char *)propValue, eq->name);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int level = xml_ivalue(node, "level", 0);
|
||||
if (level > 0) {
|
||||
equipment_addspell(eq, sp, level);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("spell '%s' for equipment-set '%s' has no level\n", sp->sname, eq->name);
|
||||
}
|
||||
}
|
||||
|
@ -1190,7 +1216,8 @@ static void add_skills(equipment * eq, xmlNodeSetPtr nsetSkills)
|
|||
if (sk == NOSKILL) {
|
||||
log_error("unknown skill '%s' in equipment-set %s\n", (const char *)propValue, eq->name);
|
||||
xmlFree(propValue);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
xmlFree(propValue);
|
||||
propValue = xmlGetProp(node, BAD_CAST "level");
|
||||
if (propValue != NULL) {
|
||||
|
@ -1338,7 +1365,8 @@ static int parse_spellbooks(xmlDocPtr doc)
|
|||
if (propValue) {
|
||||
sb = get_spellbook((const char *)propValue);
|
||||
xmlFree(propValue);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("spellbook at index '%d' has n name\n", i);
|
||||
continue;
|
||||
}
|
||||
|
@ -1359,7 +1387,8 @@ static int parse_spellbooks(xmlDocPtr doc)
|
|||
}
|
||||
if (sp && level > 0) {
|
||||
spellbook_add(sb, sp, level);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name);
|
||||
}
|
||||
}
|
||||
|
@ -1459,7 +1488,8 @@ static int parse_spells(xmlDocPtr doc)
|
|||
}
|
||||
strlcpy(zText + 7, sp->sname, sizeof(zText) - 7);
|
||||
fumble = get_function(zText);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
||||
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
||||
pf_generic fun;
|
||||
|
@ -1469,12 +1499,15 @@ static int parse_spells(xmlDocPtr doc)
|
|||
if (strcmp((const char *)propValue, "cast") == 0) {
|
||||
if (fun) {
|
||||
cast = fun;
|
||||
} else {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
else if (fun && strcmp((const char *)propValue, "fumble") == 0) {
|
||||
fumble = fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown function type '%s' for spell '%s'\n", (const char *)propValue, sp->sname);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -1516,7 +1549,8 @@ static int parse_spells(xmlDocPtr doc)
|
|||
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) {
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -1692,7 +1726,8 @@ static int parse_races(xmlDocPtr doc)
|
|||
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) {
|
||||
}
|
||||
else if (strcmp((const char *)child->name, "param") == 0) {
|
||||
parse_param(&rc->parameters, child);
|
||||
}
|
||||
}
|
||||
|
@ -1718,7 +1753,8 @@ static int parse_races(xmlDocPtr doc)
|
|||
rc->study_speed = calloc(1, MAXSKILLS);
|
||||
rc->study_speed[sk] = (char)speed;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown skill '%s' in race '%s'\n", (const char *)propValue, rc->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -1741,19 +1777,25 @@ static int parse_races(xmlDocPtr doc)
|
|||
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) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "age") == 0) {
|
||||
rc->age = (void(*)(struct unit *))fun;
|
||||
} else if (strcmp((const char *)propValue, "move") == 0) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
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) {
|
||||
}
|
||||
else if (strcmp((const char *)propValue, "initfamiliar") == 0) {
|
||||
rc->init_familiar = (void(*)(struct unit *))fun;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_error("unknown function type '%s' for race %s\n", (const char *)propValue, rc->_name);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -1773,7 +1815,8 @@ static int parse_races(xmlDocPtr doc)
|
|||
if (xml_bvalue(node, "default", false)) {
|
||||
rc->familiars[k] = rc->familiars[0];
|
||||
rc->familiars[0] = frc;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
rc->familiars[k] = frc;
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -1804,7 +1847,8 @@ static int parse_races(xmlDocPtr doc)
|
|||
if (propValue != NULL) {
|
||||
attack->data.dice = _strdup((const char *)propValue);
|
||||
xmlFree(propValue);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
attack->data.sp = xml_spell(node, "spell");
|
||||
if (attack->data.sp) {
|
||||
attack->level = xml_ivalue(node, "level", 0);
|
||||
|
@ -2000,7 +2044,8 @@ static int parse_messages(xmlDocPtr doc)
|
|||
mtype = mt_find((const char *)propValue);
|
||||
if (mtype == NULL) {
|
||||
mtype = mt_register(mt_new((const char *)propValue, (const char **)argv));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(argv != NULL || !"cannot redefine arguments of message now");
|
||||
}
|
||||
xmlFree(propValue);
|
||||
|
@ -2087,7 +2132,8 @@ xml_readstrings(xmlXPathContextPtr xpath, xmlNodePtr * nodeTab, int nodeNr,
|
|||
locale_setstring(lang, zName, (const char *)propText);
|
||||
}
|
||||
xmlFree(propText);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
log_warning("string %s has no text in locale %s\n", zName, locale_name(lang));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -215,6 +218,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 +250,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 +283,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 +316,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 +349,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 +379,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)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <tests.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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");
|
||||
|
|
|
@ -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;
|
||||
|
||||
// TODO: this entire function is impossible to understand
|
||||
recurse_regions(rd, &rlist, f_nolux);
|
||||
if (maxluxuries < 0) {
|
||||
int i = 0;
|
||||
for (sale = luxurytypes; sale; sale = sale->next) {
|
||||
ltypes[i++] = sale;
|
||||
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;
|
||||
}
|
||||
maxluxuries = i;
|
||||
setluxuries(rd, ltype);
|
||||
return 0;
|
||||
}
|
||||
if (maxluxuries == 0) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
for (i = 0; i != maxluxuries; ++i) {
|
||||
mlux[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int fix_all_demand(region *rd) {
|
||||
region_list *rl, *rlist = NULL;
|
||||
recurse_regions(rd, &rlist, f_nolux);
|
||||
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 (!fix_demand(r)) {
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
13
src/spy.c
13
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;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ int RunAllTests(void)
|
|||
log_flags = flags;
|
||||
fail_count = suite->failCount;
|
||||
CuSuiteDelete(suite);
|
||||
kernel_done();
|
||||
return fail_count;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ struct unit *test_create_unit(struct faction *f, struct region *r)
|
|||
|
||||
void test_cleanup(void)
|
||||
{
|
||||
test_clear_terrains();
|
||||
test_clear_resources();
|
||||
free_terrains();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <kernel/types.h>
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/region.h>
|
||||
#include <kernel/terrain.h>
|
||||
|
||||
#include <util/language.h>
|
||||
|
||||
|
@ -12,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"));
|
||||
|
@ -27,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));
|
||||
}
|
||||
|
@ -36,15 +39,13 @@ 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"));
|
||||
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,14 +57,16 @@ 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"));
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -147,14 +147,13 @@ 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 (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 0;
|
||||
}
|
||||
return find->str;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,6 +241,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);
|
||||
|
@ -319,6 +319,7 @@ void free_locales(void) {
|
|||
free(strings);
|
||||
}
|
||||
}
|
||||
free(locales->name);
|
||||
free(locales);
|
||||
locales = next;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -211,7 +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);
|
||||
while (*refs) {
|
||||
tref * ref = *refs;
|
||||
*refs = ref->nexthash;
|
||||
free(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(node);
|
||||
|
|
|
@ -61,7 +61,10 @@ 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->keyword);
|
||||
free(d);
|
||||
}
|
||||
|
||||
static int a_agedirection(attrib * a)
|
||||
|
|
Loading…
Reference in New Issue