(ef_byname_from): New.
(set, mission, multifire, fuel, cons_choose, cede): Use it instead of ef_byname(). Remove the hacks to map unwanted results to wanted results. The hacks in set() were broken: bad input made the code cast arbitrary items to union trdgenstr, with potentially disastrous consequences. Closes #906483 and #906486. (set): Less cryptic prompt and diagnostics.
This commit is contained in:
parent
2df98825e9
commit
2fc1e74a72
8 changed files with 54 additions and 30 deletions
|
@ -150,6 +150,7 @@ extern int ef_ensure_space(int, int, int);
|
||||||
extern int ef_nelem(int);
|
extern int ef_nelem(int);
|
||||||
extern int ef_flags(int);
|
extern int ef_flags(int);
|
||||||
extern int ef_byname(char *);
|
extern int ef_byname(char *);
|
||||||
|
extern int ef_byname_from(char *, int *);
|
||||||
|
|
||||||
extern struct empfile empfile[];
|
extern struct empfile empfile[];
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ static void grab_ship(struct shpstr *, natid);
|
||||||
int
|
int
|
||||||
cede(void)
|
cede(void)
|
||||||
{
|
{
|
||||||
|
static int sct_or_shp[] = { EF_SECTOR, EF_SHIP, EF_BAD };
|
||||||
natid to;
|
natid to;
|
||||||
int n;
|
int n;
|
||||||
int is_sector = 0, is_ship = 0;
|
int is_sector = 0, is_ship = 0;
|
||||||
|
@ -83,13 +84,8 @@ cede(void)
|
||||||
return RET_FAIL;
|
return RET_FAIL;
|
||||||
if (strlen(p) > 4)
|
if (strlen(p) > 4)
|
||||||
p[2] = 0;
|
p[2] = 0;
|
||||||
type = ef_byname(p);
|
type = ef_byname_from(p, sct_or_shp);
|
||||||
|
if (type < 0) {
|
||||||
if (type == EF_SECTOR)
|
|
||||||
is_ship = 0;
|
|
||||||
else if (type == EF_SHIP)
|
|
||||||
is_sector = 0;
|
|
||||||
else {
|
|
||||||
pr("Please type 'se' or 'sh'!\n");
|
pr("Please type 'se' or 'sh'!\n");
|
||||||
return RET_FAIL;
|
return RET_FAIL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@ cons(void)
|
||||||
static int
|
static int
|
||||||
cons_choose(struct ltcomstr *ltcp)
|
cons_choose(struct ltcomstr *ltcp)
|
||||||
{
|
{
|
||||||
|
static int lon_or_trt[] = { EF_LOAN, EF_TREATY, EF_BAD };
|
||||||
s_char *p;
|
s_char *p;
|
||||||
struct lonstr *lp;
|
struct lonstr *lp;
|
||||||
struct trtstr *tp;
|
struct trtstr *tp;
|
||||||
|
@ -119,7 +120,7 @@ cons_choose(struct ltcomstr *ltcp)
|
||||||
memset(ltcp, 0, sizeof(*ltcp));
|
memset(ltcp, 0, sizeof(*ltcp));
|
||||||
if (getstarg(player->argp[1], "loan or treaty? ", buf) == 0)
|
if (getstarg(player->argp[1], "loan or treaty? ", buf) == 0)
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
ltcp->type = ef_byname(buf);
|
ltcp->type = ef_byname_from(buf, lon_or_trt);
|
||||||
switch (ltcp->type) {
|
switch (ltcp->type) {
|
||||||
case EF_TREATY:
|
case EF_TREATY:
|
||||||
if (!opt_TREATIES) {
|
if (!opt_TREATIES) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ union item_u {
|
||||||
int
|
int
|
||||||
fuel(void)
|
fuel(void)
|
||||||
{
|
{
|
||||||
|
static int shp_or_lnd[] = { EF_SHIP, EF_LAND, EF_BAD };
|
||||||
struct nstr_item ni;
|
struct nstr_item ni;
|
||||||
union item_u item, item2;
|
union item_u item, item2;
|
||||||
int type;
|
int type;
|
||||||
|
@ -80,10 +81,8 @@ fuel(void)
|
||||||
if ((p =
|
if ((p =
|
||||||
getstarg(player->argp[1], "Ship or land unit (s,l)? ", buf)) == 0)
|
getstarg(player->argp[1], "Ship or land unit (s,l)? ", buf)) == 0)
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
type = ef_byname(p);
|
type = ef_byname_from(p, shp_or_lnd);
|
||||||
if (type == EF_SECTOR)
|
if (type < 0) {
|
||||||
type = EF_SHIP;
|
|
||||||
if (type != EF_SHIP && type != EF_LAND) {
|
|
||||||
pr("Ships or land units only! (s, l)\n");
|
pr("Ships or land units only! (s, l)\n");
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ static void use_ammo(struct emp_qelem *);
|
||||||
int
|
int
|
||||||
multifire(void)
|
multifire(void)
|
||||||
{
|
{
|
||||||
|
static int ef_with_guns[] = { EF_SECTOR, EF_SHIP, EF_LAND, EF_BAD };
|
||||||
s_char vbuf[20];
|
s_char vbuf[20];
|
||||||
s_char *ptr;
|
s_char *ptr;
|
||||||
double range2, range;
|
double range2, range;
|
||||||
|
@ -132,7 +133,7 @@ multifire(void)
|
||||||
buf)))
|
buf)))
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
player->argp[1] = 0;
|
player->argp[1] = 0;
|
||||||
type = ef_byname(p);
|
type = ef_byname_from(p, ef_with_guns);
|
||||||
if (type == EF_SECTOR) {
|
if (type == EF_SECTOR) {
|
||||||
if (opt_NO_FORT_FIRE) {
|
if (opt_NO_FORT_FIRE) {
|
||||||
pr("Fort firing is disabled.\n");
|
pr("Fort firing is disabled.\n");
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
int
|
int
|
||||||
mission(void)
|
mission(void)
|
||||||
{
|
{
|
||||||
|
static int ef_with_missions[] = { EF_SHIP, EF_LAND, EF_PLANE, EF_BAD };
|
||||||
s_char *p;
|
s_char *p;
|
||||||
int type;
|
int type;
|
||||||
int mission;
|
int mission;
|
||||||
|
@ -72,10 +73,8 @@ mission(void)
|
||||||
getstarg(player->argp[1], "Ship, plane or land unit (p,sh,la)? ",
|
getstarg(player->argp[1], "Ship, plane or land unit (p,sh,la)? ",
|
||||||
buf)) == 0)
|
buf)) == 0)
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
type = ef_byname(p);
|
type = ef_byname_from(p, ef_with_missions);
|
||||||
if (type == EF_SECTOR)
|
if (type < 0) {
|
||||||
type = EF_SHIP;
|
|
||||||
if (type != EF_SHIP && type != EF_LAND && type != EF_PLANE) {
|
|
||||||
pr("Ships, land units or planes only! (s, l, p)\n");
|
pr("Ships, land units or planes only! (s, l, p)\n");
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
int
|
int
|
||||||
set(void)
|
set(void)
|
||||||
{
|
{
|
||||||
|
static int ef_saleable[] = { EF_SHIP, EF_PLANE, EF_LAND, EF_NUKE, EF_BAD };
|
||||||
char *p;
|
char *p;
|
||||||
int type;
|
int type;
|
||||||
int price;
|
int price;
|
||||||
|
@ -76,18 +77,12 @@ set(void)
|
||||||
check_market();
|
check_market();
|
||||||
check_trade();
|
check_trade();
|
||||||
|
|
||||||
if ((p = getstarg(player->argp[1], "Item type? ", buf)) == 0)
|
if ((p = getstarg(player->argp[1], "Ship, plane, land unit or nuke? ", buf)) == 0)
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
if ((type = ef_byname(p)) < 0) {
|
if ((type = ef_byname_from(p, ef_saleable)) < 0) {
|
||||||
pr("%s: not an item type\n", p);
|
pr("You can sell only ships, planes, land units or nukes\n", p);
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
}
|
}
|
||||||
if (type == EF_SECTOR)
|
|
||||||
type = EF_SHIP;
|
|
||||||
if (type == EF_NEWS)
|
|
||||||
type = EF_NUKE;
|
|
||||||
if (type == EF_LOAN)
|
|
||||||
type = EF_LAND;
|
|
||||||
if (!snxtitem(&ni, type, player->argp[2]))
|
if (!snxtitem(&ni, type, player->argp[2]))
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
while (nxtitem(&ni, &item)) {
|
while (nxtitem(&ni, &item)) {
|
||||||
|
|
|
@ -41,12 +41,12 @@
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "common.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include "gen.h"
|
||||||
|
#include "match.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "nsc.h"
|
#include "nsc.h"
|
||||||
#include "file.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "gen.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int fillcache(struct empfile *, int);
|
static int fillcache(struct empfile *, int);
|
||||||
static int do_write(struct empfile *, void *, int, int);
|
static int do_write(struct empfile *, void *, int, int);
|
||||||
|
@ -437,6 +437,7 @@ ef_mtime(int type)
|
||||||
int
|
int
|
||||||
ef_byname(char *name)
|
ef_byname(char *name)
|
||||||
{
|
{
|
||||||
|
/* FIXME should use stmtch() */
|
||||||
struct empfile *ef;
|
struct empfile *ef;
|
||||||
int i;
|
int i;
|
||||||
int len;
|
int len;
|
||||||
|
@ -450,6 +451,37 @@ ef_byname(char *name)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search CHOICES[] for a table ID matching NAME.
|
||||||
|
* CHOICES[] contains indexes in empfile[] and is terminated with a
|
||||||
|
* negative value.
|
||||||
|
* Return the matching index if there is one, else -1.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ef_byname_from(char *name, int choices[])
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
int *p;
|
||||||
|
|
||||||
|
res = M_NOTFOUND;
|
||||||
|
for (p = choices; *p >= 0; p++) {
|
||||||
|
if (ef_check(*p) < 0)
|
||||||
|
continue;
|
||||||
|
switch (mineq(name, empfile[*p].name)) {
|
||||||
|
case ME_MISMATCH:
|
||||||
|
break;
|
||||||
|
case ME_PARTIAL:
|
||||||
|
if (res >= 0)
|
||||||
|
return M_NOTUNIQUE;
|
||||||
|
res = *p;
|
||||||
|
break;
|
||||||
|
case ME_EXACT:
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
ef_nameof(int type)
|
ef_nameof(int type)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue