gbranden pushed a commit to branch master
in repository groff.
commit 52f93e69dddb39bbfbbf7c43e355538e35b8edab
Author: G. Branden Robinson <[email protected]>
AuthorDate: Thu Mar 20 00:24:05 2025 -0500
[troff]: Implement macro/string/diversion dumper.
...made possible by the 60+ themed commits earlier this month.
* src/roff/troff/input.cpp: Do it. Add inelegant `extern` declaration
roping in `dump_node_list()` function from "node.cpp".
(class macro_header): Replace `json_dump()` member function with
`json_dump_macro()` and `json_dump_diversion()`, since how we dump
depends on what component objects we contain.
(macro::json_dump): Call appropriate aforementioned function;
`json_dump_macro` on macros and strings, `json_dump_diversion` on
diversions.
(macro_header::json_dump_diversion): Call `dump_node_list()` on the
`head` member of this object's `node_list` `struct`.
(macro::json_dump): Rename this...
(macro::json_dump_macro): ...to this. Also use `errprint()` instead
of `fputc()`. Also explicitly compare return values of pointer type
to null pointer literal instead of letting them pun down to Booleans.
(print_macros): Check for arguments. If given any, interpret them as
macro/string/diversion names and dump the contents of each,
JSON-encoded. If not, proceed with previously unconditional behavior.
* doc/groff.texi.in (Debugging) <pm>:
* man/groff.7.man (Request short reference) <pm>:
* man/groff_diff.7.man (Other differences): Document it.
Illustrations:
Here's a string...
$ printf '.ds str \\%%ambi\\%%dextrous\n.pm str\n' \
| build/test-groff -z 2>&1
{"name": "str", "contents": "\u001Eambi\u001Edextrous"}
$ printf '.ds str \\%%ambi\\%%dextrous\n.pm str\n' \
| build/test-groff -z 2>&1 | jq
{
"name": "str",
"contents": "\u001eambi\u001edextrous"
}
...a macro...
$ printf '.de foo\nhello to \\\\$@ from\n.ie t troff\n.el nroff\nand H.\\&
H.\\& Asquith.\n..\n.pm foo\n' | build/test-groff -z 2>&1
{"name": "foo", "contents": "hello to \\$@ from\n.ie t troff\n.el
nroff\nand H.\u0012 H.\u0012 Asquith.\n"}
$ printf '.de foo\nhello to \\\\$@ from\n.ie t troff\n.el nroff\nand H.\\&
H.\\& Asquith.\n..\n.pm foo\n' | build/test-groff -z 2>&1 | jq
{
"name": "foo",
"contents": "hello to \\$@ from\n.ie t troff\n.el nroff\nand H.\u0012
H.\u0012 Asquith.\n"
}
...and (strap yourself in) a diversion.
$ printf '.di foo\nABC.\n.sp\nDEF\n.br\n.di\n.pm foo\n' \
| build/test-groff -z 2>&1
{"name": "foo", "contents": [{"type": "line_start_node", "diversion level":
0, "is_special_node": false}, {"type": "glyph_node", "diversion level": 0,
"is_special_node": false, "character": "A"}, {"type": "glyph_node", "diversion
level": 0, "is_special_node": false, "character": "B"}, {"type": "glyph_node",
"diversion level": 0, "is_special_node": false, "character": "C"}, {"type":
"glyph_node", "diversion level": 0, "is_special_node": false, "character":
"."}, {"type": "vertical_size [...]
$ printf '.di foo\nABC.\n.sp\nDEF\n.br\n.di\n.pm foo\n' \
| build/test-groff -z 2>&1 | jq
{
"name": "foo",
"contents": [
{
"type": "line_start_node",
"diversion level": 0,
"is_special_node": false
},
{
"type": "glyph_node",
"diversion level": 0,
"is_special_node": false,
"character": "A"
},
{
"type": "glyph_node",
"diversion level": 0,
"is_special_node": false,
"character": "B"
},
{
"type": "glyph_node",
"diversion level": 0,
"is_special_node": false,
"character": "C"
},
{
"type": "glyph_node",
"diversion level": 0,
"is_special_node": false,
"character": "."
},
{
"type": "vertical_size_node",
"diversion level": 0,
"is_special_node": false,
"vunits": -12000
},
{
"type": "vertical_size_node",
"diversion level": 0,
"is_special_node": false,
"vunits": 0
},
{
"type": "diverted_space_node",
"diversion level": 0,
"is_special_node": false,
"vunits": 12000
},
{
"type": "line_start_node",
"diversion level": 0,
"is_special_node": false
},
{
"type": "glyph_node",
"diversion level": 0,
"is_special_node": false,
"character": "D"
},
{
"type": "glyph_node",
"diversion level": 0,
"is_special_node": false,
"character": "E"
},
{
"type": "glyph_node",
"diversion level": 0,
"is_special_node": false,
"character": "F"
},
{
"type": "vertical_size_node",
"diversion level": 0,
"is_special_node": false,
"vunits": -12000
},
{
"type": "vertical_size_node",
"diversion level": 0,
"is_special_node": false,
"vunits": 0
}
]
}
---
doc/groff.texi.in | 12 +++++++++-
man/groff.7.man | 9 ++++++++
man/groff_diff.7.man | 3 ++-
src/roff/troff/input.cpp | 57 +++++++++++++++++++++++++++++++++++++-----------
4 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/doc/groff.texi.in b/doc/groff.texi.in
index f9b795dd9..4ff7c88d5 100644
--- a/doc/groff.texi.in
+++ b/doc/groff.texi.in
@@ -17760,11 +17760,21 @@ a pair of empty brackets
represents an empty list.
@endDefreq
-@Defreq {pm, }
+@Defreq {pm, [@Var{name} @r{@dots{}}]}}
+@cindex dumping macros, strings, or diversions (@code{pm})
@cindex dumping symbol table (@code{pm})
@cindex symbol table, dumping (@code{pm})
+@cindex macro, dumping (@code{pm})
+@cindex string, dumping (@code{pm})
+@cindex diversion, dumping (@code{pm})
Report,
to the standard error stream,
+the name and @acronym{JSON}-encoded contents of each macro,
+string,
+or diversion
+@var{name},
+or,
+without arguments,
the names of all defined macros,
strings,
and diversions and their sizes in bytes.
diff --git a/man/groff.7.man b/man/groff.7.man
index a11102f4b..89bd4cf43 100644
--- a/man/groff.7.man
+++ b/man/groff.7.man
@@ -4221,6 +4221,15 @@ strings,
and diversions and their sizes in bytes.
.
.TPx
+.REQ .pm "name \fR\&.\|.\|.\&\fP"
+Report,
+to the standard error stream,
+the name and JSON-encoded contents of each macro,
+string,
+or diversion
+.IR name .
+.
+.TPx
.REQ .pn \[+-]N
Set next page number.
.
diff --git a/man/groff_diff.7.man b/man/groff_diff.7.man
index 78ecab57e..4a1f57fee 100644
--- a/man/groff_diff.7.man
+++ b/man/groff_diff.7.man
@@ -6282,7 +6282,8 @@ units.
.
GNU
.I troff \" GNU
-ignores any arguments and reports the sizes in bytes.
+reports the sizes in bytes if given no arguments,
+and otherwise dumps the contents of each named argument.
.
.
.P
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 0bf7533c5..1b18403ce 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -3552,7 +3552,8 @@ public:
node_list nl;
macro_header() { count = 1; }
macro_header *copy(int);
- void json_dump();
+ void json_dump_macro();
+ void json_dump_diversion();
};
macro::~macro()
@@ -3719,7 +3720,10 @@ void macro::print_size()
void macro::json_dump()
{
if (p != 0 /* nullptr */)
- p->json_dump();
+ if (is_a_diversion)
+ p->json_dump_diversion();
+ else
+ p->json_dump_macro();
else
fputs("\"\"", stderr);
}
@@ -3747,9 +3751,17 @@ macro_header *macro_header::copy(int n)
return p;
}
-void macro_header::json_dump()
+extern void dump_node_list(node *);
+
+void macro_header::json_dump_diversion()
+{
+ dump_node_list(nl.head);
+ fflush(stderr);
+}
+
+void macro_header::json_dump_macro()
{
- fputc('\"', stderr);
+ errprint("\"contents\": \"");
int macro_len = cl.length();
for (int i = 0; i < macro_len; i++) {
json_char jc = json_encode_char(cl.get(i));
@@ -3758,22 +3770,41 @@ void macro_header::json_dump()
for (size_t j = 0; j < jc.len; j++)
fputc(jc.buf[j], stderr);
}
- fputc('\"', stderr);
+ errprint("\"");
fflush(stderr);
}
void print_macros()
{
- object_dictionary_iterator iter(request_dictionary);
request_or_macro *rm;
+ macro *m = 0 /* nullptr */;
symbol s;
- while (iter.get(&s, (object **)&rm)) {
- assert(!s.is_null());
- macro *m = rm->to_macro();
- if (m) {
- errprint("%1\t", s.contents());
- m->print_size();
- errprint("\n");
+ if (has_arg()) {
+ do {
+ s = get_name();
+ rm = static_cast<request_or_macro *>(request_dictionary.lookup(s));
+ if (rm != 0 /* nullptr */)
+ m = rm->to_macro();
+ if (m != 0 /* nullptr */) {
+ errprint("{\"name\": ");
+ s.json_dump();
+ errprint(", ");
+ m->json_dump();
+ errprint("}\n");
+ fflush(stderr);
+ }
+ } while (has_arg());
+ }
+ else {
+ object_dictionary_iterator iter(request_dictionary);
+ while (iter.get(&s, (object **)&rm)) {
+ assert(!s.is_null());
+ m = rm->to_macro();
+ if (m != 0 /* nullptr */) {
+ errprint("%1\t", s.contents());
+ m->print_size();
+ errprint("\n");
+ }
}
}
fflush(stderr);
_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit