]> git.cameronkatri.com Git - mandoc.git/blobdiff - main.c
Merge restructuring of main.c code. This provided by schwarze@ and inspected
[mandoc.git] / main.c
diff --git a/main.c b/main.c
index 1e635fe2f4870cec11a83a03449e3728ae44def7..ee51348e11317d787851379372fad25e35fbfb6d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/*     $Id: main.c,v 1.103 2010/08/20 01:02:07 schwarze Exp $ */
+/*     $Id: main.c,v 1.111 2010/12/01 15:09:01 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -79,6 +79,7 @@ enum  outt {
 struct curparse {
        const char       *file;         /* Current parse. */
        int               fd;           /* Current parse. */
 struct curparse {
        const char       *file;         /* Current parse. */
        int               fd;           /* Current parse. */
+       int               line;         /* Line number in the file. */
        enum mandoclevel  wlevel;       /* Ignore messages below this. */
        int               wstop;        /* Stop after a file with a warning. */
        enum intt         inttype;      /* which parser to use */
        enum mandoclevel  wlevel;       /* Ignore messages below this. */
        int               wstop;        /* Stop after a file with a warning. */
        enum intt         inttype;      /* which parser to use */
@@ -125,21 +126,17 @@ static    const char * const      mandocerrs[MANDOCERR_MAX] = {
        "out of order prologue",
        "repeated prologue entry",
        "list type must come first",
        "out of order prologue",
        "repeated prologue entry",
        "list type must come first",
-       "bad standard",
-       "bad library",
        "tab in non-literal context",
        "bad escape sequence",
        "unterminated quoted string",
        "argument requires the width argument",
        "superfluous width argument",
        "tab in non-literal context",
        "bad escape sequence",
        "unterminated quoted string",
        "argument requires the width argument",
        "superfluous width argument",
-       "ignoring argument",
        "bad date argument",
        "bad width argument",
        "unknown manual section",
        "section not in conventional manual section",
        "end of line whitespace",
        "blocks badly nested",
        "bad date argument",
        "bad width argument",
        "unknown manual section",
        "section not in conventional manual section",
        "end of line whitespace",
        "blocks badly nested",
-       "scope open on exit",
 
        "generic error",
 
 
        "generic error",
 
@@ -147,9 +144,11 @@ static     const char * const      mandocerrs[MANDOCERR_MAX] = {
        "bad Boolean value",
        "child violates parent syntax",
        "bad AT&T symbol",
        "bad Boolean value",
        "child violates parent syntax",
        "bad AT&T symbol",
+       "bad standard",
        "list type repeated",
        "display type repeated",
        "argument repeated",
        "list type repeated",
        "display type repeated",
        "argument repeated",
+       "ignoring argument",
        "manual name not yet set",
        "obsolete macro ignored",
        "empty macro ignored",
        "manual name not yet set",
        "obsolete macro ignored",
        "empty macro ignored",
@@ -161,10 +160,12 @@ static    const char * const      mandocerrs[MANDOCERR_MAX] = {
        "no text in this context",
        "bad comment style",
        "unknown macro will be lost",
        "no text in this context",
        "bad comment style",
        "unknown macro will be lost",
+       "NOT IMPLEMENTED: skipping request",
        "line scope broken",
        "argument count wrong",
        "request scope close w/none open",
        "scope already open",
        "line scope broken",
        "argument count wrong",
        "request scope close w/none open",
        "scope already open",
+       "scope open on exit",
        "macro requires line argument(s)",
        "macro requires body argument(s)",
        "macro requires argument(s)",
        "macro requires line argument(s)",
        "macro requires body argument(s)",
        "macro requires argument(s)",
@@ -174,6 +175,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "missing font type",
        "line argument(s) will be lost",
        "body argument(s) will be lost",
        "missing font type",
        "line argument(s) will be lost",
        "body argument(s) will be lost",
+       "paragraph macro ignored",
 
        "generic fatal error",
 
 
        "generic fatal error",
 
@@ -182,7 +184,6 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "unsupported display type",
        "blocks badly nested",
        "no such block is open",
        "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",
        "child violates parent syntax",
        "line scope broken, syntax violated",
        "argument count wrong, violates syntax",
        "child violates parent syntax",
@@ -193,8 +194,11 @@ static     const char * const      mandocerrs[MANDOCERR_MAX] = {
        "static buffer exhausted",
 };
 
        "static buffer exhausted",
 };
 
+static void              parsebuf(struct curparse *, struct buf, int);
+static void              pdesc(struct curparse *);
 static void              fdesc(struct curparse *);
 static void              ffile(const char *, struct curparse *);
 static void              fdesc(struct curparse *);
 static void              ffile(const char *, struct curparse *);
+static int               pfile(const char *, struct curparse *);
 static int               moptions(enum intt *, char *);
 static int               mmsg(enum mandocerr, void *, 
                                int, int, const char *);
 static int               moptions(enum intt *, char *);
 static int               mmsg(enum mandocerr, void *, 
                                int, int, const char *);
@@ -231,7 +235,7 @@ main(int argc, char *argv[])
                switch (c) {
                case ('m'):
                        if ( ! moptions(&curp.inttype, optarg))
                switch (c) {
                case ('m'):
                        if ( ! moptions(&curp.inttype, optarg))
-                               return(MANDOCLEVEL_BADARG);
+                               return((int)MANDOCLEVEL_BADARG);
                        break;
                case ('O'):
                        (void)strlcat(curp.outopts, optarg, BUFSIZ);
                        break;
                case ('O'):
                        (void)strlcat(curp.outopts, optarg, BUFSIZ);
@@ -239,11 +243,11 @@ main(int argc, char *argv[])
                        break;
                case ('T'):
                        if ( ! toptions(&curp, optarg))
                        break;
                case ('T'):
                        if ( ! toptions(&curp, optarg))
-                               return(MANDOCLEVEL_BADARG);
+                               return((int)MANDOCLEVEL_BADARG);
                        break;
                case ('W'):
                        if ( ! woptions(&curp, optarg))
                        break;
                case ('W'):
                        if ( ! woptions(&curp, optarg))
-                               return(MANDOCLEVEL_BADARG);
+                               return((int)MANDOCLEVEL_BADARG);
                        break;
                case ('V'):
                        version();
                        break;
                case ('V'):
                        version();
@@ -279,7 +283,7 @@ main(int argc, char *argv[])
        if (curp.roff)
                roff_free(curp.roff);
 
        if (curp.roff)
                roff_free(curp.roff);
 
-       return(exit_status);
+       return((int)exit_status);
 }
 
 
 }
 
 
@@ -288,7 +292,7 @@ version(void)
 {
 
        (void)printf("%s %s\n", progname, VERSION);
 {
 
        (void)printf("%s %s\n", progname, VERSION);
-       exit(MANDOCLEVEL_OK);
+       exit((int)MANDOCLEVEL_OK);
 }
 
 
 }
 
 
@@ -299,7 +303,7 @@ usage(void)
        (void)fprintf(stderr, "usage: %s [-V] [-foption] "
                        "[-mformat] [-Ooption] [-Toutput] "
                        "[-Werr] [file...]\n", progname);
        (void)fprintf(stderr, "usage: %s [-V] [-foption] "
                        "[-mformat] [-Ooption] [-Toutput] "
                        "[-Werr] [file...]\n", progname);
-       exit(MANDOCLEVEL_BADARG);
+       exit((int)MANDOCLEVEL_BADARG);
 }
 
 
 }
 
 
@@ -320,6 +324,35 @@ ffile(const char *file, struct curparse *curp)
                perror(curp->file);
 }
 
                perror(curp->file);
 }
 
+static int
+pfile(const char *file, struct curparse *curp)
+{
+       const char      *savefile;
+       int              fd, savefd;
+
+       if (-1 == (fd = open(file, O_RDONLY, 0))) {
+               perror(file);
+               exit_status = MANDOCLEVEL_SYSERR;
+               return(0);
+       }
+
+       savefile = curp->file;
+       savefd = curp->fd;
+
+       curp->file = file;
+       curp->fd = fd;
+
+       pdesc(curp);
+
+       curp->file = savefile;
+       curp->fd = savefd;
+
+       if (-1 == close(fd))
+               perror(file);
+
+       return(MANDOCLEVEL_FATAL > exit_status ? 1 : 0);
+}
+
 
 static void
 resize_buf(struct buf *buf, size_t initial)
 
 static void
 resize_buf(struct buf *buf, size_t initial)
@@ -329,7 +362,7 @@ resize_buf(struct buf *buf, size_t initial)
        buf->buf = realloc(buf->buf, buf->sz);
        if (NULL == buf->buf) {
                perror(NULL);
        buf->buf = realloc(buf->buf, buf->sz);
        if (NULL == buf->buf) {
                perror(NULL);
-               exit(MANDOCLEVEL_SYSERR);
+               exit((int)MANDOCLEVEL_SYSERR);
        }
 }
 
        }
 }
 
@@ -406,25 +439,127 @@ read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
 static void
 fdesc(struct curparse *curp)
 {
 static void
 fdesc(struct curparse *curp)
 {
-       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;
 
-       man = NULL;
-       mdoc = NULL;
-       roff = NULL;
+       pdesc(curp);
 
 
-       memset(&ln, 0, sizeof(struct buf));
+       man  = curp->man;
+       mdoc = curp->mdoc;
+       roff = curp->roff;
+
+       if (MANDOCLEVEL_FATAL <= exit_status)
+               goto cleanup;
+
+       /* NOTE a parser may not have been assigned, yet. */
+
+       if ( ! (man || mdoc)) {
+               fprintf(stderr, "%s: Not a manual\n", curp->file);
+               exit_status = MANDOCLEVEL_FATAL;
+               goto cleanup;
+       }
+
+       /* Clean up the parse routine ASTs. */
+
+       if (mdoc && ! mdoc_endparse(mdoc)) {
+               assert(MANDOCLEVEL_FATAL <= exit_status);
+               goto cleanup;
+       }
+       if (man && ! man_endparse(man)) {
+               assert(MANDOCLEVEL_FATAL <= exit_status);
+               goto cleanup;
+       }
+       if (roff && ! roff_endparse(roff)) {
+               assert(MANDOCLEVEL_FATAL <= exit_status);
+               goto cleanup;
+       }
 
        /*
 
        /*
-        * Two buffers: ln and buf.  buf is the input file and may be
-        * memory mapped.  ln is a line buffer and grows on-demand.
+        * With -Wstop and warnings or errors of at least
+        * the requested level, do not produce output.
         */
 
         */
 
+       if (MANDOCLEVEL_OK != exit_status && curp->wstop)
+               goto cleanup;
+
+       /* If unset, allocate output dev now (if applicable). */
+
+       if ( ! (curp->outman && curp->outmdoc)) {
+               switch (curp->outtype) {
+               case (OUTT_XHTML):
+                       curp->outdata = xhtml_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;
+                       break;
+               case (OUTT_TREE):
+                       curp->outman = tree_man;
+                       curp->outmdoc = tree_mdoc;
+                       break;
+               case (OUTT_PDF):
+                       /* FALLTHROUGH */
+               case (OUTT_ASCII):
+                       /* FALLTHROUGH */
+               case (OUTT_PS):
+                       curp->outman = terminal_man;
+                       curp->outmdoc = terminal_mdoc;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* Execute the out device, if it exists. */
+
+       if (man && curp->outman)
+               (*curp->outman)(curp->outdata, man);
+       if (mdoc && curp->outmdoc)
+               (*curp->outmdoc)(curp->outdata, mdoc);
+
+ cleanup:
+       memset(&curp->regs, 0, sizeof(struct regset));
+       if (mdoc)
+               mdoc_reset(mdoc);
+       if (man)
+               man_reset(man);
+       if (roff)
+               roff_reset(roff);
+
+       return;
+}
+
+
+static void
+pdesc(struct curparse *curp)
+{
+       struct buf       blk;
+       int              with_mmap;
+
        if ( ! read_whole_file(curp, &blk, &with_mmap)) {
                exit_status = MANDOCLEVEL_SYSERR;
                return;
        if ( ! read_whole_file(curp, &blk, &with_mmap)) {
                exit_status = MANDOCLEVEL_SYSERR;
                return;
@@ -433,12 +568,42 @@ fdesc(struct curparse *curp)
        if (NULL == curp->roff) 
                curp->roff = roff_alloc(&curp->regs, curp, mmsg);
        assert(curp->roff);
        if (NULL == curp->roff) 
                curp->roff = roff_alloc(&curp->regs, curp, mmsg);
        assert(curp->roff);
+
+       curp->line = 1;
+       parsebuf(curp, blk, 1);
+
+       if (with_mmap)
+               munmap(blk.buf, blk.sz);
+       else
+               free(blk.buf);
+}
+
+static void
+parsebuf(struct curparse *curp, struct buf blk, int start)
+{
+       struct buf       ln;
+       int              i, pos, lnn, of;
+       unsigned char    c;
+       struct man      *man;
+       struct mdoc     *mdoc;
+       struct roff     *roff;
+
+       man  = curp->man;
+       mdoc = curp->mdoc;
        roff = curp->roff;
 
        roff = curp->roff;
 
-       for (i = 0, lnn = 1; i < (int)blk.sz;) {
-               pos = 0;
-               lnn_start = lnn;
-               while (i < (int)blk.sz) {
+       memset(&ln, 0, sizeof(struct buf));
+
+       lnn = curp->line;  /* line number in the real file */
+       pos = 0;  /* byte number in the ln buffer */
+
+       for (i = 0; i < (int)blk.sz;) {
+               if (0 == pos && '\0' == blk.buf[i])
+                       break;
+               if (start)
+                       curp->line = lnn;
+
+               while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
                        if ('\n' == blk.buf[i]) {
                                ++i;
                                ++lnn;
                        if ('\n' == blk.buf[i]) {
                                ++i;
                                ++lnn;
@@ -457,7 +622,7 @@ fdesc(struct curparse *curp)
                        c = (unsigned char) blk.buf[i];
                        if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) {
                                mmsg(MANDOCERR_BADCHAR, curp, 
                        c = (unsigned char) blk.buf[i];
                        if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) {
                                mmsg(MANDOCERR_BADCHAR, curp, 
-                                   lnn_start, pos, "ignoring byte");
+                                   curp->line, pos, "ignoring byte");
                                i++;
                                continue;
                        }
                                i++;
                                continue;
                        }
@@ -517,16 +682,32 @@ fdesc(struct curparse *curp)
                 */
 
                of = 0;
                 */
 
                of = 0;
-               do {
-                       re = roff_parseln(roff, lnn_start, 
-                                       &ln.buf, &ln.sz, of, &of);
-               } while (ROFF_RERUN == re);
-
-               if (ROFF_IGN == re) {
+rerun:
+               switch (roff_parseln(roff, curp->line, &ln.buf, &ln.sz,
+                   of, &of)) {
+               case (ROFF_REPARSE):
+                       parsebuf(curp, ln, 0);
+                       pos = 0;
+                       continue;
+               case (ROFF_APPEND):
+                       pos = strlen(ln.buf);
                        continue;
                        continue;
-               } else if (ROFF_ERR == re) {
+               case (ROFF_RERUN):
+                       goto rerun;
+               case (ROFF_IGN):
+                       pos = 0;
+                       continue;
+               case (ROFF_ERR):
                        assert(MANDOCLEVEL_FATAL <= exit_status);
                        assert(MANDOCLEVEL_FATAL <= exit_status);
-                       goto cleanup;
+                       break;
+               case (ROFF_SO):
+                       if (pfile(ln.buf + of, curp)) {
+                               pos = 0;
+                               continue;
+                       } else
+                               break;
+               case (ROFF_CONT):
+                       break;
                }
 
                /*
                }
 
                /*
@@ -541,121 +722,24 @@ fdesc(struct curparse *curp)
 
                /* Lastly, push down into the parsers themselves. */
 
 
                /* Lastly, push down into the parsers themselves. */
 
-               if (man && ! man_parseln(man, lnn_start, ln.buf, of)) {
+               if (man && ! man_parseln(man, curp->line, ln.buf, of)) {
                        assert(MANDOCLEVEL_FATAL <= exit_status);
                        assert(MANDOCLEVEL_FATAL <= exit_status);
-                       goto cleanup;
+                       break;
                }
                }
-               if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of)) {
+               if (mdoc && ! mdoc_parseln(mdoc, curp->line, ln.buf, of)) {
                        assert(MANDOCLEVEL_FATAL <= exit_status);
                        assert(MANDOCLEVEL_FATAL <= exit_status);
-                       goto cleanup;
-               }
-       }
-
-       /*
-        * With -Wstop and warnings or errors of at least
-        * the requested level, do not produce output.
-        */
-
-       if (MANDOCLEVEL_OK != exit_status && curp->wstop)
-               goto cleanup;
-
-       /* NOTE a parser may not have been assigned, yet. */
-
-       if ( ! (man || mdoc)) {
-               fprintf(stderr, "%s: Not a manual\n", curp->file);
-               exit_status = MANDOCLEVEL_FATAL;
-               goto cleanup;
-       }
-
-       /* Clean up the parse routine ASTs. */
-
-       if (mdoc && ! mdoc_endparse(mdoc)) {
-               assert(MANDOCLEVEL_FATAL <= exit_status);
-               goto cleanup;
-       }
-       if (man && ! man_endparse(man)) {
-               assert(MANDOCLEVEL_FATAL <= exit_status);
-               goto cleanup;
-       }
-       if (roff && ! roff_endparse(roff)) {
-               assert(MANDOCLEVEL_FATAL <= exit_status);
-               goto cleanup;
-       }
-
-       /* If unset, allocate output dev now (if applicable). */
-
-       if ( ! (curp->outman && curp->outmdoc)) {
-               switch (curp->outtype) {
-               case (OUTT_XHTML):
-                       curp->outdata = xhtml_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;
                }
 
                        break;
                }
 
-               switch (curp->outtype) {
-               case (OUTT_HTML):
-                       /* FALLTHROUGH */
-               case (OUTT_XHTML):
-                       curp->outman = html_man;
-                       curp->outmdoc = html_mdoc;
-                       curp->outfree = html_free;
-                       break;
-               case (OUTT_TREE):
-                       curp->outman = tree_man;
-                       curp->outmdoc = tree_mdoc;
-                       break;
-               case (OUTT_PDF):
-                       /* FALLTHROUGH */
-               case (OUTT_ASCII):
-                       /* FALLTHROUGH */
-               case (OUTT_PS):
-                       curp->outman = terminal_man;
-                       curp->outmdoc = terminal_mdoc;
-                       break;
-               default:
+               /* Temporary buffers typically are not full. */
+               if (0 == start && '\0' == blk.buf[i])
                        break;
                        break;
-               }
-       }
-
-       /* Execute the out device, if it exists. */
-
-       if (man && curp->outman)
-               (*curp->outman)(curp->outdata, man);
-       if (mdoc && curp->outmdoc)
-               (*curp->outmdoc)(curp->outdata, mdoc);
 
 
- cleanup:
-       memset(&curp->regs, 0, sizeof(struct regset));
-       if (mdoc)
-               mdoc_reset(mdoc);
-       if (man)
-               man_reset(man);
-       if (roff)
-               roff_reset(roff);
-       if (ln.buf)
-               free(ln.buf);
-       if (with_mmap)
-               munmap(blk.buf, blk.sz);
-       else
-               free(blk.buf);
+               /* Start the next input line. */
+               pos = 0;
+       }
 
 
-       return;
+       free(ln.buf);
 }
 
 
 }
 
 
@@ -809,6 +893,7 @@ mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
 
        level = MANDOCLEVEL_FATAL;
        while (t < mandoclimits[level])
 
        level = MANDOCLEVEL_FATAL;
        while (t < mandoclimits[level])
+               /* LINTED */
                level--;
 
        cp = (struct curparse *)arg;
                level--;
 
        cp = (struct curparse *)arg;