1*61d06d6bSBaptiste Daroussin /* $Id: demandoc.c,v 1.29 2017/06/24 14:38:32 schwarze Exp $ */ 2*61d06d6bSBaptiste Daroussin /* 3*61d06d6bSBaptiste Daroussin * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4*61d06d6bSBaptiste Daroussin * 5*61d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 6*61d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 7*61d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 8*61d06d6bSBaptiste Daroussin * 9*61d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*61d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*61d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*61d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*61d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*61d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*61d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*61d06d6bSBaptiste Daroussin */ 17*61d06d6bSBaptiste Daroussin #include "config.h" 18*61d06d6bSBaptiste Daroussin 19*61d06d6bSBaptiste Daroussin #include <sys/types.h> 20*61d06d6bSBaptiste Daroussin 21*61d06d6bSBaptiste Daroussin #include <assert.h> 22*61d06d6bSBaptiste Daroussin #include <ctype.h> 23*61d06d6bSBaptiste Daroussin #include <stdio.h> 24*61d06d6bSBaptiste Daroussin #include <stdlib.h> 25*61d06d6bSBaptiste Daroussin #include <string.h> 26*61d06d6bSBaptiste Daroussin #include <unistd.h> 27*61d06d6bSBaptiste Daroussin 28*61d06d6bSBaptiste Daroussin #include "mandoc.h" 29*61d06d6bSBaptiste Daroussin #include "roff.h" 30*61d06d6bSBaptiste Daroussin #include "man.h" 31*61d06d6bSBaptiste Daroussin #include "mdoc.h" 32*61d06d6bSBaptiste Daroussin 33*61d06d6bSBaptiste Daroussin static void pline(int, int *, int *, int); 34*61d06d6bSBaptiste Daroussin static void pman(const struct roff_node *, int *, int *, int); 35*61d06d6bSBaptiste Daroussin static void pmandoc(struct mparse *, int, const char *, int); 36*61d06d6bSBaptiste Daroussin static void pmdoc(const struct roff_node *, int *, int *, int); 37*61d06d6bSBaptiste Daroussin static void pstring(const char *, int, int *, int); 38*61d06d6bSBaptiste Daroussin static void usage(void); 39*61d06d6bSBaptiste Daroussin 40*61d06d6bSBaptiste Daroussin static const char *progname; 41*61d06d6bSBaptiste Daroussin 42*61d06d6bSBaptiste Daroussin int 43*61d06d6bSBaptiste Daroussin main(int argc, char *argv[]) 44*61d06d6bSBaptiste Daroussin { 45*61d06d6bSBaptiste Daroussin struct mparse *mp; 46*61d06d6bSBaptiste Daroussin int ch, fd, i, list; 47*61d06d6bSBaptiste Daroussin extern int optind; 48*61d06d6bSBaptiste Daroussin 49*61d06d6bSBaptiste Daroussin if (argc < 1) 50*61d06d6bSBaptiste Daroussin progname = "demandoc"; 51*61d06d6bSBaptiste Daroussin else if ((progname = strrchr(argv[0], '/')) == NULL) 52*61d06d6bSBaptiste Daroussin progname = argv[0]; 53*61d06d6bSBaptiste Daroussin else 54*61d06d6bSBaptiste Daroussin ++progname; 55*61d06d6bSBaptiste Daroussin 56*61d06d6bSBaptiste Daroussin mp = NULL; 57*61d06d6bSBaptiste Daroussin list = 0; 58*61d06d6bSBaptiste Daroussin 59*61d06d6bSBaptiste Daroussin while (-1 != (ch = getopt(argc, argv, "ikm:pw"))) 60*61d06d6bSBaptiste Daroussin switch (ch) { 61*61d06d6bSBaptiste Daroussin case ('i'): 62*61d06d6bSBaptiste Daroussin /* FALLTHROUGH */ 63*61d06d6bSBaptiste Daroussin case ('k'): 64*61d06d6bSBaptiste Daroussin /* FALLTHROUGH */ 65*61d06d6bSBaptiste Daroussin case ('m'): 66*61d06d6bSBaptiste Daroussin /* FALLTHROUGH */ 67*61d06d6bSBaptiste Daroussin case ('p'): 68*61d06d6bSBaptiste Daroussin break; 69*61d06d6bSBaptiste Daroussin case ('w'): 70*61d06d6bSBaptiste Daroussin list = 1; 71*61d06d6bSBaptiste Daroussin break; 72*61d06d6bSBaptiste Daroussin default: 73*61d06d6bSBaptiste Daroussin usage(); 74*61d06d6bSBaptiste Daroussin return (int)MANDOCLEVEL_BADARG; 75*61d06d6bSBaptiste Daroussin } 76*61d06d6bSBaptiste Daroussin 77*61d06d6bSBaptiste Daroussin argc -= optind; 78*61d06d6bSBaptiste Daroussin argv += optind; 79*61d06d6bSBaptiste Daroussin 80*61d06d6bSBaptiste Daroussin mchars_alloc(); 81*61d06d6bSBaptiste Daroussin mp = mparse_alloc(MPARSE_SO, MANDOCERR_MAX, NULL, 82*61d06d6bSBaptiste Daroussin MANDOC_OS_OTHER, NULL); 83*61d06d6bSBaptiste Daroussin assert(mp); 84*61d06d6bSBaptiste Daroussin 85*61d06d6bSBaptiste Daroussin if (argc < 1) 86*61d06d6bSBaptiste Daroussin pmandoc(mp, STDIN_FILENO, "<stdin>", list); 87*61d06d6bSBaptiste Daroussin 88*61d06d6bSBaptiste Daroussin for (i = 0; i < argc; i++) { 89*61d06d6bSBaptiste Daroussin mparse_reset(mp); 90*61d06d6bSBaptiste Daroussin if ((fd = mparse_open(mp, argv[i])) == -1) { 91*61d06d6bSBaptiste Daroussin perror(argv[i]); 92*61d06d6bSBaptiste Daroussin continue; 93*61d06d6bSBaptiste Daroussin } 94*61d06d6bSBaptiste Daroussin pmandoc(mp, fd, argv[i], list); 95*61d06d6bSBaptiste Daroussin } 96*61d06d6bSBaptiste Daroussin 97*61d06d6bSBaptiste Daroussin mparse_free(mp); 98*61d06d6bSBaptiste Daroussin mchars_free(); 99*61d06d6bSBaptiste Daroussin return (int)MANDOCLEVEL_OK; 100*61d06d6bSBaptiste Daroussin } 101*61d06d6bSBaptiste Daroussin 102*61d06d6bSBaptiste Daroussin static void 103*61d06d6bSBaptiste Daroussin usage(void) 104*61d06d6bSBaptiste Daroussin { 105*61d06d6bSBaptiste Daroussin 106*61d06d6bSBaptiste Daroussin fprintf(stderr, "usage: %s [-w] [files...]\n", progname); 107*61d06d6bSBaptiste Daroussin } 108*61d06d6bSBaptiste Daroussin 109*61d06d6bSBaptiste Daroussin static void 110*61d06d6bSBaptiste Daroussin pmandoc(struct mparse *mp, int fd, const char *fn, int list) 111*61d06d6bSBaptiste Daroussin { 112*61d06d6bSBaptiste Daroussin struct roff_man *man; 113*61d06d6bSBaptiste Daroussin int line, col; 114*61d06d6bSBaptiste Daroussin 115*61d06d6bSBaptiste Daroussin mparse_readfd(mp, fd, fn); 116*61d06d6bSBaptiste Daroussin close(fd); 117*61d06d6bSBaptiste Daroussin mparse_result(mp, &man, NULL); 118*61d06d6bSBaptiste Daroussin line = 1; 119*61d06d6bSBaptiste Daroussin col = 0; 120*61d06d6bSBaptiste Daroussin 121*61d06d6bSBaptiste Daroussin if (man == NULL) 122*61d06d6bSBaptiste Daroussin return; 123*61d06d6bSBaptiste Daroussin if (man->macroset == MACROSET_MDOC) { 124*61d06d6bSBaptiste Daroussin mdoc_validate(man); 125*61d06d6bSBaptiste Daroussin pmdoc(man->first->child, &line, &col, list); 126*61d06d6bSBaptiste Daroussin } else { 127*61d06d6bSBaptiste Daroussin man_validate(man); 128*61d06d6bSBaptiste Daroussin pman(man->first->child, &line, &col, list); 129*61d06d6bSBaptiste Daroussin } 130*61d06d6bSBaptiste Daroussin 131*61d06d6bSBaptiste Daroussin if ( ! list) 132*61d06d6bSBaptiste Daroussin putchar('\n'); 133*61d06d6bSBaptiste Daroussin } 134*61d06d6bSBaptiste Daroussin 135*61d06d6bSBaptiste Daroussin /* 136*61d06d6bSBaptiste Daroussin * Strip the escapes out of a string, emitting the results. 137*61d06d6bSBaptiste Daroussin */ 138*61d06d6bSBaptiste Daroussin static void 139*61d06d6bSBaptiste Daroussin pstring(const char *p, int col, int *colp, int list) 140*61d06d6bSBaptiste Daroussin { 141*61d06d6bSBaptiste Daroussin enum mandoc_esc esc; 142*61d06d6bSBaptiste Daroussin const char *start, *end; 143*61d06d6bSBaptiste Daroussin int emit; 144*61d06d6bSBaptiste Daroussin 145*61d06d6bSBaptiste Daroussin /* 146*61d06d6bSBaptiste Daroussin * Print as many column spaces til we achieve parity with the 147*61d06d6bSBaptiste Daroussin * input document. 148*61d06d6bSBaptiste Daroussin */ 149*61d06d6bSBaptiste Daroussin 150*61d06d6bSBaptiste Daroussin again: 151*61d06d6bSBaptiste Daroussin if (list && '\0' != *p) { 152*61d06d6bSBaptiste Daroussin while (isspace((unsigned char)*p)) 153*61d06d6bSBaptiste Daroussin p++; 154*61d06d6bSBaptiste Daroussin 155*61d06d6bSBaptiste Daroussin while ('\'' == *p || '(' == *p || '"' == *p) 156*61d06d6bSBaptiste Daroussin p++; 157*61d06d6bSBaptiste Daroussin 158*61d06d6bSBaptiste Daroussin emit = isalpha((unsigned char)p[0]) && 159*61d06d6bSBaptiste Daroussin isalpha((unsigned char)p[1]); 160*61d06d6bSBaptiste Daroussin 161*61d06d6bSBaptiste Daroussin for (start = p; '\0' != *p; p++) 162*61d06d6bSBaptiste Daroussin if ('\\' == *p) { 163*61d06d6bSBaptiste Daroussin p++; 164*61d06d6bSBaptiste Daroussin esc = mandoc_escape(&p, NULL, NULL); 165*61d06d6bSBaptiste Daroussin if (ESCAPE_ERROR == esc) 166*61d06d6bSBaptiste Daroussin return; 167*61d06d6bSBaptiste Daroussin emit = 0; 168*61d06d6bSBaptiste Daroussin } else if (isspace((unsigned char)*p)) 169*61d06d6bSBaptiste Daroussin break; 170*61d06d6bSBaptiste Daroussin 171*61d06d6bSBaptiste Daroussin end = p - 1; 172*61d06d6bSBaptiste Daroussin 173*61d06d6bSBaptiste Daroussin while (end > start) 174*61d06d6bSBaptiste Daroussin if ('.' == *end || ',' == *end || 175*61d06d6bSBaptiste Daroussin '\'' == *end || '"' == *end || 176*61d06d6bSBaptiste Daroussin ')' == *end || '!' == *end || 177*61d06d6bSBaptiste Daroussin '?' == *end || ':' == *end || 178*61d06d6bSBaptiste Daroussin ';' == *end) 179*61d06d6bSBaptiste Daroussin end--; 180*61d06d6bSBaptiste Daroussin else 181*61d06d6bSBaptiste Daroussin break; 182*61d06d6bSBaptiste Daroussin 183*61d06d6bSBaptiste Daroussin if (emit && end - start >= 1) { 184*61d06d6bSBaptiste Daroussin for ( ; start <= end; start++) 185*61d06d6bSBaptiste Daroussin if (ASCII_HYPH == *start) 186*61d06d6bSBaptiste Daroussin putchar('-'); 187*61d06d6bSBaptiste Daroussin else 188*61d06d6bSBaptiste Daroussin putchar((unsigned char)*start); 189*61d06d6bSBaptiste Daroussin putchar('\n'); 190*61d06d6bSBaptiste Daroussin } 191*61d06d6bSBaptiste Daroussin 192*61d06d6bSBaptiste Daroussin if (isspace((unsigned char)*p)) 193*61d06d6bSBaptiste Daroussin goto again; 194*61d06d6bSBaptiste Daroussin 195*61d06d6bSBaptiste Daroussin return; 196*61d06d6bSBaptiste Daroussin } 197*61d06d6bSBaptiste Daroussin 198*61d06d6bSBaptiste Daroussin while (*colp < col) { 199*61d06d6bSBaptiste Daroussin putchar(' '); 200*61d06d6bSBaptiste Daroussin (*colp)++; 201*61d06d6bSBaptiste Daroussin } 202*61d06d6bSBaptiste Daroussin 203*61d06d6bSBaptiste Daroussin /* 204*61d06d6bSBaptiste Daroussin * Print the input word, skipping any special characters. 205*61d06d6bSBaptiste Daroussin */ 206*61d06d6bSBaptiste Daroussin while ('\0' != *p) 207*61d06d6bSBaptiste Daroussin if ('\\' == *p) { 208*61d06d6bSBaptiste Daroussin p++; 209*61d06d6bSBaptiste Daroussin esc = mandoc_escape(&p, NULL, NULL); 210*61d06d6bSBaptiste Daroussin if (ESCAPE_ERROR == esc) 211*61d06d6bSBaptiste Daroussin break; 212*61d06d6bSBaptiste Daroussin } else { 213*61d06d6bSBaptiste Daroussin putchar((unsigned char )*p++); 214*61d06d6bSBaptiste Daroussin (*colp)++; 215*61d06d6bSBaptiste Daroussin } 216*61d06d6bSBaptiste Daroussin } 217*61d06d6bSBaptiste Daroussin 218*61d06d6bSBaptiste Daroussin static void 219*61d06d6bSBaptiste Daroussin pline(int line, int *linep, int *col, int list) 220*61d06d6bSBaptiste Daroussin { 221*61d06d6bSBaptiste Daroussin 222*61d06d6bSBaptiste Daroussin if (list) 223*61d06d6bSBaptiste Daroussin return; 224*61d06d6bSBaptiste Daroussin 225*61d06d6bSBaptiste Daroussin /* 226*61d06d6bSBaptiste Daroussin * Print out as many lines as needed to reach parity with the 227*61d06d6bSBaptiste Daroussin * original input. 228*61d06d6bSBaptiste Daroussin */ 229*61d06d6bSBaptiste Daroussin 230*61d06d6bSBaptiste Daroussin while (*linep < line) { 231*61d06d6bSBaptiste Daroussin putchar('\n'); 232*61d06d6bSBaptiste Daroussin (*linep)++; 233*61d06d6bSBaptiste Daroussin } 234*61d06d6bSBaptiste Daroussin 235*61d06d6bSBaptiste Daroussin *col = 0; 236*61d06d6bSBaptiste Daroussin } 237*61d06d6bSBaptiste Daroussin 238*61d06d6bSBaptiste Daroussin static void 239*61d06d6bSBaptiste Daroussin pmdoc(const struct roff_node *p, int *line, int *col, int list) 240*61d06d6bSBaptiste Daroussin { 241*61d06d6bSBaptiste Daroussin 242*61d06d6bSBaptiste Daroussin for ( ; p; p = p->next) { 243*61d06d6bSBaptiste Daroussin if (NODE_LINE & p->flags) 244*61d06d6bSBaptiste Daroussin pline(p->line, line, col, list); 245*61d06d6bSBaptiste Daroussin if (ROFFT_TEXT == p->type) 246*61d06d6bSBaptiste Daroussin pstring(p->string, p->pos, col, list); 247*61d06d6bSBaptiste Daroussin if (p->child) 248*61d06d6bSBaptiste Daroussin pmdoc(p->child, line, col, list); 249*61d06d6bSBaptiste Daroussin } 250*61d06d6bSBaptiste Daroussin } 251*61d06d6bSBaptiste Daroussin 252*61d06d6bSBaptiste Daroussin static void 253*61d06d6bSBaptiste Daroussin pman(const struct roff_node *p, int *line, int *col, int list) 254*61d06d6bSBaptiste Daroussin { 255*61d06d6bSBaptiste Daroussin 256*61d06d6bSBaptiste Daroussin for ( ; p; p = p->next) { 257*61d06d6bSBaptiste Daroussin if (NODE_LINE & p->flags) 258*61d06d6bSBaptiste Daroussin pline(p->line, line, col, list); 259*61d06d6bSBaptiste Daroussin if (ROFFT_TEXT == p->type) 260*61d06d6bSBaptiste Daroussin pstring(p->string, p->pos, col, list); 261*61d06d6bSBaptiste Daroussin if (p->child) 262*61d06d6bSBaptiste Daroussin pman(p->child, line, col, list); 263*61d06d6bSBaptiste Daroussin } 264*61d06d6bSBaptiste Daroussin } 265