Print this page
Update to 1.12.3.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mandoc/mdoc_man.c
+++ new/usr/src/cmd/mandoc/mdoc_man.c
1 -/* $Id: mdoc_man.c,v 1.9 2011/10/24 21:47:59 schwarze Exp $ */
1 +/* $Id: mdoc_man.c,v 1.57 2013/12/25 22:00:45 schwarze Exp $ */
2 2 /*
3 - * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
3 + * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
4 4 *
5 5 * Permission to use, copy, modify, and distribute this software for any
6 6 * purpose with or without fee is hereby granted, provided that the above
7 7 * copyright notice and this permission notice appear in all copies.
8 8 *
9 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 16 */
17 17 #ifdef HAVE_CONFIG_H
18 18 #include "config.h"
19 19 #endif
20 20
21 +#include <assert.h>
21 22 #include <stdio.h>
22 23 #include <string.h>
23 24
24 25 #include "mandoc.h"
26 +#include "out.h"
25 27 #include "man.h"
26 28 #include "mdoc.h"
27 29 #include "main.h"
28 30
29 -#define DECL_ARGS const struct mdoc_meta *m, \
30 - const struct mdoc_node *n, \
31 - struct mman *mm
31 +#define DECL_ARGS const struct mdoc_meta *meta, \
32 + const struct mdoc_node *n
32 33
33 -struct mman {
34 - int need_space; /* next word needs prior ws */
35 - int need_nl; /* next word needs prior nl */
36 -};
37 -
38 34 struct manact {
39 35 int (*cond)(DECL_ARGS); /* DON'T run actions */
40 36 int (*pre)(DECL_ARGS); /* pre-node action */
41 37 void (*post)(DECL_ARGS); /* post-node action */
42 38 const char *prefix; /* pre-node string constant */
43 39 const char *suffix; /* post-node string constant */
44 40 };
45 41
46 42 static int cond_body(DECL_ARGS);
47 43 static int cond_head(DECL_ARGS);
44 +static void font_push(char);
45 +static void font_pop(void);
46 +static void mid_it(void);
47 +static void post__t(DECL_ARGS);
48 48 static void post_bd(DECL_ARGS);
49 +static void post_bf(DECL_ARGS);
50 +static void post_bk(DECL_ARGS);
51 +static void post_bl(DECL_ARGS);
49 52 static void post_dl(DECL_ARGS);
50 53 static void post_enc(DECL_ARGS);
54 +static void post_eo(DECL_ARGS);
55 +static void post_fa(DECL_ARGS);
56 +static void post_fd(DECL_ARGS);
57 +static void post_fl(DECL_ARGS);
58 +static void post_fn(DECL_ARGS);
59 +static void post_fo(DECL_ARGS);
60 +static void post_font(DECL_ARGS);
61 +static void post_in(DECL_ARGS);
62 +static void post_it(DECL_ARGS);
63 +static void post_lb(DECL_ARGS);
51 64 static void post_nm(DECL_ARGS);
52 65 static void post_percent(DECL_ARGS);
53 66 static void post_pf(DECL_ARGS);
54 67 static void post_sect(DECL_ARGS);
55 68 static void post_sp(DECL_ARGS);
69 +static void post_vt(DECL_ARGS);
70 +static int pre__t(DECL_ARGS);
71 +static int pre_an(DECL_ARGS);
56 72 static int pre_ap(DECL_ARGS);
57 73 static int pre_bd(DECL_ARGS);
74 +static int pre_bf(DECL_ARGS);
75 +static int pre_bk(DECL_ARGS);
76 +static int pre_bl(DECL_ARGS);
58 77 static int pre_br(DECL_ARGS);
59 78 static int pre_bx(DECL_ARGS);
60 79 static int pre_dl(DECL_ARGS);
61 80 static int pre_enc(DECL_ARGS);
81 +static int pre_em(DECL_ARGS);
82 +static int pre_fa(DECL_ARGS);
83 +static int pre_fd(DECL_ARGS);
84 +static int pre_fl(DECL_ARGS);
85 +static int pre_fn(DECL_ARGS);
86 +static int pre_fo(DECL_ARGS);
87 +static int pre_ft(DECL_ARGS);
88 +static int pre_in(DECL_ARGS);
62 89 static int pre_it(DECL_ARGS);
90 +static int pre_lk(DECL_ARGS);
91 +static int pre_li(DECL_ARGS);
63 92 static int pre_nm(DECL_ARGS);
93 +static int pre_no(DECL_ARGS);
64 94 static int pre_ns(DECL_ARGS);
65 95 static int pre_pp(DECL_ARGS);
96 +static int pre_rs(DECL_ARGS);
97 +static int pre_sm(DECL_ARGS);
66 98 static int pre_sp(DECL_ARGS);
67 99 static int pre_sect(DECL_ARGS);
100 +static int pre_sy(DECL_ARGS);
101 +static void pre_syn(const struct mdoc_node *);
102 +static int pre_vt(DECL_ARGS);
68 103 static int pre_ux(DECL_ARGS);
69 104 static int pre_xr(DECL_ARGS);
70 -static void print_word(struct mman *, const char *);
105 +static void print_word(const char *);
106 +static void print_line(const char *, int);
107 +static void print_block(const char *, int);
108 +static void print_offs(const char *);
109 +static void print_width(const char *,
110 + const struct mdoc_node *, size_t);
111 +static void print_count(int *);
71 112 static void print_node(DECL_ARGS);
72 113
73 114 static const struct manact manacts[MDOC_MAX + 1] = {
74 115 { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
75 116 { NULL, NULL, NULL, NULL, NULL }, /* Dd */
76 117 { NULL, NULL, NULL, NULL, NULL }, /* Dt */
77 118 { NULL, NULL, NULL, NULL, NULL }, /* Os */
78 119 { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
79 120 { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
80 121 { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
81 122 { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
82 123 { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
83 124 { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
84 125 { NULL, NULL, NULL, NULL, NULL }, /* Ed */
85 - { NULL, NULL, NULL, NULL, NULL }, /* Bl */
126 + { cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */
86 127 { NULL, NULL, NULL, NULL, NULL }, /* El */
87 - { NULL, pre_it, NULL, NULL, NULL }, /* _It */
88 - { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ad */
89 - { NULL, NULL, NULL, NULL, NULL }, /* _An */
90 - { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
91 - { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cd */
92 - { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
93 - { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Dv */
94 - { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Er */
95 - { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Ev */
128 + { NULL, pre_it, post_it, NULL, NULL }, /* It */
129 + { NULL, pre_em, post_font, NULL, NULL }, /* Ad */
130 + { NULL, pre_an, NULL, NULL, NULL }, /* An */
131 + { NULL, pre_em, post_font, NULL, NULL }, /* Ar */
132 + { NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
133 + { NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
134 + { NULL, pre_li, post_font, NULL, NULL }, /* Dv */
135 + { NULL, pre_li, post_font, NULL, NULL }, /* Er */
136 + { NULL, pre_li, post_font, NULL, NULL }, /* Ev */
96 137 { NULL, pre_enc, post_enc, "The \\fB",
97 138 "\\fP\nutility exits 0 on success, and >0 if an error occurs."
98 139 }, /* Ex */
99 - { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
100 - { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
101 - { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
102 - { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
103 - { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
104 - { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */
105 - { NULL, NULL, NULL, NULL, NULL }, /* _In */
106 - { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Li */
140 + { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
141 + { NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */
142 + { NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */
143 + { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
144 + { NULL, pre_ft, post_font, NULL, NULL }, /* Ft */
145 + { NULL, pre_sy, post_font, NULL, NULL }, /* Ic */
146 + { NULL, pre_in, post_in, NULL, NULL }, /* In */
147 + { NULL, pre_li, post_font, NULL, NULL }, /* Li */
107 148 { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
108 149 { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
109 150 { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
110 151 { NULL, NULL, NULL, NULL, NULL }, /* Ot */
111 - { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Pa */
152 + { NULL, pre_em, post_font, NULL, NULL }, /* Pa */
112 153 { NULL, pre_enc, post_enc, "The \\fB",
113 154 "\\fP\nfunction returns the value 0 if successful;\n"
114 155 "otherwise the value -1 is returned and the global\n"
115 156 "variable \\fIerrno\\fP is set to indicate the error."
116 157 }, /* Rv */
117 158 { NULL, NULL, NULL, NULL, NULL }, /* St */
118 - { NULL, NULL, NULL, NULL, NULL }, /* _Va */
119 - { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
159 + { NULL, pre_em, post_font, NULL, NULL }, /* Va */
160 + { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
120 161 { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
121 - { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
122 - { NULL, NULL, NULL, NULL, NULL }, /* _%B */
123 - { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
124 - { NULL, NULL, NULL, NULL, NULL }, /* _%I */
125 - { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
126 - { NULL, NULL, NULL, NULL, NULL }, /* _%N */
127 - { NULL, NULL, NULL, NULL, NULL }, /* _%O */
128 - { NULL, NULL, NULL, NULL, NULL }, /* _%P */
129 - { NULL, NULL, NULL, NULL, NULL }, /* _%R */
130 - { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
131 - { NULL, NULL, NULL, NULL, NULL }, /* _%V */
162 + { NULL, NULL, post_percent, NULL, NULL }, /* %A */
163 + { NULL, pre_em, post_percent, NULL, NULL }, /* %B */
164 + { NULL, NULL, post_percent, NULL, NULL }, /* %D */
165 + { NULL, pre_em, post_percent, NULL, NULL }, /* %I */
166 + { NULL, pre_em, post_percent, NULL, NULL }, /* %J */
167 + { NULL, NULL, post_percent, NULL, NULL }, /* %N */
168 + { NULL, NULL, post_percent, NULL, NULL }, /* %O */
169 + { NULL, NULL, post_percent, NULL, NULL }, /* %P */
170 + { NULL, NULL, post_percent, NULL, NULL }, /* %R */
171 + { NULL, pre__t, post__t, NULL, NULL }, /* %T */
172 + { NULL, NULL, post_percent, NULL, NULL }, /* %V */
132 173 { NULL, NULL, NULL, NULL, NULL }, /* Ac */
133 174 { cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */
134 175 { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
135 176 { NULL, NULL, NULL, NULL, NULL }, /* At */
136 177 { NULL, NULL, NULL, NULL, NULL }, /* Bc */
137 - { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
178 + { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
138 179 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
139 180 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
140 181 { NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */
141 182 { NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
142 183 { NULL, NULL, NULL, NULL, NULL }, /* Db */
143 184 { NULL, NULL, NULL, NULL, NULL }, /* Dc */
144 - { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */
145 - { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
146 - { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
147 - { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
148 - { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */
149 - { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
185 + { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
186 + { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
187 + { NULL, NULL, NULL, NULL, NULL }, /* Ec */
188 + { NULL, NULL, NULL, NULL, NULL }, /* Ef */
189 + { NULL, pre_em, post_font, NULL, NULL }, /* Em */
190 + { NULL, NULL, post_eo, NULL, NULL }, /* Eo */
150 191 { NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */
151 - { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ms */
152 - { NULL, NULL, NULL, NULL, NULL }, /* No */
192 + { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
193 + { NULL, pre_no, NULL, NULL, NULL }, /* No */
153 194 { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
154 195 { NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */
155 196 { NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */
156 197 { NULL, NULL, NULL, NULL, NULL }, /* Pc */
157 198 { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
158 199 { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
159 200 { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
160 201 { NULL, NULL, NULL, NULL, NULL }, /* Qc */
161 - { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
202 + { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
162 203 { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
163 204 { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
164 205 { NULL, NULL, NULL, NULL, NULL }, /* Re */
165 - { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
206 + { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
166 207 { NULL, NULL, NULL, NULL, NULL }, /* Sc */
167 - { cond_body, pre_enc, post_enc, "`", "'" }, /* So */
168 - { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
169 - { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
170 - { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */
171 - { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */
172 - { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Tn */
208 + { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */
209 + { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */
210 + { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
211 + { NULL, pre_em, post_font, NULL, NULL }, /* Sx */
212 + { NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
213 + { NULL, pre_li, post_font, NULL, NULL }, /* Tn */
173 214 { NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */
174 - { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
175 - { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
176 - { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
177 - { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
215 + { NULL, NULL, NULL, NULL, NULL }, /* Xc */
216 + { NULL, NULL, NULL, NULL, NULL }, /* Xo */
217 + { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
218 + { NULL, NULL, NULL, NULL, NULL }, /* Fc */
178 219 { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
179 220 { NULL, NULL, NULL, NULL, NULL }, /* Oc */
180 - { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
181 - { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
221 + { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
222 + { NULL, NULL, NULL, NULL, NULL }, /* Ek */
182 223 { NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */
183 224 { NULL, NULL, NULL, NULL, NULL }, /* Hf */
184 225 { NULL, NULL, NULL, NULL, NULL }, /* Fr */
185 226 { NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */
186 - { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
227 + { NULL, NULL, post_lb, NULL, NULL }, /* Lb */
187 228 { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
188 - { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
189 - { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
229 + { NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
230 + { NULL, pre_em, post_font, NULL, NULL }, /* Mt */
190 231 { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
191 232 { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
192 233 { NULL, NULL, NULL, NULL, NULL }, /* Brc */
193 - { NULL, NULL, NULL, NULL, NULL }, /* _%C */
194 - { NULL, NULL, NULL, NULL, NULL }, /* _Es */
195 - { NULL, NULL, NULL, NULL, NULL }, /* _En */
234 + { NULL, NULL, post_percent, NULL, NULL }, /* %C */
235 + { NULL, NULL, NULL, NULL, NULL }, /* Es */
236 + { NULL, NULL, NULL, NULL, NULL }, /* En */
196 237 { NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */
197 - { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
238 + { NULL, NULL, post_percent, NULL, NULL }, /* %Q */
198 239 { NULL, pre_br, NULL, NULL, NULL }, /* br */
199 240 { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
200 - { NULL, NULL, NULL, NULL, NULL }, /* _%U */
201 - { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
241 + { NULL, NULL, post_percent, NULL, NULL }, /* %U */
242 + { NULL, NULL, NULL, NULL, NULL }, /* Ta */
202 243 { NULL, NULL, NULL, NULL, NULL }, /* ROOT */
203 244 };
204 245
246 +static int outflags;
247 +#define MMAN_spc (1 << 0) /* blank character before next word */
248 +#define MMAN_spc_force (1 << 1) /* even before trailing punctuation */
249 +#define MMAN_nl (1 << 2) /* break man(7) code line */
250 +#define MMAN_br (1 << 3) /* break output line */
251 +#define MMAN_sp (1 << 4) /* insert a blank output line */
252 +#define MMAN_PP (1 << 5) /* reset indentation etc. */
253 +#define MMAN_Sm (1 << 6) /* horizontal spacing mode */
254 +#define MMAN_Bk (1 << 7) /* word keep mode */
255 +#define MMAN_Bk_susp (1 << 8) /* suspend this (after a macro) */
256 +#define MMAN_An_split (1 << 9) /* author mode is "split" */
257 +#define MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */
258 +#define MMAN_PD (1 << 11) /* inter-paragraph spacing disabled */
259 +#define MMAN_nbrword (1 << 12) /* do not break the next word */
260 +
261 +#define BL_STACK_MAX 32
262 +
263 +static size_t Bl_stack[BL_STACK_MAX]; /* offsets [chars] */
264 +static int Bl_stack_post[BL_STACK_MAX]; /* add final .RE */
265 +static int Bl_stack_len; /* number of nested Bl blocks */
266 +static int TPremain; /* characters before tag is full */
267 +
268 +static struct {
269 + char *head;
270 + char *tail;
271 + size_t size;
272 +} fontqueue;
273 +
205 274 static void
206 -print_word(struct mman *mm, const char *s)
275 +font_push(char newfont)
207 276 {
208 277
209 - if (mm->need_nl) {
278 + if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) {
279 + fontqueue.size += 8;
280 + fontqueue.head = mandoc_realloc(fontqueue.head,
281 + fontqueue.size);
282 + }
283 + *fontqueue.tail = newfont;
284 + print_word("");
285 + printf("\\f");
286 + putchar(newfont);
287 + outflags &= ~MMAN_spc;
288 +}
289 +
290 +static void
291 +font_pop(void)
292 +{
293 +
294 + if (fontqueue.tail > fontqueue.head)
295 + fontqueue.tail--;
296 + outflags &= ~MMAN_spc;
297 + print_word("");
298 + printf("\\f");
299 + putchar(*fontqueue.tail);
300 +}
301 +
302 +static void
303 +print_word(const char *s)
304 +{
305 +
306 + if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
210 307 /*
211 308 * If we need a newline, print it now and start afresh.
212 309 */
213 - putchar('\n');
214 - mm->need_space = 0;
215 - mm->need_nl = 0;
216 - } else if (mm->need_space && '\0' != s[0])
310 + if (MMAN_PP & outflags) {
311 + if (MMAN_sp & outflags) {
312 + if (MMAN_PD & outflags) {
313 + printf("\n.PD");
314 + outflags &= ~MMAN_PD;
315 + }
316 + } else if ( ! (MMAN_PD & outflags)) {
317 + printf("\n.PD 0");
318 + outflags |= MMAN_PD;
319 + }
320 + printf("\n.PP\n");
321 + } else if (MMAN_sp & outflags)
322 + printf("\n.sp\n");
323 + else if (MMAN_br & outflags)
324 + printf("\n.br\n");
325 + else if (MMAN_nl & outflags)
326 + putchar('\n');
327 + outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
328 + if (1 == TPremain)
329 + printf(".br\n");
330 + TPremain = 0;
331 + } else if (MMAN_spc & outflags) {
217 332 /*
218 - * If we need a space, only print it before
219 - * (1) a nonzero length word;
220 - * (2) a word that is non-punctuation; and
221 - * (3) if punctuation, non-terminating puncutation.
333 + * If we need a space, only print it if
334 + * (1) it is forced by `No' or
335 + * (2) what follows is not terminating punctuation or
336 + * (3) what follows is longer than one character.
222 337 */
223 - if (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1])
338 + if (MMAN_spc_force & outflags || '\0' == s[0] ||
339 + NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
340 + if (MMAN_Bk & outflags &&
341 + ! (MMAN_Bk_susp & outflags))
342 + putchar('\\');
224 343 putchar(' ');
344 + if (TPremain)
345 + TPremain--;
346 + }
347 + }
225 348
226 349 /*
227 350 * Reassign needing space if we're not following opening
228 351 * punctuation.
229 352 */
230 - mm->need_space =
231 - ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
353 + if (MMAN_Sm & outflags && ('\0' == s[0] ||
354 + (('(' != s[0] && '[' != s[0]) || '\0' != s[1])))
355 + outflags |= MMAN_spc;
356 + else
357 + outflags &= ~MMAN_spc;
358 + outflags &= ~(MMAN_spc_force | MMAN_Bk_susp);
232 359
233 360 for ( ; *s; s++) {
234 361 switch (*s) {
235 362 case (ASCII_NBRSP):
236 - printf("\\~");
363 + printf("\\ ");
237 364 break;
238 365 case (ASCII_HYPH):
239 366 putchar('-');
240 367 break;
368 + case (' '):
369 + if (MMAN_nbrword & outflags) {
370 + printf("\\ ");
371 + break;
372 + }
373 + /* FALLTHROUGH */
241 374 default:
242 375 putchar((unsigned char)*s);
243 376 break;
244 377 }
378 + if (TPremain)
379 + TPremain--;
245 380 }
381 + outflags &= ~MMAN_nbrword;
246 382 }
247 383
384 +static void
385 +print_line(const char *s, int newflags)
386 +{
387 +
388 + outflags &= ~MMAN_br;
389 + outflags |= MMAN_nl;
390 + print_word(s);
391 + outflags |= newflags;
392 +}
393 +
394 +static void
395 +print_block(const char *s, int newflags)
396 +{
397 +
398 + outflags &= ~MMAN_PP;
399 + if (MMAN_sp & outflags) {
400 + outflags &= ~(MMAN_sp | MMAN_br);
401 + if (MMAN_PD & outflags) {
402 + print_line(".PD", 0);
403 + outflags &= ~MMAN_PD;
404 + }
405 + } else if (! (MMAN_PD & outflags))
406 + print_line(".PD 0", MMAN_PD);
407 + outflags |= MMAN_nl;
408 + print_word(s);
409 + outflags |= MMAN_Bk_susp | newflags;
410 +}
411 +
412 +static void
413 +print_offs(const char *v)
414 +{
415 + char buf[24];
416 + struct roffsu su;
417 + size_t sz;
418 +
419 + print_line(".RS", MMAN_Bk_susp);
420 +
421 + /* Convert v into a number (of characters). */
422 + if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
423 + sz = 0;
424 + else if (0 == strcmp(v, "indent"))
425 + sz = 6;
426 + else if (0 == strcmp(v, "indent-two"))
427 + sz = 12;
428 + else if (a2roffsu(v, &su, SCALE_MAX)) {
429 + if (SCALE_EN == su.unit)
430 + sz = su.scale;
431 + else {
432 + /*
433 + * XXX
434 + * If we are inside an enclosing list,
435 + * there is no easy way to add the two
436 + * indentations because they are provided
437 + * in terms of different units.
438 + */
439 + print_word(v);
440 + outflags |= MMAN_nl;
441 + return;
442 + }
443 + } else
444 + sz = strlen(v);
445 +
446 + /*
447 + * We are inside an enclosing list.
448 + * Add the two indentations.
449 + */
450 + if (Bl_stack_len)
451 + sz += Bl_stack[Bl_stack_len - 1];
452 +
453 + snprintf(buf, sizeof(buf), "%zun", sz);
454 + print_word(buf);
455 + outflags |= MMAN_nl;
456 +}
457 +
458 +/*
459 + * Set up the indentation for a list item; used from pre_it().
460 + */
248 461 void
462 +print_width(const char *v, const struct mdoc_node *child, size_t defsz)
463 +{
464 + char buf[24];
465 + struct roffsu su;
466 + size_t sz, chsz;
467 + int numeric, remain;
468 +
469 + numeric = 1;
470 + remain = 0;
471 +
472 + /* Convert v into a number (of characters). */
473 + if (NULL == v)
474 + sz = defsz;
475 + else if (a2roffsu(v, &su, SCALE_MAX)) {
476 + if (SCALE_EN == su.unit)
477 + sz = su.scale;
478 + else {
479 + sz = 0;
480 + numeric = 0;
481 + }
482 + } else
483 + sz = strlen(v);
484 +
485 + /* XXX Rough estimation, might have multiple parts. */
486 + chsz = (NULL != child && MDOC_TEXT == child->type) ?
487 + strlen(child->string) : 0;
488 +
489 + /* Maybe we are inside an enclosing list? */
490 + mid_it();
491 +
492 + /*
493 + * Save our own indentation,
494 + * such that child lists can use it.
495 + */
496 + Bl_stack[Bl_stack_len++] = sz + 2;
497 +
498 + /* Set up the current list. */
499 + if (defsz && chsz > sz)
500 + print_block(".HP", 0);
501 + else {
502 + print_block(".TP", 0);
503 + remain = sz + 2;
504 + }
505 + if (numeric) {
506 + snprintf(buf, sizeof(buf), "%zun", sz + 2);
507 + print_word(buf);
508 + } else
509 + print_word(v);
510 + TPremain = remain;
511 +}
512 +
513 +void
514 +print_count(int *count)
515 +{
516 + char buf[12];
517 +
518 + snprintf(buf, sizeof(buf), "%d.", ++*count);
519 + print_word(buf);
520 +}
521 +
522 +void
249 523 man_man(void *arg, const struct man *man)
250 524 {
251 525
252 526 /*
253 527 * Dump the keep buffer.
254 528 * We're guaranteed by now that this exists (is non-NULL).
255 529 * Flush stdout afterward, just in case.
256 530 */
257 531 fputs(mparse_getkeep(man_mparse(man)), stdout);
258 532 fflush(stdout);
259 533 }
260 534
261 535 void
262 536 man_mdoc(void *arg, const struct mdoc *mdoc)
263 537 {
264 - const struct mdoc_meta *m;
538 + const struct mdoc_meta *meta;
265 539 const struct mdoc_node *n;
266 - struct mman mm;
267 540
268 - m = mdoc_meta(mdoc);
541 + meta = mdoc_meta(mdoc);
269 542 n = mdoc_node(mdoc);
270 543
271 - printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
272 - m->title, m->msec, m->date, m->os, m->vol);
544 + printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
545 + meta->title, meta->msec, meta->date,
546 + meta->os, meta->vol);
273 547
274 - memset(&mm, 0, sizeof(struct mman));
548 + /* Disable hyphenation and if nroff, disable justification. */
549 + printf(".nh\n.if n .ad l");
275 550
276 - mm.need_nl = 1;
277 - print_node(m, n, &mm);
551 + outflags = MMAN_nl | MMAN_Sm;
552 + if (0 == fontqueue.size) {
553 + fontqueue.size = 8;
554 + fontqueue.head = fontqueue.tail = mandoc_malloc(8);
555 + *fontqueue.tail = 'R';
556 + }
557 + print_node(meta, n);
278 558 putchar('\n');
279 559 }
280 560
281 561 static void
282 562 print_node(DECL_ARGS)
283 563 {
284 - const struct mdoc_node *prev, *sub;
564 + const struct mdoc_node *sub;
285 565 const struct manact *act;
286 566 int cond, do_sub;
287 -
567 +
288 568 /*
289 569 * Break the line if we were parsed subsequent the current node.
290 570 * This makes the page structure be more consistent.
291 571 */
292 - prev = n->prev ? n->prev : n->parent;
293 - if (prev && prev->line < n->line)
294 - mm->need_nl = 1;
572 + if (MMAN_spc & outflags && MDOC_LINE & n->flags)
573 + outflags |= MMAN_nl;
295 574
296 575 act = NULL;
297 576 cond = 0;
298 577 do_sub = 1;
299 578
300 579 if (MDOC_TEXT == n->type) {
301 580 /*
302 581 * Make sure that we don't happen to start with a
303 582 * control character at the start of a line.
304 583 */
305 - if (mm->need_nl && ('.' == *n->string ||
584 + if (MMAN_nl & outflags && ('.' == *n->string ||
306 585 '\'' == *n->string)) {
307 - print_word(mm, "\\&");
308 - mm->need_space = 0;
586 + print_word("");
587 + printf("\\&");
588 + outflags &= ~MMAN_spc;
309 589 }
310 - print_word(mm, n->string);
590 + print_word(n->string);
311 591 } else {
312 592 /*
313 593 * Conditionally run the pre-node action handler for a
314 594 * node.
315 595 */
316 596 act = manacts + n->tok;
317 - cond = NULL == act->cond || (*act->cond)(m, n, mm);
597 + cond = NULL == act->cond || (*act->cond)(meta, n);
318 598 if (cond && act->pre)
319 - do_sub = (*act->pre)(m, n, mm);
599 + do_sub = (*act->pre)(meta, n);
320 600 }
321 601
322 602 /*
323 603 * Conditionally run all child nodes.
324 604 * Note that this iterates over children instead of using
325 605 * recursion. This prevents unnecessary depth in the stack.
326 606 */
327 607 if (do_sub)
328 608 for (sub = n->child; sub; sub = sub->next)
329 - print_node(m, sub, mm);
609 + print_node(meta, sub);
330 610
331 611 /*
332 612 * Lastly, conditionally run the post-node handler.
333 613 */
334 614 if (cond && act->post)
335 - (*act->post)(m, n, mm);
615 + (*act->post)(meta, n);
336 616 }
337 617
338 618 static int
339 619 cond_head(DECL_ARGS)
340 620 {
341 621
342 622 return(MDOC_HEAD == n->type);
343 623 }
344 624
345 625 static int
346 626 cond_body(DECL_ARGS)
347 627 {
348 628
349 629 return(MDOC_BODY == n->type);
350 630 }
351 631
352 -/*
353 - * Output a font encoding before a node, e.g., \fR.
354 - * This obviously has no trailing space.
355 - */
356 632 static int
357 633 pre_enc(DECL_ARGS)
358 634 {
359 635 const char *prefix;
360 636
361 637 prefix = manacts[n->tok].prefix;
362 638 if (NULL == prefix)
363 639 return(1);
364 - print_word(mm, prefix);
365 - mm->need_space = 0;
640 + print_word(prefix);
641 + outflags &= ~MMAN_spc;
366 642 return(1);
367 643 }
368 644
369 -/*
370 - * Output a font encoding subsequent a node, e.g., \fP.
371 - */
372 645 static void
373 646 post_enc(DECL_ARGS)
374 647 {
375 648 const char *suffix;
376 649
377 650 suffix = manacts[n->tok].suffix;
378 651 if (NULL == suffix)
379 652 return;
380 - mm->need_space = 0;
381 - print_word(mm, suffix);
653 + outflags &= ~MMAN_spc;
654 + print_word(suffix);
382 655 }
383 656
384 -/*
385 - * Used in listings (percent = %A, e.g.).
386 - * FIXME: this is incomplete.
387 - * It doesn't print a nice ", and" for lists.
388 - */
389 657 static void
658 +post_font(DECL_ARGS)
659 +{
660 +
661 + font_pop();
662 +}
663 +
664 +static void
390 665 post_percent(DECL_ARGS)
391 666 {
392 667
393 - post_enc(m, n, mm);
394 - if (n->next)
395 - print_word(mm, ",");
396 - else {
397 - print_word(mm, ".");
398 - mm->need_nl = 1;
668 + if (pre_em == manacts[n->tok].pre)
669 + font_pop();
670 + if (n->next) {
671 + print_word(",");
672 + if (n->prev && n->prev->tok == n->tok &&
673 + n->next->tok == n->tok)
674 + print_word("and");
675 + } else {
676 + print_word(".");
677 + outflags |= MMAN_nl;
399 678 }
400 679 }
401 680
681 +static int
682 +pre__t(DECL_ARGS)
683 +{
684 +
685 + if (n->parent && MDOC_Rs == n->parent->tok &&
686 + n->parent->norm->Rs.quote_T) {
687 + print_word("");
688 + putchar('\"');
689 + outflags &= ~MMAN_spc;
690 + } else
691 + font_push('I');
692 + return(1);
693 +}
694 +
695 +static void
696 +post__t(DECL_ARGS)
697 +{
698 +
699 + if (n->parent && MDOC_Rs == n->parent->tok &&
700 + n->parent->norm->Rs.quote_T) {
701 + outflags &= ~MMAN_spc;
702 + print_word("");
703 + putchar('\"');
704 + } else
705 + font_pop();
706 + post_percent(meta, n);
707 +}
708 +
402 709 /*
403 710 * Print before a section header.
404 711 */
405 712 static int
406 713 pre_sect(DECL_ARGS)
407 714 {
408 715
409 - if (MDOC_HEAD != n->type)
410 - return(1);
411 - mm->need_nl = 1;
412 - print_word(mm, manacts[n->tok].prefix);
413 - print_word(mm, "\"");
414 - mm->need_space = 0;
716 + if (MDOC_HEAD == n->type) {
717 + outflags |= MMAN_sp;
718 + print_block(manacts[n->tok].prefix, 0);
719 + print_word("");
720 + putchar('\"');
721 + outflags &= ~MMAN_spc;
722 + }
415 723 return(1);
416 724 }
417 725
418 726 /*
419 727 * Print subsequent a section header.
420 728 */
421 729 static void
422 730 post_sect(DECL_ARGS)
423 731 {
424 732
425 733 if (MDOC_HEAD != n->type)
426 734 return;
427 - mm->need_space = 0;
428 - print_word(mm, "\"");
429 - mm->need_nl = 1;
735 + outflags &= ~MMAN_spc;
736 + print_word("");
737 + putchar('\"');
738 + outflags |= MMAN_nl;
739 + if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec)
740 + outflags &= ~(MMAN_An_split | MMAN_An_nosplit);
430 741 }
431 742
743 +/* See mdoc_term.c, synopsis_pre() for comments. */
744 +static void
745 +pre_syn(const struct mdoc_node *n)
746 +{
747 +
748 + if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
749 + return;
750 +
751 + if (n->prev->tok == n->tok &&
752 + MDOC_Ft != n->tok &&
753 + MDOC_Fo != n->tok &&
754 + MDOC_Fn != n->tok) {
755 + outflags |= MMAN_br;
756 + return;
757 + }
758 +
759 + switch (n->prev->tok) {
760 + case (MDOC_Fd):
761 + /* FALLTHROUGH */
762 + case (MDOC_Fn):
763 + /* FALLTHROUGH */
764 + case (MDOC_Fo):
765 + /* FALLTHROUGH */
766 + case (MDOC_In):
767 + /* FALLTHROUGH */
768 + case (MDOC_Vt):
769 + outflags |= MMAN_sp;
770 + break;
771 + case (MDOC_Ft):
772 + if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
773 + outflags |= MMAN_sp;
774 + break;
775 + }
776 + /* FALLTHROUGH */
777 + default:
778 + outflags |= MMAN_br;
779 + break;
780 + }
781 +}
782 +
432 783 static int
784 +pre_an(DECL_ARGS)
785 +{
786 +
787 + switch (n->norm->An.auth) {
788 + case (AUTH_split):
789 + outflags &= ~MMAN_An_nosplit;
790 + outflags |= MMAN_An_split;
791 + return(0);
792 + case (AUTH_nosplit):
793 + outflags &= ~MMAN_An_split;
794 + outflags |= MMAN_An_nosplit;
795 + return(0);
796 + default:
797 + if (MMAN_An_split & outflags)
798 + outflags |= MMAN_br;
799 + else if (SEC_AUTHORS == n->sec &&
800 + ! (MMAN_An_nosplit & outflags))
801 + outflags |= MMAN_An_split;
802 + return(1);
803 + }
804 +}
805 +
806 +static int
433 807 pre_ap(DECL_ARGS)
434 808 {
435 809
436 - mm->need_space = 0;
437 - print_word(mm, "'");
438 - mm->need_space = 0;
810 + outflags &= ~MMAN_spc;
811 + print_word("'");
812 + outflags &= ~MMAN_spc;
439 813 return(0);
440 814 }
441 815
442 816 static int
443 817 pre_bd(DECL_ARGS)
444 818 {
445 819
820 + outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
821 +
446 822 if (DISP_unfilled == n->norm->Bd.type ||
447 - DISP_literal == n->norm->Bd.type) {
448 - mm->need_nl = 1;
449 - print_word(mm, ".nf");
450 - }
451 - mm->need_nl = 1;
823 + DISP_literal == n->norm->Bd.type)
824 + print_line(".nf", 0);
825 + if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
826 + outflags |= MMAN_sp;
827 + print_offs(n->norm->Bd.offs);
452 828 return(1);
453 829 }
454 830
455 831 static void
456 832 post_bd(DECL_ARGS)
457 833 {
458 834
835 + /* Close out this display. */
836 + print_line(".RE", MMAN_nl);
459 837 if (DISP_unfilled == n->norm->Bd.type ||
460 - DISP_literal == n->norm->Bd.type) {
461 - mm->need_nl = 1;
462 - print_word(mm, ".fi");
838 + DISP_literal == n->norm->Bd.type)
839 + print_line(".fi", MMAN_nl);
840 +
841 + /* Maybe we are inside an enclosing list? */
842 + if (NULL != n->parent->next)
843 + mid_it();
844 +}
845 +
846 +static int
847 +pre_bf(DECL_ARGS)
848 +{
849 +
850 + switch (n->type) {
851 + case (MDOC_BLOCK):
852 + return(1);
853 + case (MDOC_BODY):
854 + break;
855 + default:
856 + return(0);
463 857 }
464 - mm->need_nl = 1;
858 + switch (n->norm->Bf.font) {
859 + case (FONT_Em):
860 + font_push('I');
861 + break;
862 + case (FONT_Sy):
863 + font_push('B');
864 + break;
865 + default:
866 + font_push('R');
867 + break;
868 + }
869 + return(1);
465 870 }
466 871
872 +static void
873 +post_bf(DECL_ARGS)
874 +{
875 +
876 + if (MDOC_BODY == n->type)
877 + font_pop();
878 +}
879 +
467 880 static int
881 +pre_bk(DECL_ARGS)
882 +{
883 +
884 + switch (n->type) {
885 + case (MDOC_BLOCK):
886 + return(1);
887 + case (MDOC_BODY):
888 + outflags |= MMAN_Bk;
889 + return(1);
890 + default:
891 + return(0);
892 + }
893 +}
894 +
895 +static void
896 +post_bk(DECL_ARGS)
897 +{
898 +
899 + if (MDOC_BODY == n->type)
900 + outflags &= ~MMAN_Bk;
901 +}
902 +
903 +static int
904 +pre_bl(DECL_ARGS)
905 +{
906 + size_t icol;
907 +
908 + /*
909 + * print_offs() will increase the -offset to account for
910 + * a possible enclosing .It, but any enclosed .It blocks
911 + * just nest and do not add up their indentation.
912 + */
913 + if (n->norm->Bl.offs) {
914 + print_offs(n->norm->Bl.offs);
915 + Bl_stack[Bl_stack_len++] = 0;
916 + }
917 +
918 + switch (n->norm->Bl.type) {
919 + case (LIST_enum):
920 + n->norm->Bl.count = 0;
921 + return(1);
922 + case (LIST_column):
923 + break;
924 + default:
925 + return(1);
926 + }
927 +
928 + print_line(".TS", MMAN_nl);
929 + for (icol = 0; icol < n->norm->Bl.ncols; icol++)
930 + print_word("l");
931 + print_word(".");
932 + outflags |= MMAN_nl;
933 + return(1);
934 +}
935 +
936 +static void
937 +post_bl(DECL_ARGS)
938 +{
939 +
940 + switch (n->norm->Bl.type) {
941 + case (LIST_column):
942 + print_line(".TE", 0);
943 + break;
944 + case (LIST_enum):
945 + n->norm->Bl.count = 0;
946 + break;
947 + default:
948 + break;
949 + }
950 +
951 + if (n->norm->Bl.offs) {
952 + print_line(".RE", MMAN_nl);
953 + assert(Bl_stack_len);
954 + Bl_stack_len--;
955 + assert(0 == Bl_stack[Bl_stack_len]);
956 + } else {
957 + outflags |= MMAN_PP | MMAN_nl;
958 + outflags &= ~(MMAN_sp | MMAN_br);
959 + }
960 +
961 + /* Maybe we are inside an enclosing list? */
962 + if (NULL != n->parent->next)
963 + mid_it();
964 +
965 +}
966 +
967 +static int
468 968 pre_br(DECL_ARGS)
469 969 {
470 970
471 - mm->need_nl = 1;
472 - print_word(mm, ".br");
473 - mm->need_nl = 1;
971 + outflags |= MMAN_br;
474 972 return(0);
475 973 }
476 974
477 975 static int
478 976 pre_bx(DECL_ARGS)
479 977 {
480 978
481 979 n = n->child;
482 980 if (n) {
483 - print_word(mm, n->string);
484 - mm->need_space = 0;
981 + print_word(n->string);
982 + outflags &= ~MMAN_spc;
485 983 n = n->next;
486 984 }
487 - print_word(mm, "BSD");
985 + print_word("BSD");
488 986 if (NULL == n)
489 987 return(0);
490 - mm->need_space = 0;
491 - print_word(mm, "-");
492 - mm->need_space = 0;
493 - print_word(mm, n->string);
988 + outflags &= ~MMAN_spc;
989 + print_word("-");
990 + outflags &= ~MMAN_spc;
991 + print_word(n->string);
494 992 return(0);
495 993 }
496 994
497 995 static int
498 996 pre_dl(DECL_ARGS)
499 997 {
500 998
501 - mm->need_nl = 1;
502 - print_word(mm, ".RS 6n");
503 - mm->need_nl = 1;
999 + print_offs("6n");
504 1000 return(1);
505 1001 }
506 1002
507 1003 static void
508 1004 post_dl(DECL_ARGS)
509 1005 {
510 1006
511 - mm->need_nl = 1;
512 - print_word(mm, ".RE");
513 - mm->need_nl = 1;
1007 + print_line(".RE", MMAN_nl);
1008 +
1009 + /* Maybe we are inside an enclosing list? */
1010 + if (NULL != n->parent->next)
1011 + mid_it();
514 1012 }
515 1013
516 1014 static int
1015 +pre_em(DECL_ARGS)
1016 +{
1017 +
1018 + font_push('I');
1019 + return(1);
1020 +}
1021 +
1022 +static void
1023 +post_eo(DECL_ARGS)
1024 +{
1025 +
1026 + if (MDOC_HEAD == n->type || MDOC_BODY == n->type)
1027 + outflags &= ~MMAN_spc;
1028 +}
1029 +
1030 +static int
1031 +pre_fa(DECL_ARGS)
1032 +{
1033 + int am_Fa;
1034 +
1035 + am_Fa = MDOC_Fa == n->tok;
1036 +
1037 + if (am_Fa)
1038 + n = n->child;
1039 +
1040 + while (NULL != n) {
1041 + font_push('I');
1042 + if (am_Fa || MDOC_SYNPRETTY & n->flags)
1043 + outflags |= MMAN_nbrword;
1044 + print_node(meta, n);
1045 + font_pop();
1046 + if (NULL != (n = n->next))
1047 + print_word(",");
1048 + }
1049 + return(0);
1050 +}
1051 +
1052 +static void
1053 +post_fa(DECL_ARGS)
1054 +{
1055 +
1056 + if (NULL != n->next && MDOC_Fa == n->next->tok)
1057 + print_word(",");
1058 +}
1059 +
1060 +static int
1061 +pre_fd(DECL_ARGS)
1062 +{
1063 +
1064 + pre_syn(n);
1065 + font_push('B');
1066 + return(1);
1067 +}
1068 +
1069 +static void
1070 +post_fd(DECL_ARGS)
1071 +{
1072 +
1073 + font_pop();
1074 + outflags |= MMAN_br;
1075 +}
1076 +
1077 +static int
1078 +pre_fl(DECL_ARGS)
1079 +{
1080 +
1081 + font_push('B');
1082 + print_word("\\-");
1083 + outflags &= ~MMAN_spc;
1084 + return(1);
1085 +}
1086 +
1087 +static void
1088 +post_fl(DECL_ARGS)
1089 +{
1090 +
1091 + font_pop();
1092 + if (0 == n->nchild && NULL != n->next &&
1093 + n->next->line == n->line)
1094 + outflags &= ~MMAN_spc;
1095 +}
1096 +
1097 +static int
1098 +pre_fn(DECL_ARGS)
1099 +{
1100 +
1101 + pre_syn(n);
1102 +
1103 + n = n->child;
1104 + if (NULL == n)
1105 + return(0);
1106 +
1107 + if (MDOC_SYNPRETTY & n->flags)
1108 + print_block(".HP 4n", MMAN_nl);
1109 +
1110 + font_push('B');
1111 + print_node(meta, n);
1112 + font_pop();
1113 + outflags &= ~MMAN_spc;
1114 + print_word("(");
1115 + outflags &= ~MMAN_spc;
1116 +
1117 + n = n->next;
1118 + if (NULL != n)
1119 + pre_fa(meta, n);
1120 + return(0);
1121 +}
1122 +
1123 +static void
1124 +post_fn(DECL_ARGS)
1125 +{
1126 +
1127 + print_word(")");
1128 + if (MDOC_SYNPRETTY & n->flags) {
1129 + print_word(";");
1130 + outflags |= MMAN_PP;
1131 + }
1132 +}
1133 +
1134 +static int
1135 +pre_fo(DECL_ARGS)
1136 +{
1137 +
1138 + switch (n->type) {
1139 + case (MDOC_BLOCK):
1140 + pre_syn(n);
1141 + break;
1142 + case (MDOC_HEAD):
1143 + if (MDOC_SYNPRETTY & n->flags)
1144 + print_block(".HP 4n", MMAN_nl);
1145 + font_push('B');
1146 + break;
1147 + case (MDOC_BODY):
1148 + outflags &= ~MMAN_spc;
1149 + print_word("(");
1150 + outflags &= ~MMAN_spc;
1151 + break;
1152 + default:
1153 + break;
1154 + }
1155 + return(1);
1156 +}
1157 +
1158 +static void
1159 +post_fo(DECL_ARGS)
1160 +{
1161 +
1162 + switch (n->type) {
1163 + case (MDOC_HEAD):
1164 + font_pop();
1165 + break;
1166 + case (MDOC_BODY):
1167 + post_fn(meta, n);
1168 + break;
1169 + default:
1170 + break;
1171 + }
1172 +}
1173 +
1174 +static int
1175 +pre_ft(DECL_ARGS)
1176 +{
1177 +
1178 + pre_syn(n);
1179 + font_push('I');
1180 + return(1);
1181 +}
1182 +
1183 +static int
1184 +pre_in(DECL_ARGS)
1185 +{
1186 +
1187 + if (MDOC_SYNPRETTY & n->flags) {
1188 + pre_syn(n);
1189 + font_push('B');
1190 + print_word("#include <");
1191 + outflags &= ~MMAN_spc;
1192 + } else {
1193 + print_word("<");
1194 + outflags &= ~MMAN_spc;
1195 + font_push('I');
1196 + }
1197 + return(1);
1198 +}
1199 +
1200 +static void
1201 +post_in(DECL_ARGS)
1202 +{
1203 +
1204 + if (MDOC_SYNPRETTY & n->flags) {
1205 + outflags &= ~MMAN_spc;
1206 + print_word(">");
1207 + font_pop();
1208 + outflags |= MMAN_br;
1209 + } else {
1210 + font_pop();
1211 + outflags &= ~MMAN_spc;
1212 + print_word(">");
1213 + }
1214 +}
1215 +
1216 +static int
517 1217 pre_it(DECL_ARGS)
518 1218 {
519 1219 const struct mdoc_node *bln;
520 1220
521 - if (MDOC_HEAD == n->type) {
522 - mm->need_nl = 1;
523 - print_word(mm, ".TP");
524 - bln = n->parent->parent->prev;
1221 + switch (n->type) {
1222 + case (MDOC_HEAD):
1223 + outflags |= MMAN_PP | MMAN_nl;
1224 + bln = n->parent->parent;
1225 + if (0 == bln->norm->Bl.comp ||
1226 + (NULL == n->parent->prev &&
1227 + NULL == bln->parent->prev))
1228 + outflags |= MMAN_sp;
1229 + outflags &= ~MMAN_br;
525 1230 switch (bln->norm->Bl.type) {
1231 + case (LIST_item):
1232 + return(0);
1233 + case (LIST_inset):
1234 + /* FALLTHROUGH */
1235 + case (LIST_diag):
1236 + /* FALLTHROUGH */
1237 + case (LIST_ohang):
1238 + if (bln->norm->Bl.type == LIST_diag)
1239 + print_line(".B \"", 0);
1240 + else
1241 + print_line(".R \"", 0);
1242 + outflags &= ~MMAN_spc;
1243 + return(1);
526 1244 case (LIST_bullet):
527 - print_word(mm, "4n");
528 - mm->need_nl = 1;
529 - print_word(mm, "\\fBo\\fP");
1245 + /* FALLTHROUGH */
1246 + case (LIST_dash):
1247 + /* FALLTHROUGH */
1248 + case (LIST_hyphen):
1249 + print_width(bln->norm->Bl.width, NULL, 0);
1250 + TPremain = 0;
1251 + outflags |= MMAN_nl;
1252 + font_push('B');
1253 + if (LIST_bullet == bln->norm->Bl.type)
1254 + print_word("o");
1255 + else
1256 + print_word("-");
1257 + font_pop();
530 1258 break;
1259 + case (LIST_enum):
1260 + print_width(bln->norm->Bl.width, NULL, 0);
1261 + TPremain = 0;
1262 + outflags |= MMAN_nl;
1263 + print_count(&bln->norm->Bl.count);
1264 + break;
1265 + case (LIST_hang):
1266 + print_width(bln->norm->Bl.width, n->child, 6);
1267 + TPremain = 0;
1268 + break;
1269 + case (LIST_tag):
1270 + print_width(bln->norm->Bl.width, n->child, 0);
1271 + putchar('\n');
1272 + outflags &= ~MMAN_spc;
1273 + return(1);
531 1274 default:
532 - if (bln->norm->Bl.width)
533 - print_word(mm, bln->norm->Bl.width);
1275 + return(1);
1276 + }
1277 + outflags |= MMAN_nl;
1278 + default:
1279 + break;
1280 + }
1281 + return(1);
1282 +}
1283 +
1284 +/*
1285 + * This function is called after closing out an indented block.
1286 + * If we are inside an enclosing list, restore its indentation.
1287 + */
1288 +static void
1289 +mid_it(void)
1290 +{
1291 + char buf[24];
1292 +
1293 + /* Nothing to do outside a list. */
1294 + if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1])
1295 + return;
1296 +
1297 + /* The indentation has already been set up. */
1298 + if (Bl_stack_post[Bl_stack_len - 1])
1299 + return;
1300 +
1301 + /* Restore the indentation of the enclosing list. */
1302 + print_line(".RS", MMAN_Bk_susp);
1303 + snprintf(buf, sizeof(buf), "%zun", Bl_stack[Bl_stack_len - 1]);
1304 + print_word(buf);
1305 +
1306 + /* Remeber to close out this .RS block later. */
1307 + Bl_stack_post[Bl_stack_len - 1] = 1;
1308 +}
1309 +
1310 +static void
1311 +post_it(DECL_ARGS)
1312 +{
1313 + const struct mdoc_node *bln;
1314 +
1315 + bln = n->parent->parent;
1316 +
1317 + switch (n->type) {
1318 + case (MDOC_HEAD):
1319 + switch (bln->norm->Bl.type) {
1320 + case (LIST_diag):
1321 + outflags &= ~MMAN_spc;
1322 + print_word("\\ ");
534 1323 break;
1324 + case (LIST_ohang):
1325 + outflags |= MMAN_br;
1326 + break;
1327 + default:
1328 + break;
535 1329 }
536 - mm->need_nl = 1;
1330 + break;
1331 + case (MDOC_BODY):
1332 + switch (bln->norm->Bl.type) {
1333 + case (LIST_bullet):
1334 + /* FALLTHROUGH */
1335 + case (LIST_dash):
1336 + /* FALLTHROUGH */
1337 + case (LIST_hyphen):
1338 + /* FALLTHROUGH */
1339 + case (LIST_enum):
1340 + /* FALLTHROUGH */
1341 + case (LIST_hang):
1342 + /* FALLTHROUGH */
1343 + case (LIST_tag):
1344 + assert(Bl_stack_len);
1345 + Bl_stack[--Bl_stack_len] = 0;
1346 +
1347 + /*
1348 + * Our indentation had to be restored
1349 + * after a child display or child list.
1350 + * Close out that indentation block now.
1351 + */
1352 + if (Bl_stack_post[Bl_stack_len]) {
1353 + print_line(".RE", MMAN_nl);
1354 + Bl_stack_post[Bl_stack_len] = 0;
1355 + }
1356 + break;
1357 + case (LIST_column):
1358 + if (NULL != n->next) {
1359 + putchar('\t');
1360 + outflags &= ~MMAN_spc;
1361 + }
1362 + break;
1363 + default:
1364 + break;
1365 + }
1366 + break;
1367 + default:
1368 + break;
537 1369 }
1370 +}
1371 +
1372 +static void
1373 +post_lb(DECL_ARGS)
1374 +{
1375 +
1376 + if (SEC_LIBRARY == n->sec)
1377 + outflags |= MMAN_br;
1378 +}
1379 +
1380 +static int
1381 +pre_lk(DECL_ARGS)
1382 +{
1383 + const struct mdoc_node *link, *descr;
1384 +
1385 + if (NULL == (link = n->child))
1386 + return(0);
1387 +
1388 + if (NULL != (descr = link->next)) {
1389 + font_push('I');
1390 + while (NULL != descr) {
1391 + print_word(descr->string);
1392 + descr = descr->next;
1393 + }
1394 + print_word(":");
1395 + font_pop();
1396 + }
1397 +
1398 + font_push('B');
1399 + print_word(link->string);
1400 + font_pop();
1401 + return(0);
1402 +}
1403 +
1404 +static int
1405 +pre_li(DECL_ARGS)
1406 +{
1407 +
1408 + font_push('R');
538 1409 return(1);
539 1410 }
540 1411
541 1412 static int
542 1413 pre_nm(DECL_ARGS)
543 1414 {
1415 + char *name;
544 1416
1417 + if (MDOC_BLOCK == n->type) {
1418 + outflags |= MMAN_Bk;
1419 + pre_syn(n);
1420 + }
545 1421 if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
546 1422 return(1);
547 - print_word(mm, "\\fB");
548 - mm->need_space = 0;
1423 + name = n->child ? n->child->string : meta->name;
1424 + if (NULL == name)
1425 + return(0);
1426 + if (MDOC_HEAD == n->type) {
1427 + if (NULL == n->parent->prev)
1428 + outflags |= MMAN_sp;
1429 + print_block(".HP", 0);
1430 + printf(" %zun", strlen(name) + 1);
1431 + outflags |= MMAN_nl;
1432 + }
1433 + font_push('B');
549 1434 if (NULL == n->child)
550 - print_word(mm, m->name);
1435 + print_word(meta->name);
551 1436 return(1);
552 1437 }
553 1438
554 1439 static void
555 1440 post_nm(DECL_ARGS)
556 1441 {
557 1442
558 - if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
559 - return;
560 - mm->need_space = 0;
561 - print_word(mm, "\\fP");
1443 + switch (n->type) {
1444 + case (MDOC_BLOCK):
1445 + outflags &= ~MMAN_Bk;
1446 + break;
1447 + case (MDOC_HEAD):
1448 + /* FALLTHROUGH */
1449 + case (MDOC_ELEM):
1450 + font_pop();
1451 + break;
1452 + default:
1453 + break;
1454 + }
562 1455 }
563 1456
564 1457 static int
1458 +pre_no(DECL_ARGS)
1459 +{
1460 +
1461 + outflags |= MMAN_spc_force;
1462 + return(1);
1463 +}
1464 +
1465 +static int
565 1466 pre_ns(DECL_ARGS)
566 1467 {
567 1468
568 - mm->need_space = 0;
1469 + outflags &= ~MMAN_spc;
569 1470 return(0);
570 1471 }
571 1472
572 1473 static void
573 1474 post_pf(DECL_ARGS)
574 1475 {
575 1476
576 - mm->need_space = 0;
1477 + outflags &= ~MMAN_spc;
577 1478 }
578 1479
579 1480 static int
580 1481 pre_pp(DECL_ARGS)
581 1482 {
582 1483
583 - mm->need_nl = 1;
584 - if (MDOC_It == n->parent->tok)
585 - print_word(mm, ".sp");
586 - else
587 - print_word(mm, ".PP");
588 - mm->need_nl = 1;
1484 + if (MDOC_It != n->parent->tok)
1485 + outflags |= MMAN_PP;
1486 + outflags |= MMAN_sp | MMAN_nl;
1487 + outflags &= ~MMAN_br;
1488 + return(0);
1489 +}
1490 +
1491 +static int
1492 +pre_rs(DECL_ARGS)
1493 +{
1494 +
1495 + if (SEC_SEE_ALSO == n->sec) {
1496 + outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
1497 + outflags &= ~MMAN_br;
1498 + }
589 1499 return(1);
590 1500 }
591 1501
592 1502 static int
1503 +pre_sm(DECL_ARGS)
1504 +{
1505 +
1506 + assert(n->child && MDOC_TEXT == n->child->type);
1507 + if (0 == strcmp("on", n->child->string))
1508 + outflags |= MMAN_Sm | MMAN_spc;
1509 + else
1510 + outflags &= ~MMAN_Sm;
1511 + return(0);
1512 +}
1513 +
1514 +static int
593 1515 pre_sp(DECL_ARGS)
594 1516 {
595 1517
596 - mm->need_nl = 1;
597 - print_word(mm, ".sp");
1518 + if (MMAN_PP & outflags) {
1519 + outflags &= ~MMAN_PP;
1520 + print_line(".PP", 0);
1521 + } else
1522 + print_line(".sp", 0);
598 1523 return(1);
599 1524 }
600 1525
601 1526 static void
602 1527 post_sp(DECL_ARGS)
603 1528 {
604 1529
605 - mm->need_nl = 1;
1530 + outflags |= MMAN_nl;
606 1531 }
607 1532
608 1533 static int
1534 +pre_sy(DECL_ARGS)
1535 +{
1536 +
1537 + font_push('B');
1538 + return(1);
1539 +}
1540 +
1541 +static int
1542 +pre_vt(DECL_ARGS)
1543 +{
1544 +
1545 + if (MDOC_SYNPRETTY & n->flags) {
1546 + switch (n->type) {
1547 + case (MDOC_BLOCK):
1548 + pre_syn(n);
1549 + return(1);
1550 + case (MDOC_BODY):
1551 + break;
1552 + default:
1553 + return(0);
1554 + }
1555 + }
1556 + font_push('I');
1557 + return(1);
1558 +}
1559 +
1560 +static void
1561 +post_vt(DECL_ARGS)
1562 +{
1563 +
1564 + if (MDOC_SYNPRETTY & n->flags && MDOC_BODY != n->type)
1565 + return;
1566 + font_pop();
1567 +}
1568 +
1569 +static int
609 1570 pre_xr(DECL_ARGS)
610 1571 {
611 1572
612 1573 n = n->child;
613 1574 if (NULL == n)
614 1575 return(0);
615 - print_node(m, n, mm);
1576 + print_node(meta, n);
616 1577 n = n->next;
617 1578 if (NULL == n)
618 1579 return(0);
619 - mm->need_space = 0;
620 - print_word(mm, "(");
621 - print_node(m, n, mm);
622 - print_word(mm, ")");
1580 + outflags &= ~MMAN_spc;
1581 + print_word("(");
1582 + print_node(meta, n);
1583 + print_word(")");
623 1584 return(0);
624 1585 }
625 1586
626 1587 static int
627 1588 pre_ux(DECL_ARGS)
628 1589 {
629 1590
630 - print_word(mm, manacts[n->tok].prefix);
1591 + print_word(manacts[n->tok].prefix);
631 1592 if (NULL == n->child)
632 1593 return(0);
633 - mm->need_space = 0;
634 - print_word(mm, "\\~");
635 - mm->need_space = 0;
1594 + outflags &= ~MMAN_spc;
1595 + print_word("\\ ");
1596 + outflags &= ~MMAN_spc;
636 1597 return(1);
637 1598 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX