Bug Summary

File:src/usr.bin/mandoc/mdoc_man.c
Warning:line 1637, column 12
Access to field 'next' results in a dereference of a null pointer (loaded from field 'child')

Annotated Source Code

Press '?' to see keyboard shortcuts

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