diff --git a/src/economy.c b/src/economy.c index 7c8321d88..0fb810848 100644 --- a/src/economy.c +++ b/src/economy.c @@ -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)); @@ -1499,14 +1502,14 @@ int make_cmd(unit * u, struct order *ord) kwd = init_order(ord); assert(kwd == K_MAKE); - s = getstrtok(token, sizeof(token)); + 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 = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); } else { m = INT_MAX; @@ -1522,7 +1525,7 @@ int make_cmd(unit * u, struct order *ord) cmistake(u, ord, 275, MSG_PRODUCE); } else { - const char * s = getstrtok(token, sizeof(token)); + 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); @@ -1755,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; @@ -1838,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); @@ -2061,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; @@ -2078,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; @@ -2136,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) { @@ -2464,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; @@ -2477,12 +2483,12 @@ static void breed_cmd(unit * u, struct order *ord) /* züchte [] */ (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; @@ -2545,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); diff --git a/src/give.c b/src/give.c index 71928f630..913226bb4 100644 --- a/src/give.c +++ b/src/give.c @@ -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); diff --git a/src/items.c b/src/items.c index 49d7a2652..012dc9f7c 100644 --- a/src/items.c +++ b/src/items.c @@ -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); diff --git a/src/kernel/build.c b/src/kernel/build.c index 6c0b8c76e..a3abdf43e 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -1,7 +1,7 @@ /* Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -69,20 +69,20 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. struct building *getbuilding(const struct region *r) { - building *b = findbuilding(getid()); - if (b == NULL || r != b->region) - return NULL; - return b; + building *b = findbuilding(getid()); + if (b == NULL || r != b->region) + return NULL; + return b; } ship *getship(const struct region * r) { - ship *sh, *sx = findship(getshipid()); - for (sh = r->ships; sh; sh = sh->next) { - if (sh == sx) - return sh; - } - return NULL; + ship *sh, *sx = findship(getshipid()); + for (sh = r->ships; sh; sh = sh->next) { + if (sh == sx) + return sh; + } + return NULL; } /* ------------------------------------------------------------- */ @@ -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; } @@ -126,244 +129,253 @@ static void destroy_road(unit * u, int nmax, struct order *ord) /* TODO: error message */ } if (willdo > SHRT_MAX) - road = 0; + road = 0; else - road = road - (short)willdo; + road = road - (short)willdo; rsetroad(r, d, road); ADDMSG(&u->faction->msgs, msg_message("destroy_road", - "unit from to", u, r, r2)); + "unit from to", u, r, r2)); } } } int destroy_cmd(unit * u, struct order *ord) { - ship *sh; - unit *u2; - region *r = u->region; - const construction *con = NULL; - int size = 0; - const char *s; - int n = INT_MAX; + char token[128]; + ship *sh; + unit *u2; + region *r = u->region; + const construction *con = NULL; + int size = 0; + const char *s; + int n = INT_MAX; - if (u->number < 1) - return 0; + if (u->number < 1) + return 0; - init_order(ord); - s = getstrtoken(); + init_order(ord); + s = gettoken(token, sizeof(token)); - if (findparam(s, u->faction->locale) == P_ROAD) { - destroy_road(u, INT_MAX, ord); - return 0; - } - - if (s && *s) { - n = atoi((const char *)s); - if (n <= 0) { - cmistake(u, ord, 288, MSG_PRODUCE); - return 0; + if (findparam(s, u->faction->locale) == P_ROAD) { + destroy_road(u, INT_MAX, ord); + return 0; } - } - if (getparam(u->faction->locale) == P_ROAD) { - destroy_road(u, n, ord); - return 0; - } - - if (u->building) { - building *b = u->building; - - if (u!=building_owner(b)) { - cmistake(u, ord, 138, MSG_PRODUCE); - return 0; - } - if (fval(b->type, BTF_INDESTRUCTIBLE)) { - cmistake(u, ord, 138, MSG_PRODUCE); - return 0; - } - if (n >= b->size) { - /* destroy completly */ - /* all units leave the building */ - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->building == b) { - leave_building(u2); + if (s && *s) { + n = atoi((const char *)s); + if (n <= 0) { + cmistake(u, ord, 288, MSG_PRODUCE); + return 0; } - } - ADDMSG(&u->faction->msgs, msg_message("destroy", "building unit", b, u)); - con = b->type->construction; - remove_building(&r->buildings, b); - } else { - /* partial destroy */ - b->size -= n; - ADDMSG(&u->faction->msgs, msg_message("destroy_partial", - "building unit", b, u)); - } - } else if (u->ship) { - sh = u->ship; - - if (u!=ship_owner(sh)) { - cmistake(u, ord, 138, MSG_PRODUCE); - return 0; - } - if (fval(r->terrain, SEA_REGION)) { - cmistake(u, ord, 14, MSG_EVENT); - return 0; } - if (n >= (sh->size * 100) / sh->type->construction->maxsize) { - /* destroy completly */ - /* all units leave the ship */ - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->ship == sh) { - leave_ship(u2); + if (getparam(u->faction->locale) == P_ROAD) { + destroy_road(u, n, ord); + return 0; + } + + if (u->building) { + building *b = u->building; + + if (u != building_owner(b)) { + cmistake(u, ord, 138, MSG_PRODUCE); + return 0; + } + if (fval(b->type, BTF_INDESTRUCTIBLE)) { + cmistake(u, ord, 138, MSG_PRODUCE); + return 0; + } + if (n >= b->size) { + /* destroy completly */ + /* all units leave the building */ + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->building == b) { + leave_building(u2); + } + } + ADDMSG(&u->faction->msgs, msg_message("destroy", "building unit", b, u)); + con = b->type->construction; + remove_building(&r->buildings, b); + } + else { + /* partial destroy */ + b->size -= n; + ADDMSG(&u->faction->msgs, msg_message("destroy_partial", + "building unit", b, u)); } - } - ADDMSG(&u->faction->msgs, msg_message("shipdestroy", - "unit region ship", u, r, sh)); - con = sh->type->construction; - remove_ship(&sh->region->ships, sh); - } 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 { - cmistake(u, ord, 138, MSG_PRODUCE); - return 0; - } + else if (u->ship) { + sh = u->ship; - if (con) { - /* TODO: Nicht an ZERSTÖRE mit Punktangabe angepaßt! */ - int c; - for (c = 0; con->materials[c].number; ++c) { - const requirement *rq = con->materials + c; - int recycle = (rq->number * size / con->reqsize)/2; - if (recycle) { - change_resource(u, rq->rtype, recycle); - } + if (u != ship_owner(sh)) { + cmistake(u, ord, 138, MSG_PRODUCE); + return 0; + } + if (fval(r->terrain, SEA_REGION)) { + cmistake(u, ord, 14, MSG_EVENT); + return 0; + } + + if (n >= (sh->size * 100) / sh->type->construction->maxsize) { + /* destroy completly */ + /* all units leave the ship */ + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->ship == sh) { + leave_ship(u2); + } + } + ADDMSG(&u->faction->msgs, msg_message("shipdestroy", + "unit region ship", u, r, sh)); + con = sh->type->construction; + remove_ship(&sh->region->ships, sh); + } + 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)); + } } - } - return 0; + else { + cmistake(u, ord, 138, MSG_PRODUCE); + return 0; + } + + if (con) { + /* TODO: Nicht an ZERSTÖRE mit Punktangabe angepaßt! */ + int c; + for (c = 0; con->materials[c].number; ++c) { + const requirement *rq = con->materials + c; + int recycle = (rq->number * size / con->reqsize) / 2; + if (recycle) { + change_resource(u, rq->rtype, recycle); + } + } + } + return 0; } /* ------------------------------------------------------------- */ void build_road(region * r, unit * u, int size, direction_t d) { - int n, left; - region *rn = rconnect(r, d); + int n, left; + region *rn = rconnect(r, d); - assert(u->number); - if (!eff_skill(u, SK_ROAD_BUILDING, r)) { - cmistake(u, u->thisorder, 103, MSG_PRODUCE); - return; - } - if (besieged(u)) { - cmistake(u, u->thisorder, 60, MSG_PRODUCE); - return; - } - - if (rn == NULL || rn->terrain->max_road < 0) { - cmistake(u, u->thisorder, 94, MSG_PRODUCE); - return; - } - - if (r->terrain->max_road < 0) { - cmistake(u, u->thisorder, 94, MSG_PRODUCE); - return; - } - - if (r->terrain == newterrain(T_SWAMP)) { - /* wenn kein Damm existiert */ - const struct building_type *bt_dam = bt_find("dam"); - if (!bt_dam || !buildingtype_exists(r, bt_dam, true)) { - cmistake(u, u->thisorder, 132, MSG_PRODUCE); - return; + assert(u->number); + if (!eff_skill(u, SK_ROAD_BUILDING, r)) { + cmistake(u, u->thisorder, 103, MSG_PRODUCE); + return; } - } 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; + if (besieged(u)) { + cmistake(u, u->thisorder, 60, MSG_PRODUCE); + return; } - } 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)) { - cmistake(u, u->thisorder, 131, MSG_PRODUCE); - return; - } - } - /* left kann man noch bauen */ - left = r->terrain->max_road - rroad(r, d); - - /* hoffentlich ist r->road <= r->terrain->max_road, n also >= 0 */ - if (left <= 0) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "error_roads_finished", "")); - return; - } - - if (size > 0) - left = _min(size, left); - /* baumaximum anhand der rohstoffe */ - if (u_race(u) == get_race(RC_STONEGOLEM)) { - n = u->number * GOLEM_STONE; - } else { - n = get_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, left); - if (n == 0) { - cmistake(u, u->thisorder, 151, MSG_PRODUCE); - return; + if (rn == NULL || rn->terrain->max_road < 0) { + cmistake(u, u->thisorder, 94, MSG_PRODUCE); + return; } - } - left = _min(n, left); - /* n = maximum by skill. try to maximize it */ - n = u->number * eff_skill(u, SK_ROAD_BUILDING, r); - if (n < left) { - const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); - item *itm = ring ? *i_find(&u->items, ring->itype) : 0; - if (itm != NULL && itm->number > 0) { - int rings = _min(u->number, itm->number); - n = n * ((roqf_factor() - 1) * rings + u->number) / u->number; + if (r->terrain->max_road < 0) { + cmistake(u, u->thisorder, 94, MSG_PRODUCE); + return; } - } - if (n < left) { - int dm = get_effect(u, oldpotiontype[P_DOMORE]); - if (dm != 0) { - int sk = eff_skill(u, SK_ROAD_BUILDING, r); - int todo = (left - n + sk - 1) / sk; - todo = _min(todo, u->number); - dm = _min(dm, todo); - change_effect(u, oldpotiontype[P_DOMORE], -dm); - n += dm * sk; - } /* Auswirkung Schaffenstrunk */ - } - /* make minimum of possible and available: */ - n = _min(left, n); - - /* n is now modified by several special effects, so we have to - * minimize it again to make sure the road will not grow beyond - * maximum. */ - rsetroad(r, d, rroad(r, d) + (short)n); - - if (u_race(u) == get_race(RC_STONEGOLEM)) { - int golemsused = n / GOLEM_STONE; - if (n % GOLEM_STONE != 0) { - ++golemsused; + if (r->terrain == newterrain(T_SWAMP)) { + /* wenn kein Damm existiert */ + const struct building_type *bt_dam = bt_find("dam"); + if (!bt_dam || !buildingtype_exists(r, bt_dam, true)) { + cmistake(u, u->thisorder, 132, MSG_PRODUCE); + return; + } } - scale_number(u, u->number - golemsused); - } 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)); - } - ADDMSG(&u->faction->msgs, msg_message("buildroad", - "region unit size", r, u, n)); + 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)) { + const struct building_type *bt_tunnel = bt_find("tunnel"); + /* wenn kein Tunnel existiert */ + if (!bt_tunnel || !buildingtype_exists(r, bt_tunnel, true)) { + cmistake(u, u->thisorder, 131, MSG_PRODUCE); + return; + } + } + + /* left kann man noch bauen */ + left = r->terrain->max_road - rroad(r, d); + + /* hoffentlich ist r->road <= r->terrain->max_road, n also >= 0 */ + if (left <= 0) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "error_roads_finished", "")); + return; + } + + if (size > 0) + left = _min(size, left); + /* baumaximum anhand der rohstoffe */ + if (u_race(u) == get_race(RC_STONEGOLEM)) { + n = u->number * GOLEM_STONE; + } + else { + n = get_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, left); + if (n == 0) { + cmistake(u, u->thisorder, 151, MSG_PRODUCE); + return; + } + } + left = _min(n, left); + + /* n = maximum by skill. try to maximize it */ + n = u->number * eff_skill(u, SK_ROAD_BUILDING, r); + if (n < left) { + const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); + item *itm = ring ? *i_find(&u->items, ring->itype) : 0; + if (itm != NULL && itm->number > 0) { + int rings = _min(u->number, itm->number); + n = n * ((roqf_factor() - 1) * rings + u->number) / u->number; + } + } + if (n < left) { + int dm = get_effect(u, oldpotiontype[P_DOMORE]); + if (dm != 0) { + int sk = eff_skill(u, SK_ROAD_BUILDING, r); + int todo = (left - n + sk - 1) / sk; + todo = _min(todo, u->number); + dm = _min(dm, todo); + change_effect(u, oldpotiontype[P_DOMORE], -dm); + n += dm * sk; + } /* Auswirkung Schaffenstrunk */ + } + + /* make minimum of possible and available: */ + n = _min(left, n); + + /* n is now modified by several special effects, so we have to + * minimize it again to make sure the road will not grow beyond + * maximum. */ + rsetroad(r, d, rroad(r, d) + (short)n); + + if (u_race(u) == get_race(RC_STONEGOLEM)) { + int golemsused = n / GOLEM_STONE; + if (n % GOLEM_STONE != 0) { + ++golemsused; + } + scale_number(u, u->number - golemsused); + } + 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)); + } + ADDMSG(&u->faction->msgs, msg_message("buildroad", + "region unit size", r, u, n)); } /* ------------------------------------------------------------- */ @@ -373,38 +385,38 @@ 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, - * braucht man required von maxneed resourcen */ +/* um size von msize Punkten zu bauen, + * braucht man required von maxneed resourcen */ { - int used; + int used; - used = size * maxneed / msize; - if (size * maxneed % msize) - ++used; - return used; + used = size * maxneed / msize; + if (size * maxneed % msize) + ++used; + return used; } 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; - a = a->next) { - mm_fun fun = (mm_fun) a->data.f; - value = fun(u, material, value); - if (value < 0) - return value; /* pass errors to caller */ - } - return value; + for (a = a_find((attrib *)a, &at_matmod); a && a->type == &at_matmod; + a = a->next) { + mm_fun fun = (mm_fun)a->data.f; + value = fun(u, material, value); + if (value < 0) + return value; /* pass errors to caller */ + } + return value; } int roqf_factor(void) { - int value = -1; - if (value < 0) { - value = get_param_int(global.parameters, "rules.economy.roqf", 10); - } - return value; + int value = -1; + if (value < 0) { + value = get_param_int(global.parameters, "rules.economy.roqf", 10); + } + return value; } /** Use up resources for building an object. @@ -414,230 +426,234 @@ int roqf_factor(void) */ int build(unit * u, const construction * ctype, int completed, int want) { - const construction *type = ctype; - int skills = INT_MAX; /* number of skill points remainig */ - int basesk = 0; - int made = 0; + const construction *type = ctype; + int skills = INT_MAX; /* number of skill points remainig */ + int basesk = 0; + int made = 0; - if (want <= 0) - return 0; - if (type == NULL) - return ENOMATERIALS; - if (type->improvement == NULL && completed == type->maxsize) - return ECOMPLETE; - if (type->btype != NULL) { - building *b; - if (!u->building || u->building->type != type->btype) { - return EBUILDINGREQ; - } - b = inside_building(u); - if (b == NULL) - return EBUILDINGREQ; - } - - if (type->skill != NOSKILL) { - int effsk; - int dm = get_effect(u, oldpotiontype[P_DOMORE]); - - assert(u->number); - basesk = effskill(u, type->skill); - if (basesk == 0) - return ENEEDSKILL; - - effsk = basesk; - if (inside_building(u)) { - effsk = skillmod(u->building->type->attribs, u, u->region, type->skill, - effsk, SMF_PRODUCTION); - } - effsk = skillmod(type->attribs, u, u->region, type->skill, - effsk, SMF_PRODUCTION); - if (effsk < 0) - return effsk; /* pass errors to caller */ - if (effsk == 0) - return ENEEDSKILL; - - skills = effsk * u->number; - - /* technically, nimblefinge and domore should be in a global set of - * "game"-attributes, (as at_skillmod) but for a while, we're leaving - * them in here. */ - - if (dm != 0) { - /* Auswirkung Schaffenstrunk */ - dm = _min(dm, u->number); - change_effect(u, oldpotiontype[P_DOMORE], -dm); - skills += dm * effsk; - } - } - for (; want > 0 && skills > 0;) { - int c, n; - - /* skip over everything that's already been done: - * type->improvement==NULL means no more improvements, but no size limits - * type->improvement==type means build another object of the same time - * while material lasts type->improvement==x means build x when type - * is finished */ - while (type->improvement != NULL && - type->improvement != type && - type->maxsize > 0 && type->maxsize <= completed) { - completed -= type->maxsize; - type = type->improvement; - } - if (type == NULL) { - if (made == 0) - return ECOMPLETE; - break; /* completed */ - } - - /* Hier ist entweder maxsize == -1, oder completed < maxsize. - * Andernfalls ist das Datenfile oder sonstwas kaputt... - * (enno): Nein, das ist für Dinge, bei denen die nächste Ausbaustufe - * die gleiche wie die vorherige ist. z.b. gegenstände. - */ - if (type->maxsize > 1) { - completed = completed % type->maxsize; - } else { - completed = 0; - assert(type->reqsize >= 1); - } - - if (basesk < type->minskill) { - if (made == 0) - return ELOWSKILL; /* not good enough to go on */ - } - - /* n = maximum buildable size */ - if (type->minskill > 1) { - n = skills / type->minskill; - } else { - n = skills; - } - /* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische) - * Talente */ - if (skill_limit(u->faction, type->skill) == INT_MAX) { - const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); - item *itm = ring ? *i_find(&u->items, ring->itype) : 0; - int i = itm ? itm->number : 0; - if (i > 0) { - int rings = _min(u->number, i); - n = n * ((roqf_factor() - 1) * rings + u->number) / u->number; - } - } - - if (want < n) n = want; - - if (type->maxsize > 0) { - n = _min(type->maxsize - completed, n); - if (type->improvement == NULL) { - want = n; - } - } - - if (type->materials) - for (c = 0; n > 0 && type->materials[c].number; c++) { - const struct resource_type *rtype = type->materials[c].rtype; - int need, prebuilt; - int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); - - if (inside_building(u)) { - canuse = matmod(u->building->type->attribs, u, rtype, canuse); - } - - if (canuse < 0) - return canuse; /* pass errors to caller */ - canuse = matmod(type->attribs, u, rtype, canuse); - if (type->reqsize > 1) { - prebuilt = - required(completed, type->reqsize, type->materials[c].number); - for (; n;) { - need = - required(completed + n, type->reqsize, type->materials[c].number); - if (need - prebuilt <= canuse) - break; - --n; /* TODO: optimieren? */ - } - } else { - int maxn = canuse / type->materials[c].number; - if (maxn < n) - n = maxn; - } - } - if (n <= 0) { - if (made == 0) + if (want <= 0) + return 0; + if (type == NULL) return ENOMATERIALS; - else - break; + if (type->improvement == NULL && completed == type->maxsize) + return ECOMPLETE; + if (type->btype != NULL) { + building *b; + if (!u->building || u->building->type != type->btype) { + return EBUILDINGREQ; + } + b = inside_building(u); + if (b == NULL) + return EBUILDINGREQ; } - if (type->materials) - for (c = 0; type->materials[c].number; c++) { - const struct resource_type *rtype = type->materials[c].rtype; - int prebuilt = - required(completed, type->reqsize, type->materials[c].number); - int need = - required(completed + n, type->reqsize, type->materials[c].number); - int multi = 1; - int canuse = 100; /* normalization */ - if (inside_building(u)) - canuse = matmod(u->building->type->attribs, u, rtype, canuse); - if (canuse < 0) - return canuse; /* pass errors to caller */ - canuse = matmod(type->attribs, u, rtype, canuse); - assert(canuse % 100 == 0 - || !"only constant multipliers are implemented in build()"); - multi = canuse / 100; - if (canuse < 0) - return canuse; /* pass errors to caller */ + if (type->skill != NOSKILL) { + int effsk; + int dm = get_effect(u, oldpotiontype[P_DOMORE]); - use_pooled(u, rtype, GET_DEFAULT, - (need - prebuilt + multi - 1) / multi); - } - made += n; - skills -= n * type->minskill; - want -= n; - completed = completed + n; - } - /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ - produceexp(u, ctype->skill, _min(made, u->number)); + assert(u->number); + basesk = effskill(u, type->skill); + if (basesk == 0) + return ENEEDSKILL; - return made; + effsk = basesk; + if (inside_building(u)) { + effsk = skillmod(u->building->type->attribs, u, u->region, type->skill, + effsk, SMF_PRODUCTION); + } + effsk = skillmod(type->attribs, u, u->region, type->skill, + effsk, SMF_PRODUCTION); + if (effsk < 0) + return effsk; /* pass errors to caller */ + if (effsk == 0) + return ENEEDSKILL; + + skills = effsk * u->number; + + /* technically, nimblefinge and domore should be in a global set of + * "game"-attributes, (as at_skillmod) but for a while, we're leaving + * them in here. */ + + if (dm != 0) { + /* Auswirkung Schaffenstrunk */ + dm = _min(dm, u->number); + change_effect(u, oldpotiontype[P_DOMORE], -dm); + skills += dm * effsk; + } + } + for (; want > 0 && skills > 0;) { + int c, n; + + /* skip over everything that's already been done: + * type->improvement==NULL means no more improvements, but no size limits + * type->improvement==type means build another object of the same time + * while material lasts type->improvement==x means build x when type + * is finished */ + while (type->improvement != NULL && + type->improvement != type && + type->maxsize > 0 && type->maxsize <= completed) { + completed -= type->maxsize; + type = type->improvement; + } + if (type == NULL) { + if (made == 0) + return ECOMPLETE; + break; /* completed */ + } + + /* Hier ist entweder maxsize == -1, oder completed < maxsize. + * Andernfalls ist das Datenfile oder sonstwas kaputt... + * (enno): Nein, das ist für Dinge, bei denen die nächste Ausbaustufe + * die gleiche wie die vorherige ist. z.b. gegenstände. + */ + if (type->maxsize > 1) { + completed = completed % type->maxsize; + } + else { + completed = 0; + assert(type->reqsize >= 1); + } + + if (basesk < type->minskill) { + if (made == 0) + return ELOWSKILL; /* not good enough to go on */ + } + + /* n = maximum buildable size */ + if (type->minskill > 1) { + n = skills / type->minskill; + } + else { + n = skills; + } + /* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische) + * Talente */ + if (skill_limit(u->faction, type->skill) == INT_MAX) { + const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); + item *itm = ring ? *i_find(&u->items, ring->itype) : 0; + int i = itm ? itm->number : 0; + if (i > 0) { + int rings = _min(u->number, i); + n = n * ((roqf_factor() - 1) * rings + u->number) / u->number; + } + } + + if (want < n) n = want; + + if (type->maxsize > 0) { + n = _min(type->maxsize - completed, n); + if (type->improvement == NULL) { + want = n; + } + } + + if (type->materials) + for (c = 0; n > 0 && type->materials[c].number; c++) { + const struct resource_type *rtype = type->materials[c].rtype; + int need, prebuilt; + int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); + + if (inside_building(u)) { + canuse = matmod(u->building->type->attribs, u, rtype, canuse); + } + + if (canuse < 0) + return canuse; /* pass errors to caller */ + canuse = matmod(type->attribs, u, rtype, canuse); + if (type->reqsize > 1) { + prebuilt = + required(completed, type->reqsize, type->materials[c].number); + for (; n;) { + need = + required(completed + n, type->reqsize, type->materials[c].number); + if (need - prebuilt <= canuse) + break; + --n; /* TODO: optimieren? */ + } + } + else { + int maxn = canuse / type->materials[c].number; + if (maxn < n) + n = maxn; + } + } + if (n <= 0) { + if (made == 0) + return ENOMATERIALS; + else + break; + } + if (type->materials) + for (c = 0; type->materials[c].number; c++) { + const struct resource_type *rtype = type->materials[c].rtype; + int prebuilt = + required(completed, type->reqsize, type->materials[c].number); + int need = + required(completed + n, type->reqsize, type->materials[c].number); + int multi = 1; + int canuse = 100; /* normalization */ + if (inside_building(u)) + canuse = matmod(u->building->type->attribs, u, rtype, canuse); + if (canuse < 0) + return canuse; /* pass errors to caller */ + canuse = matmod(type->attribs, u, rtype, canuse); + + assert(canuse % 100 == 0 + || !"only constant multipliers are implemented in build()"); + multi = canuse / 100; + if (canuse < 0) + return canuse; /* pass errors to caller */ + + use_pooled(u, rtype, GET_DEFAULT, + (need - prebuilt + multi - 1) / multi); + } + made += n; + skills -= n * type->minskill; + want -= n; + completed = completed + n; + } + /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ + produceexp(u, ctype->skill, _min(made, u->number)); + + return made; } message *msg_materials_required(unit * u, order * ord, - const construction * ctype, int multi) + const construction * ctype, int multi) { - int c; - /* something missing from the list of materials */ - resource *reslist = NULL; + int c; + /* something missing from the list of materials */ + resource *reslist = NULL; - if (multi <= 0 || multi == INT_MAX) - multi = 1; - for (c = 0; ctype && ctype->materials[c].number; ++c) { - resource *res = malloc(sizeof(resource)); - res->number = multi * ctype->materials[c].number / ctype->reqsize; - res->type = ctype->materials[c].rtype; - res->next = reslist; - reslist = res; - } - return msg_feedback(u, ord, "build_required", "required", reslist); + if (multi <= 0 || multi == INT_MAX) + multi = 1; + for (c = 0; ctype && ctype->materials[c].number; ++c) { + resource *res = malloc(sizeof(resource)); + res->number = multi * ctype->materials[c].number / ctype->reqsize; + res->type = ctype->materials[c].rtype; + res->next = reslist; + reslist = res; + } + return msg_feedback(u, ord, "build_required", "required", reslist); } 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; - for (c = 0; cons->materials[c].number; c++) { - const resource_type *rtype = cons->materials[c].rtype; - int have = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); - int need = required(1, cons->reqsize, cons->materials[c].number); - if (have < need) { - return 0; - } else - maximum = _min(maximum, have / need); - } - return maximum; + int c; + int maximum = INT_MAX; + for (c = 0; cons->materials[c].number; c++) { + const resource_type *rtype = cons->materials[c].rtype; + int have = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); + int need = required(1, cons->reqsize, cons->materials[c].number); + if (have < need) { + return 0; + } + else + maximum = _min(maximum, have / need); + } + return maximum; } /** old build routines */ @@ -645,302 +661,312 @@ int maxbuild(const unit * u, const construction * cons) int build_building(unit * u, const building_type * btype, int id, int want, order * ord) { - region *r = u->region; - int n = want, built = 0; - building *b = NULL; - /* einmalige Korrektur */ - const char *btname; - order *new_order = NULL; - const struct locale *lang = u->faction->locale; - static int rule_other = -1; + region *r = u->region; + int n = want, built = 0; + building *b = NULL; + /* einmalige Korrektur */ + const char *btname; + order *new_order = NULL; + const struct locale *lang = u->faction->locale; + static int rule_other = -1; - assert(u->number); - assert(btype->construction); - if (eff_skill(u, SK_BUILDING, r) == 0) { - cmistake(u, ord, 101, MSG_PRODUCE); - return 0; - } + assert(u->number); + assert(btype->construction); + if (eff_skill(u, SK_BUILDING, r) == 0) { + cmistake(u, ord, 101, MSG_PRODUCE); + return 0; + } - /* Falls eine Nummer angegeben worden ist, und ein Gebaeude mit der - * betreffenden Nummer existiert, ist b nun gueltig. Wenn keine Burg - * gefunden wurde, dann wird nicht einfach eine neue erbaut. Ansonsten - * baut man an der eigenen burg weiter. */ + /* Falls eine Nummer angegeben worden ist, und ein Gebaeude mit der + * betreffenden Nummer existiert, ist b nun gueltig. Wenn keine Burg + * gefunden wurde, dann wird nicht einfach eine neue erbaut. Ansonsten + * baut man an der eigenen burg weiter. */ - /* Wenn die angegebene Nummer falsch ist, KEINE Burg bauen! */ - if (id > 0) { /* eine Nummer angegeben, keine neue Burg bauen */ - b = findbuilding(id); - if (!b || b->region != u->region) { /* eine Burg mit dieser Nummer gibt es hier nicht */ - /* vieleicht Tippfehler und die eigene Burg ist gemeint? */ - if (u->building && u->building->type == btype) { + /* Wenn die angegebene Nummer falsch ist, KEINE Burg bauen! */ + if (id > 0) { /* eine Nummer angegeben, keine neue Burg bauen */ + b = findbuilding(id); + if (!b || b->region != u->region) { /* eine Burg mit dieser Nummer gibt es hier nicht */ + /* vieleicht Tippfehler und die eigene Burg ist gemeint? */ + if (u->building && u->building->type == btype) { + b = u->building; + } + 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) { b = u->building; - } else { - /* keine neue Burg anfangen wenn eine Nummer angegeben war */ - cmistake(u, ord, 6, MSG_PRODUCE); + } + + if (b) + btype = b->type; + + if (fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype, false)) { + /* only one of these per region */ + cmistake(u, ord, 93, MSG_PRODUCE); return 0; - } } - } else if (u->building && u->building->type == btype) { - b = u->building; - } - - if (b) - btype = b->type; - - if (fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype, false)) { - /* only one of these per region */ - cmistake(u, ord, 93, MSG_PRODUCE); - return 0; - } - if (besieged(u)) { - /* units under siege can not build */ - cmistake(u, ord, 60, MSG_PRODUCE); - return 0; - } - if (btype->flags & BTF_NOBUILD) { - /* special building, cannot be built */ - cmistake(u, ord, 221, MSG_PRODUCE); - return 0; - } - if ((r->terrain->flags & LAND_REGION) == 0) { - /* special terrain, cannot build */ - cmistake(u, ord, 221, MSG_PRODUCE); - return 0; - } - if (btype->flags & BTF_ONEPERTURN) { - if (b && fval(b, BLD_EXPANDED)) { - cmistake(u, ord, 318, MSG_PRODUCE); - return 0; - } - n = 1; - } - if (b) { - if (rule_other < 0) { - rule_other = - get_param_int(global.parameters, "rules.build.other_buildings", 1); - } - if (!rule_other) { - unit *owner = building_owner(b); - if (!owner || owner->faction != u->faction) { - cmistake(u, ord, 1222, MSG_PRODUCE); + if (besieged(u)) { + /* units under siege can not build */ + cmistake(u, ord, 60, MSG_PRODUCE); return 0; - } } - } + if (btype->flags & BTF_NOBUILD) { + /* special building, cannot be built */ + cmistake(u, ord, 221, MSG_PRODUCE); + return 0; + } + if ((r->terrain->flags & LAND_REGION) == 0) { + /* special terrain, cannot build */ + cmistake(u, ord, 221, MSG_PRODUCE); + return 0; + } + if (btype->flags & BTF_ONEPERTURN) { + if (b && fval(b, BLD_EXPANDED)) { + cmistake(u, ord, 318, MSG_PRODUCE); + return 0; + } + n = 1; + } + if (b) { + if (rule_other < 0) { + rule_other = + get_param_int(global.parameters, "rules.build.other_buildings", 1); + } + if (!rule_other) { + unit *owner = building_owner(b); + if (!owner || owner->faction != u->faction) { + cmistake(u, ord, 1222, MSG_PRODUCE); + return 0; + } + } + } - if (b) - built = b->size; - if (n <= 0 || n == INT_MAX) { + if (b) + built = b->size; + if (n <= 0 || n == INT_MAX) { + if (b == NULL) { + if (btype->maxsize > 0) { + n = btype->maxsize - built; + } + else { + n = INT_MAX; + } + } + else { + if (b->type->maxsize > 0) { + n = b->type->maxsize - built; + } + else { + n = INT_MAX; + } + } + } + built = build(u, btype->construction, built, n); + + switch (built) { + case ECOMPLETE: + /* the building is already complete */ + cmistake(u, ord, 4, MSG_PRODUCE); + break; + case ENOMATERIALS: + ADDMSG(&u->faction->msgs, msg_materials_required(u, ord, + btype->construction, want)); + break; + case ELOWSKILL: + case ENEEDSKILL: + /* no skill, or not enough skill points to build */ + cmistake(u, ord, 50, MSG_PRODUCE); + break; + } + if (built <= 0) { + return built; + } + /* at this point, the building size is increased. */ if (b == NULL) { - if (btype->maxsize > 0) { - n = btype->maxsize - built; - } else { - n = INT_MAX; - } - } else { - if (b->type->maxsize > 0) { - n = b->type->maxsize - built; - } else { - n = INT_MAX; - } - } - } - built = build(u, btype->construction, built, n); + /* build a new building */ + b = new_building(btype, r, lang); + b->type = btype; + fset(b, BLD_MAINTAINED | BLD_WORKING); - switch (built) { - case ECOMPLETE: - /* the building is already complete */ - cmistake(u, ord, 4, MSG_PRODUCE); - break; - case ENOMATERIALS: - ADDMSG(&u->faction->msgs, msg_materials_required(u, ord, - btype->construction, want)); - break; - case ELOWSKILL: - case ENEEDSKILL: - /* no skill, or not enough skill points to build */ - cmistake(u, ord, 50, MSG_PRODUCE); - break; - } - if (built<=0) { + /* Die Einheit befindet sich automatisch im Inneren der neuen Burg. */ + if (u->number && leave(u, false)) { + u_set_building(u, b); + } + } + + btname = LOC(lang, btype->_name); + + if (want - built <= 0) { + /* gebäude fertig */ + new_order = default_order(lang); + } + 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 { + new_order = + create_order(K_MAKE, lang, "%d %s %i", n - built, btname, b->no); + } + } + 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 { + new_order = create_order(K_MAKE, lang, "%s %i", btname, b->no); + } + } + + if (new_order) { + replace_order(&u->orders, ord, new_order); + free_order(new_order); + } + + b->size += built; + fset(b, BLD_EXPANDED); + + update_lighthouse(b); + + ADDMSG(&u->faction->msgs, msg_message("buildbuilding", + "building unit size", b, u, built)); return built; - } - /* at this point, the building size is increased. */ - if (b == NULL) { - /* build a new building */ - b = new_building(btype, r, lang); - b->type = btype; - fset(b, BLD_MAINTAINED|BLD_WORKING); - - /* Die Einheit befindet sich automatisch im Inneren der neuen Burg. */ - if (u->number && leave(u, false)) { - u_set_building(u, b); - } - } - - btname = LOC(lang, btype->_name); - - if (want - built <= 0) { - /* gebäude fertig */ - new_order = default_order(lang); - } 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 { - new_order = - create_order(K_MAKE, lang, "%d %s %i", n - built, btname, b->no); - } - } 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 { - new_order = create_order(K_MAKE, lang, "%s %i", btname, b->no); - } - } - - if (new_order) { - replace_order(&u->orders, ord, new_order); - free_order(new_order); - } - - b->size += built; - fset(b, BLD_EXPANDED); - - update_lighthouse(b); - - ADDMSG(&u->faction->msgs, msg_message("buildbuilding", - "building unit size", b, u, built)); - return built; } static void build_ship(unit * u, ship * sh, int want) { - const construction *construction = sh->type->construction; - int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE; - int n; - int can = build(u, construction, size, want); + const construction *construction = sh->type->construction; + int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE; + int n; + int can = build(u, construction, size, want); - if ((n = construction->maxsize - sh->size) > 0 && can > 0) { - if (can >= n) { - sh->size += n; - can -= n; - } else { - sh->size += can; - n = can; - can = 0; + if ((n = construction->maxsize - sh->size) > 0 && can > 0) { + if (can >= n) { + sh->size += n; + can -= n; + } + else { + sh->size += can; + n = can; + can = 0; + } } - } - if (sh->damage && can) { - int repair = _min(sh->damage, can * DAMAGE_SCALE); - n += repair / DAMAGE_SCALE; - if (repair % DAMAGE_SCALE) - ++n; - sh->damage = sh->damage - repair; - } + if (sh->damage && can) { + int repair = _min(sh->damage, can * DAMAGE_SCALE); + n += repair / DAMAGE_SCALE; + if (repair % DAMAGE_SCALE) + ++n; + sh->damage = sh->damage - repair; + } - if (n) - ADDMSG(&u->faction->msgs, - msg_message("buildship", "ship unit size", sh, u, n)); + if (n) + ADDMSG(&u->faction->msgs, + msg_message("buildship", "ship unit size", sh, u, n)); } void create_ship(region * r, unit * u, const struct ship_type *newtype, int want, - order * ord) +order * ord) { - ship *sh; - int msize; - const construction *cons = newtype->construction; - order *new_order; + ship *sh; + int msize; + const construction *cons = newtype->construction; + order *new_order; - if (!eff_skill(u, SK_SHIPBUILDING, r)) { - cmistake(u, ord, 100, MSG_PRODUCE); - return; - } - if (besieged(u)) { - cmistake(u, ord, 60, MSG_PRODUCE); - return; - } - - /* check if skill and material for 1 size is available */ - if (eff_skill(u, cons->skill, r) < cons->minskill) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "error_build_skill_low", "value", cons->minskill)); - return; - } - - msize = maxbuild(u, cons); - if (msize == 0) { - cmistake(u, ord, 88, MSG_PRODUCE); - return; - } - if (want > 0) - want = _min(want, msize); - else - want = msize; - - sh = new_ship(newtype, r, u->faction->locale); - - if (leave(u, false)) { - if (fval(u_race(u), RCF_CANSAIL)) { - u_set_ship(u, sh); + if (!eff_skill(u, SK_SHIPBUILDING, r)) { + cmistake(u, ord, 100, MSG_PRODUCE); + return; + } + if (besieged(u)) { + cmistake(u, ord, 60, MSG_PRODUCE); + return; } - } - new_order = - create_order(K_MAKE, u->faction->locale, "%s %i", LOC(u->faction->locale, - parameters[P_SHIP]), sh->no); - replace_order(&u->orders, ord, new_order); - free_order(new_order); - build_ship(u, sh, want); + /* check if skill and material for 1 size is available */ + if (eff_skill(u, cons->skill, r) < cons->minskill) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "error_build_skill_low", "value", cons->minskill)); + return; + } + + msize = maxbuild(u, cons); + if (msize == 0) { + cmistake(u, ord, 88, MSG_PRODUCE); + return; + } + if (want > 0) + want = _min(want, msize); + else + want = msize; + + sh = new_ship(newtype, r, u->faction->locale); + + if (leave(u, false)) { + if (fval(u_race(u), RCF_CANSAIL)) { + u_set_ship(u, sh); + } + } + new_order = + create_order(K_MAKE, u->faction->locale, "%s %i", LOC(u->faction->locale, + parameters[P_SHIP]), sh->no); + replace_order(&u->orders, ord, new_order); + free_order(new_order); + + build_ship(u, sh, want); } void continue_ship(region * r, unit * u, int want) { - const construction *cons; - ship *sh; - int msize; + const construction *cons; + ship *sh; + int msize; - if (!eff_skill(u, SK_SHIPBUILDING, r)) { - cmistake(u, u->thisorder, 100, MSG_PRODUCE); - return; - } + if (!eff_skill(u, SK_SHIPBUILDING, r)) { + cmistake(u, u->thisorder, 100, MSG_PRODUCE); + return; + } - /* Die Schiffsnummer bzw der Schiffstyp wird eingelesen */ - sh = getship(r); + /* Die Schiffsnummer bzw der Schiffstyp wird eingelesen */ + sh = getship(r); - if (!sh) - sh = u->ship; + if (!sh) + sh = u->ship; - if (!sh) { - cmistake(u, u->thisorder, 20, MSG_PRODUCE); - return; - } - cons = sh->type->construction; - assert(cons->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ - if (sh->size == cons->maxsize && !sh->damage) { - cmistake(u, u->thisorder, 16, MSG_PRODUCE); - return; - } - if (eff_skill(u, cons->skill, r) < cons->minskill) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "error_build_skill_low", "value", cons->minskill)); - return; - } - msize = maxbuild(u, cons); - if (msize == 0) { - cmistake(u, u->thisorder, 88, MSG_PRODUCE); - return; - } - if (want > 0) - want = _min(want, msize); - else - want = msize; + if (!sh) { + cmistake(u, u->thisorder, 20, MSG_PRODUCE); + return; + } + cons = sh->type->construction; + assert(cons->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ + if (sh->size == cons->maxsize && !sh->damage) { + cmistake(u, u->thisorder, 16, MSG_PRODUCE); + return; + } + if (eff_skill(u, cons->skill, r) < cons->minskill) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "error_build_skill_low", "value", cons->minskill)); + return; + } + msize = maxbuild(u, cons); + if (msize == 0) { + cmistake(u, u->thisorder, 88, MSG_PRODUCE); + return; + } + if (want > 0) + want = _min(want, msize); + else + want = msize; - build_ship(u, sh, want); + build_ship(u, sh, want); } diff --git a/src/kernel/command.c b/src/kernel/command.c index c6d262dd0..86681c7c1 100644 --- a/src/kernel/command.c +++ b/src/kernel/command.c @@ -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) { diff --git a/src/kernel/config.c b/src/kernel/config.c index 0e0e53e28..6d7f778a4 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -796,13 +796,15 @@ parse(keyword_t kword, int(*dofun) (unit *, struct order *), bool thisorder) unsigned int getuint(void) { - const char *s = getstrtoken(); + char token[16]; + const char *s = gettoken(token, sizeof(token)); return s ? atoip(s) : 0; } int getint(void) { - const char * s = getstrtoken(); + char token[16]; + const char * s = gettoken(token, sizeof(token)); return s ? atoi(s) : 0; } @@ -875,7 +877,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 +912,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 diff --git a/src/kernel/save.c b/src/kernel/save.c index 01cc9fc70..00cb89d3e 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -225,7 +225,7 @@ static faction *factionorders(void) if (f != NULL && !fval(f, FFL_NPC)) { char token[128]; - const char *pass = getstrtok(token, sizeof(token)); + const char *pass = gettoken(token, sizeof(token)); if (!checkpasswd(f, (const char *)pass)) { log_debug("Invalid password for faction %s\n", itoa36(fid)); @@ -273,7 +273,7 @@ int readorders(const char *filename) param_t p; const char *s; init_tokens_str(b); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); p = s ? findparam(s, lang) : NOPARAM; switch (p) { #undef LOCALE_CHANGE diff --git a/src/kernel/unit.c b/src/kernel/unit.c index e55d21b5c..22dc8bc55 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -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); } /*********************/ diff --git a/src/laws.c b/src/laws.c index 95894ad9b..a7fd9a3f4 100755 --- a/src/laws.c +++ b/src/laws.c @@ -953,7 +953,7 @@ int quit_cmd(unit * u, struct order *ord) kwd = init_order(ord); assert(kwd == K_QUIT); - passwd = getstrtok(token, sizeof(token)); + passwd = gettoken(token, sizeof(token)); if (checkpasswd(f, (const char *)passwd)) { if (EnhancedQuit()) { int f2_id = getid(); @@ -1167,7 +1167,7 @@ void do_enter(struct region *r, bool is_final_attempt) const char * s; init_order(ord); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); p = findparam_ex(s, u->faction->locale); id = getid(); @@ -1357,7 +1357,7 @@ int ally_cmd(unit * u, struct order *ord) if (f == u->faction) return 0; - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); if (!s[0]) keyword = P_ANY; @@ -1495,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; @@ -1512,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; @@ -1559,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: @@ -1601,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: @@ -1732,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; @@ -1740,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); } @@ -1994,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! */ @@ -2185,7 +2181,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)); } @@ -2204,7 +2200,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++) @@ -2213,14 +2209,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); @@ -2238,11 +2230,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); @@ -2579,14 +2572,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; } @@ -2621,7 +2611,7 @@ int reshow_cmd(unit * u, struct order *ord) param_t p = NOPARAM; init_order(ord); - s = getstrtok(lbuf, sizeof(lbuf)); + s = gettoken(lbuf, sizeof(lbuf)); if (s && isparam(s, u->faction->locale, P_ANY)) { p = getparam(u->faction->locale); @@ -2634,12 +2624,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; @@ -2667,7 +2657,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", "")); } @@ -2686,7 +2676,7 @@ int combatspell_cmd(unit * u, struct order *ord) spell *sp = 0; init_order(ord); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); /* KAMPFZAUBER [NICHT] löscht alle gesetzten Kampfzauber */ if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) { @@ -2699,7 +2689,7 @@ int combatspell_cmd(unit * u, struct order *ord) /* Merken, setzen kommt erst später */ level = getint(); level = _max(0, level); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); } sp = unit_getspell(u, s, u->faction->locale); @@ -2708,7 +2698,7 @@ int combatspell_cmd(unit * u, struct order *ord) return 0; } - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); if (findparam(s, u->faction->locale) == P_NOT) { /* KAMPFZAUBER "" NICHT löscht diesen speziellen @@ -2933,7 +2923,7 @@ void restack_units(void) unit *v; init_order(ord); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); p = findparam(s, u->faction->locale); id = getid(); v = findunit(id); @@ -3009,11 +2999,11 @@ int renumber_cmd(unit * u, order * ord) faction *f = u->faction; init_order(ord); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); switch (findparam_ex(s, u->faction->locale)) { case P_FACTION: - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); if (s && *s) { int id = atoi36((const char *)s); attrib *a = a_find(f->attribs, &at_number); @@ -3024,7 +3014,7 @@ int renumber_cmd(unit * u, order * ord) break; case P_UNIT: - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); if (s == NULL || *s == 0) { i = newunitid(); } @@ -3067,7 +3057,7 @@ int renumber_cmd(unit * u, order * ord) cmistake(u, ord, 116, MSG_EVENT); break; } - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); if (s == NULL || *s == 0) { i = newcontainerid(); } @@ -3096,7 +3086,7 @@ int renumber_cmd(unit * u, order * ord) cmistake(u, ord, 148, MSG_EVENT); break; } - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); if (*s == 0) { i = newcontainerid(); } @@ -3397,7 +3387,7 @@ void new_units(void) init_order(makeord); alias = getid(); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); if (s && s[0]) { name = _strdup(s); } @@ -3707,7 +3697,7 @@ void defaultorders(void) order *new_order = 0; const char *s; init_order(ord); - s = getstrtok(lbuf, sizeof(lbuf)); + s = gettoken(lbuf, sizeof(lbuf)); if (s) { new_order = parse_order(s, u->faction->locale); } @@ -3823,13 +3813,13 @@ int use_cmd(unit * u, struct order *ord) init_order(ord); - t = getstrtok(token, sizeof(token)); + 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 = getstrtok(token, sizeof(token)); + t = gettoken(token, sizeof(token)); } else { /* BENUTZE Yanxspirit */ @@ -3838,7 +3828,7 @@ int use_cmd(unit * u, struct order *ord) } else { /* BENUTZE 42 Yanxspirit */ - t = getstrtok(token, sizeof(token)); + t = gettoken(token, sizeof(token)); } itype = t ? finditemtype(t, u->faction->locale) : NULL; @@ -3920,20 +3910,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; @@ -3963,19 +3954,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); diff --git a/src/magic.c b/src/magic.c index d1bd6c661..4afd3cf61 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2519,7 +2519,7 @@ static castorder *cast_cmd(unit * u, order * ord) level = eff_skill(u, SK_MAGIC, r); init_order(ord); - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); param = findparam(s, u->faction->locale); /* für Syntax ' STUFE x REGION y z ' */ if (param == P_LEVEL) { @@ -2530,7 +2530,7 @@ static castorder *cast_cmd(unit * u, order * ord) cmistake(u, ord, 10, MSG_MAGIC); return 0; } - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); param = findparam(s, u->faction->locale); } if (param == P_REGION) { @@ -2547,7 +2547,7 @@ static castorder *cast_cmd(unit * u, order * ord) "unit region command", u, u->region, ord)); return 0; } - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); param = findparam(s, u->faction->locale); } /* für Syntax ' REGION x y STUFE z ' @@ -2560,7 +2560,7 @@ static castorder *cast_cmd(unit * u, order * ord) cmistake(u, ord, 10, MSG_MAGIC); return 0; } - s = getstrtok(token, sizeof(token)); + s = gettoken(token, sizeof(token)); } if (!s || !s[0] || strlen(s) == 0) { /* Fehler "Es wurde kein Zauber angegeben" */ @@ -2693,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) { diff --git a/src/move.c b/src/move.c index cadb6dca6..4b295896e 100644 --- a/src/move.c +++ b/src/move.c @@ -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); diff --git a/src/util/parser.c b/src/util/parser.c index 12ac19a6e..da2f3f521 100644 --- a/src/util/parser.c +++ b/src/util/parser.c @@ -132,6 +132,9 @@ char *parse_token(const char **str, char *lbuf, size_t len) } eatwhitespace_c(&ctoken); if (!*ctoken) { + if (len > 0) { + *cursor = 0; + } return 0; } while (*ctoken && cursor-len < lbuf-1) { @@ -209,7 +212,7 @@ const char *getstrtoken(void) return parse_token((const char **)&states->current_token, lbuf, MAXTOKENSIZE); } -const char *getstrtok(char *lbuf, size_t bufsize) +const char *gettoken(char *lbuf, size_t bufsize) { return parse_token((const char **)&states->current_token, lbuf, bufsize); } @@ -217,7 +220,7 @@ const char *getstrtok(char *lbuf, size_t bufsize) int getid(void) { char token[16]; - const char *str = getstrtok(token, sizeof(token)); + const char *str = gettoken(token, sizeof(token)); int i = str ? atoi36(str) : 0; if (i < 0) { return -1; diff --git a/src/util/parser.h b/src/util/parser.h index 2ab7f1b75..ab62591a9 100644 --- a/src/util/parser.h +++ b/src/util/parser.h @@ -22,7 +22,7 @@ extern "C" { void parser_popstate(void); bool parser_end(void); const char *getstrtoken(void); - const char *getstrtok(char *lbuf, size_t bufsize); + const char *gettoken(char *lbuf, size_t bufsize); int getid(void); #define getshipid() getid() #define getfactionid() getid() diff --git a/src/util/parser.test.c b/src/util/parser.test.c index f5543a7cb..910c11fc3 100644 --- a/src/util/parser.test.c +++ b/src/util/parser.test.c @@ -3,13 +3,21 @@ #include -static void test_parser(CuTest *tc) { +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); } CuSuite *get_parser_suite(void) { CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_parser); + SUITE_ADD_TEST(suite, test_gettoken); return suite; }