Annotation of src/usr.bin/mandoc/out.c, Revision 1.7
1.7 ! schwarze 1: /* $Id: out.c,v 1.6 2010/07/25 18:05:54 schwarze Exp $ */
1.1 schwarze 2: /*
1.6 schwarze 3: * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
1.1 schwarze 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:
1.2 schwarze 19: #include <assert.h>
1.1 schwarze 20: #include <ctype.h>
21: #include <stdio.h>
22: #include <stdlib.h>
1.2 schwarze 23: #include <string.h>
24: #include <time.h>
1.1 schwarze 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:
1.6 schwarze 115: /* FIXME: do this in the caller. */
1.1 schwarze 116: if ((dst->scale = atof(buf)) < 0)
117: dst->scale = 0;
118: dst->unit = unit;
119: return(1);
120: }
1.2 schwarze 121:
122:
123: /*
124: * Correctly writes the time in nroff form, which differs from standard
125: * form in that a space isn't printed in lieu of the extra %e field for
126: * single-digit dates.
127: */
128: void
129: time2a(time_t t, char *dst, size_t sz)
130: {
131: struct tm tm;
132: char buf[5];
133: char *p;
134: size_t nsz;
135:
136: assert(sz > 1);
137: localtime_r(&t, &tm);
138:
139: p = dst;
140: nsz = 0;
141:
142: dst[0] = '\0';
143:
144: if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
145: return;
146:
147: p += (int)nsz;
148: sz -= nsz;
149:
150: if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
151: return;
152:
153: nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
154:
155: if (nsz >= sz)
156: return;
157:
158: p += (int)nsz;
159: sz -= nsz;
160:
161: (void)strftime(p, sz, "%Y", &tm);
162: }
163:
1.3 schwarze 164:
165: int
1.6 schwarze 166: a2roffdeco(enum roffdeco *d, const char **word, size_t *sz)
1.3 schwarze 167: {
1.6 schwarze 168: int i, j, lim;
169: char term, c;
170: const char *wp;
1.3 schwarze 171:
172: *d = DECO_NONE;
1.6 schwarze 173: lim = i = 0;
174: term = '\0';
1.3 schwarze 175: wp = *word;
176:
1.6 schwarze 177: switch ((c = wp[i++])) {
1.3 schwarze 178: case ('('):
179: *d = DECO_SPECIAL;
1.6 schwarze 180: lim = 2;
181: break;
1.4 schwarze 182: case ('F'):
183: /* FALLTHROUGH */
184: case ('f'):
1.6 schwarze 185: *d = 'F' == c ? DECO_FFONT : DECO_FONT;
186:
187: switch (wp[i++]) {
188: case ('('):
189: lim = 2;
190: break;
191: case ('['):
192: term = ']';
193: break;
1.4 schwarze 194: case ('3'):
195: /* FALLTHROUGH */
196: case ('B'):
197: *d = DECO_BOLD;
1.6 schwarze 198: return(i);
1.4 schwarze 199: case ('2'):
200: /* FALLTHROUGH */
201: case ('I'):
202: *d = DECO_ITALIC;
1.6 schwarze 203: return(i);
1.4 schwarze 204: case ('P'):
205: *d = DECO_PREVIOUS;
1.6 schwarze 206: return(i);
1.4 schwarze 207: case ('1'):
208: /* FALLTHROUGH */
209: case ('R'):
210: *d = DECO_ROMAN;
1.6 schwarze 211: return(i);
1.4 schwarze 212: default:
1.6 schwarze 213: i--;
214: lim = 1;
1.4 schwarze 215: break;
216: }
1.6 schwarze 217: break;
218: case ('M'):
219: /* FALLTHROUGH */
220: case ('m'):
221: /* FALLTHROUGH */
1.3 schwarze 222: case ('*'):
1.6 schwarze 223: if ('*' == c)
224: *d = DECO_RESERVED;
1.3 schwarze 225:
1.6 schwarze 226: switch (wp[i++]) {
1.3 schwarze 227: case ('('):
1.6 schwarze 228: lim = 2;
229: break;
1.3 schwarze 230: case ('['):
1.6 schwarze 231: term = ']';
232: break;
1.3 schwarze 233: default:
1.6 schwarze 234: i--;
235: lim = 1;
1.4 schwarze 236: break;
1.3 schwarze 237: }
1.6 schwarze 238: break;
1.7 ! schwarze 239: case ('h'):
! 240: /* FALLTHROUGH */
! 241: case ('v'):
! 242: /* FALLTHROUGH */
1.3 schwarze 243: case ('s'):
1.7 ! schwarze 244: j = 0;
! 245: if ('+' == wp[i] || '-' == wp[i]) {
1.6 schwarze 246: i++;
1.7 ! schwarze 247: j = 1;
! 248: }
1.3 schwarze 249:
1.6 schwarze 250: switch (wp[i++]) {
251: case ('('):
252: lim = 2;
253: break;
254: case ('['):
255: term = ']';
256: break;
1.3 schwarze 257: case ('\''):
1.6 schwarze 258: term = '\'';
259: break;
260: case ('0'):
1.7 ! schwarze 261: j = 1;
1.3 schwarze 262: /* FALLTHROUGH */
263: default:
1.6 schwarze 264: i--;
265: lim = 1;
1.3 schwarze 266: break;
267: }
268:
1.6 schwarze 269: if ('+' == wp[i] || '-' == wp[i]) {
1.7 ! schwarze 270: if (j)
1.6 schwarze 271: return(i);
272: i++;
273: }
274:
275: break;
276: case ('['):
277: *d = DECO_SPECIAL;
278: term = ']';
279: break;
280: case ('c'):
281: *d = DECO_NOSPACE;
282: return(i);
283: default:
284: *d = DECO_SSPECIAL;
285: i--;
286: lim = 1;
287: break;
288: }
1.3 schwarze 289:
1.6 schwarze 290: assert(term || lim);
291: *word = &wp[i];
1.3 schwarze 292:
1.6 schwarze 293: if (term) {
294: j = i;
295: while (wp[i] && wp[i] != term)
296: i++;
297: if ('\0' == wp[i]) {
298: *d = DECO_NONE;
299: return(i);
1.3 schwarze 300: }
301:
1.6 schwarze 302: assert(i >= j);
303: *sz = (size_t)(i - j);
1.3 schwarze 304:
1.6 schwarze 305: return(i + 1);
306: }
1.3 schwarze 307:
1.6 schwarze 308: assert(lim > 0);
309: *sz = (size_t)lim;
1.3 schwarze 310:
1.6 schwarze 311: for (j = 0; wp[i] && j < lim; j++)
312: i++;
313: if (j < lim)
314: *d = DECO_NONE;
1.3 schwarze 315:
1.6 schwarze 316: return(i);
1.3 schwarze 317: }