mandoc(1): Update to 1.9.13.
[dragonfly.git] / usr.bin / mandoc / out.c
CommitLineData
32c903ac 1/* $Id: out.c,v 1.7 2009/10/22 18:59:00 kristaps Exp $ */
589e7c1d
SW
2/*
3 * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
4 *
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.
8 *
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.
16 */
17#include <sys/types.h>
18
cbce6d97 19#include <assert.h>
589e7c1d
SW
20#include <ctype.h>
21#include <stdio.h>
22#include <stdlib.h>
cbce6d97
SW
23#include <string.h>
24#include <time.h>
589e7c1d
SW
25
26#include "out.h"
27
32c903ac
SW
28#ifdef __linux__
29extern size_t strlcat(char *, const char *, size_t);
30#endif
31
589e7c1d
SW
32/*
33 * Convert a `scaling unit' to a consistent form, or fail. Scaling
34 * units are documented in groff.7, mdoc.7, man.7.
35 */
36int
37a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
38{
39 char buf[BUFSIZ], hasd;
40 int i;
41 enum roffscale unit;
42
43 if ('\0' == *src)
44 return(0);
45
46 i = hasd = 0;
47
48 switch (*src) {
49 case ('+'):
50 src++;
51 break;
52 case ('-'):
53 buf[i++] = *src++;
54 break;
55 default:
56 break;
57 }
58
59 if ('\0' == *src)
60 return(0);
61
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;
70 }
71 buf[i++] = *src++;
72 }
73
74 if (BUFSIZ == i || (*src && *(src + 1)))
75 return(0);
76
77 buf[i] = '\0';
78
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);
117 }
118
119 if ((dst->scale = atof(buf)) < 0)
120 dst->scale = 0;
121 dst->unit = unit;
122 dst->pt = hasd;
123
124 return(1);
125}
cbce6d97
SW
126
127
128/*
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.
132 */
133void
134time2a(time_t t, char *dst, size_t sz)
135{
136 struct tm tm;
137 char buf[5];
138 char *p;
139 size_t nsz;
140
141 assert(sz > 1);
142 localtime_r(&t, &tm);
143
144 p = dst;
145 nsz = 0;
146
147 dst[0] = '\0';
148
149 if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
150 return;
151
152 p += (int)nsz;
153 sz -= nsz;
154
155 if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
156 return;
157
158 nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
159
160 if (nsz >= sz)
161 return;
162
163 p += (int)nsz;
164 sz -= nsz;
165
166 (void)strftime(p, sz, "%Y", &tm);
167}