]> git.cameronkatri.com Git - mandoc.git/blobdiff - main.c
Move check for closing punctuation into its own function. This will
[mandoc.git] / main.c
diff --git a/main.c b/main.c
index a83f8aeb2e133db9b8093766dc17dfcf37167712..496024e1c3ea94c5c10cb0b176ff830776a9b2aa 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
-/*     $Id: main.c,v 1.138 2011/01/12 15:50:42 kristaps Exp $ */
+/*     $Id: main.c,v 1.151 2011/03/16 15:28:35 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011 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
@@ -42,7 +42,6 @@
 #endif
 
 #define        REPARSE_LIMIT   1000
-#define        UNCONST(a)      ((void *)(uintptr_t)(const void *)(a))
 
 /* FIXME: Intel's compiler?  LLVM?  pcc?  */
 
@@ -78,11 +77,13 @@ 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 mandoclevel  exit_status;  /* status of all file parses */
+       const char       *file;         /* current file-name */
+       enum mandoclevel  file_status;  /* error status of current parse */
+       int               fd;           /* current file-descriptor */
+       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 */
        struct man       *pman;         /* persistent man parser */
        struct mdoc      *pmdoc;        /* persistent mdoc parser */
@@ -128,7 +129,8 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "no title in document",
        "document title should be all caps",
        "unknown manual section",
-       "cannot parse date argument",
+       "date missing, using today's date",
+       "cannot parse date, using it verbatim",
        "prologue macros out of order",
        "duplicate prologue macro",
        "macro not allowed in prologue",
@@ -146,6 +148,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        /* related to macros and nesting */
        "skipping obsolete macro",
        "skipping paragraph macro",
+       "skipping no-space macro",
        "blocks badly nested",
        "child violates parent syntax",
        "nested displays are not portable",
@@ -196,7 +199,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "escaped character not allowed in a name",
        "skipping text before the first section header",
        "skipping unknown macro",
-       "NOT IMPLEMENTED: skipping request",
+       "NOT IMPLEMENTED, please use groff: skipping request",
        "line scope broken",
        "argument count wrong",
        "skipping end of block that is not open",
@@ -239,8 +242,6 @@ static      void              version(void) __attribute__((noreturn));
 static int               woptions(struct curparse *, char *);
 
 static const char       *progname;
-static enum mandoclevel  file_status = MANDOCLEVEL_OK;
-static enum mandoclevel  exit_status = MANDOCLEVEL_OK;
 
 int
 main(int argc, char *argv[])
@@ -259,6 +260,7 @@ main(int argc, char *argv[])
        curp.inttype = INTT_AUTO;
        curp.outtype = OUTT_ASCII;
        curp.wlevel  = MANDOCLEVEL_FATAL;
+       curp.exit_status = MANDOCLEVEL_OK;
 
        /* LINTED */
        while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
@@ -299,7 +301,7 @@ main(int argc, char *argv[])
 
        while (*argv) {
                ffile(*argv, &curp);
-               if (MANDOCLEVEL_OK != exit_status && curp.wstop)
+               if (MANDOCLEVEL_OK != curp.exit_status && curp.wstop)
                        break;
                ++argv;
        }
@@ -313,7 +315,7 @@ main(int argc, char *argv[])
        if (curp.roff)
                roff_free(curp.roff);
 
-       return((int)exit_status);
+       return((int)curp.exit_status);
 }
 
 
@@ -358,7 +360,7 @@ ffile(const char *file, struct curparse *curp)
 
        if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
                perror(curp->file);
-               exit_status = MANDOCLEVEL_SYSERR;
+               curp->exit_status = MANDOCLEVEL_SYSERR;
                return;
        }
 
@@ -376,7 +378,7 @@ pfile(const char *file, struct curparse *curp)
 
        if (-1 == (fd = open(file, O_RDONLY, 0))) {
                perror(file);
-               file_status = MANDOCLEVEL_SYSERR;
+               curp->file_status = MANDOCLEVEL_SYSERR;
                return(0);
        }
 
@@ -394,7 +396,7 @@ pfile(const char *file, struct curparse *curp)
        if (-1 == close(fd))
                perror(file);
 
-       return(MANDOCLEVEL_FATAL > file_status ? 1 : 0);
+       return(MANDOCLEVEL_FATAL > curp->file_status ? 1 : 0);
 }
 
 
@@ -498,7 +500,7 @@ fdesc(struct curparse *curp)
 
        curp->mdoc = NULL;
        curp->man = NULL;
-       file_status = MANDOCLEVEL_OK;
+       curp->file_status = MANDOCLEVEL_OK;
 
        /* Make sure the mandotory roff parser is initialised. */
 
@@ -511,26 +513,26 @@ fdesc(struct curparse *curp)
 
        pdesc(curp);
 
-       if (MANDOCLEVEL_FATAL <= file_status)
+       if (MANDOCLEVEL_FATAL <= curp->file_status)
                goto cleanup;
 
        /* NOTE a parser may not have been assigned, yet. */
 
        if ( ! (curp->man || curp->mdoc)) {
                fprintf(stderr, "%s: Not a manual\n", curp->file);
-               file_status = MANDOCLEVEL_FATAL;
+               curp->file_status = MANDOCLEVEL_FATAL;
                goto cleanup;
        }
 
        /* Clean up the parse routine ASTs. */
 
        if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
-               assert(MANDOCLEVEL_FATAL <= file_status);
+               assert(MANDOCLEVEL_FATAL <= curp->file_status);
                goto cleanup;
        }
 
        if (curp->man && ! man_endparse(curp->man)) {
-               assert(MANDOCLEVEL_FATAL <= file_status);
+               assert(MANDOCLEVEL_FATAL <= curp->file_status);
                goto cleanup;
        }
 
@@ -542,7 +544,7 @@ fdesc(struct curparse *curp)
         * the requested level, do not produce output.
         */
 
-       if (MANDOCLEVEL_OK != file_status && curp->wstop)
+       if (MANDOCLEVEL_OK != curp->file_status && curp->wstop)
                goto cleanup;
 
        /* If unset, allocate output dev now (if applicable). */
@@ -617,8 +619,8 @@ fdesc(struct curparse *curp)
        assert(curp->roff);
        roff_reset(curp->roff);
 
-       if (exit_status < file_status)
-               exit_status = file_status;
+       if (curp->exit_status < curp->file_status)
+               curp->exit_status = curp->file_status;
 
        return;
 }
@@ -637,7 +639,7 @@ pdesc(struct curparse *curp)
         */
 
        if ( ! read_whole_file(curp, &blk, &with_mmap)) {
-               file_status = MANDOCLEVEL_SYSERR;
+               curp->file_status = MANDOCLEVEL_SYSERR;
                return;
        }
 
@@ -653,9 +655,15 @@ pdesc(struct curparse *curp)
                free(blk.buf);
 }
 
+/*
+ * Main parse routine for an opened file.  This is called for each
+ * opened file and simply loops around the full input file, possibly
+ * nesting (i.e., with `so').
+ */
 static void
 parsebuf(struct curparse *curp, struct buf blk, int start)
 {
+       const struct tbl_span   *span;
        struct buf       ln;
        enum rofferr     rr;
        int              i, of, rc;
@@ -663,12 +671,6 @@ parsebuf(struct curparse *curp, struct buf blk, int start)
        int              lnn; /* line number in the real file */
        unsigned char    c;
 
-       /*
-        * Main parse routine for an opened file.  This is called for
-        * each opened file and simply loops around the full input file,
-        * possibly nesting (i.e., with `so').
-        */
-
        memset(&ln, 0, sizeof(struct buf));
 
        lnn = curp->line; 
@@ -684,6 +686,16 @@ parsebuf(struct curparse *curp, struct buf blk, int start)
                }
 
                while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
+
+                       /*
+                        * When finding an unescaped newline character,
+                        * leave the character loop to process the line.
+                        * Skip a preceding carriage return, if any.
+                        */
+
+                       if ('\r' == blk.buf[i] && i + 1 < (int)blk.sz &&
+                           '\n' == blk.buf[i + 1])
+                               ++i;
                        if ('\n' == blk.buf[i]) {
                                ++i;
                                ++lnn;
@@ -718,11 +730,18 @@ parsebuf(struct curparse *curp, struct buf blk, int start)
                                continue;
                        }
 
-                       /* Found escape & at least one other char. */
+                       /*
+                        * Found escape and at least one other character.
+                        * When it's a newline character, skip it.
+                        * When there is a carriage return in between,
+                        * skip that one as well.
+                        */
 
+                       if ('\r' == blk.buf[i + 1] && i + 2 < (int)blk.sz &&
+                           '\n' == blk.buf[i + 2])
+                               ++i;
                        if ('\n' == blk.buf[i + 1]) {
                                i += 2;
-                               /* Escaped newlines are skipped over */
                                ++lnn;
                                continue;
                        }
@@ -788,7 +807,7 @@ rerun:
                        pos = 0;
                        continue;
                case (ROFF_APPEND):
-                       pos = strlen(ln.buf);
+                       pos = (int)strlen(ln.buf);
                        continue;
                case (ROFF_RERUN):
                        goto rerun;
@@ -796,7 +815,7 @@ rerun:
                        pos = 0;
                        continue;
                case (ROFF_ERR):
-                       assert(MANDOCLEVEL_FATAL <= file_status);
+                       assert(MANDOCLEVEL_FATAL <= curp->file_status);
                        break;
                case (ROFF_SO):
                        if (pfile(ln.buf + of, curp)) {
@@ -813,7 +832,7 @@ rerun:
                 * call, make sure we don't continue parsing.
                 */
 
-               if (MANDOCLEVEL_FATAL <= file_status)
+               if (MANDOCLEVEL_FATAL <= curp->file_status)
                        break;
 
                /*
@@ -834,26 +853,35 @@ rerun:
                 * currently open parse.  Since we only get here if
                 * there does exist data (see tbl_data.c), we're
                 * guaranteed that something's been allocated.
+                * Do the same for ROFF_EQN.
                 */
 
-               if (ROFF_TBL == rr) {
-                       assert(curp->man || curp->mdoc);
-                       if (curp->man)
-                               man_addspan(curp->man, roff_span(curp->roff));
-                       else
-                               mdoc_addspan(curp->mdoc, roff_span(curp->roff));
+               rc = -1;
 
-               } else if (curp->man || curp->mdoc) {
+               if (ROFF_TBL == rr)
+                       while (NULL != (span = roff_span(curp->roff))) {
+                               rc = curp->man ?
+                                       man_addspan(curp->man, span) :
+                                       mdoc_addspan(curp->mdoc, span);
+                               if (0 == rc)
+                                       break;
+                       }
+               else if (ROFF_EQN == rr)
+                       rc = curp->mdoc ? 
+                               mdoc_addeqn(curp->mdoc, 
+                                       roff_eqn(curp->roff)) :
+                               man_addeqn(curp->man,
+                                       roff_eqn(curp->roff));
+               else if (curp->man || curp->mdoc)
                        rc = curp->man ?
                                man_parseln(curp->man, 
                                        curp->line, ln.buf, of) :
                                mdoc_parseln(curp->mdoc, 
                                        curp->line, ln.buf, of);
 
-                       if ( ! rc) {
-                               assert(MANDOCLEVEL_FATAL <= file_status);
-                               break;
-                       }
+               if (0 == rc) {
+                       assert(MANDOCLEVEL_FATAL <= curp->file_status);
+                       break;
                }
 
                /* Temporary buffers typically are not full. */
@@ -1033,8 +1061,8 @@ mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
                fprintf(stderr, ": %s", msg);
        fputc('\n', stderr);
 
-       if (file_status < level)
-               file_status = level;
+       if (cp->file_status < level)
+               cp->file_status = level;
        
        return(level < MANDOCLEVEL_FATAL);
 }