[BACK]Return to html.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/html.c between version 1.268 and 1.269

version 1.268, 2020/04/18 20:40:10 version 1.269, 2020/04/19 15:16:56
Line 112  static const struct htmldata htmltags[TAG_MAX] = {
Line 112  static const struct htmldata htmltags[TAG_MAX] = {
 };  };
   
 /* Avoid duplicate HTML id= attributes. */  /* Avoid duplicate HTML id= attributes. */
   
   struct  id_entry {
           int      ord;   /* Ordinal number of the latest occurrence. */
           char     id[];  /* The id= attribute without any ordinal suffix. */
   };
 static  struct ohash     id_unique;  static  struct ohash     id_unique;
   
 static  void     html_reset_internal(struct html *);  static  void     html_reset_internal(struct html *);
Line 146  html_alloc(const struct manoutput *outopts)
Line 151  html_alloc(const struct manoutput *outopts)
         if (outopts->toc)          if (outopts->toc)
                 h->oflags |= HTML_TOC;                  h->oflags |= HTML_TOC;
   
         mandoc_ohash_init(&id_unique, 4, 0);          mandoc_ohash_init(&id_unique, 4, offsetof(struct id_entry, id));
   
         return h;          return h;
 }  }
Line 155  static void
Line 160  static void
 html_reset_internal(struct html *h)  html_reset_internal(struct html *h)
 {  {
         struct tag      *tag;          struct tag      *tag;
         char            *cp;          struct id_entry *entry;
         unsigned int     slot;          unsigned int     slot;
   
         while ((tag = h->tag) != NULL) {          while ((tag = h->tag) != NULL) {
                 h->tag = tag->next;                  h->tag = tag->next;
                 free(tag);                  free(tag);
         }          }
         cp = ohash_first(&id_unique, &slot);          entry = ohash_first(&id_unique, &slot);
         while (cp != NULL) {          while (entry != NULL) {
                 free(cp);                  free(entry);
                 cp = ohash_next(&id_unique, &slot);                  entry = ohash_next(&id_unique, &slot);
         }          }
         ohash_delete(&id_unique);          ohash_delete(&id_unique);
 }  }
Line 174  void
Line 179  void
 html_reset(void *p)  html_reset(void *p)
 {  {
         html_reset_internal(p);          html_reset_internal(p);
         mandoc_ohash_init(&id_unique, 4, 0);          mandoc_ohash_init(&id_unique, 4, offsetof(struct id_entry, id));
 }  }
   
 void  void
Line 329  html_fillmode(struct html *h, enum roff_tok want)
Line 334  html_fillmode(struct html *h, enum roff_tok want)
  * element and/or as a segment identifier for a URI in an <a> element.   * element and/or as a segment identifier for a URI in an <a> element.
  * The function may fail and return NULL if the node lacks text data   * The function may fail and return NULL if the node lacks text data
  * to create the attribute from.   * to create the attribute from.
  * If the "unique" argument is 0, the caller is responsible for   * The caller is responsible for free(3)ing the returned string.
  * free(3)ing the returned string after using it.   *
  * If the "unique" argument is non-zero, the "id_unique" ohash table   * If the "unique" argument is non-zero, the "id_unique" ohash table
  * is used for de-duplication and owns the returned string, so the   * is used for de-duplication.  If the "unique" argument is 1,
  * caller must not free(3) it.  In this case, it will be freed   * it is the first time the function is called for this tag and
  * automatically by html_reset() or html_free().   * location, so if an ordinal suffix is needed, it is incremented.
    * If the "unique" argument is 2, it is the second time the function
    * is called for this tag and location, so the ordinal suffix
    * remains unchanged.
  */   */
 char *  char *
 html_make_id(const struct roff_node *n, int unique)  html_make_id(const struct roff_node *n, int unique)
 {  {
         const struct roff_node  *nch;          const struct roff_node  *nch;
         char                    *buf, *bufs, *cp;          struct id_entry         *entry;
           char                    *buf, *cp;
           size_t                   len;
         unsigned int             slot;          unsigned int             slot;
         int                      suffix;  
   
         if (n->tag != NULL)          if (n->tag != NULL)
                 buf = mandoc_strdup(n->tag);                  buf = mandoc_strdup(n->tag);
Line 386  html_make_id(const struct roff_node *n, int unique)
Line 395  html_make_id(const struct roff_node *n, int unique)
   
         /* Avoid duplicate HTML id= attributes. */          /* Avoid duplicate HTML id= attributes. */
   
         bufs = NULL;  
         suffix = 1;  
         slot = ohash_qlookup(&id_unique, buf);          slot = ohash_qlookup(&id_unique, buf);
         cp = ohash_find(&id_unique, slot);          if ((entry = ohash_find(&id_unique, slot)) == NULL) {
         if (cp != NULL) {                  len = strlen(buf) + 1;
                 while (cp != NULL) {                  entry = mandoc_malloc(sizeof(*entry) + len);
                         free(bufs);                  entry->ord = 1;
                         if (++suffix > 127) {                  memcpy(entry->id, buf, len);
                                 free(buf);                  ohash_insert(&id_unique, slot, entry);
                                 return NULL;          } else if (unique == 1)
                         }                  entry->ord++;
                         mandoc_asprintf(&bufs, "%s_%d", buf, suffix);  
                         slot = ohash_qlookup(&id_unique, bufs);          if (entry->ord > 1) {
                         cp = ohash_find(&id_unique, slot);                  cp = buf;
                 }                  mandoc_asprintf(&buf, "%s_%d", cp, entry->ord);
                 free(buf);                  free(cp);
                 buf = bufs;  
         }          }
         ohash_insert(&id_unique, slot, buf);  
         return buf;          return buf;
 }  }
   
Line 786  print_otag_id(struct html *h, enum htmltag elemtype, c
Line 791  print_otag_id(struct html *h, enum htmltag elemtype, c
         if (n->flags & NODE_ID)          if (n->flags & NODE_ID)
                 id = html_make_id(n, 1);                  id = html_make_id(n, 1);
         if (n->flags & NODE_HREF)          if (n->flags & NODE_HREF)
                 href = id == NULL ? html_make_id(n, 0) : id;                  href = id == NULL ? html_make_id(n, 2) : id;
         if (href != NULL && htmltags[elemtype].flags & HTML_INPHRASE)          if (href != NULL && htmltags[elemtype].flags & HTML_INPHRASE)
                 ret = print_otag(h, TAG_A, "chR", "permalink", href);                  ret = print_otag(h, TAG_A, "chR", "permalink", href);
         t = print_otag(h, elemtype, "ci", cattr, id);          t = print_otag(h, elemtype, "ci", cattr, id);
Line 804  print_otag_id(struct html *h, enum htmltag elemtype, c
Line 809  print_otag_id(struct html *h, enum htmltag elemtype, c
                                 print_otag(h, TAG_A, "chR", "permalink", href);                                  print_otag(h, TAG_A, "chR", "permalink", href);
                 }                  }
         }          }
           free(id);
         if (id == NULL)          if (id == NULL)
                 free(href);                  free(href);
         return ret;          return ret;
Line 915  print_tagged_text(struct html *h, const char *word, st
Line 921  print_tagged_text(struct html *h, const char *word, st
         print_metaf(h);          print_metaf(h);
         print_indent(h);          print_indent(h);
   
         if (n != NULL && (href = html_make_id(n, 0)) != NULL) {          if (n != NULL && (href = html_make_id(n, 2)) != NULL) {
                 t = print_otag(h, TAG_A, "chR", "permalink", href);                  t = print_otag(h, TAG_A, "chR", "permalink", href);
                 free(href);                  free(href);
         } else          } else

Legend:
Removed from v.1.268  
changed lines
  Added in v.1.269

CVSweb