=================================================================== RCS file: /cvs/docbook2mdoc/parse.c,v retrieving revision 1.15 retrieving revision 1.19 diff -u -p -r1.15 -r1.19 --- docbook2mdoc/parse.c 2019/04/06 13:45:58 1.15 +++ docbook2mdoc/parse.c 2019/04/07 17:39:26 1.19 @@ -1,4 +1,4 @@ -/* $Id: parse.c,v 1.15 2019/04/06 13:45:58 schwarze Exp $ */ +/* $Id: parse.c,v 1.19 2019/04/07 17:39:26 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * Copyright (c) 2019 Ingo Schwarze @@ -52,6 +52,7 @@ struct parse { int nline; /* Line number of next token. */ int ncol; /* Column number of next token. */ int del; /* Levels of nested nodes being deleted. */ + int spc; /* Whitespace before the next element. */ int attr; /* The most recent attribute is valid. */ int warn; }; @@ -189,7 +190,7 @@ static const struct element elements[] = { { "title", NODE_TITLE }, { "trademark", NODE_IGNORE }, { "type", NODE_TYPE }, - { "ulink", NODE_ULINK }, + { "ulink", NODE_LINK }, { "userinput", NODE_LITERAL }, { "variablelist", NODE_VARIABLELIST }, { "varlistentry", NODE_VARLISTENTRY }, @@ -294,6 +295,7 @@ static void xml_char(struct parse *ps, const char *p, int sz) { struct pnode *dat; + size_t newsz; if (ps->del > 0) return; @@ -309,6 +311,7 @@ xml_char(struct parse *ps, const char *p, int sz) exit(1); } dat->node = NODE_TEXT; + dat->spc = ps->spc; dat->parent = ps->cur; TAILQ_INIT(&dat->childq); TAILQ_INIT(&dat->attrq); @@ -323,24 +326,35 @@ xml_char(struct parse *ps, const char *p, int sz) /* Append to the current text node. */ assert(sz >= 0); - ps->cur->b = realloc(ps->cur->b, ps->cur->bsz + sz + 1); + newsz = ps->cur->bsz + (ps->cur->bsz && ps->spc) + sz; + ps->cur->b = realloc(ps->cur->b, newsz + 1); if (ps->cur->b == NULL) { perror(NULL); exit(1); } + if (ps->cur->bsz && ps->spc) + ps->cur->b[ps->cur->bsz++] = ' '; memcpy(ps->cur->b + ps->cur->bsz, p, sz); - ps->cur->bsz += sz; - ps->cur->b[ps->cur->bsz] = '\0'; + ps->cur->b[ps->cur->bsz = newsz] = '\0'; ps->cur->real = ps->cur->b; + ps->spc = 0; } +/* + * Close out the text node and strip trailing whitespace, if one is open. + */ static void -pnode_trim(struct pnode *pn) +pnode_closetext(struct parse *p) { - assert(pn->node == NODE_TEXT); - for (; pn->bsz > 0; pn->b[--pn->bsz] = '\0') - if (isspace((unsigned char)pn->b[pn->bsz - 1]) == 0) - break; + struct pnode *n; + + if ((n = p->cur) == NULL || n->node != NODE_TEXT) + return; + p->cur = n->parent; + while (n->bsz > 0 && isspace((unsigned char)n->b[n->bsz - 1])) { + n->b[--n->bsz] = '\0'; + p->spc = 1; + } } static void @@ -357,11 +371,7 @@ xml_entity(struct parse *p, const char *name) return; } - /* Close out the text node, if there is one. */ - if (p->cur->node == NODE_TEXT) { - pnode_trim(p->cur); - p->cur = p->cur->parent; - } + pnode_closetext(p); if (p->tree->flags & TREE_CLOSED && p->cur == p->tree->root) warn_msg(p, "entity after end of document: &%s;", name); @@ -383,10 +393,12 @@ xml_entity(struct parse *p, const char *name) } dat->node = NODE_ESCAPE; dat->bsz = strlen(dat->b); + dat->spc = p->spc; dat->parent = p->cur; TAILQ_INIT(&dat->childq); TAILQ_INIT(&dat->attrq); TAILQ_INSERT_TAIL(&p->cur->childq, dat, child); + p->spc = 0; } /* @@ -410,11 +422,7 @@ xml_elem_start(struct parse *ps, const char *name) return; } - /* Close out the text node, if there is one. */ - if (ps->cur != NULL && ps->cur->node == NODE_TEXT) { - pnode_trim(ps->cur); - ps->cur = ps->cur->parent; - } + pnode_closetext(ps); for (elem = elements; elem->name != NULL; elem++) if (strcmp(elem->name, name) == 0) @@ -448,7 +456,50 @@ xml_elem_start(struct parse *ps, const char *name) perror(NULL); exit(1); } - dat->node = elem->node; + + /* + * Nodes that begin a new macro or request line or start by + * printing text always want whitespace before themselves. + */ + + switch (dat->node = elem->node) { + case NODE_AUTHORGROUP: + case NODE_BOOKINFO: + case NODE_CAUTION: + case NODE_EDITOR: + case NODE_ENTRY: + case NODE_FUNCDEF: + case NODE_FUNCPROTOTYPE: + case NODE_INFORMALEQUATION: + case NODE_INLINEEQUATION: + case NODE_ITEMIZEDLIST: + case NODE_LEGALNOTICE: + case NODE_LITERALLAYOUT: + case NODE_NOTE: + case NODE_ORDEREDLIST: + case NODE_PARA: + case NODE_PREFACE: + case NODE_PROGRAMLISTING: + case NODE_REFMETA: + case NODE_REFNAMEDIV: + case NODE_REFSYNOPSISDIV: + case NODE_ROW: + case NODE_SBR: + case NODE_SCREEN: + case NODE_SECTION: + case NODE_SYNOPSIS: + case NODE_TGROUP: + case NODE_TIP: + case NODE_TITLE: + case NODE_VARIABLELIST: + case NODE_VARLISTENTRY: + case NODE_WARNING: + dat->spc = 1; + break; + default: + dat->spc = ps->spc; + break; + } dat->parent = ps->cur; TAILQ_INIT(&dat->childq); TAILQ_INIT(&dat->attrq); @@ -467,7 +518,7 @@ xml_attrkey(struct parse *ps, const char *name) struct pattr *attr; enum attrkey key; - if (ps->del > 0 || *name == '\0') + if (ps->del > 0 || ps->ncur == NODE_IGNORE || *name == '\0') return; if ((key = attrkey_parse(name)) == ATTRKEY__MAX) { ps->attr = 0; @@ -489,7 +540,7 @@ xml_attrval(struct parse *ps, const char *name) { struct pattr *attr; - if (ps->del > 0 || ps->attr == 0) + if (ps->del > 0 || ps->ncur == NODE_IGNORE || ps->attr == 0) return; if ((attr = TAILQ_LAST(&ps->cur->attrq, pattrq)) == NULL) return; @@ -519,11 +570,8 @@ xml_elem_end(struct parse *ps, const char *name) return; } - /* Close out the text node, if there is one. */ - if (ps->del == 0 && ps->cur != NULL && ps->cur->node == NODE_TEXT) { - pnode_trim(ps->cur); - ps->cur = ps->cur->parent; - } + if (ps->del == 0) + pnode_closetext(ps); if (name != NULL) { for (elem = elements; elem->name != NULL; elem++) @@ -558,6 +606,7 @@ xml_elem_end(struct parse *ps, const char *name) ps->tree->flags |= TREE_CLOSED; else ps->cur = ps->cur->parent; + ps->spc = 0; break; } assert(ps->del == 0); @@ -651,6 +700,7 @@ parse_string(struct parse *p, char *b, size_t rlen, size_t pend; /* Offset of the end of the current word. */ int elem_end; + p->spc = 0; pend = 0; for (;;) { @@ -663,6 +713,7 @@ parse_string(struct parse *p, char *b, size_t rlen, if ((poff = pend) == rlen) break; if (isspace((unsigned char)b[pend])) { + p->spc = 1; increment(p, b, &pend, refill); continue; } @@ -836,10 +887,7 @@ parse_file(struct parse *p, int fd, const char *fname) perror(fname); p->tree->flags |= TREE_FAIL; } - if (p->cur != NULL && p->cur->node == NODE_TEXT) { - pnode_trim(p->cur); - p->cur = p->cur->parent; - } + pnode_closetext(p); if ((p->tree->flags & TREE_CLOSED) == 0) warn_msg(p, "document not closed"); return p->tree;