Annotation of mandoc/out.c, Revision 1.8
1.8 ! kristaps 1: /* $Id: out.c,v 1.7 2009/10/22 18:59:00 kristaps Exp $ */
1.1 kristaps 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:
1.6 kristaps 19: #include <assert.h>
1.1 kristaps 20: #include <ctype.h>
1.3 kristaps 21: #include <stdio.h>
1.1 kristaps 22: #include <stdlib.h>
1.6 kristaps 23: #include <string.h>
1.7 kristaps 24: #include <time.h>
1.1 kristaps 25:
26: #include "out.h"
27:
1.7 kristaps 28: #ifdef __linux__
29: extern size_t strlcat(char *, const char *, size_t);
30: #endif
1.3 kristaps 31:
32: /*
33: * Convert a `scaling unit' to a consistent form, or fail. Scaling
1.5 kristaps 34: * units are documented in groff.7, mdoc.7, man.7.
1.3 kristaps 35: */
1.1 kristaps 36: int
1.5 kristaps 37: a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
1.1 kristaps 38: {
1.4 kristaps 39: char buf[BUFSIZ], hasd;
1.1 kristaps 40: int i;
1.3 kristaps 41: enum roffscale unit;
1.1 kristaps 42:
1.5 kristaps 43: if ('\0' == *src)
44: return(0);
45:
1.4 kristaps 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:
1.5 kristaps 59: if ('\0' == *src)
60: return(0);
61:
1.4 kristaps 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: }
1.1 kristaps 73:
1.3 kristaps 74: if (BUFSIZ == i || (*src && *(src + 1)))
1.1 kristaps 75: return(0);
76:
1.4 kristaps 77: buf[i] = '\0';
1.1 kristaps 78:
1.3 kristaps 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'):
1.5 kristaps 102: if (SCALE_MAX == def)
103: return(0);
104: unit = SCALE_BU;
105: break;
1.3 kristaps 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:
1.1 kristaps 116: return(0);
1.3 kristaps 117: }
1.1 kristaps 118:
1.4 kristaps 119: if ((dst->scale = atof(buf)) < 0)
1.3 kristaps 120: dst->scale = 0;
121: dst->unit = unit;
1.4 kristaps 122: dst->pt = hasd;
123:
1.3 kristaps 124: return(1);
1.1 kristaps 125: }
1.6 kristaps 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: }
168:
1.8 ! kristaps 169:
! 170: /* Returns length of parsed string. */
! 171: int
! 172: a2roffdeco(enum roffdeco *d,
! 173: const char **word, size_t *sz)
! 174: {
! 175: int j, type, sv, t, lim;
! 176: const char *wp;
! 177:
! 178: *d = DECO_NONE;
! 179:
! 180: wp = *word;
! 181: type = 1;
! 182:
! 183: switch (*wp) {
! 184: case ('\0'):
! 185: return(0);
! 186:
! 187: case ('('):
! 188: wp++;
! 189: if ('\0' == *wp)
! 190: return(1);
! 191: if ('\0' == *(wp + 1))
! 192: return(2);
! 193:
! 194: *d = DECO_SPECIAL;
! 195: *sz = 2;
! 196: *word = wp;
! 197: return(3);
! 198:
! 199: case ('*'):
! 200: wp++;
! 201:
! 202: switch (*wp) {
! 203: case ('\0'):
! 204: return(1);
! 205:
! 206: case ('('):
! 207: wp++;
! 208: if ('\0' == *wp)
! 209: return(2);
! 210: if ('\0' == *(wp + 1))
! 211: return(3);
! 212:
! 213: *d = DECO_RESERVED;
! 214: *sz = 2;
! 215: *word = wp;
! 216: return(4);
! 217:
! 218: case ('['):
! 219: type = 0;
! 220: break;
! 221:
! 222: default:
! 223: *d = DECO_RESERVED;
! 224: *sz = 1;
! 225: *word = wp;
! 226: return(3);
! 227: }
! 228: break;
! 229:
! 230: #if 0
! 231: case ('s'):
! 232: wp++;
! 233:
! 234: /* This closely follows mandoc_special(). */
! 235: if ('\0' == *wp)
! 236: return(1);
! 237:
! 238: t = 0;
! 239: lim = 1;
! 240:
! 241: if (*wp == '\'') {
! 242: lim = 0;
! 243: t = 1;
! 244: ++wp;
! 245: } else if (*wp == '[') {
! 246: lim = 0;
! 247: t = 2;
! 248: ++wp;
! 249: } else if (*wp == '(') {
! 250: lim = 2;
! 251: t = 3;
! 252: ++wp;
! 253: }
! 254:
! 255: if (*wp == '+' || *wp == '-')
! 256: ++wp;
! 257:
! 258: if (*wp == '\'') {
! 259: if (t) {
! 260: *word = wp;
! 261: return;
! 262: }
! 263: lim = 0;
! 264: t = 1;
! 265: ++wp;
! 266: } else if (*wp == '[') {
! 267: if (t) {
! 268: *word = wp;
! 269: return;
! 270: }
! 271: lim = 0;
! 272: t = 2;
! 273: ++wp;
! 274: } else if (*wp == '(') {
! 275: if (t) {
! 276: *word = wp;
! 277: return;
! 278: }
! 279: lim = 2;
! 280: t = 3;
! 281: ++wp;
! 282: }
! 283:
! 284: if ( ! isdigit((u_char)*wp)) {
! 285: *word = --wp;
! 286: return;
! 287: }
! 288:
! 289: for (j = 0; isdigit((u_char)*wp); j++) {
! 290: if (lim && j >= lim)
! 291: break;
! 292: ++wp;
! 293: }
! 294:
! 295: if (t && t < 3) {
! 296: if (1 == t && *wp != '\'') {
! 297: *word = --wp;
! 298: return;
! 299: }
! 300: if (2 == t && *wp != ']') {
! 301: *word = --wp;
! 302: return;
! 303: }
! 304: ++wp;
! 305: }
! 306: *word = --wp;
! 307: return;
! 308: #endif
! 309:
! 310: case ('f'):
! 311: wp++;
! 312:
! 313: switch (*wp) {
! 314: case ('\0'):
! 315: return(1);
! 316: case ('3'):
! 317: /* FALLTHROUGH */
! 318: case ('B'):
! 319: *d = DECO_BOLD;
! 320: break;
! 321: case ('2'):
! 322: /* FALLTHROUGH */
! 323: case ('I'):
! 324: *d = DECO_ITALIC;
! 325: break;
! 326: case ('P'):
! 327: *d = DECO_PREVIOUS;
! 328: break;
! 329: case ('1'):
! 330: /* FALLTHROUGH */
! 331: case ('R'):
! 332: *d = DECO_ROMAN;
! 333: break;
! 334: default:
! 335: break;
! 336: }
! 337:
! 338: return(2);
! 339:
! 340: case ('['):
! 341: break;
! 342:
! 343: default:
! 344: *d = DECO_SPECIAL;
! 345: *word = wp;
! 346: *sz = 1;
! 347: return(1);
! 348: }
! 349:
! 350: *word = ++wp;
! 351: for (j = 0; *wp && ']' != *wp; wp++, j++)
! 352: /* Loop... */ ;
! 353:
! 354: if ('\0' == *wp)
! 355: return(j + 1);
! 356:
! 357: *d = type ? DECO_SPECIAL : DECO_RESERVED;
! 358: *sz = j;
! 359: return (j + 2);
! 360: }
CVSweb