mandoc 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/COPYING +674 -0
  4. data/README.md +117 -0
  5. data/ext/mandoc/extconf.rb +59 -0
  6. data/ext/mandoc/rb_mandoc.c +548 -0
  7. data/ext/mandoc/rb_mandoc.h +22 -0
  8. data/lib/mandoc/version.rb +19 -0
  9. data/lib/mandoc.rb +26 -0
  10. data/mandoc-1.14.6/LICENSE +55 -0
  11. data/mandoc-1.14.6/arch.c +54 -0
  12. data/mandoc-1.14.6/att.c +49 -0
  13. data/mandoc-1.14.6/catman.c +260 -0
  14. data/mandoc-1.14.6/cgi.c +1279 -0
  15. data/mandoc-1.14.6/chars.c +507 -0
  16. data/mandoc-1.14.6/compat_err.c +103 -0
  17. data/mandoc-1.14.6/compat_fts.c +696 -0
  18. data/mandoc-1.14.6/compat_fts.h +106 -0
  19. data/mandoc-1.14.6/compat_getline.c +59 -0
  20. data/mandoc-1.14.6/compat_getsubopt.c +87 -0
  21. data/mandoc-1.14.6/compat_isblank.c +23 -0
  22. data/mandoc-1.14.6/compat_mkdtemp.c +50 -0
  23. data/mandoc-1.14.6/compat_mkstemps.c +63 -0
  24. data/mandoc-1.14.6/compat_ohash.c +330 -0
  25. data/mandoc-1.14.6/compat_ohash.h +72 -0
  26. data/mandoc-1.14.6/compat_progname.c +31 -0
  27. data/mandoc-1.14.6/compat_reallocarray.c +40 -0
  28. data/mandoc-1.14.6/compat_recallocarray.c +99 -0
  29. data/mandoc-1.14.6/compat_strcasestr.c +64 -0
  30. data/mandoc-1.14.6/compat_stringlist.c +135 -0
  31. data/mandoc-1.14.6/compat_stringlist.h +48 -0
  32. data/mandoc-1.14.6/compat_strlcat.c +57 -0
  33. data/mandoc-1.14.6/compat_strlcpy.c +52 -0
  34. data/mandoc-1.14.6/compat_strndup.c +42 -0
  35. data/mandoc-1.14.6/compat_strsep.c +70 -0
  36. data/mandoc-1.14.6/compat_strtonum.c +67 -0
  37. data/mandoc-1.14.6/compat_vasprintf.c +47 -0
  38. data/mandoc-1.14.6/config.h +52 -0
  39. data/mandoc-1.14.6/dba.c +508 -0
  40. data/mandoc-1.14.6/dba.h +50 -0
  41. data/mandoc-1.14.6/dba_array.c +190 -0
  42. data/mandoc-1.14.6/dba_array.h +47 -0
  43. data/mandoc-1.14.6/dba_read.c +74 -0
  44. data/mandoc-1.14.6/dba_write.c +127 -0
  45. data/mandoc-1.14.6/dba_write.h +30 -0
  46. data/mandoc-1.14.6/dbm.c +480 -0
  47. data/mandoc-1.14.6/dbm.h +68 -0
  48. data/mandoc-1.14.6/dbm_map.c +194 -0
  49. data/mandoc-1.14.6/dbm_map.h +29 -0
  50. data/mandoc-1.14.6/demandoc.c +260 -0
  51. data/mandoc-1.14.6/eqn.c +1132 -0
  52. data/mandoc-1.14.6/eqn.h +72 -0
  53. data/mandoc-1.14.6/eqn_html.c +246 -0
  54. data/mandoc-1.14.6/eqn_parse.h +48 -0
  55. data/mandoc-1.14.6/eqn_term.c +174 -0
  56. data/mandoc-1.14.6/html.c +1102 -0
  57. data/mandoc-1.14.6/html.h +142 -0
  58. data/mandoc-1.14.6/lib.c +35 -0
  59. data/mandoc-1.14.6/libman.h +42 -0
  60. data/mandoc-1.14.6/libmandoc.h +85 -0
  61. data/mandoc-1.14.6/libmdoc.h +87 -0
  62. data/mandoc-1.14.6/main.c +1375 -0
  63. data/mandoc-1.14.6/main.h +53 -0
  64. data/mandoc-1.14.6/man.c +345 -0
  65. data/mandoc-1.14.6/man.h +21 -0
  66. data/mandoc-1.14.6/man_html.c +640 -0
  67. data/mandoc-1.14.6/man_macro.c +470 -0
  68. data/mandoc-1.14.6/man_term.c +1143 -0
  69. data/mandoc-1.14.6/man_validate.c +660 -0
  70. data/mandoc-1.14.6/manconf.h +58 -0
  71. data/mandoc-1.14.6/mandoc.c +669 -0
  72. data/mandoc-1.14.6/mandoc.h +329 -0
  73. data/mandoc-1.14.6/mandoc_aux.c +118 -0
  74. data/mandoc-1.14.6/mandoc_aux.h +27 -0
  75. data/mandoc-1.14.6/mandoc_msg.c +375 -0
  76. data/mandoc-1.14.6/mandoc_ohash.c +65 -0
  77. data/mandoc-1.14.6/mandoc_ohash.h +23 -0
  78. data/mandoc-1.14.6/mandoc_parse.h +44 -0
  79. data/mandoc-1.14.6/mandoc_xr.c +123 -0
  80. data/mandoc-1.14.6/mandoc_xr.h +31 -0
  81. data/mandoc-1.14.6/mandocd.c +282 -0
  82. data/mandoc-1.14.6/mandocdb.c +2448 -0
  83. data/mandoc-1.14.6/manpath.c +363 -0
  84. data/mandoc-1.14.6/mansearch.c +851 -0
  85. data/mandoc-1.14.6/mansearch.h +118 -0
  86. data/mandoc-1.14.6/mdoc.c +433 -0
  87. data/mandoc-1.14.6/mdoc.h +158 -0
  88. data/mandoc-1.14.6/mdoc_argv.c +682 -0
  89. data/mandoc-1.14.6/mdoc_html.c +1762 -0
  90. data/mandoc-1.14.6/mdoc_macro.c +1600 -0
  91. data/mandoc-1.14.6/mdoc_man.c +1850 -0
  92. data/mandoc-1.14.6/mdoc_markdown.c +1610 -0
  93. data/mandoc-1.14.6/mdoc_state.c +256 -0
  94. data/mandoc-1.14.6/mdoc_term.c +1964 -0
  95. data/mandoc-1.14.6/mdoc_validate.c +3062 -0
  96. data/mandoc-1.14.6/msec.c +37 -0
  97. data/mandoc-1.14.6/out.c +544 -0
  98. data/mandoc-1.14.6/out.h +70 -0
  99. data/mandoc-1.14.6/preconv.c +179 -0
  100. data/mandoc-1.14.6/read.c +732 -0
  101. data/mandoc-1.14.6/roff.c +4390 -0
  102. data/mandoc-1.14.6/roff.h +561 -0
  103. data/mandoc-1.14.6/roff_html.c +119 -0
  104. data/mandoc-1.14.6/roff_int.h +94 -0
  105. data/mandoc-1.14.6/roff_term.c +266 -0
  106. data/mandoc-1.14.6/roff_validate.c +151 -0
  107. data/mandoc-1.14.6/soelim.c +182 -0
  108. data/mandoc-1.14.6/st.c +82 -0
  109. data/mandoc-1.14.6/tag.c +327 -0
  110. data/mandoc-1.14.6/tag.h +35 -0
  111. data/mandoc-1.14.6/tbl.c +183 -0
  112. data/mandoc-1.14.6/tbl.h +121 -0
  113. data/mandoc-1.14.6/tbl_data.c +323 -0
  114. data/mandoc-1.14.6/tbl_html.c +293 -0
  115. data/mandoc-1.14.6/tbl_int.h +47 -0
  116. data/mandoc-1.14.6/tbl_layout.c +376 -0
  117. data/mandoc-1.14.6/tbl_opts.c +173 -0
  118. data/mandoc-1.14.6/tbl_parse.h +30 -0
  119. data/mandoc-1.14.6/tbl_term.c +948 -0
  120. data/mandoc-1.14.6/term.c +1113 -0
  121. data/mandoc-1.14.6/term.h +158 -0
  122. data/mandoc-1.14.6/term_ascii.c +424 -0
  123. data/mandoc-1.14.6/term_ps.c +1362 -0
  124. data/mandoc-1.14.6/term_tab.c +130 -0
  125. data/mandoc-1.14.6/term_tag.c +227 -0
  126. data/mandoc-1.14.6/term_tag.h +34 -0
  127. data/mandoc-1.14.6/tree.c +536 -0
  128. metadata +170 -0
@@ -0,0 +1,1850 @@
1
+ /* $Id: mdoc_man.c,v 1.137 2021/07/04 15:38:26 schwarze Exp $ */
2
+ /*
3
+ * Copyright (c) 2011-2021 Ingo Schwarze <schwarze@openbsd.org>
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 "config.h"
18
+
19
+ #include <sys/types.h>
20
+
21
+ #include <assert.h>
22
+ #include <stdio.h>
23
+ #include <stdlib.h>
24
+ #include <string.h>
25
+
26
+ #include "mandoc_aux.h"
27
+ #include "mandoc.h"
28
+ #include "roff.h"
29
+ #include "mdoc.h"
30
+ #include "man.h"
31
+ #include "out.h"
32
+ #include "main.h"
33
+
34
+ #define DECL_ARGS const struct roff_meta *meta, struct roff_node *n
35
+
36
+ typedef int (*int_fp)(DECL_ARGS);
37
+ typedef void (*void_fp)(DECL_ARGS);
38
+
39
+ struct mdoc_man_act {
40
+ int_fp cond; /* DON'T run actions */
41
+ int_fp pre; /* pre-node action */
42
+ void_fp post; /* post-node action */
43
+ const char *prefix; /* pre-node string constant */
44
+ const char *suffix; /* post-node string constant */
45
+ };
46
+
47
+ static int cond_body(DECL_ARGS);
48
+ static int cond_head(DECL_ARGS);
49
+ static void font_push(char);
50
+ static void font_pop(void);
51
+ static int man_strlen(const char *);
52
+ static void mid_it(void);
53
+ static void post__t(DECL_ARGS);
54
+ static void post_aq(DECL_ARGS);
55
+ static void post_bd(DECL_ARGS);
56
+ static void post_bf(DECL_ARGS);
57
+ static void post_bk(DECL_ARGS);
58
+ static void post_bl(DECL_ARGS);
59
+ static void post_dl(DECL_ARGS);
60
+ static void post_en(DECL_ARGS);
61
+ static void post_enc(DECL_ARGS);
62
+ static void post_eo(DECL_ARGS);
63
+ static void post_fa(DECL_ARGS);
64
+ static void post_fd(DECL_ARGS);
65
+ static void post_fl(DECL_ARGS);
66
+ static void post_fn(DECL_ARGS);
67
+ static void post_fo(DECL_ARGS);
68
+ static void post_font(DECL_ARGS);
69
+ static void post_in(DECL_ARGS);
70
+ static void post_it(DECL_ARGS);
71
+ static void post_lb(DECL_ARGS);
72
+ static void post_nm(DECL_ARGS);
73
+ static void post_percent(DECL_ARGS);
74
+ static void post_pf(DECL_ARGS);
75
+ static void post_sect(DECL_ARGS);
76
+ static void post_vt(DECL_ARGS);
77
+ static int pre__t(DECL_ARGS);
78
+ static int pre_abort(DECL_ARGS);
79
+ static int pre_an(DECL_ARGS);
80
+ static int pre_ap(DECL_ARGS);
81
+ static int pre_aq(DECL_ARGS);
82
+ static int pre_bd(DECL_ARGS);
83
+ static int pre_bf(DECL_ARGS);
84
+ static int pre_bk(DECL_ARGS);
85
+ static int pre_bl(DECL_ARGS);
86
+ static void pre_br(DECL_ARGS);
87
+ static int pre_dl(DECL_ARGS);
88
+ static int pre_en(DECL_ARGS);
89
+ static int pre_enc(DECL_ARGS);
90
+ static int pre_em(DECL_ARGS);
91
+ static int pre_skip(DECL_ARGS);
92
+ static int pre_eo(DECL_ARGS);
93
+ static int pre_ex(DECL_ARGS);
94
+ static int pre_fa(DECL_ARGS);
95
+ static int pre_fd(DECL_ARGS);
96
+ static int pre_fl(DECL_ARGS);
97
+ static int pre_fn(DECL_ARGS);
98
+ static int pre_fo(DECL_ARGS);
99
+ static void pre_ft(DECL_ARGS);
100
+ static int pre_Ft(DECL_ARGS);
101
+ static int pre_in(DECL_ARGS);
102
+ static int pre_it(DECL_ARGS);
103
+ static int pre_lk(DECL_ARGS);
104
+ static int pre_li(DECL_ARGS);
105
+ static int pre_nm(DECL_ARGS);
106
+ static int pre_no(DECL_ARGS);
107
+ static void pre_noarg(DECL_ARGS);
108
+ static int pre_ns(DECL_ARGS);
109
+ static void pre_onearg(DECL_ARGS);
110
+ static int pre_pp(DECL_ARGS);
111
+ static int pre_rs(DECL_ARGS);
112
+ static int pre_sm(DECL_ARGS);
113
+ static void pre_sp(DECL_ARGS);
114
+ static int pre_sect(DECL_ARGS);
115
+ static int pre_sy(DECL_ARGS);
116
+ static void pre_syn(struct roff_node *);
117
+ static void pre_ta(DECL_ARGS);
118
+ static int pre_vt(DECL_ARGS);
119
+ static int pre_xr(DECL_ARGS);
120
+ static void print_word(const char *);
121
+ static void print_line(const char *, int);
122
+ static void print_block(const char *, int);
123
+ static void print_offs(const char *, int);
124
+ static void print_width(const struct mdoc_bl *,
125
+ const struct roff_node *);
126
+ static void print_count(int *);
127
+ static void print_node(DECL_ARGS);
128
+
129
+ static const void_fp roff_man_acts[ROFF_MAX] = {
130
+ pre_br, /* br */
131
+ pre_onearg, /* ce */
132
+ pre_noarg, /* fi */
133
+ pre_ft, /* ft */
134
+ pre_onearg, /* ll */
135
+ pre_onearg, /* mc */
136
+ pre_noarg, /* nf */
137
+ pre_onearg, /* po */
138
+ pre_onearg, /* rj */
139
+ pre_sp, /* sp */
140
+ pre_ta, /* ta */
141
+ pre_onearg, /* ti */
142
+ };
143
+
144
+ static const struct mdoc_man_act mdoc_man_acts[MDOC_MAX - MDOC_Dd] = {
145
+ { NULL, NULL, NULL, NULL, NULL }, /* Dd */
146
+ { NULL, NULL, NULL, NULL, NULL }, /* Dt */
147
+ { NULL, NULL, NULL, NULL, NULL }, /* Os */
148
+ { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
149
+ { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
150
+ { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
151
+ { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
152
+ { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
153
+ { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
154
+ { NULL, NULL, NULL, NULL, NULL }, /* Ed */
155
+ { cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */
156
+ { NULL, NULL, NULL, NULL, NULL }, /* El */
157
+ { NULL, pre_it, post_it, NULL, NULL }, /* It */
158
+ { NULL, pre_em, post_font, NULL, NULL }, /* Ad */
159
+ { NULL, pre_an, NULL, NULL, NULL }, /* An */
160
+ { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
161
+ { NULL, pre_em, post_font, NULL, NULL }, /* Ar */
162
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
163
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
164
+ { NULL, pre_li, post_font, NULL, NULL }, /* Dv */
165
+ { NULL, pre_li, post_font, NULL, NULL }, /* Er */
166
+ { NULL, pre_li, post_font, NULL, NULL }, /* Ev */
167
+ { NULL, pre_ex, NULL, NULL, NULL }, /* Ex */
168
+ { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
169
+ { NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */
170
+ { NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */
171
+ { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
172
+ { NULL, pre_Ft, post_font, NULL, NULL }, /* Ft */
173
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Ic */
174
+ { NULL, pre_in, post_in, NULL, NULL }, /* In */
175
+ { NULL, pre_li, post_font, NULL, NULL }, /* Li */
176
+ { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
177
+ { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
178
+ { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
179
+ { NULL, pre_abort, NULL, NULL, NULL }, /* Ot */
180
+ { NULL, pre_em, post_font, NULL, NULL }, /* Pa */
181
+ { NULL, pre_ex, NULL, NULL, NULL }, /* Rv */
182
+ { NULL, NULL, NULL, NULL, NULL }, /* St */
183
+ { NULL, pre_em, post_font, NULL, NULL }, /* Va */
184
+ { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
185
+ { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
186
+ { NULL, NULL, post_percent, NULL, NULL }, /* %A */
187
+ { NULL, pre_em, post_percent, NULL, NULL }, /* %B */
188
+ { NULL, NULL, post_percent, NULL, NULL }, /* %D */
189
+ { NULL, pre_em, post_percent, NULL, NULL }, /* %I */
190
+ { NULL, pre_em, post_percent, NULL, NULL }, /* %J */
191
+ { NULL, NULL, post_percent, NULL, NULL }, /* %N */
192
+ { NULL, NULL, post_percent, NULL, NULL }, /* %O */
193
+ { NULL, NULL, post_percent, NULL, NULL }, /* %P */
194
+ { NULL, NULL, post_percent, NULL, NULL }, /* %R */
195
+ { NULL, pre__t, post__t, NULL, NULL }, /* %T */
196
+ { NULL, NULL, post_percent, NULL, NULL }, /* %V */
197
+ { NULL, NULL, NULL, NULL, NULL }, /* Ac */
198
+ { cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */
199
+ { cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */
200
+ { NULL, NULL, NULL, NULL, NULL }, /* At */
201
+ { NULL, NULL, NULL, NULL, NULL }, /* Bc */
202
+ { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
203
+ { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
204
+ { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
205
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Bsx */
206
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Bx */
207
+ { NULL, pre_skip, NULL, NULL, NULL }, /* Db */
208
+ { NULL, NULL, NULL, NULL, NULL }, /* Dc */
209
+ { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
210
+ { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
211
+ { NULL, NULL, NULL, NULL, NULL }, /* Ec */
212
+ { NULL, NULL, NULL, NULL, NULL }, /* Ef */
213
+ { NULL, pre_em, post_font, NULL, NULL }, /* Em */
214
+ { cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */
215
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Fx */
216
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
217
+ { NULL, pre_no, NULL, NULL, NULL }, /* No */
218
+ { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
219
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Nx */
220
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Ox */
221
+ { NULL, NULL, NULL, NULL, NULL }, /* Pc */
222
+ { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
223
+ { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
224
+ { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
225
+ { NULL, NULL, NULL, NULL, NULL }, /* Qc */
226
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
227
+ { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
228
+ { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
229
+ { NULL, NULL, NULL, NULL, NULL }, /* Re */
230
+ { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
231
+ { NULL, NULL, NULL, NULL, NULL }, /* Sc */
232
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */
233
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */
234
+ { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
235
+ { NULL, pre_em, post_font, NULL, NULL }, /* Sx */
236
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
237
+ { NULL, pre_li, post_font, NULL, NULL }, /* Tn */
238
+ { NULL, NULL, NULL, NULL, NULL }, /* Ux */
239
+ { NULL, NULL, NULL, NULL, NULL }, /* Xc */
240
+ { NULL, NULL, NULL, NULL, NULL }, /* Xo */
241
+ { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
242
+ { NULL, NULL, NULL, NULL, NULL }, /* Fc */
243
+ { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
244
+ { NULL, NULL, NULL, NULL, NULL }, /* Oc */
245
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
246
+ { NULL, NULL, NULL, NULL, NULL }, /* Ek */
247
+ { NULL, NULL, NULL, NULL, NULL }, /* Bt */
248
+ { NULL, NULL, NULL, NULL, NULL }, /* Hf */
249
+ { NULL, pre_em, post_font, NULL, NULL }, /* Fr */
250
+ { NULL, NULL, NULL, NULL, NULL }, /* Ud */
251
+ { NULL, NULL, post_lb, NULL, NULL }, /* Lb */
252
+ { NULL, pre_abort, NULL, NULL, NULL }, /* Lp */
253
+ { NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
254
+ { NULL, pre_em, post_font, NULL, NULL }, /* Mt */
255
+ { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
256
+ { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
257
+ { NULL, NULL, NULL, NULL, NULL }, /* Brc */
258
+ { NULL, NULL, post_percent, NULL, NULL }, /* %C */
259
+ { NULL, pre_skip, NULL, NULL, NULL }, /* Es */
260
+ { cond_body, pre_en, post_en, NULL, NULL }, /* En */
261
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Dx */
262
+ { NULL, NULL, post_percent, NULL, NULL }, /* %Q */
263
+ { NULL, NULL, post_percent, NULL, NULL }, /* %U */
264
+ { NULL, NULL, NULL, NULL, NULL }, /* Ta */
265
+ { NULL, pre_skip, NULL, NULL, NULL }, /* Tg */
266
+ };
267
+ static const struct mdoc_man_act *mdoc_man_act(enum roff_tok);
268
+
269
+ static int outflags;
270
+ #define MMAN_spc (1 << 0) /* blank character before next word */
271
+ #define MMAN_spc_force (1 << 1) /* even before trailing punctuation */
272
+ #define MMAN_nl (1 << 2) /* break man(7) code line */
273
+ #define MMAN_br (1 << 3) /* break output line */
274
+ #define MMAN_sp (1 << 4) /* insert a blank output line */
275
+ #define MMAN_PP (1 << 5) /* reset indentation etc. */
276
+ #define MMAN_Sm (1 << 6) /* horizontal spacing mode */
277
+ #define MMAN_Bk (1 << 7) /* word keep mode */
278
+ #define MMAN_Bk_susp (1 << 8) /* suspend this (after a macro) */
279
+ #define MMAN_An_split (1 << 9) /* author mode is "split" */
280
+ #define MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */
281
+ #define MMAN_PD (1 << 11) /* inter-paragraph spacing disabled */
282
+ #define MMAN_nbrword (1 << 12) /* do not break the next word */
283
+
284
+ #define BL_STACK_MAX 32
285
+
286
+ static int Bl_stack[BL_STACK_MAX]; /* offsets [chars] */
287
+ static int Bl_stack_post[BL_STACK_MAX]; /* add final .RE */
288
+ static int Bl_stack_len; /* number of nested Bl blocks */
289
+ static int TPremain; /* characters before tag is full */
290
+
291
+ static struct {
292
+ char *head;
293
+ char *tail;
294
+ size_t size;
295
+ } fontqueue;
296
+
297
+
298
+ static const struct mdoc_man_act *
299
+ mdoc_man_act(enum roff_tok tok)
300
+ {
301
+ assert(tok >= MDOC_Dd && tok <= MDOC_MAX);
302
+ return mdoc_man_acts + (tok - MDOC_Dd);
303
+ }
304
+
305
+ static int
306
+ man_strlen(const char *cp)
307
+ {
308
+ size_t rsz;
309
+ int skip, sz;
310
+
311
+ sz = 0;
312
+ skip = 0;
313
+ for (;;) {
314
+ rsz = strcspn(cp, "\\");
315
+ if (rsz) {
316
+ cp += rsz;
317
+ if (skip) {
318
+ skip = 0;
319
+ rsz--;
320
+ }
321
+ sz += rsz;
322
+ }
323
+ if ('\0' == *cp)
324
+ break;
325
+ cp++;
326
+ switch (mandoc_escape(&cp, NULL, NULL)) {
327
+ case ESCAPE_ERROR:
328
+ return sz;
329
+ case ESCAPE_UNICODE:
330
+ case ESCAPE_NUMBERED:
331
+ case ESCAPE_SPECIAL:
332
+ case ESCAPE_UNDEF:
333
+ case ESCAPE_OVERSTRIKE:
334
+ if (skip)
335
+ skip = 0;
336
+ else
337
+ sz++;
338
+ break;
339
+ case ESCAPE_SKIPCHAR:
340
+ skip = 1;
341
+ break;
342
+ default:
343
+ break;
344
+ }
345
+ }
346
+ return sz;
347
+ }
348
+
349
+ static void
350
+ font_push(char newfont)
351
+ {
352
+
353
+ if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) {
354
+ fontqueue.size += 8;
355
+ fontqueue.head = mandoc_realloc(fontqueue.head,
356
+ fontqueue.size);
357
+ }
358
+ *fontqueue.tail = newfont;
359
+ print_word("");
360
+ printf("\\f");
361
+ putchar(newfont);
362
+ outflags &= ~MMAN_spc;
363
+ }
364
+
365
+ static void
366
+ font_pop(void)
367
+ {
368
+
369
+ if (fontqueue.tail > fontqueue.head)
370
+ fontqueue.tail--;
371
+ outflags &= ~MMAN_spc;
372
+ print_word("");
373
+ printf("\\f");
374
+ putchar(*fontqueue.tail);
375
+ }
376
+
377
+ static void
378
+ print_word(const char *s)
379
+ {
380
+
381
+ if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
382
+ /*
383
+ * If we need a newline, print it now and start afresh.
384
+ */
385
+ if (MMAN_PP & outflags) {
386
+ if (MMAN_sp & outflags) {
387
+ if (MMAN_PD & outflags) {
388
+ printf("\n.PD");
389
+ outflags &= ~MMAN_PD;
390
+ }
391
+ } else if ( ! (MMAN_PD & outflags)) {
392
+ printf("\n.PD 0");
393
+ outflags |= MMAN_PD;
394
+ }
395
+ printf("\n.PP\n");
396
+ } else if (MMAN_sp & outflags)
397
+ printf("\n.sp\n");
398
+ else if (MMAN_br & outflags)
399
+ printf("\n.br\n");
400
+ else if (MMAN_nl & outflags)
401
+ putchar('\n');
402
+ outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
403
+ if (1 == TPremain)
404
+ printf(".br\n");
405
+ TPremain = 0;
406
+ } else if (MMAN_spc & outflags) {
407
+ /*
408
+ * If we need a space, only print it if
409
+ * (1) it is forced by `No' or
410
+ * (2) what follows is not terminating punctuation or
411
+ * (3) what follows is longer than one character.
412
+ */
413
+ if (MMAN_spc_force & outflags || '\0' == s[0] ||
414
+ NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
415
+ if (MMAN_Bk & outflags &&
416
+ ! (MMAN_Bk_susp & outflags))
417
+ putchar('\\');
418
+ putchar(' ');
419
+ if (TPremain)
420
+ TPremain--;
421
+ }
422
+ }
423
+
424
+ /*
425
+ * Reassign needing space if we're not following opening
426
+ * punctuation.
427
+ */
428
+ if (MMAN_Sm & outflags && ('\0' == s[0] ||
429
+ (('(' != s[0] && '[' != s[0]) || '\0' != s[1])))
430
+ outflags |= MMAN_spc;
431
+ else
432
+ outflags &= ~MMAN_spc;
433
+ outflags &= ~(MMAN_spc_force | MMAN_Bk_susp);
434
+
435
+ for ( ; *s; s++) {
436
+ switch (*s) {
437
+ case ASCII_NBRSP:
438
+ printf("\\ ");
439
+ break;
440
+ case ASCII_HYPH:
441
+ putchar('-');
442
+ break;
443
+ case ASCII_BREAK:
444
+ printf("\\:");
445
+ break;
446
+ case ' ':
447
+ if (MMAN_nbrword & outflags) {
448
+ printf("\\ ");
449
+ break;
450
+ }
451
+ /* FALLTHROUGH */
452
+ default:
453
+ putchar((unsigned char)*s);
454
+ break;
455
+ }
456
+ if (TPremain)
457
+ TPremain--;
458
+ }
459
+ outflags &= ~MMAN_nbrword;
460
+ }
461
+
462
+ static void
463
+ print_line(const char *s, int newflags)
464
+ {
465
+
466
+ outflags |= MMAN_nl;
467
+ print_word(s);
468
+ outflags |= newflags;
469
+ }
470
+
471
+ static void
472
+ print_block(const char *s, int newflags)
473
+ {
474
+
475
+ outflags &= ~MMAN_PP;
476
+ if (MMAN_sp & outflags) {
477
+ outflags &= ~(MMAN_sp | MMAN_br);
478
+ if (MMAN_PD & outflags) {
479
+ print_line(".PD", 0);
480
+ outflags &= ~MMAN_PD;
481
+ }
482
+ } else if (! (MMAN_PD & outflags))
483
+ print_line(".PD 0", MMAN_PD);
484
+ outflags |= MMAN_nl;
485
+ print_word(s);
486
+ outflags |= MMAN_Bk_susp | newflags;
487
+ }
488
+
489
+ static void
490
+ print_offs(const char *v, int keywords)
491
+ {
492
+ char buf[24];
493
+ struct roffsu su;
494
+ const char *end;
495
+ int sz;
496
+
497
+ print_line(".RS", MMAN_Bk_susp);
498
+
499
+ /* Convert v into a number (of characters). */
500
+ if (NULL == v || '\0' == *v || (keywords && !strcmp(v, "left")))
501
+ sz = 0;
502
+ else if (keywords && !strcmp(v, "indent"))
503
+ sz = 6;
504
+ else if (keywords && !strcmp(v, "indent-two"))
505
+ sz = 12;
506
+ else {
507
+ end = a2roffsu(v, &su, SCALE_EN);
508
+ if (end == NULL || *end != '\0')
509
+ sz = man_strlen(v);
510
+ else if (SCALE_EN == su.unit)
511
+ sz = su.scale;
512
+ else {
513
+ /*
514
+ * XXX
515
+ * If we are inside an enclosing list,
516
+ * there is no easy way to add the two
517
+ * indentations because they are provided
518
+ * in terms of different units.
519
+ */
520
+ print_word(v);
521
+ outflags |= MMAN_nl;
522
+ return;
523
+ }
524
+ }
525
+
526
+ /*
527
+ * We are inside an enclosing list.
528
+ * Add the two indentations.
529
+ */
530
+ if (Bl_stack_len)
531
+ sz += Bl_stack[Bl_stack_len - 1];
532
+
533
+ (void)snprintf(buf, sizeof(buf), "%dn", sz);
534
+ print_word(buf);
535
+ outflags |= MMAN_nl;
536
+ }
537
+
538
+ /*
539
+ * Set up the indentation for a list item; used from pre_it().
540
+ */
541
+ static void
542
+ print_width(const struct mdoc_bl *bl, const struct roff_node *child)
543
+ {
544
+ char buf[24];
545
+ struct roffsu su;
546
+ const char *end;
547
+ int numeric, remain, sz, chsz;
548
+
549
+ numeric = 1;
550
+ remain = 0;
551
+
552
+ /* Convert the width into a number (of characters). */
553
+ if (bl->width == NULL)
554
+ sz = (bl->type == LIST_hang) ? 6 : 0;
555
+ else {
556
+ end = a2roffsu(bl->width, &su, SCALE_MAX);
557
+ if (end == NULL || *end != '\0')
558
+ sz = man_strlen(bl->width);
559
+ else if (SCALE_EN == su.unit)
560
+ sz = su.scale;
561
+ else {
562
+ sz = 0;
563
+ numeric = 0;
564
+ }
565
+ }
566
+
567
+ /* XXX Rough estimation, might have multiple parts. */
568
+ if (bl->type == LIST_enum)
569
+ chsz = (bl->count > 8) + 1;
570
+ else if (child != NULL && child->type == ROFFT_TEXT)
571
+ chsz = man_strlen(child->string);
572
+ else
573
+ chsz = 0;
574
+
575
+ /* Maybe we are inside an enclosing list? */
576
+ mid_it();
577
+
578
+ /*
579
+ * Save our own indentation,
580
+ * such that child lists can use it.
581
+ */
582
+ Bl_stack[Bl_stack_len++] = sz + 2;
583
+
584
+ /* Set up the current list. */
585
+ if (chsz > sz && bl->type != LIST_tag)
586
+ print_block(".HP", MMAN_spc);
587
+ else {
588
+ print_block(".TP", MMAN_spc);
589
+ remain = sz + 2;
590
+ }
591
+ if (numeric) {
592
+ (void)snprintf(buf, sizeof(buf), "%dn", sz + 2);
593
+ print_word(buf);
594
+ } else
595
+ print_word(bl->width);
596
+ TPremain = remain;
597
+ }
598
+
599
+ static void
600
+ print_count(int *count)
601
+ {
602
+ char buf[24];
603
+
604
+ (void)snprintf(buf, sizeof(buf), "%d.\\&", ++*count);
605
+ print_word(buf);
606
+ }
607
+
608
+ void
609
+ man_mdoc(void *arg, const struct roff_meta *mdoc)
610
+ {
611
+ struct roff_node *n;
612
+
613
+ printf(".\\\" Automatically generated from an mdoc input file."
614
+ " Do not edit.\n");
615
+ for (n = mdoc->first->child; n != NULL; n = n->next) {
616
+ if (n->type != ROFFT_COMMENT)
617
+ break;
618
+ printf(".\\\"%s\n", n->string);
619
+ }
620
+
621
+ printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
622
+ mdoc->title, (mdoc->msec == NULL ? "" : mdoc->msec),
623
+ mdoc->date, mdoc->os, mdoc->vol);
624
+
625
+ /* Disable hyphenation and if nroff, disable justification. */
626
+ printf(".nh\n.if n .ad l");
627
+
628
+ outflags = MMAN_nl | MMAN_Sm;
629
+ if (0 == fontqueue.size) {
630
+ fontqueue.size = 8;
631
+ fontqueue.head = fontqueue.tail = mandoc_malloc(8);
632
+ *fontqueue.tail = 'R';
633
+ }
634
+ for (; n != NULL; n = n->next)
635
+ print_node(mdoc, n);
636
+ putchar('\n');
637
+ }
638
+
639
+ static void
640
+ print_node(DECL_ARGS)
641
+ {
642
+ const struct mdoc_man_act *act;
643
+ struct roff_node *sub;
644
+ int cond, do_sub;
645
+
646
+ if (n->flags & NODE_NOPRT)
647
+ return;
648
+
649
+ /*
650
+ * Break the line if we were parsed subsequent the current node.
651
+ * This makes the page structure be more consistent.
652
+ */
653
+ if (outflags & MMAN_spc &&
654
+ n->flags & NODE_LINE &&
655
+ !roff_node_transparent(n))
656
+ outflags |= MMAN_nl;
657
+
658
+ act = NULL;
659
+ cond = 0;
660
+ do_sub = 1;
661
+ n->flags &= ~NODE_ENDED;
662
+
663
+ switch (n->type) {
664
+ case ROFFT_EQN:
665
+ case ROFFT_TBL:
666
+ mandoc_msg(n->type == ROFFT_EQN ? MANDOCERR_EQN_TMAN :
667
+ MANDOCERR_TBL_TMAN, n->line, n->pos, NULL);
668
+ outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
669
+ print_word("The");
670
+ print_line(".B \\-T man", MMAN_nl);
671
+ print_word("output mode does not support");
672
+ print_word(n->type == ROFFT_EQN ? "eqn(7)" : "tbl(7)");
673
+ print_word("input.");
674
+ outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
675
+ return;
676
+ case ROFFT_TEXT:
677
+ /*
678
+ * Make sure that we don't happen to start with a
679
+ * control character at the start of a line.
680
+ */
681
+ if (MMAN_nl & outflags &&
682
+ ('.' == *n->string || '\'' == *n->string)) {
683
+ print_word("");
684
+ printf("\\&");
685
+ outflags &= ~MMAN_spc;
686
+ }
687
+ if (n->flags & NODE_DELIMC)
688
+ outflags &= ~(MMAN_spc | MMAN_spc_force);
689
+ else if (outflags & MMAN_Sm)
690
+ outflags |= MMAN_spc_force;
691
+ print_word(n->string);
692
+ if (n->flags & NODE_DELIMO)
693
+ outflags &= ~(MMAN_spc | MMAN_spc_force);
694
+ else if (outflags & MMAN_Sm)
695
+ outflags |= MMAN_spc;
696
+ break;
697
+ default:
698
+ if (n->tok < ROFF_MAX) {
699
+ (*roff_man_acts[n->tok])(meta, n);
700
+ return;
701
+ }
702
+ act = mdoc_man_act(n->tok);
703
+ cond = act->cond == NULL || (*act->cond)(meta, n);
704
+ if (cond && act->pre != NULL &&
705
+ (n->end == ENDBODY_NOT || n->child != NULL))
706
+ do_sub = (*act->pre)(meta, n);
707
+ break;
708
+ }
709
+
710
+ /*
711
+ * Conditionally run all child nodes.
712
+ * Note that this iterates over children instead of using
713
+ * recursion. This prevents unnecessary depth in the stack.
714
+ */
715
+ if (do_sub)
716
+ for (sub = n->child; sub; sub = sub->next)
717
+ print_node(meta, sub);
718
+
719
+ /*
720
+ * Lastly, conditionally run the post-node handler.
721
+ */
722
+ if (NODE_ENDED & n->flags)
723
+ return;
724
+
725
+ if (cond && act->post)
726
+ (*act->post)(meta, n);
727
+
728
+ if (ENDBODY_NOT != n->end)
729
+ n->body->flags |= NODE_ENDED;
730
+ }
731
+
732
+ static int
733
+ cond_head(DECL_ARGS)
734
+ {
735
+
736
+ return n->type == ROFFT_HEAD;
737
+ }
738
+
739
+ static int
740
+ cond_body(DECL_ARGS)
741
+ {
742
+
743
+ return n->type == ROFFT_BODY;
744
+ }
745
+
746
+ static int
747
+ pre_abort(DECL_ARGS)
748
+ {
749
+ abort();
750
+ }
751
+
752
+ static int
753
+ pre_enc(DECL_ARGS)
754
+ {
755
+ const char *prefix;
756
+
757
+ prefix = mdoc_man_act(n->tok)->prefix;
758
+ if (NULL == prefix)
759
+ return 1;
760
+ print_word(prefix);
761
+ outflags &= ~MMAN_spc;
762
+ return 1;
763
+ }
764
+
765
+ static void
766
+ post_enc(DECL_ARGS)
767
+ {
768
+ const char *suffix;
769
+
770
+ suffix = mdoc_man_act(n->tok)->suffix;
771
+ if (NULL == suffix)
772
+ return;
773
+ outflags &= ~(MMAN_spc | MMAN_nl);
774
+ print_word(suffix);
775
+ }
776
+
777
+ static int
778
+ pre_ex(DECL_ARGS)
779
+ {
780
+ outflags |= MMAN_br | MMAN_nl;
781
+ return 1;
782
+ }
783
+
784
+ static void
785
+ post_font(DECL_ARGS)
786
+ {
787
+
788
+ font_pop();
789
+ }
790
+
791
+ static void
792
+ post_percent(DECL_ARGS)
793
+ {
794
+ struct roff_node *np, *nn, *nnn;
795
+
796
+ if (mdoc_man_act(n->tok)->pre == pre_em)
797
+ font_pop();
798
+
799
+ if ((nn = roff_node_next(n)) != NULL) {
800
+ np = roff_node_prev(n);
801
+ nnn = nn == NULL ? NULL : roff_node_next(nn);
802
+ if (nn->tok != n->tok ||
803
+ (np != NULL && np->tok == n->tok) ||
804
+ (nnn != NULL && nnn->tok == n->tok))
805
+ print_word(",");
806
+ if (nn->tok == n->tok &&
807
+ (nnn == NULL || nnn->tok != n->tok))
808
+ print_word("and");
809
+ } else {
810
+ print_word(".");
811
+ outflags |= MMAN_nl;
812
+ }
813
+ }
814
+
815
+ static int
816
+ pre__t(DECL_ARGS)
817
+ {
818
+
819
+ if (n->parent->tok == MDOC_Rs && n->parent->norm->Rs.quote_T) {
820
+ print_word("\\(lq");
821
+ outflags &= ~MMAN_spc;
822
+ } else
823
+ font_push('I');
824
+ return 1;
825
+ }
826
+
827
+ static void
828
+ post__t(DECL_ARGS)
829
+ {
830
+
831
+ if (n->parent->tok == MDOC_Rs && n->parent->norm->Rs.quote_T) {
832
+ outflags &= ~MMAN_spc;
833
+ print_word("\\(rq");
834
+ } else
835
+ font_pop();
836
+ post_percent(meta, n);
837
+ }
838
+
839
+ /*
840
+ * Print before a section header.
841
+ */
842
+ static int
843
+ pre_sect(DECL_ARGS)
844
+ {
845
+
846
+ if (n->type == ROFFT_HEAD) {
847
+ outflags |= MMAN_sp;
848
+ print_block(mdoc_man_act(n->tok)->prefix, 0);
849
+ print_word("");
850
+ putchar('\"');
851
+ outflags &= ~MMAN_spc;
852
+ }
853
+ return 1;
854
+ }
855
+
856
+ /*
857
+ * Print subsequent a section header.
858
+ */
859
+ static void
860
+ post_sect(DECL_ARGS)
861
+ {
862
+
863
+ if (n->type != ROFFT_HEAD)
864
+ return;
865
+ outflags &= ~MMAN_spc;
866
+ print_word("");
867
+ putchar('\"');
868
+ outflags |= MMAN_nl;
869
+ if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec)
870
+ outflags &= ~(MMAN_An_split | MMAN_An_nosplit);
871
+ }
872
+
873
+ /* See mdoc_term.c, synopsis_pre() for comments. */
874
+ static void
875
+ pre_syn(struct roff_node *n)
876
+ {
877
+ struct roff_node *np;
878
+
879
+ if ((n->flags & NODE_SYNPRETTY) == 0 ||
880
+ (np = roff_node_prev(n)) == NULL)
881
+ return;
882
+
883
+ if (np->tok == n->tok &&
884
+ MDOC_Ft != n->tok &&
885
+ MDOC_Fo != n->tok &&
886
+ MDOC_Fn != n->tok) {
887
+ outflags |= MMAN_br;
888
+ return;
889
+ }
890
+
891
+ switch (np->tok) {
892
+ case MDOC_Fd:
893
+ case MDOC_Fn:
894
+ case MDOC_Fo:
895
+ case MDOC_In:
896
+ case MDOC_Vt:
897
+ outflags |= MMAN_sp;
898
+ break;
899
+ case MDOC_Ft:
900
+ if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
901
+ outflags |= MMAN_sp;
902
+ break;
903
+ }
904
+ /* FALLTHROUGH */
905
+ default:
906
+ outflags |= MMAN_br;
907
+ break;
908
+ }
909
+ }
910
+
911
+ static int
912
+ pre_an(DECL_ARGS)
913
+ {
914
+
915
+ switch (n->norm->An.auth) {
916
+ case AUTH_split:
917
+ outflags &= ~MMAN_An_nosplit;
918
+ outflags |= MMAN_An_split;
919
+ return 0;
920
+ case AUTH_nosplit:
921
+ outflags &= ~MMAN_An_split;
922
+ outflags |= MMAN_An_nosplit;
923
+ return 0;
924
+ default:
925
+ if (MMAN_An_split & outflags)
926
+ outflags |= MMAN_br;
927
+ else if (SEC_AUTHORS == n->sec &&
928
+ ! (MMAN_An_nosplit & outflags))
929
+ outflags |= MMAN_An_split;
930
+ return 1;
931
+ }
932
+ }
933
+
934
+ static int
935
+ pre_ap(DECL_ARGS)
936
+ {
937
+
938
+ outflags &= ~MMAN_spc;
939
+ print_word("'");
940
+ outflags &= ~MMAN_spc;
941
+ return 0;
942
+ }
943
+
944
+ static int
945
+ pre_aq(DECL_ARGS)
946
+ {
947
+
948
+ print_word(n->child != NULL && n->child->next == NULL &&
949
+ n->child->tok == MDOC_Mt ? "<" : "\\(la");
950
+ outflags &= ~MMAN_spc;
951
+ return 1;
952
+ }
953
+
954
+ static void
955
+ post_aq(DECL_ARGS)
956
+ {
957
+
958
+ outflags &= ~(MMAN_spc | MMAN_nl);
959
+ print_word(n->child != NULL && n->child->next == NULL &&
960
+ n->child->tok == MDOC_Mt ? ">" : "\\(ra");
961
+ }
962
+
963
+ static int
964
+ pre_bd(DECL_ARGS)
965
+ {
966
+ outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
967
+ if (n->norm->Bd.type == DISP_unfilled ||
968
+ n->norm->Bd.type == DISP_literal)
969
+ print_line(".nf", 0);
970
+ if (n->norm->Bd.comp == 0 && roff_node_prev(n->parent) != NULL)
971
+ outflags |= MMAN_sp;
972
+ print_offs(n->norm->Bd.offs, 1);
973
+ return 1;
974
+ }
975
+
976
+ static void
977
+ post_bd(DECL_ARGS)
978
+ {
979
+ enum roff_tok bef, now;
980
+
981
+ /* Close out this display. */
982
+ print_line(".RE", MMAN_nl);
983
+ bef = n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi;
984
+ if (n->last == NULL)
985
+ now = n->norm->Bd.type == DISP_unfilled ||
986
+ n->norm->Bd.type == DISP_literal ? ROFF_nf : ROFF_fi;
987
+ else if (n->last->tok == ROFF_nf)
988
+ now = ROFF_nf;
989
+ else if (n->last->tok == ROFF_fi)
990
+ now = ROFF_fi;
991
+ else
992
+ now = n->last->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi;
993
+ if (bef != now) {
994
+ outflags |= MMAN_nl;
995
+ print_word(".");
996
+ outflags &= ~MMAN_spc;
997
+ print_word(roff_name[bef]);
998
+ outflags |= MMAN_nl;
999
+ }
1000
+
1001
+ /* Maybe we are inside an enclosing list? */
1002
+ if (roff_node_next(n->parent) != NULL)
1003
+ mid_it();
1004
+ }
1005
+
1006
+ static int
1007
+ pre_bf(DECL_ARGS)
1008
+ {
1009
+
1010
+ switch (n->type) {
1011
+ case ROFFT_BLOCK:
1012
+ return 1;
1013
+ case ROFFT_BODY:
1014
+ break;
1015
+ default:
1016
+ return 0;
1017
+ }
1018
+ switch (n->norm->Bf.font) {
1019
+ case FONT_Em:
1020
+ font_push('I');
1021
+ break;
1022
+ case FONT_Sy:
1023
+ font_push('B');
1024
+ break;
1025
+ default:
1026
+ font_push('R');
1027
+ break;
1028
+ }
1029
+ return 1;
1030
+ }
1031
+
1032
+ static void
1033
+ post_bf(DECL_ARGS)
1034
+ {
1035
+
1036
+ if (n->type == ROFFT_BODY)
1037
+ font_pop();
1038
+ }
1039
+
1040
+ static int
1041
+ pre_bk(DECL_ARGS)
1042
+ {
1043
+ switch (n->type) {
1044
+ case ROFFT_BLOCK:
1045
+ return 1;
1046
+ case ROFFT_BODY:
1047
+ case ROFFT_ELEM:
1048
+ outflags |= MMAN_Bk;
1049
+ return 1;
1050
+ default:
1051
+ return 0;
1052
+ }
1053
+ }
1054
+
1055
+ static void
1056
+ post_bk(DECL_ARGS)
1057
+ {
1058
+ switch (n->type) {
1059
+ case ROFFT_ELEM:
1060
+ while ((n = n->parent) != NULL)
1061
+ if (n->tok == MDOC_Bk)
1062
+ return;
1063
+ /* FALLTHROUGH */
1064
+ case ROFFT_BODY:
1065
+ outflags &= ~MMAN_Bk;
1066
+ break;
1067
+ default:
1068
+ break;
1069
+ }
1070
+ }
1071
+
1072
+ static int
1073
+ pre_bl(DECL_ARGS)
1074
+ {
1075
+ size_t icol;
1076
+
1077
+ /*
1078
+ * print_offs() will increase the -offset to account for
1079
+ * a possible enclosing .It, but any enclosed .It blocks
1080
+ * just nest and do not add up their indentation.
1081
+ */
1082
+ if (n->norm->Bl.offs) {
1083
+ print_offs(n->norm->Bl.offs, 0);
1084
+ Bl_stack[Bl_stack_len++] = 0;
1085
+ }
1086
+
1087
+ switch (n->norm->Bl.type) {
1088
+ case LIST_enum:
1089
+ n->norm->Bl.count = 0;
1090
+ return 1;
1091
+ case LIST_column:
1092
+ break;
1093
+ default:
1094
+ return 1;
1095
+ }
1096
+
1097
+ if (n->child != NULL) {
1098
+ print_line(".TS", MMAN_nl);
1099
+ for (icol = 0; icol < n->norm->Bl.ncols; icol++)
1100
+ print_word("l");
1101
+ print_word(".");
1102
+ }
1103
+ outflags |= MMAN_nl;
1104
+ return 1;
1105
+ }
1106
+
1107
+ static void
1108
+ post_bl(DECL_ARGS)
1109
+ {
1110
+
1111
+ switch (n->norm->Bl.type) {
1112
+ case LIST_column:
1113
+ if (n->child != NULL)
1114
+ print_line(".TE", 0);
1115
+ break;
1116
+ case LIST_enum:
1117
+ n->norm->Bl.count = 0;
1118
+ break;
1119
+ default:
1120
+ break;
1121
+ }
1122
+
1123
+ if (n->norm->Bl.offs) {
1124
+ print_line(".RE", MMAN_nl);
1125
+ assert(Bl_stack_len);
1126
+ Bl_stack_len--;
1127
+ assert(Bl_stack[Bl_stack_len] == 0);
1128
+ } else {
1129
+ outflags |= MMAN_PP | MMAN_nl;
1130
+ outflags &= ~(MMAN_sp | MMAN_br);
1131
+ }
1132
+
1133
+ /* Maybe we are inside an enclosing list? */
1134
+ if (roff_node_next(n->parent) != NULL)
1135
+ mid_it();
1136
+ }
1137
+
1138
+ static void
1139
+ pre_br(DECL_ARGS)
1140
+ {
1141
+ outflags |= MMAN_br;
1142
+ }
1143
+
1144
+ static int
1145
+ pre_dl(DECL_ARGS)
1146
+ {
1147
+ print_offs("6n", 0);
1148
+ return 1;
1149
+ }
1150
+
1151
+ static void
1152
+ post_dl(DECL_ARGS)
1153
+ {
1154
+ print_line(".RE", MMAN_nl);
1155
+
1156
+ /* Maybe we are inside an enclosing list? */
1157
+ if (roff_node_next(n->parent) != NULL)
1158
+ mid_it();
1159
+ }
1160
+
1161
+ static int
1162
+ pre_em(DECL_ARGS)
1163
+ {
1164
+
1165
+ font_push('I');
1166
+ return 1;
1167
+ }
1168
+
1169
+ static int
1170
+ pre_en(DECL_ARGS)
1171
+ {
1172
+
1173
+ if (NULL == n->norm->Es ||
1174
+ NULL == n->norm->Es->child)
1175
+ return 1;
1176
+
1177
+ print_word(n->norm->Es->child->string);
1178
+ outflags &= ~MMAN_spc;
1179
+ return 1;
1180
+ }
1181
+
1182
+ static void
1183
+ post_en(DECL_ARGS)
1184
+ {
1185
+
1186
+ if (NULL == n->norm->Es ||
1187
+ NULL == n->norm->Es->child ||
1188
+ NULL == n->norm->Es->child->next)
1189
+ return;
1190
+
1191
+ outflags &= ~MMAN_spc;
1192
+ print_word(n->norm->Es->child->next->string);
1193
+ return;
1194
+ }
1195
+
1196
+ static int
1197
+ pre_eo(DECL_ARGS)
1198
+ {
1199
+
1200
+ if (n->end == ENDBODY_NOT &&
1201
+ n->parent->head->child == NULL &&
1202
+ n->child != NULL &&
1203
+ n->child->end != ENDBODY_NOT)
1204
+ print_word("\\&");
1205
+ else if (n->end != ENDBODY_NOT ? n->child != NULL :
1206
+ n->parent->head->child != NULL && (n->child != NULL ||
1207
+ (n->parent->tail != NULL && n->parent->tail->child != NULL)))
1208
+ outflags &= ~(MMAN_spc | MMAN_nl);
1209
+ return 1;
1210
+ }
1211
+
1212
+ static void
1213
+ post_eo(DECL_ARGS)
1214
+ {
1215
+ int body, tail;
1216
+
1217
+ if (n->end != ENDBODY_NOT) {
1218
+ outflags |= MMAN_spc;
1219
+ return;
1220
+ }
1221
+
1222
+ body = n->child != NULL || n->parent->head->child != NULL;
1223
+ tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
1224
+
1225
+ if (body && tail)
1226
+ outflags &= ~MMAN_spc;
1227
+ else if ( ! (body || tail))
1228
+ print_word("\\&");
1229
+ else if ( ! tail)
1230
+ outflags |= MMAN_spc;
1231
+ }
1232
+
1233
+ static int
1234
+ pre_fa(DECL_ARGS)
1235
+ {
1236
+ int am_Fa;
1237
+
1238
+ am_Fa = MDOC_Fa == n->tok;
1239
+
1240
+ if (am_Fa)
1241
+ n = n->child;
1242
+
1243
+ while (NULL != n) {
1244
+ font_push('I');
1245
+ if (am_Fa || NODE_SYNPRETTY & n->flags)
1246
+ outflags |= MMAN_nbrword;
1247
+ print_node(meta, n);
1248
+ font_pop();
1249
+ if (NULL != (n = n->next))
1250
+ print_word(",");
1251
+ }
1252
+ return 0;
1253
+ }
1254
+
1255
+ static void
1256
+ post_fa(DECL_ARGS)
1257
+ {
1258
+ struct roff_node *nn;
1259
+
1260
+ if ((nn = roff_node_next(n)) != NULL && nn->tok == MDOC_Fa)
1261
+ print_word(",");
1262
+ }
1263
+
1264
+ static int
1265
+ pre_fd(DECL_ARGS)
1266
+ {
1267
+ pre_syn(n);
1268
+ font_push('B');
1269
+ return 1;
1270
+ }
1271
+
1272
+ static void
1273
+ post_fd(DECL_ARGS)
1274
+ {
1275
+ font_pop();
1276
+ outflags |= MMAN_br;
1277
+ }
1278
+
1279
+ static int
1280
+ pre_fl(DECL_ARGS)
1281
+ {
1282
+ font_push('B');
1283
+ print_word("\\-");
1284
+ if (n->child != NULL)
1285
+ outflags &= ~MMAN_spc;
1286
+ return 1;
1287
+ }
1288
+
1289
+ static void
1290
+ post_fl(DECL_ARGS)
1291
+ {
1292
+ struct roff_node *nn;
1293
+
1294
+ font_pop();
1295
+ if (n->child == NULL &&
1296
+ ((nn = roff_node_next(n)) != NULL &&
1297
+ nn->type != ROFFT_TEXT &&
1298
+ (nn->flags & NODE_LINE) == 0))
1299
+ outflags &= ~MMAN_spc;
1300
+ }
1301
+
1302
+ static int
1303
+ pre_fn(DECL_ARGS)
1304
+ {
1305
+
1306
+ pre_syn(n);
1307
+
1308
+ n = n->child;
1309
+ if (NULL == n)
1310
+ return 0;
1311
+
1312
+ if (NODE_SYNPRETTY & n->flags)
1313
+ print_block(".HP 4n", MMAN_nl);
1314
+
1315
+ font_push('B');
1316
+ print_node(meta, n);
1317
+ font_pop();
1318
+ outflags &= ~MMAN_spc;
1319
+ print_word("(");
1320
+ outflags &= ~MMAN_spc;
1321
+
1322
+ n = n->next;
1323
+ if (NULL != n)
1324
+ pre_fa(meta, n);
1325
+ return 0;
1326
+ }
1327
+
1328
+ static void
1329
+ post_fn(DECL_ARGS)
1330
+ {
1331
+
1332
+ print_word(")");
1333
+ if (NODE_SYNPRETTY & n->flags) {
1334
+ print_word(";");
1335
+ outflags |= MMAN_PP;
1336
+ }
1337
+ }
1338
+
1339
+ static int
1340
+ pre_fo(DECL_ARGS)
1341
+ {
1342
+
1343
+ switch (n->type) {
1344
+ case ROFFT_BLOCK:
1345
+ pre_syn(n);
1346
+ break;
1347
+ case ROFFT_HEAD:
1348
+ if (n->child == NULL)
1349
+ return 0;
1350
+ if (NODE_SYNPRETTY & n->flags)
1351
+ print_block(".HP 4n", MMAN_nl);
1352
+ font_push('B');
1353
+ break;
1354
+ case ROFFT_BODY:
1355
+ outflags &= ~(MMAN_spc | MMAN_nl);
1356
+ print_word("(");
1357
+ outflags &= ~MMAN_spc;
1358
+ break;
1359
+ default:
1360
+ break;
1361
+ }
1362
+ return 1;
1363
+ }
1364
+
1365
+ static void
1366
+ post_fo(DECL_ARGS)
1367
+ {
1368
+
1369
+ switch (n->type) {
1370
+ case ROFFT_HEAD:
1371
+ if (n->child != NULL)
1372
+ font_pop();
1373
+ break;
1374
+ case ROFFT_BODY:
1375
+ post_fn(meta, n);
1376
+ break;
1377
+ default:
1378
+ break;
1379
+ }
1380
+ }
1381
+
1382
+ static int
1383
+ pre_Ft(DECL_ARGS)
1384
+ {
1385
+
1386
+ pre_syn(n);
1387
+ font_push('I');
1388
+ return 1;
1389
+ }
1390
+
1391
+ static void
1392
+ pre_ft(DECL_ARGS)
1393
+ {
1394
+ print_line(".ft", 0);
1395
+ print_word(n->child->string);
1396
+ outflags |= MMAN_nl;
1397
+ }
1398
+
1399
+ static int
1400
+ pre_in(DECL_ARGS)
1401
+ {
1402
+
1403
+ if (NODE_SYNPRETTY & n->flags) {
1404
+ pre_syn(n);
1405
+ font_push('B');
1406
+ print_word("#include <");
1407
+ outflags &= ~MMAN_spc;
1408
+ } else {
1409
+ print_word("<");
1410
+ outflags &= ~MMAN_spc;
1411
+ font_push('I');
1412
+ }
1413
+ return 1;
1414
+ }
1415
+
1416
+ static void
1417
+ post_in(DECL_ARGS)
1418
+ {
1419
+
1420
+ if (NODE_SYNPRETTY & n->flags) {
1421
+ outflags &= ~MMAN_spc;
1422
+ print_word(">");
1423
+ font_pop();
1424
+ outflags |= MMAN_br;
1425
+ } else {
1426
+ font_pop();
1427
+ outflags &= ~MMAN_spc;
1428
+ print_word(">");
1429
+ }
1430
+ }
1431
+
1432
+ static int
1433
+ pre_it(DECL_ARGS)
1434
+ {
1435
+ const struct roff_node *bln;
1436
+
1437
+ switch (n->type) {
1438
+ case ROFFT_HEAD:
1439
+ outflags |= MMAN_PP | MMAN_nl;
1440
+ bln = n->parent->parent;
1441
+ if (bln->norm->Bl.comp == 0 ||
1442
+ (n->parent->prev == NULL &&
1443
+ roff_node_prev(bln->parent) == NULL))
1444
+ outflags |= MMAN_sp;
1445
+ outflags &= ~MMAN_br;
1446
+ switch (bln->norm->Bl.type) {
1447
+ case LIST_item:
1448
+ return 0;
1449
+ case LIST_inset:
1450
+ case LIST_diag:
1451
+ case LIST_ohang:
1452
+ if (bln->norm->Bl.type == LIST_diag)
1453
+ print_line(".B \"", 0);
1454
+ else
1455
+ print_line(".BR \\& \"", 0);
1456
+ outflags &= ~MMAN_spc;
1457
+ return 1;
1458
+ case LIST_bullet:
1459
+ case LIST_dash:
1460
+ case LIST_hyphen:
1461
+ print_width(&bln->norm->Bl, NULL);
1462
+ TPremain = 0;
1463
+ outflags |= MMAN_nl;
1464
+ font_push('B');
1465
+ if (LIST_bullet == bln->norm->Bl.type)
1466
+ print_word("\\(bu");
1467
+ else
1468
+ print_word("-");
1469
+ font_pop();
1470
+ outflags |= MMAN_nl;
1471
+ return 0;
1472
+ case LIST_enum:
1473
+ print_width(&bln->norm->Bl, NULL);
1474
+ TPremain = 0;
1475
+ outflags |= MMAN_nl;
1476
+ print_count(&bln->norm->Bl.count);
1477
+ outflags |= MMAN_nl;
1478
+ return 0;
1479
+ case LIST_hang:
1480
+ print_width(&bln->norm->Bl, n->child);
1481
+ TPremain = 0;
1482
+ outflags |= MMAN_nl;
1483
+ return 1;
1484
+ case LIST_tag:
1485
+ print_width(&bln->norm->Bl, n->child);
1486
+ putchar('\n');
1487
+ outflags &= ~MMAN_spc;
1488
+ return 1;
1489
+ default:
1490
+ return 1;
1491
+ }
1492
+ default:
1493
+ break;
1494
+ }
1495
+ return 1;
1496
+ }
1497
+
1498
+ /*
1499
+ * This function is called after closing out an indented block.
1500
+ * If we are inside an enclosing list, restore its indentation.
1501
+ */
1502
+ static void
1503
+ mid_it(void)
1504
+ {
1505
+ char buf[24];
1506
+
1507
+ /* Nothing to do outside a list. */
1508
+ if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1])
1509
+ return;
1510
+
1511
+ /* The indentation has already been set up. */
1512
+ if (Bl_stack_post[Bl_stack_len - 1])
1513
+ return;
1514
+
1515
+ /* Restore the indentation of the enclosing list. */
1516
+ print_line(".RS", MMAN_Bk_susp);
1517
+ (void)snprintf(buf, sizeof(buf), "%dn",
1518
+ Bl_stack[Bl_stack_len - 1]);
1519
+ print_word(buf);
1520
+
1521
+ /* Remeber to close out this .RS block later. */
1522
+ Bl_stack_post[Bl_stack_len - 1] = 1;
1523
+ }
1524
+
1525
+ static void
1526
+ post_it(DECL_ARGS)
1527
+ {
1528
+ const struct roff_node *bln;
1529
+
1530
+ bln = n->parent->parent;
1531
+
1532
+ switch (n->type) {
1533
+ case ROFFT_HEAD:
1534
+ switch (bln->norm->Bl.type) {
1535
+ case LIST_diag:
1536
+ outflags &= ~MMAN_spc;
1537
+ print_word("\\ ");
1538
+ break;
1539
+ case LIST_ohang:
1540
+ outflags |= MMAN_br;
1541
+ break;
1542
+ default:
1543
+ break;
1544
+ }
1545
+ break;
1546
+ case ROFFT_BODY:
1547
+ switch (bln->norm->Bl.type) {
1548
+ case LIST_bullet:
1549
+ case LIST_dash:
1550
+ case LIST_hyphen:
1551
+ case LIST_enum:
1552
+ case LIST_hang:
1553
+ case LIST_tag:
1554
+ assert(Bl_stack_len);
1555
+ Bl_stack[--Bl_stack_len] = 0;
1556
+
1557
+ /*
1558
+ * Our indentation had to be restored
1559
+ * after a child display or child list.
1560
+ * Close out that indentation block now.
1561
+ */
1562
+ if (Bl_stack_post[Bl_stack_len]) {
1563
+ print_line(".RE", MMAN_nl);
1564
+ Bl_stack_post[Bl_stack_len] = 0;
1565
+ }
1566
+ break;
1567
+ case LIST_column:
1568
+ if (NULL != n->next) {
1569
+ putchar('\t');
1570
+ outflags &= ~MMAN_spc;
1571
+ }
1572
+ break;
1573
+ default:
1574
+ break;
1575
+ }
1576
+ break;
1577
+ default:
1578
+ break;
1579
+ }
1580
+ }
1581
+
1582
+ static void
1583
+ post_lb(DECL_ARGS)
1584
+ {
1585
+
1586
+ if (SEC_LIBRARY == n->sec)
1587
+ outflags |= MMAN_br;
1588
+ }
1589
+
1590
+ static int
1591
+ pre_lk(DECL_ARGS)
1592
+ {
1593
+ const struct roff_node *link, *descr, *punct;
1594
+
1595
+ if ((link = n->child) == NULL)
1596
+ return 0;
1597
+
1598
+ /* Find beginning of trailing punctuation. */
1599
+ punct = n->last;
1600
+ while (punct != link && punct->flags & NODE_DELIMC)
1601
+ punct = punct->prev;
1602
+ punct = punct->next;
1603
+
1604
+ /* Link text. */
1605
+ if ((descr = link->next) != NULL && descr != punct) {
1606
+ font_push('I');
1607
+ while (descr != punct) {
1608
+ print_word(descr->string);
1609
+ descr = descr->next;
1610
+ }
1611
+ font_pop();
1612
+ print_word(":");
1613
+ }
1614
+
1615
+ /* Link target. */
1616
+ font_push('B');
1617
+ print_word(link->string);
1618
+ font_pop();
1619
+
1620
+ /* Trailing punctuation. */
1621
+ while (punct != NULL) {
1622
+ print_word(punct->string);
1623
+ punct = punct->next;
1624
+ }
1625
+ return 0;
1626
+ }
1627
+
1628
+ static void
1629
+ pre_onearg(DECL_ARGS)
1630
+ {
1631
+ outflags |= MMAN_nl;
1632
+ print_word(".");
1633
+ outflags &= ~MMAN_spc;
1634
+ print_word(roff_name[n->tok]);
1635
+ if (n->child != NULL)
1636
+ print_word(n->child->string);
1637
+ outflags |= MMAN_nl;
1638
+ if (n->tok == ROFF_ce)
1639
+ for (n = n->child->next; n != NULL; n = n->next)
1640
+ print_node(meta, n);
1641
+ }
1642
+
1643
+ static int
1644
+ pre_li(DECL_ARGS)
1645
+ {
1646
+ font_push('R');
1647
+ return 1;
1648
+ }
1649
+
1650
+ static int
1651
+ pre_nm(DECL_ARGS)
1652
+ {
1653
+ char *name;
1654
+
1655
+ switch (n->type) {
1656
+ case ROFFT_BLOCK:
1657
+ outflags |= MMAN_Bk;
1658
+ pre_syn(n);
1659
+ return 1;
1660
+ case ROFFT_HEAD:
1661
+ case ROFFT_ELEM:
1662
+ break;
1663
+ default:
1664
+ return 1;
1665
+ }
1666
+ name = n->child == NULL ? NULL : n->child->string;
1667
+ if (name == NULL)
1668
+ return 0;
1669
+ if (n->type == ROFFT_HEAD) {
1670
+ if (roff_node_prev(n->parent) == NULL)
1671
+ outflags |= MMAN_sp;
1672
+ print_block(".HP", 0);
1673
+ printf(" %dn", man_strlen(name) + 1);
1674
+ outflags |= MMAN_nl;
1675
+ }
1676
+ font_push('B');
1677
+ return 1;
1678
+ }
1679
+
1680
+ static void
1681
+ post_nm(DECL_ARGS)
1682
+ {
1683
+ switch (n->type) {
1684
+ case ROFFT_BLOCK:
1685
+ outflags &= ~MMAN_Bk;
1686
+ break;
1687
+ case ROFFT_HEAD:
1688
+ case ROFFT_ELEM:
1689
+ if (n->child != NULL && n->child->string != NULL)
1690
+ font_pop();
1691
+ break;
1692
+ default:
1693
+ break;
1694
+ }
1695
+ }
1696
+
1697
+ static int
1698
+ pre_no(DECL_ARGS)
1699
+ {
1700
+ outflags |= MMAN_spc_force;
1701
+ return 1;
1702
+ }
1703
+
1704
+ static void
1705
+ pre_noarg(DECL_ARGS)
1706
+ {
1707
+ outflags |= MMAN_nl;
1708
+ print_word(".");
1709
+ outflags &= ~MMAN_spc;
1710
+ print_word(roff_name[n->tok]);
1711
+ outflags |= MMAN_nl;
1712
+ }
1713
+
1714
+ static int
1715
+ pre_ns(DECL_ARGS)
1716
+ {
1717
+ outflags &= ~MMAN_spc;
1718
+ return 0;
1719
+ }
1720
+
1721
+ static void
1722
+ post_pf(DECL_ARGS)
1723
+ {
1724
+
1725
+ if ( ! (n->next == NULL || n->next->flags & NODE_LINE))
1726
+ outflags &= ~MMAN_spc;
1727
+ }
1728
+
1729
+ static int
1730
+ pre_pp(DECL_ARGS)
1731
+ {
1732
+
1733
+ if (MDOC_It != n->parent->tok)
1734
+ outflags |= MMAN_PP;
1735
+ outflags |= MMAN_sp | MMAN_nl;
1736
+ outflags &= ~MMAN_br;
1737
+ return 0;
1738
+ }
1739
+
1740
+ static int
1741
+ pre_rs(DECL_ARGS)
1742
+ {
1743
+
1744
+ if (SEC_SEE_ALSO == n->sec) {
1745
+ outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
1746
+ outflags &= ~MMAN_br;
1747
+ }
1748
+ return 1;
1749
+ }
1750
+
1751
+ static int
1752
+ pre_skip(DECL_ARGS)
1753
+ {
1754
+
1755
+ return 0;
1756
+ }
1757
+
1758
+ static int
1759
+ pre_sm(DECL_ARGS)
1760
+ {
1761
+
1762
+ if (NULL == n->child)
1763
+ outflags ^= MMAN_Sm;
1764
+ else if (0 == strcmp("on", n->child->string))
1765
+ outflags |= MMAN_Sm;
1766
+ else
1767
+ outflags &= ~MMAN_Sm;
1768
+
1769
+ if (MMAN_Sm & outflags)
1770
+ outflags |= MMAN_spc;
1771
+
1772
+ return 0;
1773
+ }
1774
+
1775
+ static void
1776
+ pre_sp(DECL_ARGS)
1777
+ {
1778
+ if (outflags & MMAN_PP) {
1779
+ outflags &= ~MMAN_PP;
1780
+ print_line(".PP", 0);
1781
+ } else {
1782
+ print_line(".sp", 0);
1783
+ if (n->child != NULL)
1784
+ print_word(n->child->string);
1785
+ }
1786
+ outflags |= MMAN_nl;
1787
+ }
1788
+
1789
+ static int
1790
+ pre_sy(DECL_ARGS)
1791
+ {
1792
+
1793
+ font_push('B');
1794
+ return 1;
1795
+ }
1796
+
1797
+ static void
1798
+ pre_ta(DECL_ARGS)
1799
+ {
1800
+ print_line(".ta", 0);
1801
+ for (n = n->child; n != NULL; n = n->next)
1802
+ print_word(n->string);
1803
+ outflags |= MMAN_nl;
1804
+ }
1805
+
1806
+ static int
1807
+ pre_vt(DECL_ARGS)
1808
+ {
1809
+
1810
+ if (NODE_SYNPRETTY & n->flags) {
1811
+ switch (n->type) {
1812
+ case ROFFT_BLOCK:
1813
+ pre_syn(n);
1814
+ return 1;
1815
+ case ROFFT_BODY:
1816
+ break;
1817
+ default:
1818
+ return 0;
1819
+ }
1820
+ }
1821
+ font_push('I');
1822
+ return 1;
1823
+ }
1824
+
1825
+ static void
1826
+ post_vt(DECL_ARGS)
1827
+ {
1828
+
1829
+ if (n->flags & NODE_SYNPRETTY && n->type != ROFFT_BODY)
1830
+ return;
1831
+ font_pop();
1832
+ }
1833
+
1834
+ static int
1835
+ pre_xr(DECL_ARGS)
1836
+ {
1837
+
1838
+ n = n->child;
1839
+ if (NULL == n)
1840
+ return 0;
1841
+ print_node(meta, n);
1842
+ n = n->next;
1843
+ if (NULL == n)
1844
+ return 0;
1845
+ outflags &= ~MMAN_spc;
1846
+ print_word("(");
1847
+ print_node(meta, n);
1848
+ print_word(")");
1849
+ return 0;
1850
+ }