bfd43373351606514db6ba9787ccb90a6c1f73ef
[dragonfly.git] / usr.bin / mandoc / out.c
1 /*      $Id: out.c,v 1.2 2009/10/27 21:40:07 schwarze 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 /*
29  * Convert a `scaling unit' to a consistent form, or fail.  Scaling
30  * units are documented in groff.7, mdoc.7, man.7.
31  */
32 int
33 a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
34 {
35         char             buf[BUFSIZ], hasd;
36         int              i;
37         enum roffscale   unit;
38
39         if ('\0' == *src)
40                 return(0);
41
42         i = hasd = 0;
43
44         switch (*src) {
45         case ('+'):
46                 src++;
47                 break;
48         case ('-'):
49                 buf[i++] = *src++;
50                 break;
51         default:
52                 break;
53         }
54
55         if ('\0' == *src)
56                 return(0);
57
58         while (i < BUFSIZ) {
59                 if ( ! isdigit((u_char)*src)) {
60                         if ('.' != *src)
61                                 break;
62                         else if (hasd)
63                                 break;
64                         else
65                                 hasd = 1;
66                 }
67                 buf[i++] = *src++;
68         }
69
70         if (BUFSIZ == i || (*src && *(src + 1)))
71                 return(0);
72
73         buf[i] = '\0';
74
75         switch (*src) {
76         case ('c'):
77                 unit = SCALE_CM;
78                 break;
79         case ('i'):
80                 unit = SCALE_IN;
81                 break;
82         case ('P'):
83                 unit = SCALE_PC;
84                 break;
85         case ('p'):
86                 unit = SCALE_PT;
87                 break;
88         case ('f'):
89                 unit = SCALE_FS;
90                 break;
91         case ('v'):
92                 unit = SCALE_VS;
93                 break;
94         case ('m'):
95                 unit = SCALE_EM;
96                 break;
97         case ('\0'):
98                 if (SCALE_MAX == def)
99                         return(0);
100                 unit = SCALE_BU;
101                 break;
102         case ('u'):
103                 unit = SCALE_BU;
104                 break;
105         case ('M'):
106                 unit = SCALE_MM;
107                 break;
108         case ('n'):
109                 unit = SCALE_EN;
110                 break;
111         default:
112                 return(0);
113         }
114
115         if ((dst->scale = atof(buf)) < 0)
116                 dst->scale = 0;
117         dst->unit = unit;
118         dst->pt = hasd;
119
120         return(1);
121 }
122
123
124 /*
125  * Correctly writes the time in nroff form, which differs from standard
126  * form in that a space isn't printed in lieu of the extra %e field for
127  * single-digit dates.
128  */
129 void
130 time2a(time_t t, char *dst, size_t sz)
131 {
132         struct tm        tm;
133         char             buf[5];
134         char            *p;
135         size_t           nsz;
136
137         assert(sz > 1);
138         localtime_r(&t, &tm);
139
140         p = dst;
141         nsz = 0;
142
143         dst[0] = '\0';
144
145         if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
146                 return;
147
148         p += (int)nsz;
149         sz -= nsz;
150
151         if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
152                 return;
153
154         nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
155
156         if (nsz >= sz)
157                 return;
158
159         p += (int)nsz;
160         sz -= nsz;
161
162         (void)strftime(p, sz, "%Y", &tm);
163 }