=================================================================== RCS file: /cvs/docbook2mdoc/parse.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -p -r1.15 -r1.16 --- docbook2mdoc/parse.c 2019/04/06 13:45:58 1.15 +++ docbook2mdoc/parse.c 2019/04/06 22:37:57 1.16 @@ -1,4 +1,4 @@ -/* $Id: parse.c,v 1.15 2019/04/06 13:45:58 schwarze Exp $ */ +/* $Id: parse.c,v 1.16 2019/04/06 22:37:57 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; }; @@ -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) @@ -449,6 +457,7 @@ xml_elem_start(struct parse *ps, const char *name) exit(1); } dat->node = elem->node; + dat->spc = ps->spc; dat->parent = ps->cur; TAILQ_INIT(&dat->childq); TAILQ_INIT(&dat->attrq); @@ -519,11 +528,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 +564,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 +658,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 +671,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 +845,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;