]> 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 63b778f42718bc9600c47a59650467bff4285344..496024e1c3ea94c5c10cb0b176ff830776a9b2aa 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
-/*     $Id: main.c,v 1.134 2011/01/04 12:06:21 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) 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
  *
  * 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
 #endif
 
 #define        REPARSE_LIMIT   1000
-#define        UNCONST(a)      ((void *)(uintptr_t)(const void *)(a))
 
 /* FIXME: Intel's compiler?  LLVM?  pcc?  */
 
 
 /* FIXME: Intel's compiler?  LLVM?  pcc?  */
 
@@ -78,11 +77,13 @@ enum        outt {
 };
 
 struct curparse {
 };
 
 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 */
        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",
        "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",
        "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",
        /* 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",
        "blocks badly nested",
        "child violates parent syntax",
        "nested displays are not portable",
@@ -158,6 +161,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "list type must come first",
        "tag lists require a width argument",
        "missing font type",
        "list type must come first",
        "tag lists require a width argument",
        "missing font type",
+       "skipping end of block that is not open",
 
        /* related to bad macro arguments */
        "skipping argument",
 
        /* related to bad macro arguments */
        "skipping argument",
@@ -178,9 +182,6 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "unknown escape sequence",
        "unterminated quoted string",
        
        "unknown escape sequence",
        "unterminated quoted string",
        
-       /* related to tables */
-       "extra data cells",
-
        "generic error",
 
        /* related to tables */
        "generic error",
 
        /* related to tables */
@@ -190,12 +191,15 @@ static    const char * const      mandocerrs[MANDOCERR_MAX] = {
        "no table layout cells specified",
        "no table data cells specified",
        "ignore data in cell",
        "no table layout cells specified",
        "no table data cells specified",
        "ignore data in cell",
+       "data block still open",
+       "ignoring extra data cells",
 
        "input stack limit exceeded, infinite loop?",
        "skipping bad character",
 
        "input stack limit exceeded, infinite loop?",
        "skipping bad character",
+       "escaped character not allowed in a name",
        "skipping text before the first section header",
        "skipping unknown macro",
        "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",
        "line scope broken",
        "argument count wrong",
        "skipping end of block that is not open",
@@ -238,8 +242,6 @@ static      void              version(void) __attribute__((noreturn));
 static int               woptions(struct curparse *, char *);
 
 static const char       *progname;
 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[])
 
 int
 main(int argc, char *argv[])
@@ -258,6 +260,7 @@ main(int argc, char *argv[])
        curp.inttype = INTT_AUTO;
        curp.outtype = OUTT_ASCII;
        curp.wlevel  = MANDOCLEVEL_FATAL;
        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:")))
 
        /* LINTED */
        while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
@@ -298,7 +301,7 @@ main(int argc, char *argv[])
 
        while (*argv) {
                ffile(*argv, &curp);
 
        while (*argv) {
                ffile(*argv, &curp);
-               if (MANDOCLEVEL_OK != exit_status && curp.wstop)
+               if (MANDOCLEVEL_OK != curp.exit_status && curp.wstop)
                        break;
                ++argv;
        }
                        break;
                ++argv;
        }
@@ -312,7 +315,7 @@ main(int argc, char *argv[])
        if (curp.roff)
                roff_free(curp.roff);
 
        if (curp.roff)
                roff_free(curp.roff);
 
-       return((int)exit_status);
+       return((int)curp.exit_status);
 }
 
 
 }
 
 
@@ -357,7 +360,7 @@ ffile(const char *file, struct curparse *curp)
 
        if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
                perror(curp->file);
 
        if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
                perror(curp->file);
-               exit_status = MANDOCLEVEL_SYSERR;
+               curp->exit_status = MANDOCLEVEL_SYSERR;
                return;
        }
 
                return;
        }
 
@@ -375,7 +378,7 @@ pfile(const char *file, struct curparse *curp)
 
        if (-1 == (fd = open(file, O_RDONLY, 0))) {
                perror(file);
 
        if (-1 == (fd = open(file, O_RDONLY, 0))) {
                perror(file);
-               file_status = MANDOCLEVEL_SYSERR;
+               curp->file_status = MANDOCLEVEL_SYSERR;
                return(0);
        }
 
                return(0);
        }
 
@@ -393,7 +396,7 @@ pfile(const char *file, struct curparse *curp)
        if (-1 == close(fd))
                perror(file);
 
        if (-1 == close(fd))
                perror(file);
 
-       return(MANDOCLEVEL_FATAL > file_status ? 1 : 0);
+       return(MANDOCLEVEL_FATAL > curp->file_status ? 1 : 0);
 }
 
 
 }
 
 
@@ -497,7 +500,7 @@ fdesc(struct curparse *curp)
 
        curp->mdoc = NULL;
        curp->man = NULL;
 
        curp->mdoc = NULL;
        curp->man = NULL;
-       file_status = MANDOCLEVEL_OK;
+       curp->file_status = MANDOCLEVEL_OK;
 
        /* Make sure the mandotory roff parser is initialised. */
 
 
        /* Make sure the mandotory roff parser is initialised. */
 
@@ -510,26 +513,26 @@ fdesc(struct curparse *curp)
 
        pdesc(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);
                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)) {
                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)) {
                goto cleanup;
        }
 
        if (curp->man && ! man_endparse(curp->man)) {
-               assert(MANDOCLEVEL_FATAL <= file_status);
+               assert(MANDOCLEVEL_FATAL <= curp->file_status);
                goto cleanup;
        }
 
                goto cleanup;
        }
 
@@ -541,7 +544,7 @@ fdesc(struct curparse *curp)
         * the requested level, do not produce output.
         */
 
         * 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). */
                goto cleanup;
 
        /* If unset, allocate output dev now (if applicable). */
@@ -616,8 +619,8 @@ fdesc(struct curparse *curp)
        assert(curp->roff);
        roff_reset(curp->roff);
 
        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;
 }
 
        return;
 }
@@ -636,7 +639,7 @@ pdesc(struct curparse *curp)
         */
 
        if ( ! read_whole_file(curp, &blk, &with_mmap)) {
         */
 
        if ( ! read_whole_file(curp, &blk, &with_mmap)) {
-               file_status = MANDOCLEVEL_SYSERR;
+               curp->file_status = MANDOCLEVEL_SYSERR;
                return;
        }
 
                return;
        }
 
@@ -652,9 +655,15 @@ pdesc(struct curparse *curp)
                free(blk.buf);
 }
 
                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)
 {
 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;
        struct buf       ln;
        enum rofferr     rr;
        int              i, of, rc;
@@ -662,12 +671,6 @@ parsebuf(struct curparse *curp, struct buf blk, int start)
        int              lnn; /* line number in the real file */
        unsigned char    c;
 
        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; 
        memset(&ln, 0, sizeof(struct buf));
 
        lnn = curp->line; 
@@ -683,6 +686,16 @@ parsebuf(struct curparse *curp, struct buf blk, int start)
                }
 
                while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
                }
 
                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;
                        if ('\n' == blk.buf[i]) {
                                ++i;
                                ++lnn;
@@ -717,11 +730,18 @@ parsebuf(struct curparse *curp, struct buf blk, int start)
                                continue;
                        }
 
                                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;
                        if ('\n' == blk.buf[i + 1]) {
                                i += 2;
-                               /* Escaped newlines are skipped over */
                                ++lnn;
                                continue;
                        }
                                ++lnn;
                                continue;
                        }
@@ -787,7 +807,7 @@ rerun:
                        pos = 0;
                        continue;
                case (ROFF_APPEND):
                        pos = 0;
                        continue;
                case (ROFF_APPEND):
-                       pos = strlen(ln.buf);
+                       pos = (int)strlen(ln.buf);
                        continue;
                case (ROFF_RERUN):
                        goto rerun;
                        continue;
                case (ROFF_RERUN):
                        goto rerun;
@@ -795,7 +815,7 @@ rerun:
                        pos = 0;
                        continue;
                case (ROFF_ERR):
                        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)) {
                        break;
                case (ROFF_SO):
                        if (pfile(ln.buf + of, curp)) {
@@ -812,7 +832,7 @@ rerun:
                 * call, make sure we don't continue parsing.
                 */
 
                 * call, make sure we don't continue parsing.
                 */
 
-               if (MANDOCLEVEL_FATAL <= file_status)
+               if (MANDOCLEVEL_FATAL <= curp->file_status)
                        break;
 
                /*
                        break;
 
                /*
@@ -833,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.
                 * 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);
 
                        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. */
                }
 
                /* Temporary buffers typically are not full. */
@@ -1032,8 +1061,8 @@ mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
                fprintf(stderr, ": %s", msg);
        fputc('\n', stderr);
 
                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);
 }
        
        return(level < MANDOCLEVEL_FATAL);
 }