]> git.cameronkatri.com Git - mandoc.git/commitdiff
No more segfaults when run over openbsd sources.
authorKristaps Dzonsons <kristaps@bsd.lv>
Mon, 1 Dec 2008 21:25:48 +0000 (21:25 +0000)
committerKristaps Dzonsons <kristaps@bsd.lv>
Mon, 1 Dec 2008 21:25:48 +0000 (21:25 +0000)
Makefile
roff.c

index d799d62703a034af5482276dca469599051986c2..fb85076f25b088869aefb6d1349e713f07b83efa 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ FAIL  = test.0 test.1 test.2 test.3 test.4 test.5 test.6 \
 
 SUCCEED        = test.7 test.8 test.9 test.10 test.11 test.12 test.13 \
          test.14 test.16 test.17 test.18 test.19 test.21 test.23 \
-         test.25 test.28 test.29
+         test.25 test.28 test.29 test.31
 
 
 all: mdocml
diff --git a/roff.c b/roff.c
index efcfcc50ad18f311f5414cf9dcf5758f9e3a8a49..1441389419fc869c9068abf71b1d5cf114fc86b9 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.29 2008/12/01 16:14:34 kristaps Exp $ */
+/* $Id: roff.c,v 1.30 2008/12/01 21:25:48 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -16,6 +16,8 @@
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  * PERFORMANCE OF THIS SOFTWARE.
  */
+#include <sys/param.h>
+
 #include <assert.h>
 #include <ctype.h>
 #include <err.h>
@@ -90,7 +92,7 @@ struct        rofftree {
        struct roffnode  *last;                 /* Last parsed node. */
        char             *cur;
 
-       time_t            date;                 /* `Dd' results. */
+       struct tm         tm;                   /* `Dd' results. */
        char              os[64];               /* `Os' results. */
        char              title[64];            /* `Dt' results. */
        char              section[64];          /* `Dt' results. */
@@ -397,6 +399,9 @@ roff_free(struct rofftree *tree, int flush)
                        goto end;
        }
 
+       if ( ! (*tree->cb.rofftail)(tree->arg))
+               goto end;
+
        error = 0;
 
 end:
@@ -451,6 +456,10 @@ static int
 textparse(const struct rofftree *tree, char *buf)
 {
 
+       if ( ! (ROFF_BODY & tree->state)) {
+               roff_err(tree, buf, "data not in body");
+               return(0);
+       }
        return((*tree->cb.roffdata)(tree->arg, 1, buf));
 }
 
@@ -897,6 +906,8 @@ roffparseopts(struct rofftree *tree, int tok,
 static int
 roff_Dd(ROFFCALL_ARGS)
 {
+       time_t           t;
+       char            *p, buf[32];
 
        if (ROFF_BODY & tree->state) {
                assert( ! (ROFF_PRELUDE & tree->state));
@@ -915,11 +926,63 @@ roff_Dd(ROFFCALL_ARGS)
                return(0);
        }
 
-       /* TODO: parse date. */
-
        assert(NULL == tree->last);
-       tree->state |= ROFF_PRELUDE_Dd;
 
+       argv++;
+
+       if (0 == strcmp(*argv, "$Mdocdate: December 1 2008 $")) {
+               t = time(NULL);
+               if (NULL == localtime_r(&t, &tree->tm))
+                       err(1, "localtime_r");
+               tree->state |= ROFF_PRELUDE_Dd;
+               return(1);
+       } 
+
+       /* Build this from Mdocdate or raw date. */
+       
+       buf[0] = 0;
+       p = *argv;
+
+       if (0 != strcmp(*argv, "$Mdocdate:")) {
+               while (*argv) {
+                       if (strlcat(buf, *argv++, sizeof(buf))
+                                       < sizeof(buf)) 
+                               continue;
+                       roff_err(tree, p, "bad `Dd' date");
+                       return(0);
+               }
+               if (strptime(buf, "%b%d,%Y", &tree->tm)) {
+                       tree->state |= ROFF_PRELUDE_Dd;
+                       return(1);
+               }
+               roff_err(tree, *argv, "bad `Dd' date");
+               return(0);
+       }
+
+       argv++;
+       while (*argv && **argv != '$') {
+               if (strlcat(buf, *argv++, sizeof(buf))
+                               >= sizeof(buf)) {
+                       roff_err(tree, p, "bad `Dd' Mdocdate");
+                       return(0);
+               } 
+               if (strlcat(buf, " ", sizeof(buf))
+                               >= sizeof(buf)) {
+                       roff_err(tree, p, "bad `Dd' Mdocdate");
+                       return(0);
+               }
+       }
+       if (NULL == *argv) {
+               roff_err(tree, p, "bad `Dd' Mdocdate");
+               return(0);
+       }
+
+       if (NULL == strptime(buf, "%b %d %Y", &tree->tm)) {
+               roff_err(tree, *argv, "bad `Dd' Mdocdate");
+               return(0);
+       }
+
+       tree->state |= ROFF_PRELUDE_Dd;
        return(1);
 }
 
@@ -946,7 +1009,34 @@ roff_Dt(ROFFCALL_ARGS)
                return(0);
        }
 
-       /* TODO: parse date. */
+       argv++;
+       if (NULL == *argv) {
+               roff_err(tree, *argv, "`Dt' needs document title");
+               return(0);
+       } else if (strlcpy(tree->title, *argv, sizeof(tree->title))
+                       >= sizeof(tree->title)) {
+               roff_err(tree, *argv, "`Dt' document title too long");
+               return(0);
+       }
+
+       argv++;
+       if (NULL == *argv) {
+               roff_err(tree, *argv, "`Dt' needs section");
+               return(0);
+       } else if (strlcpy(tree->section, *argv, sizeof(tree->section))
+                       >= sizeof(tree->section)) {
+               roff_err(tree, *argv, "`Dt' section too long");
+               return(0);
+       }
+
+       argv++;
+       if (NULL == *argv) {
+               tree->volume[0] = 0;
+       } else if (strlcpy(tree->volume, *argv, sizeof(tree->volume))
+                       >= sizeof(tree->volume)) {
+               roff_err(tree, *argv, "`Dt' volume too long");
+               return(0);
+       }
 
        assert(NULL == tree->last);
        tree->state |= ROFF_PRELUDE_Dt;
@@ -959,10 +1049,9 @@ roff_Dt(ROFFCALL_ARGS)
 static int
 roff_Os(ROFFCALL_ARGS)
 {
+       char            *p;
 
-       if (ROFF_EXIT == type) {
-               return((*tree->cb.rofftail)(tree->arg));
-       } else if (ROFF_BODY & tree->state) {
+       if (ROFF_BODY & tree->state) {
                assert( ! (ROFF_PRELUDE & tree->state));
                assert(ROFF_PRELUDE_Os & tree->state);
                return(roff_text(tok, tree, argv, type));
@@ -975,7 +1064,24 @@ roff_Os(ROFFCALL_ARGS)
                return(0);
        }
 
-       /* TODO: extract OS. */
+       tree->os[0] = 0;
+
+       p = *++argv;
+
+       while (*argv) {
+               if (strlcat(tree->os, *argv++, sizeof(tree->os))
+                               < sizeof(tree->os)) 
+                       continue;
+               roff_err(tree, p, "`Os' value too long");
+               return(0);
+       }
+
+       if (0 == tree->os[0])
+               if (strlcpy(tree->os, "LOCAL", sizeof(tree->os))
+                               >= sizeof(tree->os)) {
+                       roff_err(tree, p, "`Os' value too long");
+                       return(0);
+               }
 
        tree->state |= ROFF_PRELUDE_Os;
        tree->state &= ~ROFF_PRELUDE;
@@ -1093,7 +1199,6 @@ roff_layout(ROFFCALL_ARGS)
        while (i >= 0 && roffispunct(argv[i]))
                i--;
 
-       assert(0 != i);
        i++;
 
        /* LINTED */
@@ -1224,8 +1329,6 @@ roff_text(ROFFCALL_ARGS)
 
        while (i >= 0 && roffispunct(argv[i]))
                i--;
-
-       assert(0 != i);
        i++;
 
        /* LINTED */