another static analyzer bit - Japanese_item_name()

The analyzer complained that the second call to Japanese_item_name()
might return Null after the first one didn't.
|    if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
|        actualnm = Japanese_item_name(otyp);
even though the code involved is self-contained and deterministic.
Then later in obj_typename() 'actualnm' gets passed to strcat() or
strcpy() where Null isn't acceptable.

Could probably fix that by caching and reusing the first return value:
|    if (Role_if(PM_SAMURAI) && (jname = Japanese_item_name(otyp)) != 0)
|        actualnm = jname;
but I went a different route, revising that routine to take a second
argument:
|    if (Role_if(PM_SAMURAI))
|        actualnm = Japanese_item_name(otyp, actualnm);
It now passes back 'actualnm' instead of Null when no substitution
takes place.

The recent introduction of generic objects without names meant that
'actualnm' could actually be Null, but generic objects only occur
for map glyphs and only when dknown is 0, so the actual-name field
shouldn't ever be get used for them.  Give actualnm a fallback value
just in case.

Wishing is a place that loops over all of objects[] so have it skip
the generic objects.  They're all flagged no-wish so weren't being
chosen, but explicitly skipping them makes the intention clear.
This commit is contained in:
PatR
2023-01-13 23:41:23 -08:00
parent ed884c0579
commit 97a90de172

View File

@@ -54,6 +54,7 @@ static void readobjnam_parse_charges(struct _readobjnam_data *);
static int readobjnam_postparse1(struct _readobjnam_data *);
static int readobjnam_postparse2(struct _readobjnam_data *);
static int readobjnam_postparse3(struct _readobjnam_data *);
static const char *Japanese_item_name(int, const char *);
struct Jitem {
int item;
@@ -73,7 +74,7 @@ struct Jitem {
&& typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
&& typ != OPAL)))
static struct Jitem Japanese_items[] = {
static const struct Jitem Japanese_items[] = {
{ SHORT_SWORD, "wakizashi" },
{ BROADSWORD, "ninja-to" },
{ FLAIL, "nunchaku" },
@@ -89,8 +90,6 @@ static struct Jitem Japanese_items[] = {
{ 0, "" }
};
static const char *Japanese_item_name(int i);
static char *
strprepend(char *s,const char * pref)
{
@@ -178,8 +177,13 @@ obj_typename(int otyp)
const char *un = ocl->oc_uname;
int nn = ocl->oc_name_known;
if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
actualn = Japanese_item_name(otyp);
if (Role_if(PM_SAMURAI))
actualn = Japanese_item_name(otyp, actualn);
/* generic items don't have an actual-name; we shouldn't ever be called
for those; pacify static analyzer without resorting to impossible() */
if (!actualn)
actualn = (otyp > 0 && otyp < MAXOCLASSES) ? "generic" : "object?";
switch (ocl->oc_class) {
case COIN_CLASS:
Strcpy(buf, "coin");
@@ -514,8 +518,12 @@ xname_flags(
boolean known, dknown, bknown;
buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
actualn = Japanese_item_name(typ);
if (Role_if(PM_SAMURAI))
actualn = Japanese_item_name(typ, actualn);
/* generic items don't have an actual-name; we shouldn't ever be called
for those; pacify static analyzer without resorting to impossible() */
if (!actualn)
actualn = (typ > 0 && typ < MAXOCLASSES) ? "generic" : "object?";
/* As of 3.6.2: this used to be part of 'dn's initialization, but it
needs to come after possibly overriding 'actualn' */
if (!dn)
@@ -2374,9 +2382,9 @@ static const char *const as_is[] = {
/* singularize/pluralize decisions common to both makesingular & makeplural */
static boolean
singplur_lookup(
char *basestr, char *endstring, /* base string, pointer to eos(string) */
boolean to_plural, /* true => makeplural, false => makesingular */
const char *const *alt_as_is) /* another set like as_is[] */
char *basestr, char *endstring, /* base string, pointer to eos(string) */
boolean to_plural, /* true => makeplural, false => makesingular */
const char *const *alt_as_is) /* another set like as_is[] */
{
const struct sing_plur *sp;
const char *same, *other, *const *as;
@@ -3143,7 +3151,7 @@ rnd_otyp_by_namedesc(
lo = gb.bases[(uchar) oclass];
hi = gb.bases[(uchar) oclass + 1] - 1;
} else {
lo = STRANGE_OBJECT + 1;
lo = MAXOCLASSES; /* STRANGE_OBJECT + 1; */
hi = NUM_OBJECTS - 1;
}
/* FIXME:
@@ -4324,10 +4332,10 @@ readobjnam_postparse3(struct _readobjnam_data *d)
d->typ = 0;
if (d->actualn) {
struct Jitem *j = Japanese_items;
const struct Jitem *j = Japanese_items;
while (j->item) {
if (d->actualn && !strcmpi(d->actualn, j->name)) {
if (!strcmpi(d->actualn, j->name)) {
d->typ = j->item;
return 2; /*goto typfnd;*/
}
@@ -4959,16 +4967,16 @@ rnd_class(int first, int last)
}
static const char *
Japanese_item_name(int i)
Japanese_item_name(int i, const char *ordinaryname)
{
struct Jitem *j = Japanese_items;
const struct Jitem *j = Japanese_items;
while (j->item) {
if (i == j->item)
return j->name;
j++;
}
return (const char *) 0;
return ordinaryname;
}
const char *