diff --git a/src/glyphs.c b/src/glyphs.c index 226a7f208..8e12da56d 100644 --- a/src/glyphs.c +++ b/src/glyphs.c @@ -373,8 +373,10 @@ compose_glyph_name(int glyph, char *buf, size_t bufsz) }; j = glyph - GLYPH_SWALLOW_OFF; - cmap = glyph_to_swallow(glyph); mnum = j / ((S_sw_br - S_sw_tl) + 1); + if (!attacktype(&mons[mnum], AT_ENGL)) + return 0; + cmap = glyph_to_swallow(glyph); Snprintf(tmpbuf[3], sizeof tmpbuf[3], "swallow %s %s", monsdump[mnum].nm, swallow_texts[cmap]); buf3 = tmpbuf[3]; diff --git a/src/symbols.c b/src/symbols.c index 1512ed7c5..b1f459341 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -7,6 +7,9 @@ staticfn void savedsym_add(const char *, const char *, int); staticfn struct _savedsym *savedsym_find(const char *, int); +staticfn const struct symparse *search_loadsyms(const char *buf, size_t len); +staticfn int symparse_compare(const void *s1_, const void *s2_); +staticfn int symparse_find(const void *bstr_, const void *rec_); extern const uchar def_r_oc_syms[MAXOCLASSES]; /* drawing.c */ @@ -29,6 +32,11 @@ void (*utf8graphics_mode_callback)(void) = 0; /* set in term_start_screen and * found in unixtty,windtty,&c */ #endif +struct bounded_string { + const char *str; + size_t len; +}; + /* * Explanations of the functions found below: * @@ -864,42 +872,113 @@ match_sym(char *buf) { "S_explode8", "S_expl_bc" }, { "S_explode9", "S_expl_br" }, }; int i; - size_t len = strlen(buf); - const char *p = strchr(buf, ':'), *q = strchr(buf, '='); - const struct symparse *sp = loadsyms; + size_t len; + const struct symparse *sp; /* G_ lines will never match here */ if ((buf[0] == 'G' || buf[0] == 'g') && buf[1] == '_') return (struct symparse *) 0; - if (!p || (q && q < p)) - p = q; - if (p) { - /* note: there will be at most one space before the '=' - because caller has condensed buf[] with mungspaces() */ - if (p > buf && p[-1] == ' ') - p--; - len = (int) (p - buf); - } - while (sp->range) { - if ((len >= strlen(sp->name)) && !strncmpi(buf, sp->name, len)) - return sp; - sp++; - } + len = strcspn(buf, "=:"); + /* note: there will be at most one space before the '=' + because caller has condensed buf[] with mungspaces() */ + if (len != 0 && buf[len-1] == ' ') + len--; + sp = search_loadsyms(buf, len); + if (sp != NULL) + return sp; for (i = 0; i < SIZE(alternates); ++i) { if ((len >= strlen(alternates[i].altnm)) && !strncmpi(buf, alternates[i].altnm, len)) { - sp = loadsyms; - while (sp->range) { - if (!strcmp(alternates[i].nm, sp->name)) - return sp; - sp++; - } + sp = search_loadsyms(alternates[i].nm, strlen(alternates[i].nm)); + if (sp != NULL) + return sp; } } return (struct symparse *) 0; } +staticfn const struct symparse * +search_loadsyms(const char *buf, size_t len) +{ + struct bounded_string bstr; + + /* Sorted index to loadsyms */ + static boolean first_time = TRUE; + static const struct symparse *loadsyms_sorted[SIZE(loadsyms) - 1]; + if (first_time) { + const struct symparse *sp = loadsyms; + size_t i = 0; + while (sp->range) { + loadsyms_sorted[i] = sp; + ++sp; + ++i; + } + qsort(loadsyms_sorted, SIZE(loadsyms_sorted), sizeof(loadsyms_sorted[0]), + symparse_compare); + first_time = FALSE; + } + + bstr.str = buf; + bstr.len = len; + const struct symparse **sp = bsearch(&bstr, loadsyms_sorted, + SIZE(loadsyms_sorted), sizeof(loadsyms_sorted[0]), + symparse_find); + return sp ? *sp : NULL; +} + +staticfn int +symparse_compare(const void *s1_, const void *s2_) +{ + const struct symparse **s1 = (const struct symparse **)s1_; + const struct symparse **s2 = (const struct symparse **)s2_; + const char *n1 = (*s1)->name; + const char *n2 = (*s2)->name; + size_t i; + + /* Can we count on strcmpi to say less than or greater than consistently? */ + for (i = 0; n1[i] != 0 && n2[i] != 0; ++i) { + char c1 = n1[i]; + char c2 = n2[i]; + if ('A' <= c1 && c1 <= 'Z') { + c1 += 'a' - 'A'; + } + if ('A' <= c2 && c2 <= 'Z') { + c2 += 'a' - 'A'; + } + if (c1 != c2) { + return c1 - c2; + } + } + + return n1[i] - n2[i]; +} + +staticfn int +symparse_find(const void *bstr_, const void *rec_) +{ + const struct bounded_string *bstr = (const struct bounded_string *)bstr_; + const struct symparse **rec = (const struct symparse **)rec_; + size_t i; + + /* Can we count on strcmpi to say less than or greater than consistently? */ + for (i = 0; i < bstr->len; ++i) { + char c1 = bstr->str[i]; + char c2 = (*rec)->name[i]; + if ('A' <= c1 && c1 <= 'Z') { + c1 += 'a' - 'A'; + } + if ('A' <= c2 && c2 <= 'Z') { + c2 += 'a' - 'A'; + } + if (c1 != c2) { + return c1 - c2; + } + } + + return 0; +} + DISABLE_WARNING_FORMAT_NONLITERAL /*