gbranden pushed a commit to branch master
in repository groff.

commit 45409e003ae0bc60b5f663ec667c1c4a11638a30
Author: G. Branden Robinson <[email protected]>
AuthorDate: Wed Aug 7 02:56:27 2024 -0500

    src/roff/troff/env.cpp: Slightly refactor.
    
    * src/roff/troff/env.cpp (hyphenate): Slightly refactor.  Reorder
      equality comparison to avoid inadvertent lvalue assignment.
      `memset()` the stack-allocated character array `hbuf` with null
      terminators as a paranoid hedge.  Rename `buf` to `bufp`, since it is
      a pointer and moreover used as a cursor into the word that is a
      candidate for hyphenation.  Pointers and arrays are _not_ synonymous
      in C/C++; see Chapter 4, _Expert C Programming: Deep C Secrets_, by
      van der Linden (1994).  Add assertions for further paranoia.  Use
      `static_cast` instead of C-style cast on dictionary values.
      `memset()` the stack-allocated integer array `word` with zeroes.
    
    Also add annotations, including null pointers with `nullptr` comment to
    ease any future transition to C++11, which defines it as a keyword.
---
 ChangeLog              | 14 ++++++++++++++
 src/roff/troff/env.cpp | 51 ++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8aba5f2d2..de9cd6205 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2024-08-07  G. Branden Robinson <[email protected]>
+
+       * src/roff/troff/env.cpp (hyphenate): Slightly refactor.
+       Reorder equality comparison to avoid inadvertent lvalue
+       assignment.  `memset()` the stack-allocated character array
+       `hbuf` with null terminators as a paranoid hedge.  Rename `buf`
+       to `bufp`, since it is a pointer and moreover used as a cursor
+       into the word that is a candidate for hyphenation.  Pointers and
+       arrays are _not_ synonymous in C/C++; see Chapter 4, _Expert C
+       Programming: Deep C Secrets_, by van der Linden (1994).  Add
+       assertions for further paranoia.  Use `static_cast` instead of
+       C-style cast on dictionary values.  `memset()` the
+       stack-allocated integer array `word` with zeroes.
+
 2024-08-07  G. Branden Robinson <[email protected]>
 
        [troff]: Fix code style nits.
diff --git a/src/roff/troff/env.cpp b/src/roff/troff/env.cpp
index 5e3371cff..ca69e38fa 100644
--- a/src/roff/troff/env.cpp
+++ b/src/roff/troff/env.cpp
@@ -4225,30 +4225,50 @@ void init_env_requests()
   register_dictionary.define("st", new variable_reg(&st_reg_contents));
 }
 
+// Appendix H of _The TeXbook_ is useful background for the following.
+
 void hyphenate(hyphen_list *h, unsigned flags)
 {
   if (!current_language)
     return;
   while (h) {
-    while (h && h->hyphenation_code == 0)
+    while (h && (0 == h->hyphenation_code))
       h = h->next;
     int len = 0;
+    // Locate hyphenable points within a (subset of) an input word.
+    //
+    // We first look up the word in the environment's hyphenation
+    // exceptions dictionary; its keys are C strings, so the buffer
+    // `hbuf` that holds our word needs to be null terminated and we
+    // allocate a byte for that.  If the lookup fails, we apply the
+    // hyphenation patterns, which require that the word be bracketed at
+    // each end with a dot ('.'), so we allocate two further bytes.
+    //
+    // `hbuf` can be thought of as a mapping of the letters of the input
+    // word to the hyphenation codes that correspond to each letter.
+    // The hyphenation codes are normalized; "AbBoT" becomes "abbot".
+    //
+    // We can hyphenate words longer than WORD_MAX, but WORD_MAX is the
+    // maximum size of the "window" inside a word within which we apply
+    // the hyphenation patterns to determine a break point.
     char hbuf[WORD_MAX + 2 + 1];
-    char *buf = hbuf + 1;
+    (void) memset(hbuf, '\0', sizeof hbuf);
+    char *bufp = hbuf + 1;
     hyphen_list *tem;
     for (tem = h; tem && len < WORD_MAX; tem = tem->next) {
       if (tem->hyphenation_code != 0)
-       buf[len++] = tem->hyphenation_code;
+       bufp[len++] = tem->hyphenation_code;
       else
        break;
     }
     hyphen_list *nexth = tem;
     if (len >= 2) {
-      // check `.hw' entries
-      buf[len] = 0;
-      unsigned char *pos
-       = (unsigned char *)current_language->exceptions.lookup(buf);
-      if (pos != 0) {
+      // Check hyphenation exceptions defined with `hw` request.
+      assert((bufp + len) < (hbuf + sizeof hbuf));
+      bufp[len] = '\0';
+      unsigned char *pos = static_cast<unsigned char *>(
+                          current_language->exceptions.lookup(bufp));
+      if (pos != 0 /* nullptr */) {
        int j = 0;
        int i = 1;
        for (tem = h; tem != 0 /* nullptr */; tem = tem->next, i++)
@@ -4258,12 +4278,14 @@ void hyphenate(hyphen_list *h, unsigned flags)
          }
       }
       else {
-       // check `\hyphenation' entries from pattern files;
-       // such entries are marked with a trailing space
-       buf[len] = ' ';
-       buf[len + 1] = 0;
-       pos = (unsigned char *)current_language->exceptions.lookup(buf);
-       if (pos != 0) {
+       // Check `\hyphenation' entries from pattern files; such entries
+       // are marked with a trailing space.
+       assert((hbuf + len + 1) < (hbuf + sizeof hbuf));
+       bufp[len] = ' ';
+       bufp[len + 1] = '\0';
+       pos = static_cast<unsigned char *>(
+             current_language->exceptions.lookup(bufp));
+       if (pos != 0 /* nullptr */) {
          int j = 0;
          int i = 1;
          tem = h;
@@ -4294,6 +4316,7 @@ void hyphenate(hyphen_list *h, unsigned flags)
        else {
          hbuf[0] = hbuf[len + 1] = '.';
          int num[WORD_MAX + 2 + 1];
+         (void) memset(num, 0, sizeof num);
          current_language->patterns.hyphenate(hbuf, len + 2, num);
          // The position of a hyphenation point gets marked with an odd
          // number.  Example:

_______________________________________________
Groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit

Reply via email to