=================================================================== RCS file: /cvs/mandoc/out.c,v retrieving revision 1.3 retrieving revision 1.7 diff -u -p -r1.3 -r1.7 --- mandoc/out.c 2009/10/07 12:35:24 1.3 +++ mandoc/out.c 2009/10/22 18:59:00 1.7 @@ -1,4 +1,4 @@ -/* $Id: out.c,v 1.3 2009/10/07 12:35:24 kristaps Exp $ */ +/* $Id: out.c,v 1.7 2009/10/22 18:59:00 kristaps Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons * @@ -16,47 +16,65 @@ */ #include +#include #include #include #include +#include +#include #include "out.h" +#ifdef __linux__ +extern size_t strlcat(char *, const char *, size_t); +#endif /* * Convert a `scaling unit' to a consistent form, or fail. Scaling - * units are documented in groff.7, which stipulates the following: - * - * (1) A scaling unit is a signed/unsigned integer/float with or - * without a unit. - * - * (2) The following units exist: - * c Centimeter - * i Inch - * P Pica = 1/6 inch - * p Point = 1/72 inch - * m Em = the font size in points (width of letter m) - * M 100th of an Em - * n En = Em/2 - * u Basic unit for actual output device - * v Vertical line space in basic units scaled point = - * 1/sizescale of a point (defined in font DESC file) - * f Scale by 65536. + * units are documented in groff.7, mdoc.7, man.7. */ int -a2roffsu(const char *src, struct roffsu *dst) +a2roffsu(const char *src, struct roffsu *dst, enum roffscale def) { - char buf[BUFSIZ], *p; + char buf[BUFSIZ], hasd; int i; enum roffscale unit; - for (p = buf, i = 0; i < BUFSIZ && isdigit((u_char)*src); i++) - *p++ = *src++; + if ('\0' == *src) + return(0); + i = hasd = 0; + + switch (*src) { + case ('+'): + src++; + break; + case ('-'): + buf[i++] = *src++; + break; + default: + break; + } + + if ('\0' == *src) + return(0); + + while (i < BUFSIZ) { + if ( ! isdigit((u_char)*src)) { + if ('.' != *src) + break; + else if (hasd) + break; + else + hasd = 1; + } + buf[i++] = *src++; + } + if (BUFSIZ == i || (*src && *(src + 1))) return(0); - *p = '\0'; + buf[i] = '\0'; switch (*src) { case ('c'): @@ -81,7 +99,10 @@ a2roffsu(const char *src, struct roffsu *dst) unit = SCALE_EM; break; case ('\0'): - /* FALLTHROUGH */ + if (SCALE_MAX == def) + return(0); + unit = SCALE_BU; + break; case ('u'): unit = SCALE_BU; break; @@ -95,8 +116,53 @@ a2roffsu(const char *src, struct roffsu *dst) return(0); } - if ((dst->scale = atoi(buf)) < 0) + if ((dst->scale = atof(buf)) < 0) dst->scale = 0; dst->unit = unit; + dst->pt = hasd; + return(1); } + + +/* + * Correctly writes the time in nroff form, which differs from standard + * form in that a space isn't printed in lieu of the extra %e field for + * single-digit dates. + */ +void +time2a(time_t t, char *dst, size_t sz) +{ + struct tm tm; + char buf[5]; + char *p; + size_t nsz; + + assert(sz > 1); + localtime_r(&t, &tm); + + p = dst; + nsz = 0; + + dst[0] = '\0'; + + if (0 == (nsz = strftime(p, sz, "%B ", &tm))) + return; + + p += (int)nsz; + sz -= nsz; + + if (0 == strftime(buf, sizeof(buf), "%e, ", &tm)) + return; + + nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz); + + if (nsz >= sz) + return; + + p += (int)nsz; + sz -= nsz; + + (void)strftime(p, sz, "%Y", &tm); +} +