mandoc(1): Update to 1.9.13.
[dragonfly.git] / usr.bin / mandoc / out.c
blobcdd0bc2994c1403d2c8a150274dd03ab4b87e96e
1 /* $Id: out.c,v 1.7 2009/10/22 18:59:00 kristaps Exp $ */
2 /*
3 * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <sys/types.h>
19 #include <assert.h>
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
26 #include "out.h"
28 #ifdef __linux__
29 extern size_t strlcat(char *, const char *, size_t);
30 #endif
33 * Convert a `scaling unit' to a consistent form, or fail. Scaling
34 * units are documented in groff.7, mdoc.7, man.7.
36 int
37 a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
39 char buf[BUFSIZ], hasd;
40 int i;
41 enum roffscale unit;
43 if ('\0' == *src)
44 return(0);
46 i = hasd = 0;
48 switch (*src) {
49 case ('+'):
50 src++;
51 break;
52 case ('-'):
53 buf[i++] = *src++;
54 break;
55 default:
56 break;
59 if ('\0' == *src)
60 return(0);
62 while (i < BUFSIZ) {
63 if ( ! isdigit((u_char)*src)) {
64 if ('.' != *src)
65 break;
66 else if (hasd)
67 break;
68 else
69 hasd = 1;
71 buf[i++] = *src++;
74 if (BUFSIZ == i || (*src && *(src + 1)))
75 return(0);
77 buf[i] = '\0';
79 switch (*src) {
80 case ('c'):
81 unit = SCALE_CM;
82 break;
83 case ('i'):
84 unit = SCALE_IN;
85 break;
86 case ('P'):
87 unit = SCALE_PC;
88 break;
89 case ('p'):
90 unit = SCALE_PT;
91 break;
92 case ('f'):
93 unit = SCALE_FS;
94 break;
95 case ('v'):
96 unit = SCALE_VS;
97 break;
98 case ('m'):
99 unit = SCALE_EM;
100 break;
101 case ('\0'):
102 if (SCALE_MAX == def)
103 return(0);
104 unit = SCALE_BU;
105 break;
106 case ('u'):
107 unit = SCALE_BU;
108 break;
109 case ('M'):
110 unit = SCALE_MM;
111 break;
112 case ('n'):
113 unit = SCALE_EN;
114 break;
115 default:
116 return(0);
119 if ((dst->scale = atof(buf)) < 0)
120 dst->scale = 0;
121 dst->unit = unit;
122 dst->pt = hasd;
124 return(1);
129 * Correctly writes the time in nroff form, which differs from standard
130 * form in that a space isn't printed in lieu of the extra %e field for
131 * single-digit dates.
133 void
134 time2a(time_t t, char *dst, size_t sz)
136 struct tm tm;
137 char buf[5];
138 char *p;
139 size_t nsz;
141 assert(sz > 1);
142 localtime_r(&t, &tm);
144 p = dst;
145 nsz = 0;
147 dst[0] = '\0';
149 if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
150 return;
152 p += (int)nsz;
153 sz -= nsz;
155 if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
156 return;
158 nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
160 if (nsz >= sz)
161 return;
163 p += (int)nsz;
164 sz -= nsz;
166 (void)strftime(p, sz, "%Y", &tm);