version 1.34, 2019/04/12 04:39:24 |
version 1.45, 2019/04/16 14:58:19 |
|
|
int nline; /* Line number of next token. */ |
int nline; /* Line number of next token. */ |
int ncol; /* Column number of next token. */ |
int ncol; /* Column number of next token. */ |
int del; /* Levels of nested nodes being deleted. */ |
int del; /* Levels of nested nodes being deleted. */ |
|
int nofill; /* Levels of open no-fill displays. */ |
int flags; |
int flags; |
#define PFLAG_WARN (1 << 0) /* Print warning messages. */ |
#define PFLAG_WARN (1 << 0) /* Print warning messages. */ |
#define PFLAG_SPC (1 << 1) /* Whitespace before the next element. */ |
#define PFLAG_SPC (1 << 1) /* Whitespace before the next element. */ |
|
|
#define PFLAG_EEND (1 << 3) /* This element is self-closing. */ |
#define PFLAG_EEND (1 << 3) /* This element is self-closing. */ |
}; |
}; |
|
|
struct element { |
struct alias { |
const char *name; /* DocBook element name. */ |
const char *name; /* DocBook element name. */ |
enum nodeid node; /* Node type to generate. */ |
enum nodeid node; /* Node type to generate. */ |
}; |
}; |
|
|
static const struct element elements[] = { |
static const struct alias aliases[] = { |
{ "acronym", NODE_IGNORE }, |
{ "acronym", NODE_IGNORE }, |
{ "affiliation", NODE_AFFILIATION }, |
{ "affiliation", NODE_IGNORE }, |
{ "anchor", NODE_DELETE }, |
{ "anchor", NODE_DELETE }, |
{ "appendix", NODE_APPENDIX }, |
{ "application", NODE_COMMAND }, |
{ "application", NODE_APPLICATION }, |
|
{ "arg", NODE_ARG }, |
|
{ "article", NODE_SECTION }, |
{ "article", NODE_SECTION }, |
{ "author", NODE_AUTHOR }, |
{ "articleinfo", NODE_BOOKINFO }, |
{ "authorgroup", NODE_AUTHORGROUP }, |
|
{ "blockquote", NODE_BLOCKQUOTE }, |
|
{ "book", NODE_SECTION }, |
{ "book", NODE_SECTION }, |
{ "bookinfo", NODE_BOOKINFO }, |
|
{ "caution", NODE_CAUTION }, |
|
{ "chapter", NODE_SECTION }, |
{ "chapter", NODE_SECTION }, |
{ "citerefentry", NODE_CITEREFENTRY }, |
{ "caption", NODE_IGNORE }, |
{ "citetitle", NODE_CITETITLE }, |
|
{ "cmdsynopsis", NODE_CMDSYNOPSIS }, |
|
{ "code", NODE_LITERAL }, |
{ "code", NODE_LITERAL }, |
{ "colspec", NODE_COLSPEC }, |
{ "computeroutput", NODE_LITERAL }, |
{ "command", NODE_COMMAND }, |
|
{ "constant", NODE_CONSTANT }, |
|
{ "contrib", NODE_CONTRIB }, |
|
{ "copyright", NODE_COPYRIGHT }, |
|
{ "date", NODE_DATE }, |
|
{ "!doctype", NODE_DOCTYPE }, |
{ "!doctype", NODE_DOCTYPE }, |
{ "!DOCTYPE", NODE_DOCTYPE }, |
{ "figure", NODE_IGNORE }, |
{ "editor", NODE_EDITOR }, |
|
{ "email", NODE_EMAIL }, |
|
{ "emphasis", NODE_EMPHASIS }, |
|
{ "!ENTITY", NODE_ENTITY }, |
|
{ "entry", NODE_ENTRY }, |
|
{ "envar", NODE_ENVAR }, |
|
{ "errorname", NODE_ERRORNAME }, |
|
{ "fieldsynopsis", NODE_FIELDSYNOPSIS }, |
|
{ "filename", NODE_FILENAME }, |
|
{ "firstname", NODE_PERSONNAME }, |
{ "firstname", NODE_PERSONNAME }, |
{ "firstterm", NODE_FIRSTTERM }, |
|
{ "footnote", NODE_FOOTNOTE }, |
|
{ "funcdef", NODE_FUNCDEF }, |
|
{ "funcprototype", NODE_FUNCPROTOTYPE }, |
|
{ "funcsynopsis", NODE_FUNCSYNOPSIS }, |
|
{ "funcsynopsisinfo", NODE_FUNCSYNOPSISINFO }, |
|
{ "function", NODE_FUNCTION }, |
|
{ "glossary", NODE_VARIABLELIST }, |
{ "glossary", NODE_VARIABLELIST }, |
{ "glossdef", NODE_IGNORE }, |
{ "glossdef", NODE_IGNORE }, |
{ "glossdiv", NODE_IGNORE }, |
{ "glossdiv", NODE_IGNORE }, |
{ "glossentry", NODE_VARLISTENTRY }, |
{ "glossentry", NODE_VARLISTENTRY }, |
{ "glosslist", NODE_VARIABLELIST }, |
{ "glosslist", NODE_VARIABLELIST }, |
{ "glossterm", NODE_GLOSSTERM }, |
{ "holder", NODE_IGNORE }, |
{ "group", NODE_GROUP }, |
{ "imageobject", NODE_IGNORE }, |
{ "holder", NODE_HOLDER }, |
|
{ "index", NODE_INDEX }, |
|
{ "indexterm", NODE_DELETE }, |
{ "indexterm", NODE_DELETE }, |
{ "info", NODE_INFO }, |
|
{ "informalequation", NODE_INFORMALEQUATION }, |
|
{ "informaltable", NODE_TABLE }, |
{ "informaltable", NODE_TABLE }, |
{ "inlineequation", NODE_INLINEEQUATION }, |
{ "keycap", NODE_KEYSYM }, |
{ "itemizedlist", NODE_ITEMIZEDLIST }, |
{ "keycode", NODE_IGNORE }, |
{ "keysym", NODE_KEYSYM }, |
{ "mediaobject", NODE_BLOCKQUOTE }, |
{ "legalnotice", NODE_LEGALNOTICE }, |
{ "orgname", NODE_IGNORE }, |
{ "link", NODE_LINK }, |
{ "othercredit", NODE_AUTHOR }, |
{ "listitem", NODE_LISTITEM }, |
|
{ "literal", NODE_LITERAL }, |
|
{ "literallayout", NODE_LITERALLAYOUT }, |
|
{ "manvolnum", NODE_MANVOLNUM }, |
|
{ "member", NODE_MEMBER }, |
|
{ "mml:math", NODE_MML_MATH }, |
|
{ "mml:mfenced", NODE_MML_MFENCED }, |
|
{ "mml:mfrac", NODE_MML_MFRAC }, |
|
{ "mml:mi", NODE_MML_MI }, |
|
{ "mml:mn", NODE_MML_MN }, |
|
{ "mml:mo", NODE_MML_MO }, |
|
{ "mml:mrow", NODE_MML_MROW }, |
|
{ "mml:msub", NODE_MML_MSUB }, |
|
{ "mml:msup", NODE_MML_MSUP }, |
|
{ "modifier", NODE_MODIFIER }, |
|
{ "note", NODE_NOTE }, |
|
{ "option", NODE_OPTION }, |
|
{ "orderedlist", NODE_ORDEREDLIST }, |
|
{ "orgname", NODE_ORGNAME }, |
|
{ "othername", NODE_PERSONNAME }, |
{ "othername", NODE_PERSONNAME }, |
{ "para", NODE_PARA }, |
|
{ "paramdef", NODE_PARAMDEF }, |
|
{ "parameter", NODE_PARAMETER }, |
|
{ "part", NODE_SECTION }, |
{ "part", NODE_SECTION }, |
{ "personname", NODE_PERSONNAME }, |
|
{ "phrase", NODE_IGNORE }, |
{ "phrase", NODE_IGNORE }, |
{ "preface", NODE_PREFACE }, |
|
{ "primary", NODE_DELETE }, |
{ "primary", NODE_DELETE }, |
{ "programlisting", NODE_PROGRAMLISTING }, |
{ "property", NODE_PARAMETER }, |
{ "prompt", NODE_PROMPT }, |
|
{ "quote", NODE_QUOTE }, |
|
{ "refclass", NODE_REFCLASS }, |
|
{ "refdescriptor", NODE_REFDESCRIPTOR }, |
|
{ "refentry", NODE_REFENTRY }, |
|
{ "refentryinfo", NODE_REFENTRYINFO }, |
|
{ "refentrytitle", NODE_REFENTRYTITLE }, |
|
{ "refmeta", NODE_REFMETA }, |
|
{ "refmetainfo", NODE_REFMETAINFO }, |
|
{ "refmiscinfo", NODE_REFMISCINFO }, |
|
{ "refname", NODE_REFNAME }, |
|
{ "refnamediv", NODE_REFNAMEDIV }, |
|
{ "refpurpose", NODE_REFPURPOSE }, |
|
{ "refsect1", NODE_SECTION }, |
{ "refsect1", NODE_SECTION }, |
{ "refsect2", NODE_SECTION }, |
{ "refsect2", NODE_SECTION }, |
{ "refsect3", NODE_SECTION }, |
{ "refsect3", NODE_SECTION }, |
{ "refsection", NODE_SECTION }, |
{ "refsection", NODE_SECTION }, |
{ "refsynopsisdiv", NODE_REFSYNOPSISDIV }, |
{ "releaseinfo", NODE_IGNORE }, |
{ "releaseinfo", NODE_RELEASEINFO }, |
{ "returnvalue", NODE_IGNORE }, |
{ "replaceable", NODE_REPLACEABLE }, |
|
{ "row", NODE_ROW }, |
|
{ "sbr", NODE_SBR }, |
|
{ "screen", NODE_SCREEN }, |
|
{ "secondary", NODE_DELETE }, |
{ "secondary", NODE_DELETE }, |
{ "sect1", NODE_SECTION }, |
{ "sect1", NODE_SECTION }, |
{ "sect2", NODE_SECTION }, |
{ "sect2", NODE_SECTION }, |
{ "section", NODE_SECTION }, |
{ "sgmltag", NODE_MARKUP }, |
{ "sgmltag", NODE_SGMLTAG }, |
|
{ "simpara", NODE_PARA }, |
{ "simpara", NODE_PARA }, |
{ "simplelist", NODE_SIMPLELIST }, |
|
{ "spanspec", NODE_SPANSPEC }, |
|
{ "structfield", NODE_PARAMETER }, |
{ "structfield", NODE_PARAMETER }, |
{ "structname", NODE_TYPE }, |
{ "structname", NODE_TYPE }, |
{ "subtitle", NODE_SUBTITLE }, |
|
{ "surname", NODE_PERSONNAME }, |
{ "surname", NODE_PERSONNAME }, |
{ "symbol", NODE_CONSTANT }, |
{ "symbol", NODE_CONSTANT }, |
{ "synopsis", NODE_SYNOPSIS }, |
|
{ "table", NODE_TABLE }, |
|
{ "tbody", NODE_TBODY }, |
|
{ "term", NODE_TERM }, |
|
{ "tfoot", NODE_TFOOT }, |
|
{ "tgroup", NODE_TGROUP }, |
|
{ "thead", NODE_THEAD }, |
|
{ "tip", NODE_TIP }, |
|
{ "title", NODE_TITLE }, |
|
{ "trademark", NODE_IGNORE }, |
{ "trademark", NODE_IGNORE }, |
{ "type", NODE_TYPE }, |
|
{ "ulink", NODE_LINK }, |
{ "ulink", NODE_LINK }, |
{ "userinput", NODE_LITERAL }, |
{ "userinput", NODE_LITERAL }, |
{ "variablelist", NODE_VARIABLELIST }, |
{ "year", NODE_IGNORE }, |
{ "varlistentry", NODE_VARLISTENTRY }, |
|
{ "varname", NODE_VARNAME }, |
|
{ "warning", NODE_WARNING }, |
|
{ "wordasword", NODE_WORDASWORD }, |
|
{ "xi:include", NODE_INCLUDE }, |
|
{ "year", NODE_YEAR }, |
|
{ NULL, NODE_IGNORE } |
{ NULL, NODE_IGNORE } |
}; |
}; |
|
|
Line 322 warn_msg(struct parse *p, const char *fmt, ...) |
|
Line 229 warn_msg(struct parse *p, const char *fmt, ...) |
|
* Otherwise, create a new one as a child of the current node. |
* Otherwise, create a new one as a child of the current node. |
*/ |
*/ |
static void |
static void |
xml_char(struct parse *p, const char *word, int sz) |
xml_text(struct parse *p, const char *word, int sz) |
{ |
{ |
struct pnode *n; |
struct pnode *n, *np; |
size_t oldsz, newsz; |
size_t oldsz, newsz; |
|
int i; |
|
|
assert(sz > 0); |
assert(sz > 0); |
if (p->del > 0) |
if (p->del > 0) |
return; |
return; |
|
|
if ((n = p->cur) == NULL) { |
if ((n = p->cur) == NULL) { |
error_msg(p, "discarding text before document: %.*s", sz, word); |
error_msg(p, "discarding text before document: %.*s", |
|
sz, word); |
return; |
return; |
} |
} |
|
|
if (n->node != NODE_TEXT) { |
/* Append to the current text node, if one is open. */ |
if ((n = pnode_alloc(p->cur)) == NULL) |
|
|
if (n->node == NODE_TEXT) { |
|
oldsz = strlen(n->b); |
|
newsz = oldsz + sz; |
|
if (oldsz && (p->flags & PFLAG_SPC)) |
|
newsz++; |
|
if ((n->b = realloc(n->b, newsz + 1)) == NULL) |
fatal(p); |
fatal(p); |
n->node = NODE_TEXT; |
if (oldsz && (p->flags & PFLAG_SPC)) |
n->spc = (p->flags & PFLAG_SPC) != 0; |
n->b[oldsz++] = ' '; |
p->cur = n; |
memcpy(n->b + oldsz, word, sz); |
|
n->b[newsz] = '\0'; |
|
p->flags &= ~PFLAG_SPC; |
|
return; |
} |
} |
|
|
if (p->tree->flags & TREE_CLOSED && n->parent == p->tree->root) |
if (p->tree->flags & TREE_CLOSED && n == p->tree->root) |
warn_msg(p, "text after end of document: %.*s", sz, word); |
warn_msg(p, "text after end of document: %.*s", sz, word); |
|
|
/* Append to the current text node. */ |
/* Create a new text node. */ |
|
|
oldsz = n->b == NULL ? 0 : strlen(n->b); |
if ((n = pnode_alloc(p->cur)) == NULL) |
newsz = oldsz + sz; |
|
if (oldsz && (p->flags & PFLAG_SPC)) |
|
newsz++; |
|
if ((n->b = realloc(n->b, newsz + 1)) == NULL) |
|
fatal(p); |
fatal(p); |
if (oldsz && (p->flags & PFLAG_SPC)) |
n->node = NODE_TEXT; |
n->b[oldsz++] = ' '; |
n->spc = (p->flags & PFLAG_SPC) != 0; |
memcpy(n->b + oldsz, word, sz); |
|
n->b[newsz] = '\0'; |
|
p->flags &= ~PFLAG_SPC; |
p->flags &= ~PFLAG_SPC; |
|
|
|
/* |
|
* If this node follows an in-line macro without intervening |
|
* whitespace, keep the text in it as short as possible, |
|
* and do not keep it open. |
|
*/ |
|
|
|
np = n->spc ? NULL : TAILQ_PREV(n, pnodeq, child); |
|
while (np != NULL) { |
|
switch (pnode_class(np->node)) { |
|
case CLASS_VOID: |
|
case CLASS_TEXT: |
|
case CLASS_BLOCK: |
|
case CLASS_NOFILL: |
|
np = NULL; |
|
break; |
|
case CLASS_TRANS: |
|
np = TAILQ_LAST(&np->childq, pnodeq); |
|
continue; |
|
case CLASS_LINE: |
|
case CLASS_ENCL: |
|
break; |
|
} |
|
break; |
|
} |
|
if (np != NULL) { |
|
i = 0; |
|
while (i < sz && !isspace((unsigned char)word[i])) |
|
i++; |
|
if ((n->b = strndup(word, i)) == NULL) |
|
fatal(p); |
|
if (i == sz) |
|
return; |
|
while (i < sz && isspace((unsigned char)word[i])) |
|
i++; |
|
if (i == sz) { |
|
p->flags |= PFLAG_SPC; |
|
return; |
|
} |
|
|
|
/* Put any remaining text into a second node. */ |
|
|
|
if ((n = pnode_alloc(p->cur)) == NULL) |
|
fatal(p); |
|
n->node = NODE_TEXT; |
|
n->spc = 1; |
|
word += i; |
|
sz -= i; |
|
} |
|
if ((n->b = strndup(word, sz)) == NULL) |
|
fatal(p); |
|
|
|
/* The new node remains open for later pnode_closetext(). */ |
|
|
|
p->cur = n; |
} |
} |
|
|
/* |
/* |
* Close out the text node and strip trailing whitespace, if one is open. |
* Close out the text node and strip trailing whitespace, if one is open. |
*/ |
*/ |
static void |
static void |
pnode_closetext(struct parse *p) |
pnode_closetext(struct parse *p, int check_last_word) |
{ |
{ |
struct pnode *n; |
struct pnode *n; |
char *cp; |
char *cp, *last_word; |
|
|
if ((n = p->cur) == NULL || n->node != NODE_TEXT) |
if ((n = p->cur) == NULL || n->node != NODE_TEXT) |
return; |
return; |
Line 378 pnode_closetext(struct parse *p) |
|
Line 345 pnode_closetext(struct parse *p) |
|
cp > n->b && isspace((unsigned char)cp[-1]); |
cp > n->b && isspace((unsigned char)cp[-1]); |
*--cp = '\0') |
*--cp = '\0') |
p->flags |= PFLAG_SPC; |
p->flags |= PFLAG_SPC; |
|
|
|
if (p->flags & PFLAG_SPC || !check_last_word) |
|
return; |
|
|
|
/* |
|
* Find the beginning of the last word |
|
* and delete whitespace before it. |
|
*/ |
|
|
|
while (cp > n->b && !isspace((unsigned char)cp[-1])) |
|
cp--; |
|
if (cp == n->b) |
|
return; |
|
|
|
last_word = cp; |
|
while (cp > n->b && isspace((unsigned char)cp[-1])) |
|
*--cp = '\0'; |
|
|
|
/* Move the last word into its own node, for use with .Pf. */ |
|
|
|
if ((n = pnode_alloc(p->cur)) == NULL) |
|
fatal(p); |
|
n->node = NODE_TEXT; |
|
n->spc = 1; |
|
if ((n->b = strdup(last_word)) == NULL) |
|
fatal(p); |
} |
} |
|
|
static void |
static void |
Line 397 xml_entity(struct parse *p, const char *name) |
|
Line 390 xml_entity(struct parse *p, const char *name) |
|
return; |
return; |
} |
} |
|
|
pnode_closetext(p); |
pnode_closetext(p, 0); |
|
|
if (p->tree->flags & TREE_CLOSED && p->cur == p->tree->root) |
if (p->tree->flags & TREE_CLOSED && p->cur == p->tree->root) |
warn_msg(p, "entity after end of document: &%s;", name); |
warn_msg(p, "entity after end of document: &%s;", name); |
Line 445 xml_entity(struct parse *p, const char *name) |
|
Line 438 xml_entity(struct parse *p, const char *name) |
|
} |
} |
|
|
/* |
/* |
|
* Parse an element name. |
|
*/ |
|
static enum nodeid |
|
xml_name2node(struct parse *p, const char *name) |
|
{ |
|
const struct alias *alias; |
|
enum nodeid node; |
|
|
|
if ((node = pnode_parse(name)) < NODE_UNKNOWN) |
|
return node; |
|
|
|
for (alias = aliases; alias->name != NULL; alias++) |
|
if (strcmp(alias->name, name) == 0) |
|
return alias->node; |
|
|
|
return NODE_UNKNOWN; |
|
} |
|
|
|
/* |
* Begin an element. |
* Begin an element. |
*/ |
*/ |
static void |
static void |
xml_elem_start(struct parse *p, const char *name) |
xml_elem_start(struct parse *p, const char *name) |
{ |
{ |
const struct element *elem; |
|
struct pnode *n; |
struct pnode *n; |
|
|
/* |
/* |
Line 463 xml_elem_start(struct parse *p, const char *name) |
|
Line 474 xml_elem_start(struct parse *p, const char *name) |
|
return; |
return; |
} |
} |
|
|
pnode_closetext(p); |
switch (p->ncur = xml_name2node(p, name)) { |
|
|
for (elem = elements; elem->name != NULL; elem++) |
|
if (strcmp(elem->name, name) == 0) |
|
break; |
|
|
|
if (elem->name == NULL) { |
|
if (*name == '!' || *name == '?') |
|
return; |
|
error_msg(p, "unknown element <%s>", name); |
|
} |
|
|
|
p->ncur = elem->node; |
|
|
|
switch (p->ncur) { |
|
case NODE_DELETE_WARN: |
case NODE_DELETE_WARN: |
warn_msg(p, "skipping element <%s>", name); |
warn_msg(p, "skipping element <%s>", name); |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
Line 486 xml_elem_start(struct parse *p, const char *name) |
|
Line 483 xml_elem_start(struct parse *p, const char *name) |
|
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
case NODE_IGNORE: |
case NODE_IGNORE: |
return; |
return; |
case NODE_INLINEEQUATION: |
case NODE_UNKNOWN: |
p->tree->flags |= TREE_EQN; |
if (*name != '!' && *name != '?') |
break; |
error_msg(p, "unknown element <%s>", name); |
|
return; |
default: |
default: |
break; |
break; |
} |
} |
Line 496 xml_elem_start(struct parse *p, const char *name) |
|
Line 494 xml_elem_start(struct parse *p, const char *name) |
|
if (p->tree->flags & TREE_CLOSED && p->cur->parent == NULL) |
if (p->tree->flags & TREE_CLOSED && p->cur->parent == NULL) |
warn_msg(p, "element after end of document: <%s>", name); |
warn_msg(p, "element after end of document: <%s>", name); |
|
|
|
switch (pnode_class(p->ncur)) { |
|
case CLASS_LINE: |
|
case CLASS_ENCL: |
|
pnode_closetext(p, 1); |
|
break; |
|
default: |
|
pnode_closetext(p, 0); |
|
break; |
|
} |
|
|
if ((n = pnode_alloc(p->cur)) == NULL) |
if ((n = pnode_alloc(p->cur)) == NULL) |
fatal(p); |
fatal(p); |
|
|
/* |
/* |
|
* Some elements are self-closing. |
* Nodes that begin a new macro or request line or start by |
* Nodes that begin a new macro or request line or start by |
* printing text always want whitespace before themselves. |
* printing text always want whitespace before themselves. |
*/ |
*/ |
|
|
switch (n->node = elem->node) { |
switch (n->node = p->ncur) { |
case NODE_DOCTYPE: |
case NODE_DOCTYPE: |
case NODE_ENTITY: |
case NODE_ENTITY: |
case NODE_SBR: |
case NODE_SBR: |
p->flags |= PFLAG_EEND; |
p->flags |= PFLAG_EEND; |
/* FALLTHROUGH */ |
|
case NODE_APPENDIX: |
|
case NODE_AUTHORGROUP: |
|
case NODE_BLOCKQUOTE: |
|
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_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: |
|
n->spc = 1; |
|
break; |
break; |
default: |
default: |
|
break; |
|
} |
|
switch (pnode_class(p->ncur)) { |
|
case CLASS_LINE: |
|
case CLASS_ENCL: |
n->spc = (p->flags & PFLAG_SPC) != 0; |
n->spc = (p->flags & PFLAG_SPC) != 0; |
break; |
break; |
|
case CLASS_NOFILL: |
|
p->nofill++; |
|
/* FALLTHROUGH */ |
|
default: |
|
n->spc = 1; |
|
break; |
} |
} |
p->cur = n; |
p->cur = n; |
if (n->node == NODE_DOCTYPE) { |
if (n->node == NODE_DOCTYPE) { |
Line 620 xml_attrval(struct parse *p, const char *name) |
|
Line 606 xml_attrval(struct parse *p, const char *name) |
|
static void |
static void |
xml_elem_end(struct parse *p, const char *name) |
xml_elem_end(struct parse *p, const char *name) |
{ |
{ |
const struct element *elem; |
|
struct pnode *n; |
struct pnode *n; |
const char *cp; |
const char *cp; |
enum nodeid node; |
enum nodeid node; |
Line 635 xml_elem_end(struct parse *p, const char *name) |
|
Line 620 xml_elem_end(struct parse *p, const char *name) |
|
} |
} |
|
|
if (p->del == 0) |
if (p->del == 0) |
pnode_closetext(p); |
pnode_closetext(p, 0); |
|
|
if (name != NULL) { |
node = name == NULL ? p->ncur : xml_name2node(p, name); |
for (elem = elements; elem->name != NULL; elem++) |
|
if (strcmp(elem->name, name) == 0) |
|
break; |
|
node = elem->node; |
|
} else |
|
node = p->ncur; |
|
|
|
switch (node) { |
switch (node) { |
case NODE_DELETE_WARN: |
case NODE_DELETE_WARN: |
Line 652 xml_elem_end(struct parse *p, const char *name) |
|
Line 631 xml_elem_end(struct parse *p, const char *name) |
|
p->del--; |
p->del--; |
break; |
break; |
case NODE_IGNORE: |
case NODE_IGNORE: |
|
case NODE_UNKNOWN: |
break; |
break; |
case NODE_INCLUDE: |
case NODE_INCLUDE: |
n = p->cur; |
n = p->cur; |
Line 674 xml_elem_end(struct parse *p, const char *name) |
|
Line 654 xml_elem_end(struct parse *p, const char *name) |
|
warn_msg(p, "element not open: </%s>", name); |
warn_msg(p, "element not open: </%s>", name); |
break; |
break; |
} |
} |
|
if (pnode_class(node) == CLASS_NOFILL) |
|
p->nofill--; |
|
|
/* |
/* |
* Refrain from actually closing the document element. |
* Refrain from actually closing the document element. |
Line 781 parse_string(struct parse *p, char *b, size_t rlen, |
|
Line 763 parse_string(struct parse *p, char *b, size_t rlen, |
|
enum pstate *pstate, int refill) |
enum pstate *pstate, int refill) |
{ |
{ |
char *cp; |
char *cp; |
|
size_t pws; /* Parse offset including whitespace. */ |
size_t poff; /* Parse offset in b[]. */ |
size_t poff; /* Parse offset in b[]. */ |
size_t pend; /* Offset of the end of the current word. */ |
size_t pend; /* Offset of the end of the current word. */ |
int elem_end; |
int elem_end; |
|
|
pend = 0; |
pend = pws = 0; |
for (;;) { |
for (;;) { |
|
|
/* Proceed to the next token, skipping whitespace. */ |
/* Proceed to the next token, skipping whitespace. */ |
Line 798 parse_string(struct parse *p, char *b, size_t rlen, |
|
Line 781 parse_string(struct parse *p, char *b, size_t rlen, |
|
break; |
break; |
if (isspace((unsigned char)b[pend])) { |
if (isspace((unsigned char)b[pend])) { |
p->flags |= PFLAG_SPC; |
p->flags |= PFLAG_SPC; |
|
if (b[pend] == '\n') |
|
pws = pend + 1; |
increment(p, b, &pend, refill); |
increment(p, b, &pend, refill); |
continue; |
continue; |
} |
} |
Line 959 parse_string(struct parse *p, char *b, size_t rlen, |
|
Line 944 parse_string(struct parse *p, char *b, size_t rlen, |
|
advance(p, b, rlen, &pend, |
advance(p, b, rlen, &pend, |
p->ncur == NODE_DOCTYPE ? "<&]\n" : "<&\n", |
p->ncur == NODE_DOCTYPE ? "<&]\n" : "<&\n", |
refill); |
refill); |
xml_char(p, b + poff, pend - poff); |
if (p->nofill) |
|
poff = pws; |
|
xml_text(p, b + poff, pend - poff); |
if (b[pend] == '\n') |
if (b[pend] == '\n') |
pnode_closetext(p); |
pnode_closetext(p, 0); |
} |
} |
|
pws = pend; |
} |
} |
return poff; |
return poff; |
} |
} |
Line 1046 parse_file(struct parse *p, int fd, const char *fname) |
|
Line 1034 parse_file(struct parse *p, int fd, const char *fname) |
|
/* On the top level, finalize the parse tree. */ |
/* On the top level, finalize the parse tree. */ |
|
|
if (save_fname == NULL) { |
if (save_fname == NULL) { |
pnode_closetext(p); |
pnode_closetext(p, 0); |
if (p->tree->root == NULL) |
if (p->tree->root == NULL) |
error_msg(p, "empty document"); |
error_msg(p, "empty document"); |
else if ((p->tree->flags & TREE_CLOSED) == 0) |
else if ((p->tree->flags & TREE_CLOSED) == 0) |