]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdocml.c
Boolean validation.
[mandoc.git] / mdocml.c
index ec53aa10b328542e64131b672d75fbb2a940b2ec..2b7c4388fb4f9bde9142d0a3f9ddaddeae43d20f 100644 (file)
--- a/mdocml.c
+++ b/mdocml.c
@@ -1,4 +1,4 @@
-/* $Id: mdocml.c,v 1.40 2009/01/12 12:52:21 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, 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,6 +194,7 @@ 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)
 {
@@ -188,44 +205,36 @@ print_node(const struct mdoc_node *n, int indent)
        struct mdoc_arg  *argv;
 
        argv = NULL;
-       argc = 0;
+       argc = sz = 0;
        params = NULL;
-       sz = 0;
 
-       /* FIXME: put parts of this in util.c. */
+       t = mdoc_type2a(n->type);
+
        switch (n->type) {
        case (MDOC_TEXT):
-               assert(NULL == n->child);
                p = n->data.text.string;
-               t = "text";
                break;
        case (MDOC_BODY):
                p = mdoc_macronames[n->tok];
-               t = "block-body";
                break;
        case (MDOC_HEAD):
                p = mdoc_macronames[n->tok];
-               t = "block-head";
                break;
        case (MDOC_TAIL):
                p = mdoc_macronames[n->tok];
-               t = "block-tail";
                break;
        case (MDOC_ELEM):
                p = mdoc_macronames[n->tok];
-               t = "element";
                argv = n->data.elem.argv;
                argc = n->data.elem.argc;
                break;
        case (MDOC_BLOCK):
                p = mdoc_macronames[n->tok];
-               t = "block";
                argv = n->data.block.argv;
                argc = n->data.block.argc;
                break;
        case (MDOC_ROOT):
                p = "root";
-               t = "root";
                break;
        default:
                abort();
@@ -233,19 +242,23 @@ print_node(const struct mdoc_node *n, int indent)
        }
 
        for (i = 0; i < indent; i++)
-               (void)printf("    ");
-       (void)printf("%s (%s)", p, t);
+               xprintf("    ");
+       xprintf("%s (%s)", p, t);
 
        for (i = 0; i < (int)argc; i++) {
-               (void)printf(" -%s", mdoc_argnames[argv[i].arg]);
+               xprintf(" -%s", mdoc_argnames[argv[i].arg]);
+               if (argv[i].sz > 0)
+                       xprintf(" [");
                for (j = 0; j < (int)argv[i].sz; j++)
-                       (void)printf(" \"%s\"", argv[i].value[j]);
+                       xprintf(" [%s]", argv[i].value[j]);
+               if (argv[i].sz > 0)
+                       xprintf(" ]");
        }
 
        for (i = 0; i < (int)sz; i++)
-               (void)printf(" \"%s\"", params[i]);
+               xprintf(" [%s]", params[i]);
 
-       (void)printf(" %d:%d\n", n->line, n->pos);
+       xprintf(" %d:%d\n", n->line, n->pos);
 
        if (n->child)
                print_node(n->child, indent + 1);
@@ -278,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;
@@ -288,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));
@@ -301,21 +312,19 @@ parse_begin(struct md_parse *p)
                for (i = 0; i < sz; i++) {
                        if ('\n' != p->buf[i]) {
                                if (pos < sizeof(line)) {
-                                       sv[(int)pos] = p->buf[(int)i];
-                                       line[(int)pos++] = 
-                                               p->buf[(int)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, p->lnn, line))
+                       line[(int)pos] = 0;
+                       if ( ! mdoc_parseln(p->mdoc, lnn, line))
                                return(parse_leave(p, 0));
 
-                       p->lnn++;
+                       lnn++;
                        pos = 0;
                }
        }
@@ -325,123 +334,14 @@ parse_begin(struct md_parse *p)
 
 
 static int
-msg_err(void *arg, int line, int col, enum mdoc_err type)
+msg_err(void *arg, int line, int col, const char *msg)
 {
-       char             *lit;
        struct md_parse  *p;
 
        p = (struct md_parse *)arg;
 
-       lit = NULL;
-
-       switch (type) {
-       case (ERR_SYNTAX_NOTEXT):
-               lit = "syntax: context-free text disallowed";
-               break;
-       case (ERR_SYNTAX_QUOTE):
-               lit = "syntax: disallowed argument quotation";
-               break;
-       case (ERR_SYNTAX_UNQUOTE):
-               lit = "syntax: unterminated quotation";
-               break;
-       case (ERR_SYNTAX_WS):
-               lit = "syntax: whitespace in argument";
-               break;
-       case (ERR_SYNTAX_ARGFORM):
-               lit = "syntax: macro arguments malformed";
-               break;
-       case (ERR_SYNTAX_NOPUNCT):
-               lit = "syntax: macro doesn't understand punctuation";
-               break;
-       case (ERR_SYNTAX_ARG):
-               lit = "syntax: unknown argument for macro";
-               break;
-       case (ERR_SCOPE_BREAK):
-               /* Which scope is broken? */
-               lit = "scope: macro breaks prior explicit scope";
-               break;
-       case (ERR_SCOPE_NOCTX):
-               lit = "scope: closure macro has no context";
-               break;
-       case (ERR_SCOPE_NONEST):
-               lit = "scope: macro may not be nested in the current context";
-               break;
-       case (ERR_MACRO_NOTSUP):
-               lit = "macro not supported";
-               break;
-       case (ERR_MACRO_NOTCALL):
-               lit = "macro not callable";
-               break;
-       case (ERR_SEC_PROLOGUE):
-               lit = "macro cannot be called in the prologue";
-               break;
-       case (ERR_SEC_NPROLOGUE):
-               lit = "macro called outside of prologue";
-               break;
-       case (ERR_ARGS_EQ0):
-               lit = "macro expects zero arguments";
-               break;
-       case (ERR_ARGS_EQ1):
-               lit = "macro expects one argument";
-               break;
-       case (ERR_ARGS_GE1):
-               lit = "macro expects one or more arguments";
-               break;
-       case (ERR_ARGS_LE2):
-               lit = "macro expects two or fewer arguments";
-               break;
-       case (ERR_ARGS_LE8):
-               lit = "macro expects eight or fewer arguments";
-               break;
-       case (ERR_ARGS_MANY):
-               lit = "macro has too many arguments";
-               break;
-       case (ERR_SEC_PROLOGUE_OO):
-               lit = "prologue macro is out-of-order";
-               break;
-       case (ERR_SEC_PROLOGUE_REP):
-               lit = "prologue macro repeated";
-               break;
-       case (ERR_SEC_NAME):
-               lit = "`NAME' section must be first";
-               break;
-       case (ERR_SYNTAX_ARGVAL):
-               lit = "syntax: expected value for macro argument";
-               break;
-       case (ERR_SYNTAX_ARGBAD):
-               lit = "syntax: invalid value(s) for macro argument";
-               break;
-       case (ERR_SYNTAX_ARGMISS):
-               lit = "syntax: missing required argument(s) for macro";
-               break;
-       case (ERR_SYNTAX_ARGMANY):
-               lit = "syntax: too many values for macro argument";
-               break;
-       case (ERR_SYNTAX_CHILDBAD):
-               lit = "syntax: invalid child for parent macro";
-               break;
-       case (ERR_SYNTAX_PARENTBAD):
-               lit = "syntax: invalid parent for macro";
-               break;
-       case (ERR_SYNTAX_CHILDHEAD):
-               lit = "syntax: expected only block-header section";
-               break;
-       case (ERR_SYNTAX_CHILDBODY):
-               lit = "syntax: expected only a block-body section";
-               break;
-       case (ERR_SYNTAX_EMPTYHEAD):
-               lit = "syntax: block-header section may not be empty";
-               break;
-       case (ERR_SYNTAX_EMPTYBODY):
-               lit = "syntax: block-body section may not be empty";
-               break;
-       default:
-               abort();
-               /* NOTREACHED */
-       }
-
-       (void)fprintf(stderr, "%s:%d: error: %s (column %d)\n", 
-                       p->name, line, lit, col);
+       xfprintf(stderr, "%s:%d: error: %s (column %d)\n", 
+                       p->name, line, msg, col);
        return(0);
 }
 
@@ -453,99 +353,50 @@ msg_msg(void *arg, int line, int col, const char *msg)
 
        p = (struct md_parse *)arg;
 
-       if (p->dbg < 2)
+       if (0 == p->dbg)
                return;
 
-       (void)printf("%s:%d: %s (column %d)\n", 
+       xfprintf(stderr, "%s:%d: debug: %s (column %d)\n", 
                        p->name, line, msg, col);
 }
 
 
 static int
-msg_warn(void *arg, int line, int col, enum mdoc_warn type)
+msg_warn(void *arg, int line, int col, 
+               enum mdoc_warn type, const char *msg)
 {
-       char             *lit;
        struct md_parse  *p;
-       extern char      *__progname;
 
        p = (struct md_parse *)arg;
 
-       if ( ! (p->warn & MD_WARN_ALL))
-               return(1);
-
-       lit = NULL;
-
        switch (type) {
-       case (WARN_SYNTAX_WS_EOLN):
-               lit = "syntax: whitespace at end-of-line";
-               break;
-       case (WARN_SYNTAX_QUOTED):
-               lit = "syntax: quotation mark starting string";
-               break;
-       case (WARN_SYNTAX_MACLIKE):
-               lit = "syntax: macro-like argument";
-               break;
-       case (WARN_SYNTAX_ARGLIKE):
-               lit = "syntax: argument-like value";
-               break;
-       case (WARN_SYNTAX_EMPTYBODY):
-               lit = "syntax: macro suggests non-empty block-body section";
-               break;
-       case (WARN_SYNTAX_EMPTYHEAD):
-               lit = "syntax: macro suggests non-empty block-head section";
-               break;
-       case (WARN_SYNTAX_NOBODY):
-               lit = "syntax: macro suggests empty block-body section";
-               break;
-       case (WARN_SEC_OO):
-               lit = "section is out of conventional order";
-               break;
-       case (WARN_SEC_REP):
-               lit = "section repeated";
-               break;
-       case (WARN_ARGS_GE1):
-               lit = "macro suggests one or more arguments";
-               break;
-       case (WARN_ARGS_EQ0):
-               lit = "macro suggests zero arguments";
-               break;
-       case (WARN_IGN_AFTER_BLK):
-               lit = "ignore: macro ignored after block macro";
-               break;
-       case (WARN_IGN_OBSOLETE):
-               lit = "ignore: macro is obsolete";
-               break;
-       case (WARN_IGN_BEFORE_BLK):
-               lit = "ignore: macro before block macro ignored";
-               break;
-       case (WARN_COMPAT_TROFF):
-               lit = "compat: macro behaves differently in troff and nroff";
-               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);
        }
 
+       xfprintf(stderr, "%s:%d: warning: %s (column %d)\n", 
+                       p->name, line, msg, col);
 
-       (void)fprintf(stderr, "%s:%d: warning: %s (column %d)\n", 
-                       p->name, line, lit, col);
-
-       if (p->warn & MD_WARN_ERR) {
-               (void)fprintf(stderr, "%s: considering warnings as "
-                               "errors\n", __progname);
-               return(0);
-       }
+       if ( ! (p->warn & MD_WARN_ERR))
+               return(1);
 
-       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);
 }