=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/html.c,v retrieving revision 1.98 retrieving revision 1.99 diff -c -r1.98 -r1.99 *** src/usr.bin/mandoc/html.c 2018/05/21 01:10:06 1.98 --- src/usr.bin/mandoc/html.c 2018/05/25 20:23:39 1.99 *************** *** 1,4 **** ! /* $OpenBSD: html.c,v 1.98 2018/05/21 01:10:06 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons * Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze --- 1,4 ---- ! /* $OpenBSD: html.c,v 1.99 2018/05/25 20:23:39 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons * Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze *************** *** 20,25 **** --- 20,26 ---- #include #include #include + #include #include #include #include *************** *** 27,32 **** --- 28,34 ---- #include #include "mandoc_aux.h" + #include "mandoc_ohash.h" #include "mandoc.h" #include "roff.h" #include "out.h" *************** *** 115,120 **** --- 117,125 ---- "ex", /* SCALE_FS */ }; + /* Avoid duplicate HTML id= attributes. */ + static struct ohash id_unique; + static void a2width(const char *, struct roffsu *); static void print_byte(struct html *, char); static void print_endword(struct html *); *************** *** 142,147 **** --- 147,154 ---- if (outopts->fragment) h->oflags |= HTML_FRAGMENT; + mandoc_ohash_init(&id_unique, 4, 0); + return h; } *************** *** 150,164 **** { struct tag *tag; struct html *h; h = (struct html *)p; - while ((tag = h->tag) != NULL) { h->tag = tag->next; free(tag); } - free(h); } void --- 157,178 ---- { struct tag *tag; struct html *h; + char *cp; + unsigned int slot; h = (struct html *)p; while ((tag = h->tag) != NULL) { h->tag = tag->next; free(tag); } free(h); + + cp = ohash_first(&id_unique, &slot); + while (cp != NULL) { + free(cp); + cp = ohash_next(&id_unique, &slot); + } + ohash_delete(&id_unique); } void *************** *** 255,264 **** } char * ! html_make_id(const struct roff_node *n) { const struct roff_node *nch; ! char *buf, *cp; for (nch = n->child; nch != NULL; nch = nch->next) if (nch->type != ROFFT_TEXT) --- 269,280 ---- } char * ! html_make_id(const struct roff_node *n, int unique) { const struct roff_node *nch; ! char *buf, *bufs, *cp; ! unsigned int slot; ! int suffix; for (nch = n->child; nch != NULL; nch = nch->next) if (nch->type != ROFFT_TEXT) *************** *** 275,280 **** --- 291,320 ---- if (*cp == ' ') *cp = '_'; + if (unique == 0) + return buf; + + /* Avoid duplicate HTML id= attributes. */ + + bufs = NULL; + suffix = 1; + slot = ohash_qlookup(&id_unique, buf); + cp = ohash_find(&id_unique, slot); + if (cp != NULL) { + while (cp != NULL) { + free(bufs); + if (++suffix > 127) { + free(buf); + return NULL; + } + mandoc_asprintf(&bufs, "%s_%d", buf, suffix); + slot = ohash_qlookup(&id_unique, bufs); + cp = ohash_find(&id_unique, slot); + } + free(buf); + buf = bufs; + } + ohash_insert(&id_unique, slot, buf); return buf; }