diff --git a/res/core/common/items.xml b/res/core/common/items.xml
index 308a41df2..564e9fafd 100644
--- a/res/core/common/items.xml
+++ b/res/core/common/items.xml
@@ -46,7 +46,7 @@
-
+
diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml
index 6bf4f5abe..f773be014 100644
--- a/res/core/de/strings.xml
+++ b/res/core/de/strings.xml
@@ -7331,7 +7331,7 @@
- eine zu $percent%% vollendete Straße
+ eine zu $percent% vollendete Straße
a road that is $percent% complete
diff --git a/res/core/messages.xml b/res/core/messages.xml
index 5ea0694fd..f09530e0f 100644
--- a/res/core/messages.xml
+++ b/res/core/messages.xml
@@ -42,6 +42,18 @@
pulled by 8 young dragons flies through the stary night and presents
your faction with a $resource($item,1).
+
+
+
+
+ 'Ho ho ho!' Ein dicker Gnom fliegt auf einem von
+ 8 Jungdrachen gezogenen Schlitten durch die Nacht und vermacht Deiner
+ Partei einen $resource($item,1). (Um diesen Gegenstand einer Einheit zu geben, gib
+ ihr den Befehl 'BEANSPRUCHE 1 $resource($item,1)').
+ 'Ho ho ho!' A fat little gnome Gnom on a sled
+ pulled by 8 young dragons flies through the stary night and presents
+ your faction with a $resource($item,1).
+
diff --git a/s/travis-build b/s/travis-build
index 9ef0fbdd5..a678b1de2 100755
--- a/s/travis-build
+++ b/s/travis-build
@@ -16,11 +16,23 @@ cd tests
./run-turn.sh
}
+cppcheck_tests() {
+ cppcheck --version
+ DIRS="util kernel modules races attributes triggers items tools spells"
+ IGNORE=""
+ for DIR in $DIRS ; do
+ IGNORE="$IGNORE -i src/$DIR"
+ echo "cppcheck src/$DIR"
+ cppcheck --quiet -Isrc -Iclibs -Istorage -IcJSON --error-exitcode=1 "src/$DIR"
+ done
+ echo "cppcheck src"
+ cppcheck --quiet -Isrc -Iclibs -Istorage -IcJSON --error-exitcode=1 $IGNORE src
+}
+
set -e
[ -z $BUILD ] && BUILD=Debug ; export BUILD
s/cmake-init
-cppcheck --version
-cppcheck --quiet -Isrc -Iclibs -Istorage -IcJSON --error-exitcode=1 src
+# cppcheck_tests
s/build
cd process
make
diff --git a/scripts/eressea/xmas.lua b/scripts/eressea/xmas.lua
index 6f319a316..9fe368e42 100644
--- a/scripts/eressea/xmas.lua
+++ b/scripts/eressea/xmas.lua
@@ -2,16 +2,15 @@ if not config.xmas or config.xmas==0 then return nil end
local gifts = {
e2 = {
- { year = 2017, turn = 1057, item = 'snowglobe', msg='santa_f' },
- { year = 2015, turn = 959, item = 'snowglobe', msg='santa_f' },
- { year = 2009, turn = 624, item = 'xmastree' },
- { year = 2006, turn = 468, key = 'xm06', item = 'snowman' },
- { year = 2005, turn = 416, key = 'xm05', item = 'stardust' },
- { year = 2004, turn = 364, key = 'xm04', item = 'speedsail' }
+ [1057] = { year = 2017, item = 'snowglobe', msg='santa_f' },
+ [959] = { year = 2015, item = 'snowglobe', msg='santa_f' },
+ [624] = { year = 2009, item = 'xmastree', msg='santa_m' },
+ [468] = { year = 2006, item = 'snowman', msg='santa_m' },
+ [416] = { year = 2005, item = 'stardust' },
+ [364] = { year = 2004, item = 'speedsail' }
},
e3 = {
- -- { year = 2015, turn = 338, item = 'snowglobe' },
- { year = 2009, turn = 26, key = 'xm09', item = 'xmastree' }
+ [26] = { year = 2009, item = 'xmastree' }
}
}
@@ -38,13 +37,9 @@ function self.init()
local turn = get_turn()
local tbl = gifts[config.rules]
if tbl then
- for _, gift in ipairs(tbl) do
- if turn == gift.turn then
- give_gifts(gift)
- elseif gift.key and not get_key(gift.key) then
- give_gifts(gift)
- set_key(gift.key)
- end
+ gift = tbl[turn]
+ if gift then
+ give_gifts(gift)
end
end
end
diff --git a/src/battle.c b/src/battle.c
index 837d4a280..da84b2763 100644
--- a/src/battle.c
+++ b/src/battle.c
@@ -185,7 +185,7 @@ static int army_index(side * s)
return s->index;
}
-static char *sidename(side * s)
+const char *sidename(const side * s)
{
#define SIDENAMEBUFLEN 256
static int bufno; /* STATIC_XCALL: used across calls */
@@ -206,7 +206,7 @@ static const char *sideabkz(side * s, bool truename)
return sideabkz_buf;
}
-static void message_faction(battle * b, faction * f, struct message *m)
+void battle_message_faction(battle * b, faction * f, struct message *m)
{
region *r = b->region;
@@ -227,14 +227,14 @@ void message_all(battle * b, message * m)
for (bf = b->factions; bf; bf = bf->next) {
assert(bf->faction);
- message_faction(b, bf->faction, m);
+ battle_message_faction(b, bf->faction, m);
}
}
static void fbattlerecord(battle * b, faction * f, const char *s)
{
message *m = msg_message("battle_msg", "string", s);
- message_faction(b, f, m);
+ battle_message_faction(b, f, m);
msg_release(m);
}
@@ -1302,7 +1302,7 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
if (oldpotiontype[P_HEAL] && !fval(&df->person[dt.index], FL_HEALING_USED)) {
if (i_get(du->items, oldpotiontype[P_HEAL]->itype) > 0) {
message *m = msg_message("potionsave", "unit", du);
- message_faction(b, du->faction, m);
+ battle_message_faction(b, du->faction, m);
msg_release(m);
i_change(&du->items, oldpotiontype[P_HEAL]->itype, -1);
fset(&df->person[dt.index], FL_HEALING_USED);
@@ -2531,7 +2531,7 @@ static void loot_items(fighter * corpse)
}
}
-static bool seematrix(const faction * f, const side * s)
+bool seematrix(const faction * f, const side * s)
{
if (f == s->faction)
return true;
@@ -2615,7 +2615,7 @@ static void aftermath(battle * b)
struct message *m =
msg_message("killsandhits", "unit hits kills", du, df->hits,
df->kills);
- message_faction(b, du->faction, m);
+ battle_message_faction(b, du->faction, m);
msg_release(m);
}
}
@@ -2755,7 +2755,7 @@ static void aftermath(battle * b)
faction *f = bf->faction;
message *m = seematrix(f, s) ? seen : unseen;
- message_faction(b, f, m);
+ battle_message_faction(b, f, m);
}
msg_release(seen);
@@ -2779,7 +2779,7 @@ static void aftermath(battle * b)
message *m =
msg_message("battle_loot", "unit amount item", du, l->number,
itype->rtype);
- message_faction(b, du->faction, m);
+ battle_message_faction(b, du->faction, m);
msg_release(m);
i_change(&du->items, itype, l->number);
}
@@ -2877,54 +2877,6 @@ static void set_attacker(fighter * fig)
fset(fig, FIG_ATTACKER);
}
-static void print_header(battle * b)
-{
- bfaction *bf;
- char zText[32 * MAXSIDES];
-
- for (bf = b->factions; bf; bf = bf->next) {
- message *m;
- faction *f = bf->faction;
- const char *lastf = NULL;
- bool first = false;
- side *s;
- char *bufp = zText;
- size_t size = sizeof(zText) - 1;
-
- for (s = b->sides; s != b->sides + b->nsides; ++s) {
- fighter *df;
- for (df = s->fighters; df; df = df->next) {
- if (is_attacker(df)) {
- if (first) {
- str_strlcpy(bufp, ", ", size);
- }
- if (lastf) {
- str_strlcpy(bufp, lastf, size);
- first = true;
- }
- if (seematrix(f, s))
- lastf = sidename(s);
- else
- lastf = LOC(f->locale, "unknown_faction_dative");
- break;
- }
- }
- }
- if (first) {
- bufp = STRLCPY(bufp, " ", size);
- bufp = STRLCPY(bufp, LOC(f->locale, "and"), size);
- bufp = STRLCPY(bufp, " ", size);
- }
- if (lastf) {
- bufp = STRLCPY(bufp, lastf, size);
- }
-
- m = msg_message("start_battle", "factions", zText);
- message_faction(b, f, m);
- msg_release(m);
- }
-}
-
static void print_stats(battle * b)
{
side *s2;
@@ -2947,10 +2899,10 @@ static void print_stats(battle * b)
message *msg;
char buf[1024];
- message_faction(b, f, msg_separator);
+ battle_message_faction(b, f, msg_separator);
msg = msg_message("battle_army", "index name", army_index(s), sname);
- message_faction(b, f, msg);
+ battle_message_faction(b, f, msg);
msg_release(msg);
bufp = buf;
@@ -3569,13 +3521,13 @@ static int battle_report(battle * b)
size_t size = sizeof(buf) - 1;
message *m;
- message_faction(b, fac, msg_separator);
+ battle_message_faction(b, fac, msg_separator);
if (cont)
m = msg_message("lineup_battle", "turn", b->turn);
else
m = msg_message("after_battle", "");
- message_faction(b, fac, m);
+ battle_message_faction(b, fac, m);
msg_release(m);
komma = false;
@@ -4078,7 +4030,7 @@ void do_battle(region * r)
/* Bevor wir die alliierten hineinziehen, sollten wir schauen, *
* Ob jemand fliehen kann. Dann er�brigt sich das ganze ja
* vielleicht schon. */
- print_header(b);
+ report_battle_start(b);
if (!fighting) {
/* Niemand mehr da, Kampf kann nicht stattfinden. */
message *m = msg_message("aborted_battle", "");
diff --git a/src/battle.h b/src/battle.h
index f7e84ea6b..6494a6e27 100644
--- a/src/battle.h
+++ b/src/battle.h
@@ -47,7 +47,6 @@ extern "C" {
#define LAST_ROW FLEE_ROW
#define MAXSIDES 192 /* if there are ever more than this, we're fucked. */
-
typedef struct bfaction {
struct bfaction *next;
struct side *sides;
@@ -266,6 +265,9 @@ extern "C" {
const struct faction * stealthfaction);
int skilldiff(troop at, troop dt, int dist);
void force_leave(struct region *r, struct battle *b);
+ bool seematrix(const struct faction * f, const struct side * s);
+ const char *sidename(const struct side * s);
+ void battle_message_faction(struct battle * b, struct faction * f, struct message *m);
#ifdef __cplusplus
}
diff --git a/src/kernel/faction.c b/src/kernel/faction.c
index d49bcd877..f56285b6b 100755
--- a/src/kernel/faction.c
+++ b/src/kernel/faction.c
@@ -316,7 +316,7 @@ bool checkpasswd(const faction * f, const char *passwd)
if (!passwd) return false;
if (f->_password && password_verify(f->_password, passwd) == VERIFY_FAIL) {
- log_warning("password check failed: %s", factionname(f));
+ log_info("password check failed: %s", factionname(f));
return false;
}
return true;
@@ -408,12 +408,8 @@ void save_special_items(unit *usrc)
static int cache;
static const char *name = NULL;
if (rc_changed(&cache)) {
- rc_ghost = rc_find("ghost");
- if (!rc_ghost) {
- rc_ghost = get_race(RC_TEMPLATE);
- name = "ghost";
- }
- assert(rc_ghost);
+ rc_ghost = get_race(RC_TEMPLATE);
+ name = "ghost";
}
for (u = r->units; u; u = u->next) {
if (u->faction == fm) {
diff --git a/src/kernel/order.c b/src/kernel/order.c
index 05a4ac4ba..8defd05c9 100644
--- a/src/kernel/order.c
+++ b/src/kernel/order.c
@@ -19,7 +19,6 @@
#include "keyword.h"
#include
-#include
#include
#include
#include
@@ -68,29 +67,17 @@ keyword_t getkeyword(const order * ord)
* keywords are expanded to their full length.
*/
char* get_command(const order *ord, const struct locale *lang, char *sbuffer, size_t size) {
- char *bufp = sbuffer;
order_data *od = NULL;
const char * text;
keyword_t kwd = ORD_KEYWORD(ord);
- int bytes;
+ sbstring sbs;
+ sbs_init(&sbs, sbuffer, size);
if (ord->command & CMD_QUIET) {
- if (size > 0) {
- *bufp++ = '!';
- --size;
- }
- else {
- WARN_STATIC_BUFFER();
- }
+ sbs_strcpy(&sbs, "!");
}
if (ord->command & CMD_PERSIST) {
- if (size > 0) {
- *bufp++ = '@';
- --size;
- }
- else {
- WARN_STATIC_BUFFER();
- }
+ sbs_strcat(&sbs, "@");
}
if (ord->id < 0) {
@@ -102,39 +89,19 @@ char* get_command(const order *ord, const struct locale *lang, char *sbuffer, si
text = OD_STRING(od);
}
if (kwd != NOKEYWORD) {
- if (size > 0) {
- const char *str = (const char *)LOC(lang, keyword(kwd));
- assert(str);
- if (text) --size;
- bytes = (int)str_strlcpy(bufp, str, size);
- if (wrptr(&bufp, &size, bytes) != 0) {
- WARN_STATIC_BUFFER();
- }
- if (text) *bufp++ = ' ';
- }
- else {
- WARN_STATIC_BUFFER();
+ const char *str = (const char *)LOC(lang, keyword(kwd));
+ assert(str);
+ sbs_strcat(&sbs, str);
+ if (text) {
+ sbs_strcat(&sbs, " ");
}
}
if (text) {
- bytes = (int)str_strlcpy(bufp, (const char *)text, size);
- if (wrptr(&bufp, &size, bytes) != 0) {
- WARN_STATIC_BUFFER();
- if (bufp - sbuffer >= 6) {
- bufp -= 6;
- while (bufp > sbuffer && (*bufp & 0x80) != 0) {
- ++size;
- --bufp;
- }
- memcpy(bufp, "[...]", 6); /* TODO: make sure this only happens in eval_command */
- bufp += 6;
- }
- }
+ sbs_strcat(&sbs, text);
}
if (od) {
odata_release(od);
}
- if (size > 0) *bufp = 0;
return sbuffer;
}
@@ -267,50 +234,46 @@ order *create_order(keyword_t kwd, const struct locale * lang,
order *ord;
char zBuffer[DISPLAYSIZE];
if (params) {
- char *bufp = zBuffer;
- int bytes;
- size_t size = sizeof(zBuffer) - 1;
+ sbstring sbs;
va_list marker;
+ char *tok;
assert(lang);
va_start(marker, params);
+ sbs_init(&sbs, zBuffer, sizeof(zBuffer));
while (*params) {
- if (*params == '%') {
- int i;
- const char *s;
- ++params;
- switch (*params) {
+ int i;
+ const char *s;
+ tok = strchr(params, '%');
+ if (tok) {
+ if (tok != params) {
+ sbs_strncat(&sbs, params, tok - params);
+ }
+ switch (tok[1]) {
case 's':
s = va_arg(marker, const char *);
assert(s);
- bytes = (int)str_strlcpy(bufp, s, size);
- if (wrptr(&bufp, &size, bytes) != 0)
- WARN_STATIC_BUFFER();
+ sbs_strcat(&sbs, s);
break;
case 'd':
i = va_arg(marker, int);
- bytes = (int)str_strlcpy(bufp, itoa10(i), size);
- if (wrptr(&bufp, &size, bytes) != 0)
- WARN_STATIC_BUFFER();
+ sbs_strcat(&sbs, itoa10(i));
break;
case 'i':
i = va_arg(marker, int);
- bytes = (int)str_strlcpy(bufp, itoa36(i), size);
- if (wrptr(&bufp, &size, bytes) != 0)
- WARN_STATIC_BUFFER();
+ sbs_strcat(&sbs, itoa36(i));
break;
default:
assert(!"unknown format-character in create_order");
}
+ params = tok + 2;
}
- else if (size > 0) {
- *bufp++ = *params;
- --size;
+ else {
+ sbs_strcat(&sbs, params);
+ break;
}
- ++params;
}
va_end(marker);
- *bufp = 0;
}
else {
zBuffer[0] = 0;
diff --git a/src/report.c b/src/report.c
index c431f1b1b..e154ab045 100644
--- a/src/report.c
+++ b/src/report.c
@@ -2230,7 +2230,7 @@ report_plaintext(const char *filename, report_context * ctx,
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
- ++m;
+ ++rm;
if (rm->number)
bytes = (int)str_strlcpy(bufp, ", ", size);
if (wrptr(&bufp, &size, bytes) != 0)
diff --git a/src/reports.c b/src/reports.c
index ff289c8d0..da4b2af45 100644
--- a/src/reports.c
+++ b/src/reports.c
@@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include
#include "reports.h"
+#include "battle.h"
#include "calendar.h"
#include "guard.h"
#include "laws.h"
@@ -2030,6 +2031,54 @@ static void eval_order(struct opstack **stack, const void *userdata)
opush(stack, var);
}
+void report_battle_start(battle * b)
+{
+ bfaction *bf;
+ char zText[32 * MAXSIDES];
+ sbstring sbs;
+
+ for (bf = b->factions; bf; bf = bf->next) {
+ message *m;
+ faction *f = bf->faction;
+ const char *lastf = NULL;
+ bool first = false;
+ side *s;
+
+ sbs_init(&sbs, zText, sizeof(zText));
+ for (s = b->sides; s != b->sides + b->nsides; ++s) {
+ fighter *df;
+ for (df = s->fighters; df; df = df->next) {
+ if (is_attacker(df)) {
+ if (first) {
+ sbs_strcpy(&sbs, ", ");
+ }
+ if (lastf) {
+ sbs_strcpy(&sbs, lastf);
+ first = true;
+ }
+ if (seematrix(f, s))
+ lastf = sidename(s);
+ else
+ lastf = LOC(f->locale, "unknown_faction_dative");
+ break;
+ }
+ }
+ }
+ if (first) {
+ sbs_strcpy(&sbs, " ");
+ sbs_strcpy(&sbs, LOC(f->locale, "and"));
+ sbs_strcpy(&sbs, " ");
+ }
+ if (lastf) {
+ sbs_strcpy(&sbs, lastf);
+ }
+
+ m = msg_message("start_battle", "factions", zText);
+ battle_message_faction(b, f, m);
+ msg_release(m);
+ }
+}
+
static void eval_resources(struct opstack **stack, const void *userdata)
{ /* order -> string */
const faction *f = (const faction *)userdata;
diff --git a/src/reports.h b/src/reports.h
index f30dfc051..3eaa6137c 100644
--- a/src/reports.h
+++ b/src/reports.h
@@ -29,6 +29,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" {
#endif
+ struct battle;
struct gamedate;
struct selist;
struct stream;
@@ -97,6 +98,7 @@ extern "C" {
const struct locale *lang);
size_t report_status(const struct unit *u,
const struct locale *lang, char *buf, size_t siz);
+ void report_battle_start(struct battle * b);
void register_reports(void);
diff --git a/src/util/strings.c b/src/util/strings.c
index 9350f4d5e..d3a1b2eec 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -238,3 +238,44 @@ char *str_strdup(const char *s) {
return strdup(s);
#endif
}
+
+void sbs_init(struct sbstring *sbs, char *buffer, size_t size)
+{
+ assert(sbs);
+ assert(size>0);
+ sbs->begin = buffer;
+ sbs->size = size;
+ sbs->end = buffer;
+ buffer[0] = '\0';
+}
+
+void sbs_strncat(struct sbstring *sbs, const char *str, size_t size)
+{
+ size_t len;
+ assert(sbs);
+ len = sbs->size - (sbs->end - sbs->begin) - 1;
+ if (len < size) {
+ size = len;
+ }
+ memcpy(sbs->end, str, size);
+ sbs->end[size] = '\0';
+ sbs->end += size;
+}
+
+void sbs_strcat(struct sbstring *sbs, const char *str)
+{
+ size_t len;
+ assert(sbs);
+ len = sbs->size - (sbs->end - sbs->begin);
+ len = str_strlcpy(sbs->end, str, len);
+ sbs->end += len;
+}
+
+void sbs_strcpy(struct sbstring *sbs, const char *str)
+{
+ size_t len = str_strlcpy(sbs->begin, str, sbs->size);
+ if (len >= sbs->size) {
+ len = sbs->size - 1;
+ }
+ sbs->end = sbs->begin + len;
+}
diff --git a/src/util/strings.h b/src/util/strings.h
index bc1b48d7e..76bc5a12a 100644
--- a/src/util/strings.h
+++ b/src/util/strings.h
@@ -37,6 +37,18 @@ extern "C" {
unsigned int jenkins_hash(unsigned int a);
unsigned int wang_hash(unsigned int a);
+ /* static buffered string */
+ typedef struct sbstring {
+ size_t size;
+ char *begin;
+ char *end;
+ } sbstring;
+
+ void sbs_init(struct sbstring *sbs, char *buffer, size_t size);
+ void sbs_strcat(struct sbstring *sbs, const char *str);
+ void sbs_strncat(struct sbstring *sbs, const char *str, size_t size);
+ void sbs_strcpy(struct sbstring *sbs, const char *str);
+
/* benchmark for units:
* JENKINS_HASH: 5.25 misses/hit (with good cache behavior)
* WANG_HASH: 5.33 misses/hit (with good cache behavior)
diff --git a/src/util/strings.test.c b/src/util/strings.test.c
index 68a7fefe0..89c880a70 100644
--- a/src/util/strings.test.c
+++ b/src/util/strings.test.c
@@ -91,6 +91,32 @@ static void test_str_strlcpy(CuTest * tc)
errno = 0;
}
+static void test_sbstring(CuTest * tc)
+{
+ char buffer[16];
+ sbstring sbs;
+ sbs_init(&sbs, buffer, sizeof(buffer));
+ CuAssertStrEquals(tc, "", sbs.begin);
+ sbs_strcpy(&sbs, "Hodor");
+ CuAssertStrEquals(tc, "Hodor", sbs.begin);
+ sbs_strcat(&sbs, "Hodor");
+ CuAssertStrEquals(tc, "HodorHodor", sbs.begin);
+ sbs_strcpy(&sbs, "Hodor");
+ CuAssertStrEquals(tc, "Hodor", sbs.begin);
+ sbs_strcpy(&sbs, "12345678901234567890");
+ CuAssertStrEquals(tc, "123456789012345", sbs.begin);
+ CuAssertPtrEquals(tc, sbs.begin + sbs.size - 1, sbs.end);
+ sbs_strcat(&sbs, "12345678901234567890");
+ CuAssertStrEquals(tc, "123456789012345", sbs.begin);
+ CuAssertPtrEquals(tc, buffer, sbs.begin);
+ sbs_strcpy(&sbs, "1234567890");
+ CuAssertStrEquals(tc, "1234567890", sbs.begin);
+ sbs_strncat(&sbs, "1234567890", 4);
+ CuAssertStrEquals(tc, "12345678901234", sbs.begin);
+ sbs_strncat(&sbs, "567890", 6);
+ CuAssertStrEquals(tc, "123456789012345", sbs.begin);
+}
+
CuSuite *get_strings_suite(void)
{
CuSuite *suite = CuSuiteNew();
@@ -100,5 +126,6 @@ CuSuite *get_strings_suite(void)
SUITE_ADD_TEST(suite, test_str_slprintf);
SUITE_ADD_TEST(suite, test_str_strlcat);
SUITE_ADD_TEST(suite, test_str_strlcpy);
+ SUITE_ADD_TEST(suite, test_sbstring);
return suite;
}