From 7dc1106ec15f9e3c7b8fd9cfc5a8c4700a0d78e7 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Fri, 25 Nov 2022 08:37:55 -0500 Subject: [PATCH 01/10] Sort the glyph cache and search it with bsearch Also, recognize G_slime_mold and G_piletop_slime_mold when the fruit has been set. --- include/system.h | 5 ++++ src/utf8map.c | 72 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/include/system.h b/include/system.h index 2616b07f6..432315a71 100644 --- a/include/system.h +++ b/include/system.h @@ -148,13 +148,18 @@ extern void perror(const char *); #ifdef POSIX_TYPES extern void qsort(genericptr_t, size_t, size_t, int (*)(const genericptr, const genericptr)); +extern genericptr_t bsearch(const genericptr, const genericptr, size_t, size_t, + int (*)(const genericptr, const genericptr)); #else #if defined(BSD) || defined(ULTRIX) extern int qsort(); +extern genericptr_t bsearch(); #else #if !defined(LATTICE) && !defined(AZTEC_50) extern void qsort(genericptr_t, size_t, size_t, int (*)(const genericptr, const genericptr)); +extern genericptr_t bsearch(const genericptr, const genericptr, size_t, size_t, + int (*)(const genericptr, const genericptr)); #endif #endif #endif diff --git a/src/utf8map.c b/src/utf8map.c index 4748cd618..37d63b77a 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -34,7 +34,7 @@ struct glyphid_cache_t { int glyphnum; char *id; }; -struct glyphid_cache_t *glyphid_cache; +static struct glyphid_cache_t *glyphid_cache; struct find_struct glyphcache_find, to_custom_symbol_find; static void to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat); @@ -44,6 +44,8 @@ static int glyph_find_core(const char *id, struct find_struct *findwhat); static char *fix_glyphname(char *str); static int32_t rgbstr_to_int32(const char *rgbstr); boolean closest_color(uint32_t lcolor, uint32_t *closecolor, int *clridx); +static int glyphid_sort_compare(const void *p1, const void *p2); +static int glyphid_search_compare(const void *p1, const void *p2); static void to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat) @@ -335,6 +337,26 @@ void fill_glyphid_cache(void) glyphid_cache = (struct glyphid_cache_t *) 0; } } + if (glyphid_cache) { + for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { + if (glyphid_cache[glyph].id != NULL) { + lcase(glyphid_cache[glyph].id); + } + } + qsort(glyphid_cache, MAX_GLYPH, sizeof(glyphid_cache[0]), + glyphid_sort_compare); + } +} + +static int +glyphid_sort_compare(const void *p1, const void *p2) +{ + const struct glyphid_cache_t *elem1 = (const struct glyphid_cache_t *) p1; + const struct glyphid_cache_t *elem2 = (const struct glyphid_cache_t *) p2; + const char *id1 = elem1->id ? elem1->id : ""; + const char *id2 = elem2->id ? elem2->id : ""; + + return strcmp(id1, id2); } void free_glyphid_cache(void) @@ -601,18 +623,28 @@ parse_id(const char *id, struct find_struct *findwhat) } } if (is_G || filling_cache || dump_ids) { - /* individual matching glyph entries */ - for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { - if (!filling_cache && id && glyphid_cache) { - if (!glyphid_cache[glyph].id) /* skipped during cache fill */ - continue; - if (!strcmpi(id, glyphid_cache[glyph].id)) { - findwhat->findtype = find_glyph; - findwhat->val = glyph; - findwhat->loadsyms_offset = 0; - return 1; - } + if (!filling_cache && id && glyphid_cache) { + char *id_l; + const struct glyphid_cache_t *gptr; + + id_l = dupstr(id); + lcase(id_l); + gptr = (const struct glyphid_cache_t *) + bsearch(id_l, glyphid_cache, MAX_GLYPH, + sizeof(glyphid_cache[0]), + glyphid_search_compare); + free(id_l); + if (gptr != NULL) { + findwhat->findtype = find_glyph; + findwhat->val = gptr->glyphnum; + findwhat->loadsyms_offset = 0; + return 1; } else { + return 0; + } + } else { + /* individual matching glyph entries */ + for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { skip_base = FALSE; skip_this_one = FALSE; buf[0][0] = buf[1][0] = buf[2][0] = buf[3][0] = buf[4][0] = @@ -700,6 +732,8 @@ parse_id(const char *id, struct find_struct *findwhat) (i == SCR_BLANK_PAPER) ? "blank scroll" : (i == SPE_BLANK_PAPER) ? "blank spellbook" + : (i == SLIME_MOLD) + ? "slime mold" : obj_descr[i].oc_name); Snprintf(buf[1], sizeof buf[1], "%s%s%s", glyph_is_normal_piletop_obj(glyph) @@ -839,8 +873,8 @@ parse_id(const char *id, struct find_struct *findwhat) } } } - } /* not glyphid_cache */ - } + } + } /* not glyphid_cache */ } else if (is_S) { /* cmap entries */ for (i = 0; i < cmap_count; ++i) { @@ -878,6 +912,16 @@ parse_id(const char *id, struct find_struct *findwhat) return 0; } +static int +glyphid_search_compare(const void *p1, const void *p2) +{ + const char *key = (const char *) p1; + const struct glyphid_cache_t *elem = (const struct glyphid_cache_t *) p2; + const char *str = elem->id ? elem->id : ""; + + return strcmp(key, str); +} + static struct { int index; uint32_t value; From d70bdeab3b976549bdd5d2a5a2675a864ca11f62 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Fri, 25 Nov 2022 08:39:03 -0500 Subject: [PATCH 02/10] Fill the glyph cache when switching symbol sets --- src/symbols.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/symbols.c b/src/symbols.c index 4e84b1765..f7a4d3fef 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1031,7 +1031,19 @@ do_symset(boolean rogueflag) if (gs.symset[which_set].name) { /* non-default symbols */ - if (read_sym_file(which_set)) { + int ok; +#ifdef ENHANCED_SYMBOLS + if (!glyphid_cache_status()) { + fill_glyphid_cache(); + } +#endif + ok = read_sym_file(which_set); +#ifdef ENHANCED_SYMBOLS + if (glyphid_cache_status()) { + free_glyphid_cache(); + } +#endif + if (ok) { ready_to_switch = TRUE; } else { clear_symsetentry(which_set, TRUE); From 51ec42886e5ae8d25846e2bd0dc8e83c9bcbf168 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Fri, 25 Nov 2022 08:39:38 -0500 Subject: [PATCH 03/10] Fix -dumpglyphids on Unix The order of the statements needs to be changed, so the -d is not interpreted as requesting a directory. --- sys/unix/unixmain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 4992d9988..796c6fedc 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -114,12 +114,12 @@ main(int argc, char *argv[]) if (!dir) dir = nh_getenv("HACKDIR"); #endif /* CHDIR */ - /* handle -dalthackdir, -s , --version, --showpaths */ - early_options(&argc, &argv, &dir); #ifdef ENHANCED_SYMBOLS if (argcheck(argc, argv, ARG_DUMPGLYPHIDS) == 2) exit(EXIT_SUCCESS); #endif + /* handle -dalthackdir, -s , --version, --showpaths */ + early_options(&argc, &argv, &dir); #ifdef CHDIR /* * Change directories before we initialize the window system so From d90cd6d7d2c7b5a6f7ec930bff30425519c6504d Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Mon, 5 Dec 2022 19:56:50 -0500 Subject: [PATCH 04/10] Skip match_sym for G_ lines --- src/symbols.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/symbols.c b/src/symbols.c index f7a4d3fef..6b21b7519 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -835,6 +835,10 @@ match_sym(char *buf) const char *p = strchr(buf, ':'), *q = strchr(buf, '='); const struct symparse *sp = loadsyms; + /* 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) { From e556af78eced970b8562b0f2e34bba14cfdf131f Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Mon, 5 Dec 2022 19:57:46 -0500 Subject: [PATCH 05/10] Use pointer assignments to generate glyph names --- src/utf8map.c | 140 +++++++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/src/utf8map.c b/src/utf8map.c index 37d63b77a..c62861dac 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -581,7 +581,7 @@ parse_id(const char *id, struct find_struct *findwhat) pm_count = 0, oc_count = 0, cmap_count = 0; boolean skip_base = FALSE, skip_this_one, dump_ids = FALSE, filling_cache = FALSE, is_S = FALSE, is_G = FALSE; - char buf[5][QBUFSZ]; + char buf[4][QBUFSZ]; if (findwhat->findtype == find_nothing && findwhat->restype) { if (findwhat->restype == res_dump_glyphids) { @@ -647,129 +647,123 @@ parse_id(const char *id, struct find_struct *findwhat) for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { skip_base = FALSE; skip_this_one = FALSE; - buf[0][0] = buf[1][0] = buf[2][0] = buf[3][0] = buf[4][0] = - '\0'; + buf[0][0] = buf[1][0] = buf[2][0] = buf[3][0] = '\0'; if (glyph_is_monster(glyph)) { - /* buf[2] will hold the distinguishing prefix */ - /* buf[3] will hold the base name */ - buf[2][0] = '\0'; - Snprintf(buf[3], sizeof buf[3], "%s", - monsdump[glyph_to_mon(glyph)].nm); + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + const char *buf2 = ""; + const char *buf3 = monsdump[glyph_to_mon(glyph)].nm; if (glyph_is_normal_male_monster(glyph)) { - Snprintf(buf[2], sizeof buf[2], "male_"); + buf2 = "male_"; } else if (glyph_is_normal_female_monster(glyph)) { - Snprintf(buf[2], sizeof buf[2], "female_"); + buf2 = "female_"; } else if (glyph_is_ridden_male_monster(glyph)) { - Snprintf(buf[2], sizeof buf[2], "ridden_male_"); + buf2 = "ridden_male_"; } else if (glyph_is_ridden_female_monster(glyph)) { - Snprintf(buf[2], sizeof buf[2], "ridden_female_"); + buf2 = "ridden_female_"; } else if (glyph_is_detected_male_monster(glyph)) { - Snprintf(buf[2], sizeof buf[2], "detected_male_"); + buf2 = "detected_male_"; } else if (glyph_is_detected_female_monster(glyph)) { - Snprintf(buf[2], sizeof buf[2], "detected_female_"); + buf2 = "detected_female_"; } else if (glyph_is_male_pet(glyph)) { - Snprintf(buf[2], sizeof buf[2], "pet_male_"); + buf2 = "pet_male_"; } else if (glyph_is_female_pet(glyph)) { - Snprintf(buf[2], sizeof buf[2], "pet_female_"); + buf2 = "pet_female_"; } - Snprintf(buf[1], sizeof buf[1], "%s%s", buf[2], buf[3]); + Snprintf(buf[1], sizeof buf[1], "%s%s", buf2, buf3); } else if (glyph_is_body(glyph)) { - /* buf[2] will hold the distinguishing prefix */ - /* buf[3] will hold the base name */ - buf[2][0] = '\0'; - Snprintf(buf[3], sizeof buf[3], "%s", - monsdump[glyph_to_body_corpsenm(glyph)].nm); + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + const char *buf2 = ""; + const char *buf3 = monsdump[glyph_to_body_corpsenm(glyph)].nm; if (glyph_is_body_piletop(glyph)) { - Snprintf(buf[2], sizeof buf[2], "piletop_body_"); + buf2 = "piletop_body_"; } else { - Snprintf(buf[2], sizeof buf[2], "body_"); + buf2 = "body_"; } - Snprintf(buf[1], sizeof buf[1], "%s%s", buf[2], buf[3]); + Snprintf(buf[1], sizeof buf[1], "%s%s", buf2, buf3); } else if (glyph_is_statue(glyph)) { - /* buf[2] will hold the distinguishing prefix */ - /* buf[3] will hold the base name */ - buf[2][0] = '\0'; - Snprintf(buf[3], sizeof buf[3], "%s", - monsdump[glyph_to_statue_corpsenm(glyph)].nm); + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + const char *buf2 = ""; + const char *buf3 = monsdump[glyph_to_statue_corpsenm(glyph)].nm; if (glyph_is_fem_statue_piletop(glyph)) { - Snprintf(buf[2], sizeof buf[2], - "piletop_statue_of_female_"); + buf2 = "piletop_statue_of_female_"; } else if (glyph_is_fem_statue(glyph)) { - Snprintf(buf[2], sizeof buf[2], "statue_of_female_"); + buf2 = "statue_of_female_"; } else if (glyph_is_male_statue_piletop(glyph)) { - Snprintf(buf[2], sizeof buf[2], - "piletop_statue_of_male_"); + buf2 = "piletop_statue_of_male_"; } else if (glyph_is_male_statue(glyph)) { - Snprintf(buf[2], sizeof buf[2], "statue_of_male_"); + buf2 = "statue_of_male_"; } - Snprintf(buf[1], sizeof buf[1], "%s%s", buf[2], buf[3]); + Snprintf(buf[1], sizeof buf[1], "%s%s", buf2, buf3); } else if (glyph_is_object(glyph)) { i = glyph_to_obj(glyph); - /* buf[2] will hold the distinguishing prefix */ - /* buf[3] will hold the base name */ - buf[2][0] = '\0'; + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + const char *buf2 = ""; + const char *buf3 = ""; if (((i > SCR_STINKING_CLOUD) && (i < SCR_MAIL)) || ((i > WAN_LIGHTNING) && (i < GOLD_PIECE))) skip_this_one = TRUE; if (!skip_this_one) { if ((i >= WAN_LIGHT) && (i <= WAN_LIGHTNING)) - Snprintf(buf[2], sizeof buf[2], "wand of "); + buf2 = "wand of "; else if ((i >= SPE_DIG) && (i < SPE_BLANK_PAPER)) - Snprintf(buf[2], sizeof buf[2], "spellbook of "); + buf2 = "spellbook of "; else if ((i >= SCR_ENCHANT_ARMOR) && (i <= SCR_STINKING_CLOUD)) - Snprintf(buf[2], sizeof buf[2], "scroll of "); + buf2 = "scroll of "; else if ((i >= POT_GAIN_ABILITY) && (i <= POT_WATER)) - Snprintf(buf[2], sizeof buf[2], "%s", - (i == POT_WATER) ? "flask of n" - : "potion of "); + buf2 = (i == POT_WATER) ? "flask of n" + : "potion of "; else if ((i >= RIN_ADORNMENT) && (i <= RIN_PROTECTION_FROM_SHAPE_CHAN)) - Snprintf(buf[2], sizeof buf[2], "ring of "); + buf2 = "ring of "; else if (i == LAND_MINE) - Snprintf(buf[2], sizeof buf[2], "unset "); - Snprintf(buf[3], sizeof buf[3], "%s", - (i == SCR_BLANK_PAPER) ? "blank scroll" + buf2 = "unset "; + buf3 = (i == SCR_BLANK_PAPER) ? "blank scroll" : (i == SPE_BLANK_PAPER) ? "blank spellbook" : (i == SLIME_MOLD) ? "slime mold" - : obj_descr[i].oc_name); + : obj_descr[i].oc_name; Snprintf(buf[1], sizeof buf[1], "%s%s%s", glyph_is_normal_piletop_obj(glyph) ? "piletop_" : "", - buf[2], buf[3]); + buf2, buf3); } } else if (glyph_is_cmap(glyph) || glyph_is_cmap_zap(glyph) || glyph_is_swallow(glyph) || glyph_is_explosion(glyph)) { int cmap = -1; - buf[2][0] = - '\0'; /* buf[2] will hold the distinguishing prefix */ - buf[3][0] = '\0'; /* buf[3] will hold the base name */ - buf[4][0] = - '\0'; /* buf[4] will hold the distinguishing suffix */ + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + /* buf4 will hold the distinguishing suffix */ + const char *buf2 = ""; + const char *buf3 = ""; + const char *buf4 = ""; if (glyph == GLYPH_CMAP_OFF) { cmap = S_stone; - Strcpy(buf[3], "stone substrate"); + buf3 = "stone substrate"; skip_base = TRUE; } else if (glyph_is_cmap_gehennom(glyph)) { cmap = (glyph - GLYPH_CMAP_GEH_OFF) + S_vwall; - Snprintf(buf[4], sizeof buf[4], "%s", "_gehennom"); + buf4 = "_gehennom"; } else if (glyph_is_cmap_knox(glyph)) { cmap = (glyph - GLYPH_CMAP_KNOX_OFF) + S_vwall; - Snprintf(buf[4], sizeof buf[4], "%s", "_knox"); + buf4 = "_knox"; } else if (glyph_is_cmap_main(glyph)) { cmap = (glyph - GLYPH_CMAP_MAIN_OFF) + S_vwall; - Snprintf(buf[4], sizeof buf[4], "%s", "_main"); + buf4 = "_main"; } else if (glyph_is_cmap_mines(glyph)) { cmap = (glyph - GLYPH_CMAP_MINES_OFF) + S_vwall; - Snprintf(buf[4], sizeof buf[4], "%s", "_mines"); + buf4 = "_mines"; } else if (glyph_is_cmap_sokoban(glyph)) { cmap = (glyph - GLYPH_CMAP_SOKO_OFF) + S_vwall; - Snprintf(buf[4], sizeof buf[4], "%s", "_sokoban"); + buf4 = "_sokoban"; } else if (glyph_is_cmap_a(glyph)) { cmap = (glyph - GLYPH_CMAP_A_OFF) + S_ndoor; } else if (glyph_is_cmap_altar(glyph)) { @@ -782,8 +776,9 @@ parse_id(const char *id, struct find_struct *findwhat) if (j != altar_other) { Snprintf(buf[2], sizeof buf[2], "%s_", altar_text[j]); + buf2 = buf[2]; } else { - Strcpy(buf[3], "altar other"); + buf3 = "altar other"; skip_base = TRUE; } } else if (glyph_is_cmap_b(glyph)) { @@ -799,7 +794,8 @@ parse_id(const char *id, struct find_struct *findwhat) loadsyms[cmap + cmap_offset].name + 2); Snprintf(buf[3], sizeof buf[3], "%s zap %s", zap_texts[j / 4], fix_glyphname(buf[2])); - buf[2][0] = '\0'; + buf3 = buf[3]; + buf2 = ""; skip_base = TRUE; } else if (glyph_is_cmap_c(glyph)) { cmap = (glyph - GLYPH_CMAP_C_OFF) + S_digbeam; @@ -815,6 +811,7 @@ parse_id(const char *id, struct find_struct *findwhat) i = cmap - S_sw_tl; Snprintf(buf[3], sizeof buf[3], "%s %s %s", "swallow", monsdump[mnum].nm, swallow_texts[cmap]); + buf3 = buf[3]; skip_base = TRUE; } else if (glyph_is_explosion(glyph)) { int expl; @@ -834,24 +831,27 @@ parse_id(const char *id, struct find_struct *findwhat) i = cmap - S_expl_tl; Snprintf(buf[2], sizeof buf[2], "%s ", expl_type_texts[expl]); + buf2 = buf[2]; Snprintf(buf[3], sizeof buf[3], "%s%s", "expl_", expl_texts[i]); + buf3 = buf[3]; skip_base = TRUE; } if (!skip_base) { if (cmap >= 0 && cmap < MAXPCHARS) { Snprintf(buf[3], sizeof buf[3], "%s", loadsyms[cmap + cmap_offset].name + 2); + buf3 = buf[3]; } } - Snprintf(buf[1], sizeof buf[1], "%s%s%s", buf[2], buf[3], - buf[4]); + Snprintf(buf[1], sizeof buf[1], "%s%s%s", buf2, buf3, + buf4); } else if (glyph_is_invisible(glyph)) { - Snprintf(buf[1], sizeof buf[1], "%s", "invisible"); + Snprintf(buf[1], sizeof buf[1], "invisible"); } else if (glyph_is_nothing(glyph)) { - Snprintf(buf[1], sizeof buf[1], "%s", "nothing"); + Snprintf(buf[1], sizeof buf[1], "nothing"); } else if (glyph_is_unexplored(glyph)) { - Snprintf(buf[1], sizeof buf[1], "%s", "unexplored"); + Snprintf(buf[1], sizeof buf[1], "unexplored"); } else if (glyph_is_warning(glyph)) { j = glyph - GLYPH_WARNING_OFF; Snprintf(buf[1], sizeof buf[1], "%s%d", "warning", j); From b9ef6e6bb9ccafe4dff4d4d4b2564d47be754bd9 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Tue, 6 Dec 2022 18:46:43 -0500 Subject: [PATCH 06/10] Define a tail pointer for the glyph list Use the tail pointer to add new glyphs, avoiding the need to traverse the list. --- include/sym.h | 1 + src/symbols.c | 1 + src/utf8map.c | 23 ++++++----------------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/include/sym.h b/include/sym.h index 165492dd2..8dd14c311 100644 --- a/include/sym.h +++ b/include/sym.h @@ -157,6 +157,7 @@ struct symset_customization { int count; int custtype; struct customization_detail *details; + struct customization_detail *details_end; }; #endif /* ENHANCED_SYMBOLS */ diff --git a/src/symbols.c b/src/symbols.c index 6b21b7519..383d8b8eb 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1200,6 +1200,7 @@ purge_custom_entries(enum graphics_sets which_set) details = next; } gdc->details = 0; + gdc->details_end = 0; if (gdc->customization_name) { free((genericptr_t) gdc->customization_name); gdc->customization_name = 0; diff --git a/src/utf8map.c b/src/utf8map.c index c62861dac..87ebb11e3 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -509,16 +509,15 @@ add_custom_urep_entry( { static uint32_t closecolor = 0; static int clridx = 0; - int retval = 0; struct symset_customization *gdc = &gs.sym_customizations[which_set]; - struct customization_detail *details, *prev = 0, *newdetails = 0, - *lastdetail = 0; + struct customization_detail *details, *newdetails = 0; if (!gdc->details) { gdc->customization_name = dupstr(customization_name); gdc->custtype = custom_ureps; gdc->details = 0; + gdc->details_end = 0; } details = find_matching_symset_customization(customization_name, custom_symbols, which_set); @@ -537,7 +536,6 @@ add_custom_urep_entry( details->content.urep.u.utf32ch = utf32ch; return 1; } - prev = details; details = details->next; } } @@ -554,23 +552,14 @@ add_custom_urep_entry( newdetails->content.urep.u.u256coloridx = 0; newdetails->content.urep.u.utf32ch = utf32ch; newdetails->next = (struct customization_detail *) 0; - if (!details && prev) { - prev->next = newdetails; - retval = 1; - } else if (!gdc->details) { + if (gdc->details == NULL) { gdc->details = newdetails; - retval = 1; } else { - lastdetail = gdc->details; - while (lastdetail) { - prev = lastdetail; - lastdetail = lastdetail->next; - } - prev->next = newdetails; - retval = 1; + gdc->details_end->next = newdetails; } + gdc->details_end = newdetails; gdc->count++; - return retval; + return 1; } static int From d5bc73881220bd385758a704cb0f803be3b785ae Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Fri, 9 Dec 2022 17:24:21 -0500 Subject: [PATCH 07/10] Replace Snprintf with faster Strcpy --- src/utf8map.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/utf8map.c b/src/utf8map.c index 87ebb11e3..c955f5b53 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -659,7 +659,9 @@ parse_id(const char *id, struct find_struct *findwhat) } else if (glyph_is_female_pet(glyph)) { buf2 = "pet_female_"; } - Snprintf(buf[1], sizeof buf[1], "%s%s", buf2, buf3); + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); } else if (glyph_is_body(glyph)) { /* buf2 will hold the distinguishing prefix */ /* buf3 will hold the base name */ @@ -670,7 +672,9 @@ parse_id(const char *id, struct find_struct *findwhat) } else { buf2 = "body_"; } - Snprintf(buf[1], sizeof buf[1], "%s%s", buf2, buf3); + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); } else if (glyph_is_statue(glyph)) { /* buf2 will hold the distinguishing prefix */ /* buf3 will hold the base name */ @@ -685,7 +689,9 @@ parse_id(const char *id, struct find_struct *findwhat) } else if (glyph_is_male_statue(glyph)) { buf2 = "statue_of_male_"; } - Snprintf(buf[1], sizeof buf[1], "%s%s", buf2, buf3); + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); } else if (glyph_is_object(glyph)) { i = glyph_to_obj(glyph); /* buf2 will hold the distinguishing prefix */ @@ -717,11 +723,11 @@ parse_id(const char *id, struct find_struct *findwhat) : (i == SLIME_MOLD) ? "slime mold" : obj_descr[i].oc_name; - Snprintf(buf[1], sizeof buf[1], "%s%s%s", - glyph_is_normal_piletop_obj(glyph) - ? "piletop_" - : "", - buf2, buf3); + Strcpy(buf[0], "G_"); + if (glyph_is_normal_piletop_obj(glyph)) + Strcat(buf[0], "piletop_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); } } else if (glyph_is_cmap(glyph) || glyph_is_cmap_zap(glyph) || glyph_is_swallow(glyph) @@ -798,8 +804,10 @@ parse_id(const char *id, struct find_struct *findwhat) cmap = glyph_to_swallow(glyph); mnum = j / ((S_sw_br - S_sw_tl) + 1); i = cmap - S_sw_tl; - Snprintf(buf[3], sizeof buf[3], "%s %s %s", "swallow", - monsdump[mnum].nm, swallow_texts[cmap]); + Strcpy(buf[3], "swallow "); + Strcat(buf[3], monsdump[mnum].nm); + Strcat(buf[3], " "); + Strcat(buf[3], swallow_texts[cmap]); buf3 = buf[3]; skip_base = TRUE; } else if (glyph_is_explosion(glyph)) { @@ -828,26 +836,27 @@ parse_id(const char *id, struct find_struct *findwhat) } if (!skip_base) { if (cmap >= 0 && cmap < MAXPCHARS) { - Snprintf(buf[3], sizeof buf[3], "%s", - loadsyms[cmap + cmap_offset].name + 2); - buf3 = buf[3]; + buf3 = loadsyms[cmap + cmap_offset].name + 2; } } - Snprintf(buf[1], sizeof buf[1], "%s%s%s", buf2, buf3, - buf4); + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); + Strcat(buf[0], buf4); } else if (glyph_is_invisible(glyph)) { - Snprintf(buf[1], sizeof buf[1], "invisible"); + Strcpy(buf[0], "G_invisible"); } else if (glyph_is_nothing(glyph)) { - Snprintf(buf[1], sizeof buf[1], "nothing"); + Strcpy(buf[0], "G_nothing"); } else if (glyph_is_unexplored(glyph)) { - Snprintf(buf[1], sizeof buf[1], "unexplored"); + Strcpy(buf[0], "G_unexplored"); } else if (glyph_is_warning(glyph)) { j = glyph - GLYPH_WARNING_OFF; - Snprintf(buf[1], sizeof buf[1], "%s%d", "warning", j); + Snprintf(buf[0], sizeof buf[0], "G_%s%d", "warning", j); } + if (memchr(buf[0], '\0', sizeof buf[0]) == NULL) + panic("parse_id: buf[0] overflowed\n"); if (!skip_this_one) { - Snprintf(buf[0], sizeof buf[0], "G_%s", - fix_glyphname(buf[1])); + fix_glyphname(buf[0]+2); if (dump_ids) { Fprintf(fp, "(%04d) %s\n", glyph, buf[0]); } else if (filling_cache) { From c7431d6942e6d90acdfc2c1e40413501eeb6569d Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Fri, 9 Dec 2022 18:24:48 -0500 Subject: [PATCH 08/10] Reimplement glyph cache as a hash table --- src/utf8map.c | 159 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 108 insertions(+), 51 deletions(-) diff --git a/src/utf8map.c b/src/utf8map.c index c955f5b53..66158dead 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -35,7 +35,13 @@ struct glyphid_cache_t { char *id; }; static struct glyphid_cache_t *glyphid_cache; +static unsigned glyphid_cache_lsize; +static size_t glyphid_cache_size; struct find_struct glyphcache_find, to_custom_symbol_find; +static void init_glyph_cache(void); +static void add_glyph_to_cache(int glyphnum, const char *id); +static int find_glyph_in_cache(const char *id); +static uint32 glyph_hash(const char *id); static void to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat); static int unicode_val(const char *cp); @@ -44,8 +50,6 @@ static int glyph_find_core(const char *id, struct find_struct *findwhat); static char *fix_glyphname(char *str); static int32_t rgbstr_to_int32(const char *rgbstr); boolean closest_color(uint32_t lcolor, uint32_t *closecolor, int *clridx); -static int glyphid_sort_compare(const void *p1, const void *p2); -static int glyphid_search_compare(const void *p1, const void *p2); static void to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat) @@ -316,15 +320,10 @@ glyph_find_core(const char *id, struct find_struct *findwhat) void fill_glyphid_cache(void) { - int glyph, reslt = 0; + int reslt = 0; if (!glyphid_cache) { - glyphid_cache = (struct glyphid_cache_t *) alloc( - MAX_GLYPH * sizeof(struct glyphid_cache_t)); - for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { - glyphid_cache[glyph].glyphnum = 0; - glyphid_cache[glyph].id = (char *) 0; - } + init_glyph_cache(); } if (glyphid_cache) { glyphcache_find = zero_find; @@ -337,26 +336,37 @@ void fill_glyphid_cache(void) glyphid_cache = (struct glyphid_cache_t *) 0; } } - if (glyphid_cache) { - for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { - if (glyphid_cache[glyph].id != NULL) { - lcase(glyphid_cache[glyph].id); - } - } - qsort(glyphid_cache, MAX_GLYPH, sizeof(glyphid_cache[0]), - glyphid_sort_compare); - } } -static int -glyphid_sort_compare(const void *p1, const void *p2) -{ - const struct glyphid_cache_t *elem1 = (const struct glyphid_cache_t *) p1; - const struct glyphid_cache_t *elem2 = (const struct glyphid_cache_t *) p2; - const char *id1 = elem1->id ? elem1->id : ""; - const char *id2 = elem2->id ? elem2->id : ""; +/* + * The glyph ID cache is a simple double-hash table. + * The cache size is a power of two, and two hashes are derived from the + * cache ID. The first is a location in the table, and the second is an + * offset. On any collision, the second hash is added to the first until + * a match or an empty bucket is found. + * The second hash is an odd number, which is necessary and sufficient + * to traverse the entire table. + */ - return strcmp(id1, id2); +static void +init_glyph_cache(void) +{ + size_t glyph; + + /* Cache size of power of 2 not less than 2*MAX_GLYPH */ + glyphid_cache_lsize = 0; + glyphid_cache_size = 1; + while (glyphid_cache_size < 2*MAX_GLYPH) { + ++glyphid_cache_lsize; + glyphid_cache_size <<= 1; + } + + glyphid_cache = (struct glyphid_cache_t *) alloc( + glyphid_cache_size * sizeof(struct glyphid_cache_t)); + for (glyph = 0; glyph < glyphid_cache_size; ++glyph) { + glyphid_cache[glyph].glyphnum = 0; + glyphid_cache[glyph].id = (char *) 0; + } } void free_glyphid_cache(void) @@ -375,6 +385,73 @@ void free_glyphid_cache(void) glyphid_cache = (struct glyphid_cache_t *) 0; } +static void +add_glyph_to_cache(int glyphnum, const char *id) +{ + uint32 hash = glyph_hash(id); + size_t hash1 = (size_t) (hash & (glyphid_cache_size - 1)); + size_t hash2 = (size_t) + (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); + size_t i = hash1; + unsigned count = 0; + + do { + ++count; + if (glyphid_cache[i].id == NULL) { + /* Empty bucket found */ + glyphid_cache[i].id = dupstr(id); + glyphid_cache[i].glyphnum = glyphnum; + return; + } + /* For speed, assume that no ID occurs twice */ + i = (i + hash2) & (glyphid_cache_size - 1); + } while (i != hash1); + /* This should never happen */ + panic("glyphid_cache full"); +} + +static int +find_glyph_in_cache(const char *id) +{ + uint32 hash = glyph_hash(id); + size_t hash1 = (size_t) (hash & (glyphid_cache_size - 1)); + size_t hash2 = (size_t) + (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); + size_t i = hash1; + unsigned count = 0; + + do { + ++count; + if (glyphid_cache[i].id == NULL) { + /* Empty bucket found */ + return -1; + } + if (strcmpi(id, glyphid_cache[i].id) == 0) { + /* Match found */ + return glyphid_cache[i].glyphnum; + } + i = (i + hash2) & (glyphid_cache_size - 1); + } while (i != hash1); + return -1; +} + +static uint32 +glyph_hash(const char *id) +{ + uint32 hash = 0; + size_t i; + + for (i = 0; id[i] != '\0'; ++i) { + char ch = id[i]; + if ('A' <= ch && ch <= 'Z') { + ch += 'a' - 'A'; + } + hash = (hash << 1) | (hash >> 31); + hash ^= ch; + } + return hash; +} + boolean glyphid_cache_status(void) { @@ -613,19 +690,10 @@ parse_id(const char *id, struct find_struct *findwhat) } if (is_G || filling_cache || dump_ids) { if (!filling_cache && id && glyphid_cache) { - char *id_l; - const struct glyphid_cache_t *gptr; - - id_l = dupstr(id); - lcase(id_l); - gptr = (const struct glyphid_cache_t *) - bsearch(id_l, glyphid_cache, MAX_GLYPH, - sizeof(glyphid_cache[0]), - glyphid_search_compare); - free(id_l); - if (gptr != NULL) { + int val = find_glyph_in_cache(id); + if (val >= 0) { findwhat->findtype = find_glyph; - findwhat->val = gptr->glyphnum; + findwhat->val = val; findwhat->loadsyms_offset = 0; return 1; } else { @@ -854,14 +922,13 @@ parse_id(const char *id, struct find_struct *findwhat) Snprintf(buf[0], sizeof buf[0], "G_%s%d", "warning", j); } if (memchr(buf[0], '\0', sizeof buf[0]) == NULL) - panic("parse_id: buf[0] overflowed\n"); + panic("parse_id: buf[0] overflowed"); if (!skip_this_one) { fix_glyphname(buf[0]+2); if (dump_ids) { Fprintf(fp, "(%04d) %s\n", glyph, buf[0]); } else if (filling_cache) { - glyphid_cache[glyph].glyphnum = glyph; - glyphid_cache[glyph].id = dupstr(buf[0]); + add_glyph_to_cache(glyph, buf[0]); } else if (id) { if (!strcmpi(id, buf[0])) { findwhat->findtype = find_glyph; @@ -910,16 +977,6 @@ parse_id(const char *id, struct find_struct *findwhat) return 0; } -static int -glyphid_search_compare(const void *p1, const void *p2) -{ - const char *key = (const char *) p1; - const struct glyphid_cache_t *elem = (const struct glyphid_cache_t *) p2; - const char *str = elem->id ? elem->id : ""; - - return strcmp(key, str); -} - static struct { int index; uint32_t value; From aa1d130345f06770bd1eb8b19b9ec57bf312540d Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Fri, 9 Dec 2022 18:58:19 -0500 Subject: [PATCH 09/10] Revert adding bsearch to system.h --- include/system.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/system.h b/include/system.h index 432315a71..2616b07f6 100644 --- a/include/system.h +++ b/include/system.h @@ -148,18 +148,13 @@ extern void perror(const char *); #ifdef POSIX_TYPES extern void qsort(genericptr_t, size_t, size_t, int (*)(const genericptr, const genericptr)); -extern genericptr_t bsearch(const genericptr, const genericptr, size_t, size_t, - int (*)(const genericptr, const genericptr)); #else #if defined(BSD) || defined(ULTRIX) extern int qsort(); -extern genericptr_t bsearch(); #else #if !defined(LATTICE) && !defined(AZTEC_50) extern void qsort(genericptr_t, size_t, size_t, int (*)(const genericptr, const genericptr)); -extern genericptr_t bsearch(const genericptr, const genericptr, size_t, size_t, - int (*)(const genericptr, const genericptr)); #endif #endif #endif From ea84598613f3caebdeca13b0b49ee6b017e99021 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Sat, 10 Dec 2022 13:13:28 -0500 Subject: [PATCH 10/10] Remove some debug code --- src/utf8map.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utf8map.c b/src/utf8map.c index 66158dead..1f1745c0a 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -393,10 +393,8 @@ add_glyph_to_cache(int glyphnum, const char *id) size_t hash2 = (size_t) (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); size_t i = hash1; - unsigned count = 0; do { - ++count; if (glyphid_cache[i].id == NULL) { /* Empty bucket found */ glyphid_cache[i].id = dupstr(id); @@ -418,10 +416,8 @@ find_glyph_in_cache(const char *id) size_t hash2 = (size_t) (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); size_t i = hash1; - unsigned count = 0; do { - ++count; if (glyphid_cache[i].id == NULL) { /* Empty bucket found */ return -1;