kernel - Video - Add suppor for Intel IGD chipsets (netbook / N450 etc)
[dragonfly.git] / usr.bin / mandoc / out.c
blob72c54fc24f1cda30417ef238a2d8139e9c4b04b5
1 /* $Id: out.c,v 1.11 2009/11/12 08:21:05 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 /* See a2roffdeco(). */
29 #define C2LIM(c, l) do { \
30 (l) = 1; \
31 if ('[' == (c) || '\'' == (c)) \
32 (l) = 0; \
33 else if ('(' == (c)) \
34 (l) = 2; } \
35 while (/* CONSTCOND */ 0)
37 /* See a2roffdeco(). */
38 #define C2TERM(c, t) do { \
39 (t) = 0; \
40 if ('\'' == (c)) \
41 (t) = 1; \
42 else if ('[' == (c)) \
43 (t) = 2; \
44 else if ('(' == (c)) \
45 (t) = 3; } \
46 while (/* CONSTCOND */ 0)
48 #ifdef __linux__
49 extern size_t strlcat(char *, const char *, size_t);
50 #endif
53 * Convert a `scaling unit' to a consistent form, or fail. Scaling
54 * units are documented in groff.7, mdoc.7, man.7.
56 int
57 a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
59 char buf[BUFSIZ], hasd;
60 int i;
61 enum roffscale unit;
63 if ('\0' == *src)
64 return(0);
66 i = hasd = 0;
68 switch (*src) {
69 case ('+'):
70 src++;
71 break;
72 case ('-'):
73 buf[i++] = *src++;
74 break;
75 default:
76 break;
79 if ('\0' == *src)
80 return(0);
82 while (i < BUFSIZ) {
83 if ( ! isdigit((u_char)*src)) {
84 if ('.' != *src)
85 break;
86 else if (hasd)
87 break;
88 else
89 hasd = 1;
91 buf[i++] = *src++;
94 if (BUFSIZ == i || (*src && *(src + 1)))
95 return(0);
97 buf[i] = '\0';
99 switch (*src) {
100 case ('c'):
101 unit = SCALE_CM;
102 break;
103 case ('i'):
104 unit = SCALE_IN;
105 break;
106 case ('P'):
107 unit = SCALE_PC;
108 break;
109 case ('p'):
110 unit = SCALE_PT;
111 break;
112 case ('f'):
113 unit = SCALE_FS;
114 break;
115 case ('v'):
116 unit = SCALE_VS;
117 break;
118 case ('m'):
119 unit = SCALE_EM;
120 break;
121 case ('\0'):
122 if (SCALE_MAX == def)
123 return(0);
124 unit = SCALE_BU;
125 break;
126 case ('u'):
127 unit = SCALE_BU;
128 break;
129 case ('M'):
130 unit = SCALE_MM;
131 break;
132 case ('n'):
133 unit = SCALE_EN;
134 break;
135 default:
136 return(0);
139 if ((dst->scale = atof(buf)) < 0)
140 dst->scale = 0;
141 dst->unit = unit;
142 dst->pt = hasd;
144 return(1);
149 * Correctly writes the time in nroff form, which differs from standard
150 * form in that a space isn't printed in lieu of the extra %e field for
151 * single-digit dates.
153 void
154 time2a(time_t t, char *dst, size_t sz)
156 struct tm tm;
157 char buf[5];
158 char *p;
159 size_t nsz;
161 assert(sz > 1);
162 localtime_r(&t, &tm);
164 p = dst;
165 nsz = 0;
167 dst[0] = '\0';
169 if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
170 return;
172 p += (int)nsz;
173 sz -= nsz;
175 if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
176 return;
178 nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
180 if (nsz >= sz)
181 return;
183 p += (int)nsz;
184 sz -= nsz;
186 (void)strftime(p, sz, "%Y", &tm);
191 * Returns length of parsed string (the leading "\" should NOT be
192 * included). This can be zero if the current character is the nil
193 * terminator. "d" is set to the type of parsed decorator, which may
194 * have an adjoining "word" of size "sz" (e.g., "(ab" -> "ab", 2).
197 a2roffdeco(enum roffdeco *d,
198 const char **word, size_t *sz)
200 int j, type, term, lim;
201 const char *wp, *sp;
203 *d = DECO_NONE;
204 wp = *word;
205 type = 1;
207 switch (*wp) {
208 case ('\0'):
209 return(0);
211 case ('('):
212 if ('\0' == *(++wp))
213 return(1);
214 if ('\0' == *(wp + 1))
215 return(2);
217 *d = DECO_SPECIAL;
218 *sz = 2;
219 *word = wp;
220 return(3);
222 case ('*'):
223 switch (*(++wp)) {
224 case ('\0'):
225 return(1);
227 case ('('):
228 if ('\0' == *(++wp))
229 return(2);
230 if ('\0' == *(wp + 1))
231 return(3);
233 *d = DECO_RESERVED;
234 *sz = 2;
235 *word = wp;
236 return(4);
238 case ('['):
239 type = 0;
240 break;
242 default:
243 *d = DECO_RESERVED;
244 *sz = 1;
245 *word = wp;
246 return(2);
248 break;
250 case ('s'):
251 sp = wp;
252 if ('\0' == *(++wp))
253 return(1);
255 C2LIM(*wp, lim);
256 C2TERM(*wp, term);
258 if (term)
259 wp++;
261 *word = wp;
263 if (*wp == '+' || *wp == '-')
264 ++wp;
266 switch (*wp) {
267 case ('\''):
268 /* FALLTHROUGH */
269 case ('['):
270 /* FALLTHROUGH */
271 case ('('):
272 if (term)
273 return((int)(wp - sp));
275 C2LIM(*wp, lim);
276 C2TERM(*wp, term);
277 wp++;
278 break;
279 default:
280 break;
283 if ( ! isdigit((u_char)*wp))
284 return((int)(wp - sp));
286 for (j = 0; isdigit((u_char)*wp); j++) {
287 if (lim && j >= lim)
288 break;
289 ++wp;
292 if (term && term < 3) {
293 if (1 == term && *wp != '\'')
294 return((int)(wp - sp));
295 if (2 == term && *wp != ']')
296 return((int)(wp - sp));
297 ++wp;
300 *d = DECO_SIZE;
301 return((int)(wp - sp));
303 case ('f'):
304 switch (*(++wp)) {
305 case ('\0'):
306 return(1);
307 case ('3'):
308 /* FALLTHROUGH */
309 case ('B'):
310 *d = DECO_BOLD;
311 break;
312 case ('2'):
313 /* FALLTHROUGH */
314 case ('I'):
315 *d = DECO_ITALIC;
316 break;
317 case ('P'):
318 *d = DECO_PREVIOUS;
319 break;
320 case ('1'):
321 /* FALLTHROUGH */
322 case ('R'):
323 *d = DECO_ROMAN;
324 break;
325 default:
326 break;
329 return(2);
331 case ('['):
332 break;
334 case ('c'):
335 *d = DECO_NOSPACE;
336 *sz = 1;
337 return(1);
339 default:
340 *d = DECO_SPECIAL;
341 *word = wp;
342 *sz = 1;
343 return(1);
346 *word = ++wp;
347 for (j = 0; *wp && ']' != *wp; wp++, j++)
348 /* Loop... */ ;
350 if ('\0' == *wp)
351 return(j + 1);
353 *d = type ? DECO_SPECIAL : DECO_RESERVED;
354 *sz = (size_t)j;
355 return (j + 2);