Merge pull request #88 from badgerman/parser-static-removal

parser refactoring, tests and cleanup.
This commit is contained in:
Enno Rehling 2014-12-23 13:27:35 +01:00
commit 1ba7248e48
22 changed files with 1074 additions and 959 deletions

View File

@ -476,7 +476,8 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
n = getuint();
if (u->number == 0) {
str = getstrtoken();
char token[128];
str = gettoken(token, sizeof(token));
if (str && str[0]) {
/* Monsters can RECRUIT 15 DRACOID
* also: secondary race */
@ -626,6 +627,7 @@ void give_control(unit * u, unit * u2)
int give_control_cmd(unit * u, order * ord)
{
char token[128];
region *r = u->region;
unit *u2;
const char *s;
@ -633,7 +635,7 @@ int give_control_cmd(unit * u, order * ord)
init_order(ord);
getunit(r, u->faction, &u2);
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (s && isparam(s, u->faction->locale, P_CONTROL)) {
message *msg = 0;
@ -676,6 +678,7 @@ int give_control_cmd(unit * u, order * ord)
static int forget_cmd(unit * u, order * ord)
{
char token[128];
skill_t sk;
const char *s;
@ -685,7 +688,7 @@ static int forget_cmd(unit * u, order * ord)
}
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
if ((sk = get_skill(s, u->faction->locale)) != NOSKILL) {
ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk));
@ -1485,6 +1488,7 @@ static void create_item(unit * u, const item_type * itype, int want)
int make_cmd(unit * u, struct order *ord)
{
char token[128];
region *r = u->region;
const building_type *btype = 0;
const ship_type *stype = 0;
@ -1498,15 +1502,16 @@ int make_cmd(unit * u, struct order *ord)
kwd = init_order(ord);
assert(kwd == K_MAKE);
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (s) {
m = atoi((const char *)s);
sprintf(ibuf, "%d", m);
if (!strcmp(ibuf, (const char *)s)) {
/* a quantity was given */
s = getstrtoken();
} else {
s = gettoken(token, sizeof(token));
}
else {
m = INT_MAX;
}
if (s) {
@ -1520,7 +1525,7 @@ int make_cmd(unit * u, struct order *ord)
cmistake(u, ord, 275, MSG_PRODUCE);
}
else {
const char * s = getstrtoken();
const char * s = gettoken(token, sizeof(token));
direction_t d = s ? get_direction(s, u->faction->locale) : NODIRECTION;
if (d != NODIRECTION) {
build_road(r, u, m, d);
@ -1753,6 +1758,7 @@ attrib_type at_trades = {
static void buy(unit * u, request ** buyorders, struct order *ord)
{
char token[128];
region *r = u->region;
int n, k;
request *o;
@ -1836,7 +1842,7 @@ static void buy(unit * u, request ** buyorders, struct order *ord)
/* die Menge der verkauften Güter merken */
a->data.i += n;
s = getstrtoken();
s = gettoken(token, sizeof(token));
itype = s ? finditemtype(s, u->faction->locale) : 0;
if (itype != NULL) {
ltype = resource2luxury(itype->rtype);
@ -2059,6 +2065,7 @@ static void expandselling(region * r, request * sellorders, int limit)
static bool sell(unit * u, request ** sellorders, struct order *ord)
{
char token[128];
bool unlimited = true;
const item_type *itype;
const luxury_type *ltype;
@ -2076,7 +2083,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord)
kwd = init_order(ord);
assert(kwd == K_SELL);
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (findparam(s, u->faction->locale) == P_ANY) {
unlimited = false;
@ -2134,7 +2141,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord)
cmistake(u, ord, 54, MSG_COMMERCE);
return false;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
itype = s ? finditemtype(s, u->faction->locale) : 0;
ltype = itype ? resource2luxury(itype->rtype) : 0;
if (ltype == NULL) {
@ -2462,6 +2469,7 @@ static void breedhorses(region * r, unit * u)
static void breed_cmd(unit * u, struct order *ord)
{
char token[128];
int m;
const char *s;
param_t p;
@ -2475,12 +2483,12 @@ static void breed_cmd(unit * u, struct order *ord)
/* züchte [<anzahl>] <parameter> */
(void)init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
m = s ? atoi((const char *)s) : 0;
if (m != 0) {
/* first came a want-paramter */
s = getstrtoken();
s = gettoken(token, sizeof(token));
}
else {
m = INT_MAX;
@ -2543,10 +2551,6 @@ static void research_cmd(unit * u, struct order *ord)
kwd = init_order(ord);
assert(kwd == K_RESEARCH);
/*
const char *s = getstrtoken();
if (findparam(s, u->faction->locale) == P_HERBS) { */
if (eff_skill(u, SK_HERBALISM, r) < 7) {
cmistake(u, ord, 227, MSG_EVENT);

View File

@ -531,6 +531,7 @@ bool can_give_to(unit *u, unit *u2) {
void give_cmd(unit * u, order * ord)
{
char token[128];
region *r = u->region;
unit *u2;
const char *s;
@ -544,7 +545,7 @@ void give_cmd(unit * u, order * ord)
kwd = init_order(ord);
assert(kwd == K_GIVE);
err = getunit(r, u->faction, &u2);
s = getstrtoken();
s = gettoken(token, sizeof(token));
n = s ? atoip(s) : 0;
p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale);
@ -652,7 +653,7 @@ void give_cmd(unit * u, order * ord)
feedback_give_not_allowed(u, ord);
return;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (!s || *s == 0) { /* GIVE ALL items that you have */
/* do these checks once, not for each item we have: */
@ -732,11 +733,11 @@ void give_cmd(unit * u, order * ord)
msg_feedback(u, ord, "peasants_give_invalid", ""));
return;
}
s = getstrtoken(); /* skip one ahead to get the amount. */
n = atoip(s); /* n: Anzahl */
s = gettoken(token, sizeof(token)); /* skip one ahead to get the amount. */
n = s ? atoip(s) : 0; /* n: Anzahl */
n *= u2->number;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (s == NULL) {
cmistake(u, ord, 113, MSG_COMMERCE);

View File

@ -35,9 +35,10 @@ use_studypotion(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
{
if (init_order(u->thisorder) == K_STUDY) {
char token[128];
skill_t sk = NOSKILL;
skill *sv = 0;
const char * s = getstrtoken();
const char * s = gettoken(token, sizeof(token));
if (s) {
sk = get_skill(s, u->faction->locale);

View File

@ -1,7 +1,7 @@
/*
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -91,19 +91,22 @@ ship *getship(const struct region * r)
static void destroy_road(unit * u, int nmax, struct order *ord)
{
const char *s = getstrtoken();
char token[128];
const char *s = gettoken(token, sizeof(token));
direction_t d = s ? get_direction(s, u->faction->locale) : NODIRECTION;
if (d == NODIRECTION) {
/* Die Richtung wurde nicht erkannt */
cmistake(u, ord, 71, MSG_PRODUCE);
} else {
}
else {
unit *u2;
region *r = u->region;
short road, n = (short)nmax;
if (nmax > SHRT_MAX) {
n = SHRT_MAX;
} else if (nmax < 0) {
}
else if (nmax < 0) {
n = 0;
}
@ -138,6 +141,7 @@ static void destroy_road(unit * u, int nmax, struct order *ord)
int destroy_cmd(unit * u, struct order *ord)
{
char token[128];
ship *sh;
unit *u2;
region *r = u->region;
@ -150,7 +154,7 @@ int destroy_cmd(unit * u, struct order *ord)
return 0;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (findparam(s, u->faction->locale) == P_ROAD) {
destroy_road(u, INT_MAX, ord);
@ -173,7 +177,7 @@ int destroy_cmd(unit * u, struct order *ord)
if (u->building) {
building *b = u->building;
if (u!=building_owner(b)) {
if (u != building_owner(b)) {
cmistake(u, ord, 138, MSG_PRODUCE);
return 0;
}
@ -192,16 +196,18 @@ int destroy_cmd(unit * u, struct order *ord)
ADDMSG(&u->faction->msgs, msg_message("destroy", "building unit", b, u));
con = b->type->construction;
remove_building(&r->buildings, b);
} else {
}
else {
/* partial destroy */
b->size -= n;
ADDMSG(&u->faction->msgs, msg_message("destroy_partial",
"building unit", b, u));
}
} else if (u->ship) {
}
else if (u->ship) {
sh = u->ship;
if (u!=ship_owner(sh)) {
if (u != ship_owner(sh)) {
cmistake(u, ord, 138, MSG_PRODUCE);
return 0;
}
@ -222,13 +228,15 @@ int destroy_cmd(unit * u, struct order *ord)
"unit region ship", u, r, sh));
con = sh->type->construction;
remove_ship(&sh->region->ships, sh);
} else {
}
else {
/* partial destroy */
sh->size -= (sh->type->construction->maxsize * n) / 100;
ADDMSG(&u->faction->msgs, msg_message("shipdestroy_partial",
"unit region ship", u, r, sh));
}
} else {
}
else {
cmistake(u, ord, 138, MSG_PRODUCE);
return 0;
}
@ -238,7 +246,7 @@ int destroy_cmd(unit * u, struct order *ord)
int c;
for (c = 0; con->materials[c].number; ++c) {
const requirement *rq = con->materials + c;
int recycle = (rq->number * size / con->reqsize)/2;
int recycle = (rq->number * size / con->reqsize) / 2;
if (recycle) {
change_resource(u, rq->rtype, recycle);
}
@ -281,14 +289,16 @@ void build_road(region * r, unit * u, int size, direction_t d)
cmistake(u, u->thisorder, 132, MSG_PRODUCE);
return;
}
} else if (r->terrain == newterrain(T_DESERT)) {
}
else if (r->terrain == newterrain(T_DESERT)) {
const struct building_type *bt_caravan = bt_find("caravan");
/* wenn keine Karawanserei existiert */
if (!bt_caravan || !buildingtype_exists(r, bt_caravan, true)) {
cmistake(u, u->thisorder, 133, MSG_PRODUCE);
return;
}
} else if (r->terrain == newterrain(T_GLACIER)) {
}
else if (r->terrain == newterrain(T_GLACIER)) {
const struct building_type *bt_tunnel = bt_find("tunnel");
/* wenn kein Tunnel existiert */
if (!bt_tunnel || !buildingtype_exists(r, bt_tunnel, true)) {
@ -312,7 +322,8 @@ void build_road(region * r, unit * u, int size, direction_t d)
/* baumaximum anhand der rohstoffe */
if (u_race(u) == get_race(RC_STONEGOLEM)) {
n = u->number * GOLEM_STONE;
} else {
}
else {
n = get_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, left);
if (n == 0) {
cmistake(u, u->thisorder, 151, MSG_PRODUCE);
@ -357,7 +368,8 @@ void build_road(region * r, unit * u, int size, direction_t d)
++golemsused;
}
scale_number(u, u->number - golemsused);
} else {
}
else {
use_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, n);
/* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */
produceexp(u, SK_ROAD_BUILDING, _min(n, u->number));
@ -373,7 +385,7 @@ void build_road(region * r, unit * u, int size, direction_t d)
* ** ** ** ** ** ** */
static int required(int size, int msize, int maxneed)
/* um size von msize Punkten zu bauen,
/* um size von msize Punkten zu bauen,
* braucht man required von maxneed resourcen */
{
int used;
@ -386,11 +398,11 @@ static int required(int size, int msize, int maxneed)
static int
matmod(const attrib * a, const unit * u, const resource_type * material,
int value)
int value)
{
for (a = a_find((attrib *) a, &at_matmod); a && a->type == &at_matmod;
for (a = a_find((attrib *)a, &at_matmod); a && a->type == &at_matmod;
a = a->next) {
mm_fun fun = (mm_fun) a->data.f;
mm_fun fun = (mm_fun)a->data.f;
value = fun(u, material, value);
if (value < 0)
return value; /* pass errors to caller */
@ -496,7 +508,8 @@ int build(unit * u, const construction * ctype, int completed, int want)
*/
if (type->maxsize > 1) {
completed = completed % type->maxsize;
} else {
}
else {
completed = 0;
assert(type->reqsize >= 1);
}
@ -509,7 +522,8 @@ int build(unit * u, const construction * ctype, int completed, int want)
/* n = maximum buildable size */
if (type->minskill > 1) {
n = skills / type->minskill;
} else {
}
else {
n = skills;
}
/* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische)
@ -556,7 +570,8 @@ int build(unit * u, const construction * ctype, int completed, int want)
break;
--n; /* TODO: optimieren? */
}
} else {
}
else {
int maxn = canuse / type->materials[c].number;
if (maxn < n)
n = maxn;
@ -623,8 +638,8 @@ message *msg_materials_required(unit * u, order * ord,
}
int maxbuild(const unit * u, const construction * cons)
/* calculate maximum size that can be built from available material */
/* !! ignores maximum objectsize and improvements... */
/* calculate maximum size that can be built from available material */
/* !! ignores maximum objectsize and improvements... */
{
int c;
int maximum = INT_MAX;
@ -634,7 +649,8 @@ int maxbuild(const unit * u, const construction * cons)
int need = required(1, cons->reqsize, cons->materials[c].number);
if (have < need) {
return 0;
} else
}
else
maximum = _min(maximum, have / need);
}
return maximum;
@ -673,13 +689,15 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
/* vieleicht Tippfehler und die eigene Burg ist gemeint? */
if (u->building && u->building->type == btype) {
b = u->building;
} else {
}
else {
/* keine neue Burg anfangen wenn eine Nummer angegeben war */
cmistake(u, ord, 6, MSG_PRODUCE);
return 0;
}
}
} else if (u->building && u->building->type == btype) {
}
else if (u->building && u->building->type == btype) {
b = u->building;
}
@ -733,13 +751,16 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
if (b == NULL) {
if (btype->maxsize > 0) {
n = btype->maxsize - built;
} else {
}
else {
n = INT_MAX;
}
} else {
}
else {
if (b->type->maxsize > 0) {
n = b->type->maxsize - built;
} else {
}
else {
n = INT_MAX;
}
}
@ -761,7 +782,7 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
cmistake(u, ord, 50, MSG_PRODUCE);
break;
}
if (built<=0) {
if (built <= 0) {
return built;
}
/* at this point, the building size is increased. */
@ -769,7 +790,7 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
/* build a new building */
b = new_building(btype, r, lang);
b->type = btype;
fset(b, BLD_MAINTAINED|BLD_WORKING);
fset(b, BLD_MAINTAINED | BLD_WORKING);
/* Die Einheit befindet sich automatisch im Inneren der neuen Burg. */
if (u->number && leave(u, false)) {
@ -782,22 +803,26 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
if (want - built <= 0) {
/* gebäude fertig */
new_order = default_order(lang);
} else if (want != INT_MAX) {
}
else if (want != INT_MAX) {
/* reduzierte restgröße */
const char *hasspace = strchr(btname, ' ');
if (hasspace) {
new_order =
create_order(K_MAKE, lang, "%d \"%s\" %i", n - built, btname, b->no);
} else {
}
else {
new_order =
create_order(K_MAKE, lang, "%d %s %i", n - built, btname, b->no);
}
} else if (btname) {
}
else if (btname) {
/* Neues Haus, Befehl mit Gebäudename */
const char *hasspace = strchr(btname, ' ');
if (hasspace) {
new_order = create_order(K_MAKE, lang, "\"%s\" %i", btname, b->no);
} else {
}
else {
new_order = create_order(K_MAKE, lang, "%s %i", btname, b->no);
}
}
@ -828,7 +853,8 @@ static void build_ship(unit * u, ship * sh, int want)
if (can >= n) {
sh->size += n;
can -= n;
} else {
}
else {
sh->size += can;
n = can;
can = 0;
@ -850,7 +876,7 @@ static void build_ship(unit * u, ship * sh, int want)
void
create_ship(region * r, unit * u, const struct ship_type *newtype, int want,
order * ord)
order * ord)
{
ship *sh;
int msize;

View File

@ -73,10 +73,11 @@ const char *str, parser fun)
static int do_command_i(const void *keys, struct unit *u, struct order *ord)
{
char token[128];
const char *c;
variant var;
c = getstrtoken();
c = gettoken(token, sizeof(token));
if (findtoken(keys, c, &var) == E_TOK_SUCCESS) {
command *cmd = (command *)var.v;
if (cmd->nodes && *c) {

View File

@ -587,19 +587,6 @@ int change_hitpoints(unit * u, int value)
return hp;
}
unsigned int atoip(const char *s)
{
int n;
assert(s);
n = atoi(s);
if (n < 0)
n = 0;
return n;
}
bool unit_has_cursed_item(const unit * u)
{
item *itm = u->items;
@ -794,18 +781,6 @@ parse(keyword_t kword, int(*dofun) (unit *, struct order *), bool thisorder)
}
}
unsigned int getuint(void)
{
const char *s = getstrtoken();
return s ? atoip(s) : 0;
}
int getint(void)
{
const char * s = getstrtoken();
return s ? atoi(s) : 0;
}
const struct race *findrace(const char *s, const struct locale *lang)
{
void **tokens = get_translations(lang, UT_RACES);
@ -875,7 +850,8 @@ bool isparam(const char *s, const struct locale * lang, param_t param)
param_t getparam(const struct locale * lang)
{
const char *s = getstrtoken();
char token[64];
const char *s = gettoken(token, sizeof(token));
return s ? findparam(s, lang) : NOPARAM;
}
@ -909,7 +885,8 @@ static int read_newunitid(const faction * f, const region * r)
int read_unitid(const faction * f, const region * r)
{
const char *s = getstrtoken();
char token[8];
const char *s = gettoken(token, sizeof(token));
/* Da s nun nur einen string enthaelt, suchen wir ihn direkt in der
* paramliste. machen wir das nicht, dann wird getnewunit in s nach der

View File

@ -108,10 +108,6 @@ extern "C" {
/* special units */
void make_undead_unit(struct unit *);
unsigned int atoip(const char *s);
unsigned int getuint(void);
int getint(void);
param_t findparam(const char *s, const struct locale *lang);
param_t findparam_ex(const char *s, const struct locale * lang);
bool isparam(const char *s, const struct locale * lang, param_t param);

View File

@ -278,9 +278,9 @@ unit *addplayer(region * r, faction * f)
return u;
}
bool checkpasswd(const faction * f, const char *passwd, bool shortp)
bool checkpasswd(const faction * f, const char *passwd)
{
if (unicode_utf8_strcasecmp(f->passw, passwd) == 0)
if (passwd && unicode_utf8_strcasecmp(f->passw, passwd) == 0)
return true;
return false;
}

View File

@ -120,7 +120,7 @@ const char *factionname(const struct faction *f);
struct unit *addplayer(struct region *r, faction * f);
struct faction *addfaction(const char *email, const char *password,
const struct race *frace, const struct locale *loc, int subscription);
bool checkpasswd(const faction * f, const char *passwd, bool shortp);
bool checkpasswd(const faction * f, const char *passwd);
void destroyfaction(faction * f);
extern void set_alliance(struct faction *a, struct faction *b, int status);

View File

@ -207,7 +207,7 @@ static order_data *create_data(keyword_t kwd, const char *sptr, int lindex)
/* learning, only one order_data per skill required */
if (kwd == K_STUDY) {
skill_t sk = get_skill(parse_token(&sptr), lang);
skill_t sk = get_skill(parse_token_depr(&sptr), lang);
switch (sk) {
case NOSKILL: /* fehler */
break;
@ -364,11 +364,11 @@ order *parse_order(const char *s, const struct locale * lang)
++s;
}
sptr = s;
p = *sptr ? parse_token(&sptr) : 0;
p = *sptr ? parse_token_depr(&sptr) : 0;
kwd = p ? get_keyword(p, lang) : NOKEYWORD;
if (kwd == K_MAKE) {
const char *s, *sp = sptr;
s = parse_token(&sp);
s = parse_token_depr(&sp);
if (s && isparam(s, lang, P_TEMP)) {
kwd = K_MAKETEMP;
sptr = sp;
@ -570,6 +570,6 @@ keyword_t init_order(const struct order *ord)
assert(ord && ord->data);
if (ord->data->_str) cmd = _strdup(ord->data->_str);
init_tokens_str(cmd, cmd);
init_tokens_str(cmd);
return ord->data->_keyword;
}

View File

@ -128,19 +128,19 @@ static void test_init_order(CuTest *tc) {
static void test_getstrtoken(CuTest *tc) {
char *cmd = _strdup("hurr \"durr\" \"\" \'\'");
init_tokens_str(cmd, cmd);
init_tokens_str(cmd);
CuAssertStrEquals(tc, "hurr", getstrtoken());
CuAssertStrEquals(tc, "durr", getstrtoken());
CuAssertStrEquals(tc, "", getstrtoken());
CuAssertStrEquals(tc, "", getstrtoken());
CuAssertStrEquals(tc, 0, getstrtoken());
init_tokens_str(0, 0);
init_tokens_str(0);
CuAssertStrEquals(tc, 0, getstrtoken());
}
static void test_skip_token(CuTest *tc) {
char *cmd = _strdup("hurr \"durr\"");
init_tokens_str(cmd, cmd);
init_tokens_str(cmd);
skip_token();
CuAssertStrEquals(tc, "durr", getstrtoken());
CuAssertStrEquals(tc, 0, getstrtoken());

View File

@ -169,7 +169,7 @@ static unit *unitorders(FILE * F, int enc, struct faction *f)
if (s[0]) {
if (s[0] != '@') {
const char *stok = s;
stok = parse_token(&stok);
stok = parse_token_depr(&stok);
if (stok) {
bool quit = false;
@ -224,9 +224,10 @@ static faction *factionorders(void)
f = findfaction(fid);
if (f != NULL && !fval(f, FFL_NPC)) {
const char *pass = getstrtoken();
char token[128];
const char *pass = gettoken(token, sizeof(token));
if (!checkpasswd(f, (const char *)pass, true)) {
if (!checkpasswd(f, (const char *)pass)) {
log_debug("Invalid password for faction %s\n", itoa36(fid));
ADDMSG(&f->msgs, msg_message("wrongpasswd", "faction password",
f->no, pass));
@ -267,11 +268,12 @@ int readorders(const char *filename)
* Partei */
while (b) {
char token[128];
const struct locale *lang = f ? f->locale : default_locale;
param_t p;
const char *s;
init_tokens_str(b, NULL);
s = getstrtoken();
init_tokens_str(b);
s = gettoken(token, sizeof(token));
p = s ? findparam(s, lang) : NOPARAM;
switch (p) {
#undef LOCALE_CHANGE
@ -308,7 +310,7 @@ int readorders(const char *filename)
if (!b) {
break;
}
init_tokens_str(b, NULL);
init_tokens_str(b);
b = getstrtoken();
p = (!b || b[0] == '@') ? NOPARAM : findparam(b, lang);
} while ((p != P_UNIT || !f) && p != P_FACTION && p != P_NEXT

View File

@ -491,16 +491,19 @@ void usetprivate(unit * u, const char *str)
{
attrib *a = a_find(u->attribs, &at_private);
if (str == NULL) {
if (a)
if (str == NULL || *str == 0) {
if (a) {
a_remove(&u->attribs, a);
}
return;
}
if (!a)
if (!a) {
a = a_add(&u->attribs, a_new(&at_private));
if (a->data.v)
}
if (a->data.v) {
free(a->data.v);
a->data.v = _strdup((const char *)str);
}
a->data.v = _strdup(str);
}
/*********************/

View File

@ -946,14 +946,15 @@ static bool EnhancedQuit(void)
int quit_cmd(unit * u, struct order *ord)
{
char token[128];
faction *f = u->faction;
const char *passwd;
keyword_t kwd;
kwd = init_order(ord);
assert(kwd == K_QUIT);
passwd = getstrtoken();
if (checkpasswd(f, (const char *)passwd, false)) {
passwd = gettoken(token, sizeof(token));
if (checkpasswd(f, (const char *)passwd)) {
if (EnhancedQuit()) {
int f2_id = getid();
if (f2_id > 0) {
@ -1159,13 +1160,14 @@ void do_enter(struct region *r, bool is_final_attempt)
while (*ordp) {
order *ord = *ordp;
if (getkeyword(ord) == K_ENTER) {
char token[128];
param_t p;
int id;
unit *ulast = NULL;
const char * s;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
p = findparam_ex(s, u->faction->locale);
id = getid();
@ -1339,6 +1341,7 @@ void quit(void)
int ally_cmd(unit * u, struct order *ord)
{
char token[128];
ally *sf, **sfp;
faction *f;
int keyword, not_kw;
@ -1354,7 +1357,7 @@ int ally_cmd(unit * u, struct order *ord)
if (f == u->faction)
return 0;
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (!s[0])
keyword = P_ANY;
@ -1492,6 +1495,7 @@ static void init_prefixnames(void)
int prefix_cmd(unit * u, struct order *ord)
{
char token[128];
attrib **ap;
const char *s;
local_names *in = pnames;
@ -1509,7 +1513,7 @@ int prefix_cmd(unit * u, struct order *ord)
}
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (!s || !*s) {
attrib *a = NULL;
@ -1556,13 +1560,14 @@ static cmp_building_cb get_cmp_region_owner(void)
int display_cmd(unit * u, struct order *ord)
{
char token[128];
char **s = NULL;
const char *str;
region *r = u->region;
init_order(ord);
str = getstrtoken();
str = gettoken(token, sizeof(token));
switch (findparam_ex(str, u->faction->locale)) {
case P_BUILDING:
case P_GEBAEUDE:
@ -1598,15 +1603,7 @@ int display_cmd(unit * u, struct order *ord)
break;
case P_PRIVAT:
{
const char *d = getstrtoken();
if (d == NULL || *d == 0) {
usetprivate(u, NULL);
}
else {
usetprivate(u, d);
}
}
usetprivate(u, getstrtoken());
break;
case P_REGION:
@ -1729,6 +1726,7 @@ rename_building(unit * u, order * ord, building * b, const char *name)
int name_cmd(struct unit *u, struct order *ord)
{
char token[128];
building *b = u->building;
region *r = u->region;
char **s = NULL;
@ -1737,11 +1735,11 @@ int name_cmd(struct unit *u, struct order *ord)
const char *str;
init_order(ord);
str = getstrtoken();
str = gettoken(token, sizeof(token));
p = findparam_ex(str, u->faction->locale);
if (p == P_FOREIGN) {
str = getstrtoken();
str = gettoken(token, sizeof(token));
foreign = true;
p = findparam_ex(str, u->faction->locale);
}
@ -1991,13 +1989,14 @@ static void mailfaction(unit * u, int n, struct order *ord, const char *s)
int mail_cmd(unit * u, struct order *ord)
{
char token[128];
region *r = u->region;
unit *u2;
const char *s;
int n, cont;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
/* Falls kein Parameter, ist das eine Einheitsnummer;
* das Füllwort "AN" muß wegfallen, da gültige Nummer! */
@ -2018,19 +2017,15 @@ int mail_cmd(unit * u, struct order *ord)
}
case P_FACTION:
{
bool see = false;
n = getfactionid();
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->faction->no == n && seefaction(u->faction, r, u2, 0)) {
see = true;
break;
}
}
if (!see) {
if (!u2) {
cmistake(u, ord, 66, MSG_MESSAGE);
break;
}
@ -2042,21 +2037,17 @@ int mail_cmd(unit * u, struct order *ord)
}
mailfaction(u, n, ord, s);
return 0;
}
case P_UNIT:
{
bool see = false;
n = getid();
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->no == n && cansee(u->faction, r, u2, 0)) {
see = true;
break;
}
}
if (!see) {
if (!u2) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
"feedback_unit_not_found", ""));
return 0;
@ -2082,7 +2073,6 @@ int mail_cmd(unit * u, struct order *ord)
mailunit(r, u, n, ord, s);
}
return 0;
}
case P_BUILDING:
case P_GEBAEUDE:
@ -2182,7 +2172,7 @@ int email_cmd(unit * u, struct order *ord)
}
else {
faction *f = u->faction;
if (set_email(&f->email, (const char *)s) != 0) {
if (set_email(&f->email, s) != 0) {
log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), s);
ADDMSG(&f->msgs, msg_message("changemail_invalid", "value", s));
}
@ -2201,7 +2191,7 @@ int password_cmd(unit * u, struct order *ord)
bool pwok = true;
init_order(ord);
s = getstrtoken();
s = gettoken(pwbuf, sizeof(pwbuf));
if (!s || !*s) {
for (i = 0; i < 6; i++)
@ -2210,14 +2200,10 @@ int password_cmd(unit * u, struct order *ord)
}
else {
char *c;
strlcpy(pwbuf, (const char *)s, 31);
pwbuf[31] = 0;
c = pwbuf;
while (*c && pwok) {
if (!isalnum(*(unsigned char *)c))
for (c = pwbuf; *c && pwok; ++c) {
if (!isalnum(*(unsigned char *)c)) {
pwok = false;
c++;
}
}
}
free(u->faction->passw);
@ -2235,11 +2221,12 @@ int password_cmd(unit * u, struct order *ord)
int send_cmd(unit * u, struct order *ord)
{
char token[128];
const char *s;
int option;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
option = findoption(s, u->faction->locale);
@ -2576,14 +2563,11 @@ int promotion_cmd(unit * u, struct order *ord)
int group_cmd(unit * u, struct order *ord)
{
const char *s;
keyword_t kwd;
kwd = init_order(ord);
assert(kwd == K_GROUP);
s = getstrtoken();
join_group(u, s);
join_group(u, getstrtoken());
return 0;
}
@ -2613,11 +2597,12 @@ int guard_off_cmd(unit * u, struct order *ord)
int reshow_cmd(unit * u, struct order *ord)
{
char lbuf[64];
const char *s;
param_t p = NOPARAM;
init_order(ord);
s = getstrtoken();
s = gettoken(lbuf, sizeof(lbuf));
if (s && isparam(s, u->faction->locale, P_ANY)) {
p = getparam(u->faction->locale);
@ -2630,12 +2615,12 @@ int reshow_cmd(unit * u, struct order *ord)
int status_cmd(unit * u, struct order *ord)
{
const char *param;
char token[128];
const char *s;
init_order(ord);
param = getstrtoken();
switch (findparam(param, u->faction->locale)) {
s = gettoken(token, sizeof(token));
switch (findparam(s, u->faction->locale)) {
case P_NOT:
setstatus(u, ST_AVOID);
break;
@ -2663,7 +2648,7 @@ int status_cmd(unit * u, struct order *ord)
}
break;
default:
if (param && param[0]) {
if (s && s[0]) {
add_message(&u->faction->msgs,
msg_feedback(u, ord, "unknown_status", ""));
}
@ -2676,12 +2661,13 @@ int status_cmd(unit * u, struct order *ord)
int combatspell_cmd(unit * u, struct order *ord)
{
char token[128];
const char *s;
int level = 0;
spell *sp = 0;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
/* KAMPFZAUBER [NICHT] löscht alle gesetzten Kampfzauber */
if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) {
@ -2694,7 +2680,7 @@ int combatspell_cmd(unit * u, struct order *ord)
/* Merken, setzen kommt erst später */
level = getint();
level = _max(0, level);
s = getstrtoken();
s = gettoken(token, sizeof(token));
}
sp = unit_getspell(u, s, u->faction->locale);
@ -2703,7 +2689,7 @@ int combatspell_cmd(unit * u, struct order *ord)
return 0;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (findparam(s, u->faction->locale) == P_NOT) {
/* KAMPFZAUBER "<Spruchname>" NICHT löscht diesen speziellen
@ -2921,13 +2907,14 @@ void restack_units(void)
struct order *ord;
for (ord = u->orders; ord; ord = ord->next) {
if (getkeyword(ord) == K_SORT) {
char token[128];
const char *s;
param_t p;
int id;
unit *v;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
p = findparam(s, u->faction->locale);
id = getid();
v = findunit(id);
@ -2997,16 +2984,17 @@ void restack_units(void)
int renumber_cmd(unit * u, order * ord)
{
char token[128];
const char *s;
int i;
faction *f = u->faction;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
switch (findparam_ex(s, u->faction->locale)) {
case P_FACTION:
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (s && *s) {
int id = atoi36((const char *)s);
attrib *a = a_find(f->attribs, &at_number);
@ -3017,7 +3005,7 @@ int renumber_cmd(unit * u, order * ord)
break;
case P_UNIT:
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (s == NULL || *s == 0) {
i = newunitid();
}
@ -3060,7 +3048,7 @@ int renumber_cmd(unit * u, order * ord)
cmistake(u, ord, 116, MSG_EVENT);
break;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (s == NULL || *s == 0) {
i = newcontainerid();
}
@ -3089,7 +3077,7 @@ int renumber_cmd(unit * u, order * ord)
cmistake(u, ord, 148, MSG_EVENT);
break;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (*s == 0) {
i = newcontainerid();
}
@ -3355,8 +3343,8 @@ void new_units(void)
while (*ordp) {
order *makeord = *ordp;
if (getkeyword(makeord) == K_MAKETEMP) {
const char *token;
char *name = NULL;
char token[128], *name = NULL;
const char *s;
int alias;
ship *sh;
order **newordersp;
@ -3390,9 +3378,9 @@ void new_units(void)
init_order(makeord);
alias = getid();
token = getstrtoken();
if (token && token[0]) {
name = _strdup(token);
s = gettoken(token, sizeof(token));
if (s && s[0]) {
name = _strdup(s);
}
u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u);
if (name != NULL)
@ -3700,10 +3688,9 @@ void defaultorders(void)
order *new_order = 0;
const char *s;
init_order(ord);
s = getstrtoken();
s = gettoken(lbuf, sizeof(lbuf));
if (s) {
strcpy(lbuf, s);
new_order = parse_order(lbuf, u->faction->locale);
new_order = parse_order(s, u->faction->locale);
}
*ordp = ord->next;
ord->next = NULL;
@ -3810,19 +3797,20 @@ static void update_spells(void)
int use_cmd(unit * u, struct order *ord)
{
char token[128];
const char *t;
int n, err = ENOITEM;
const item_type *itype;
init_order(ord);
t = getstrtoken();
t = gettoken(token, sizeof(token));
n = atoi((const char *)t);
if (n == 0) {
if (isparam(t, u->faction->locale, P_ANY)) {
/* BENUTZE ALLES Yanxspirit */
n = INT_MAX;
t = getstrtoken();
t = gettoken(token, sizeof(token));
}
else {
/* BENUTZE Yanxspirit */
@ -3831,7 +3819,7 @@ int use_cmd(unit * u, struct order *ord)
}
else {
/* BENUTZE 42 Yanxspirit */
t = getstrtoken();
t = gettoken(token, sizeof(token));
}
itype = t ? finditemtype(t, u->faction->locale) : NULL;
@ -3913,20 +3901,21 @@ int pay_cmd(unit * u, struct order *ord)
static int reserve_i(unit * u, struct order *ord, int flags)
{
char token[128];
if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) {
int use, count, para;
const item_type *itype;
const char *s;
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
count = s ? atoip(s) : 0;
para = findparam(s, u->faction->locale);
if (count == 0 && para == P_EACH) {
count = getint() * u->number;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
itype = s ? finditemtype(s, u->faction->locale) : 0;
if (itype == NULL)
return 0;
@ -3956,19 +3945,20 @@ int reserve_self(unit * u, struct order *ord) {
int claim_cmd(unit * u, struct order *ord)
{
char token[128];
const char *t;
int n;
const item_type *itype;
init_order(ord);
t = getstrtoken();
t = gettoken(token, sizeof(token));
n = atoi((const char *)t);
if (n == 0) {
n = 1;
}
else {
t = getstrtoken();
t = gettoken(token, sizeof(token));
}
itype = finditemtype(t, u->faction->locale);

View File

@ -2495,6 +2495,7 @@ static bool is_moving_ship(const region * r, ship * sh)
static castorder *cast_cmd(unit * u, order * ord)
{
char token[128];
region *r = u->region;
region *target_r = r;
int level, range;
@ -2518,7 +2519,7 @@ static castorder *cast_cmd(unit * u, order * ord)
level = eff_skill(u, SK_MAGIC, r);
init_order(ord);
s = getstrtoken();
s = gettoken(token, sizeof(token));
param = findparam(s, u->faction->locale);
/* für Syntax ' STUFE x REGION y z ' */
if (param == P_LEVEL) {
@ -2529,7 +2530,7 @@ static castorder *cast_cmd(unit * u, order * ord)
cmistake(u, ord, 10, MSG_MAGIC);
return 0;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
param = findparam(s, u->faction->locale);
}
if (param == P_REGION) {
@ -2546,7 +2547,7 @@ static castorder *cast_cmd(unit * u, order * ord)
"unit region command", u, u->region, ord));
return 0;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
param = findparam(s, u->faction->locale);
}
/* für Syntax ' REGION x y STUFE z '
@ -2559,7 +2560,7 @@ static castorder *cast_cmd(unit * u, order * ord)
cmistake(u, ord, 10, MSG_MAGIC);
return 0;
}
s = getstrtoken();
s = gettoken(token, sizeof(token));
}
if (!s || !s[0] || strlen(s) == 0) {
/* Fehler "Es wurde kein Zauber angegeben" */
@ -2692,7 +2693,7 @@ static castorder *cast_cmd(unit * u, order * ord)
char **params = (char**)malloc(2 * sizeof(char *));
int p = 0, size = 2;
for (;;) {
s = getstrtoken();
s = gettoken(token, sizeof(token));
if (!s || *s == 0)
break;
if (p + 1 >= size) {
@ -2935,7 +2936,7 @@ spell *unit_getspell(struct unit *u, const char *name, const struct locale * lan
if (sb) {
select_spellbook(&tokens, sb, lang);
}
#if 0 // TODO: some familiars can cast spells from the mage's spellbook?
u = get_familiar_mage(u);
if (u) {
sb = unit_get_spellbook(u);
@ -2943,6 +2944,7 @@ spell *unit_getspell(struct unit *u, const char *name, const struct locale * lan
select_spellbook(&tokens, sb, lang);
}
}
#endif
if (tokens) {
variant token;

View File

@ -1156,7 +1156,7 @@ static void cycle_route(order * ord, unit * u, int gereist)
int bytes, cm = 0;
char tail[1024], *bufp = tail;
char neworder[2048];
const char *token;
char token[128];
direction_t d = NODIRECTION;
bool paused = false;
bool pause;
@ -1171,11 +1171,12 @@ static void cycle_route(order * ord, unit * u, int gereist)
neworder[0] = 0;
for (cm = 0;; ++cm) {
const char *s;
const struct locale *lang = u->faction->locale;
pause = false;
token = getstrtoken();
if (token && *token) {
d = get_direction(token, lang);
s = gettoken(token, sizeof(token));
if (s && *s) {
d = get_direction(s, lang);
if (d == D_PAUSE) {
pause = true;
}
@ -1448,11 +1449,12 @@ static void make_route(unit * u, order * ord, region_list ** routep)
region_list **iroute = routep;
region *current = u->region;
region *next = NULL;
const char *token = getstrtoken();
int error = movewhere(u, token, current, &next);
char token[128];
const char *s = gettoken(token, sizeof(token));
int error = movewhere(u, s, current, &next);
if (error != E_MOVE_OK) {
message *msg = movement_error(u, token, ord, error);
message *msg = movement_error(u, s, ord, error);
if (msg != NULL) {
add_message(&u->faction->msgs, msg);
msg_release(msg);
@ -1471,10 +1473,10 @@ static void make_route(unit * u, order * ord, region_list ** routep)
iroute = &(*iroute)->next;
current = next;
token = getstrtoken();
error = movewhere(u, token, current, &next);
s = gettoken(token, sizeof(token));
error = movewhere(u, s, current, &next);
if (error) {
message *msg = movement_error(u, token, ord, error);
message *msg = movement_error(u, s, ord, error);
if (msg != NULL) {
add_message(&u->faction->msgs, msg);
msg_release(msg);
@ -2615,7 +2617,7 @@ static int hunt(unit * u, order * ord)
/* In command steht jetzt das NACH-Kommando. */
/* NACH ignorieren und Parsing initialisieren. */
init_tokens_str(command, NULL);
init_tokens_str(command);
getstrtoken();
/* NACH ausführen */
move(u, false);

View File

@ -58,7 +58,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
static skill_t getskill(const struct locale *lang)
{
const char * s = getstrtoken();
char token[128];
const char * s = gettoken(token, sizeof(token));
return s ? get_skill(s, lang) : NOSKILL;
}

View File

@ -48,6 +48,7 @@ int RunAllTests(void)
RUN_TESTS(suite, base36);
RUN_TESTS(suite, bsdstring);
RUN_TESTS(suite, functions);
RUN_TESTS(suite, parser);
RUN_TESTS(suite, umlaut);
RUN_TESTS(suite, unicode);
RUN_TESTS(suite, strings);

View File

@ -2,6 +2,7 @@ project(util C)
SET(_TEST_FILES
base36.test.c
parser.test.c
attrib.test.c
strings.test.c
bsdstring.test.c

View File

@ -15,7 +15,6 @@
typedef struct parser_state {
const char *current_token;
char *current_cmd;
struct parser_state *next;
} parser_state;
@ -50,22 +49,17 @@ static int eatwhitespace_c(const char **str_p)
return ret;
}
void init_tokens_str(const char *initstr, char *cmd)
void init_tokens_str(const char *initstr)
{
if (states == NULL) {
states = malloc(sizeof(parser_state));
}
else if (states->current_cmd && states->current_cmd!=cmd) {
free(states->current_cmd);
}
states->current_cmd = cmd;
states->current_token = initstr;
}
void parser_pushstate(void)
{
parser_state *new_state = malloc(sizeof(parser_state));
new_state->current_cmd = NULL;
new_state->current_token = NULL;
new_state->next = states;
states = new_state;
@ -74,8 +68,6 @@ void parser_pushstate(void)
void parser_popstate(void)
{
parser_state *new_state = states->next;
if (states->current_cmd != NULL)
free(states->current_cmd);
free(states);
states = new_state;
}
@ -128,9 +120,8 @@ void skip_token(void)
}
}
const char *parse_token(const char **str)
char *parse_token(const char **str, char *lbuf, size_t len)
{
static char lbuf[MAXTOKENSIZE]; /* STATIC_RESULT: used for return, not across calls */
char *cursor = lbuf;
char quotechar = 0;
bool escape = false;
@ -141,9 +132,12 @@ const char *parse_token(const char **str)
}
eatwhitespace_c(&ctoken);
if (!*ctoken) {
if (len > 0) {
*cursor = 0;
}
return 0;
}
while (*ctoken && cursor - lbuf < MAXTOKENSIZE - 1) {
while (*ctoken && cursor-len < lbuf-1) {
ucs4_t ucs;
size_t len;
bool copy = false;
@ -152,7 +146,8 @@ const char *parse_token(const char **str)
if (~utf8_character & 0x80) {
ucs = utf8_character;
len = 1;
} else {
}
else {
int ret = unicode_utf8_to_ucs4(&ucs, ctoken, &len);
if (ret != 0) {
log_warning("illegal character sequence in UTF8 string: %s\n", ctoken);
@ -162,27 +157,34 @@ const char *parse_token(const char **str)
if (escape) {
copy = true;
escape = false;
} else if (iswxspace((wint_t) ucs)) {
}
else if (iswxspace((wint_t)ucs)) {
if (quotechar == 0)
break;
copy = true;
} else if (utf8_character == '"' || utf8_character == '\'') {
}
else if (utf8_character == '"' || utf8_character == '\'') {
if (utf8_character == quotechar) {
++ctoken;
break;
} else if (quotechar == 0) {
}
else if (quotechar == 0) {
quotechar = utf8_character;
++ctoken;
} else {
}
else {
*cursor++ = *ctoken++;
}
} else if (utf8_character == SPACE_REPLACEMENT) {
}
else if (utf8_character == SPACE_REPLACEMENT) {
*cursor++ = ' ';
++ctoken;
} else if (utf8_character == ESCAPE_CHAR) {
}
else if (utf8_character == ESCAPE_CHAR) {
escape = true;
++ctoken;
} else {
}
else {
copy = true;
}
if (copy) {
@ -192,22 +194,62 @@ const char *parse_token(const char **str)
}
}
assert(cursor - len < lbuf - 1); // TODO: handle too-small buffers
*cursor = '\0';
*str = ctoken;
return lbuf;
}
const char *parse_token_depr(const char **str)
{
static char lbuf[MAXTOKENSIZE]; /* STATIC_RESULT: used for return, not across calls */
return parse_token(str, lbuf, MAXTOKENSIZE);
}
const char *getstrtoken(void)
{
return parse_token((const char **)&states->current_token);
char lbuf[MAXTOKENSIZE];
return parse_token((const char **)&states->current_token, lbuf, MAXTOKENSIZE);
}
const char *gettoken(char *lbuf, size_t bufsize)
{
return parse_token((const char **)&states->current_token, lbuf, bufsize);
}
int getint(void)
{
char token[16];
const char * s = gettoken(token, sizeof(token));
return s ? atoi(s) : 0;
}
unsigned int getuint(void)
{
int n = getint();
return (n < 0) ? 0 : n;
}
int getid(void)
{
const char *str = getstrtoken();
char token[16];
const char *str = gettoken(token, sizeof(token));
int i = str ? atoi36(str) : 0;
if (i < 0) {
return -1;
}
return i;
}
unsigned int atoip(const char *s)
{
int n;
assert(s);
n = atoi(s);
if (n < 0)
n = 0;
return n;
}

View File

@ -14,14 +14,20 @@
extern "C" {
#endif
void init_tokens_str(const char *initstr, char *cmd); /* initialize token parsing, take ownership of cmd */
void init_tokens_str(const char *initstr); /* initialize token parsing */
void skip_token(void);
const char *parse_token(const char **str);
const char *parse_token_depr(const char **str);
char *parse_token(const char **str, char *buffer, size_t bufsize);
void parser_pushstate(void);
void parser_popstate(void);
bool parser_end(void);
const char *getstrtoken(void);
const char *gettoken(char *lbuf, size_t bufsize);
unsigned int getuint(void);
int getint(void);
int getid(void);
unsigned int atoip(const char *s);
#define getshipid() getid()
#define getfactionid() getid()

59
src/util/parser.test.c Normal file
View File

@ -0,0 +1,59 @@
#include <platform.h>
#include "parser.h"
#include <CuTest.h>
static void test_gettoken(CuTest *tc) {
char token[128];
init_tokens_str("HELP ONE TWO THREE");
CuAssertStrEquals(tc, "HELP", gettoken(token, sizeof(token)));
CuAssertStrEquals(tc, "HELP", token);
CuAssertStrEquals(tc, "ONE", gettoken(token, sizeof(token)));
CuAssertStrEquals(tc, "TWO", gettoken(token, sizeof(token)));
CuAssertStrEquals(tc, "THREE", gettoken(token, sizeof(token)));
CuAssertPtrEquals(tc, NULL, (void *)gettoken(token, sizeof(token)));
CuAssertStrEquals(tc, "", token);
}
static void test_skip_token(CuTest *tc) {
char token[128];
init_tokens_str("HELP ONE TWO THREE");
skip_token();
CuAssertStrEquals(tc, "ONE", gettoken(token, sizeof(token)));
}
static void test_getintegers(CuTest *tc) {
init_tokens_str("ii 666 666 -42 -42");
CuAssertIntEquals(tc, 666, getid());
CuAssertIntEquals(tc, 666, getint());
CuAssertIntEquals(tc, 666, getuint());
CuAssertIntEquals(tc, -42, getint());
CuAssertIntEquals(tc, 0, getuint());
CuAssertIntEquals(tc, 0, getint());
}
static void test_getstrtoken(CuTest *tc) {
init_tokens_str("HELP ONE TWO THREE");
CuAssertStrEquals(tc, "HELP", getstrtoken());
CuAssertStrEquals(tc, "ONE", getstrtoken());
CuAssertStrEquals(tc, "TWO", getstrtoken());
CuAssertStrEquals(tc, "THREE", getstrtoken());
CuAssertPtrEquals(tc, NULL, (void *)getstrtoken());
}
static void test_atoip(CuTest *tc) {
CuAssertIntEquals(tc, 42, atoip("42"));
CuAssertIntEquals(tc, 0, atoip("-42"));
CuAssertIntEquals(tc, 0, atoip("NOPE"));
}
CuSuite *get_parser_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_atoip);
SUITE_ADD_TEST(suite, test_skip_token);
SUITE_ADD_TEST(suite, test_gettoken);
SUITE_ADD_TEST(suite, test_getintegers);
SUITE_ADD_TEST(suite, test_getstrtoken);
return suite;
}