gbranden pushed a commit to branch master
in repository groff.

commit 9a9d7b55b6cc565ed2c065b8e993bdac9fb576d1
Author: G. Branden Robinson <g.branden.robin...@gmail.com>
AuthorDate: Fri Feb 21 04:05:40 2025 -0600

    [troff]: Create characters less aggressively.
    
    Make it possible to retrieve information about a *roff character without
    creating it as a side effect.
    
    * src/roff/troff/charinfo.h (get_charinfo, get_charinfo_by_index):
    * src/roff/troff/token.h (get_char):
    * src/roff/troff/input.cpp (get_charinfo_by_index): Add new `bool`
      argument `lookup_only`, defaulting `false`.
    
    * src/roff/troff/input.cpp: Use these new facilities.
    
      (report_character_request): Prevent creation of each character we look
      up.  Improve diagnostics.  Report information about indexed characters
      (`\N'123'`) more intelligibly.
    
      (remove_character): Prevent creation of each character we remove.
      Intelligibly report nonexistence of characters for which removal is
      attempted.  Throw error when attempt is made to remove a
      non-character, like `\~`.
---
 ChangeLog                 | 18 ++++++++++++
 src/roff/troff/charinfo.h |  2 +-
 src/roff/troff/input.cpp  | 74 ++++++++++++++++++++++++++++++++++-------------
 src/roff/troff/token.h    |  3 +-
 4 files changed, 75 insertions(+), 22 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index afad02463..c03dd90ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2025-02-21  G. Branden Robinson <g.branden.robin...@gmail.com>
+
+       [troff]: Make it possible to retrieve information about a *roff
+       character without creating it as a side effect.
+
+       * src/roff/troff/charinfo.h (get_charinfo):
+       * src/roff/troff/token.h (get_char):
+       * src/roff/troff/input.cpp (get_charinfo_by_index): Add new
+       `bool` argument `lookup_only`, defaulting `false`.
+       * src/roff/troff/input.cpp: Use these new facilities.
+       (report_character_request): Prevent creation of each character
+       we look up.  Improve diagnostics.  Report information about
+       indexed characters (`\N'123'`) more intelligibly.
+       (remove_character): Prevent creation of each character we
+       remove.  Intelligibly report nonexistence of characters for
+       which removal is attempted.  Throw error when attempt is made to
+       remove a non-character, like `\~`.
+
 2025-02-21  G. Branden Robinson <g.branden.robin...@gmail.com>
 
        [troff]: Add member functions to `token` class to assist with
diff --git a/src/roff/troff/charinfo.h b/src/roff/troff/charinfo.h
index 05d785e91..93c1ca8a1 100644
--- a/src/roff/troff/charinfo.h
+++ b/src/roff/troff/charinfo.h
@@ -114,7 +114,7 @@ public:
   void dump();
 };
 
-charinfo *get_charinfo(symbol);
+charinfo *get_charinfo(symbol, bool /* lookup_only */ = false);
 extern charinfo *charset_table[];
 
 inline bool charinfo::overlaps_horizontally()
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 54072a520..f67090bef 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -4690,12 +4690,26 @@ static void report_character_request()
   }
   charinfo *ci;
   do {
-    ci = tok.get_char();
-    if (0 /* nullptr */ == ci)
-      warning(WARN_CHAR, "%1 is not a character", tok.description());
+    ci = tok.get_char(false, true /* lookup only */);
+    if (!tok.is_character()) {
+      error("character report request expects characters as arguments;"
+           " got %1", tok.description());
+      break;
+    }
+    if (0 /* nullptr */ == ci) {
+      if (!tok.is_indexed_character())
+       warning(WARN_CHAR, "%1 is not defined", tok.description());
+      else
+       warning(WARN_CHAR, "character with index %1 in the current font"
+               " is not defined", tok.character_index());
+    }
     else {
       // A charinfo doesn't know the name by which it is accessed.
-      errprint("%1\n", tok.description());
+      if (tok.is_indexed_character())
+       errprint("character indexed %1 in current font\n",
+                tok.character_index());
+      else
+       errprint("%1\n", tok.description());
       fflush(stderr);
       ci->dump();
     }
@@ -4714,12 +4728,27 @@ static void remove_character()
   }
   while (!tok.is_newline() && !tok.is_eof()) {
     if (!tok.is_space() && !tok.is_tab()) {
-      charinfo *ci = tok.get_char(true /* required */);
-      if (0 /* nullptr */ == ci)
+      if (tok.is_character()) {
+       charinfo *ci = tok.get_char(true /* required */,
+                                   true /* lookup only */);
+       if (0 /* nullptr */ == ci) {
+         if (!tok.is_indexed_character())
+           warning(WARN_CHAR, "%1 is not defined", tok.description());
+         else
+           warning(WARN_CHAR, "character with index %1 in the current"
+                   " font is not defined", tok.character_index());
+       }
+       else {
+         macro *m = ci->set_macro(0 /* nullptr */);
+         if (m)
+           delete m;
+       }
+      }
+      else {
+       error("cannot remove character; %1 is not a character",
+             tok.description());
        break;
-      macro *m = ci->set_macro(0 /* nullptr */);
-      if (m)
-       delete m;
+      }
     }
     tok.next();
   }
@@ -8148,16 +8177,17 @@ void define_class()
   skip_line();
 }
 
-static charinfo *get_charinfo_by_index(int n); // forward declaration
+// forward declaration
+static charinfo *get_charinfo_by_index(int n, bool lookup_only = false);
 
-charinfo *token::get_char(bool required)
+charinfo *token::get_char(bool required, bool lookup_only)
 {
   if (type == TOKEN_CHAR)
     return charset_table[c];
   if (type == TOKEN_SPECIAL_CHAR)
-    return get_charinfo(nm);
+    return get_charinfo(nm, lookup_only);
   if (type == TOKEN_INDEXED_CHAR)
-    return get_charinfo_by_index(val);
+    return get_charinfo_by_index(val, lookup_only);
   if (type == TOKEN_ESCAPE) {
     if (escape_char != 0)
       return charset_table[escape_char];
@@ -9986,14 +10016,18 @@ void debug_with_file_and_line(const char *filename,
 
 dictionary charinfo_dictionary(501);
 
-charinfo *get_charinfo(symbol nm)
+charinfo *get_charinfo(symbol nm, bool lookup_only)
 {
   void *p = charinfo_dictionary.lookup(nm);
   if (p != 0 /* nullptr */)
     return static_cast<charinfo *>(p);
-  charinfo *cp = new charinfo(nm);
-  (void) charinfo_dictionary.lookup(nm, cp);
-  return cp;
+  if (lookup_only)
+    return static_cast<charinfo *>(0 /* nullptr */);
+  else {
+    charinfo *cp = new charinfo(nm);
+    (void) charinfo_dictionary.lookup(nm, cp);
+    return cp;
+  }
 }
 
 int charinfo::next_index = 0;
@@ -10211,13 +10245,13 @@ symbol UNNAMED_SYMBOL("---");
 
 dictionary indexed_charinfo_dictionary(11);
 
-static charinfo *get_charinfo_by_index(int n)
+static charinfo *get_charinfo_by_index(int n, bool lookup_only)
 {
   static charinfo *index_table[256];
 
   if (n >= 0 && n < 256) {
     charinfo *ci = index_table[n];
-    if (0 /*nullptr */ == ci) {
+    if ((0 /*nullptr */ == ci) && !lookup_only) {
       ci = new charinfo(UNNAMED_SYMBOL);
       ci->set_number(n);
       index_table[n] = ci;
@@ -10227,7 +10261,7 @@ static charinfo *get_charinfo_by_index(int n)
   else {
     symbol ns(i_to_a(n));
     charinfo *ci = (charinfo *)indexed_charinfo_dictionary.lookup(ns);
-    if (0 /*nullptr */ == ci) {
+    if ((0 /*nullptr */ == ci) && !lookup_only) {
       ci = new charinfo(UNNAMED_SYMBOL);
       ci->set_number(n);
       (void) indexed_charinfo_dictionary.lookup(ns, ci);
diff --git a/src/roff/troff/token.h b/src/roff/troff/token.h
index 796d2b1bf..a3da2e2d2 100644
--- a/src/roff/troff/token.h
+++ b/src/roff/troff/token.h
@@ -99,7 +99,8 @@ public:
   bool operator!=(const token &); // ditto
   unsigned char ch();
   int character_index();
-  charinfo *get_char(bool /* required */ = false);
+  charinfo *get_char(bool /* required */ = false,
+                    bool /* lookup_only */ = false);
   bool add_to_zero_width_node_list(node **);
   void make_space();
   void make_newline();

_______________________________________________
groff-commit mailing list
groff-commit@gnu.org
https://lists.gnu.org/mailman/listinfo/groff-commit

Reply via email to