mandoc(1): Update to 1.9.13.
[dragonfly.git] / usr.bin / mandoc / out.c
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>
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
19 #include <assert.h>
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25
26 #include "out.h"
27
28 #ifdef __linux__
29 extern  size_t    strlcat(char *, const char *, size_t);
30 #endif
31
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  */
36 int
37 a2roffsu(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 }
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  */
133 void
134 time2a(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 }