+ else if (a2time(&t, "%Y-%m-%d", in))
+ t = 0;
+ else if (!a2time(&t, "$" "Mdocdate: %b %d %Y $", in) &&
+ !a2time(&t, "%b %d, %Y", in)) {
+ mandoc_msg(MANDOCERR_DATE_BAD, parse, ln, pos, in);
+ t = 0;
+ }
+ out = t ? time2a(t) : NULL;
+ return(out ? out : mandoc_strdup(in));
+}
+
+int
+mandoc_eos(const char *p, size_t sz)
+{
+ const char *q;
+ int enclosed, found;
+
+ if (0 == sz)
+ return(0);
+
+ /*
+ * End-of-sentence recognition must include situations where
+ * some symbols, such as `)', allow prior EOS punctuation to
+ * propagate outward.
+ */
+
+ enclosed = found = 0;
+ for (q = p + (int)sz - 1; q >= p; q--) {
+ switch (*q) {
+ case '\"':
+ /* FALLTHROUGH */
+ case '\'':
+ /* FALLTHROUGH */
+ case ']':
+ /* FALLTHROUGH */
+ case ')':
+ if (0 == found)
+ enclosed = 1;
+ break;
+ case '.':
+ /* FALLTHROUGH */
+ case '!':
+ /* FALLTHROUGH */
+ case '?':
+ found = 1;
+ break;
+ default:
+ return(found && (!enclosed || isalnum((unsigned char)*q)));
+ }
+ }
+
+ return(found && !enclosed);
+}
+
+/*
+ * Convert a string to a long that may not be <0.
+ * If the string is invalid, or is less than 0, return -1.
+ */
+int
+mandoc_strntoi(const char *p, size_t sz, int base)
+{
+ char buf[32];
+ char *ep;
+ long v;
+
+ if (sz > 31)
+ return(-1);
+
+ memcpy(buf, p, sz);
+ buf[(int)sz] = '\0';
+
+ errno = 0;
+ v = strtol(buf, &ep, base);
+
+ if (buf[0] == '\0' || *ep != '\0')
+ return(-1);
+
+ if (v > INT_MAX)
+ v = INT_MAX;
+ if (v < INT_MIN)
+ v = INT_MIN;