=================================================================== RCS file: /cvs/mandoc/demandoc.c,v retrieving revision 1.2 retrieving revision 1.21 diff -u -p -r1.2 -r1.21 --- mandoc/demandoc.c 2011/09/01 10:47:47 1.2 +++ mandoc/demandoc.c 2015/10/06 18:32:19 1.21 @@ -1,4 +1,4 @@ -/* $Id: demandoc.c,v 1.2 2011/09/01 10:47:47 kristaps Exp $ */ +/* $Id: demandoc.c,v 1.21 2015/10/06 18:32:19 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -14,26 +14,28 @@ * 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 #include #include +#include "roff.h" #include "man.h" #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 roff_node *, int *, int *, int); +static void pmandoc(struct mparse *, int, const char *, int); +static void pmdoc(const struct roff_node *, int *, int *, int); +static void pstring(const char *, int, int *, int); static void usage(void); static const char *progname; @@ -42,140 +44,218 @@ int main(int argc, char *argv[]) { struct mparse *mp; - int ch, i; + struct mchars *mchars; + int ch, fd, i, list; extern int optind; - extern char *optarg; - progname = strrchr(argv[0], '/'); - if (progname == NULL) + if (argc < 1) + progname = "demandoc"; + else if ((progname = strrchr(argv[0], '/')) == NULL) progname = argv[0]; else ++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); + return (int)MANDOCLEVEL_BADARG; } 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, ""); + if (argc < 1) + 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); - return(MANDOCLEVEL_OK); + mchars_free(mchars); + return (int)MANDOCLEVEL_OK; } 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; + struct roff_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, &man, NULL); line = 1; col = 0; - if (mdoc) - pmdoc(mdoc_node(mdoc), &line, &col); - else if (man) - pman(man_node(man), &line, &col); - else + if (man == NULL) return; + if (man->macroset == MACROSET_MDOC) + pmdoc(man->first->child, &line, &col, list); + else + pman(man->first->child, &line, &col, list); - 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(*p++); + 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 roff_node *p, int *line, int *col, int list) { for ( ; p; p = p->next) { if (MDOC_LINE & p->flags) - pline(p->line, line, col); - if (MDOC_TEXT == p->type) - pstring(p->string, p->pos, col); - if (p->child) - pmdoc(p->child, line, col); + pline(p->line, line, col, list); + if (ROFFT_TEXT == p->type) + pstring(p->string, p->pos, col, list); + if (p->child) + pmdoc(p->child, line, col, list); } } static void -pman(const struct man_node *p, int *line, int *col) +pman(const struct roff_node *p, int *line, int *col, int list) { for ( ; p; p = p->next) { if (MAN_LINE & p->flags) - pline(p->line, line, col); - if (MAN_TEXT == p->type) - pstring(p->string, p->pos, col); - if (p->child) - pman(p->child, line, col); + pline(p->line, line, col, list); + if (ROFFT_TEXT == p->type) + pstring(p->string, p->pos, col, list); + if (p->child) + pman(p->child, line, col, list); } }