]> git.pond.sub.org Git - empserver/commitdiff
(ef_byname_from): New.
authorMarkus Armbruster <armbru@pond.sub.org>
Thu, 27 Oct 2005 21:33:17 +0000 (21:33 +0000)
committerMarkus Armbruster <armbru@pond.sub.org>
Thu, 27 Oct 2005 21:33:17 +0000 (21:33 +0000)
(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.

include/file.h
src/lib/commands/cede.c
src/lib/commands/cons.c
src/lib/commands/fuel.c
src/lib/commands/mfir.c
src/lib/commands/miss.c
src/lib/commands/set.c
src/lib/common/file.c

index 301a0ca79102f692217aa0aee4c79425023ace52..2739558068eef4a8efefb8ae5e497b600b191d6d 100644 (file)
@@ -150,6 +150,7 @@ extern int ef_ensure_space(int, int, int);
 extern int ef_nelem(int);
 extern int ef_flags(int);
 extern int ef_byname(char *);
+extern int ef_byname_from(char *, int *);
 
 extern struct empfile empfile[];
 
index 7e882554a8a7cfe80194e057dc2d7b864d6f5409..7ca01d6ac3cc3262b8ff7ca05ec00d43cfa563b0 100644 (file)
@@ -55,6 +55,7 @@ static void grab_ship(struct shpstr *, natid);
 int
 cede(void)
 {
+    static int sct_or_shp[] = { EF_SECTOR, EF_SHIP, EF_BAD };
     natid to;
     int n;
     int is_sector = 0, is_ship = 0;
@@ -83,13 +84,8 @@ cede(void)
            return RET_FAIL;
        if (strlen(p) > 4)
            p[2] = 0;
-       type = ef_byname(p);
-
-       if (type == EF_SECTOR)
-           is_ship = 0;
-       else if (type == EF_SHIP)
-           is_sector = 0;
-       else {
+       type = ef_byname_from(p, sct_or_shp);
+       if (type < 0) {
            pr("Please type 'se' or 'sh'!\n");
            return RET_FAIL;
        }
index 51292f4bb25ce4c81a2c96b3c63775d9ec97e06c..f1999536c6020ff42200114b4b85d17c1a7c79b6 100644 (file)
@@ -110,6 +110,7 @@ cons(void)
 static int
 cons_choose(struct ltcomstr *ltcp)
 {
+    static int lon_or_trt[] = { EF_LOAN, EF_TREATY, EF_BAD };
     s_char *p;
     struct lonstr *lp;
     struct trtstr *tp;
@@ -119,7 +120,7 @@ cons_choose(struct ltcomstr *ltcp)
     memset(ltcp, 0, sizeof(*ltcp));
     if (getstarg(player->argp[1], "loan or treaty? ", buf) == 0)
        return RET_SYN;
-    ltcp->type = ef_byname(buf);
+    ltcp->type = ef_byname_from(buf, lon_or_trt);
     switch (ltcp->type) {
     case EF_TREATY:
        if (!opt_TREATIES) {
index 5ddc7daa72e708ae98b4251829e5bf476fa06d90..f97456d8ff077710e23a82147b053b2ca48e6b0e 100644 (file)
@@ -54,6 +54,7 @@ union item_u {
 int
 fuel(void)
 {
+    static int shp_or_lnd[] = { EF_SHIP, EF_LAND, EF_BAD };
     struct nstr_item ni;
     union item_u item, item2;
     int type;
@@ -80,10 +81,8 @@ fuel(void)
     if ((p =
         getstarg(player->argp[1], "Ship or land unit (s,l)? ", buf)) == 0)
        return RET_SYN;
-    type = ef_byname(p);
-    if (type == EF_SECTOR)
-       type = EF_SHIP;
-    if (type != EF_SHIP && type != EF_LAND) {
+    type = ef_byname_from(p, shp_or_lnd);
+    if (type < 0) {
        pr("Ships or land units only! (s, l)\n");
        return RET_SYN;
     }
index e4f23059576bd233cfdd10b495e04ac16cfe17f8..643077d34b541eee6813fa41b4b6288fbf357144 100644 (file)
@@ -86,6 +86,7 @@ static void use_ammo(struct emp_qelem *);
 int
 multifire(void)
 {
+    static int ef_with_guns[] = { EF_SECTOR, EF_SHIP, EF_LAND, EF_BAD };
     s_char vbuf[20];
     s_char *ptr;
     double range2, range;
@@ -132,7 +133,7 @@ multifire(void)
                           buf)))
            return RET_SYN;
        player->argp[1] = 0;
-       type = ef_byname(p);
+       type = ef_byname_from(p, ef_with_guns);
        if (type == EF_SECTOR) {
            if (opt_NO_FORT_FIRE) {
                pr("Fort firing is disabled.\n");
index 9dfb982ade14be93874f5c6b3083382fceab9f0c..60defb8fc6748d91ccb0c2c5c35f684a759e7cbc 100644 (file)
@@ -55,6 +55,7 @@
 int
 mission(void)
 {
+    static int ef_with_missions[] = { EF_SHIP, EF_LAND, EF_PLANE, EF_BAD };
     s_char *p;
     int type;
     int mission;
@@ -72,10 +73,8 @@ mission(void)
         getstarg(player->argp[1], "Ship, plane or land unit (p,sh,la)? ",
                  buf)) == 0)
        return RET_SYN;
-    type = ef_byname(p);
-    if (type == EF_SECTOR)
-       type = EF_SHIP;
-    if (type != EF_SHIP && type != EF_LAND && type != EF_PLANE) {
+    type = ef_byname_from(p, ef_with_missions);
+    if (type < 0) {
        pr("Ships, land units or planes only! (s, l, p)\n");
        return RET_SYN;
     }
index 45f887c8a1279fd557965a2639998057012bbab9..9e6a3b28508b3a0b21f57da41ca5811664a1735f 100644 (file)
@@ -53,6 +53,7 @@
 int
 set(void)
 {
+    static int ef_saleable[] = { EF_SHIP, EF_PLANE, EF_LAND, EF_NUKE, EF_BAD };
     char *p;
     int type;
     int price;
@@ -76,18 +77,12 @@ set(void)
     check_market();
     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;
-    if ((type = ef_byname(p)) < 0) {
-       pr("%s: not an item type\n", p);
+    if ((type = ef_byname_from(p, ef_saleable)) < 0) {
+       pr("You can sell only ships, planes, land units or nukes\n", p);
        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]))
        return RET_SYN;
     while (nxtitem(&ni, &item)) {
index a1a4b975e1f50d7d91da1ee5d0911a68a2b81362..c647a337a12d750cff48c74cab443aaa792d31a0 100644 (file)
 #if !defined(_WIN32)
 #include <unistd.h>
 #endif
-#include "misc.h"
-#include "nsc.h"
-#include "file.h"
 #include "common.h"
+#include "file.h"
 #include "gen.h"
-
+#include "match.h"
+#include "misc.h"
+#include "nsc.h"
 
 static int fillcache(struct empfile *, int);
 static int do_write(struct empfile *, void *, int, int);
@@ -437,6 +437,7 @@ ef_mtime(int type)
 int
 ef_byname(char *name)
 {
+    /* FIXME should use stmtch() */
     struct empfile *ef;
     int i;
     int len;
@@ -450,6 +451,37 @@ ef_byname(char *name)
     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 *
 ef_nameof(int type)
 {