gbranden pushed a commit to branch master in repository groff. commit 52f93e69dddb39bbfbbf7c43e355538e35b8edab Author: G. Branden Robinson <g.branden.robin...@gmail.com> 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 groff-commit@gnu.org https://lists.gnu.org/mailman/listinfo/groff-commit