diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4aa4ca472..7507bd99f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,6 +11,10 @@ if (MSVC)
include(MSVC)
endif (MSVC)
+INCLUDE (CheckSymbolExists)
+CHECK_SYMBOL_EXISTS(strlcat string.h HAVE_STRLCAT)
+CHECK_SYMBOL_EXISTS(strdup string.h HAVE_STRDUP)
+
find_package (SQLite3)
find_package (BerkeleyDB)
find_package (Curses)
diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml
index ea4acf758..b06ff0445 100644
--- a/res/core/de/strings.xml
+++ b/res/core/de/strings.xml
@@ -7337,8 +7337,8 @@
- eine zu %d%% vollendete Straße
- a road that is %d%% complete
+ eine zu $percent%% vollendete Straße
+ a road that is $percent% complete
diff --git a/res/e3a/spellbooks/cerddor.xml b/res/e3a/spellbooks/cerddor.xml
index 3d5f0e08e..9b6e4cd8e 100644
--- a/res/e3a/spellbooks/cerddor.xml
+++ b/res/e3a/spellbooks/cerddor.xml
@@ -33,4 +33,5 @@
+
diff --git a/res/e3a/spellbooks/common.xml b/res/e3a/spellbooks/common.xml
index 0735bc248..688a1b9ae 100644
--- a/res/e3a/spellbooks/common.xml
+++ b/res/e3a/spellbooks/common.xml
@@ -34,7 +34,6 @@
-
diff --git a/res/e3a/spellbooks/draig.xml b/res/e3a/spellbooks/draig.xml
index 34b6e7642..d97a695b3 100644
--- a/res/e3a/spellbooks/draig.xml
+++ b/res/e3a/spellbooks/draig.xml
@@ -29,4 +29,5 @@
+
diff --git a/res/e3a/spellbooks/gray.xml b/res/e3a/spellbooks/gray.xml
index 9c0035e78..78645f907 100644
--- a/res/e3a/spellbooks/gray.xml
+++ b/res/e3a/spellbooks/gray.xml
@@ -127,7 +127,6 @@
-
diff --git a/res/e3a/spellbooks/gwyrrd.xml b/res/e3a/spellbooks/gwyrrd.xml
index ac51495cf..452100ace 100644
--- a/res/e3a/spellbooks/gwyrrd.xml
+++ b/res/e3a/spellbooks/gwyrrd.xml
@@ -30,4 +30,5 @@
+
diff --git a/res/e3a/spellbooks/illaun.xml b/res/e3a/spellbooks/illaun.xml
index 129e15f21..6b89df8fa 100644
--- a/res/e3a/spellbooks/illaun.xml
+++ b/res/e3a/spellbooks/illaun.xml
@@ -30,4 +30,5 @@
+
diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua
index c186107c4..d76c2cfdf 100644
--- a/scripts/tests/common.lua
+++ b/scripts/tests/common.lua
@@ -1112,3 +1112,51 @@ function test_build_castle()
assert_equal(1, u.building.size)
assert_equal(u.building.name, "Burg")
end
+
+function test_route()
+ local r1 = region.create(0, 0, "plain")
+ local r2 = region.create(1, 0, "plain")
+ local f = faction.create("human", "route@example.com")
+ local u = unit.create(f, r1, 1)
+ u:add_order("ROUTE O W P")
+ process_orders()
+ assert_equal("ROUTE West PAUSE Ost", u:get_order(0))
+ assert_equal(r2, u.region)
+end
+
+function test_route_horse()
+ local r1 = region.create(0, 0, "plain")
+ local r2 = region.create(1, 0, "plain")
+ local f = faction.create("human", "route@example.com")
+ local u = unit.create(f, r1, 1)
+ u:add_order("ROUTE O P W P")
+ u:add_item('horse', 1)
+ u:set_skill('riding', 1)
+ process_orders()
+ assert_equal("ROUTE West PAUSE Ost PAUSE", u:get_order(0))
+ assert_equal(r2, u.region)
+end
+
+function test_route_pause()
+ local r1 = region.create(0, 0, "plain")
+ local r2 = region.create(1, 0, "plain")
+ local f = faction.create("human", "route@example.com")
+ local u = unit.create(f, r1, 1)
+ u:add_order("ROUTE P O W")
+ process_orders()
+ assert_equal("ROUTE P O W", u:get_order(0))
+ assert_equal(r1, u.region)
+end
+
+function test_bug_2393_cart()
+ local r1 = region.create(0, 0, "plain")
+ local r2 = region.create(1, 0, "plain")
+ local f = faction.create("human", "cart@example.com")
+ local u = unit.create(f, r1, 2)
+ u:add_order("NACH O")
+ u:add_item('stone', 2)
+ u:add_item('horse', 2)
+ u:add_item('cart', 1)
+ process_orders()
+ assert_equal(r1, u.region)
+end
diff --git a/scripts/tests/e2/init.lua b/scripts/tests/e2/init.lua
index 222723082..d8d21a5c8 100644
--- a/scripts/tests/e2/init.lua
+++ b/scripts/tests/e2/init.lua
@@ -1,3 +1,4 @@
+require 'tests.e2.insects'
require 'tests.e2.spells'
require 'tests.e2.buildings'
require 'tests.e2.production'
diff --git a/scripts/tests/e2/insects.lua b/scripts/tests/e2/insects.lua
new file mode 100644
index 000000000..374bedff8
--- /dev/null
+++ b/scripts/tests/e2/insects.lua
@@ -0,0 +1,83 @@
+require "lunit"
+
+module("tests.e2.insects", package.seeall, lunit.testcase)
+
+function setup()
+ eressea.free_game()
+ eressea.settings.set("rules.food.flags", "4")
+ eressea.settings.set("nmr.timeout", "0")
+ eressea.settings.set("NewbieImmunity", "0")
+end
+
+function test_move_to_glacier()
+ local r = region.create(0, 0, "plain")
+ local r2 = region.create(1, 0, "glacier")
+ local f = faction.create("insect", "insect@eressea.de", "de")
+ local u = unit.create(f, r, 1)
+
+ u:clear_orders()
+ u:add_order("NACH OST")
+ process_orders()
+ assert_equal(r, u.region)
+end
+
+function test_sail_into_glacier()
+ local r = region.create(0, 0, "ocean")
+ local r2 = region.create(1, 0, "glacier")
+ local f = faction.create("insect", "insect@eressea.de", "de")
+ local u1 = unit.create(f, r, 1, 'human')
+ local u2 = unit.create(f, r, 1, 'insect')
+
+ u1.ship = ship.create(r, 'boat')
+ u1:set_skill("sailing", 10)
+ u1:clear_orders()
+ u1:add_order("NACH OST")
+ u2.ship = u1.ship
+ process_orders()
+ assert_equal(r, u2.region)
+end
+
+function test_recruit_in_winter()
+ local r = region.create(0, 0, "plain")
+ local f = faction.create("insect", "insect@eressea.de", "de")
+ local u = unit.create(f, r, 1)
+
+ u:add_item('money', 1000)
+ u:clear_orders()
+ u:add_order("REKRUTIERE 1")
+ set_turn(1010)
+ process_orders()
+ assert_equal('winter', get_season(get_turn()))
+ assert_equal(1, u.number)
+
+ u:clear_orders()
+ u:add_order("REKRUTIERE 1")
+ set_turn(1011)
+ process_orders()
+ assert_equal('spring', get_season(get_turn()))
+ assert_equal(2, u.number)
+end
+
+function test_recruit_in_desert()
+ local r = region.create(0, 0, "desert")
+ local f = faction.create("insect", "insect@eressea.de", "de")
+ local u = unit.create(f, r, 1)
+
+ u:add_item('money', 1000)
+ u:clear_orders()
+ u:add_order("REKRUTIERE 1")
+ set_turn(1010)
+ process_orders()
+ assert_equal('winter', get_season(get_turn()))
+ assert_equal(2, u.number)
+end
+
+function bug_1841_test_hunger_in_glacier()
+ local r = region.create(0, 0, "glacier")
+ local f = faction.create("insect", "insect@eressea.de", "de")
+ local u = unit.create(f, r, 1)
+
+ local flags = u.flags
+ process_orders()
+ assert_equal(flags+2048, u.flags)
+end
diff --git a/scripts/tests/spells.lua b/scripts/tests/spells.lua
index 1a8442f2e..de56472c3 100644
--- a/scripts/tests/spells.lua
+++ b/scripts/tests/spells.lua
@@ -81,7 +81,7 @@ function test_create_dreameye()
assert_equal(amax - 5, u.aura_max)
end
-function test_appeasement()
+function test_appeasement_can_move()
local u1, u2, r1, r2, uno
r1 = region.create(0, 0, 'plain')
r2 = region.create(1, 0, 'plain')
@@ -102,4 +102,32 @@ function test_appeasement()
u2 = get_unit(uno)
assert_not_nil(u2)
assert_equal(r2, u2.region)
+ assert_equal(5, u2.status)
+end
+
+function test_appeasement_break_guard()
+ local u1, u2, r1, r2, uno
+ r1 = region.create(0, 0, 'plain')
+ r2 = region.create(1, 0, 'plain')
+ u2 = unit.create(faction.create('human'), r1, 1)
+ u2.race = 'elf'
+ u2.name = 'Angsthase'
+ u2.magic = 'gwyrrd'
+ u2.guard = true
+ u2.status = 1
+ u2:set_skill('magic', 5)
+ u2.aura = 10
+ u2:add_spell('appeasement')
+ u2:add_order('BEWACHE')
+ u2:add_order('KAMPFZAUBER STUFE 1 Friedenslied')
+ uno = u2.id
+ u1 = unit.create(faction.create('human'), r1, 1)
+ u1:set_skill('polearm', 5)
+ u1:add_order('ATTACKIERE ' .. itoa36(uno))
+ process_orders()
+ u2 = get_unit(uno)
+ assert_not_nil(u2)
+ assert_equal(r1, u2.region)
+ assert_equal(5, u2.status)
+ assert_equal(false, u2.guard)
end
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d3cfdafce..9436a8946 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -266,6 +266,14 @@ add_test(server test_eressea)
install(TARGETS eressea DESTINATION "bin")
+if (HAVE_STRLCAT)
+ add_definitions(-DHAVE_BSDSTRING)
+endif(HAVE_STRLCAT)
+
+if (HAVE_STRDUP)
+ add_definitions(-DHAVE_STRDUP)
+endif(HAVE_STRDUP)
+
if (DB_FOUND)
include_directories (${DB_INCLUDE_DIR})
target_link_libraries(convert ${DB_LIBRARIES})
diff --git a/src/battle.c b/src/battle.c
index a58b0ab63..823fd89f1 100644
--- a/src/battle.c
+++ b/src/battle.c
@@ -69,6 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include
#include
#include
+#include
#include
#include
#include
@@ -1643,7 +1644,6 @@ static castorder * create_castorder_combat(castorder *co, fighter *fig, const sp
return co;
}
-#ifdef FFL_CURSED
static void summon_igjarjuk(battle *b, spellrank spellranks[]) {
side *s;
castorder *co;
@@ -1681,7 +1681,6 @@ static void summon_igjarjuk(battle *b, spellrank spellranks[]) {
}
}
}
-#endif
void do_combatmagic(battle * b, combatmagic_t was)
{
@@ -1693,11 +1692,9 @@ void do_combatmagic(battle * b, combatmagic_t was)
memset(spellranks, 0, sizeof(spellranks));
-#ifdef FFL_CURSED
if (was == DO_PRECOMBATSPELL) {
summon_igjarjuk(b, spellranks);
}
-#endif
for (s = b->sides; s != b->sides + b->nsides; ++s) {
fighter *fig;
for (fig = s->fighters; fig; fig = fig->next) {
@@ -2886,10 +2883,10 @@ static void print_header(battle * b)
for (df = s->fighters; df; df = df->next) {
if (is_attacker(df)) {
if (first) {
- bufp = STRLCPY(bufp, ", ", size);
+ strlcpy(bufp, ", ", size);
}
if (lastf) {
- bufp = STRLCPY(bufp, lastf, size);
+ strlcpy(bufp, lastf, size);
first = true;
}
if (seematrix(f, s))
@@ -3579,7 +3576,7 @@ static int battle_report(battle * b)
if (komma) {
bufp = STRLCPY(bufp, ", ", size);
}
- slprintf(buffer, sizeof(buffer), "%s %2d(%s): ",
+ snprintf(buffer, sizeof(buffer), "%s %2d(%s): ",
loc_army, army_index(s), abbrev);
bufp = STRLCPY(bufp, buffer, size);
diff --git a/src/bind_unit.c b/src/bind_unit.c
index a7e8f61ab..f48965bfc 100644
--- a/src/bind_unit.c
+++ b/src/bind_unit.c
@@ -718,6 +718,30 @@ static int tolua_unit_set_region(lua_State * L)
return 0;
}
+static int tolua_unit_get_order(lua_State * L)
+{
+ unit *self = (unit *)tolua_tousertype(L, 1, 0);
+ int index = (int)tolua_tonumber(L, 2, -1);
+ order *ord = NULL;
+ if (index < 0) {
+ ord = self->thisorder;
+ }
+ else {
+ int i;
+ ord = self->orders;
+ for (i = 0; ord && i != index; ++i) {
+ ord = ord->next;
+ }
+ }
+ if (ord) {
+ char buffer[1024];
+ get_command(ord, self->faction->locale, buffer, sizeof(buffer));
+ lua_pushstring(L, buffer);
+ return 1;
+ }
+ return 0;
+}
+
static int tolua_unit_add_order(lua_State * L)
{
unit *self = (unit *)tolua_tousertype(L, 1, 0);
@@ -972,6 +996,7 @@ void tolua_unit_open(lua_State * L)
tolua_variable(L, TOLUA_CAST "weight", tolua_unit_get_weight, 0);
tolua_variable(L, TOLUA_CAST "capacity", tolua_unit_get_capacity, 0);
+ tolua_function(L, TOLUA_CAST "get_order", tolua_unit_get_order);
tolua_function(L, TOLUA_CAST "add_order", tolua_unit_add_order);
tolua_function(L, TOLUA_CAST "clear_orders", tolua_unit_clear_orders);
tolua_function(L, TOLUA_CAST "get_curse", tolua_unit_get_curse);
diff --git a/src/creport.c b/src/creport.c
index 89cf4c9ce..3f3e1bfb8 100644
--- a/src/creport.c
+++ b/src/creport.c
@@ -516,7 +516,7 @@ static void report_crtypes(FILE * F, const struct locale *lang)
assert(hash > 0);
fprintf(F, "MESSAGETYPE %u\n", hash);
fputc('\"', F);
- fputs(escape_string(nrt_string(nrt), buffer, sizeof(buffer)), F);
+ fputs(str_escape(nrt_string(nrt), buffer, sizeof(buffer)), F);
fputs("\";text\n", F);
fprintf(F, "\"%s\";section\n", nrt_section(nrt));
}
@@ -1067,7 +1067,7 @@ static void cr_reportspell(FILE * F, spell * sp, int level, const struct locale
const char *name =
translate(mkname("spell", sp->sname), spell_name(sp, lang));
- fprintf(F, "ZAUBER %d\n", hashstring(sp->sname));
+ fprintf(F, "ZAUBER %d\n", str_hash(sp->sname));
fprintf(F, "\"%s\";name\n", name);
fprintf(F, "%d;level\n", level);
fprintf(F, "%d;rank\n", sp->rank);
@@ -1115,7 +1115,7 @@ static char *cr_output_resource(char *buf, const resource_type *rtype,
assert(rtype);
name = resourcename(rtype, NMF_PLURAL);
assert(name);
- buf += sprintf(buf, "RESOURCE %u\n", hashstring(rtype->_name));
+ buf += sprintf(buf, "RESOURCE %u\n", str_hash(rtype->_name));
tname = LOC(loc, name);
assert(tname);
tname = translate(name, tname);
@@ -1663,7 +1663,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
if (ptype == NULL)
continue;
ch = resourcename(ptype->itype->rtype, 0);
- fprintf(F, "TRANK %d\n", hashstring(ch));
+ fprintf(F, "TRANK %d\n", str_hash(ch));
fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch)));
fprintf(F, "%d;Stufe\n", ptype->level);
diff --git a/src/direction.c b/src/direction.c
index 5e2333bbe..13feff13b 100644
--- a/src/direction.c
+++ b/src/direction.c
@@ -8,6 +8,15 @@
#include
+const char *shortdirections[MAXDIRECTIONS] = {
+ "dir_nw",
+ "dir_ne",
+ "dir_east",
+ "dir_se",
+ "dir_sw",
+ "dir_west"
+};
+
void init_direction(const struct locale *lang, direction_t dir, const char *str) {
void **tokens = get_translations(lang, UT_DIRECTIONS);
variant token;
diff --git a/src/direction.h b/src/direction.h
index 14ced4c1c..724878663 100644
--- a/src/direction.h
+++ b/src/direction.h
@@ -21,6 +21,8 @@ extern "C"
NODIRECTION = -1
} direction_t;
+ extern const char *shortdirections[MAXDIRECTIONS];
+
direction_t get_direction(const char *s, const struct locale *);
void init_directions(struct locale *lang);
void init_direction(const struct locale *lang, direction_t dir, const char *str);
diff --git a/src/economy.c b/src/economy.c
index 759d60cb8..c7ab2247d 100644
--- a/src/economy.c
+++ b/src/economy.c
@@ -64,7 +64,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -248,6 +247,7 @@ void add_recruits(unit * u, int number, int wanted)
if (number > 0) {
unit *unew;
char equipment[64];
+ int len;
if (u->number == 0) {
set_number(u, number);
@@ -258,10 +258,10 @@ void add_recruits(unit * u, int number, int wanted)
unew = create_unit(r, u->faction, number, u_race(u), 0, NULL, u);
}
- strlcpy(equipment, "new_", sizeof(equipment));
- strlcat(equipment, u_race(u)->_name, sizeof(equipment));
- equip_unit(unew, get_equipment(equipment));
-
+ len = snprintf(equipment, sizeof(equipment), "new_%s", u_race(u)->_name);
+ if (len > 0 && (size_t)len < sizeof(equipment)) {
+ equip_unit(unew, get_equipment(equipment));
+ }
if (unew != u) {
transfermen(unew, u, unew->number);
remove_unit(&r->units, unew);
diff --git a/src/gmtool.c b/src/gmtool.c
index fcb8cff8b..1fba47be6 100644
--- a/src/gmtool.c
+++ b/src/gmtool.c
@@ -50,7 +50,6 @@
#include
#include
#include
-#include
#include
#include
@@ -58,6 +57,7 @@
#include
#include
#include
+#include
#include
static int g_quit;
@@ -1228,7 +1228,7 @@ static void handlekey(state * st, int c)
else if (findmode == 'F') {
faction *f = select_faction(st);
if (f != NULL) {
- strlcpy(locate, itoa36(f->no), sizeof(locate));
+ itoab_r(f->no, 36, locate, sizeof(locate));
findmode = 'f';
}
else {
@@ -1254,7 +1254,7 @@ static void handlekey(state * st, int c)
region *first = (mr && mr->r && mr->r->next) ? mr->r->next : regions;
if (findmode == 'f') {
- slprintf(sbuffer, sizeof(sbuffer), "find-faction: %s", locate);
+ snprintf(sbuffer, sizeof(sbuffer), "find-faction: %s", locate);
statusline(st->wnd_status->handle, sbuffer);
f = findfaction(atoi36(locate));
if (f == NULL) {
diff --git a/src/helpers.c b/src/helpers.c
index 897e39720..6924dbf61 100644
--- a/src/helpers.c
+++ b/src/helpers.c
@@ -17,7 +17,6 @@ without prior permission by the authors of Eressea.
#include
#include
-#include
#include
#include
#include
@@ -52,66 +51,64 @@ lua_giveitem(unit * s, unit * d, const item_type * itype, int n, struct order *o
{
lua_State *L = (lua_State *)global.vm_state;
char fname[64];
- int result = -1;
+ int result = -1, len;
const char *iname = itype->rtype->_name;
assert(s != NULL);
- strlcpy(fname, iname, sizeof(fname));
- strlcat(fname, "_give", sizeof(fname));
+ len = snprintf(fname, sizeof(fname), "%s_give", iname);
+ if (len > 0 && (size_t)len < sizeof(fname)) {
+ lua_getglobal(L, fname);
+ if (lua_isfunction(L, -1)) {
+ tolua_pushusertype(L, s, TOLUA_CAST "unit");
+ tolua_pushusertype(L, d, TOLUA_CAST "unit");
+ tolua_pushstring(L, iname);
+ lua_pushinteger(L, n);
- lua_getglobal(L, fname);
- if (lua_isfunction(L, -1)) {
- tolua_pushusertype(L, s, TOLUA_CAST "unit");
- tolua_pushusertype(L, d, TOLUA_CAST "unit");
- tolua_pushstring(L, iname);
- lua_pushinteger(L, n);
-
- if (lua_pcall(L, 4, 1, 0) != 0) {
- const char *error = lua_tostring(L, -1);
- log_error("unit %s calling '%s': %s.\n", unitname(s), fname, error);
- lua_pop(L, 1);
+ if (lua_pcall(L, 4, 1, 0) != 0) {
+ const char *error = lua_tostring(L, -1);
+ log_error("unit %s calling '%s': %s.\n", unitname(s), fname, error);
+ lua_pop(L, 1);
+ }
+ else {
+ result = (int)lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
}
else {
- result = (int)lua_tonumber(L, -1);
+ log_error("unit %s trying to call '%s' : not a function.\n", unitname(s), fname);
lua_pop(L, 1);
}
}
- else {
- log_error("unit %s trying to call '%s' : not a function.\n", unitname(s), fname);
- lua_pop(L, 1);
- }
-
return result;
}
static int limit_resource_lua(const region * r, const resource_type * rtype)
{
char fname[64];
- int result = -1;
+ int result = -1, len;
lua_State *L = (lua_State *)global.vm_state;
- strlcpy(fname, rtype->_name, sizeof(fname));
- strlcat(fname, "_limit", sizeof(fname));
+ len = snprintf(fname, sizeof(fname), "%s_limit", rtype->_name);
+ if (len > 0 && (size_t)len < sizeof(fname)) {
+ lua_getglobal(L, fname);
+ if (lua_isfunction(L, -1)) {
+ tolua_pushusertype(L, (void *)r, TOLUA_CAST "region");
- lua_getglobal(L, fname);
- if (lua_isfunction(L, -1)) {
- tolua_pushusertype(L, (void *)r, TOLUA_CAST "region");
-
- if (lua_pcall(L, 1, 1, 0) != 0) {
- const char *error = lua_tostring(L, -1);
- log_error("limit(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error);
- lua_pop(L, 1);
+ if (lua_pcall(L, 1, 1, 0) != 0) {
+ const char *error = lua_tostring(L, -1);
+ log_error("limit(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error);
+ lua_pop(L, 1);
+ }
+ else {
+ result = (int)lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
}
else {
- result = (int)lua_tonumber(L, -1);
+ log_error("limit(%s) calling '%s': not a function.\n", regionname(r, NULL), fname);
lua_pop(L, 1);
}
}
- else {
- log_error("limit(%s) calling '%s': not a function.\n", regionname(r, NULL), fname);
- lua_pop(L, 1);
- }
-
return result;
}
@@ -120,25 +117,26 @@ produce_resource_lua(region * r, const resource_type * rtype, int norders)
{
lua_State *L = (lua_State *)global.vm_state;
char fname[64];
+ int len;
- strlcpy(fname, rtype->_name, sizeof(fname));
- strlcat(fname, "_produce", sizeof(fname));
+ len = snprintf(fname, sizeof(fname), "%s_produce", rtype->_name);
+ if (len > 0 && (size_t)len < sizeof(fname)) {
+ lua_getglobal(L, fname);
+ if (lua_isfunction(L, -1)) {
+ tolua_pushusertype(L, (void *)r, TOLUA_CAST "region");
+ lua_pushinteger(L, norders);
- lua_getglobal(L, fname);
- if (lua_isfunction(L, -1)) {
- tolua_pushusertype(L, (void *)r, TOLUA_CAST "region");
- lua_pushinteger(L, norders);
-
- if (lua_pcall(L, 2, 0, 0) != 0) {
- const char *error = lua_tostring(L, -1);
- log_error("produce(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error);
+ if (lua_pcall(L, 2, 0, 0) != 0) {
+ const char *error = lua_tostring(L, -1);
+ log_error("produce(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error);
+ lua_pop(L, 1);
+ }
+ }
+ else {
+ log_error("produce(%s) calling '%s': not a function.\n", regionname(r, NULL), fname);
lua_pop(L, 1);
}
}
- else {
- log_error("produce(%s) calling '%s': not a function.\n", regionname(r, NULL), fname);
- lua_pop(L, 1);
- }
}
static void push_param(lua_State * L, char c, spllprm * param)
@@ -216,32 +214,31 @@ static int
lua_changeresource(unit * u, const struct resource_type *rtype, int delta)
{
lua_State *L = (lua_State *)global.vm_state;
- int result = -1;
+ int len, result = -1;
char fname[64];
- strlcpy(fname, rtype->_name, sizeof(fname));
- strlcat(fname, "_changeresource", sizeof(fname));
-
- lua_getglobal(L, fname);
- if (lua_isfunction(L, -1)) {
- tolua_pushusertype(L, u, TOLUA_CAST "unit");
- lua_pushinteger(L, delta);
-
- if (lua_pcall(L, 2, 1, 0) != 0) {
- const char *error = lua_tostring(L, -1);
- log_error("change(%s) calling '%s': %s.\n", unitname(u), fname, error);
- lua_pop(L, 1);
+ len = snprintf(fname, sizeof(fname), "%s_changeresource", rtype->_name);
+ if (len > 0 && (size_t)len < sizeof(fname)) {
+ lua_getglobal(L, fname);
+ if (lua_isfunction(L, -1)) {
+ tolua_pushusertype(L, u, TOLUA_CAST "unit");
+ lua_pushinteger(L, delta);
+
+ if (lua_pcall(L, 2, 1, 0) != 0) {
+ const char *error = lua_tostring(L, -1);
+ log_error("change(%s) calling '%s': %s.\n", unitname(u), fname, error);
+ lua_pop(L, 1);
+ }
+ else {
+ result = (int)lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
}
else {
- result = (int)lua_tonumber(L, -1);
+ log_error("change(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
}
}
- else {
- log_error("change(%s) calling '%s': not a function.\n", unitname(u), fname);
- lua_pop(L, 1);
- }
-
return result;
}
@@ -250,13 +247,12 @@ static int
use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
{
lua_State *L = (lua_State *)global.vm_state;
- int result = 0;
+ int len, result = 0;
char fname[64];
int (*callout)(unit *, const item_type *, int, struct order *);
- strlcpy(fname, "use_", sizeof(fname));
- strlcat(fname, itype->rtype->_name, sizeof(fname));
-
+ len = snprintf(fname, sizeof(fname), "use_%s", itype->rtype->_name);
+ if (len > 0 && (size_t)len < sizeof(fname)) {
callout = (int(*)(unit *, const item_type *, int, struct order *))get_function(fname);
if (callout) {
return callout(u, itype, amount, ord);
@@ -286,7 +282,7 @@ use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
log_error("no such callout: %s", fname);
}
log_error("use(%s) calling '%s': not a function.\n", unitname(u), fname);
-
+ }
return result;
}
diff --git a/src/kernel/alliance.c b/src/kernel/alliance.c
index f0cdf3bbd..ba3929f1f 100644
--- a/src/kernel/alliance.c
+++ b/src/kernel/alliance.c
@@ -28,7 +28,6 @@ without prior permission by the authors of Eressea.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -40,6 +39,7 @@ without prior permission by the authors of Eressea.
#include
#include
#include
+#include
alliance *alliances = NULL;
@@ -422,7 +422,7 @@ const char *alliancename(const alliance * al)
char *ibuf = idbuf[(++nextbuf) % 8];
if (al && al->name) {
- slprintf(ibuf, sizeof(idbuf[0]), "%s (%s)", al->name, itoa36(al->id));
+ snprintf(ibuf, sizeof(idbuf[0]), "%s (%s)", al->name, itoa36(al->id));
}
else {
return NULL;
diff --git a/src/kernel/building.c b/src/kernel/building.c
index ea01fe665..26d261e97 100644
--- a/src/kernel/building.c
+++ b/src/kernel/building.c
@@ -38,7 +38,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -54,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */
#include
#include
+#include
#include
#include
@@ -372,7 +372,7 @@ building *new_building(const struct building_type * btype, region * r,
bname = parameters[P_GEBAEUDE];
}
assert(bname);
- slprintf(buffer, sizeof(buffer), "%s %s", bname, itoa36(b->no));
+ snprintf(buffer, sizeof(buffer), "%s %s", bname, itoa36(b->no));
b->name = strdup(bname);
return b;
}
@@ -489,7 +489,7 @@ int bt_effsize(const building_type * btype, const building * b, int bsize)
const char *write_buildingname(const building * b, char *ibuf, size_t size)
{
- slprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no));
+ snprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no));
return ibuf;
}
diff --git a/src/kernel/connection.c b/src/kernel/connection.c
index b630429fe..2cae4ec8f 100644
--- a/src/kernel/connection.c
+++ b/src/kernel/connection.c
@@ -25,19 +25,21 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "unit.h"
#include
-#include
+#include
#include
#include
#include
-#include
#include
+#include
+#include
#include
/* libc includes */
#include
#include
#include
+#include
#include
int nextborder = 0;
@@ -514,8 +516,8 @@ static const char *b_nameroad(const connection * b, const region * r,
else {
int percent = MAX(1, 100 * local / r->terrain->max_road);
if (local) {
- slprintf(buffer, sizeof(buffer), LOC(f->locale, mkname("border",
- "a_road_percent")), percent);
+ const char *temp = LOC(f->locale, mkname("border", "a_road_percent"));
+ str_replace(buffer, sizeof(buffer), temp, "$percent", itoa10(percent));
}
else {
return LOC(f->locale, mkname("border", "a_road_connection"));
diff --git a/src/kernel/faction.c b/src/kernel/faction.c
index 8da74e80e..f0010ddce 100755
--- a/src/kernel/faction.c
+++ b/src/kernel/faction.c
@@ -39,7 +39,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -50,6 +49,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include
#include
#include
+#include
#include
#include
diff --git a/src/kernel/order.c b/src/kernel/order.c
index baf26f615..605f44be9 100644
--- a/src/kernel/order.c
+++ b/src/kernel/order.c
@@ -170,7 +170,7 @@ int stream_order(struct stream *out, const struct order *ord, const struct local
char obuf[1024];
swrite(" ", 1, 1, out);
if (escape) {
- text = escape_string(text, obuf, sizeof(obuf));
+ text = str_escape(text, obuf, sizeof(obuf));
}
swrite(text, 1, strlen(text), out);
}
diff --git a/src/kernel/orderdb.c b/src/kernel/orderdb.c
index d97c5fae3..b30131be4 100644
--- a/src/kernel/orderdb.c
+++ b/src/kernel/orderdb.c
@@ -6,6 +6,7 @@
#include
+#include
#include
#include
@@ -14,12 +15,15 @@ void odata_create(order_data **pdata, size_t len, const char *str)
order_data *data;
char *result;
+ assert(pdata);
data = malloc(sizeof(order_data) + len + 1);
data->_refcount = 1;
result = (char *)(data + 1);
data->_str = (len > 0) ? result : NULL;
- if (str) strcpy(result, str);
- if (pdata) *pdata = data;
+ if (str) {
+ strcpy(result, str);
+ }
+ *pdata = data;
}
void odata_release(order_data * od)
diff --git a/src/kernel/region.c b/src/kernel/region.c
index 91afaabd4..81e9e4285 100644
--- a/src/kernel/region.c
+++ b/src/kernel/region.c
@@ -124,7 +124,7 @@ const char *write_regionname(const region * r, const faction * f, char *buffer,
int nx = r->x, ny = r->y;
pnormalize(&nx, &ny, pl);
adjust_coordinates(f, &nx, &ny, pl);
- slprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny);
+ snprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny);
}
return buffer;
}
diff --git a/src/kernel/save.c b/src/kernel/save.c
index a044601aa..fe83f943a 100644
--- a/src/kernel/save.c
+++ b/src/kernel/save.c
@@ -1429,7 +1429,7 @@ int read_game(gamedata *data)
/* Burgen */
READ_INT(store, &p);
if (p > 0 && !r->land) {
- log_error("%s, uid=%d has %d buildings", regionname(r, NULL), r->uid, p);
+ log_error("%s, uid=%d has %d %s", regionname(r, NULL), r->uid, p, (p==1) ? "building" : "buildings");
}
bp = &r->buildings;
@@ -1569,14 +1569,12 @@ int writegame(const char *filename)
create_directories();
join_path(datapath(), filename, path, sizeof(path));
-#ifdef HAVE_UNISTD_H
/* make sure we don't overwrite an existing file (hard links) */
- if (remove(path)!=0) {
- if (errno==ENOENT) {
+ if (remove(path) != 0) {
+ if (errno == ENOENT) {
errno = 0;
}
}
-#endif
F = fopen(path, "wb");
if (!F) {
perror(path);
diff --git a/src/kernel/ship.c b/src/kernel/ship.c
index a55eada2e..88eb5c39f 100644
--- a/src/kernel/ship.c
+++ b/src/kernel/ship.c
@@ -36,7 +36,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -217,7 +216,7 @@ ship *new_ship(const ship_type * stype, region * r, const struct locale *lang)
sname = parameters[P_SHIP];
}
assert(sname);
- slprintf(buffer, sizeof(buffer), "%s %s", sname, itoa36(sh->no));
+ snprintf(buffer, sizeof(buffer), "%s %s", sname, itoa36(sh->no));
sh->name = strdup(buffer);
shash(sh);
if (r) {
@@ -283,7 +282,7 @@ void free_ships(void)
const char *write_shipname(const ship * sh, char *ibuf, size_t size)
{
- slprintf(ibuf, size, "%s (%s)", sh->name, itoa36(sh->no));
+ snprintf(ibuf, size, "%s (%s)", sh->name, itoa36(sh->no));
return ibuf;
}
diff --git a/src/kernel/unit.c b/src/kernel/unit.c
index ee4da958c..87ccd5944 100644
--- a/src/kernel/unit.c
+++ b/src/kernel/unit.c
@@ -51,7 +51,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -1458,9 +1457,7 @@ void default_name(const unit *u, char name[], int len) {
else {
result = parameters[P_UNIT];
}
- strlcpy(name, result, len);
- strlcat(name, " ", len);
- strlcat(name, itoa36(u->no), len);
+ snprintf(name, len, "%s %s", result, itoa36(u->no));
}
void name_unit(unit * u)
@@ -1874,7 +1871,7 @@ static int nextbuf = 0;
char *write_unitname(const unit * u, char *buffer, size_t size)
{
const char * name = unit_getname(u);
- slprintf(buffer, size, "%s (%s)", name, itoa36(u->no));
+ snprintf(buffer, size, "%s (%s)", name, itoa36(u->no));
buffer[size - 1] = 0;
return buffer;
}
diff --git a/src/laws.c b/src/laws.c
index f03f76730..873dc470f 100644
--- a/src/laws.c
+++ b/src/laws.c
@@ -90,6 +90,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include
#include
#include
+#include
#include
#include
diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c
index 1e877459e..a574f2dfb 100644
--- a/src/modules/autoseed.c
+++ b/src/modules/autoseed.c
@@ -33,7 +33,6 @@
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -166,9 +165,7 @@ newfaction *read_newfactions(const char *filename)
break;
}
if (password[0] == '\0') {
- size_t sz;
- sz = strlcpy(password, itoa36(rng_int()), sizeof(password));
- sz += strlcat(password, itoa36(rng_int()), sizeof(password));
+ snprintf(password, sizeof(password), "%s%s", itoa36(rng_int()), itoa36(rng_int()));
}
for (f = factions; f; f = f->next) {
if (strcmp(faction_getemail(f), email) == 0 && f->age < MINAGE_MULTI) {
diff --git a/src/modules/score.c b/src/modules/score.c
index efb3465d4..202fc77b7 100644
--- a/src/modules/score.c
+++ b/src/modules/score.c
@@ -34,7 +34,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
-#include
#include
/* libc includes */
@@ -237,5 +236,5 @@ int default_score(const item_type *itype) {
}
void write_score(char *buffer, size_t size, score_t score) {
- slprintf(buffer, size, "%lld", score);
+ snprintf(buffer, size, "%lld", score);
}
diff --git a/src/monsters.c b/src/monsters.c
index 3b02b2be2..a17d9f1fa 100644
--- a/src/monsters.c
+++ b/src/monsters.c
@@ -82,7 +82,7 @@ static double attack_chance; /* rules.monsters.attack_chance, or default 0.4 */
static void give_peasants(unit *u, const item_type *itype, int reduce) {
char buf[64];
- slprintf(buf, sizeof(buf), "%s 0 %d %s", LOC(u->faction->locale, keyword(K_GIVE)), reduce, LOC(u->faction->locale, itype->rtype->_name));
+ snprintf(buf, sizeof(buf), "%s 0 %d %s", LOC(u->faction->locale, keyword(K_GIVE)), reduce, LOC(u->faction->locale, itype->rtype->_name));
unit_addorder(u, parse_order(buf, u->faction->locale));
}
diff --git a/src/move.c b/src/move.c
index 798c3da27..69a84c2cd 100644
--- a/src/move.c
+++ b/src/move.c
@@ -78,6 +78,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include
#include
#include
+#include
#include
@@ -1042,15 +1043,6 @@ int movewhere(const unit * u, const char *token, region * r, region ** resultp)
return E_MOVE_OK;
}
-static const char *shortdirections[MAXDIRECTIONS] = {
- "dir_nw",
- "dir_ne",
- "dir_east",
- "dir_se",
- "dir_sw",
- "dir_west"
-};
-
static void cycle_route(order * ord, unit * u, int gereist)
{
int cm = 0;
@@ -1063,13 +1055,11 @@ static void cycle_route(order * ord, unit * u, int gereist)
order *norder;
size_t size = sizeof(tail) - 1;
- if (getkeyword(ord) != K_ROUTE)
- return;
+ assert(getkeyword(ord) == K_ROUTE);
tail[0] = '\0';
+ neworder[0] = '\0';
+ init_order(ord, u->faction->locale);
- init_order_depr(ord);
-
- neworder[0] = 0;
for (cm = 0;; ++cm) {
const char *s;
const struct locale *lang = u->faction->locale;
@@ -1092,6 +1082,7 @@ static void cycle_route(order * ord, unit * u, int gereist)
assert(!pause);
if (!pause) {
const char *loc = LOC(lang, shortdirections[d]);
+ assert(loc);
if (bufp != tail) {
bufp = STRLCPY_EX(bufp, " ", &size, "cycle_route");
}
@@ -1371,7 +1362,7 @@ static void make_route(unit * u, order * ord, region_list ** routep)
current = next;
s = gettoken(token, sizeof(token));
error = movewhere(u, s, current, &next);
- if (error) {
+ if (error != E_MOVE_OK) {
message *msg = movement_error(u, s, ord, error);
if (msg != NULL) {
add_message(&u->faction->msgs, msg);
@@ -1606,7 +1597,9 @@ static const region_list *travel_route(unit * u,
int walkmode;
setguard(u, false);
- cycle_route(ord, u, steps);
+ if (getkeyword(ord) == K_ROUTE) {
+ cycle_route(ord, u, steps);
+ }
if (mode == TRAVEL_RUNNING) {
walkmode = 0;
@@ -1936,7 +1929,9 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting)
unit *harbourmaster;
/* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten
* transferiert wurden, kann der aktuelle Befehl gelöscht werden. */
- cycle_route(ord, u, step);
+ if (getkeyword(ord) == K_ROUTE) {
+ cycle_route(ord, u, step);
+ }
set_order(&u->thisorder, NULL);
set_coast(sh, last_point, current_point);
@@ -2026,7 +2021,7 @@ static const region_list *travel_i(unit * u, const region_list * route_begin,
region *r = u->region;
int mp;
if (u->building && !can_leave(u)) {
- cmistake(u, u->thisorder, 150, MSG_MOVE);
+ cmistake(u, ord, 150, MSG_MOVE);
return route_begin;
}
switch (canwalk(u)) {
@@ -2115,7 +2110,7 @@ static const region_list *travel_i(unit * u, const region_list * route_begin,
/** traveling without ships
* walking, flying or riding units use this function
*/
-static void travel(unit * u, region_list ** routep)
+static void travel(unit * u, order *ord, region_list ** routep)
{
region *r = u->region;
region_list *route_begin;
@@ -2129,7 +2124,7 @@ static void travel(unit * u, region_list ** routep)
ship *sh = u->ship;
if (!can_leave(u)) {
- cmistake(u, u->thisorder, 150, MSG_MOVE);
+ cmistake(u, ord, 150, MSG_MOVE);
return;
}
@@ -2142,28 +2137,28 @@ static void travel(unit * u, region_list ** routep)
if (sh) {
unit *guard = is_guarded(r, u);
if (guard) {
- ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder,
+ ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
"region_guarded", "guard", guard));
return;
}
}
if (u->ship && u_race(u)->flags & RCF_SWIM) {
- cmistake(u, u->thisorder, 143, MSG_MOVE);
+ cmistake(u, ord, 143, MSG_MOVE);
return;
}
}
else if (u->ship && fval(u->ship, SF_MOVED)) {
/* die Einheit ist auf einem Schiff, das sich bereits bewegt hat */
- cmistake(u, u->thisorder, 13, MSG_MOVE);
+ cmistake(u, ord, 13, MSG_MOVE);
return;
}
- make_route(u, u->thisorder, routep);
+ make_route(u, ord, routep);
route_begin = *routep;
if (route_begin) {
/* und ab die post: */
- travel_i(u, route_begin, NULL, u->thisorder, TRAVEL_NORMAL, &followers);
+ travel_i(u, route_begin, NULL, ord, TRAVEL_NORMAL, &followers);
/* followers */
while (followers != NULL) {
@@ -2204,7 +2199,7 @@ void move_cmd(unit * u, order * ord)
sail(u, ord, &route, drifting);
}
else {
- travel(u, &route);
+ travel(u, ord, &route);
}
fset(u, UFL_LONGACTION | UFL_NOTMOVING);
diff --git a/src/move.test.c b/src/move.test.c
index 7095da855..edb070bfb 100644
--- a/src/move.test.c
+++ b/src/move.test.c
@@ -545,6 +545,52 @@ static void test_movement_speed(CuTest *tc) {
test_cleanup();
}
+static void test_route_cycle(CuTest *tc) {
+ unit *u;
+ region *r;
+ struct locale *lang;
+ char buffer[32];
+
+ test_setup();
+ test_create_region(1, 0, NULL);
+ r = test_create_region(2, 0, NULL);
+ lang = test_create_locale();
+ CuAssertPtrNotNull(tc, LOC(lang, shortdirections[D_WEST]));
+ u = test_create_unit(test_create_faction(NULL), r);
+ u->faction->locale = lang;
+ CuAssertIntEquals(tc, RCF_WALK, u->_race->flags & RCF_WALK);
+ u->orders = create_order(K_ROUTE, u->faction->locale, "WEST EAST NW");
+ CuAssertStrEquals(tc, "route WEST EAST NW", get_command(u->orders, lang, buffer, sizeof(buffer)));
+ init_order(u->orders, u->faction->locale);
+ move_cmd(u, u->orders);
+ CuAssertIntEquals(tc, 1, u->region->x);
+ CuAssertStrEquals(tc, "route east nw west", get_command(u->orders, lang, buffer, sizeof(buffer)));
+ test_cleanup();
+}
+
+static void test_route_pause(CuTest *tc) {
+ unit *u;
+ region *r;
+ struct locale *lang;
+ char buffer[32];
+
+ test_setup();
+ test_create_region(1, 0, NULL);
+ r = test_create_region(2, 0, NULL);
+ lang = test_create_locale();
+ CuAssertPtrNotNull(tc, LOC(lang, shortdirections[D_WEST]));
+ u = test_create_unit(test_create_faction(NULL), r);
+ u->faction->locale = lang;
+ CuAssertIntEquals(tc, RCF_WALK, u->_race->flags & RCF_WALK);
+ u->orders = create_order(K_ROUTE, u->faction->locale, "PAUSE EAST NW");
+ CuAssertStrEquals(tc, "route PAUSE EAST NW", get_command(u->orders, lang, buffer, sizeof(buffer)));
+ init_order(u->orders, u->faction->locale);
+ move_cmd(u, u->orders);
+ CuAssertIntEquals(tc, 2, u->region->x);
+ CuAssertStrEquals(tc, "route PAUSE EAST NW", get_command(u->orders, lang, buffer, sizeof(buffer)));
+ test_cleanup();
+}
+
CuSuite *get_move_suite(void)
{
CuSuite *suite = CuSuiteNew();
@@ -570,5 +616,7 @@ CuSuite *get_move_suite(void)
SUITE_ADD_TEST(suite, test_ship_damage_overload);
SUITE_ADD_TEST(suite, test_follow_ship_msg);
SUITE_ADD_TEST(suite, test_drifting_ships);
+ SUITE_ADD_TEST(suite, test_route_cycle);
+ SUITE_ADD_TEST(suite, test_route_pause);
return suite;
}
diff --git a/src/names.c b/src/names.c
index ef2d58422..d85b91805 100644
--- a/src/names.c
+++ b/src/names.c
@@ -262,7 +262,7 @@ static void dragon_name(unit * u)
rnd = num_postfix / 6;
rnd = (rng_int() % rnd) + ter * rnd;
}
- sprintf(zText, "dragon_postfix_%d", rnd);
+ snprintf(zText, sizeof(zText), "dragon_postfix_%d", rnd);
str = locale_getstring(default_locale, zText);
assert(str != NULL);
@@ -271,28 +271,25 @@ static void dragon_name(unit * u)
const char *no_article = strchr((const char *)str, ' ');
assert(no_article);
/* TODO: localization */
- sprintf(name, "Die %sn von %s", no_article + 1, rname(u->region,
+ snprintf(name, sizeof(name), "Die %sn von %s", no_article + 1, rname(u->region,
default_locale));
}
else {
char n[32];
- size_t sz;
- sz = strlcpy(n, silbe1[rng_int() % SIL1], sizeof(n));
- sz += strlcat(n, silbe2[rng_int() % SIL2], sizeof(n));
- sz += strlcat(n, silbe3[rng_int() % SIL3], sizeof(n));
+ snprintf(n, sizeof(n), "%s%s%s", silbe1[rng_int() % SIL1], silbe2[rng_int() % SIL2], silbe3[rng_int() % SIL3]);
if (rng_int() % 5 > 2) {
sprintf(name, "%s, %s", n, str); /* "Name, der Titel" */
}
else {
- sz = strlcpy(name, (const char *)str, sizeof(name)); /* "Der Titel Name" */
+ if (rng_int() % 3 == 0) {
+ /* TODO: localization */
+ snprintf(name, sizeof(name), "%s %s von %s", n, str, rname(u->region, default_locale));
+ }
+ else {
+ snprintf(name, sizeof(name), "%s %s", n, str);
+ }
name[0] = (char)toupper(name[0]); /* TODO: UNICODE - should use towupper() */
- sz += strlcat(name, " ", sizeof(name));
- sz += strlcat(name, n, sizeof(name));
- }
- if (rng_int() % 3 == 0) {
- sz += strlcat(name, " von ", sizeof(name));
- sz += strlcat(name, (const char *)rname(u->region, default_locale), sizeof(name));
}
}
diff --git a/src/platform.h b/src/platform.h
index 9e2ecfadb..968aa3ec3 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -29,8 +29,8 @@
#endif
-#define _POSIX_C_SOURCE 200809L
-
+/* #define _POSIX_C_SOURCE 200809L
+*/
#ifndef MAX_PATH
# define MAX_PATH 4096
#endif
diff --git a/src/randenc.c b/src/randenc.c
index 48f7a5827..3e1ac3554 100644
--- a/src/randenc.c
+++ b/src/randenc.c
@@ -53,7 +53,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
-#include
#include
#include
#include
@@ -62,10 +61,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include
/* libc includes */
-#include
#include
#include
#include
+#include
#include
#include
@@ -234,9 +233,9 @@ void find_manual(region * r, unit * u)
break;
}
- slprintf(zLocation, sizeof(zLocation), "manual_location_%d",
+ snprintf(zLocation, sizeof(zLocation), "manual_location_%d",
(int)(rng_int() % 4));
- slprintf(zBook, sizeof(zLocation), "manual_title_%s", skillnames[skill]);
+ snprintf(zBook, sizeof(zLocation), "manual_title_%s", skillnames[skill]);
msg = msg_message("find_manual", "unit location book", u, zLocation, zBook);
if (msg) {
diff --git a/src/spells.c b/src/spells.c
index b25b933fd..a9fa12127 100644
--- a/src/spells.c
+++ b/src/spells.c
@@ -61,7 +61,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -4643,7 +4642,7 @@ int sp_clonecopy(castorder * co)
return 0;
}
- slprintf(name, sizeof(name), (const char *)LOC(mage->faction->locale,
+ snprintf(name, sizeof(name), (const char *)LOC(mage->faction->locale,
"clone_of"), unitname(mage));
clone =
create_unit(target_region, mage->faction, 1, get_race(RC_CLONE), 0, name,
diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c
index 8c139fb9c..688a389cb 100644
--- a/src/spells/combatspells.c
+++ b/src/spells/combatspells.c
@@ -1279,7 +1279,7 @@ int sp_appeasement(struct castorder * co)
}
/* und bewachen nicht */
setguard(mage, false);
- /* irgendwie den langen befehl sperren */
+ setstatus(mage, ST_FLEE);
/* wir tun so, als w�re die Person geflohen */
fi->flags |= FIG_NOLOOT;
diff --git a/src/tests.c b/src/tests.c
index d07124af3..70f006ef6 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -44,6 +44,7 @@ struct race *test_create_race(const char *name)
rc->maintenance = 10;
rc->hitpoints = 20;
rc->maxaura = 100;
+ rc->flags |= RCF_WALK;
rc->ec_flags |= ECF_GETITEM;
rc->battle_flags = BF_EQUIPMENT;
return rc;
@@ -120,6 +121,7 @@ struct locale * test_create_locale(void) {
locale_setstring(loc, alliance_kwd[i], alliance_kwd[i]);
}
for (i = 0; i != MAXDIRECTIONS; ++i) {
+ locale_setstring(loc, shortdirections[i], shortdirections[i] + 4);
locale_setstring(loc, directions[i], directions[i]);
init_direction(loc, i, directions[i]);
init_direction(loc, i, coasts[i] + 7);
diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
index 91ed118ae..d021ada72 100644
--- a/src/util/CMakeLists.txt
+++ b/src/util/CMakeLists.txt
@@ -22,7 +22,6 @@ password.test.c
# resolve.test.c
rng.test.c
strings.test.c
-bsdstring.test.c
functions.test.c
log.test.c
# translation.test.c
@@ -60,6 +59,7 @@ unicode.c
variant.c
xml.c
)
+
FOREACH(_FILE ${_FILES})
LIST(APPEND _SOURCES ${PROJECT_NAME}/${_FILE})
ENDFOREACH(_FILE)
diff --git a/src/util/base36.c b/src/util/base36.c
index 221ece870..3ded21a54 100644
--- a/src/util/base36.c
+++ b/src/util/base36.c
@@ -52,16 +52,13 @@ int atoi36(const char *str)
return i * sign;
}
-const char *itoab(int i, int base)
+const char *itoab_r(int i, int base, char *s, size_t len)
{
- static char sstr[80];
- char *s, *dst;
- static int index = 0; /* STATIC_XCALL: used across calls */
+ char *dst;
- s = sstr + (index * 20);
- index = (index + 1) & 3; /* quick for % 4 */
- dst = s + 19;
- (*dst--) = 0;
+ assert(len > 2);
+ dst = s + len - 2;
+ *dst = 0;
if (i != 0) {
int neg = 0;
@@ -101,6 +98,18 @@ const char *itoab(int i, int base)
return dst;
}
+const char *itoab(int i, int base)
+{
+ static char sstr[80];
+ char *s;
+ static int index = 0; /* STATIC_XCALL: used across calls */
+
+ s = sstr + (index * 20);
+ index = (index + 1) & 3; /* quick for % 4 */
+
+ return itoab_r(i, base, s, 20);
+}
+
const char *itoa36(int i)
{
return itoab(i, 36);
diff --git a/src/util/base36.h b/src/util/base36.h
index 650538219..804952ab7 100644
--- a/src/util/base36.h
+++ b/src/util/base36.h
@@ -18,15 +18,19 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef H_UTIL_BASE36
#define H_UTIL_BASE36
+
+#include
+
#ifdef __cplusplus
extern "C" {
#endif
+ const char *itoab_r(int i, int base, char *result, size_t len);
+ const char *itoab(int i, int base);
+ const char *itoa36(int i);
+ const char *itoa10(int i);
extern int atoi36(const char *s);
- extern const char *itoab(int i, int base);
- extern const char *itoa36(int i);
- extern const char *itoa10(int i);
- extern int i10toi36(int i);
+ int i10toi36(int i);
#ifdef __cplusplus
}
diff --git a/src/util/bsdstring.c b/src/util/bsdstring.c
index 4aa779495..f4499465b 100644
--- a/src/util/bsdstring.c
+++ b/src/util/bsdstring.c
@@ -1,9 +1,7 @@
#include
-#include
#include
#include
#include
-#include
#include
#include "bsdstring.h"
@@ -35,8 +33,7 @@ int wrptr(char **ptr, size_t * size, int result)
return ERANGE;
}
-#ifndef HAVE_STRLCPY
-#define HAVE_STRLCPY
+#ifndef HAVE_BSDSTRING
size_t strlcpy(char *dst, const char *src, size_t siz)
{ /* copied from OpenBSD source code */
register char *d = dst;
@@ -61,25 +58,7 @@ size_t strlcpy(char *dst, const char *src, size_t siz)
return (s - src - 1); /* count does not include NUL */
}
-#endif
-char * strlcpy_w(char *dst, const char *src, size_t *siz, const char *err, const char *file, int line)
-{
- size_t bytes = strlcpy(dst, src, *siz);
- char * buf = dst;
- assert(bytes <= INT_MAX);
- if (wrptr(&buf, siz, (int)bytes) != 0) {
- if (err) {
- log_warning("%s: static buffer too small in %s:%d\n", err, file, line);
- } else {
- log_warning("static buffer too small in %s:%d\n", file, line);
- }
- }
- return buf;
-}
-
-#ifndef HAVE_STRLCAT
-#define HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t siz)
{
register char *d = dst;
@@ -108,21 +87,17 @@ size_t strlcat(char *dst, const char *src, size_t siz)
}
#endif
-#ifndef HAVE_SLPRINTF
-#define HAVE_SLPRINTF
-size_t slprintf(char * dst, size_t size, const char * format, ...)
+char * strlcpy_w(char *dst, const char *src, size_t *siz, const char *err, const char *file, int line)
{
- va_list args;
- int result;
-
- va_start(args, format);
- result = vsnprintf(dst, size, format, args);
- va_end(args);
- if (result < 0 || result >= (int)size) {
- dst[size - 1] = '\0';
- return size;
+ size_t bytes = strlcpy(dst, src, *siz);
+ char * buf = dst;
+ assert(bytes <= INT_MAX);
+ if (wrptr(&buf, siz, (int)bytes) != 0) {
+ if (err) {
+ log_warning("%s: static buffer too small in %s:%d\n", err, file, line);
+ } else {
+ log_warning("static buffer too small in %s:%d\n", file, line);
+ }
}
-
- return (size_t)result;
+ return buf;
}
-#endif
diff --git a/src/util/bsdstring.h b/src/util/bsdstring.h
index dad4d6281..77c1b94ed 100644
--- a/src/util/bsdstring.h
+++ b/src/util/bsdstring.h
@@ -2,20 +2,16 @@
#define UTIL_BSDSTRING_H
#include
-int wrptr(char **ptr, size_t * size, int bytes);
-#ifndef HAVE_STRLCPY
+#ifndef HAVE_BSDSTRING
size_t strlcpy(char *dst, const char *src, size_t siz);
-#endif
-char * strlcpy_w(char *dst, const char *src, size_t *siz, const char *err, const char *file, int line);
-
-#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t siz);
+#else
+#include
#endif
-#ifndef HAVE_SLPRINTF
-size_t slprintf(char * dst, size_t size, const char * format, ...);
-#endif
+int wrptr(char **ptr, size_t * size, int bytes);
+char * strlcpy_w(char *dst, const char *src, size_t *siz, const char *err, const char *file, int line);
#define WARN_STATIC_BUFFER_EX(foo) log_warning("%s: static buffer too small in %s:%d\n", (foo), __FILE__, __LINE__)
#define WARN_STATIC_BUFFER() log_warning("static buffer too small in %s:%d\n", __FILE__, __LINE__)
diff --git a/src/util/bsdstring.test.c b/src/util/bsdstring.test.c
index d4276ef61..61453f893 100644
--- a/src/util/bsdstring.test.c
+++ b/src/util/bsdstring.test.c
@@ -42,29 +42,10 @@ static void test_strlcpy(CuTest * tc)
errno = 0;
}
-static void test_slprintf(CuTest * tc)
-{
- char buffer[32];
-
- memset(buffer, 0x7f, sizeof(buffer));
-
- CuAssertTrue(tc, slprintf(buffer, 4, "%s", "herpderp") > 3);
- CuAssertStrEquals(tc, "her", buffer);
-
- CuAssertIntEquals(tc, 4, (int)slprintf(buffer, 8, "%s", "herp"));
- CuAssertStrEquals(tc, "herp", buffer);
- CuAssertIntEquals(tc, 0x7f, buffer[5]);
-
- CuAssertIntEquals(tc, 8, (int)slprintf(buffer, 8, "%s", "herpderp"));
- CuAssertStrEquals(tc, "herpder", buffer);
- CuAssertIntEquals(tc, 0x7f, buffer[8]);
-}
-
CuSuite *get_bsdstring_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_strlcat);
SUITE_ADD_TEST(suite, test_strlcpy);
- SUITE_ADD_TEST(suite, test_slprintf);
return suite;
}
diff --git a/src/util/language.c b/src/util/language.c
index a1cda4d2f..8cd6188d2 100644
--- a/src/util/language.c
+++ b/src/util/language.c
@@ -56,7 +56,7 @@ unsigned int locale_index(const locale * lang)
locale *get_locale(const char *name)
{
- unsigned int hkey = hashstring(name);
+ unsigned int hkey = str_hash(name);
locale *l = locales;
while (l && l->hashkey != hkey)
l = l->next;
@@ -68,7 +68,7 @@ static unsigned int nextlocaleindex = 0;
locale *get_or_create_locale(const char *name)
{
locale *l;
- unsigned int hkey = hashstring(name);
+ unsigned int hkey = str_hash(name);
locale **lp = &locales;
if (!locales) {
@@ -120,7 +120,7 @@ void make_locales(const char *str)
const char *locale_getstring(const locale * lang, const char *key)
{
- unsigned int hkey = hashstring(key);
+ unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1);
const struct locale_str *find;
@@ -150,7 +150,7 @@ const char *locale_string(const locale * lang, const char *key, bool warn)
assert(key);
if (key != NULL) {
- unsigned int hkey = hashstring(key);
+ unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1);
struct locale_str *find;
@@ -188,7 +188,7 @@ const char *locale_string(const locale * lang, const char *key, bool warn)
void locale_setstring(locale * lang, const char *key, const char *value)
{
- unsigned int hkey = hashstring(key);
+ unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1);
struct locale_str *find;
if (!lang) {
diff --git a/src/util/message.c b/src/util/message.c
index e53010093..239863bd1 100644
--- a/src/util/message.c
+++ b/src/util/message.c
@@ -192,7 +192,7 @@ void mt_clear(void) {
const message_type *mt_find(const char *name)
{
- unsigned int hash = hashstring(name) % MT_MAXHASH;
+ unsigned int hash = str_hash(name) % MT_MAXHASH;
selist *ql = messagetypes[hash];
int qi;
@@ -218,7 +218,7 @@ static unsigned int mt_id(const message_type * mtype)
const message_type *mt_register(message_type * type)
{
- unsigned int hash = hashstring(type->name) % MT_MAXHASH;
+ unsigned int hash = str_hash(type->name) % MT_MAXHASH;
selist **qlp = messagetypes + hash;
if (selist_set_insert(qlp, type, NULL)) {
diff --git a/src/util/strings.c b/src/util/strings.c
index 4e7e17aa4..a63a694ce 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -22,10 +22,28 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "assert.h"
/* libc includes */
+#include
+#include
#include
#include
#include
+size_t str_slprintf(char * dst, size_t size, const char * format, ...)
+{
+ va_list args;
+ int result;
+
+ va_start(args, format);
+ result = vsnprintf(dst, size, format, args);
+ va_end(args);
+ if (result < 0 || result >= (int)size) {
+ dst[size - 1] = '\0';
+ return size;
+ }
+
+ return (size_t)result;
+}
+
char *set_string(char **s, const char *neu)
{
if (neu == NULL) {
@@ -45,7 +63,40 @@ char *set_string(char **s, const char *neu)
return *s;
}
-unsigned int hashstring(const char *s)
+void str_replace(char *buffer, size_t size, const char *tmpl, const char *var, const char *value)
+{
+ size_t val_len = strlen(value);
+ size_t var_len = strlen(var);
+ char *s = buffer;
+ while (buffer + size > s) {
+ char *p = strstr(tmpl, var);
+ size_t len;
+ if (p) {
+ len = p - tmpl;
+ }
+ else {
+ len = strlen(tmpl);
+ }
+ if (len < size) {
+ memmove(s, tmpl, len);
+ tmpl += len;
+ s += len;
+ size -= len;
+ if (p && val_len < size) {
+ tmpl += var_len;
+ memmove(s, value, val_len);
+ s += val_len;
+ size -= val_len;
+ }
+ }
+ if (!p) {
+ break;
+ }
+ }
+ *s = 0;
+}
+
+unsigned int str_hash(const char *s)
{
unsigned int key = 0;
assert(s);
@@ -55,7 +106,7 @@ unsigned int hashstring(const char *s)
return key & 0x7FFFFFFF;
}
-const char *escape_string(const char *str, char *buffer,
+const char *str_escape(const char *str, char *buffer,
size_t len)
{
const char *start = strchr(str, '\"');
diff --git a/src/util/strings.h b/src/util/strings.h
index 05a435e2c..9add04e23 100644
--- a/src/util/strings.h
+++ b/src/util/strings.h
@@ -25,9 +25,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" {
#endif
+ void str_replace(char *buffer, size_t size, const char *tmpl, const char *var, const char *value);
+ const char *str_escape(const char *str, char *buffer, size_t len);
char *set_string(char **s, const char *neu);
- unsigned int hashstring(const char *s);
- const char *escape_string(const char *str, char *buffer, size_t len);
+ unsigned int str_hash(const char *s);
+ size_t str_slprintf(char * dst, size_t size, const char * format, ...);
+
unsigned int jenkins_hash(unsigned int a);
unsigned int wang_hash(unsigned int a);
@@ -48,6 +51,7 @@ extern "C" {
#define HASH1 JENKINS_HASH1
#define HASH2 JENKINS_HASH2
+#define slprintf str_slprintf
#ifdef __cplusplus
}
diff --git a/src/util/strings.test.c b/src/util/strings.test.c
index bcee29e47..14d62200a 100644
--- a/src/util/strings.test.c
+++ b/src/util/strings.test.c
@@ -4,21 +4,55 @@
#include
#include "strings.h"
-static void test_escape_string(CuTest * tc)
+static void test_str_escape(CuTest * tc)
{
char scratch[64];
- CuAssertStrEquals(tc, "12345678901234567890", escape_string("12345678901234567890", scratch, 16));
- CuAssertStrEquals(tc, "123456789\\\"12345", escape_string("123456789\"1234567890", scratch, 16));
- CuAssertStrEquals(tc, "1234567890123456", escape_string("1234567890123456\"890", scratch, 16));
- CuAssertStrEquals(tc, "hello world", escape_string("hello world", scratch, sizeof(scratch)));
- CuAssertStrEquals(tc, "hello \\\"world\\\"", escape_string("hello \"world\"", scratch, sizeof(scratch)));
- CuAssertStrEquals(tc, "\\\"\\\\", escape_string("\"\\", scratch, sizeof(scratch)));
- CuAssertStrEquals(tc, "\\\\", escape_string("\\", scratch, sizeof(scratch)));
+ CuAssertStrEquals(tc, "12345678901234567890", str_escape("12345678901234567890", scratch, 16));
+ CuAssertStrEquals(tc, "123456789\\\"12345", str_escape("123456789\"1234567890", scratch, 16));
+ CuAssertStrEquals(tc, "1234567890123456", str_escape("1234567890123456\"890", scratch, 16));
+ CuAssertStrEquals(tc, "hello world", str_escape("hello world", scratch, sizeof(scratch)));
+ CuAssertStrEquals(tc, "hello \\\"world\\\"", str_escape("hello \"world\"", scratch, sizeof(scratch)));
+ CuAssertStrEquals(tc, "\\\"\\\\", str_escape("\"\\", scratch, sizeof(scratch)));
+ CuAssertStrEquals(tc, "\\\\", str_escape("\\", scratch, sizeof(scratch)));
+}
+
+static void test_str_replace(CuTest * tc)
+{
+ char result[64];
+ str_replace(result, sizeof(result), "Hello $who!", "$who", "World");
+ CuAssertStrEquals(tc, "Hello World!", result);
+}
+
+static void test_str_hash(CuTest * tc)
+{
+ CuAssertIntEquals(tc, 0, str_hash(""));
+ CuAssertIntEquals(tc, 140703196, str_hash("Hodor"));
+}
+
+static void test_str_slprintf(CuTest * tc)
+{
+ char buffer[32];
+
+ memset(buffer, 0x7f, sizeof(buffer));
+
+ CuAssertTrue(tc, slprintf(buffer, 4, "%s", "herpderp") > 3);
+ CuAssertStrEquals(tc, "her", buffer);
+
+ CuAssertIntEquals(tc, 4, (int)str_slprintf(buffer, 8, "%s", "herp"));
+ CuAssertStrEquals(tc, "herp", buffer);
+ CuAssertIntEquals(tc, 0x7f, buffer[5]);
+
+ CuAssertIntEquals(tc, 8, (int)str_slprintf(buffer, 8, "%s", "herpderp"));
+ CuAssertStrEquals(tc, "herpder", buffer);
+ CuAssertIntEquals(tc, 0x7f, buffer[8]);
}
CuSuite *get_strings_suite(void)
{
CuSuite *suite = CuSuiteNew();
- SUITE_ADD_TEST(suite, test_escape_string);
+ SUITE_ADD_TEST(suite, test_str_hash);
+ SUITE_ADD_TEST(suite, test_str_escape);
+ SUITE_ADD_TEST(suite, test_str_replace);
+ SUITE_ADD_TEST(suite, test_str_slprintf);
return suite;
}