]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdocml.c
Boolean validation.
[mandoc.git] / mdocml.c
index f5440b8f96a9feeda53792edc305804928de7f06..2b7c4388fb4f9bde9142d0a3f9ddaddeae43d20f 100644 (file)
--- a/mdocml.c
+++ b/mdocml.c
@@ -1,4 +1,4 @@
-/* $Id: mdocml.c,v 1.21 2008/12/15 01:54:58 kristaps Exp $ */
+/* $Id: mdocml.c,v 1.46 2009/01/16 14:15:12 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 
 #include "mdoc.h"
 
-#define        MD_LINE_SZ      (256)
+#define        xfprintf        (void)fprintf
+#define        xprintf         (void)printf
+#define        xvfprintf       (void)fvprintf
+
+#define        MD_LINE_SZ      (256)           /* Max input line size. */
 
 struct md_parse {
-       int              warn;
-#define        MD_WARN_ALL     (1 << 0)
-#define        MD_WARN_ERR     (1 << 1)
-       int              dbg;
-       struct mdoc     *mdoc;
-       char            *buf;
-       u_long           bufsz;
-       char            *name;
-       int              fd;
-       int              lnn;
-       char            *line;
+       int              warn;          /* Warning flags. */
+#define        MD_WARN_SYNTAX  (1 << 0)        /* Show syntax warnings. */
+#define        MD_WARN_COMPAT  (1 << 1)        /* Show compat warnings. */
+#define        MD_WARN_ALL     (0x03)          /* Show all warnings. */
+#define        MD_WARN_ERR     (1 << 2)        /* Make warnings->errors. */
+       int              dbg;           /* Debug level. */
+       struct mdoc     *mdoc;          /* Active parser. */
+       char            *buf;           /* Input buffer. */
+       u_long           bufsz;         /* Input buffer size. */
+       char            *name;          /* Input file name. */
+       int              fd;            /* Input file desc. */
 };
 
+extern char            *__progname;
+
 static void             usage(void);
 
 static int              parse_begin(struct md_parse *);
@@ -55,9 +61,10 @@ static       int              io_leave(struct md_parse *, int);
 static int              buf_begin(struct md_parse *);
 static int              buf_leave(struct md_parse *, int);
 
-static int              msg_err(void *, int, int, enum mdoc_err);
-static int              msg_warn(void *, int, int, enum mdoc_warn);
-static void             msg_msg(void *, int, const char *);
+static void             msg_msg(void *, int, int, const char *);
+static int              msg_err(void *, int, int, const char *);
+static int              msg_warn(void *, int, int, 
+                               enum mdoc_warn, const char *);
 
 #ifdef __linux__
 extern int              getsubopt(char **, char *const *, char **);
@@ -70,8 +77,11 @@ main(int argc, char *argv[])
        struct md_parse  parser;
        char            *opts, *v;
 #define ALL             0
-#define ERROR           1
-       char            *toks[] = { "all", "error", NULL };
+#define COMPAT          1
+#define SYNTAX          2
+#define ERROR           3
+       char            *toks[] = { "all", "compat", "syntax", 
+                                   "error", NULL };
 
        extern char     *optarg;
        extern int       optind;
@@ -90,6 +100,12 @@ main(int argc, char *argv[])
                                case (ALL):
                                        parser.warn |= MD_WARN_ALL;
                                        break;
+                               case (COMPAT):
+                                       parser.warn |= MD_WARN_COMPAT;
+                                       break;
+                               case (SYNTAX):
+                                       parser.warn |= MD_WARN_SYNTAX;
+                                       break;
                                case (ERROR):
                                        parser.warn |= MD_WARN_ERR;
                                        break;
@@ -178,40 +194,71 @@ buf_begin(struct md_parse *p)
 }
 
 
+/* TODO: remove this to a print-tree output filter. */
 static void
 print_node(const struct mdoc_node *n, int indent)
 {
-       const char      *p, *t;
-       int              i;
+       const char       *p, *t;
+       int               i, j;
+       size_t            argc, sz;
+       char            **params;
+       struct mdoc_arg  *argv;
+
+       argv = NULL;
+       argc = sz = 0;
+       params = NULL;
+
+       t = mdoc_type2a(n->type);
 
        switch (n->type) {
        case (MDOC_TEXT):
-               assert(NULL == n->child);
-               p = "<text>";
-               t = "text";
+               p = n->data.text.string;
                break;
        case (MDOC_BODY):
-               p = mdoc_macronames[n->data.body.tok];
-               t = "block-body";
+               p = mdoc_macronames[n->tok];
                break;
        case (MDOC_HEAD):
-               p = mdoc_macronames[n->data.head.tok];
-               t = "block-head";
+               p = mdoc_macronames[n->tok];
+               break;
+       case (MDOC_TAIL):
+               p = mdoc_macronames[n->tok];
                break;
        case (MDOC_ELEM):
-               assert(NULL == n->child);
-               p = mdoc_macronames[n->data.elem.tok];
-               t = "element";
+               p = mdoc_macronames[n->tok];
+               argv = n->data.elem.argv;
+               argc = n->data.elem.argc;
                break;
        case (MDOC_BLOCK):
-               p = mdoc_macronames[n->data.block.tok];
-               t = "block";
+               p = mdoc_macronames[n->tok];
+               argv = n->data.block.argv;
+               argc = n->data.block.argc;
                break;
+       case (MDOC_ROOT):
+               p = "root";
+               break;
+       default:
+               abort();
+               /* NOTREACHED */
        }
 
        for (i = 0; i < indent; i++)
-               (void)printf("    ");
-       (void)printf("%s (%s)\n", p, t);
+               xprintf("    ");
+       xprintf("%s (%s)", p, t);
+
+       for (i = 0; i < (int)argc; i++) {
+               xprintf(" -%s", mdoc_argnames[argv[i].arg]);
+               if (argv[i].sz > 0)
+                       xprintf(" [");
+               for (j = 0; j < (int)argv[i].sz; j++)
+                       xprintf(" [%s]", argv[i].value[j]);
+               if (argv[i].sz > 0)
+                       xprintf(" ]");
+       }
+
+       for (i = 0; i < (int)sz; i++)
+               xprintf(" [%s]", params[i]);
+
+       xprintf(" %d:%d\n", n->line, n->pos);
 
        if (n->child)
                print_node(n->child, indent + 1);
@@ -225,11 +272,16 @@ parse_leave(struct md_parse *p, int code)
 {
        const struct mdoc_node *n;
 
-       if (p->mdoc) {
-               if ((n = mdoc_result(p->mdoc)))
-                       print_node(n, 0);
-               mdoc_free(p->mdoc);
-       }
+       if (NULL == p->mdoc)
+               return(code);
+
+       if ( ! mdoc_endparse(p->mdoc))
+               code = 0;
+       if ((n = mdoc_result(p->mdoc)))
+               print_node(n, 0);
+
+       mdoc_free(p->mdoc);
+
        return(code);
 }
 
@@ -239,8 +291,9 @@ parse_begin(struct md_parse *p)
 {
        ssize_t          sz, i;
        size_t           pos;
-       char             line[256], sv[256];
+       char             line[MD_LINE_SZ];
        struct mdoc_cb   cb;
+       int              lnn;
 
        cb.mdoc_err = msg_err;
        cb.mdoc_warn = msg_warn;
@@ -249,10 +302,7 @@ parse_begin(struct md_parse *p)
        if (NULL == (p->mdoc = mdoc_alloc(p, &cb)))
                return(parse_leave(p, 0));
 
-       p->lnn = 1;
-       p->line = sv;
-
-       for (pos = 0; ; ) {
+       for (lnn = 1, pos = 0; ; ) {
                if (-1 == (sz = read(p->fd, p->buf, p->bufsz))) {
                        warn("%s", p->name);
                        return(parse_leave(p, 0));
@@ -262,21 +312,19 @@ parse_begin(struct md_parse *p)
                for (i = 0; i < sz; i++) {
                        if ('\n' != p->buf[i]) {
                                if (pos < sizeof(line)) {
-                                       /* LINTED */
-                                       sv[pos] = p->buf[i];
-                                       line[pos++] = p->buf[i];
+                                       line[(int)pos++] = p->buf[(int)i];
                                        continue;
                                }
                                warnx("%s: line %d too long", 
-                                               p->name, p->lnn);
+                                               p->name, lnn);
                                return(parse_leave(p, 0));
                        }
        
-                       line[(int)pos] = sv[(int)pos] = 0;
-                       if ( ! mdoc_parseln(p->mdoc, line))
+                       line[(int)pos] = 0;
+                       if ( ! mdoc_parseln(p->mdoc, lnn, line))
                                return(parse_leave(p, 0));
 
-                       p->lnn++;
+                       lnn++;
                        pos = 0;
                }
        }
@@ -286,150 +334,69 @@ parse_begin(struct md_parse *p)
 
 
 static int
-msg_err(void *arg, int tok, int col, enum mdoc_err type)
+msg_err(void *arg, int line, int col, const char *msg)
 {
-       char             *fmt, *lit;
        struct md_parse  *p;
-       int               i;
 
        p = (struct md_parse *)arg;
 
-       fmt = lit = NULL;
-
-       switch (type) {
-       case (ERR_SYNTAX_QUOTE):
-               lit = "syntax: unterminated quotation";
-               break;
-       case (ERR_SYNTAX_WS):
-               lit = "syntax: whitespace in argument";
-               break;
-       case (ERR_SCOPE_BREAK):
-               /* Which scope is broken? */
-               fmt = "macro `%s' breaks prior explicit scope";
-               break;
-       case (ERR_MACRO_NOTSUP):
-               fmt = "macro `%s' not supported";
-               break;
-       case (ERR_MACRO_NOTCALL):
-               fmt = "macro `%s' not callable";
-               break;
-       case (ERR_ARGS_GE1):
-               fmt = "macro `%s' expects one or more arguments";
-               break;
-       default:
-               abort();
-               /* NOTREACHED */
-       }
-
-       if (fmt) {
-               (void)fprintf(stderr, "%s:%d: error: ",
-                               p->name, p->lnn);
-               (void)fprintf(stderr, fmt, mdoc_macronames[tok]);
-       } else
-               (void)fprintf(stderr, "%s:%d: error: %s",
-                               p->name, p->lnn, lit);
-
-       if (p->dbg < 1) {
-               (void)fprintf(stderr, " (column %d)\n", col);
-               return(0);
-       }
-
-       (void)fprintf(stderr, "\nFrom: %s\n      ", p->line);
-       for (i = 0; i < col; i++)
-               (void)fprintf(stderr, " ");
-       (void)fprintf(stderr, "^\n");
-
+       xfprintf(stderr, "%s:%d: error: %s (column %d)\n", 
+                       p->name, line, msg, col);
        return(0);
 }
 
 
 static void
-msg_msg(void *arg, int col, const char *msg)
+msg_msg(void *arg, int line, int col, const char *msg)
 {
        struct md_parse  *p;
-       int               i;
 
        p = (struct md_parse *)arg;
 
-       if (p->dbg < 2)
+       if (0 == p->dbg)
                return;
 
-       (void)printf("%s:%d: %s", p->name, p->lnn, msg);
-
-       if (p->dbg < 3) {
-               (void)printf(" (column %d)\n", col);
-               return;
-       }
-
-       (void)printf("\nFrom: %s\n      ", p->line);
-       for (i = 0; i < col; i++)
-               (void)printf(" ");
-       (void)printf("^\n");
+       xfprintf(stderr, "%s:%d: debug: %s (column %d)\n", 
+                       p->name, line, msg, col);
 }
 
 
 static int
-msg_warn(void *arg, int tok, int col, enum mdoc_warn type)
+msg_warn(void *arg, int line, int col, 
+               enum mdoc_warn type, const char *msg)
 {
-       char             *fmt, *lit;
        struct md_parse  *p;
-       int               i;
-       extern char      *__progname;
 
        p = (struct md_parse *)arg;
 
-       if ( ! (p->warn & MD_WARN_ALL))
-               return(1);
-
-       fmt = lit = NULL;
-
        switch (type) {
-       case (WARN_SYNTAX_WS_EOLN):
-               lit = "syntax: whitespace at end-of-line";
-               break;
-       case (WARN_SYNTAX_MACLIKE):
-               lit = "syntax: macro-like argument";
-               break;
-       case (WARN_ARGS_GE1):
-               fmt = "macro `%s' suggests one or more arguments";
-               break;
-       default:
-               abort();
-               /* NOTREACHED */
+       case (WARN_COMPAT):
+               if (p->warn & MD_WARN_COMPAT)
+                       break;
+               return(1);
+       case (WARN_SYNTAX):
+               if (p->warn & MD_WARN_SYNTAX)
+                       break;
+               return(1);
        }
 
-       if (fmt) {
-               (void)fprintf(stderr, "%s:%d: warning: ",
-                               p->name, p->lnn);
-               (void)fprintf(stderr, fmt, mdoc_macronames[tok]);
-       } else
-               (void)fprintf(stderr, "%s:%d: warning: %s",
-                               p->name, p->lnn, lit);
-
-       if (p->dbg >= 1) {
-               (void)fprintf(stderr, "\nFrom: %s\n      ", p->line);
-               for (i = 0; i < col; i++)
-                       (void)fprintf(stderr, " ");
-               (void)fprintf(stderr, "^\n");
-       } else
-               (void)fprintf(stderr, " (column %d)\n", col);
-
-       if (p->warn & MD_WARN_ERR) {
-               (void)fprintf(stderr, "%s: considering warnings as "
-                               "errors\n", __progname);
-               return(0);
-       }
+       xfprintf(stderr, "%s:%d: warning: %s (column %d)\n", 
+                       p->name, line, msg, col);
 
-       return(1);
+       if ( ! (p->warn & MD_WARN_ERR))
+               return(1);
+
+       xfprintf(stderr, "%s: considering warnings as errors\n", 
+                       __progname);
+       return(0);
 }
 
 
 static void
 usage(void)
 {
-       extern char     *__progname;
 
-       (void)fprintf(stderr, "usage: %s [-v] [-Wwarn...] [infile]\n",
+       xfprintf(stderr, "usage: %s [-v] [-Wwarn...] [infile]\n",
                        __progname);
 }