From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from scc-mailout-kit-01.scc.kit.edu (scc-mailout-kit-01.scc.kit.edu [129.13.231.81]) by fantadrom.bsd.lv (OpenSMTPD) with ESMTP id 6ddd710f for ; Thu, 28 Mar 2019 15:53:50 -0500 (EST) Received: from asta-nat.asta.uni-karlsruhe.de ([172.22.63.82] helo=hekate.usta.de) by scc-mailout-kit-01.scc.kit.edu with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (envelope-from ) id 1h9c20-0005Qx-Bo; Thu, 28 Mar 2019 21:53:49 +0100 Received: from donnerwolke.usta.de ([172.24.96.3]) by hekate.usta.de with esmtp (Exim 4.77) (envelope-from ) id 1h9c1z-0002RP-HP; Thu, 28 Mar 2019 21:53:47 +0100 Received: from athene.usta.de ([172.24.96.10]) by donnerwolke.usta.de with esmtp (Exim 4.84_2) (envelope-from ) id 1h9c1z-0004th-CO; Thu, 28 Mar 2019 21:53:47 +0100 Received: from localhost (athene.usta.de [local]) by athene.usta.de (OpenSMTPD) with ESMTPA id 1591ca88; Thu, 28 Mar 2019 21:53:47 +0100 (CET) Date: Thu, 28 Mar 2019 21:53:47 +0100 From: Ingo Schwarze To: Stephen Gregoratto Cc: tech@mandoc.bsd.lv Subject: Re: [PATCH docbook2mdoc] Add NODE_CONTRIB, NODE_PRODUCTNAME Message-ID: <20190328205347.GC48147@athene.usta.de> References: <20190327035224.7eyuctlnbt67pu5r@BlackBox> <20190328171956.GB48147@athene.usta.de> X-Mailinglist: mandoc-tech Reply-To: tech@mandoc.bsd.lv MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20190328171956.GB48147@athene.usta.de> User-Agent: Mutt/1.8.0 (2017-02-23) Hi Stephen, Ingo Schwarze wrote on Thu, Mar 28, 2019 at 06:19:56PM +0100: > Stephen Gregoratto wrote on Wed, Mar 27, 2019 at 02:52:24PM +1100: >> >> Developer >> Matthias >> Clasen >> > Right, handling properly is a challenge that is on my TODO > list. There are three things to do that i'm aware of: (1) in normal > text, stop skipping children like ; Done. > (2) below , , and the like, > move the information down to the AUTHORS section > (a slightly tricky task); Still open. > (3) handle . Implemented with the patch below. Part of the decision to do it right away was for your benefit, such that you can see a practical example up to date with the latest parser and formatter infrastructure how such formatters are written nowadays. Here is an example of how it works: $ cat regress/author/contrib.xml initial text OpenBSD Theo de Raadt project founder developer final text $ ./docbook2mdoc regress/author/contrib.xml .Dd $Mdocdate$ .Dt UNKNOWN 1 .Os initial text project founder, developer: .An Theo de Raadt , OpenBSD final text Yours, Ingo Log Message: ----------- Implement a formatter for elements, handling , , , , , as well as arbitrary children properly. This required minor work on the formatting infrastructure: Improve macro_addnode() such that it also handles text nodes. Add a companion function print_textnode(). Let print_text() optionally work without ARG_SPACE. Triggered by a report from Stephen Gregoratto that and how GTK documentation uses . Modified Files: -------------- docbook2mdoc: docbook2mdoc.c macro.c macro.h node.h parse.c Revision Data ------------- Index: node.h =================================================================== RCS file: /home/cvs/mdocml/docbook2mdoc/node.h,v retrieving revision 1.5 retrieving revision 1.6 diff -Lnode.h -Lnode.h -u -p -r1.5 -r1.6 --- node.h +++ node.h @@ -46,6 +46,7 @@ enum nodeid { NODE_COLSPEC, NODE_COMMAND, NODE_CONSTANT, + NODE_CONTRIB, NODE_COPYRIGHT, NODE_DATE, NODE_EDITOR, Index: macro.h =================================================================== RCS file: /home/cvs/mdocml/docbook2mdoc/macro.h,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacro.h -Lmacro.h -u -p -r1.1 -r1.2 --- macro.h +++ macro.h @@ -46,3 +46,6 @@ void macro_addarg(struct format *, cons void macro_argline(struct format *, const char *, const char *); void macro_addnode(struct format *, struct pnode *, int); void macro_nodeline(struct format *, const char *, struct pnode *, int); + +void print_text(struct format *, const char *, int); +void print_textnode(struct format *, struct pnode *); Index: docbook2mdoc.c =================================================================== RCS file: /home/cvs/mdocml/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.77 retrieving revision 1.78 diff -Ldocbook2mdoc.c -Ldocbook2mdoc.c -u -p -r1.77 -r1.78 --- docbook2mdoc.c +++ docbook2mdoc.c @@ -32,23 +32,6 @@ static void pnode_print(struct format * static void -print_text(struct format *p, const char *word) -{ - switch (p->linestate) { - case LINE_NEW: - break; - case LINE_TEXT: - putchar(' '); - break; - case LINE_MACRO: - macro_close(p); - break; - } - fputs(word, stdout); - p->linestate = LINE_TEXT; -} - -static void pnode_printpara(struct format *p, struct pnode *pn) { struct pnode *pp; @@ -407,6 +390,66 @@ pnode_printgroup(struct format *p, struc } static void +pnode_printauthor(struct format *f, struct pnode *n) +{ + struct pnode *nc, *ncn; + int have_contrib, have_name; + + /* + * Print children up front, before the .An scope, + * and figure out whether we a name of a person. + */ + + have_contrib = have_name = 0; + TAILQ_FOREACH_SAFE(nc, &n->childq, child, ncn) { + switch (nc->node) { + case NODE_CONTRIB: + if (have_contrib) + print_text(f, ",", 0); + print_textnode(f, nc); + pnode_unlink(nc); + have_contrib = 1; + break; + case NODE_PERSONNAME: + have_name = 1; + break; + default: + break; + } + } + if (TAILQ_FIRST(&n->childq) == NULL) + return; + + if (have_contrib) + print_text(f, ":", 0); + + /* + * If we have a name, print it in the .An scope and leave + * all other content for child handlers, to print after the + * scope. Otherwise, print everything in the scope. + */ + + macro_open(f, "An"); + TAILQ_FOREACH_SAFE(nc, &n->childq, child, ncn) { + if (nc->node == NODE_PERSONNAME || have_name == 0) { + macro_addnode(f, nc, ARG_SPACE); + pnode_unlink(nc); + } + } + + /* + * If there are still unprinted children, end the scope + * with a comma. Otherwise, leave the scope open in case + * a text node follows that starts with closing punctuation. + */ + + if (TAILQ_FIRST(&n->childq) != NULL) { + macro_addarg(f, ",", ARG_SPACE); + macro_close(f); + } +} + +static void pnode_printprologue(struct format *p, struct ptree *tree) { struct pnode *refmeta; @@ -428,7 +471,7 @@ pnode_printprologue(struct format *p, st if (tree->flags & TREE_EQN) { macro_line(p, "EQ"); - print_text(p, "delim $$"); + print_text(p, "delim $$", 0); macro_line(p, "EN"); } } @@ -563,7 +606,7 @@ pnode_print(struct format *p, struct pno pnode_printarg(p, pn); break; case NODE_AUTHOR: - macro_open(p, "An"); + pnode_printauthor(p, pn); break; case NODE_AUTHORGROUP: macro_line(p, "An -split"); @@ -587,7 +630,7 @@ pnode_print(struct format *p, struct pno macro_open(p, "Dv"); break; case NODE_EDITOR: - print_text(p, "editor:"); + print_text(p, "editor:", ARG_SPACE); macro_open(p, "An"); break; case NODE_EMAIL: Index: macro.c =================================================================== RCS file: /home/cvs/mdocml/docbook2mdoc/macro.c,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacro.c -Lmacro.c -u -p -r1.1 -r1.2 --- macro.c +++ macro.c @@ -157,13 +157,13 @@ macro_addnode(struct format *f, struct p assert(f->linestate == LINE_MACRO); /* - * If the only child is a text node, just add that text, - * letting macro_addarg() decide about quoting. + * If this node or its only child is a text node, just add + * that text, letting macro_addarg() decide about quoting. */ - pn = TAILQ_FIRST(&pn->childq); - if (pn != NULL && pn->node == NODE_TEXT && - TAILQ_NEXT(pn, child) == NULL) { + if (pn->node == NODE_TEXT || + ((pn = TAILQ_FIRST(&pn->childq)) != NULL && + pn->node == NODE_TEXT && TAILQ_NEXT(pn, child) == NULL)) { macro_addarg(f, pn->b, flags); return; } @@ -193,10 +193,7 @@ macro_addnode(struct format *f, struct p */ while (pn != NULL) { - if (pn->node == NODE_TEXT) - macro_addarg(f, pn->b, flags); - else - macro_addnode(f, pn, flags); + macro_addnode(f, pn, flags); pn = TAILQ_NEXT(pn, child); flags |= ARG_SPACE; } @@ -210,4 +207,41 @@ macro_nodeline(struct format *f, const c macro_open(f, name); macro_addnode(f, pn, ARG_SPACE | flags); macro_close(f); +} + + +/* + * Print a word on the current text line if one is open, or on a new text + * line otherwise. The flag ARG_SPACE inserts spaces between words. + */ +void +print_text(struct format *f, const char *word, int flags) { + switch (f->linestate) { + case LINE_NEW: + break; + case LINE_TEXT: + if (flags & ARG_SPACE) + putchar(' '); + break; + case LINE_MACRO: + macro_close(f); + break; + } + fputs(word, stdout); + f->linestate = LINE_TEXT; +} + +/* + * Recursively print the content of a node on a text line. + */ +void +print_textnode(struct format *f, struct pnode *n) +{ + struct pnode *nc; + + if (n->node == NODE_TEXT) + print_text(f, n->b, ARG_SPACE); + else + TAILQ_FOREACH(nc, &n->childq, child) + print_textnode(f, nc); } Index: parse.c =================================================================== RCS file: /home/cvs/mdocml/docbook2mdoc/parse.c,v retrieving revision 1.6 retrieving revision 1.7 diff -Lparse.c -Lparse.c -u -p -r1.6 -r1.7 --- parse.c +++ parse.c @@ -73,6 +73,7 @@ static const struct element elements[] = { "colspec", NODE_COLSPEC }, { "command", NODE_COMMAND }, { "constant", NODE_CONSTANT }, + { "contrib", NODE_CONTRIB }, { "copyright", NODE_COPYRIGHT }, { "date", NODE_DATE }, { "editor", NODE_EDITOR }, @@ -82,7 +83,7 @@ static const struct element elements[] = { "envar", NODE_ENVAR }, { "fieldsynopsis", NODE_FIELDSYNOPSIS }, { "filename", NODE_FILENAME }, - { "firstname", NODE_IGNORE }, + { "firstname", NODE_PERSONNAME }, { "firstterm", NODE_FIRSTTERM }, { "footnote", NODE_FOOTNOTE }, { "funcdef", NODE_FUNCDEF }, @@ -122,7 +123,7 @@ static const struct element elements[] = { "option", NODE_OPTION }, { "orderedlist", NODE_ORDEREDLIST }, { "orgname", NODE_ORGNAME }, - { "othername", NODE_IGNORE }, + { "othername", NODE_PERSONNAME }, { "para", NODE_PARA }, { "paramdef", NODE_PARAMDEF }, { "parameter", NODE_PARAMETER }, @@ -164,7 +165,7 @@ static const struct element elements[] = { "spanspec", NODE_SPANSPEC }, { "structname", NODE_STRUCTNAME }, { "subtitle", NODE_SUBTITLE }, - { "surname", NODE_IGNORE }, + { "surname", NODE_PERSONNAME }, { "synopsis", NODE_SYNOPSIS }, { "table", NODE_TABLE }, { "tbody", NODE_TBODY }, -- To unsubscribe send an email to tech+unsubscribe@mandoc.bsd.lv