]> git.cameronkatri.com Git - mandoc.git/blobdiff - main.c
Added mail archive periodically generated by hypermail.
[mandoc.git] / main.c
diff --git a/main.c b/main.c
index af2e98a113c70cc1658bc624b7c88e71b501a522..d7937f33571d8842ec02ca6c60b28f29b128c702 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
-/*     $Id: main.c,v 1.79 2010/05/17 22:11:42 kristaps Exp $ */
+/*     $Id: main.c,v 1.102 2010/08/08 14:45:59 schwarze Exp $ */
 /*
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -22,6 +23,7 @@
 #include <sys/stat.h>
 
 #include <assert.h>
 #include <sys/stat.h>
 
 #include <assert.h>
+#include <ctype.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <unistd.h>
 
 #include "mandoc.h"
 #include <unistd.h>
 
 #include "mandoc.h"
+#include "main.h"
 #include "mdoc.h"
 #include "man.h"
 #include "roff.h"
 #include "mdoc.h"
 #include "man.h"
 #include "roff.h"
-#include "main.h"
+
+#ifndef MAP_FILE
+#define        MAP_FILE        0
+#endif
 
 #define        UNCONST(a)      ((void *)(uintptr_t)(const void *)(a))
 
 
 #define        UNCONST(a)      ((void *)(uintptr_t)(const void *)(a))
 
@@ -65,7 +71,9 @@ enum  outt {
        OUTT_TREE,
        OUTT_HTML,
        OUTT_XHTML,
        OUTT_TREE,
        OUTT_HTML,
        OUTT_XHTML,
-       OUTT_LINT
+       OUTT_LINT,
+       OUTT_PS,
+       OUTT_PDF
 };
 
 struct curparse {
 };
 
 struct curparse {
@@ -86,6 +94,7 @@ struct        curparse {
        struct man       *man;          /* man parser */
        struct mdoc      *mdoc;         /* mdoc parser */
        struct roff      *roff;         /* roff parser (!NULL) */
        struct man       *man;          /* man parser */
        struct mdoc      *mdoc;         /* mdoc parser */
        struct roff      *roff;         /* roff parser (!NULL) */
+       struct regset     regs;         /* roff registers */
        enum outt         outtype;      /* which output to use */
        out_mdoc          outmdoc;      /* mdoc output ptr */
        out_man           outman;       /* man output ptr */
        enum outt         outtype;      /* which output to use */
        out_mdoc          outmdoc;      /* mdoc output ptr */
        out_man           outman;       /* man output ptr */
@@ -96,25 +105,33 @@ struct     curparse {
 
 static const char * const      mandocerrs[MANDOCERR_MAX] = {
        "ok",
 
 static const char * const      mandocerrs[MANDOCERR_MAX] = {
        "ok",
+
+       "generic warning",
+
        "text should be uppercase",
        "text should be uppercase",
-       "sections out of conentional order",
+       "sections out of conventional order",
        "section name repeats",
        "out of order prologue",
        "repeated prologue entry",
        "list type must come first",
        "section name repeats",
        "out of order prologue",
        "repeated prologue entry",
        "list type must come first",
-       "column syntax is inconsistent",
        "bad standard",
        "bad library",
        "bad standard",
        "bad library",
+       "tab in non-literal context",
        "bad escape sequence",
        "unterminated quoted string",
        "argument requires the width argument",
        "superfluous width argument",
        "bad escape sequence",
        "unterminated quoted string",
        "argument requires the width argument",
        "superfluous width argument",
+       "ignoring argument",
        "bad date argument",
        "bad width argument",
        "bad date argument",
        "bad width argument",
-       "unknown manual sction",
+       "unknown manual section",
        "section not in conventional manual section",
        "end of line whitespace",
        "section not in conventional manual section",
        "end of line whitespace",
+       "blocks badly nested",
        "scope open on exit",
        "scope open on exit",
+
+       "generic error",
+
        "NAME section must come first",
        "bad Boolean value",
        "child violates parent syntax",
        "NAME section must come first",
        "bad Boolean value",
        "child violates parent syntax",
@@ -134,7 +151,6 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "bad comment style",
        "unknown macro will be lost",
        "line scope broken",
        "bad comment style",
        "unknown macro will be lost",
        "line scope broken",
-       "scope broken",
        "argument count wrong",
        "request scope close w/none open",
        "scope already open",
        "argument count wrong",
        "request scope close w/none open",
        "scope already open",
@@ -142,13 +158,19 @@ static    const char * const      mandocerrs[MANDOCERR_MAX] = {
        "macro requires body argument(s)",
        "macro requires argument(s)",
        "no title in document",
        "macro requires body argument(s)",
        "macro requires argument(s)",
        "no title in document",
+       "missing list type",
+       "missing display type",
+       "missing font type",
        "line argument(s) will be lost",
        "body argument(s) will be lost",
        "line argument(s) will be lost",
        "body argument(s) will be lost",
-       "missing font type",
-       "missing display type",
-       "missing list type",
+
+       "generic fatal error",
+
+       "column syntax is inconsistent",
        "displays may not be nested",
        "displays may not be nested",
-       "no scope to rewind: syntax violated",
+       "unsupported display type",
+       "blocks badly nested",
+       "no such block is open",
        "scope broken, syntax violated",
        "line scope broken, syntax violated",
        "argument count wrong, violates syntax",
        "scope broken, syntax violated",
        "line scope broken, syntax violated",
        "argument count wrong, violates syntax",
@@ -177,8 +199,8 @@ static      void              version(void) __attribute__((noreturn));
 static int               woptions(int *, char *);
 
 static const char       *progname;
 static int               woptions(int *, char *);
 
 static const char       *progname;
-static         int               with_error;
-static int               with_warning;
+static int               with_fatal;
+static int               with_error;
 
 int
 main(int argc, char *argv[])
 
 int
 main(int argc, char *argv[])
@@ -241,7 +263,7 @@ main(int argc, char *argv[])
        while (*argv) {
                ffile(*argv, &curp);
 
        while (*argv) {
                ffile(*argv, &curp);
 
-               if (with_error && !(curp.fflags & FL_IGN_ERRORS))
+               if (with_fatal && !(curp.fflags & FL_IGN_ERRORS))
                        break;
                ++argv;
        }
                        break;
                ++argv;
        }
@@ -255,7 +277,7 @@ main(int argc, char *argv[])
        if (curp.roff)
                roff_free(curp.roff);
 
        if (curp.roff)
                roff_free(curp.roff);
 
-       return((with_warning || with_error) ? 
+       return((with_fatal || with_error) ? 
                        EXIT_FAILURE :  EXIT_SUCCESS);
 }
 
                        EXIT_FAILURE :  EXIT_SUCCESS);
 }
 
@@ -294,7 +316,7 @@ man_init(struct curparse *curp)
        if (curp->fflags & FL_NIGN_ESCAPE)
                pflags &= ~MAN_IGN_ESCAPE;
 
        if (curp->fflags & FL_NIGN_ESCAPE)
                pflags &= ~MAN_IGN_ESCAPE;
 
-       return(man_alloc(curp, pflags, mmsg));
+       return(man_alloc(&curp->regs, curp, pflags, mmsg));
 }
 
 
 }
 
 
@@ -302,7 +324,7 @@ static struct roff *
 roff_init(struct curparse *curp)
 {
 
 roff_init(struct curparse *curp)
 {
 
-       return(roff_alloc(mmsg, curp));
+       return(roff_alloc(&curp->regs, mmsg, curp));
 }
 
 
 }
 
 
@@ -322,7 +344,7 @@ mdoc_init(struct curparse *curp)
        if (curp->fflags & FL_NIGN_MACRO)
                pflags &= ~MDOC_IGN_MACRO;
 
        if (curp->fflags & FL_NIGN_MACRO)
                pflags &= ~MDOC_IGN_MACRO;
 
-       return(mdoc_alloc(curp, pflags, mmsg));
+       return(mdoc_alloc(&curp->regs, curp, pflags, mmsg));
 }
 
 
 }
 
 
@@ -333,7 +355,7 @@ ffile(const char *file, struct curparse *curp)
        curp->file = file;
        if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
                perror(curp->file);
        curp->file = file;
        if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
                perror(curp->file);
-               with_error = 1;
+               with_fatal = 1;
                return;
        }
 
                return;
        }
 
@@ -374,7 +396,7 @@ read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
 
        if (-1 == fstat(curp->fd, &st)) {
                perror(curp->file);
 
        if (-1 == fstat(curp->fd, &st)) {
                perror(curp->file);
-               with_error = 1;
+               with_fatal = 1;
                return(0);
        }
 
                return(0);
        }
 
@@ -389,13 +411,13 @@ read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
                if (st.st_size >= (1U << 31)) {
                        fprintf(stderr, "%s: input too large\n", 
                                        curp->file);
                if (st.st_size >= (1U << 31)) {
                        fprintf(stderr, "%s: input too large\n", 
                                        curp->file);
-                       with_error = 1;
+                       with_fatal = 1;
                        return(0);
                }
                *with_mmap = 1;
                fb->sz = (size_t)st.st_size;
                fb->buf = mmap(NULL, fb->sz, PROT_READ, 
                        return(0);
                }
                *with_mmap = 1;
                fb->sz = (size_t)st.st_size;
                fb->buf = mmap(NULL, fb->sz, PROT_READ, 
-                               MAP_FILE, curp->fd, 0);
+                               MAP_FILE|MAP_SHARED, curp->fd, 0);
                if (fb->buf != MAP_FAILED)
                        return(1);
        }
                if (fb->buf != MAP_FAILED)
                        return(1);
        }
@@ -433,7 +455,7 @@ read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
 
        free(fb->buf);
        fb->buf = NULL;
 
        free(fb->buf);
        fb->buf = NULL;
-       with_error = 1;
+       with_fatal = 1;
        return(0);
 }
 
        return(0);
 }
 
@@ -444,6 +466,7 @@ fdesc(struct curparse *curp)
        struct buf       ln, blk;
        int              i, pos, lnn, lnn_start, with_mmap, of;
        enum rofferr     re;
        struct buf       ln, blk;
        int              i, pos, lnn, lnn_start, with_mmap, of;
        enum rofferr     re;
+       unsigned char    c;
        struct man      *man;
        struct mdoc     *mdoc;
        struct roff     *roff;
        struct man      *man;
        struct mdoc     *mdoc;
        struct roff     *roff;
@@ -451,6 +474,7 @@ fdesc(struct curparse *curp)
        man = NULL;
        mdoc = NULL;
        roff = NULL;
        man = NULL;
        mdoc = NULL;
        roff = NULL;
+
        memset(&ln, 0, sizeof(struct buf));
 
        /*
        memset(&ln, 0, sizeof(struct buf));
 
        /*
@@ -475,6 +499,26 @@ fdesc(struct curparse *curp)
                                ++lnn;
                                break;
                        }
                                ++lnn;
                                break;
                        }
+
+                       /* 
+                        * Warn about bogus characters.  If you're using
+                        * non-ASCII encoding, you're screwing your
+                        * readers.  Since I'd rather this not happen,
+                        * I'll be helpful and drop these characters so
+                        * we don't display gibberish.  Note to manual
+                        * writers: use special characters.
+                        */
+
+                       c = (unsigned char) blk.buf[i];
+                       if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) {
+                               if ( ! mmsg(MANDOCERR_BADCHAR, curp, 
+                                               lnn_start, pos, 
+                                               "ignoring byte"))
+                                       goto bailout;
+                               i++;
+                               continue;
+                       }
+
                        /* Trailing backslash is like a plain character. */
                        if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
                                if (pos >= (int)ln.sz)
                        /* Trailing backslash is like a plain character. */
                        if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
                                if (pos >= (int)ln.sz)
@@ -584,12 +628,30 @@ fdesc(struct curparse *curp)
                switch (curp->outtype) {
                case (OUTT_XHTML):
                        curp->outdata = xhtml_alloc(curp->outopts);
                switch (curp->outtype) {
                case (OUTT_XHTML):
                        curp->outdata = xhtml_alloc(curp->outopts);
-                       curp->outman = html_man;
-                       curp->outmdoc = html_mdoc;
-                       curp->outfree = html_free;
                        break;
                case (OUTT_HTML):
                        curp->outdata = html_alloc(curp->outopts);
                        break;
                case (OUTT_HTML):
                        curp->outdata = html_alloc(curp->outopts);
+                       break;
+               case (OUTT_ASCII):
+                       curp->outdata = ascii_alloc(curp->outopts);
+                       curp->outfree = ascii_free;
+                       break;
+               case (OUTT_PDF):
+                       curp->outdata = pdf_alloc(curp->outopts);
+                       curp->outfree = pspdf_free;
+                       break;
+               case (OUTT_PS):
+                       curp->outdata = ps_alloc(curp->outopts);
+                       curp->outfree = pspdf_free;
+                       break;
+               default:
+                       break;
+               }
+
+               switch (curp->outtype) {
+               case (OUTT_HTML):
+                       /* FALLTHROUGH */
+               case (OUTT_XHTML):
                        curp->outman = html_man;
                        curp->outmdoc = html_mdoc;
                        curp->outfree = html_free;
                        curp->outman = html_man;
                        curp->outmdoc = html_mdoc;
                        curp->outfree = html_free;
@@ -598,13 +660,15 @@ fdesc(struct curparse *curp)
                        curp->outman = tree_man;
                        curp->outmdoc = tree_mdoc;
                        break;
                        curp->outman = tree_man;
                        curp->outmdoc = tree_mdoc;
                        break;
-               case (OUTT_LINT):
-                       break;
-               default:
-                       curp->outdata = ascii_alloc(80);
+               case (OUTT_PDF):
+                       /* FALLTHROUGH */
+               case (OUTT_ASCII):
+                       /* FALLTHROUGH */
+               case (OUTT_PS):
                        curp->outman = terminal_man;
                        curp->outmdoc = terminal_mdoc;
                        curp->outman = terminal_man;
                        curp->outmdoc = terminal_mdoc;
-                       curp->outfree = terminal_free;
+                       break;
+               default:
                        break;
                }
        }
                        break;
                }
        }
@@ -617,6 +681,7 @@ fdesc(struct curparse *curp)
                (*curp->outmdoc)(curp->outdata, mdoc);
 
  cleanup:
                (*curp->outmdoc)(curp->outdata, mdoc);
 
  cleanup:
+       memset(&curp->regs, 0, sizeof(struct regset));
        if (mdoc)
                mdoc_reset(mdoc);
        if (man)
        if (mdoc)
                mdoc_reset(mdoc);
        if (man)
@@ -633,7 +698,7 @@ fdesc(struct curparse *curp)
        return;
 
  bailout:
        return;
 
  bailout:
-       with_error = 1;
+       with_fatal = 1;
        goto cleanup;
 }
 
        goto cleanup;
 }
 
@@ -729,6 +794,10 @@ toptions(struct curparse *curp, char *arg)
                curp->outtype = OUTT_HTML;
        else if (0 == strcmp(arg, "xhtml"))
                curp->outtype = OUTT_XHTML;
                curp->outtype = OUTT_HTML;
        else if (0 == strcmp(arg, "xhtml"))
                curp->outtype = OUTT_XHTML;
+       else if (0 == strcmp(arg, "ps"))
+               curp->outtype = OUTT_PS;
+       else if (0 == strcmp(arg, "pdf"))
+               curp->outtype = OUTT_PDF;
        else {
                fprintf(stderr, "%s: Bad argument\n", arg);
                return(0);
        else {
                fprintf(stderr, "%s: Bad argument\n", arg);
                return(0);
@@ -816,30 +885,37 @@ static int
 mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
 {
        struct curparse *cp;
 mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
 {
        struct curparse *cp;
+       const char *level;
+       int rc;
 
        cp = (struct curparse *)arg;
 
        cp = (struct curparse *)arg;
-
-       if (t <= MANDOCERR_ERROR) {
-               if ( ! (cp->wflags & WARN_WALL))
+       level = NULL;
+       rc = 1;
+
+       if (t >= MANDOCERR_FATAL) {
+               with_fatal = 1;
+               level = "FATAL";
+               rc = 0;
+       } else {
+               if ( ! (WARN_WALL & cp->wflags))
                        return(1);
                        return(1);
-               with_warning = 1;
-       } else
-               with_error = 1;
-
-       fprintf(stderr, "%s:%d:%d: %s", cp->file, 
-                       ln, col + 1, mandocerrs[t]);
+               if (t >= MANDOCERR_ERROR) {
+                       with_error = 1;
+                       level = "ERROR";
+               }
+               if (WARN_WERR & cp->wflags) {
+                       with_fatal = 1;
+                       rc = 0;
+               }
+       }
 
 
+       fprintf(stderr, "%s:%d:%d:", cp->file, ln, col + 1);
+       if (level)
+               fprintf(stderr, " %s:", level);
+       fprintf(stderr, " %s", mandocerrs[t]);
        if (msg)
                fprintf(stderr, ": %s", msg);
        if (msg)
                fprintf(stderr, ": %s", msg);
-
        fputc('\n', stderr);
 
        fputc('\n', stderr);
 
-       /* This is superfluous, but whatever. */
-       if (t > MANDOCERR_ERROR)
-               return(0);
-       if (cp->wflags & WARN_WERR) {
-               with_error = 1;
-               return(0);
-       }
-       return(1);
+       return(rc);
 }
 }