bugGNU roff - Bugs: bug #62692, [eqn] want a way to recover...

 
 

bug #62692: [eqn] want a way to recover "set" parameteric defaults

Submitter:  G. Branden Robinson <gbranden>
Submitted:  Fri 01 Jul 2022 05:37:15 AM UTC
   
 
Category:  Preprocessor eqn Severity:  1 - Wish
Item Group:  Feature change Status:  Fixed
Privacy:  Public Assigned to:  gbranden
Open/Closed:  Closed Planned Release:  1.24.0
* Mandatory Fields

Add a New Comment Rich Markup
   

Mon 28 Aug 2023 07:57:04 PM UTC, comment #2: 


commit 3c7c02e20006011b838d49930998bbf0ad324912
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
Date:   Sat Aug 26 11:18:22 2023 -0500

    [eqn]: Implement "reset" primitive/command (3/3).

    * src/preproc/eqn/tests/parameters-can-be-set-and-reset.sh: Test it.

    * src/preproc/eqn/eqn.am (eqn_TESTS): Run test.

commit 9e709d64f7aa5f3c706ef9154e596fbb6a87637a
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
Date:   Sat Aug 26 11:02:04 2023 -0500

    [eqn]: Implement "reset" primitive/command (2/3).

    * src/preproc/eqn/eqn.1.man (Customization): Document it.

    * NEWS: Add item.

commit 661dafc33b393b5191abade8fa5c25873d1f56e8
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
Date:   Sat Aug 26 07:14:53 2023 -0500

    [eqn]: Implement "reset" primitive/command (1/3).

    * src/preproc/eqn/box.cpp: Use `static` storage class for parametric
      defaults, moving them to file scope from global.  Rename `param_table`
      array of structs to `default_param_table`.  Use the length of this
      array for iteration since it is known at compile time.  Convert
      `param_table` to a null pointer.

      (set_param): Update diagnostic message text.

      (reset_param): New function restores a rendering parameter in
      `param_table` to its corresponding value in `default_param_table`.

      (get_param): New function accesses `param_table` entries via a C
      string rather than integer lvalues.  Use `assert()` to dump core; this
      function is never called by the parser, but only by static logic.  Add
      `fatal()` under this same circumstance, in case anyone `#define`s
      `NDEBUG`.

      (init_param_table): New function populates the (mutable) `param_table`
      from the (immutable) `default_param_table` using heap storage.

      (free_param_table): New function avoids memory leak by freeing the
      heap storage allocated for `param_table`.

    * src/preproc/eqn/eqn.h: Drop external declaration of `nroff`.

    * src/preproc/eqn/eqn.ypp: Add new token `RESET`.

    * src/preproc/eqn/lex.cpp: Map C string "reset" to token `RESET` in
      untagged struct `token_table`.

      (do_reset): Handle new keyword; if argument valid, call
      `reset_param()` with it.

      (yylex): Hook up token `RESET` to `do_reset()`.

    * src/preproc/eqn/box.h: Declare `reset_param()`, `get_param()`,
      `init_param_table()`, and `free_param_table()`.

    * src/preproc/eqn/main.cpp (main): Call `init_param_table()` when
      starting up.  Register `free_param_table()` with `std::atexit()`.

    * src/preproc/eqn/pbox.h: Drop external declarations of rendering
      parameters.

    * src/preproc/eqn/delim.cpp (build_extensible)
      (define_extensible_string, delim_box::compute_metrics):
    * src/preproc/eqn/lex.cpp (yylex):
    * src/preproc/eqn/limit.cpp (limit_box::compute_metrics):
    * src/preproc/eqn/list.cpp (compute_spacing):
    * src/preproc/eqn/other.cpp (accent_box::compute_metrics)
      (overline_char_box::overline_char_box):
      (overline_box::compute_metrics, overline_box::output):
      (underline_char_box::underline_char_box):
      (underline_box::compute_metrics, underline_box::output):
      (fat_box::compute_metrics, fat_box::output):
      (vcenter_box::compute_metrics):
    * src/preproc/eqn/over.cpp (over_box::compute_metrics):
      (over_box::output):
    * src/preproc/eqn/pile.cpp (pile_box::compute_metrics):
      (matrix_box::compute_metrics, matrix_box::output):
    * src/preproc/eqn/script.cpp (script_box::compute_metrics):
    * src/preproc/eqn/sqrt.cpp (sqrt_box::compute_metrics): Migrate from
      lvalue access to `get_param()` for parameter retrieval.

    Fixes <https://savannah.gnu.org/bugs/?62692>.


G. Branden Robinson <gbranden>
Group administrator
Fri 25 Aug 2023 09:55:01 PM UTC, comment #1: 

This works.  Need to write docs and a commit message, which will be an effort of itself.


diff --git a/src/preproc/eqn/box.cpp b/src/preproc/eqn/box.cpp
index a9dc0e01d..50f99f09d 100644
--- a/src/preproc/eqn/box.cpp
+++ b/src/preproc/eqn/box.cpp
@@ -35,57 +35,57 @@ int negative_space = -1;

 int minimum_size = 5;

-int fat_offset = 4;
-int body_height = 85;
-int body_depth = 35;
-
-int over_hang = 0;
-int accent_width = 31;
-int delimiter_factor = 900;
-int delimiter_shortfall = 50;
-
-int null_delimiter_space = 12;
-int script_space = 5;
-int thin_space = 17;
-int half_space = 17;
-int medium_space = 22;
-int thick_space = 28;
-int full_space = 28;
-
-int num1 = 70;
-int num2 = 40;
+static int fat_offset = 4;
+static int over_hang = 0;
+static int accent_width = 31;
+static int delimiter_factor = 900;
+static int delimiter_shortfall = 50;
+
+static int null_delimiter_space = 12;
+static int script_space = 5;
+static int thin_space = 17;
+static int half_space = 17;
+static int medium_space = 22;
+static int thick_space = 28;
+static int full_space = 28;
+
+static int num1 = 70;
+static int num2 = 40;
 // we don't use num3, because we don't have \atop
-int denom1 = 70;
-int denom2 = 36;
-int axis_height = 26;          // in 100ths of an em
-int sup1 = 42;
-int sup2 = 37;
-int sup3 = 28;
-int default_rule_thickness = 4;
-int sub1 = 20;
-int sub2 = 23;
-int sup_drop = 38;
-int sub_drop = 5;
-int x_height = 45;
-int big_op_spacing1 = 11;
-int big_op_spacing2 = 17;
-int big_op_spacing3 = 20;
-int big_op_spacing4 = 60;
-int big_op_spacing5 = 10;
+static int denom1 = 70;
+static int denom2 = 36;
+static int axis_height = 26;   // in 100ths of an em
+static int sup1 = 42;
+static int sup2 = 37;
+static int sup3 = 28;
+static int default_rule_thickness = 4;
+static int sub1 = 20;
+static int sub2 = 23;
+static int sup_drop = 38;
+static int sub_drop = 5;
+static int x_height = 45;
+static int big_op_spacing1 = 11;
+static int big_op_spacing2 = 17;
+static int big_op_spacing3 = 20;
+static int big_op_spacing4 = 60;
+static int big_op_spacing5 = 10;

 // These are for piles and matrices.

-int baseline_sep = 140;                // = num1 + denom1
-int shift_down = 26;           // = axis_height
-int column_sep = 100;          // = em space
-int matrix_side_sep = 17;      // = thin space
+static int baseline_sep = 140;         // = num1 + denom1
+static int shift_down = 26;            // = axis_height
+static int column_sep = 100;           // = em space
+static int matrix_side_sep = 17;       // = thin space

-int nroff = 0;                 // should we grok ndefine or tdefine?
+static int body_height = 85;
+static int body_depth = 35;
+
+static int nroff = 0;          // should we grok ndefine or tdefine?

 struct param {
   const char *name;
   int *ptr;
-} param_table[] = {
+} default_param_table[] = {
   { "fat_offset", &fat_offset },
   { "over_hang", &over_hang },
   { "accent_width", &accent_width },
@@ -128,14 +128,58 @@ struct param {
   { "nroff", &nroff },
 };

+struct param *param_table = 0 /* nullptr */;
+
+// Use the size of default_param_table to iterate through both it and
+// param_table, because the former is known constant to the compiler.
+
 void set_param(const char *name, int value)
 {
-  for (size_t i = 0; i < array_size(param_table); i++)
+  for (size_t i = 0; i <= array_size(default_param_table); i++)
+    if (strcmp(param_table[i].name, name) == 0) {
+      *(param_table[i].ptr) = value;
+      assert(*(param_table[i].ptr) == value);
+      return;
+    }
+  error("unrecognized parameter '%1'", name);
+}
+
+void reset_param(const char *name)
+{
+  for (size_t i = 0; i < array_size(default_param_table); i++)
     if (strcmp(param_table[i].name, name) == 0) {
-      *param_table[i].ptr = value;
+      *param_table[i].ptr = *(default_param_table[i].ptr);
       return;
     }
-  error("unrecognised parameter '%1'", name);
+  error("unrecognized parameter '%1'", name);
+}
+
+int get_param(const char *name)
+{
+  for (size_t i = 0; i < array_size(default_param_table); i++)
+    if (strcmp(param_table[i].name, name) == 0)
+      return *(param_table[i].ptr);
+  assert(0 == "attempted to access parameter not in table");
+  fatal("internal error: attempted to access parameter not in table");
+}
+
+void init_param_table()
+{
+  param_table = new param[array_size(default_param_table)];
+  for (size_t i = 0; i < array_size(default_param_table); i++) {
+    param_table[i].name = default_param_table[i].name;
+    param_table[i].ptr = new int(*(default_param_table[i].ptr));
+  }
+}
+
+void free_param_table()
+{
+  if (param_table != 0 /* nullptr */) {
+    for (size_t i = 0; i < array_size(default_param_table); i++)
+      delete param_table[i].ptr;
+    delete[] param_table;
+    param_table = 0 /* nullptr */;
+  }
 }

 int script_style(int style)
diff --git a/src/preproc/eqn/box.h b/src/preproc/eqn/box.h
index fc53e148b..baaf2179d 100644
--- a/src/preproc/eqn/box.h
+++ b/src/preproc/eqn/box.h
@@ -282,6 +282,10 @@ void restore_compatibility();
 void set_script_reduction(int n);
 void set_minimum_size(int n);
 void set_param(const char *name, int value);
+void reset_param(const char *name);
+int get_param(const char *name);
+void init_param_table();
+void free_param_table();

 void set_char_type(const char *type, char *ch);

diff --git a/src/preproc/eqn/delim.cpp b/src/preproc/eqn/delim.cpp
index 56519f188..d25592efd 100644
--- a/src/preproc/eqn/delim.cpp
+++ b/src/preproc/eqn/delim.cpp
@@ -242,7 +242,7 @@ static void build_extensible(const char *ext, const char *top, const char *mid,
     printf("/2");
   printf(">?0+\\n[" EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "]-1/(\\n["
         EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "])\n");
-
+
   printf(".nr " TOTAL_HEIGHT_REG " +(\\n[" EXT_HEIGHT_REG "]+\\n["
         EXT_DEPTH_REG "]*\\n[" TEMP_REG "]");
   if (mid)
@@ -250,7 +250,7 @@ static void build_extensible(const char *ext, const char *top, const char *mid,
   printf(")\n");
   printf(".ds " DELIM_STRING " \\Z" DELIMITER_CHAR
         "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG "]u/2u)'\n",
-        axis_height);
+        get_param("axis_height"));
   if (top)
     printf(".as " DELIM_STRING " \\v'\\n[" TOP_HEIGHT_REG "]u'"
           "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
@@ -313,7 +313,7 @@ static void define_extensible_string(char *delim, int uid,
         ".nr " TOTAL_HEIGHT_REG " \\n[rst]-\\n[rsb]\n"
         ".if \\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] "
         "\\{",
-        current_roman_font, d->small, axis_height,
+        current_roman_font, d->small, get_param("axis_height"),
         current_roman_font, d->small);

   char buf[256];
@@ -337,7 +337,7 @@ static void define_extensible_string(char *delim, int uid,
         ".el .nr " INDEX_REG " 0-1\n"
         "..\n"
         "." TEMP_MACRO "\n",
-        buf, buf, axis_height, buf);
+        buf, buf, get_param("axis_height"), buf);
   if (d->ext) {
     printf(".if \\n[" INDEX_REG "]<0 \\{.if c%s \\{\\\n", d->ext);
     build_extensible(d->ext, d->top, d->mid, d->bot);
@@ -348,10 +348,10 @@ static void define_extensible_string(char *delim, int uid,
   printf(".nr " WIDTH_FORMAT " +\\n[" DELIM_WIDTH_REG "]\n", uid);
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
         ">?(\\n[" TOTAL_HEIGHT_REG "]/2+%dM)\n",
-        uid, uid, axis_height);
+        uid, uid, get_param("axis_height"));
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
         ">?(\\n[" TOTAL_HEIGHT_REG "]/2-%dM)\n",
-        uid, uid, axis_height);
+        uid, uid, get_param("axis_height"));
 }

 int delim_box::compute_metrics(int style)
@@ -362,10 +362,12 @@ int delim_box::compute_metrics(int style)
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
   printf(".nr " DELTA_REG " \\n[" HEIGHT_FORMAT "]-%dM"
         ">?(\\n[" DEPTH_FORMAT "]+%dM)\n",
-        p->uid, axis_height, p->uid, axis_height);
+        p->uid, get_param("axis_height"), p->uid,
+        get_param("axis_height"));
   printf(".nr " DELTA_REG " 0\\n[" DELTA_REG "]*%d/500"
         ">?(\\n[" DELTA_REG "]*2-%dM)\n",
-        delimiter_factor, delimiter_shortfall);
+        get_param("delimiter_factor"),
+        get_param("delimiter_shortfall"));
   if (left) {
     define_extensible_string(left, uid, LEFT_DELIM);
     printf(".rn " DELIM_STRING " " LEFT_DELIM_STRING_FORMAT "\n",
diff --git a/src/preproc/eqn/eqn.h b/src/preproc/eqn/eqn.h
index a4143cbc5..37adb2178 100644
--- a/src/preproc/eqn/eqn.h
+++ b/src/preproc/eqn/eqn.h
@@ -35,7 +35,6 @@ extern int inline_flag;
 extern int draw_flag;
 extern int one_size_reduction_flag;
 extern int compatible_flag;
-extern int nroff;
 extern eqnmode_t output_format;
 extern int xhtml;

diff --git a/src/preproc/eqn/eqn.ypp b/src/preproc/eqn/eqn.ypp
index 3843bf4da..aa1345129 100644
--- a/src/preproc/eqn/eqn.ypp
+++ b/src/preproc/eqn/eqn.ypp
@@ -98,6 +98,7 @@ void yyerror(const char *);
 %token DELIM
 %token CHARTYPE
 %token SET
+%token RESET
 %token GRFONT
 %token GBFONT
 %token GIFONT
diff --git a/src/preproc/eqn/lex.cpp b/src/preproc/eqn/lex.cpp
index 16e634f93..b7de6fc66 100644
--- a/src/preproc/eqn/lex.cpp
+++ b/src/preproc/eqn/lex.cpp
@@ -110,6 +110,7 @@ static struct {
   { "type", TYPE },
   { "vcenter", VCENTER },
   { "set", SET },
+  { "reset", RESET },
   { "opprime", PRIME },
   { "grfont", GRFONT },
   { "gbfont", GBFONT },
@@ -1155,6 +1156,18 @@ void do_set()
   set_param(param.contents(), n);
 }

+void do_reset()
+{
+  int t = get_token(2);
+  if (t != TEXT && t != QUOTED_TEXT) {
+    lex_error("invalid parameter name argument to 'reset' primitive");
+    return;
+  }
+  token_buffer += '\0';
+  string param = token_buffer;
+  reset_param(param.contents());
+}
+
 int yylex()
 {
   for (;;) {
@@ -1170,13 +1183,13 @@ int yylex()
       do_definition(0);
       break;
     case TDEFINE:
-      if (!nroff)
+      if (!get_param("nroff"))
        do_definition(0);
       else
        ignore_definition();
       break;
     case NDEFINE:
-      if (nroff)
+      if (get_param("nroff"))
        do_definition(0);
       else
        ignore_definition();
@@ -1214,6 +1227,9 @@ int yylex()
     case SET:
       do_set();
       break;
+    case RESET:
+      do_reset();
+      break;
     case QUOTED_TEXT:
     case TEXT:
       token_buffer += '\0';
diff --git a/src/preproc/eqn/limit.cpp b/src/preproc/eqn/limit.cpp
index c8b0eb943..cd4a22410 100644
--- a/src/preproc/eqn/limit.cpp
+++ b/src/preproc/eqn/limit.cpp
@@ -115,20 +115,22 @@ int limit_box::compute_metrics(int style)
   if (to != 0) {
     printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT
           "]>?%dM+\\n[" HEIGHT_FORMAT "]\n",
-          uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid);
+          uid, get_param("big_op_spacing1"), to->uid,
+          get_param("big_op_spacing3"), p->uid);
     printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
           HEIGHT_FORMAT "]+%dM\n",
-          uid, uid, to->uid, big_op_spacing5);
+          uid, uid, to->uid, get_param("big_op_spacing5"));
   }
   else
     printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
   if (from != 0) {
     printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT
           "]>?%dM+\\n[" DEPTH_FORMAT "]\n",
-          uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid);
+          uid, get_param("big_op_spacing2"), from->uid,
+          get_param("big_op_spacing4"), p->uid);
     printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
           DEPTH_FORMAT "]+%dM\n",
-          uid, uid, from->uid, big_op_spacing5);
+          uid, uid, from->uid, get_param("big_op_spacing5"));
   }
   else
     printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
diff --git a/src/preproc/eqn/list.cpp b/src/preproc/eqn/list.cpp
index 2e0cb104a..c3b4dea11 100644
--- a/src/preproc/eqn/list.cpp
+++ b/src/preproc/eqn/list.cpp
@@ -64,25 +64,25 @@ static int compute_spacing(int is_script, int left, int right)
   if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE)
     return 0;
   if (left == PUNCTUATION_TYPE)
-    return is_script ? 0 : thin_space;
+    return is_script ? 0 : get_param("thin_space");
   if (left == OPENING_TYPE || right == CLOSING_TYPE)
     return 0;
   if (right == BINARY_TYPE || left == BINARY_TYPE)
-    return is_script ? 0 : medium_space;
+    return is_script ? 0 : get_param("medium_space");
   if (right == RELATION_TYPE) {
     if (left == RELATION_TYPE)
       return 0;
     else
-      return is_script ? 0 : thick_space;
+      return is_script ? 0 : get_param("thick_space");
   }
   if (left == RELATION_TYPE)
-    return is_script ? 0 : thick_space;
+    return is_script ? 0 : get_param("thick_space");
   if (right == OPERATOR_TYPE)
-    return thin_space;
+    return get_param("thin_space");
   if (left == INNER_TYPE || right == INNER_TYPE)
-    return is_script ? 0 : thin_space;
+    return is_script ? 0 : get_param("thin_space");
   if (left == OPERATOR_TYPE && right == ORDINARY_TYPE)
-    return thin_space;
+    return get_param("thin_space");
   return 0;
 }

diff --git a/src/preproc/eqn/main.cpp b/src/preproc/eqn/main.cpp
index 19c8b29a5..75300e102 100644
--- a/src/preproc/eqn/main.cpp
+++ b/src/preproc/eqn/main.cpp
@@ -424,6 +424,8 @@ int main(int argc, char **argv)
     }
   init_table(device);
   init_char_table();
+  init_param_table();
+  std::atexit(free_param_table);
   printf(".do if !dEQ .ds EQ\n"
         ".do if !dEN .ds EN\n");
   if (output_format == troff) {
diff --git a/src/preproc/eqn/other.cpp b/src/preproc/eqn/other.cpp
index c7e95cb5d..d40c97713 100644
--- a/src/preproc/eqn/other.cpp
+++ b/src/preproc/eqn/other.cpp
@@ -60,7 +60,7 @@ int accent_box::compute_metrics(int style)
   printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
   printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
-        uid, p->uid, x_height);
+        uid, p->uid, get_param("x_height"));
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
         SUP_RAISE_FORMAT "]\n",
         uid, ab->uid, uid);
@@ -109,7 +109,7 @@ int accent_box::compute_metrics(int style)
         uid, p->uid, ab->uid, p->uid, uid);
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
   printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
-        uid, p->uid, x_height);
+        uid, p->uid, get_param("x_height"));
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
         SUP_RAISE_FORMAT "]\n",
         uid, ab->uid, uid);
@@ -174,10 +174,12 @@ overline_char_box::overline_char_box()
 void overline_char_box::output()
 {
   if (output_format == troff) {
-    printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height);
+    printf("\\v'-%dM/2u-%dM'", 7 * get_param("default_rule_thickness"),
+          get_param("x_height"));
     printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
-          accent_width);
-    printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height);
+          get_param("accent_width"));
+    printf("\\v'%dM/2u+%dM'", 7 * get_param("default_rule_thickness"),
+          get_param("x_height"));
   }
   else if (output_format == mathml)
     printf("<mo>&macr;</mo>");
@@ -213,7 +215,7 @@ int overline_box::compute_metrics(int style)
   int r = p->compute_metrics(cramped_style(style));
   // 9
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n",
-        uid, p->uid, default_rule_thickness*5);
+        uid, p->uid, get_param("default_rule_thickness") * 5);
   printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
   return r;
@@ -225,7 +227,7 @@ void overline_box::output()
     // 9
     printf("\\Z" DELIMITER_CHAR);
     printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'",
-          p->uid, 7*default_rule_thickness);
+          p->uid, 7 * get_param("default_rule_thickness"));
     if (draw_flag)
       printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
     else
@@ -354,10 +356,10 @@ underline_char_box::underline_char_box()
 void underline_char_box::output()
 {
   if (output_format == troff) {
-    printf("\\v'%dM/2u'", 7*default_rule_thickness);
+    printf("\\v'%dM/2u'", 7 * get_param("default_rule_thickness"));
     printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
-          accent_width);
-    printf("\\v'-%dM/2u'", 7*default_rule_thickness);
+          get_param("accent_width"));
+    printf("\\v'-%dM/2u'", 7 * get_param("default_rule_thickness"));
   }
   else if (output_format == mathml)
     printf("<mo>&lowbar;</mo>");
@@ -395,7 +397,7 @@ int underline_box::compute_metrics(int style)
   int r = p->compute_metrics(style);
   // 10
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
-        uid, p->uid, default_rule_thickness*5);
+        uid, p->uid, get_param("default_rule_thickness") * 5);
   printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
   return r;
@@ -407,7 +409,7 @@ void underline_box::output()
     // 10
     printf("\\Z" DELIMITER_CHAR);
     printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'",
-          p->uid, 7*default_rule_thickness);
+          p->uid, 7 * get_param("default_rule_thickness"));
     if (draw_flag)
       printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
     else
@@ -553,7 +555,7 @@ int fat_box::compute_metrics(int style)
 {
   int r = p->compute_metrics(style);
   printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
-        uid, p->uid, fat_offset);
+        uid, p->uid, get_param("fat_offset"));
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
   return r;
@@ -564,7 +566,7 @@ void fat_box::output()
   if (output_format == troff) {
     p->output();
     printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid);
-    printf("\\h'%dM'", fat_offset);
+    printf("\\h'%dM'", get_param("fat_offset"));
     p->output();
   }
   else if (output_format == mathml) {
@@ -678,7 +680,7 @@ int vcenter_box::compute_metrics(int style)
   printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
   printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
         HEIGHT_FORMAT "]/2+%dM\n",
-        uid, p->uid, p->uid, axis_height);
+        uid, p->uid, p->uid, get_param("axis_height"));
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
         SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
diff --git a/src/preproc/eqn/over.cpp b/src/preproc/eqn/over.cpp
index 8a5729a3c..76eeaff3d 100644
--- a/src/preproc/eqn/over.cpp
+++ b/src/preproc/eqn/over.cpp
@@ -76,27 +76,31 @@ int over_box::compute_metrics(int style)
   }
   if (reduce_size)
     printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
-  printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
+  printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
         uid, num->uid, den->uid);
   // allow for \(ru being wider than both the numerator and denominator
   if (!draw_flag)
     fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
-  printf(")+%dM\n", null_delimiter_space*2 + over_hang*2);
+  printf(")+%dM\n", get_param("null_delimiter_space") * 2
+         + get_param("over_hang") * 2);
   // 15b
   printf(".nr " SUP_RAISE_FORMAT " %dM\n",
-        uid, (reduce_size ? num2 : num1));
+        uid, (reduce_size ? get_param("num2") : get_param("num1")));
   printf(".nr " SUB_LOWER_FORMAT " %dM\n",
-        uid, (reduce_size ? denom2 : denom1));
+        uid, (reduce_size ? get_param("denom2")
+                          : get_param("denom1")));

   // 15d
   printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
         "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
-        uid, num->uid, uid, axis_height, default_rule_thickness,
-        default_rule_thickness*(reduce_size ? 1 : 3));
+        uid, num->uid, uid, get_param("axis_height"),
+        get_param("default_rule_thickness"),
+        get_param("default_rule_thickness") * (reduce_size ? 1 : 3));
   printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
         "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
-        uid, den->uid, uid, axis_height, default_rule_thickness,
-        default_rule_thickness*(reduce_size ? 1 : 3));
+        uid, den->uid, uid, get_param("axis_height"),
+        get_param("default_rule_thickness"),
+        get_param("default_rule_thickness") * (reduce_size ? 1 : 3));


   printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
@@ -166,14 +170,14 @@ void over_box::output()
     if (reduce_size)
       printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
     // draw the line
-    printf("\\h'%dM'", null_delimiter_space);
-    printf("\\v'-%dM'", axis_height);
+    printf("\\h'%dM'", get_param("null_delimiter_space"));
+    printf("\\v'-%dM'", get_param("axis_height"));
     fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
     printf("\\n[" WIDTH_FORMAT "]u-%dM",
-          uid, 2*null_delimiter_space);
+          uid, 2 * get_param("null_delimiter_space"));
     fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
-    printf("\\v'%dM'", axis_height);
-    printf("\\h'%dM'", null_delimiter_space);
+    printf("\\v'%dM'", get_param("axis_height"));
+    printf("\\h'%dM'", get_param("null_delimiter_space"));
   }
   else if (output_format == mathml) {
     // FIXME: passing a displaystyle attribute doesn't validate.
diff --git a/src/preproc/eqn/pbox.h b/src/preproc/eqn/pbox.h
index e4cd88e29..c4d55cb21 100644
--- a/src/preproc/eqn/pbox.h
+++ b/src/preproc/eqn/pbox.h
@@ -16,48 +16,6 @@ for more details.
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>. */

-extern int fat_offset;
-
-extern int over_hang;
-extern int accent_width;
-
-extern int delimiter_factor;
-extern int delimiter_shortfall;
-
-extern int null_delimiter_space;
-extern int script_space;
-extern int thin_space;
-extern int medium_space;
-extern int thick_space;
-extern int half_space;
-extern int full_space;
-
-extern int num1;
-extern int num2;
-// we don't use num3, because we don't have \atop
-extern int denom1;
-extern int denom2;
-extern int axis_height;
-extern int sup1;
-extern int sup2;
-extern int sup3;
-extern int default_rule_thickness;
-extern int sub1;
-extern int sub2;
-extern int sup_drop;
-extern int sub_drop;
-extern int x_height;
-extern int big_op_spacing1;
-extern int big_op_spacing2;
-extern int big_op_spacing3;
-extern int big_op_spacing4;
-extern int big_op_spacing5;
-
-extern int baseline_sep;
-extern int shift_down;
-extern int column_sep;
-extern int matrix_side_sep;
-
 // ms.eqn relies on this!

 #define LINE_STRING "10"
diff --git a/src/preproc/eqn/pile.cpp b/src/preproc/eqn/pile.cpp
index 5ce8ee9eb..1829d7cc4 100644
--- a/src/preproc/eqn/pile.cpp
+++ b/src/preproc/eqn/pile.cpp
@@ -36,16 +36,18 @@ int pile_box::compute_metrics(int style)
     printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
   printf("\n");
   printf(".nr " BASELINE_SEP_FORMAT " %dM",
-        uid, baseline_sep+col.space);
+        uid, get_param("baseline_sep") + col.space);
   for (i = 1; i < col.len; i++)
     printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
-          col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
+          col.p[i-1]->uid, col.p[i]->uid,
+          get_param("default_rule_thickness") * 5);
   // round it so that it's a multiple of the vertical motion quantum
   printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");

   printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
         "+%dM\n",
-        uid, uid, col.len-1, axis_height - shift_down);
+        uid, uid, col.len-1, get_param("axis_height")
+                             - get_param("shift_down"));
   printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
         HEIGHT_FORMAT "]\n",
         uid, uid, col.p[0]->uid);
@@ -157,21 +159,24 @@ int matrix_box::compute_metrics(int style)
     printf("\n");
   }
   printf(".nr " WIDTH_FORMAT " %dM",
-        uid, column_sep*(len-1)+2*matrix_side_sep);
+        uid, get_param("column_sep") * (len - 1) + 2
+        * get_param("matrix_side_sep"));
   for (i = 0; i < len; i++)
     printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
   printf("\n");
   printf(".nr " BASELINE_SEP_FORMAT " %dM",
-        uid, baseline_sep+space);
+        uid, get_param("baseline_sep") + space);
   for (i = 0; i < len; i++)
     for (j = 1; j < p[i]->len; j++)
       printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
-          p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
+          p[i]->p[j-1]->uid, p[i]->p[j]->uid,
+          get_param("default_rule_thickness") * 5);
   // round it so that it's a multiple of the vertical motion quantum
   printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");
   printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
         "+%dM\n",
-        uid, uid, max_len-1, axis_height - shift_down);
+        uid, uid, max_len-1, get_param("axis_height")
+        - get_param("shift_down"));
   printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
         uid, uid);
   for (i = 0; i < len; i++)
@@ -190,7 +195,7 @@ int matrix_box::compute_metrics(int style)
 void matrix_box::output()
 {
   if (output_format == troff) {
-    printf("\\h'%dM'", matrix_side_sep);
+    printf("\\h'%dM'", get_param("matrix_side_sep"));
     for (int i = 0; i < len; i++) {
       int j;
       printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
@@ -232,9 +237,9 @@ void matrix_box::output()
       printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
       printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
       if (i != len - 1)
-       printf("\\h'%dM'", column_sep);
+       printf("\\h'%dM'", get_param("column_sep"));
     }
-    printf("\\h'%dM'", matrix_side_sep);
+    printf("\\h'%dM'", get_param("matrix_side_sep"));
   }
   else if (output_format == mathml) {
     int n = p[0]->len; // Each column must have the same number of rows in it
diff --git a/src/preproc/eqn/script.cpp b/src/preproc/eqn/script.cpp
index 7bb16a5b9..747e07fe8 100644
--- a/src/preproc/eqn/script.cpp
+++ b/src/preproc/eqn/script.cpp
@@ -88,9 +88,9 @@ int script_box::compute_metrics(int style)
   }
   else {
     printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
-          uid, p->uid, sup_drop);
+          uid, p->uid, get_param("sup_drop"));
     printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
-          uid, p->uid, sub_drop);
+          uid, p->uid, get_param("sub_drop"));
   }
   printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
   if (sup == 0) {
@@ -98,35 +98,37 @@ int script_box::compute_metrics(int style)
     // 18b
     printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
           HEIGHT_FORMAT "]-(%dM*4/5))\n",
-          uid, uid, sub1, sub->uid, x_height);
+          uid, uid, get_param("sub1"), sub->uid,
+          get_param("x_height"));
   }
   else {
     // sup != 0
     // 18c
     int pos;
     if (style == DISPLAY_STYLE)
-      pos = sup1;
+      pos = get_param("sup1");
     else if (style & 1)                // not cramped
-      pos = sup2;
+      pos = get_param("sup2");
     else
-      pos = sup3;
+      pos = get_param("sup3");
     printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
           "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
-          uid, uid, pos, sup->uid, x_height);
+          uid, uid, pos, sup->uid, get_param("x_height"));
     // 18d
     if (sub != 0) {
       printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
-            uid, uid, sub2);
+            uid, uid, get_param("sub2"));
       // 18e
       printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
             SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
             SUB_LOWER_FORMAT "]+(4*%dM)\n",
-            sup->uid, uid, sub->uid, uid, default_rule_thickness);
+            sup->uid, uid, sub->uid, uid,
+            get_param("default_rule_thickness"));
       printf(".if \\n[" TEMP_REG "] \\{");
       printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
       printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
             "]+\\n[" DEPTH_FORMAT "]>?0\n",
-            x_height, uid, sup->uid);
+            get_param("x_height"), uid, sup->uid);
       printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
       printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
       printf(".\\}\n");
@@ -136,12 +138,13 @@ int script_box::compute_metrics(int style)
   if (sub != 0 && sup != 0)
     printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
           WIDTH_FORMAT "])+%dM)>?0\n",
-          sub->uid, p->uid, sup->uid, script_space);
+          sub->uid, p->uid, sup->uid, get_param("script_space"));
   else if (sub != 0)
     printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
-          sub->uid, p->uid, script_space);
+          sub->uid, p->uid, get_param("script_space"));
   else if (sup != 0)
-    printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
+    printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid,
+          get_param("script_space"));
   else
     printf("\n");
   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
diff --git a/src/preproc/eqn/sqrt.cpp b/src/preproc/eqn/sqrt.cpp
index a4ae8d724..bf5c58327 100644
--- a/src/preproc/eqn/sqrt.cpp
+++ b/src/preproc/eqn/sqrt.cpp
@@ -50,8 +50,9 @@ int sqrt_box::compute_metrics(int style)
   int r = p->compute_metrics(cramped_style(style));
   printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
         "]+%dM+(%dM/4)\n",
-        p->uid, p->uid, default_rule_thickness,
-        (style > SCRIPT_STYLE ? x_height : default_rule_thickness));
+        p->uid, p->uid, get_param("default_rule_thickness"),
+        (style > SCRIPT_STYLE ? get_param("x_height")
+                              : get_param("default_rule_thickness")));
   printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
   printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
   printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
@@ -59,7 +60,7 @@ int sqrt_box::compute_metrics(int style)
         " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
         uid);
   printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
-        default_rule_thickness);
+        get_param("default_rule_thickness"));

   printf(".nr " INDEX_REG " 0\n"
         ".de " TEMP_MACRO "\n"
@@ -76,7 +77,7 @@ int sqrt_box::compute_metrics(int style)
         ".el .nr " INDEX_REG " 0-1\n"
         "..\n"
         "." TEMP_MACRO "\n",
-        uid, uid, default_rule_thickness);
+        uid, uid, get_param("default_rule_thickness"));

   printf(".if \\n[" INDEX_REG "]<0 \\{");

@@ -98,14 +99,14 @@ int sqrt_box::compute_metrics(int style)
         ".\\}\n"
         "..\n"
         "." TEMP_MACRO "\n",
-        uid, uid, default_rule_thickness);
-
+        uid, uid, get_param("default_rule_thickness"));
+
   printf(".\\}\\}\n");

   printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
   // set TEMP_REG to the amount by which the radical sign is too big
   printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
-        default_rule_thickness);
+        get_param("default_rule_thickness"));
   // If TEMP_REG is negative, the bottom of the radical sign should
   // be -TEMP_REG above the bottom of p. If it's positive, the bottom
   // of the radical sign should be TEMP_REG/2 below the bottom of p.
@@ -141,7 +142,8 @@ int sqrt_box::compute_metrics(int style)
         ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
         uid, p->uid, uid);
   // put a bit of extra space above the bar
-  printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
+  printf(".nr " HEIGHT_FORMAT " +%dM\n", uid,
+        get_param("default_rule_thickness"));
   printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
   return r;
 }


G. Branden Robinson <gbranden>
Group administrator
Fri 01 Jul 2022 05:37:15 AM UTC, original submission:  

See the griping comment in the following diff to Kernighan & Cherry's "Typesetting Mathematics--User's Guide" (2nd ed.) below.


@@ -428,11 +432,18 @@
 right ]
 .P2
 will make
+.\" Cheat #1: AT&T eqn stacked piles more tightly than GNU eqn.
 .EQ
+set baseline_sep 1v
 A ~=~ left [
 pile { a above b above c } ~~ pile { x above y above z }
 right ]
 .EN
+.\" Reset equation baseline separation to the default, which is not
+.\" documented anywhere and has no syntactical access.  :-/
+.EQ
+set baseline_sep 140
+.EN
 The elements of the pile (there can be as many as you want)
 are centered one above another, at the right height for
 most purposes.


These "set" parameters are GNU extensions.  As far as I can see there is no way within the eqn language to copy their values (say into an eqn macro), and no way to access the compiled-in default once it is changed.  This appears to be because they are stored as (mutable) global symbols in the executable. 

https://git.savannah.gnu.org/cgit/groff.git/tree/src/preproc/eqn/box.cpp

I think all of these parameters are numeric.  If that bears out then I suggest supporting a special syntax, like


set baseline_sep @


or some other punctuation symbol to recover the default.

G. Branden Robinson <gbranden>
Group administrator

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by gbranden (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2023-08-28 gbranden StatusIn Progress Fixed
        Open/ClosedOpen Closed
        Planned ReleaseNone 1.24.0
    2023-08-25 gbranden StatusNone In Progress
        Assigned toNone gbranden
    2022-07-01 gbranden Summary[eqn] want a way to recover &quot;set&quot; parameteric defaults. [eqn] want a way to recover "set" parameteric defaults

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code