=================================================================== RCS file: /cvs/docbook2mdoc/macro.c,v retrieving revision 1.1 retrieving revision 1.9 diff -u -p -r1.1 -r1.9 --- docbook2mdoc/macro.c 2019/03/26 19:17:29 1.1 +++ docbook2mdoc/macro.c 2019/04/11 04:23:22 1.9 @@ -1,4 +1,4 @@ -/* $Id: macro.c,v 1.1 2019/03/26 19:17:29 schwarze Exp $ */ +/* $Id: macro.c,v 1.9 2019/04/11 04:23:22 schwarze Exp $ */ /* * Copyright (c) 2019 Ingo Schwarze * @@ -17,6 +17,7 @@ #include #include #include +#include #include "node.h" #include "macro.h" @@ -30,55 +31,48 @@ void macro_open(struct format *f, const char *name) { switch (f->linestate) { + case LINE_MACRO: + if (f->flags & FMT_NOSPC) { + fputs(" Ns ", stdout); + break; + } + if (f->flags & (FMT_CHILD | FMT_IMPL)) { + putchar(' '); + break; + } + /* FALLTHROUGH */ case LINE_TEXT: putchar('\n'); /* FALLTHROUGH */ case LINE_NEW: putchar('.'); f->linestate = LINE_MACRO; + f->flags = 0; break; - case LINE_MACRO: - putchar(' '); - break; } fputs(name, stdout); + f->flags &= FMT_IMPL; + f->flags |= FMT_ARG; } void macro_close(struct format *f) { - assert(f->linestate == LINE_MACRO); - putchar('\n'); + if (f->linestate != LINE_NEW) + putchar('\n'); f->linestate = LINE_NEW; + f->flags = 0; } void macro_line(struct format *f, const char *name) { + macro_close(f); macro_open(f, name); macro_close(f); } /* - * If the next node is a text node starting with closing punctuation, - * emit the closing punctuation as a trailing macro argument. - */ -void -macro_closepunct(struct format *f, struct pnode *pn) -{ - if ((pn = TAILQ_NEXT(pn, child)) != NULL && - pn->node == NODE_TEXT && pn->bsz > 0 && - (pn->b[0] == ',' || pn->b[0] == '.') && - (pn->bsz == 1 || isspace((unsigned char)pn->b[1]))) { - putchar(' '); - putchar(pn->b[0]); - pn->b++; - pn->bsz--; - } - macro_close(f); -} - -/* * Print an argument string on a macro line, collapsing whitespace. */ void @@ -150,21 +144,24 @@ macro_argline(struct format *f, const char *name, cons * Recursively append text from the children of a node to a macro line. */ void -macro_addnode(struct format *f, struct pnode *pn, int flags) +macro_addnode(struct format *f, struct pnode *n, int flags) { + struct pnode *nc; int quote_now; 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) { - macro_addarg(f, pn->b, flags); + while ((nc = TAILQ_FIRST(&n->childq)) != NULL && + TAILQ_NEXT(nc, child) == NULL) + n = nc; + + if (n->node == NODE_TEXT || n->node == NODE_ESCAPE) { + macro_addarg(f, n->b, flags); return; } @@ -192,12 +189,9 @@ macro_addnode(struct format *f, struct pnode *pn, int * inserting whitespace between nodes. */ - while (pn != NULL) { - if (pn->node == NODE_TEXT) - macro_addarg(f, pn->b, flags); - else - macro_addnode(f, pn, flags); - pn = TAILQ_NEXT(pn, child); + while (nc != NULL) { + macro_addnode(f, nc, flags); + nc = TAILQ_NEXT(nc, child); flags |= ARG_SPACE; } if (quote_now) @@ -205,9 +199,47 @@ macro_addnode(struct format *f, struct pnode *pn, int } void -macro_nodeline(struct format *f, const char *name, struct pnode *pn, int flags) +macro_nodeline(struct format *f, const char *name, struct pnode *n, int flags) { macro_open(f, name); - macro_addnode(f, pn, ARG_SPACE | flags); + macro_addnode(f, n, 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; + f->flags = 0; +} + +/* + * 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 || n->node == NODE_ESCAPE) + print_text(f, n->b, ARG_SPACE); + else + TAILQ_FOREACH(nc, &n->childq, child) + print_textnode(f, nc); }