=================================================================== RCS file: /cvs/mandoc/demandoc.c,v retrieving revision 1.3 retrieving revision 1.13 diff -u -p -r1.3 -r1.13 --- mandoc/demandoc.c 2011/09/01 10:49:13 1.3 +++ mandoc/demandoc.c 2015/01/15 04:26:39 1.13 @@ -1,4 +1,4 @@ -/* $Id: demandoc.c,v 1.3 2011/09/01 10:49:13 kristaps Exp $ */ +/* $Id: demandoc.c,v 1.13 2015/01/15 04:26:39 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -14,11 +14,12 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif +#include + #include +#include #include #include #include @@ -29,11 +30,11 @@ #include "mdoc.h" #include "mandoc.h" -static void pline(int, int *, int *); -static void pman(const struct man_node *, int *, int *); -static void pmandoc(struct mparse *, int, const char *); -static void pmdoc(const struct mdoc_node *, int *, int *); -static void pstring(const char *, int, int *); +static void pline(int, int *, int *, int); +static void pman(const struct man_node *, int *, int *, int); +static void pmandoc(struct mparse *, int, const char *, int); +static void pmdoc(const struct mdoc_node *, int *, int *, int); +static void pstring(const char *, int, int *, int); static void usage(void); static const char *progname; @@ -42,7 +43,8 @@ int main(int argc, char *argv[]) { struct mparse *mp; - int ch, i; + struct mchars *mchars; + int ch, fd, i, list; extern int optind; progname = strrchr(argv[0], '/'); @@ -52,9 +54,21 @@ main(int argc, char *argv[]) ++progname; mp = NULL; + list = 0; - while (-1 != (ch = getopt(argc, argv, ""))) + while (-1 != (ch = getopt(argc, argv, "ikm:pw"))) switch (ch) { + case ('i'): + /* FALLTHROUGH */ + case ('k'): + /* FALLTHROUGH */ + case ('m'): + /* FALLTHROUGH */ + case ('p'): + break; + case ('w'): + list = 1; + break; default: usage(); return((int)MANDOCLEVEL_BADARG); @@ -63,18 +77,24 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL); + mchars = mchars_alloc(); + mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, mchars, NULL); assert(mp); if (0 == argc) - pmandoc(mp, STDIN_FILENO, ""); + pmandoc(mp, STDIN_FILENO, "", list); for (i = 0; i < argc; i++) { mparse_reset(mp); - pmandoc(mp, -1, argv[i]); + if (mparse_open(mp, &fd, argv[i]) != MANDOCLEVEL_OK) { + perror(argv[i]); + continue; + } + pmandoc(mp, fd, argv[i], list); } mparse_free(mp); + mchars_free(mchars); return((int)MANDOCLEVEL_OK); } @@ -82,99 +102,159 @@ static void usage(void) { - fprintf(stderr, "usage: %s [files...]\n", progname); + fprintf(stderr, "usage: %s [-w] [files...]\n", progname); } static void -pmandoc(struct mparse *mp, int fd, const char *fn) +pmandoc(struct mparse *mp, int fd, const char *fn, int list) { struct mdoc *mdoc; struct man *man; int line, col; - if (mparse_readfd(mp, fd, fn) >= MANDOCLEVEL_FATAL) { - fprintf(stderr, "%s: Parse failure\n", fn); - return; - } - - mparse_result(mp, &mdoc, &man); + mparse_readfd(mp, fd, fn); + mparse_result(mp, &mdoc, &man, NULL); line = 1; col = 0; if (mdoc) - pmdoc(mdoc_node(mdoc), &line, &col); + pmdoc(mdoc_node(mdoc), &line, &col, list); else if (man) - pman(man_node(man), &line, &col); + pman(man_node(man), &line, &col, list); else return; - putchar('\n'); + if ( ! list) + putchar('\n'); } /* * Strip the escapes out of a string, emitting the results. */ static void -pstring(const char *p, int col, int *colp) +pstring(const char *p, int col, int *colp, int list) { enum mandoc_esc esc; + const char *start, *end; + int emit; + /* + * Print as many column spaces til we achieve parity with the + * input document. + */ + +again: + if (list && '\0' != *p) { + while (isspace((unsigned char)*p)) + p++; + + while ('\'' == *p || '(' == *p || '"' == *p) + p++; + + emit = isalpha((unsigned char)p[0]) && + isalpha((unsigned char)p[1]); + + for (start = p; '\0' != *p; p++) + if ('\\' == *p) { + p++; + esc = mandoc_escape(&p, NULL, NULL); + if (ESCAPE_ERROR == esc) + return; + emit = 0; + } else if (isspace((unsigned char)*p)) + break; + + end = p - 1; + + while (end > start) + if ('.' == *end || ',' == *end || + '\'' == *end || '"' == *end || + ')' == *end || '!' == *end || + '?' == *end || ':' == *end || + ';' == *end) + end--; + else + break; + + if (emit && end - start >= 1) { + for ( ; start <= end; start++) + if (ASCII_HYPH == *start) + putchar('-'); + else + putchar((unsigned char)*start); + putchar('\n'); + } + + if (isspace((unsigned char)*p)) + goto again; + + return; + } + while (*colp < col) { putchar(' '); (*colp)++; } - while ('\0' != *p) { + /* + * Print the input word, skipping any special characters. + */ + while ('\0' != *p) if ('\\' == *p) { p++; esc = mandoc_escape(&p, NULL, NULL); if (ESCAPE_ERROR == esc) - return; + break; } else { putchar((unsigned char )*p++); (*colp)++; } - } } -/* - * Emit lines until we're in sync with our input. - */ static void -pline(int line, int *linep, int *col) +pline(int line, int *linep, int *col, int list) { + if (list) + return; + + /* + * Print out as many lines as needed to reach parity with the + * original input. + */ + while (*linep < line) { putchar('\n'); (*linep)++; } + *col = 0; } static void -pmdoc(const struct mdoc_node *p, int *line, int *col) +pmdoc(const struct mdoc_node *p, int *line, int *col, int list) { for ( ; p; p = p->next) { if (MDOC_LINE & p->flags) - pline(p->line, line, col); + pline(p->line, line, col, list); if (MDOC_TEXT == p->type) - pstring(p->string, p->pos, col); + pstring(p->string, p->pos, col, list); if (p->child) - pmdoc(p->child, line, col); + pmdoc(p->child, line, col, list); } } static void -pman(const struct man_node *p, int *line, int *col) +pman(const struct man_node *p, int *line, int *col, int list) { for ( ; p; p = p->next) { if (MAN_LINE & p->flags) - pline(p->line, line, col); + pline(p->line, line, col, list); if (MAN_TEXT == p->type) - pstring(p->string, p->pos, col); + pstring(p->string, p->pos, col, list); if (p->child) - pman(p->child, line, col); + pman(p->child, line, col, list); } }