Annotation of src/usr.bin/mandoc/out.c, Revision 1.6
1.6 ! schwarze 1: /* $Id: out.c,v 1.5 2010/06/27 20:28:56 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.3 schwarze 239: case ('s'):
1.6 ! schwarze 240: if ('+' == wp[i] || '-' == wp[i])
! 241: i++;
1.3 schwarze 242:
1.6 ! schwarze 243: j = ('s' != wp[i - 1]);
1.3 schwarze 244:
1.6 ! schwarze 245: switch (wp[i++]) {
! 246: case ('('):
! 247: lim = 2;
! 248: break;
! 249: case ('['):
! 250: term = ']';
! 251: break;
1.3 schwarze 252: case ('\''):
1.6 ! schwarze 253: term = '\'';
! 254: break;
! 255: case ('0'):
! 256: j++;
1.3 schwarze 257: /* FALLTHROUGH */
258: default:
1.6 ! schwarze 259: i--;
! 260: lim = 1;
1.3 schwarze 261: break;
262: }
263:
1.6 ! schwarze 264: if ('+' == wp[i] || '-' == wp[i]) {
! 265: if (j++)
! 266: return(i);
! 267: i++;
! 268: }
! 269:
! 270: if (0 == j)
! 271: return(i);
! 272: break;
! 273: case ('['):
! 274: *d = DECO_SPECIAL;
! 275: term = ']';
! 276: break;
! 277: case ('c'):
! 278: *d = DECO_NOSPACE;
! 279: return(i);
! 280: default:
! 281: *d = DECO_SSPECIAL;
! 282: i--;
! 283: lim = 1;
! 284: break;
! 285: }
1.3 schwarze 286:
1.6 ! schwarze 287: assert(term || lim);
! 288: *word = &wp[i];
1.3 schwarze 289:
1.6 ! schwarze 290: if (term) {
! 291: j = i;
! 292: while (wp[i] && wp[i] != term)
! 293: i++;
! 294: if ('\0' == wp[i]) {
! 295: *d = DECO_NONE;
! 296: return(i);
1.3 schwarze 297: }
298:
1.6 ! schwarze 299: assert(i >= j);
! 300: *sz = (size_t)(i - j);
1.3 schwarze 301:
1.6 ! schwarze 302: return(i + 1);
! 303: }
1.3 schwarze 304:
1.6 ! schwarze 305: assert(lim > 0);
! 306: *sz = (size_t)lim;
1.3 schwarze 307:
1.6 ! schwarze 308: for (j = 0; wp[i] && j < lim; j++)
! 309: i++;
! 310: if (j < lim)
! 311: *d = DECO_NONE;
1.3 schwarze 312:
1.6 ! schwarze 313: return(i);
1.3 schwarze 314: }