]> git.cameronkatri.com Git - mandoc.git/blobdiff - mandoc.c
Back out OpenBSD special case (ok Ingo Schwarze).
[mandoc.git] / mandoc.c
index 7e880d4777f1656a1f0a596620ed8113aef0dfbf..17d6d1037489f20f319242e2d3f14929a17d3e29 100644 (file)
--- a/mandoc.c
+++ b/mandoc.c
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.c,v 1.6 2009/10/31 06:10:58 kristaps Exp $ */
+/*     $Id: mandoc.c,v 1.11 2010/04/07 11:25:38 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <sys/types.h>
 
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <time.h>
 
 #include "libmandoc.h"
 
+static int      a2time(time_t *, const char *, const char *);
+
+
 int
 mandoc_special(const char *p)
 {
-       int              c;
+       int              terminator;    /* Terminator for \s. */
+       int              lim;           /* Limit for N in \s. */
+       int              c, i;
        
        if ('\\' != *p++)
                return(0);
 
        switch (*p) {
-       case ('\\'):
-               /* FALLTHROUGH */
        case ('\''):
                /* FALLTHROUGH */
        case ('`'):
@@ -65,10 +73,85 @@ mandoc_special(const char *p)
                return(2);
        case ('e'):
                return(2);
-       case ('f'):
-               if (0 == *++p || ! isgraph((u_char)*p))
+       case ('s'):
+               if ('\0' == *++p)
+                       return(2);
+
+               c = 2;
+               terminator = 0;
+               lim = 1;
+
+               if (*p == '\'') {
+                       lim = 0;
+                       terminator = 1;
+                       ++p;
+                       ++c;
+               } else if (*p == '[') {
+                       lim = 0;
+                       terminator = 2;
+                       ++p;
+                       ++c;
+               } else if (*p == '(') {
+                       lim = 2;
+                       terminator = 3;
+                       ++p;
+                       ++c;
+               }
+
+               if (*p == '+' || *p == '-') {
+                       ++p;
+                       ++c;
+               }
+
+               if (*p == '\'') {
+                       if (terminator)
+                               return(0);
+                       lim = 0;
+                       terminator = 1;
+                       ++p;
+                       ++c;
+               } else if (*p == '[') {
+                       if (terminator)
+                               return(0);
+                       lim = 0;
+                       terminator = 2;
+                       ++p;
+                       ++c;
+               } else if (*p == '(') {
+                       if (terminator)
+                               return(0);
+                       lim = 2;
+                       terminator = 3;
+                       ++p;
+                       ++c;
+               }
+
+               /* TODO: needs to handle floating point. */
+
+               if ( ! isdigit((u_char)*p))
                        return(0);
-               return(3);
+
+               for (i = 0; isdigit((u_char)*p); i++) {
+                       if (lim && i >= lim)
+                               break;
+                       ++p;
+                       ++c;
+               }
+
+               if (terminator && terminator < 3) {
+                       if (1 == terminator && *p != '\'')
+                               return(0);
+                       if (2 == terminator && *p != ']')
+                               return(0);
+                       ++p;
+                       ++c;
+               }
+
+               return(c);
+       case ('f'):
+               /* FALLTHROUGH */
+       case ('F'):
+               /* FALLTHROUGH */
        case ('*'):
                if (0 == *++p || ! isgraph((u_char)*p))
                        return(0);
@@ -163,3 +246,57 @@ mandoc_strdup(const char *ptr)
 
        return(p);
 }
+
+
+static int
+a2time(time_t *t, const char *fmt, const char *p)
+{
+       struct tm        tm;
+       char            *pp;
+
+       memset(&tm, 0, sizeof(struct tm));
+
+       pp = strptime(p, fmt, &tm);
+       if (NULL != pp && '\0' == *pp) {
+               *t = mktime(&tm);
+               return(1);
+       }
+
+       return(0);
+}
+
+
+/*
+ * Convert from a manual date string (see mdoc(7) and man(7)) into a
+ * date according to the stipulated date type.
+ */
+time_t
+mandoc_a2time(int flags, const char *p)
+{
+       time_t           t;
+
+       if (MTIME_MDOCDATE & flags) {
+               if (0 == strcmp(p, "$" "Mdocdate$"))
+                       return(time(NULL));
+               if (a2time(&t, "$" "Mdocdate: %b %d %Y $", p))
+                       return(t);
+       }
+
+       if (MTIME_CANONICAL & flags || MTIME_REDUCED & flags) 
+               if (a2time(&t, "%b %d, %Y", p))
+                       return(t);
+
+       if (MTIME_ISO_8601 & flags) 
+               if (a2time(&t, "%Y-%m-%d", p))
+                       return(t);
+
+       if (MTIME_REDUCED & flags) {
+               if (a2time(&t, "%d, %Y", p))
+                       return(t);
+               if (a2time(&t, "%Y", p))
+                       return(t);
+       }
+
+       return(0);
+}
+