=================================================================== RCS file: /cvs/mandoc/man.c,v retrieving revision 1.120 retrieving revision 1.130 diff -u -p -r1.120 -r1.130 --- mandoc/man.c 2013/10/17 20:54:58 1.120 +++ mandoc/man.c 2014/05/07 14:14:17 1.130 @@ -1,6 +1,8 @@ -/* $Id: man.c,v 1.120 2013/10/17 20:54:58 schwarze Exp $ */ +/* $Id: man.c,v 1.130 2014/05/07 14:14:17 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons + * Copyright (c) 2013, 2014 Ingo Schwarze + * Copyright (c) 2011 Joerg Sonnenberger * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,6 +23,7 @@ #include #include +#include #include #include #include @@ -28,12 +31,13 @@ #include "man.h" #include "mandoc.h" +#include "mandoc_aux.h" #include "libman.h" #include "libmandoc.h" -const char *const __man_macronames[MAN_MAX] = { +const char *const __man_macronames[MAN_MAX] = { "br", "TH", "SH", "SS", - "TP", "LP", "PP", "P", + "TP", "LP", "PP", "P", "IP", "HP", "SM", "SB", "BI", "IB", "BR", "RB", "R", "B", "I", "IR", @@ -41,17 +45,17 @@ const char *const __man_macronames[MAN_MAX] = { "fi", "RE", "RS", "DT", "UC", "PD", "AT", "in", "ft", "OP", "EX", "EE", - "UR", "UE" + "UR", "UE", "ll" }; const char * const *man_macronames = __man_macronames; -static struct man_node *man_node_alloc(struct man *, int, int, +static struct man_node *man_node_alloc(struct man *, int, int, enum man_type, enum mant); -static int man_node_append(struct man *, +static int man_node_append(struct man *, struct man_node *); static void man_node_free(struct man_node *); -static void man_node_unlink(struct man *, +static void man_node_unlink(struct man *, struct man_node *); static int man_ptext(struct man *, int, char *, int); static int man_pmacro(struct man *, int, char *, int); @@ -68,7 +72,6 @@ man_node(const struct man *man) return(man->first); } - const struct man_meta * man_meta(const struct man *man) { @@ -77,7 +80,6 @@ man_meta(const struct man *man) return(&man->meta); } - void man_reset(struct man *man) { @@ -86,7 +88,6 @@ man_reset(struct man *man) man_alloc1(man); } - void man_free(struct man *man) { @@ -95,9 +96,8 @@ man_free(struct man *man) free(man); } - struct man * -man_alloc(struct roff *roff, struct mparse *parse) +man_alloc(struct roff *roff, struct mparse *parse, int quick) { struct man *p; @@ -105,13 +105,13 @@ man_alloc(struct roff *roff, struct mparse *parse) man_hash_init(); p->parse = parse; + p->quick = quick; p->roff = roff; man_alloc1(p); return(p); } - int man_endparse(struct man *man) { @@ -123,7 +123,6 @@ man_endparse(struct man *man) return(0); } - int man_parseln(struct man *man, int ln, char *buf, int offs) { @@ -133,11 +132,10 @@ man_parseln(struct man *man, int ln, char *buf, int of assert( ! (MAN_HALT & man->flags)); return (roff_getcontrol(man->roff, buf, &offs) ? - man_pmacro(man, ln, buf, offs) : - man_ptext(man, ln, buf, offs)); + man_pmacro(man, ln, buf, offs) : + man_ptext(man, ln, buf, offs)); } - static void man_free1(struct man *man) { @@ -156,7 +154,6 @@ man_free1(struct man *man) free(man->meta.msec); } - static void man_alloc1(struct man *man) { @@ -180,12 +177,12 @@ man_node_append(struct man *man, struct man_node *p) assert(MAN_ROOT != p->type); switch (man->next) { - case (MAN_NEXT_SIBLING): + case MAN_NEXT_SIBLING: man->last->next = p; p->prev = man->last; p->parent = man->last->parent; break; - case (MAN_NEXT_CHILD): + case MAN_NEXT_CHILD: man->last->child = p; p->parent = man->last; break; @@ -193,7 +190,7 @@ man_node_append(struct man *man, struct man_node *p) abort(); /* NOTREACHED */ } - + assert(p->parent); p->parent->nchild++; @@ -201,15 +198,15 @@ man_node_append(struct man *man, struct man_node *p) return(0); switch (p->type) { - case (MAN_HEAD): + case MAN_HEAD: assert(MAN_BLOCK == p->parent->type); p->parent->head = p; break; - case (MAN_TAIL): + case MAN_TAIL: assert(MAN_BLOCK == p->parent->type); p->parent->tail = p; break; - case (MAN_BODY): + case MAN_BODY: assert(MAN_BLOCK == p->parent->type); p->parent->body = p; break; @@ -220,9 +217,9 @@ man_node_append(struct man *man, struct man_node *p) man->last = p; switch (p->type) { - case (MAN_TBL): + case MAN_TBL: /* FALLTHROUGH */ - case (MAN_TEXT): + case MAN_TEXT: if ( ! man_valid_post(man)) return(0); break; @@ -233,9 +230,8 @@ man_node_append(struct man *man, struct man_node *p) return(1); } - static struct man_node * -man_node_alloc(struct man *man, int line, int pos, +man_node_alloc(struct man *man, int line, int pos, enum man_type type, enum mant tok) { struct man_node *p; @@ -252,7 +248,6 @@ man_node_alloc(struct man *man, int line, int pos, return(p); } - int man_elem_alloc(struct man *man, int line, int pos, enum mant tok) { @@ -265,7 +260,6 @@ man_elem_alloc(struct man *man, int line, int pos, enu return(1); } - int man_tail_alloc(struct man *man, int line, int pos, enum mant tok) { @@ -278,7 +272,6 @@ man_tail_alloc(struct man *man, int line, int pos, enu return(1); } - int man_head_alloc(struct man *man, int line, int pos, enum mant tok) { @@ -291,7 +284,6 @@ man_head_alloc(struct man *man, int line, int pos, enu return(1); } - int man_body_alloc(struct man *man, int line, int pos, enum mant tok) { @@ -304,7 +296,6 @@ man_body_alloc(struct man *man, int line, int pos, enu return(1); } - int man_block_alloc(struct man *man, int line, int pos, enum mant tok) { @@ -332,7 +323,6 @@ man_word_alloc(struct man *man, int line, int pos, con return(1); } - /* * Free all of the resources held by a node. This does NOT unlink a * node from its context; for that, see man_node_unlink(). @@ -346,7 +336,6 @@ man_node_free(struct man_node *p) free(p); } - void man_node_delete(struct man *man, struct man_node *p) { @@ -429,22 +418,28 @@ man_ptext(struct man *man, int line, char *buf, int of return(man_descope(man, line, offs)); } - /* Pump blank lines directly into the backend. */ - for (i = offs; ' ' == buf[i]; i++) /* Skip leading whitespace. */ ; + /* + * Blank lines are ignored right after headings + * but add a single vertical space elsewhere. + */ + if ('\0' == buf[i]) { /* Allocate a blank entry. */ - if ( ! man_elem_alloc(man, line, offs, MAN_sp)) - return(0); - man->next = MAN_NEXT_SIBLING; + if (MAN_SH != man->last->tok && + MAN_SS != man->last->tok) { + if ( ! man_elem_alloc(man, line, offs, MAN_sp)) + return(0); + man->next = MAN_NEXT_SIBLING; + } return(1); } - /* + /* * Warn if the last un-escaped character is whitespace. Then - * strip away the remaining spaces (tabs stay!). + * strip away the remaining spaces (tabs stay!). */ i = (int)strlen(buf); @@ -473,7 +468,7 @@ man_ptext(struct man *man, int line, char *buf, int of */ assert(i); - if (mandoc_eos(buf, (size_t)i, 0)) + if (mandoc_eos(buf, (size_t)i)) man->last->flags |= MAN_EOS; return(man_descope(man, line, offs)); @@ -501,8 +496,8 @@ man_pmacro(struct man *man, int ln, char *buf, int off */ i = 0; - while (i < 4 && '\0' != buf[offs] && - ' ' != buf[offs] && '\t' != buf[offs]) + while (i < 4 && '\0' != buf[offs] && ' ' != buf[offs] && + '\t' != buf[offs]) mac[i++] = buf[offs++]; mac[i] = '\0'; @@ -510,8 +505,8 @@ man_pmacro(struct man *man, int ln, char *buf, int off tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX; if (MAN_MAX == tok) { - mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln, - ppos, "%s", buf + ppos - 1); + mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln, ppos, + "%s", buf + ppos - 1); return(1); } @@ -520,7 +515,7 @@ man_pmacro(struct man *man, int ln, char *buf, int off while (buf[offs] && ' ' == buf[offs]) offs++; - /* + /* * Trailing whitespace. Note that tabs are allowed to be passed * into the parser as "text", so we only warn about spaces here. */ @@ -528,7 +523,7 @@ man_pmacro(struct man *man, int ln, char *buf, int off if ('\0' == buf[offs] && ' ' == buf[offs - 1]) man_pmsg(man, ln, offs - 1, MANDOCERR_EOLNSPACE); - /* + /* * Remove prior ELINE macro, as it's being clobbered by a new * macro. Note that NSCOPED macros do not close out ELINE * macros---they don't print text---so we let those slip by. @@ -544,7 +539,7 @@ man_pmacro(struct man *man, int ln, char *buf, int off if (MAN_NSCOPED & man_macros[n->tok].flags) n = n->parent; - mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, + mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, n->pos, "%s breaks %s", man_macronames[tok], man_macronames[n->tok]); @@ -575,7 +570,7 @@ man_pmacro(struct man *man, int ln, char *buf, int off assert(MAN_BLOCK == n->type); assert(MAN_SCOPED & man_macros[n->tok].flags); - mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, + mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, n->pos, "%s breaks %s", man_macronames[tok], man_macronames[n->tok]); @@ -598,13 +593,22 @@ man_pmacro(struct man *man, int ln, char *buf, int off if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf)) goto err; - /* + /* In quick mode (for mandocdb), abort after the NAME section. */ + + if (man->quick && MAN_SH == tok) { + n = man->last; + if (MAN_BODY == n->type && + strcmp(n->prev->child->string, "NAME")) + return(2); + } + + /* * We weren't in a block-line scope when entering the * above-parsed macro, so return. */ if ( ! (MAN_BPLINE & man->flags)) { - man->flags &= ~MAN_ILINE; + man->flags &= ~MAN_ILINE; return(1); } man->flags &= ~MAN_BPLINE; @@ -619,7 +623,7 @@ man_pmacro(struct man *man, int ln, char *buf, int off return(1); } - /* + /* * If we've opened a new next-line element scope, then return * now, as the next line will close out the block scope. */ @@ -689,4 +693,50 @@ man_mparse(const struct man *man) assert(man && man->parse); return(man->parse); +} + +void +man_deroff(char **dest, const struct man_node *n) +{ + char *cp; + size_t sz; + + if (MAN_TEXT != n->type) { + for (n = n->child; n; n = n->next) + man_deroff(dest, n); + return; + } + + /* Skip leading whitespace and escape sequences. */ + + cp = n->string; + while ('\0' != *cp) { + if ('\\' == *cp) { + cp++; + mandoc_escape((const char **)&cp, NULL, NULL); + } else if (isspace((unsigned char)*cp)) + cp++; + else + break; + } + + /* Skip trailing whitespace. */ + + for (sz = strlen(cp); sz; sz--) + if (0 == isspace((unsigned char)cp[sz-1])) + break; + + /* Skip empty strings. */ + + if (0 == sz) + return; + + if (NULL == *dest) { + *dest = mandoc_strndup(cp, sz); + return; + } + + mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp); + free(*dest); + *dest = cp; }