Merge pull request #747 from ennorehling/develop

latest changes from the 3.15 roadmap
This commit is contained in:
Enno Rehling 2017-12-15 17:27:24 +01:00 committed by GitHub
commit ba87b12fce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 574 additions and 280 deletions

View File

@ -11,6 +11,10 @@ if (MSVC)
include(MSVC) include(MSVC)
endif (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 (SQLite3)
find_package (BerkeleyDB) find_package (BerkeleyDB)
find_package (Curses) find_package (Curses)

View File

@ -7337,8 +7337,8 @@
</string> </string>
<string name="a_road_percent"> <string name="a_road_percent">
<text locale="de">eine zu %d%% vollendete Straße</text> <text locale="de">eine zu $percent%% vollendete Straße</text>
<text locale="en">a road that is %d%% complete</text> <text locale="en">a road that is $percent% complete</text>
</string> </string>
<string name="a_road_connection"> <string name="a_road_connection">

View File

@ -33,4 +33,5 @@
<entry spell="big_recruit" level="14" /> <entry spell="big_recruit" level="14" />
<entry spell="calm_riot" level="14" /> <entry spell="calm_riot" level="14" />
<entry spell="incite_riot" level="15" /> <entry spell="incite_riot" level="15" />
<entry spell="summon_familiar" level="9" />
</spellbook> </spellbook>

View File

@ -34,7 +34,6 @@
<entry spell="fish_shield" level="8" /> <entry spell="fish_shield" level="8" />
<entry spell="armor_shield" level="12" /> <entry spell="armor_shield" level="12" />
<entry spell="living_rock" level="13" /> <entry spell="living_rock" level="13" />
<entry spell="summon_familiar" level="9" />
<entry spell="draigfumbleshield" level="9" /> <entry spell="draigfumbleshield" level="9" />
<entry spell="gwyrrdfumbleshield" level="5" /> <entry spell="gwyrrdfumbleshield" level="5" />
<entry spell="cerddorfumbleshield" level="5" /> <entry spell="cerddorfumbleshield" level="5" />

View File

@ -29,4 +29,5 @@
<entry spell="summondragon" level="11" /> <entry spell="summondragon" level="11" />
<entry spell="summonshadowlords" level="12" /> <entry spell="summonshadowlords" level="12" />
<entry spell="unholypower" level="14" /> <entry spell="unholypower" level="14" />
<entry spell="summon_familiar" level="9" />
</spellbook> </spellbook>

View File

@ -127,7 +127,6 @@
<entry spell="strongwall" level="8" /> <entry spell="strongwall" level="8" />
<entry spell="summondragon" level="11" /> <entry spell="summondragon" level="11" />
<entry spell="summonent" level="10" /> <entry spell="summonent" level="10" />
<entry spell="summon_familiar" level="9" />
<entry spell="summonfireelemental" level="13" /> <entry spell="summonfireelemental" level="13" />
<entry spell="summonshadow" level="8" /> <entry spell="summonshadow" level="8" />
<entry spell="summonshadowlords" level="12" /> <entry spell="summonshadowlords" level="12" />

View File

@ -30,4 +30,5 @@
<entry spell="summonfireelemental" level="13" /> <entry spell="summonfireelemental" level="13" />
<entry spell="maelstrom" level="15" /> <entry spell="maelstrom" level="15" />
<entry spell="rustweapon" level="3" /> <entry spell="rustweapon" level="3" />
<entry spell="summon_familiar" level="9" />
</spellbook> </spellbook>

View File

@ -30,4 +30,5 @@
<entry spell="bad_dreams" level="10" /> <entry spell="bad_dreams" level="10" />
<entry spell="mindblast" level="11" /> <entry spell="mindblast" level="11" />
<entry spell="create_dreameye" level="14" /> <entry spell="create_dreameye" level="14" />
<entry spell="summon_familiar" level="9" />
</spellbook> </spellbook>

View File

@ -1112,3 +1112,51 @@ function test_build_castle()
assert_equal(1, u.building.size) assert_equal(1, u.building.size)
assert_equal(u.building.name, "Burg") assert_equal(u.building.name, "Burg")
end 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

View File

@ -1,3 +1,4 @@
require 'tests.e2.insects'
require 'tests.e2.spells' require 'tests.e2.spells'
require 'tests.e2.buildings' require 'tests.e2.buildings'
require 'tests.e2.production' require 'tests.e2.production'

View File

@ -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

View File

@ -81,7 +81,7 @@ function test_create_dreameye()
assert_equal(amax - 5, u.aura_max) assert_equal(amax - 5, u.aura_max)
end end
function test_appeasement() function test_appeasement_can_move()
local u1, u2, r1, r2, uno local u1, u2, r1, r2, uno
r1 = region.create(0, 0, 'plain') r1 = region.create(0, 0, 'plain')
r2 = region.create(1, 0, 'plain') r2 = region.create(1, 0, 'plain')
@ -102,4 +102,32 @@ function test_appeasement()
u2 = get_unit(uno) u2 = get_unit(uno)
assert_not_nil(u2) assert_not_nil(u2)
assert_equal(r2, u2.region) 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 end

View File

@ -266,6 +266,14 @@ add_test(server test_eressea)
install(TARGETS eressea DESTINATION "bin") 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) if (DB_FOUND)
include_directories (${DB_INCLUDE_DIR}) include_directories (${DB_INCLUDE_DIR})
target_link_libraries(convert ${DB_LIBRARIES}) target_link_libraries(convert ${DB_LIBRARIES})

View File

@ -69,6 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/lists.h> #include <util/lists.h>
#include <util/log.h> #include <util/log.h>
#include <util/parser.h> #include <util/parser.h>
#include <util/strings.h>
#include <selist.h> #include <selist.h>
#include <util/rand.h> #include <util/rand.h>
#include <util/rng.h> #include <util/rng.h>
@ -1643,7 +1644,6 @@ static castorder * create_castorder_combat(castorder *co, fighter *fig, const sp
return co; return co;
} }
#ifdef FFL_CURSED
static void summon_igjarjuk(battle *b, spellrank spellranks[]) { static void summon_igjarjuk(battle *b, spellrank spellranks[]) {
side *s; side *s;
castorder *co; castorder *co;
@ -1681,7 +1681,6 @@ static void summon_igjarjuk(battle *b, spellrank spellranks[]) {
} }
} }
} }
#endif
void do_combatmagic(battle * b, combatmagic_t was) 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)); memset(spellranks, 0, sizeof(spellranks));
#ifdef FFL_CURSED
if (was == DO_PRECOMBATSPELL) { if (was == DO_PRECOMBATSPELL) {
summon_igjarjuk(b, spellranks); summon_igjarjuk(b, spellranks);
} }
#endif
for (s = b->sides; s != b->sides + b->nsides; ++s) { for (s = b->sides; s != b->sides + b->nsides; ++s) {
fighter *fig; fighter *fig;
for (fig = s->fighters; fig; fig = fig->next) { 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) { for (df = s->fighters; df; df = df->next) {
if (is_attacker(df)) { if (is_attacker(df)) {
if (first) { if (first) {
bufp = STRLCPY(bufp, ", ", size); strlcpy(bufp, ", ", size);
} }
if (lastf) { if (lastf) {
bufp = STRLCPY(bufp, lastf, size); strlcpy(bufp, lastf, size);
first = true; first = true;
} }
if (seematrix(f, s)) if (seematrix(f, s))
@ -3579,7 +3576,7 @@ static int battle_report(battle * b)
if (komma) { if (komma) {
bufp = STRLCPY(bufp, ", ", size); bufp = STRLCPY(bufp, ", ", size);
} }
slprintf(buffer, sizeof(buffer), "%s %2d(%s): ", snprintf(buffer, sizeof(buffer), "%s %2d(%s): ",
loc_army, army_index(s), abbrev); loc_army, army_index(s), abbrev);
bufp = STRLCPY(bufp, buffer, size); bufp = STRLCPY(bufp, buffer, size);

View File

@ -718,6 +718,30 @@ static int tolua_unit_set_region(lua_State * L)
return 0; 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) static int tolua_unit_add_order(lua_State * L)
{ {
unit *self = (unit *)tolua_tousertype(L, 1, 0); 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 "weight", tolua_unit_get_weight, 0);
tolua_variable(L, TOLUA_CAST "capacity", tolua_unit_get_capacity, 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 "add_order", tolua_unit_add_order);
tolua_function(L, TOLUA_CAST "clear_orders", tolua_unit_clear_orders); tolua_function(L, TOLUA_CAST "clear_orders", tolua_unit_clear_orders);
tolua_function(L, TOLUA_CAST "get_curse", tolua_unit_get_curse); tolua_function(L, TOLUA_CAST "get_curse", tolua_unit_get_curse);

View File

@ -516,7 +516,7 @@ static void report_crtypes(FILE * F, const struct locale *lang)
assert(hash > 0); assert(hash > 0);
fprintf(F, "MESSAGETYPE %u\n", hash); fprintf(F, "MESSAGETYPE %u\n", hash);
fputc('\"', F); 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); fputs("\";text\n", F);
fprintf(F, "\"%s\";section\n", nrt_section(nrt)); 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 = const char *name =
translate(mkname("spell", sp->sname), spell_name(sp, lang)); 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, "\"%s\";name\n", name);
fprintf(F, "%d;level\n", level); fprintf(F, "%d;level\n", level);
fprintf(F, "%d;rank\n", sp->rank); fprintf(F, "%d;rank\n", sp->rank);
@ -1115,7 +1115,7 @@ static char *cr_output_resource(char *buf, const resource_type *rtype,
assert(rtype); assert(rtype);
name = resourcename(rtype, NMF_PLURAL); name = resourcename(rtype, NMF_PLURAL);
assert(name); 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); tname = LOC(loc, name);
assert(tname); assert(tname);
tname = translate(name, tname); tname = translate(name, tname);
@ -1663,7 +1663,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
if (ptype == NULL) if (ptype == NULL)
continue; continue;
ch = resourcename(ptype->itype->rtype, 0); 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, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch)));
fprintf(F, "%d;Stufe\n", ptype->level); fprintf(F, "%d;Stufe\n", ptype->level);

View File

@ -8,6 +8,15 @@
#include <string.h> #include <string.h>
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 init_direction(const struct locale *lang, direction_t dir, const char *str) {
void **tokens = get_translations(lang, UT_DIRECTIONS); void **tokens = get_translations(lang, UT_DIRECTIONS);
variant token; variant token;

View File

@ -21,6 +21,8 @@ extern "C"
NODIRECTION = -1 NODIRECTION = -1
} direction_t; } direction_t;
extern const char *shortdirections[MAXDIRECTIONS];
direction_t get_direction(const char *s, const struct locale *); direction_t get_direction(const char *s, const struct locale *);
void init_directions(struct locale *lang); void init_directions(struct locale *lang);
void init_direction(const struct locale *lang, direction_t dir, const char *str); void init_direction(const struct locale *lang, direction_t dir, const char *str);

View File

@ -64,7 +64,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/goodies.h> #include <util/goodies.h>
#include <util/language.h> #include <util/language.h>
@ -248,6 +247,7 @@ void add_recruits(unit * u, int number, int wanted)
if (number > 0) { if (number > 0) {
unit *unew; unit *unew;
char equipment[64]; char equipment[64];
int len;
if (u->number == 0) { if (u->number == 0) {
set_number(u, number); 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); unew = create_unit(r, u->faction, number, u_race(u), 0, NULL, u);
} }
strlcpy(equipment, "new_", sizeof(equipment)); len = snprintf(equipment, sizeof(equipment), "new_%s", u_race(u)->_name);
strlcat(equipment, u_race(u)->_name, sizeof(equipment)); if (len > 0 && (size_t)len < sizeof(equipment)) {
equip_unit(unew, get_equipment(equipment)); equip_unit(unew, get_equipment(equipment));
}
if (unew != u) { if (unew != u) {
transfermen(unew, u, unew->number); transfermen(unew, u, unew->number);
remove_unit(&r->units, unew); remove_unit(&r->units, unew);

View File

@ -50,7 +50,6 @@
#include <util/lists.h> #include <util/lists.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <storage.h> #include <storage.h>
#include <lua.h> #include <lua.h>
@ -58,6 +57,7 @@
#include <assert.h> #include <assert.h>
#include <locale.h> #include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
static int g_quit; static int g_quit;
@ -1228,7 +1228,7 @@ static void handlekey(state * st, int c)
else if (findmode == 'F') { else if (findmode == 'F') {
faction *f = select_faction(st); faction *f = select_faction(st);
if (f != NULL) { if (f != NULL) {
strlcpy(locate, itoa36(f->no), sizeof(locate)); itoab_r(f->no, 36, locate, sizeof(locate));
findmode = 'f'; findmode = 'f';
} }
else { else {
@ -1254,7 +1254,7 @@ static void handlekey(state * st, int c)
region *first = (mr && mr->r && mr->r->next) ? mr->r->next : regions; region *first = (mr && mr->r && mr->r->next) ? mr->r->next : regions;
if (findmode == 'f') { 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); statusline(st->wnd_status->handle, sbuffer);
f = findfaction(atoi36(locate)); f = findfaction(atoi36(locate));
if (f == NULL) { if (f == NULL) {

View File

@ -17,7 +17,6 @@ without prior permission by the authors of Eressea.
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/functions.h> #include <util/functions.h>
#include <util/gamedata.h> #include <util/gamedata.h>
@ -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; lua_State *L = (lua_State *)global.vm_state;
char fname[64]; char fname[64];
int result = -1; int result = -1, len;
const char *iname = itype->rtype->_name; const char *iname = itype->rtype->_name;
assert(s != NULL); assert(s != NULL);
strlcpy(fname, iname, sizeof(fname)); len = snprintf(fname, sizeof(fname), "%s_give", iname);
strlcat(fname, "_give", sizeof(fname)); 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_pcall(L, 4, 1, 0) != 0) {
if (lua_isfunction(L, -1)) { const char *error = lua_tostring(L, -1);
tolua_pushusertype(L, s, TOLUA_CAST "unit"); log_error("unit %s calling '%s': %s.\n", unitname(s), fname, error);
tolua_pushusertype(L, d, TOLUA_CAST "unit"); lua_pop(L, 1);
tolua_pushstring(L, iname); }
lua_pushinteger(L, n); else {
result = (int)lua_tonumber(L, -1);
if (lua_pcall(L, 4, 1, 0) != 0) { lua_pop(L, 1);
const char *error = lua_tostring(L, -1); }
log_error("unit %s calling '%s': %s.\n", unitname(s), fname, error);
lua_pop(L, 1);
} }
else { 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); 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; return result;
} }
static int limit_resource_lua(const region * r, const resource_type * rtype) static int limit_resource_lua(const region * r, const resource_type * rtype)
{ {
char fname[64]; char fname[64];
int result = -1; int result = -1, len;
lua_State *L = (lua_State *)global.vm_state; lua_State *L = (lua_State *)global.vm_state;
strlcpy(fname, rtype->_name, sizeof(fname)); len = snprintf(fname, sizeof(fname), "%s_limit", rtype->_name);
strlcat(fname, "_limit", sizeof(fname)); 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_pcall(L, 1, 1, 0) != 0) {
if (lua_isfunction(L, -1)) { const char *error = lua_tostring(L, -1);
tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); 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); else {
log_error("limit(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error); result = (int)lua_tonumber(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
}
} }
else { 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); 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; 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; lua_State *L = (lua_State *)global.vm_state;
char fname[64]; char fname[64];
int len;
strlcpy(fname, rtype->_name, sizeof(fname)); len = snprintf(fname, sizeof(fname), "%s_produce", rtype->_name);
strlcat(fname, "_produce", sizeof(fname)); 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_pcall(L, 2, 0, 0) != 0) {
if (lua_isfunction(L, -1)) { const char *error = lua_tostring(L, -1);
tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); log_error("produce(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error);
lua_pushinteger(L, norders); lua_pop(L, 1);
}
if (lua_pcall(L, 2, 0, 0) != 0) { }
const char *error = lua_tostring(L, -1); else {
log_error("produce(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error); log_error("produce(%s) calling '%s': not a function.\n", regionname(r, NULL), fname);
lua_pop(L, 1); 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) 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_changeresource(unit * u, const struct resource_type *rtype, int delta)
{ {
lua_State *L = (lua_State *)global.vm_state; lua_State *L = (lua_State *)global.vm_state;
int result = -1; int len, result = -1;
char fname[64]; char fname[64];
strlcpy(fname, rtype->_name, sizeof(fname)); len = snprintf(fname, sizeof(fname), "%s_changeresource", rtype->_name);
strlcat(fname, "_changeresource", sizeof(fname)); if (len > 0 && (size_t)len < sizeof(fname)) {
lua_getglobal(L, fname);
lua_getglobal(L, fname); if (lua_isfunction(L, -1)) {
if (lua_isfunction(L, -1)) { tolua_pushusertype(L, u, TOLUA_CAST "unit");
tolua_pushusertype(L, u, TOLUA_CAST "unit"); lua_pushinteger(L, delta);
lua_pushinteger(L, delta);
if (lua_pcall(L, 2, 1, 0) != 0) {
if (lua_pcall(L, 2, 1, 0) != 0) { const char *error = lua_tostring(L, -1);
const char *error = lua_tostring(L, -1); log_error("change(%s) calling '%s': %s.\n", unitname(u), fname, error);
log_error("change(%s) calling '%s': %s.\n", unitname(u), fname, error); lua_pop(L, 1);
lua_pop(L, 1); }
else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
} }
else { else {
result = (int)lua_tonumber(L, -1); log_error("change(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1); lua_pop(L, 1);
} }
} }
else {
log_error("change(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
}
return result; return result;
} }
@ -250,13 +247,12 @@ static int
use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord) use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
{ {
lua_State *L = (lua_State *)global.vm_state; lua_State *L = (lua_State *)global.vm_state;
int result = 0; int len, result = 0;
char fname[64]; char fname[64];
int (*callout)(unit *, const item_type *, int, struct order *); int (*callout)(unit *, const item_type *, int, struct order *);
strlcpy(fname, "use_", sizeof(fname)); len = snprintf(fname, sizeof(fname), "use_%s", itype->rtype->_name);
strlcat(fname, itype->rtype->_name, sizeof(fname)); if (len > 0 && (size_t)len < sizeof(fname)) {
callout = (int(*)(unit *, const item_type *, int, struct order *))get_function(fname); callout = (int(*)(unit *, const item_type *, int, struct order *))get_function(fname);
if (callout) { if (callout) {
return callout(u, itype, amount, ord); 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("no such callout: %s", fname);
} }
log_error("use(%s) calling '%s': not a function.\n", unitname(u), fname); log_error("use(%s) calling '%s': not a function.\n", unitname(u), fname);
}
return result; return result;
} }

View File

@ -28,7 +28,6 @@ without prior permission by the authors of Eressea.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/language.h> #include <util/language.h>
#include <util/parser.h> #include <util/parser.h>
#include <util/rng.h> #include <util/rng.h>
@ -40,6 +39,7 @@ without prior permission by the authors of Eressea.
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
alliance *alliances = NULL; alliance *alliances = NULL;
@ -422,7 +422,7 @@ const char *alliancename(const alliance * al)
char *ibuf = idbuf[(++nextbuf) % 8]; char *ibuf = idbuf[(++nextbuf) % 8];
if (al && al->name) { 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 { else {
return NULL; return NULL;

View File

@ -38,7 +38,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/functions.h> #include <util/functions.h>
#include <util/gamedata.h> #include <util/gamedata.h>
@ -54,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
@ -372,7 +372,7 @@ building *new_building(const struct building_type * btype, region * r,
bname = parameters[P_GEBAEUDE]; bname = parameters[P_GEBAEUDE];
} }
assert(bname); 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); b->name = strdup(bname);
return b; 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) 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; return ibuf;
} }

View File

@ -25,19 +25,21 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "unit.h" #include "unit.h"
#include <util/attrib.h> #include <util/attrib.h>
#include <util/bsdstring.h> #include <util/base36.h>
#include <util/gamedata.h> #include <util/gamedata.h>
#include <util/language.h> #include <util/language.h>
#include <util/log.h> #include <util/log.h>
#include <selist.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/strings.h>
#include <selist.h>
#include <storage.h> #include <storage.h>
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int nextborder = 0; int nextborder = 0;
@ -514,8 +516,8 @@ static const char *b_nameroad(const connection * b, const region * r,
else { else {
int percent = MAX(1, 100 * local / r->terrain->max_road); int percent = MAX(1, 100 * local / r->terrain->max_road);
if (local) { if (local) {
slprintf(buffer, sizeof(buffer), LOC(f->locale, mkname("border", const char *temp = LOC(f->locale, mkname("border", "a_road_percent"));
"a_road_percent")), percent); str_replace(buffer, sizeof(buffer), temp, "$percent", itoa10(percent));
} }
else { else {
return LOC(f->locale, mkname("border", "a_road_connection")); return LOC(f->locale, mkname("border", "a_road_connection"));

View File

@ -39,7 +39,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/gamedata.h> #include <util/gamedata.h>
#include <util/goodies.h> #include <util/goodies.h>
@ -50,6 +49,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/password.h> #include <util/password.h>
#include <util/resolve.h> #include <util/resolve.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/strings.h>
#include <util/variant.h> #include <util/variant.h>
#include <selist.h> #include <selist.h>

View File

@ -170,7 +170,7 @@ int stream_order(struct stream *out, const struct order *ord, const struct local
char obuf[1024]; char obuf[1024];
swrite(" ", 1, 1, out); swrite(" ", 1, 1, out);
if (escape) { if (escape) {
text = escape_string(text, obuf, sizeof(obuf)); text = str_escape(text, obuf, sizeof(obuf));
} }
swrite(text, 1, strlen(text), out); swrite(text, 1, strlen(text), out);
} }

View File

@ -6,6 +6,7 @@
#include <critbit.h> #include <critbit.h>
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -14,12 +15,15 @@ void odata_create(order_data **pdata, size_t len, const char *str)
order_data *data; order_data *data;
char *result; char *result;
assert(pdata);
data = malloc(sizeof(order_data) + len + 1); data = malloc(sizeof(order_data) + len + 1);
data->_refcount = 1; data->_refcount = 1;
result = (char *)(data + 1); result = (char *)(data + 1);
data->_str = (len > 0) ? result : NULL; data->_str = (len > 0) ? result : NULL;
if (str) strcpy(result, str); if (str) {
if (pdata) *pdata = data; strcpy(result, str);
}
*pdata = data;
} }
void odata_release(order_data * od) void odata_release(order_data * od)

View File

@ -124,7 +124,7 @@ const char *write_regionname(const region * r, const faction * f, char *buffer,
int nx = r->x, ny = r->y; int nx = r->x, ny = r->y;
pnormalize(&nx, &ny, pl); pnormalize(&nx, &ny, pl);
adjust_coordinates(f, &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; return buffer;
} }

View File

@ -1429,7 +1429,7 @@ int read_game(gamedata *data)
/* Burgen */ /* Burgen */
READ_INT(store, &p); READ_INT(store, &p);
if (p > 0 && !r->land) { 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; bp = &r->buildings;
@ -1569,14 +1569,12 @@ int writegame(const char *filename)
create_directories(); create_directories();
join_path(datapath(), filename, path, sizeof(path)); join_path(datapath(), filename, path, sizeof(path));
#ifdef HAVE_UNISTD_H
/* make sure we don't overwrite an existing file (hard links) */ /* make sure we don't overwrite an existing file (hard links) */
if (remove(path)!=0) { if (remove(path) != 0) {
if (errno==ENOENT) { if (errno == ENOENT) {
errno = 0; errno = 0;
} }
} }
#endif
F = fopen(path, "wb"); F = fopen(path, "wb");
if (!F) { if (!F) {
perror(path); perror(path);

View File

@ -36,7 +36,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/language.h> #include <util/language.h>
#include <util/lists.h> #include <util/lists.h>
@ -217,7 +216,7 @@ ship *new_ship(const ship_type * stype, region * r, const struct locale *lang)
sname = parameters[P_SHIP]; sname = parameters[P_SHIP];
} }
assert(sname); 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); sh->name = strdup(buffer);
shash(sh); shash(sh);
if (r) { if (r) {
@ -283,7 +282,7 @@ void free_ships(void)
const char *write_shipname(const ship * sh, char *ibuf, size_t size) 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; return ibuf;
} }

View File

@ -51,7 +51,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/gamedata.h> #include <util/gamedata.h>
#include <util/strings.h> #include <util/strings.h>
@ -1458,9 +1457,7 @@ void default_name(const unit *u, char name[], int len) {
else { else {
result = parameters[P_UNIT]; result = parameters[P_UNIT];
} }
strlcpy(name, result, len); snprintf(name, len, "%s %s", result, itoa36(u->no));
strlcat(name, " ", len);
strlcat(name, itoa36(u->no), len);
} }
void name_unit(unit * u) void name_unit(unit * u)
@ -1874,7 +1871,7 @@ static int nextbuf = 0;
char *write_unitname(const unit * u, char *buffer, size_t size) char *write_unitname(const unit * u, char *buffer, size_t size)
{ {
const char * name = unit_getname(u); 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; buffer[size - 1] = 0;
return buffer; return buffer;
} }

View File

@ -90,6 +90,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/password.h> #include <util/password.h>
#include <util/rand.h> #include <util/rand.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/strings.h>
#include <util/umlaut.h> #include <util/umlaut.h>
#include <util/unicode.h> #include <util/unicode.h>

View File

@ -33,7 +33,6 @@
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/goodies.h> #include <util/goodies.h>
#include <util/language.h> #include <util/language.h>
#include <util/lists.h> #include <util/lists.h>
@ -166,9 +165,7 @@ newfaction *read_newfactions(const char *filename)
break; break;
} }
if (password[0] == '\0') { if (password[0] == '\0') {
size_t sz; snprintf(password, sizeof(password), "%s%s", itoa36(rng_int()), itoa36(rng_int()));
sz = strlcpy(password, itoa36(rng_int()), sizeof(password));
sz += strlcat(password, itoa36(rng_int()), sizeof(password));
} }
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if (strcmp(faction_getemail(f), email) == 0 && f->age < MINAGE_MULTI) { if (strcmp(faction_getemail(f), email) == 0 && f->age < MINAGE_MULTI) {

View File

@ -34,7 +34,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/language.h> #include <util/language.h>
/* libc includes */ /* libc includes */
@ -237,5 +236,5 @@ int default_score(const item_type *itype) {
} }
void write_score(char *buffer, size_t size, score_t score) { void write_score(char *buffer, size_t size, score_t score) {
slprintf(buffer, size, "%lld", score); snprintf(buffer, size, "%lld", score);
} }

View File

@ -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) { static void give_peasants(unit *u, const item_type *itype, int reduce) {
char buf[64]; 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)); unit_addorder(u, parse_order(buf, u->faction->locale));
} }

View File

@ -78,6 +78,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/parser.h> #include <util/parser.h>
#include <util/rand.h> #include <util/rand.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/strings.h>
#include <storage.h> #include <storage.h>
@ -1042,15 +1043,6 @@ int movewhere(const unit * u, const char *token, region * r, region ** resultp)
return E_MOVE_OK; 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) static void cycle_route(order * ord, unit * u, int gereist)
{ {
int cm = 0; int cm = 0;
@ -1063,13 +1055,11 @@ static void cycle_route(order * ord, unit * u, int gereist)
order *norder; order *norder;
size_t size = sizeof(tail) - 1; size_t size = sizeof(tail) - 1;
if (getkeyword(ord) != K_ROUTE) assert(getkeyword(ord) == K_ROUTE);
return;
tail[0] = '\0'; tail[0] = '\0';
neworder[0] = '\0';
init_order(ord, u->faction->locale);
init_order_depr(ord);
neworder[0] = 0;
for (cm = 0;; ++cm) { for (cm = 0;; ++cm) {
const char *s; const char *s;
const struct locale *lang = u->faction->locale; const struct locale *lang = u->faction->locale;
@ -1092,6 +1082,7 @@ static void cycle_route(order * ord, unit * u, int gereist)
assert(!pause); assert(!pause);
if (!pause) { if (!pause) {
const char *loc = LOC(lang, shortdirections[d]); const char *loc = LOC(lang, shortdirections[d]);
assert(loc);
if (bufp != tail) { if (bufp != tail) {
bufp = STRLCPY_EX(bufp, " ", &size, "cycle_route"); bufp = STRLCPY_EX(bufp, " ", &size, "cycle_route");
} }
@ -1371,7 +1362,7 @@ static void make_route(unit * u, order * ord, region_list ** routep)
current = next; current = next;
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
error = movewhere(u, s, current, &next); error = movewhere(u, s, current, &next);
if (error) { if (error != E_MOVE_OK) {
message *msg = movement_error(u, s, ord, error); message *msg = movement_error(u, s, ord, error);
if (msg != NULL) { if (msg != NULL) {
add_message(&u->faction->msgs, msg); add_message(&u->faction->msgs, msg);
@ -1606,7 +1597,9 @@ static const region_list *travel_route(unit * u,
int walkmode; int walkmode;
setguard(u, false); setguard(u, false);
cycle_route(ord, u, steps); if (getkeyword(ord) == K_ROUTE) {
cycle_route(ord, u, steps);
}
if (mode == TRAVEL_RUNNING) { if (mode == TRAVEL_RUNNING) {
walkmode = 0; walkmode = 0;
@ -1936,7 +1929,9 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting)
unit *harbourmaster; unit *harbourmaster;
/* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten
* transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ * 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_order(&u->thisorder, NULL);
set_coast(sh, last_point, current_point); 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; region *r = u->region;
int mp; int mp;
if (u->building && !can_leave(u)) { if (u->building && !can_leave(u)) {
cmistake(u, u->thisorder, 150, MSG_MOVE); cmistake(u, ord, 150, MSG_MOVE);
return route_begin; return route_begin;
} }
switch (canwalk(u)) { switch (canwalk(u)) {
@ -2115,7 +2110,7 @@ static const region_list *travel_i(unit * u, const region_list * route_begin,
/** traveling without ships /** traveling without ships
* walking, flying or riding units use this function * 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 *r = u->region;
region_list *route_begin; region_list *route_begin;
@ -2129,7 +2124,7 @@ static void travel(unit * u, region_list ** routep)
ship *sh = u->ship; ship *sh = u->ship;
if (!can_leave(u)) { if (!can_leave(u)) {
cmistake(u, u->thisorder, 150, MSG_MOVE); cmistake(u, ord, 150, MSG_MOVE);
return; return;
} }
@ -2142,28 +2137,28 @@ static void travel(unit * u, region_list ** routep)
if (sh) { if (sh) {
unit *guard = is_guarded(r, u); unit *guard = is_guarded(r, u);
if (guard) { if (guard) {
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
"region_guarded", "guard", guard)); "region_guarded", "guard", guard));
return; return;
} }
} }
if (u->ship && u_race(u)->flags & RCF_SWIM) { if (u->ship && u_race(u)->flags & RCF_SWIM) {
cmistake(u, u->thisorder, 143, MSG_MOVE); cmistake(u, ord, 143, MSG_MOVE);
return; return;
} }
} }
else if (u->ship && fval(u->ship, SF_MOVED)) { else if (u->ship && fval(u->ship, SF_MOVED)) {
/* die Einheit ist auf einem Schiff, das sich bereits bewegt hat */ /* 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; return;
} }
make_route(u, u->thisorder, routep); make_route(u, ord, routep);
route_begin = *routep; route_begin = *routep;
if (route_begin) { if (route_begin) {
/* und ab die post: */ /* 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 */ /* followers */
while (followers != NULL) { while (followers != NULL) {
@ -2204,7 +2199,7 @@ void move_cmd(unit * u, order * ord)
sail(u, ord, &route, drifting); sail(u, ord, &route, drifting);
} }
else { else {
travel(u, &route); travel(u, ord, &route);
} }
fset(u, UFL_LONGACTION | UFL_NOTMOVING); fset(u, UFL_LONGACTION | UFL_NOTMOVING);

View File

@ -545,6 +545,52 @@ static void test_movement_speed(CuTest *tc) {
test_cleanup(); 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 *get_move_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); 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_ship_damage_overload);
SUITE_ADD_TEST(suite, test_follow_ship_msg); SUITE_ADD_TEST(suite, test_follow_ship_msg);
SUITE_ADD_TEST(suite, test_drifting_ships); SUITE_ADD_TEST(suite, test_drifting_ships);
SUITE_ADD_TEST(suite, test_route_cycle);
SUITE_ADD_TEST(suite, test_route_pause);
return suite; return suite;
} }

View File

@ -262,7 +262,7 @@ static void dragon_name(unit * u)
rnd = num_postfix / 6; rnd = num_postfix / 6;
rnd = (rng_int() % rnd) + ter * rnd; 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); str = locale_getstring(default_locale, zText);
assert(str != NULL); assert(str != NULL);
@ -271,28 +271,25 @@ static void dragon_name(unit * u)
const char *no_article = strchr((const char *)str, ' '); const char *no_article = strchr((const char *)str, ' ');
assert(no_article); assert(no_article);
/* TODO: localization */ /* 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)); default_locale));
} }
else { else {
char n[32]; char n[32];
size_t sz;
sz = strlcpy(n, silbe1[rng_int() % SIL1], sizeof(n)); snprintf(n, sizeof(n), "%s%s%s", silbe1[rng_int() % SIL1], silbe2[rng_int() % SIL2], silbe3[rng_int() % SIL3]);
sz += strlcat(n, silbe2[rng_int() % SIL2], sizeof(n));
sz += strlcat(n, silbe3[rng_int() % SIL3], sizeof(n));
if (rng_int() % 5 > 2) { if (rng_int() % 5 > 2) {
sprintf(name, "%s, %s", n, str); /* "Name, der Titel" */ sprintf(name, "%s, %s", n, str); /* "Name, der Titel" */
} }
else { 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() */ 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));
} }
} }

View File

@ -29,8 +29,8 @@
#endif #endif
#define _POSIX_C_SOURCE 200809L /* #define _POSIX_C_SOURCE 200809L
*/
#ifndef MAX_PATH #ifndef MAX_PATH
# define MAX_PATH 4096 # define MAX_PATH 4096
#endif #endif

View File

@ -53,7 +53,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/bsdstring.h>
#include <util/language.h> #include <util/language.h>
#include <util/lists.h> #include <util/lists.h>
#include <util/log.h> #include <util/log.h>
@ -62,10 +61,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/rng.h> #include <util/rng.h>
/* libc includes */ /* libc includes */
#include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <attributes/iceberg.h> #include <attributes/iceberg.h>
@ -234,9 +233,9 @@ void find_manual(region * r, unit * u)
break; break;
} }
slprintf(zLocation, sizeof(zLocation), "manual_location_%d", snprintf(zLocation, sizeof(zLocation), "manual_location_%d",
(int)(rng_int() % 4)); (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); msg = msg_message("find_manual", "unit location book", u, zLocation, zBook);
if (msg) { if (msg) {

View File

@ -61,7 +61,6 @@
#include <util/assert.h> #include <util/assert.h>
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/gamedata.h> #include <util/gamedata.h>
#include <util/language.h> #include <util/language.h>
@ -4643,7 +4642,7 @@ int sp_clonecopy(castorder * co)
return 0; 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_of"), unitname(mage));
clone = clone =
create_unit(target_region, mage->faction, 1, get_race(RC_CLONE), 0, name, create_unit(target_region, mage->faction, 1, get_race(RC_CLONE), 0, name,

View File

@ -1279,7 +1279,7 @@ int sp_appeasement(struct castorder * co)
} }
/* und bewachen nicht */ /* und bewachen nicht */
setguard(mage, false); setguard(mage, false);
/* irgendwie den langen befehl sperren */ setstatus(mage, ST_FLEE);
/* wir tun so, als w<>re die Person geflohen */ /* wir tun so, als w<>re die Person geflohen */
fi->flags |= FIG_NOLOOT; fi->flags |= FIG_NOLOOT;

View File

@ -44,6 +44,7 @@ struct race *test_create_race(const char *name)
rc->maintenance = 10; rc->maintenance = 10;
rc->hitpoints = 20; rc->hitpoints = 20;
rc->maxaura = 100; rc->maxaura = 100;
rc->flags |= RCF_WALK;
rc->ec_flags |= ECF_GETITEM; rc->ec_flags |= ECF_GETITEM;
rc->battle_flags = BF_EQUIPMENT; rc->battle_flags = BF_EQUIPMENT;
return rc; return rc;
@ -120,6 +121,7 @@ struct locale * test_create_locale(void) {
locale_setstring(loc, alliance_kwd[i], alliance_kwd[i]); locale_setstring(loc, alliance_kwd[i], alliance_kwd[i]);
} }
for (i = 0; i != MAXDIRECTIONS; ++i) { for (i = 0; i != MAXDIRECTIONS; ++i) {
locale_setstring(loc, shortdirections[i], shortdirections[i] + 4);
locale_setstring(loc, directions[i], directions[i]); locale_setstring(loc, directions[i], directions[i]);
init_direction(loc, i, directions[i]); init_direction(loc, i, directions[i]);
init_direction(loc, i, coasts[i] + 7); init_direction(loc, i, coasts[i] + 7);

View File

@ -22,7 +22,6 @@ password.test.c
# resolve.test.c # resolve.test.c
rng.test.c rng.test.c
strings.test.c strings.test.c
bsdstring.test.c
functions.test.c functions.test.c
log.test.c log.test.c
# translation.test.c # translation.test.c
@ -60,6 +59,7 @@ unicode.c
variant.c variant.c
xml.c xml.c
) )
FOREACH(_FILE ${_FILES}) FOREACH(_FILE ${_FILES})
LIST(APPEND _SOURCES ${PROJECT_NAME}/${_FILE}) LIST(APPEND _SOURCES ${PROJECT_NAME}/${_FILE})
ENDFOREACH(_FILE) ENDFOREACH(_FILE)

View File

@ -52,16 +52,13 @@ int atoi36(const char *str)
return i * sign; 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 *dst;
char *s, *dst;
static int index = 0; /* STATIC_XCALL: used across calls */
s = sstr + (index * 20); assert(len > 2);
index = (index + 1) & 3; /* quick for % 4 */ dst = s + len - 2;
dst = s + 19; *dst = 0;
(*dst--) = 0;
if (i != 0) { if (i != 0) {
int neg = 0; int neg = 0;
@ -101,6 +98,18 @@ const char *itoab(int i, int base)
return dst; 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) const char *itoa36(int i)
{ {
return itoab(i, 36); return itoab(i, 36);

View File

@ -18,15 +18,19 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef H_UTIL_BASE36 #ifndef H_UTIL_BASE36
#define H_UTIL_BASE36 #define H_UTIL_BASE36
#include <stddef.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 int atoi36(const char *s);
extern const char *itoab(int i, int base); int i10toi36(int i);
extern const char *itoa36(int i);
extern const char *itoa10(int i);
extern int i10toi36(int i);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,9 +1,7 @@
#include <platform.h> #include <platform.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <stdarg.h>
#include <limits.h> #include <limits.h>
#include "bsdstring.h" #include "bsdstring.h"
@ -35,8 +33,7 @@ int wrptr(char **ptr, size_t * size, int result)
return ERANGE; return ERANGE;
} }
#ifndef HAVE_STRLCPY #ifndef HAVE_BSDSTRING
#define HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz) size_t strlcpy(char *dst, const char *src, size_t siz)
{ /* copied from OpenBSD source code */ { /* copied from OpenBSD source code */
register char *d = dst; 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 */ 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) size_t strlcat(char *dst, const char *src, size_t siz)
{ {
register char *d = dst; register char *d = dst;
@ -108,21 +87,17 @@ size_t strlcat(char *dst, const char *src, size_t siz)
} }
#endif #endif
#ifndef HAVE_SLPRINTF char * strlcpy_w(char *dst, const char *src, size_t *siz, const char *err, const char *file, int line)
#define HAVE_SLPRINTF
size_t slprintf(char * dst, size_t size, const char * format, ...)
{ {
va_list args; size_t bytes = strlcpy(dst, src, *siz);
int result; char * buf = dst;
assert(bytes <= INT_MAX);
va_start(args, format); if (wrptr(&buf, siz, (int)bytes) != 0) {
result = vsnprintf(dst, size, format, args); if (err) {
va_end(args); log_warning("%s: static buffer too small in %s:%d\n", err, file, line);
if (result < 0 || result >= (int)size) { } else {
dst[size - 1] = '\0'; log_warning("static buffer too small in %s:%d\n", file, line);
return size; }
} }
return buf;
return (size_t)result;
} }
#endif

View File

@ -2,20 +2,16 @@
#define UTIL_BSDSTRING_H #define UTIL_BSDSTRING_H
#include <stddef.h> #include <stddef.h>
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); 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); size_t strlcat(char *dst, const char *src, size_t siz);
#else
#include <string.h>
#endif #endif
#ifndef HAVE_SLPRINTF int wrptr(char **ptr, size_t * size, int bytes);
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);
#endif
#define WARN_STATIC_BUFFER_EX(foo) log_warning("%s: static buffer too small in %s:%d\n", (foo), __FILE__, __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__) #define WARN_STATIC_BUFFER() log_warning("static buffer too small in %s:%d\n", __FILE__, __LINE__)

View File

@ -42,29 +42,10 @@ static void test_strlcpy(CuTest * tc)
errno = 0; 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 *get_bsdstring_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_strlcat); SUITE_ADD_TEST(suite, test_strlcat);
SUITE_ADD_TEST(suite, test_strlcpy); SUITE_ADD_TEST(suite, test_strlcpy);
SUITE_ADD_TEST(suite, test_slprintf);
return suite; return suite;
} }

View File

@ -56,7 +56,7 @@ unsigned int locale_index(const locale * lang)
locale *get_locale(const char *name) locale *get_locale(const char *name)
{ {
unsigned int hkey = hashstring(name); unsigned int hkey = str_hash(name);
locale *l = locales; locale *l = locales;
while (l && l->hashkey != hkey) while (l && l->hashkey != hkey)
l = l->next; l = l->next;
@ -68,7 +68,7 @@ static unsigned int nextlocaleindex = 0;
locale *get_or_create_locale(const char *name) locale *get_or_create_locale(const char *name)
{ {
locale *l; locale *l;
unsigned int hkey = hashstring(name); unsigned int hkey = str_hash(name);
locale **lp = &locales; locale **lp = &locales;
if (!locales) { if (!locales) {
@ -120,7 +120,7 @@ void make_locales(const char *str)
const char *locale_getstring(const locale * lang, const char *key) 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); unsigned int id = hkey & (SMAXHASH - 1);
const struct locale_str *find; const struct locale_str *find;
@ -150,7 +150,7 @@ const char *locale_string(const locale * lang, const char *key, bool warn)
assert(key); assert(key);
if (key != NULL) { if (key != NULL) {
unsigned int hkey = hashstring(key); unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1); unsigned int id = hkey & (SMAXHASH - 1);
struct locale_str *find; 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) 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); unsigned int id = hkey & (SMAXHASH - 1);
struct locale_str *find; struct locale_str *find;
if (!lang) { if (!lang) {

View File

@ -192,7 +192,7 @@ void mt_clear(void) {
const message_type *mt_find(const char *name) 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]; selist *ql = messagetypes[hash];
int qi; int qi;
@ -218,7 +218,7 @@ static unsigned int mt_id(const message_type * mtype)
const message_type *mt_register(message_type * type) 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; selist **qlp = messagetypes + hash;
if (selist_set_insert(qlp, type, NULL)) { if (selist_set_insert(qlp, type, NULL)) {

View File

@ -22,10 +22,28 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "assert.h" #include "assert.h"
/* libc includes */ /* libc includes */
#include <stdarg.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
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) char *set_string(char **s, const char *neu)
{ {
if (neu == NULL) { if (neu == NULL) {
@ -45,7 +63,40 @@ char *set_string(char **s, const char *neu)
return *s; 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; unsigned int key = 0;
assert(s); assert(s);
@ -55,7 +106,7 @@ unsigned int hashstring(const char *s)
return key & 0x7FFFFFFF; return key & 0x7FFFFFFF;
} }
const char *escape_string(const char *str, char *buffer, const char *str_escape(const char *str, char *buffer,
size_t len) size_t len)
{ {
const char *start = strchr(str, '\"'); const char *start = strchr(str, '\"');

View File

@ -25,9 +25,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" { extern "C" {
#endif #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); char *set_string(char **s, const char *neu);
unsigned int hashstring(const char *s); unsigned int str_hash(const char *s);
const char *escape_string(const char *str, char *buffer, size_t len); size_t str_slprintf(char * dst, size_t size, const char * format, ...);
unsigned int jenkins_hash(unsigned int a); unsigned int jenkins_hash(unsigned int a);
unsigned int wang_hash(unsigned int a); unsigned int wang_hash(unsigned int a);
@ -48,6 +51,7 @@ extern "C" {
#define HASH1 JENKINS_HASH1 #define HASH1 JENKINS_HASH1
#define HASH2 JENKINS_HASH2 #define HASH2 JENKINS_HASH2
#define slprintf str_slprintf
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -4,21 +4,55 @@
#include <string.h> #include <string.h>
#include "strings.h" #include "strings.h"
static void test_escape_string(CuTest * tc) static void test_str_escape(CuTest * tc)
{ {
char scratch[64]; char scratch[64];
CuAssertStrEquals(tc, "12345678901234567890", escape_string("12345678901234567890", scratch, 16)); CuAssertStrEquals(tc, "12345678901234567890", str_escape("12345678901234567890", scratch, 16));
CuAssertStrEquals(tc, "123456789\\\"12345", escape_string("123456789\"1234567890", scratch, 16)); CuAssertStrEquals(tc, "123456789\\\"12345", str_escape("123456789\"1234567890", scratch, 16));
CuAssertStrEquals(tc, "1234567890123456", escape_string("1234567890123456\"890", scratch, 16)); CuAssertStrEquals(tc, "1234567890123456", str_escape("1234567890123456\"890", scratch, 16));
CuAssertStrEquals(tc, "hello world", escape_string("hello world", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "hello world", str_escape("hello world", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "hello \\\"world\\\"", escape_string("hello \"world\"", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "hello \\\"world\\\"", str_escape("hello \"world\"", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "\\\"\\\\", escape_string("\"\\", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "\\\"\\\\", str_escape("\"\\", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "\\\\", escape_string("\\", 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 *get_strings_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); 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; return suite;
} }