]> git.cameronkatri.com Git - mandoc.git/commitdiff
Merge restructuring of main.c code. This provided by schwarze@ and inspected
authorKristaps Dzonsons <kristaps@bsd.lv>
Wed, 1 Dec 2010 15:09:01 +0000 (15:09 +0000)
committerKristaps Dzonsons <kristaps@bsd.lv>
Wed, 1 Dec 2010 15:09:01 +0000 (15:09 +0000)
carefully by joerg@.  Merge roff.h header for compilation's sake (this is not
yet implemented in roff.c.).

THIS IS A BUGGY CHECK-IN.  The manual type is erroneously kept between runs
of the compiler.  This is a known bug.

main.c
roff.h

diff --git a/main.c b/main.c
index 1664825d874c71517bb31780baad8acaec0b47c7..ee51348e11317d787851379372fad25e35fbfb6d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/*     $Id: main.c,v 1.110 2010/12/01 10:31:34 kristaps 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>
@@ -79,6 +79,7 @@ enum  outt {
 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 */
@@ -193,8 +194,11 @@ static     const char * const      mandocerrs[MANDOCERR_MAX] = {
        "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 int               pfile(const char *, struct curparse *);
 static int               moptions(enum intt *, char *);
 static int               mmsg(enum mandocerr, void *, 
                                int, int, const char *);
@@ -320,6 +324,35 @@ ffile(const char *file, struct curparse *curp)
                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)
@@ -406,25 +439,127 @@ read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
 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;
 
-       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;
@@ -433,12 +568,42 @@ fdesc(struct curparse *curp)
        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;
 
-       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;
@@ -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, 
-                                   lnn_start, pos, "ignoring byte");
+                                   curp->line, pos, "ignoring byte");
                                i++;
                                continue;
                        }
@@ -517,16 +682,32 @@ fdesc(struct curparse *curp)
                 */
 
                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;
-               } else if (ROFF_ERR == re) {
+               case (ROFF_RERUN):
+                       goto rerun;
+               case (ROFF_IGN):
+                       pos = 0;
+                       continue;
+               case (ROFF_ERR):
                        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. */
 
-               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);
-                       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);
-                       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;
-       }
-
-       /*
-        * 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;
+               /* Temporary buffers typically are not full. */
+               if (0 == start && '\0' == blk.buf[i])
                        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);
-       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);
 }
 
 
diff --git a/roff.h b/roff.h
index 277e2b2291e3c0040db2cbc0c5440e17f79bcebb..3624308f452158767c14c75b87a4e9b6cad15d09 100644 (file)
--- a/roff.h
+++ b/roff.h
@@ -1,4 +1,4 @@
-/*     $Id: roff.h,v 1.18 2010/08/20 01:02:07 schwarze Exp $ */
+/*     $Id: roff.h,v 1.19 2010/12/01 15:09:01 kristaps Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -20,6 +20,9 @@
 enum   rofferr {
        ROFF_CONT, /* continue processing line */
        ROFF_RERUN, /* re-run roff interpreter with offset */
+       ROFF_APPEND, /* re-run main parser, appending next line */
+       ROFF_REPARSE, /* re-run main parser on the result */
+       ROFF_SO, /* include another file */
        ROFF_IGN, /* ignore current line */
        ROFF_ERR /* badness: puke and stop */
 };