]> git.cameronkatri.com Git - mandoc.git/blobdiff - mandoc.c
Place mandoc.css into the public domain.
[mandoc.git] / mandoc.c
index fc360def79e21927a54b26cd6d4c1cde378dc170..5476fb410e2d2f25d706f1be70b7ffb0865e9775 100644 (file)
--- a/mandoc.c
+++ b/mandoc.c
@@ -1,7 +1,7 @@
-/*     $Id: mandoc.c,v 1.100 2017/06/02 19:21:23 schwarze Exp $ */
+/*     $Id: mandoc.c,v 1.108 2018/10/25 01:32:40 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011-2015, 2017, 2018 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
@@ -28,8 +28,9 @@
 #include <string.h>
 #include <time.h>
 
-#include "mandoc.h"
 #include "mandoc_aux.h"
+#include "mandoc.h"
+#include "roff.h"
 #include "libmandoc.h"
 
 static int      a2time(time_t *, const char *, const char *);
@@ -40,7 +41,7 @@ enum mandoc_esc
 mandoc_escape(const char **end, const char **start, int *sz)
 {
        const char      *local_start;
-       int              local_sz;
+       int              local_sz, c, i;
        char             term;
        enum mandoc_esc  gly;
 
@@ -95,6 +96,8 @@ mandoc_escape(const char **end, const char **start, int *sz)
        case ',':
        case '/':
                return ESCAPE_IGNORE;
+       case 'p':
+               return ESCAPE_BREAK;
 
        /*
         * The \z escape is supposed to output the following
@@ -136,6 +139,13 @@ mandoc_escape(const char **end, const char **start, int *sz)
                        break;
                }
                break;
+       case '*':
+               if (strncmp(*start, "(.T", 3) != 0)
+                       abort();
+               gly = ESCAPE_DEVICE;
+               *start = ++*end;
+               *sz = 2;
+               break;
 
        /*
         * These escapes are of the form \X'Y', where 'X' is the trigger
@@ -292,21 +302,29 @@ mandoc_escape(const char **end, const char **start, int *sz)
 
        switch (gly) {
        case ESCAPE_FONT:
-               if (2 == *sz) {
-                       if ('C' == **start) {
+               if (*sz == 2) {
+                       if (**start == 'C') {
+                               if ((*start)[1] == 'W' ||
+                                   (*start)[1] == 'R') {
+                                       gly = ESCAPE_FONTCW;
+                                       break;
+                               }
                                /*
-                                * Treat constant-width font modes
+                                * Treat other constant-width font modes
                                 * just like regular font modes.
                                 */
                                (*start)++;
                                (*sz)--;
                        } else {
-                               if ('B' == (*start)[0] && 'I' == (*start)[1])
+                               if ((*start)[0] == 'B' && (*start)[1] == 'I')
                                        gly = ESCAPE_FONTBI;
                                break;
                        }
-               } else if (1 != *sz)
+               } else if (*sz != 1) {
+                       if (*sz == 0)
+                               gly = ESCAPE_FONTPREV;
                        break;
+               }
 
                switch (**start) {
                case '3':
@@ -327,8 +345,26 @@ mandoc_escape(const char **end, const char **start, int *sz)
                }
                break;
        case ESCAPE_SPECIAL:
-               if (1 == *sz && 'c' == **start)
-                       gly = ESCAPE_NOSPACE;
+               if (**start == 'c') {
+                       if (*sz == 1) {
+                               gly = ESCAPE_NOSPACE;
+                               break;
+                       }
+                       if (*sz < 6 || *sz > 7 ||
+                           strncmp(*start, "char", 4) != 0 ||
+                           (int)strspn(*start + 4, "0123456789") + 4 < *sz)
+                               break;
+                       c = 0;
+                       for (i = 4; i < *sz; i++)
+                               c = 10 * c + ((*start)[i] - '0');
+                       if (c < 0x21 || (c > 0x7e && c < 0xa0) || c > 0xff)
+                               break;
+                       *start += 4;
+                       *sz -= 4;
+                       gly = ESCAPE_NUMBERED;
+                       break;
+               }
+
                /*
                 * Unicode escapes are defined in groff as \[u0000]
                 * to \[u10FFFF], where the contained value must be
@@ -518,27 +554,41 @@ fail:
 }
 
 char *
-mandoc_normdate(struct mparse *parse, char *in, int ln, int pos)
+mandoc_normdate(struct roff_man *man, char *in, int ln, int pos)
 {
+       char            *cp;
        time_t           t;
 
        /* No date specified: use today's date. */
 
        if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0) {
-               mandoc_msg(MANDOCERR_DATE_MISSING, parse, ln, pos, NULL);
+               mandoc_msg(MANDOCERR_DATE_MISSING, man->parse, ln, pos, NULL);
                return time2a(time(NULL));
        }
 
        /* Valid mdoc(7) date format. */
 
        if (a2time(&t, "$" "Mdocdate: %b %d %Y $", in) ||
-           a2time(&t, "%b %d, %Y", in))
-               return time2a(t);
+           a2time(&t, "%b %d, %Y", in)) {
+               cp = time2a(t);
+               if (t > time(NULL) + 86400)
+                       mandoc_msg(MANDOCERR_DATE_FUTURE, man->parse,
+                           ln, pos, cp);
+               else if (*in != '$' && strcmp(in, cp) != 0)
+                       mandoc_msg(MANDOCERR_DATE_NORM, man->parse,
+                           ln, pos, cp);
+               return cp;
+       }
 
-       /* Do not warn about the legacy man(7) format. */
+       /* In man(7), do not warn about the legacy format. */
 
-       if ( ! a2time(&t, "%Y-%m-%d", in))
-               mandoc_msg(MANDOCERR_DATE_BAD, parse, ln, pos, in);
+       if (a2time(&t, "%Y-%m-%d", in) == 0)
+               mandoc_msg(MANDOCERR_DATE_BAD, man->parse, ln, pos, in);
+       else if (t > time(NULL) + 86400)
+               mandoc_msg(MANDOCERR_DATE_FUTURE, man->parse, ln, pos, in);
+       else if (man->macroset == MACROSET_MDOC)
+               mandoc_vmsg(MANDOCERR_DATE_LEGACY, man->parse,
+                   ln, pos, "Dd %s", in);
 
        /* Use any non-mdoc(7) date verbatim. */