[BACK]Return to mdocml.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/mdocml.c, Revision 1.47

1.47    ! kristaps    1: /* $Id: mdocml.c,v 1.46 2009/01/16 14:15:12 kristaps Exp $ */
1.1       kristaps    2: /*
                      3:  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the
                      7:  * above copyright notice and this permission notice appear in all
                      8:  * copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
                     11:  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
                     12:  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
                     13:  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                     16:  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     17:  * PERFORMANCE OF THIS SOFTWARE.
                     18:  */
1.21      kristaps   19: #include <sys/stat.h>
1.1       kristaps   20: #include <sys/param.h>
                     21:
                     22: #include <assert.h>
1.21      kristaps   23: #include <fcntl.h>
1.1       kristaps   24: #include <err.h>
                     25: #include <getopt.h>
                     26: #include <stdio.h>
                     27: #include <stdlib.h>
                     28: #include <string.h>
                     29: #include <unistd.h>
                     30:
1.21      kristaps   31: #include "mdoc.h"
1.1       kristaps   32:
1.44      kristaps   33: #define        xfprintf        (void)fprintf
                     34: #define        xprintf         (void)printf
                     35: #define        xvfprintf       (void)fvprintf
                     36:
                     37: #define        MD_LINE_SZ      (256)           /* Max input line size. */
1.2       kristaps   38:
1.47    ! kristaps   39:
1.21      kristaps   40: struct md_parse {
1.47    ! kristaps   41:        int               warn;         /* Warning flags. */
        !            42: #define        MD_WARN_SYNTAX   (1 << 0)       /* Show syntax warnings. */
        !            43: #define        MD_WARN_COMPAT   (1 << 1)       /* Show compat warnings. */
        !            44: #define        MD_WARN_ALL      (0x03)         /* Show all warnings. */
        !            45: #define        MD_WARN_ERR      (1 << 2)       /* Make warnings->errors. */
        !            46:        int               dbg;          /* Debug level. */
        !            47:        struct mdoc      *mdoc;         /* Active parser. */
        !            48:        char             *buf;          /* Input buffer. */
        !            49:        u_long            bufsz;        /* Input buffer size. */
        !            50:        char             *name;         /* Input file name. */
        !            51:        int               fd;           /* Input file desc. */
        !            52:        int             (*fp)(const struct mdoc_node *, const char *);
1.21      kristaps   53: };
1.17      kristaps   54:
1.47    ! kristaps   55: extern char             *__progname;
        !            56:
        !            57: extern int
1.44      kristaps   58:
1.47    ! kristaps   59: static void              usage(void);
1.9       kristaps   60:
1.47    ! kristaps   61: static int               parse_begin(struct md_parse *);
        !            62: static int               parse_leave(struct md_parse *, int);
        !            63: static int               io_begin(struct md_parse *);
        !            64: static int               io_leave(struct md_parse *, int);
        !            65: static int               buf_begin(struct md_parse *);
        !            66: static int               buf_leave(struct md_parse *, int);
        !            67:
        !            68: static void              msg_msg(void *, int, int, const char *);
        !            69: static int               msg_err(void *, int, int, const char *);
        !            70: static int               msg_warn(void *, int, int,
1.44      kristaps   71:                                enum mdoc_warn, const char *);
1.1       kristaps   72:
1.19      kristaps   73: #ifdef __linux__
1.47    ! kristaps   74: extern int               getsubopt(char **, char *const *, char **);
1.19      kristaps   75: #endif
                     76:
1.1       kristaps   77: int
                     78: main(int argc, char *argv[])
                     79: {
                     80:        int              c;
1.21      kristaps   81:        struct md_parse  parser;
1.47    ! kristaps   82:        char            *opts, *v, *filter, *output;
1.18      kristaps   83: #define ALL             0
1.44      kristaps   84: #define COMPAT          1
                     85: #define SYNTAX          2
                     86: #define ERROR           3
                     87:        char            *toks[] = { "all", "compat", "syntax",
                     88:                                    "error", NULL };
1.1       kristaps   89:
                     90:        extern char     *optarg;
                     91:        extern int       optind;
                     92:
1.47    ! kristaps   93:        output = filter = NULL;
        !            94:
1.21      kristaps   95:        (void)memset(&parser, 0, sizeof(struct md_parse));
1.17      kristaps   96:
1.47    ! kristaps   97:        while (-1 != (c = getopt(argc, argv, "f:vW:o:")))
1.1       kristaps   98:                switch (c) {
1.47    ! kristaps   99:                case ('f'):
        !           100:                        filter = optarg;
        !           101:                        break;
        !           102:                case ('o'):
        !           103:                        output = optarg;
        !           104:                        break;
1.13      kristaps  105:                case ('v'):
1.21      kristaps  106:                        parser.dbg++;
1.13      kristaps  107:                        break;
                    108:                case ('W'):
1.18      kristaps  109:                        opts = optarg;
                    110:                        while (*opts)
                    111:                                switch (getsubopt(&opts, toks, &v)) {
                    112:                                case (ALL):
1.21      kristaps  113:                                        parser.warn |= MD_WARN_ALL;
1.18      kristaps  114:                                        break;
1.44      kristaps  115:                                case (COMPAT):
                    116:                                        parser.warn |= MD_WARN_COMPAT;
                    117:                                        break;
                    118:                                case (SYNTAX):
                    119:                                        parser.warn |= MD_WARN_SYNTAX;
                    120:                                        break;
1.18      kristaps  121:                                case (ERROR):
1.21      kristaps  122:                                        parser.warn |= MD_WARN_ERR;
1.18      kristaps  123:                                        break;
                    124:                                default:
                    125:                                        usage();
                    126:                                        return(1);
                    127:                                }
1.13      kristaps  128:                        break;
1.1       kristaps  129:                default:
                    130:                        usage();
                    131:                        return(1);
                    132:                }
                    133:
                    134:        argv += optind;
1.4       kristaps  135:        argc -= optind;
1.1       kristaps  136:
1.21      kristaps  137:        parser.name = "-";
1.4       kristaps  138:        if (1 == argc)
1.21      kristaps  139:                parser.name = *argv++;
                    140:
                    141:        if ( ! io_begin(&parser))
                    142:                return(EXIT_FAILURE);
1.1       kristaps  143:
1.21      kristaps  144:        return(EXIT_SUCCESS);
1.1       kristaps  145: }
                    146:
                    147:
                    148: static int
1.21      kristaps  149: io_leave(struct md_parse *p, int code)
1.1       kristaps  150: {
                    151:
1.21      kristaps  152:        if (-1 == p->fd || STDIN_FILENO == p->fd)
                    153:                return(code);
                    154:
                    155:        if (-1 == close(p->fd)) {
                    156:                warn("%s", p->name);
                    157:                code = 0;
1.4       kristaps  158:        }
1.21      kristaps  159:        return(code);
                    160: }
                    161:
                    162:
                    163: static int
                    164: io_begin(struct md_parse *p)
                    165: {
                    166:
                    167:        p->fd = STDIN_FILENO;
                    168:        if (0 != strncmp(p->name, "-", 1))
                    169:                if (-1 == (p->fd = open(p->name, O_RDONLY, 0))) {
                    170:                        warn("%s", p->name);
                    171:                        return(io_leave(p, 0));
                    172:                }
1.1       kristaps  173:
1.21      kristaps  174:        return(io_leave(p, buf_begin(p)));
1.1       kristaps  175: }
                    176:
                    177:
                    178: static int
1.21      kristaps  179: buf_leave(struct md_parse *p, int code)
1.1       kristaps  180: {
1.4       kristaps  181:
1.21      kristaps  182:        if (p->buf)
                    183:                free(p->buf);
                    184:        return(code);
                    185: }
1.1       kristaps  186:
                    187:
1.21      kristaps  188: static int
                    189: buf_begin(struct md_parse *p)
                    190: {
                    191:        struct stat      st;
1.1       kristaps  192:
1.21      kristaps  193:        if (-1 == fstat(p->fd, &st)) {
                    194:                warn("%s", p->name);
                    195:                return(1);
                    196:        }
                    197:
                    198:        p->bufsz = MAX(st.st_blksize, BUFSIZ);
                    199:
                    200:        if (NULL == (p->buf = malloc(p->bufsz))) {
                    201:                warn("malloc");
                    202:                return(buf_leave(p, 0));
                    203:        }
                    204:
                    205:        return(buf_leave(p, parse_begin(p)));
                    206: }
                    207:
                    208:
                    209: static int
                    210: parse_leave(struct md_parse *p, int code)
                    211: {
                    212:        const struct mdoc_node *n;
                    213:
1.36      kristaps  214:        if (NULL == p->mdoc)
                    215:                return(code);
                    216:
                    217:        if ( ! mdoc_endparse(p->mdoc))
                    218:                code = 0;
1.47    ! kristaps  219:        if (p->fp && (n = mdoc_result(p->mdoc)))
        !           220:                (*p->fp)(n, NULL);
1.36      kristaps  221:
1.38      kristaps  222:        mdoc_free(p->mdoc);
                    223:
1.21      kristaps  224:        return(code);
                    225: }
                    226:
                    227:
                    228: static int
                    229: parse_begin(struct md_parse *p)
                    230: {
                    231:        ssize_t          sz, i;
                    232:        size_t           pos;
1.44      kristaps  233:        char             line[MD_LINE_SZ];
1.21      kristaps  234:        struct mdoc_cb   cb;
1.43      kristaps  235:        int              lnn;
1.21      kristaps  236:
                    237:        cb.mdoc_err = msg_err;
                    238:        cb.mdoc_warn = msg_warn;
                    239:        cb.mdoc_msg = msg_msg;
                    240:
                    241:        if (NULL == (p->mdoc = mdoc_alloc(p, &cb)))
                    242:                return(parse_leave(p, 0));
                    243:
1.43      kristaps  244:        for (lnn = 1, pos = 0; ; ) {
1.21      kristaps  245:                if (-1 == (sz = read(p->fd, p->buf, p->bufsz))) {
                    246:                        warn("%s", p->name);
                    247:                        return(parse_leave(p, 0));
                    248:                } else if (0 == sz)
                    249:                        break;
                    250:
                    251:                for (i = 0; i < sz; i++) {
                    252:                        if ('\n' != p->buf[i]) {
                    253:                                if (pos < sizeof(line)) {
1.44      kristaps  254:                                        line[(int)pos++] = p->buf[(int)i];
1.21      kristaps  255:                                        continue;
                    256:                                }
                    257:                                warnx("%s: line %d too long",
1.43      kristaps  258:                                                p->name, lnn);
1.21      kristaps  259:                                return(parse_leave(p, 0));
                    260:                        }
                    261:
1.44      kristaps  262:                        line[(int)pos] = 0;
1.43      kristaps  263:                        if ( ! mdoc_parseln(p->mdoc, lnn, line))
1.21      kristaps  264:                                return(parse_leave(p, 0));
1.1       kristaps  265:
1.43      kristaps  266:                        lnn++;
1.21      kristaps  267:                        pos = 0;
1.4       kristaps  268:                }
1.21      kristaps  269:        }
1.1       kristaps  270:
1.21      kristaps  271:        return(parse_leave(p, 1));
1.4       kristaps  272: }
1.1       kristaps  273:
                    274:
1.4       kristaps  275: static int
1.44      kristaps  276: msg_err(void *arg, int line, int col, const char *msg)
1.21      kristaps  277: {
                    278:        struct md_parse  *p;
                    279:
                    280:        p = (struct md_parse *)arg;
                    281:
1.45      kristaps  282:        xfprintf(stderr, "%s:%d: error: %s (column %d)\n",
1.44      kristaps  283:                        p->name, line, msg, col);
1.21      kristaps  284:        return(0);
                    285: }
                    286:
                    287:
                    288: static void
1.37      kristaps  289: msg_msg(void *arg, int line, int col, const char *msg)
1.4       kristaps  290: {
1.21      kristaps  291:        struct md_parse  *p;
                    292:
                    293:        p = (struct md_parse *)arg;
                    294:
1.44      kristaps  295:        if (0 == p->dbg)
1.21      kristaps  296:                return;
                    297:
1.45      kristaps  298:        xfprintf(stderr, "%s:%d: debug: %s (column %d)\n",
1.39      kristaps  299:                        p->name, line, msg, col);
1.1       kristaps  300: }
                    301:
                    302:
                    303: static int
1.44      kristaps  304: msg_warn(void *arg, int line, int col,
                    305:                enum mdoc_warn type, const char *msg)
1.1       kristaps  306: {
1.21      kristaps  307:        struct md_parse  *p;
1.1       kristaps  308:
1.21      kristaps  309:        p = (struct md_parse *)arg;
1.1       kristaps  310:
1.44      kristaps  311:        switch (type) {
                    312:        case (WARN_COMPAT):
                    313:                if (p->warn & MD_WARN_COMPAT)
                    314:                        break;
                    315:                return(1);
                    316:        case (WARN_SYNTAX):
                    317:                if (p->warn & MD_WARN_SYNTAX)
                    318:                        break;
1.1       kristaps  319:                return(1);
                    320:        }
                    321:
1.44      kristaps  322:        xfprintf(stderr, "%s:%d: warning: %s (column %d)\n",
                    323:                        p->name, line, msg, col);
1.21      kristaps  324:
1.44      kristaps  325:        if ( ! (p->warn & MD_WARN_ERR))
                    326:                return(1);
1.21      kristaps  327:
1.44      kristaps  328:        xfprintf(stderr, "%s: considering warnings as errors\n",
                    329:                        __progname);
                    330:        return(0);
1.1       kristaps  331: }
                    332:
                    333:
                    334: static void
                    335: usage(void)
                    336: {
                    337:
1.47    ! kristaps  338:        xfprintf(stderr, "usage: %s [-v] [-Wwarn...] [-ffilter] "
        !           339:                        "[-o outfile] [infile]\n", __progname);
1.1       kristaps  340: }
1.18      kristaps  341:

CVSweb