diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2015-04-19 13:50:25 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2015-04-19 13:50:25 +0000 |
commit | 344327def21ee64357a9cdf57c5352f1c5575708 (patch) | |
tree | 9c1fa971d139df98f2c3890c5d8712eaf4436b86 | |
parent | d4d5d006d52687c2882e89b913c70967626da0e1 (diff) | |
download | mandoc-344327def21ee64357a9cdf57c5352f1c5575708.tar.gz |
Unify node handling functions:
* node_alloc() for mdoc and man_node_alloc() -> roff_node_alloc()
* node_append() for mdoc and man_node_append() -> roff_node_append()
* mdoc_head_alloc() and man_head_alloc() -> roff_head_alloc()
* mdoc_body_alloc() and man_body_alloc() -> roff_body_alloc()
* mdoc_node_unlink() and man_node_unlink() -> roff_node_unlink()
* mdoc_node_free() and man_node_free() -> roff_node_free()
* mdoc_node_delete() and man_node_delete() -> roff_node_delete()
Minus 130 lines of code, no functional change.
-rw-r--r-- | Makefile.depend | 16 | ||||
-rw-r--r-- | libman.h | 2 | ||||
-rw-r--r-- | libmandoc.h | 2 | ||||
-rw-r--r-- | libmdoc.h | 2 | ||||
-rw-r--r-- | man.c | 196 | ||||
-rw-r--r-- | man_macro.c | 14 | ||||
-rw-r--r-- | man_validate.c | 9 | ||||
-rw-r--r-- | mdoc.c | 234 | ||||
-rw-r--r-- | mdoc_macro.c | 33 | ||||
-rw-r--r-- | mdoc_validate.c | 29 | ||||
-rw-r--r-- | roff.c | 210 | ||||
-rw-r--r-- | roff_int.h | 30 |
12 files changed, 323 insertions, 454 deletions
diff --git a/Makefile.depend b/Makefile.depend index 025e46a9..9d5871e7 100644 --- a/Makefile.depend +++ b/Makefile.depend @@ -1,5 +1,5 @@ att.o: att.c config.h roff.h mdoc.h libmdoc.h -cgi.o: cgi.c config.h mandoc.h mandoc_aux.h main.h manconf.h mansearch.h cgi.h +cgi.o: cgi.c config.h mandoc_aux.h mandoc.h roff.h main.h manconf.h mansearch.h cgi.h chars.o: chars.c config.h mandoc.h mandoc_aux.h libmandoc.h chars.in compat_fgetln.o: compat_fgetln.c config.h compat_fts.o: compat_fts.c config.h compat_fts.h @@ -22,12 +22,12 @@ eqn_term.o: eqn_term.c config.h mandoc.h out.h term.h html.o: html.c config.h mandoc.h mandoc_aux.h out.h html.h manconf.h main.h lib.o: lib.c config.h roff.h mdoc.h libmdoc.h lib.in main.o: main.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h main.h manconf.h mansearch.h -man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h libman.h +man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h man_hash.o: man_hash.c config.h roff.h man.h libman.h man_html.o: man_html.c config.h mandoc_aux.h roff.h man.h out.h html.h main.h -man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h libman.h +man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h term.h main.h -man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h libman.h +man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h mandoc.o: mandoc.c config.h mandoc.h mandoc_aux.h libmandoc.h mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h mandocdb.o: mandocdb.c config.h compat_fts.h compat_ohash.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h manconf.h mansearch.h @@ -35,19 +35,19 @@ manpage.o: manpage.c config.h manconf.h mansearch.h manpath.o: manpath.c config.h mandoc_aux.h manconf.h mansearch.o: mansearch.c config.h compat_ohash.h mandoc.h mandoc_aux.h manconf.h mansearch.h mansearch_const.o: mansearch_const.c config.h mansearch.h -mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h +mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h mdoc_hash.o: mdoc_hash.c config.h roff.h mdoc.h libmdoc.h mdoc_html.o: mdoc_html.c config.h mandoc_aux.h roff.h mdoc.h out.h html.h main.h -mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h +mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h mdoc_man.o: mdoc_man.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h out.h main.h mdoc_term.o: mdoc_term.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h term.h main.h -mdoc_validate.o: mdoc_validate.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h +mdoc_validate.o: mdoc_validate.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h msec.o: msec.c config.h mandoc.h libmandoc.h msec.in out.o: out.c config.h mandoc_aux.h mandoc.h out.h preconv.o: preconv.c config.h mandoc.h libmandoc.h read.o: read.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h libmandoc.h -roff.o: roff.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h predefs.in +roff.o: roff.c config.h mandoc.h mandoc_aux.h roff.h libmandoc.h roff_int.h libroff.h libmdoc.h predefs.in st.o: st.c config.h roff.h mdoc.h libmdoc.h st.in tbl.o: tbl.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h tbl_data.o: tbl_data.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h @@ -39,8 +39,6 @@ __BEGIN_DECLS void man_word_alloc(struct roff_man *, int, int, const char *); void man_word_append(struct roff_man *, const char *); void man_block_alloc(struct roff_man *, int, int, int); -void man_head_alloc(struct roff_man *, int, int, int); -void man_body_alloc(struct roff_man *, int, int, int); void man_elem_alloc(struct roff_man *, int, int, int); int man_hash_find(const char *); void man_macroend(struct roff_man *); diff --git a/libmandoc.h b/libmandoc.h index f91c8042..94f8482b 100644 --- a/libmandoc.h +++ b/libmandoc.h @@ -56,14 +56,12 @@ int mandoc_strntoi(const char *, size_t, int); const char *mandoc_a2msec(const char*); void mdoc_hash_init(void); -void mdoc_node_delete(struct roff_man *, struct roff_node *); int mdoc_parseln(struct roff_man *, int, char *, int); void mdoc_endparse(struct roff_man *); void mdoc_addspan(struct roff_man *, const struct tbl_span *); void mdoc_addeqn(struct roff_man *, const struct eqn *); void man_hash_init(void); -void man_node_delete(struct roff_man *, struct roff_node *); int man_parseln(struct roff_man *, int, char *, int); void man_endparse(struct roff_man *); void man_addspan(struct roff_man *, const struct tbl_span *); @@ -73,9 +73,7 @@ void mdoc_elem_alloc(struct roff_man *, int, int, int, struct mdoc_arg *); struct roff_node *mdoc_block_alloc(struct roff_man *, int, int, int, struct mdoc_arg *); -struct roff_node *mdoc_head_alloc(struct roff_man *, int, int, int); void mdoc_tail_alloc(struct roff_man *, int, int, int); -struct roff_node *mdoc_body_alloc(struct roff_man *, int, int, int); struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int, int, struct roff_node *, enum mdoc_endbody); void mdoc_node_relink(struct roff_man *, struct roff_node *); @@ -32,6 +32,7 @@ #include "roff.h" #include "man.h" #include "libmandoc.h" +#include "roff_int.h" #include "libman.h" const char *const __man_macronames[MAN_MAX] = { @@ -51,13 +52,6 @@ const char * const *man_macronames = __man_macronames; static void man_breakscope(struct roff_man *, int); static void man_descope(struct roff_man *, int, int); -static struct roff_node *man_node_alloc(struct roff_man *, int, int, - enum roff_type, int); -static void man_node_append(struct roff_man *, - struct roff_node *); -static void man_node_free(struct roff_node *); -static void man_node_unlink(struct roff_man *, - struct roff_node *); static int man_ptext(struct roff_man *, int, char *, int); static int man_pmacro(struct roff_man *, int, char *, int); @@ -81,107 +75,13 @@ man_parseln(struct roff_man *man, int ln, char *buf, int offs) man_ptext(man, ln, buf, offs)); } -static void -man_node_append(struct roff_man *man, struct roff_node *p) -{ - - assert(man->last); - assert(man->first); - assert(p->type != ROFFT_ROOT); - - switch (man->next) { - case ROFF_NEXT_SIBLING: - man->last->next = p; - p->prev = man->last; - p->parent = man->last->parent; - break; - case ROFF_NEXT_CHILD: - man->last->child = p; - p->parent = man->last; - break; - default: - abort(); - /* NOTREACHED */ - } - - assert(p->parent); - p->parent->nchild++; - - switch (p->type) { - case ROFFT_BLOCK: - if (p->tok == MAN_SH || p->tok == MAN_SS) - man->flags &= ~MAN_LITERAL; - break; - case ROFFT_HEAD: - assert(p->parent->type == ROFFT_BLOCK); - p->parent->head = p; - break; - case ROFFT_BODY: - assert(p->parent->type == ROFFT_BLOCK); - p->parent->body = p; - break; - default: - break; - } - - man->last = p; - - switch (p->type) { - case ROFFT_TBL: - /* FALLTHROUGH */ - case ROFFT_TEXT: - man_valid_post(man); - break; - default: - break; - } -} - -static struct roff_node * -man_node_alloc(struct roff_man *man, int line, int pos, - enum roff_type type, int tok) -{ - struct roff_node *p; - - p = mandoc_calloc(1, sizeof(*p)); - p->line = line; - p->pos = pos; - p->type = type; - p->tok = tok; - - if (man->flags & MAN_NEWLINE) - p->flags |= MAN_LINE; - man->flags &= ~MAN_NEWLINE; - return(p); -} - void man_elem_alloc(struct roff_man *man, int line, int pos, int tok) { struct roff_node *p; - p = man_node_alloc(man, line, pos, ROFFT_ELEM, tok); - man_node_append(man, p); - man->next = ROFF_NEXT_CHILD; -} - -void -man_head_alloc(struct roff_man *man, int line, int pos, int tok) -{ - struct roff_node *p; - - p = man_node_alloc(man, line, pos, ROFFT_HEAD, tok); - man_node_append(man, p); - man->next = ROFF_NEXT_CHILD; -} - -void -man_body_alloc(struct roff_man *man, int line, int pos, int tok) -{ - struct roff_node *p; - - p = man_node_alloc(man, line, pos, ROFFT_BODY, tok); - man_node_append(man, p); + p = roff_node_alloc(man, line, pos, ROFFT_ELEM, tok); + roff_node_append(man, p); man->next = ROFF_NEXT_CHILD; } @@ -190,8 +90,8 @@ man_block_alloc(struct roff_man *man, int line, int pos, int tok) { struct roff_node *p; - p = man_node_alloc(man, line, pos, ROFFT_BLOCK, tok); - man_node_append(man, p); + p = roff_node_alloc(man, line, pos, ROFFT_BLOCK, tok); + roff_node_append(man, p); man->next = ROFF_NEXT_CHILD; } @@ -200,9 +100,10 @@ man_word_alloc(struct roff_man *man, int line, int pos, const char *word) { struct roff_node *n; - n = man_node_alloc(man, line, pos, ROFFT_TEXT, MAN_MAX); + n = roff_node_alloc(man, line, pos, ROFFT_TEXT, MAN_MAX); n->string = roff_strdup(man->roff, word); - man_node_append(man, n); + roff_node_append(man, n); + man_valid_post(man); man->next = ROFF_NEXT_SIBLING; } @@ -221,39 +122,16 @@ man_word_append(struct roff_man *man, const char *word) man->next = ROFF_NEXT_SIBLING; } -/* - * Free all of the resources held by a node. This does NOT unlink a - * node from its context; for that, see man_node_unlink(). - */ -static void -man_node_free(struct roff_node *p) -{ - - free(p->string); - free(p); -} - -void -man_node_delete(struct roff_man *man, struct roff_node *p) -{ - - while (p->child) - man_node_delete(man, p->child); - - man_node_unlink(man, p); - man_node_free(p); -} - void man_addeqn(struct roff_man *man, const struct eqn *ep) { struct roff_node *n; - n = man_node_alloc(man, ep->ln, ep->pos, ROFFT_EQN, MAN_MAX); + n = roff_node_alloc(man, ep->ln, ep->pos, ROFFT_EQN, MAN_MAX); n->eqn = ep; if (ep->ln > man->last->line) n->flags |= MAN_LINE; - man_node_append(man, n); + roff_node_append(man, n); man->next = ROFF_NEXT_SIBLING; man_descope(man, ep->ln, ep->pos); } @@ -264,9 +142,10 @@ man_addspan(struct roff_man *man, const struct tbl_span *sp) struct roff_node *n; man_breakscope(man, MAN_MAX); - n = man_node_alloc(man, sp->line, 0, ROFFT_TBL, MAN_MAX); + n = roff_node_alloc(man, sp->line, 0, ROFFT_TBL, MAN_MAX); n->span = sp; - man_node_append(man, n); + roff_node_append(man, n); + man_valid_post(man); man->next = ROFF_NEXT_SIBLING; man_descope(man, sp->line, 0); } @@ -288,7 +167,7 @@ man_descope(struct roff_man *man, int line, int offs) return; man->flags &= ~MAN_BLINE; man_unscope(man, man->last->parent); - man_body_alloc(man, line, offs, man->last->tok); + roff_body_alloc(man, line, offs, man->last->tok); } static int @@ -455,7 +334,7 @@ man_pmacro(struct roff_man *man, int ln, char *buf, int offs) man->flags &= ~MAN_BLINE; man_unscope(man, man->last->parent); - man_body_alloc(man, ln, ppos, man->last->tok); + roff_body_alloc(man, ln, ppos, man->last->tok); return(1); } @@ -482,7 +361,7 @@ man_breakscope(struct roff_man *man, int tok) tok == MAN_MAX ? "TS" : man_macronames[tok], man_macronames[n->tok]); - man_node_delete(man, n); + roff_node_delete(man, n); man->flags &= ~MAN_ELINE; } @@ -510,52 +389,11 @@ man_breakscope(struct roff_man *man, int tok) tok == MAN_MAX ? "TS" : man_macronames[tok], man_macronames[n->tok]); - man_node_delete(man, n); + roff_node_delete(man, n); man->flags &= ~MAN_BLINE; } } -/* - * Unlink a node from its context. If "man" is provided, the last parse - * point will also be adjusted accordingly. - */ -static void -man_node_unlink(struct roff_man *man, struct roff_node *n) -{ - - /* Adjust siblings. */ - - if (n->prev) - n->prev->next = n->next; - if (n->next) - n->next->prev = n->prev; - - /* Adjust parent. */ - - if (n->parent) { - n->parent->nchild--; - if (n->parent->child == n) - n->parent->child = n->prev ? n->prev : n->next; - } - - /* Adjust parse point, if applicable. */ - - if (man && man->last == n) { - /*XXX: this can occur when bailing from validation. */ - /*assert(NULL == n->next);*/ - if (n->prev) { - man->last = n->prev; - man->next = ROFF_NEXT_SIBLING; - } else { - man->last = n->parent; - man->next = ROFF_NEXT_CHILD; - } - } - - if (man && man->first == n) - man->first = NULL; -} - const struct mparse * man_mparse(const struct roff_man *man) { diff --git a/man_macro.c b/man_macro.c index 52d88199..77c5ed11 100644 --- a/man_macro.c +++ b/man_macro.c @@ -29,6 +29,7 @@ #include "roff.h" #include "man.h" #include "libmandoc.h" +#include "roff_int.h" #include "libman.h" static void blk_close(MACRO_PROT_ARGS); @@ -110,7 +111,7 @@ man_unscope(struct roff_man *man, const struct roff_node *to) } man->last = n; n = n->parent; - man_node_delete(man, man->last); + roff_node_delete(man, man->last); continue; } if (n->type == ROFFT_BLOCK && @@ -259,8 +260,7 @@ blk_exp(MACRO_PROT_ARGS) rew_scope(man, tok); man_block_alloc(man, line, ppos, tok); - man_head_alloc(man, line, ppos, tok); - head = man->last; + head = roff_head_alloc(man, line, ppos, tok); la = *pos; if (man_args(man, line, pos, buf, &p)) @@ -272,7 +272,7 @@ blk_exp(MACRO_PROT_ARGS) man_macronames[tok], buf + *pos); man_unscope(man, head); - man_body_alloc(man, line, ppos, tok); + roff_body_alloc(man, line, ppos, tok); } /* @@ -290,8 +290,10 @@ blk_imp(MACRO_PROT_ARGS) rew_scope(man, tok); man_block_alloc(man, line, ppos, tok); - man_head_alloc(man, line, ppos, tok); n = man->last; + if (n->tok == MAN_SH || n->tok == MAN_SS) + man->flags &= ~MAN_LITERAL; + n = roff_head_alloc(man, line, ppos, tok); /* Add line arguments. */ @@ -317,7 +319,7 @@ blk_imp(MACRO_PROT_ARGS) /* Close out the head and open the body. */ man_unscope(man, n); - man_body_alloc(man, line, ppos, tok); + roff_body_alloc(man, line, ppos, tok); } void diff --git a/man_validate.c b/man_validate.c index ef45ce21..e1303f38 100644 --- a/man_validate.c +++ b/man_validate.c @@ -33,6 +33,7 @@ #include "roff.h" #include "man.h" #include "libmandoc.h" +#include "roff_int.h" #include "libman.h" #define CHKARGS struct roff_man *man, struct roff_node *n @@ -256,7 +257,7 @@ check_par(CHKARGS) switch (n->type) { case ROFFT_BLOCK: if (0 == n->body->nchild) - man_node_delete(man, n); + roff_node_delete(man, n); break; case ROFFT_BODY: if (0 == n->nchild) @@ -284,7 +285,7 @@ post_IP(CHKARGS) switch (n->type) { case ROFFT_BLOCK: if (0 == n->head->nchild && 0 == n->body->nchild) - man_node_delete(man, n); + roff_node_delete(man, n); break; case ROFFT_BODY: if (0 == n->parent->head->nchild && 0 == n->nchild) @@ -388,7 +389,7 @@ post_TH(CHKARGS) * Remove the `TH' node after we've processed it for our * meta-data. */ - man_node_delete(man, man->last); + roff_node_delete(man, man->last); } static void @@ -509,7 +510,7 @@ post_vs(CHKARGS) * Don't warn about this because it occurs in pod2man * and would cause considerable (unfixable) warnage. */ - man_node_delete(man, n); + roff_node_delete(man, n); break; default: break; @@ -32,6 +32,7 @@ #include "roff.h" #include "mdoc.h" #include "libmandoc.h" +#include "roff_int.h" #include "libmdoc.h" const char *const __mdoc_macronames[MDOC_MAX + 1] = { @@ -83,12 +84,6 @@ const char *const __mdoc_argnames[MDOC_ARG_MAX] = { const char * const *mdoc_macronames = __mdoc_macronames; const char * const *mdoc_argnames = __mdoc_argnames; -static void mdoc_node_free(struct roff_node *); -static void mdoc_node_unlink(struct roff_man *, - struct roff_node *); -static struct roff_node *node_alloc(struct roff_man *, int, int, - int, enum roff_type); -static void node_append(struct roff_man *, struct roff_node *); static int mdoc_ptext(struct roff_man *, int, char *, int); static int mdoc_pmacro(struct roff_man *, int, char *, int); @@ -105,11 +100,11 @@ mdoc_addeqn(struct roff_man *mdoc, const struct eqn *ep) { struct roff_node *n; - n = node_alloc(mdoc, ep->ln, ep->pos, MDOC_MAX, ROFFT_EQN); + n = roff_node_alloc(mdoc, ep->ln, ep->pos, ROFFT_EQN, MDOC_MAX); n->eqn = ep; if (ep->ln > mdoc->last->line) n->flags |= MDOC_LINE; - node_append(mdoc, n); + roff_node_append(mdoc, n); mdoc->next = ROFF_NEXT_SIBLING; } @@ -118,9 +113,10 @@ mdoc_addspan(struct roff_man *mdoc, const struct tbl_span *sp) { struct roff_node *n; - n = node_alloc(mdoc, sp->line, 0, MDOC_MAX, ROFFT_TBL); + n = roff_node_alloc(mdoc, sp->line, 0, ROFFT_TBL, MDOC_MAX); n->span = sp; - node_append(mdoc, n); + roff_node_append(mdoc, n); + mdoc_valid_post(mdoc); mdoc->next = ROFF_NEXT_SIBLING; } @@ -177,143 +173,14 @@ mdoc_macro(MACRO_PROT_ARGS) (*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf); } - -static void -node_append(struct roff_man *mdoc, struct roff_node *p) -{ - - assert(mdoc->last); - assert(mdoc->first); - assert(p->type != ROFFT_ROOT); - - switch (mdoc->next) { - case ROFF_NEXT_SIBLING: - mdoc->last->next = p; - p->prev = mdoc->last; - p->parent = mdoc->last->parent; - break; - case ROFF_NEXT_CHILD: - mdoc->last->child = p; - p->parent = mdoc->last; - break; - default: - abort(); - /* NOTREACHED */ - } - - p->parent->nchild++; - - /* - * Copy over the normalised-data pointer of our parent. Not - * everybody has one, but copying a null pointer is fine. - */ - - switch (p->type) { - case ROFFT_BODY: - if (ENDBODY_NOT != p->end) - break; - /* FALLTHROUGH */ - case ROFFT_TAIL: - /* FALLTHROUGH */ - case ROFFT_HEAD: - p->norm = p->parent->norm; - break; - default: - break; - } - - mdoc_valid_pre(mdoc, p); - - switch (p->type) { - case ROFFT_HEAD: - assert(p->parent->type == ROFFT_BLOCK); - p->parent->head = p; - break; - case ROFFT_TAIL: - assert(p->parent->type == ROFFT_BLOCK); - p->parent->tail = p; - break; - case ROFFT_BODY: - if (p->end) - break; - assert(p->parent->type == ROFFT_BLOCK); - p->parent->body = p; - break; - default: - break; - } - - mdoc->last = p; - - switch (p->type) { - case ROFFT_TBL: - /* FALLTHROUGH */ - case ROFFT_TEXT: - mdoc_valid_post(mdoc); - break; - default: - break; - } -} - -static struct roff_node * -node_alloc(struct roff_man *mdoc, int line, int pos, - int tok, enum roff_type type) -{ - struct roff_node *p; - - p = mandoc_calloc(1, sizeof(*p)); - p->sec = mdoc->lastsec; - p->line = line; - p->pos = pos; - p->tok = tok; - p->type = type; - - /* Flag analysis. */ - - if (MDOC_SYNOPSIS & mdoc->flags) - p->flags |= MDOC_SYNPRETTY; - else - p->flags &= ~MDOC_SYNPRETTY; - if (MDOC_NEWLINE & mdoc->flags) - p->flags |= MDOC_LINE; - mdoc->flags &= ~MDOC_NEWLINE; - - return(p); -} - void mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, int tok) { struct roff_node *p; - p = node_alloc(mdoc, line, pos, tok, ROFFT_TAIL); - node_append(mdoc, p); - mdoc->next = ROFF_NEXT_CHILD; -} - -struct roff_node * -mdoc_head_alloc(struct roff_man *mdoc, int line, int pos, int tok) -{ - struct roff_node *p; - - assert(mdoc->first); - assert(mdoc->last); - p = node_alloc(mdoc, line, pos, tok, ROFFT_HEAD); - node_append(mdoc, p); + p = roff_node_alloc(mdoc, line, pos, ROFFT_TAIL, tok); + roff_node_append(mdoc, p); mdoc->next = ROFF_NEXT_CHILD; - return(p); -} - -struct roff_node * -mdoc_body_alloc(struct roff_man *mdoc, int line, int pos, int tok) -{ - struct roff_node *p; - - p = node_alloc(mdoc, line, pos, tok, ROFFT_BODY); - node_append(mdoc, p); - mdoc->next = ROFF_NEXT_CHILD; - return(p); } struct roff_node * @@ -324,11 +191,11 @@ mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok, body->flags |= MDOC_ENDED; body->parent->flags |= MDOC_ENDED; - p = node_alloc(mdoc, line, pos, tok, ROFFT_BODY); + p = roff_node_alloc(mdoc, line, pos, ROFFT_BODY, tok); p->body = body; p->norm = body->norm; p->end = end; - node_append(mdoc, p); + roff_node_append(mdoc, p); mdoc->next = ROFF_NEXT_SIBLING; return(p); } @@ -339,7 +206,7 @@ mdoc_block_alloc(struct roff_man *mdoc, int line, int pos, { struct roff_node *p; - p = node_alloc(mdoc, line, pos, tok, ROFFT_BLOCK); + p = roff_node_alloc(mdoc, line, pos, ROFFT_BLOCK, tok); p->args = args; if (p->args) (args->refcnt)++; @@ -359,7 +226,7 @@ mdoc_block_alloc(struct roff_man *mdoc, int line, int pos, default: break; } - node_append(mdoc, p); + roff_node_append(mdoc, p); mdoc->next = ROFF_NEXT_CHILD; return(p); } @@ -370,7 +237,7 @@ mdoc_elem_alloc(struct roff_man *mdoc, int line, int pos, { struct roff_node *p; - p = node_alloc(mdoc, line, pos, tok, ROFFT_ELEM); + p = roff_node_alloc(mdoc, line, pos, ROFFT_ELEM, tok); p->args = args; if (p->args) (args->refcnt)++; @@ -382,7 +249,7 @@ mdoc_elem_alloc(struct roff_man *mdoc, int line, int pos, default: break; } - node_append(mdoc, p); + roff_node_append(mdoc, p); mdoc->next = ROFF_NEXT_CHILD; } @@ -391,9 +258,10 @@ mdoc_word_alloc(struct roff_man *mdoc, int line, int pos, const char *p) { struct roff_node *n; - n = node_alloc(mdoc, line, pos, MDOC_MAX, ROFFT_TEXT); + n = roff_node_alloc(mdoc, line, pos, ROFFT_TEXT, MDOC_MAX); n->string = roff_strdup(mdoc->roff, p); - node_append(mdoc, n); + roff_node_append(mdoc, n); + mdoc_valid_post(mdoc); mdoc->next = ROFF_NEXT_SIBLING; } @@ -412,76 +280,12 @@ mdoc_word_append(struct roff_man *mdoc, const char *p) mdoc->next = ROFF_NEXT_SIBLING; } -static void -mdoc_node_free(struct roff_node *p) -{ - - if (p->type == ROFFT_BLOCK || p->type == ROFFT_ELEM) - free(p->norm); - if (p->string) - free(p->string); - if (p->args) - mdoc_argv_free(p->args); - free(p); -} - -static void -mdoc_node_unlink(struct roff_man *mdoc, struct roff_node *n) -{ - - /* Adjust siblings. */ - - if (n->prev) - n->prev->next = n->next; - if (n->next) - n->next->prev = n->prev; - - /* Adjust parent. */ - - if (n->parent) { - n->parent->nchild--; - if (n->parent->child == n) - n->parent->child = n->prev ? n->prev : n->next; - if (n->parent->last == n) - n->parent->last = n->prev ? n->prev : NULL; - } - - /* Adjust parse point, if applicable. */ - - if (mdoc && mdoc->last == n) { - if (n->prev) { - mdoc->last = n->prev; - mdoc->next = ROFF_NEXT_SIBLING; - } else { - mdoc->last = n->parent; - mdoc->next = ROFF_NEXT_CHILD; - } - } - - if (mdoc && mdoc->first == n) - mdoc->first = NULL; -} - -void -mdoc_node_delete(struct roff_man *mdoc, struct roff_node *p) -{ - - while (p->child) { - assert(p->nchild); - mdoc_node_delete(mdoc, p->child); - } - assert(0 == p->nchild); - - mdoc_node_unlink(mdoc, p); - mdoc_node_free(p); -} - void mdoc_node_relink(struct roff_man *mdoc, struct roff_node *p) { - mdoc_node_unlink(mdoc, p); - node_append(mdoc, p); + roff_node_unlink(mdoc, p); + roff_node_append(mdoc, p); } /* diff --git a/mdoc_macro.c b/mdoc_macro.c index 360e6e64..e904a6eb 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -30,6 +30,7 @@ #include "roff.h" #include "mdoc.h" #include "libmandoc.h" +#include "roff_int.h" #include "libmdoc.h" static void blk_full(MACRO_PROT_ARGS); @@ -292,7 +293,7 @@ rew_pending(struct roff_man *mdoc, const struct roff_node *n) switch (n->type) { case ROFFT_HEAD: - mdoc_body_alloc(mdoc, n->line, n->pos, n->tok); + roff_body_alloc(mdoc, n->line, n->pos, n->tok); return; case ROFFT_BLOCK: break; @@ -1022,9 +1023,9 @@ blk_full(MACRO_PROT_ARGS) */ if (tok == MDOC_Nd) { - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); rew_last(mdoc, head); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); } if (tok == MDOC_Bk) @@ -1047,7 +1048,7 @@ blk_full(MACRO_PROT_ARGS) */ if (body != NULL) rew_last(mdoc, body); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); break; } if (tok == MDOC_Bd || tok == MDOC_Bk) { @@ -1082,7 +1083,7 @@ blk_full(MACRO_PROT_ARGS) /* Open a head if one hasn't been opened. */ if (head == NULL) - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); if (ac == ARGS_PHRASE || ac == ARGS_PEND || @@ -1094,7 +1095,7 @@ blk_full(MACRO_PROT_ARGS) */ rew_last(mdoc, body == NULL ? head : body); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); /* * Process phrases: set whether we're in a @@ -1118,7 +1119,7 @@ blk_full(MACRO_PROT_ARGS) if (blk->flags & MDOC_VALID) return; if (head == NULL) - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); if (nl && tok != MDOC_Bd && tok != MDOC_Bl && tok != MDOC_Rs) append_delims(mdoc, line, pos, buf); if (body != NULL) @@ -1129,7 +1130,7 @@ blk_full(MACRO_PROT_ARGS) /* Close out scopes to remain in a consistent state. */ rew_last(mdoc, head); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); out: if (mdoc->flags & MDOC_FREECOL) { rew_last(mdoc, body); @@ -1160,7 +1161,7 @@ blk_part_imp(MACRO_PROT_ARGS) */ blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL); - rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok)); + rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok)); /* * Open the body scope "on-demand", that is, after we've @@ -1181,13 +1182,13 @@ blk_part_imp(MACRO_PROT_ARGS) } if (body == NULL) - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) break; } if (body == NULL) - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); if (find_pending(mdoc, tok, line, ppos, body)) return; @@ -1238,11 +1239,11 @@ blk_part_exp(MACRO_PROT_ARGS) } if (head == NULL) { - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); if (tok == MDOC_Eo) /* Not parsed. */ dword(mdoc, line, la, p, DELIM_MAX, 0); rew_last(mdoc, head); - mdoc_body_alloc(mdoc, line, ppos, tok); + roff_body_alloc(mdoc, line, ppos, tok); if (tok == MDOC_Eo) continue; } @@ -1254,8 +1255,8 @@ blk_part_exp(MACRO_PROT_ARGS) /* Clean-up to leave in a consistent state. */ if (head == NULL) { - rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok)); - mdoc_body_alloc(mdoc, line, ppos, tok); + rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok)); + roff_body_alloc(mdoc, line, ppos, tok); } if (nl) append_delims(mdoc, line, pos, buf); @@ -1471,6 +1472,6 @@ phrase_ta(MACRO_PROT_ARGS) /* Advance to the next column. */ rew_last(mdoc, body); - mdoc_body_alloc(mdoc, line, ppos, MDOC_It); + roff_body_alloc(mdoc, line, ppos, MDOC_It); parse_rest(mdoc, MDOC_MAX, line, pos, buf); } diff --git a/mdoc_validate.c b/mdoc_validate.c index 21109bc1..c65f4f15 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -36,6 +36,7 @@ #include "roff.h" #include "mdoc.h" #include "libmandoc.h" +#include "roff_int.h" #include "libmdoc.h" /* FIXME: .Bl -diag can't have non-text children in HEAD. */ @@ -904,7 +905,7 @@ post_fo(POST_ARGS) n->child->next->line, n->child->next->pos, "Fo ... %s", n->child->next->string); while (n->child != n->last) - mdoc_node_delete(mdoc, n->last); + roff_node_delete(mdoc, n->last); } post_fname(mdoc); @@ -1246,7 +1247,7 @@ post_bl_block(POST_ARGS) mdoc->parse, nc->line, nc->pos, "%s before It", mdoc_macronames[nc->tok]); - mdoc_node_delete(mdoc, nc); + roff_node_delete(mdoc, nc); } else break; nc = ni->body->last; @@ -1357,7 +1358,7 @@ post_bl_head(POST_ARGS) mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, nch->line, nch->pos, "Bl ... %s", nch->string); while (nch != NULL) { - mdoc_node_delete(mdoc, nch); + roff_node_delete(mdoc, nch); nch = nh->child; } return; @@ -1398,7 +1399,7 @@ post_bl_head(POST_ARGS) argv->value[i++] = nch->string; nch->string = NULL; nnext = nch->next; - mdoc_node_delete(NULL, nch); + roff_node_delete(NULL, nch); } nh->nchild = 0; nh->child = NULL; @@ -1497,7 +1498,7 @@ post_bk(POST_ARGS) if (n->type == ROFFT_BLOCK && n->body->child == NULL) { mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, n->line, n->pos, "Bk"); - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } } @@ -1585,7 +1586,7 @@ post_st(POST_ARGS) if (NULL == (p = mdoc_a2st(nch->string))) { mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse, nch->line, nch->pos, "St %s", nch->string); - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } else { free(nch->string); nch->string = mandoc_strdup(p); @@ -1632,7 +1633,7 @@ post_rs(POST_ARGS) /* * Remove this child from the chain. This somewhat - * repeats mdoc_node_unlink(), but since we're + * repeats roff_node_unlink(), but since we're * just re-ordering, there's no need for the * full unlink process. */ @@ -2005,7 +2006,7 @@ post_ignpar(POST_ARGS) mdoc->parse, np->line, np->pos, "%s after %s", mdoc_macronames[np->tok], mdoc_macronames[mdoc->last->tok]); - mdoc_node_delete(mdoc, np); + roff_node_delete(mdoc, np); } if (NULL != (np = mdoc->last->last)) @@ -2014,7 +2015,7 @@ post_ignpar(POST_ARGS) np->line, np->pos, "%s at the end of %s", mdoc_macronames[np->tok], mdoc_macronames[mdoc->last->tok]); - mdoc_node_delete(mdoc, np); + roff_node_delete(mdoc, np); } } @@ -2047,7 +2048,7 @@ pre_par(PRE_ARGS) mdoc->last->line, mdoc->last->pos, "%s before %s", mdoc_macronames[mdoc->last->tok], mdoc_macronames[n->tok]); - mdoc_node_delete(mdoc, mdoc->last); + roff_node_delete(mdoc, mdoc->last); } static void @@ -2080,7 +2081,7 @@ post_par(POST_ARGS) mdoc->last->line, mdoc->last->pos, "%s after %s", mdoc_macronames[mdoc->last->tok], mdoc_macronames[np->tok]); - mdoc_node_delete(mdoc, mdoc->last); + roff_node_delete(mdoc, mdoc->last); } static void @@ -2139,7 +2140,7 @@ post_dd(POST_ARGS) free(datestr); } out: - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } static void @@ -2224,7 +2225,7 @@ post_dt(POST_ARGS) nn->line, nn->pos, "Dt ... %s", nn->string); out: - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } static void @@ -2290,7 +2291,7 @@ post_os(POST_ARGS) #endif /*!OSNAME*/ out: - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } /* @@ -30,7 +30,9 @@ #include "mandoc_aux.h" #include "roff.h" #include "libmandoc.h" +#include "roff_int.h" #include "libroff.h" +#include "libmdoc.h" /* Maximum number of nested if-else conditionals. */ #define RSTACK_MAX 128 @@ -38,6 +40,8 @@ /* Maximum number of string expansions per line, to break infinite loops. */ #define EXPAND_LIMIT 1000 +/* --- data types --------------------------------------------------------- */ + enum rofft { ROFF_ab, ROFF_ad, @@ -374,6 +378,8 @@ struct predef { #define PREDEF(__name, __str) \ { (__name), (__str) }, +/* --- function prototypes ------------------------------------------------ */ + static enum rofft roffhash_find(const char *, size_t); static void roffhash_init(void); static void roffnode_cleanscope(struct roff *); @@ -438,6 +444,8 @@ static enum rofferr roff_T_(ROFF_ARGS); static enum rofferr roff_unsupp(ROFF_ARGS); static enum rofferr roff_userdef(ROFF_ARGS); +/* --- constant data ------------------------------------------------------ */ + /* See roffhash_find() */ #define ASCII_HI 126 @@ -734,6 +742,8 @@ static int roffit_lines; /* number of lines to delay */ static char *roffit_macro; /* nil-terminated macro line */ +/* --- request table ------------------------------------------------------ */ + static void roffhash_init(void) { @@ -786,6 +796,8 @@ roffhash_find(const char *p, size_t s) return(ROFF_MAX); } +/* --- stack of request blocks -------------------------------------------- */ + /* * Pop the current node off of the stack of roff instructions currently * pending. @@ -826,6 +838,8 @@ roffnode_push(struct roff *r, enum rofft tok, const char *name, r->last = p; } +/* --- roff parser state data management ---------------------------------- */ + static void roff_free1(struct roff *r) { @@ -901,16 +915,14 @@ roff_alloc(struct mparse *parse, const struct mchars *mchars, int options) return(r); } +/* --- syntax tree state data management ---------------------------------- */ + static void roff_man_free1(struct roff_man *man) { - if (man->first != NULL) { - if (man->macroset == MACROSET_MDOC) - mdoc_node_delete(man, man->first); - else - man_node_delete(man, man->first); - } + if (man->first != NULL) + roff_node_delete(man, man->first); free(man->meta.msec); free(man->meta.vol); free(man->meta.os); @@ -966,6 +978,180 @@ roff_man_alloc(struct roff *roff, struct mparse *parse, return(man); } +/* --- syntax tree handling ----------------------------------------------- */ + +struct roff_node * +roff_node_alloc(struct roff_man *man, int line, int pos, + enum roff_type type, int tok) +{ + struct roff_node *n; + + n = mandoc_calloc(1, sizeof(*n)); + n->line = line; + n->pos = pos; + n->tok = tok; + n->type = type; + n->sec = man->lastsec; + + if (man->flags & MDOC_SYNOPSIS) + n->flags |= MDOC_SYNPRETTY; + else + n->flags &= ~MDOC_SYNPRETTY; + if (man->flags & MDOC_NEWLINE) + n->flags |= MDOC_LINE; + man->flags &= ~MDOC_NEWLINE; + + return(n); +} + +void +roff_node_append(struct roff_man *man, struct roff_node *n) +{ + + switch (man->next) { + case ROFF_NEXT_SIBLING: + man->last->next = n; + n->prev = man->last; + n->parent = man->last->parent; + break; + case ROFF_NEXT_CHILD: + man->last->child = n; + n->parent = man->last; + break; + default: + abort(); + /* NOTREACHED */ + } + n->parent->nchild++; + + /* + * Copy over the normalised-data pointer of our parent. Not + * everybody has one, but copying a null pointer is fine. + */ + + switch (n->type) { + case ROFFT_BODY: + if (n->end != ENDBODY_NOT) + break; + /* FALLTHROUGH */ + case ROFFT_TAIL: + /* FALLTHROUGH */ + case ROFFT_HEAD: + n->norm = n->parent->norm; + break; + default: + break; + } + + if (man->macroset == MACROSET_MDOC) + mdoc_valid_pre(man, n); + + switch (n->type) { + case ROFFT_HEAD: + assert(n->parent->type == ROFFT_BLOCK); + n->parent->head = n; + break; + case ROFFT_BODY: + if (n->end) + break; + assert(n->parent->type == ROFFT_BLOCK); + n->parent->body = n; + break; + case ROFFT_TAIL: + assert(n->parent->type == ROFFT_BLOCK); + n->parent->tail = n; + break; + default: + break; + } + man->last = n; +} + +struct roff_node * +roff_head_alloc(struct roff_man *man, int line, int pos, int tok) +{ + struct roff_node *n; + + n = roff_node_alloc(man, line, pos, ROFFT_HEAD, tok); + roff_node_append(man, n); + man->next = ROFF_NEXT_CHILD; + return(n); +} + +struct roff_node * +roff_body_alloc(struct roff_man *man, int line, int pos, int tok) +{ + struct roff_node *n; + + n = roff_node_alloc(man, line, pos, ROFFT_BODY, tok); + roff_node_append(man, n); + man->next = ROFF_NEXT_CHILD; + return(n); +} + +void +roff_node_unlink(struct roff_man *man, struct roff_node *n) +{ + + /* Adjust siblings. */ + + if (n->prev) + n->prev->next = n->next; + if (n->next) + n->next->prev = n->prev; + + /* Adjust parent. */ + + if (n->parent != NULL) { + n->parent->nchild--; + if (n->parent->child == n) + n->parent->child = n->next; + if (n->parent->last == n) + n->parent->last = n->prev; + } + + /* Adjust parse point. */ + + if (man == NULL) + return; + if (man->last == n) { + if (n->prev == NULL) { + man->last = n->parent; + man->next = ROFF_NEXT_CHILD; + } else { + man->last = n->prev; + man->next = ROFF_NEXT_SIBLING; + } + } + if (man->first == n) + man->first = NULL; +} + +void +roff_node_free(struct roff_node *n) +{ + + if (n->args != NULL) + mdoc_argv_free(n->args); + if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM) + free(n->norm); + free(n->string); + free(n); +} + +void +roff_node_delete(struct roff_man *man, struct roff_node *n) +{ + + while (n->child != NULL) + roff_node_delete(man, n->child); + assert(n->nchild == 0); + roff_node_unlink(man, n); + roff_node_free(n); +} + +/* --- main functions of the roff parser ---------------------------------- */ + /* * In the current line, expand escape sequences that tend to get * used in numerical expressions and conditional requests. @@ -1385,6 +1571,8 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos) return(t); } +/* --- handling of request blocks ----------------------------------------- */ + static enum rofferr roff_cblock(ROFF_ARGS) { @@ -1695,6 +1883,8 @@ roff_cond_text(ROFF_ARGS) return(rr ? ROFF_CONT : ROFF_IGN); } +/* --- handling of numeric and conditional expressions -------------------- */ + /* * Parse a single signed integer number. Stop at the first non-digit. * If there is at least one digit, return success and advance the @@ -2212,6 +2402,8 @@ roff_evalnum(struct roff *r, int ln, const char *v, return(1); } +/* --- register management ------------------------------------------------ */ + void roff_setreg(struct roff *r, const char *name, int val, char sign) { @@ -2376,6 +2568,8 @@ roff_rr(ROFF_ARGS) return(ROFF_IGN); } +/* --- handler functions for roff requests -------------------------------- */ + static enum rofferr roff_rm(ROFF_ARGS) { @@ -2720,6 +2914,8 @@ roff_so(ROFF_ARGS) return(ROFF_SO); } +/* --- user defined strings and macros ------------------------------------ */ + static enum rofferr roff_userdef(ROFF_ARGS) { @@ -2988,6 +3184,8 @@ roff_freestr(struct roffkv *r) } } +/* --- accessors and utility functions ------------------------------------ */ + const struct tbl_span * roff_span(const struct roff *r) { diff --git a/roff_int.h b/roff_int.h new file mode 100644 index 00000000..4d338628 --- /dev/null +++ b/roff_int.h @@ -0,0 +1,30 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +__BEGIN_DECLS + +struct roff_node *roff_node_alloc(struct roff_man *, int, int, + enum roff_type, int); +void roff_node_append(struct roff_man *, struct roff_node *); +struct roff_node *roff_head_alloc(struct roff_man *, int, int, int); +struct roff_node *roff_body_alloc(struct roff_man *, int, int, int); +void roff_node_unlink(struct roff_man *, struct roff_node *); +void roff_node_free(struct roff_node *); +void roff_node_delete(struct roff_man *, struct roff_node *); + +__END_DECLS |