8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / mandoc / man.c
blob31c094e8d62c6fe7c2a8d42b6fe0bec269612aed
1 /* $Id: man.c,v 1.166 2015/10/22 21:54:23 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
5 * Copyright (c) 2011 Joerg Sonnenberger <joerg@netbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "config.h"
21 #include <sys/types.h>
23 #include <assert.h>
24 #include <ctype.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
30 #include "mandoc_aux.h"
31 #include "mandoc.h"
32 #include "roff.h"
33 #include "man.h"
34 #include "libmandoc.h"
35 #include "roff_int.h"
36 #include "libman.h"
38 const char *const __man_macronames[MAN_MAX] = {
39 "br", "TH", "SH", "SS",
40 "TP", "LP", "PP", "P",
41 "IP", "HP", "SM", "SB",
42 "BI", "IB", "BR", "RB",
43 "R", "B", "I", "IR",
44 "RI", "sp", "nf",
45 "fi", "RE", "RS", "DT",
46 "UC", "PD", "AT", "in",
47 "ft", "OP", "EX", "EE",
48 "UR", "UE", "ll"
51 const char * const *man_macronames = __man_macronames;
53 static void man_descope(struct roff_man *, int, int);
54 static int man_ptext(struct roff_man *, int, char *, int);
55 static int man_pmacro(struct roff_man *, int, char *, int);
58 int
59 man_parseln(struct roff_man *man, int ln, char *buf, int offs)
62 if (man->last->type != ROFFT_EQN || ln > man->last->line)
63 man->flags |= MAN_NEWLINE;
65 return roff_getcontrol(man->roff, buf, &offs) ?
66 man_pmacro(man, ln, buf, offs) :
67 man_ptext(man, ln, buf, offs);
70 static void
71 man_descope(struct roff_man *man, int line, int offs)
74 * Co-ordinate what happens with having a next-line scope open:
75 * first close out the element scope (if applicable), then close
76 * out the block scope (also if applicable).
79 if (man->flags & MAN_ELINE) {
80 man->flags &= ~MAN_ELINE;
81 man_unscope(man, man->last->parent);
83 if ( ! (man->flags & MAN_BLINE))
84 return;
85 man->flags &= ~MAN_BLINE;
86 man_unscope(man, man->last->parent);
87 roff_body_alloc(man, line, offs, man->last->tok);
90 static int
91 man_ptext(struct roff_man *man, int line, char *buf, int offs)
93 int i;
95 /* Literal free-form text whitespace is preserved. */
97 if (man->flags & MAN_LITERAL) {
98 roff_word_alloc(man, line, offs, buf + offs);
99 man_descope(man, line, offs);
100 return 1;
103 for (i = offs; buf[i] == ' '; i++)
104 /* Skip leading whitespace. */ ;
107 * Blank lines are ignored right after headings
108 * but add a single vertical space elsewhere.
111 if (buf[i] == '\0') {
112 /* Allocate a blank entry. */
113 if (man->last->tok != MAN_SH &&
114 man->last->tok != MAN_SS) {
115 roff_elem_alloc(man, line, offs, MAN_sp);
116 man->next = ROFF_NEXT_SIBLING;
118 return 1;
122 * Warn if the last un-escaped character is whitespace. Then
123 * strip away the remaining spaces (tabs stay!).
126 i = (int)strlen(buf);
127 assert(i);
129 if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
130 if (i > 1 && '\\' != buf[i - 2])
131 mandoc_msg(MANDOCERR_SPACE_EOL, man->parse,
132 line, i - 1, NULL);
134 for (--i; i && ' ' == buf[i]; i--)
135 /* Spin back to non-space. */ ;
137 /* Jump ahead of escaped whitespace. */
138 i += '\\' == buf[i] ? 2 : 1;
140 buf[i] = '\0';
142 roff_word_alloc(man, line, offs, buf + offs);
145 * End-of-sentence check. If the last character is an unescaped
146 * EOS character, then flag the node as being the end of a
147 * sentence. The front-end will know how to interpret this.
150 assert(i);
151 if (mandoc_eos(buf, (size_t)i))
152 man->last->flags |= MAN_EOS;
154 man_descope(man, line, offs);
155 return 1;
158 static int
159 man_pmacro(struct roff_man *man, int ln, char *buf, int offs)
161 struct roff_node *n;
162 const char *cp;
163 int tok;
164 int i, ppos;
165 int bline;
166 char mac[5];
168 ppos = offs;
171 * Copy the first word into a nil-terminated buffer.
172 * Stop when a space, tab, escape, or eoln is encountered.
175 i = 0;
176 while (i < 4 && strchr(" \t\\", buf[offs]) == NULL)
177 mac[i++] = buf[offs++];
179 mac[i] = '\0';
181 tok = (i > 0 && i < 4) ? man_hash_find(mac) : TOKEN_NONE;
183 if (tok == TOKEN_NONE) {
184 mandoc_msg(MANDOCERR_MACRO, man->parse,
185 ln, ppos, buf + ppos - 1);
186 return 1;
189 /* Skip a leading escape sequence or tab. */
191 switch (buf[offs]) {
192 case '\\':
193 cp = buf + offs + 1;
194 mandoc_escape(&cp, NULL, NULL);
195 offs = cp - buf;
196 break;
197 case '\t':
198 offs++;
199 break;
200 default:
201 break;
204 /* Jump to the next non-whitespace word. */
206 while (buf[offs] && buf[offs] == ' ')
207 offs++;
210 * Trailing whitespace. Note that tabs are allowed to be passed
211 * into the parser as "text", so we only warn about spaces here.
214 if (buf[offs] == '\0' && buf[offs - 1] == ' ')
215 mandoc_msg(MANDOCERR_SPACE_EOL, man->parse,
216 ln, offs - 1, NULL);
219 * Some macros break next-line scopes; otherwise, remember
220 * whether we are in next-line scope for a block head.
223 man_breakscope(man, tok);
224 bline = man->flags & MAN_BLINE;
226 /* Call to handler... */
228 assert(man_macros[tok].fp);
229 (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf);
231 /* In quick mode (for mandocdb), abort after the NAME section. */
233 if (man->quick && tok == MAN_SH) {
234 n = man->last;
235 if (n->type == ROFFT_BODY &&
236 strcmp(n->prev->child->string, "NAME"))
237 return 2;
241 * If we are in a next-line scope for a block head,
242 * close it out now and switch to the body,
243 * unless the next-line scope is allowed to continue.
246 if ( ! bline || man->flags & MAN_ELINE ||
247 man_macros[tok].flags & MAN_NSCOPED)
248 return 1;
250 assert(man->flags & MAN_BLINE);
251 man->flags &= ~MAN_BLINE;
253 man_unscope(man, man->last->parent);
254 roff_body_alloc(man, ln, ppos, man->last->tok);
255 return 1;
258 void
259 man_breakscope(struct roff_man *man, int tok)
261 struct roff_node *n;
264 * An element next line scope is open,
265 * and the new macro is not allowed inside elements.
266 * Delete the element that is being broken.
269 if (man->flags & MAN_ELINE && (tok == TOKEN_NONE ||
270 ! (man_macros[tok].flags & MAN_NSCOPED))) {
271 n = man->last;
272 assert(n->type != ROFFT_TEXT);
273 if (man_macros[n->tok].flags & MAN_NSCOPED)
274 n = n->parent;
276 mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
277 n->line, n->pos, "%s breaks %s",
278 tok == TOKEN_NONE ? "TS" : man_macronames[tok],
279 man_macronames[n->tok]);
281 roff_node_delete(man, n);
282 man->flags &= ~MAN_ELINE;
286 * Weird special case:
287 * Switching fill mode closes section headers.
290 if (man->flags & MAN_BLINE &&
291 (tok == MAN_nf || tok == MAN_fi) &&
292 (man->last->tok == MAN_SH || man->last->tok == MAN_SS)) {
293 n = man->last;
294 man_unscope(man, n);
295 roff_body_alloc(man, n->line, n->pos, n->tok);
296 man->flags &= ~MAN_BLINE;
300 * A block header next line scope is open,
301 * and the new macro is not allowed inside block headers.
302 * Delete the block that is being broken.
305 if (man->flags & MAN_BLINE && (tok == TOKEN_NONE ||
306 man_macros[tok].flags & MAN_BSCOPE)) {
307 n = man->last;
308 if (n->type == ROFFT_TEXT)
309 n = n->parent;
310 if ( ! (man_macros[n->tok].flags & MAN_BSCOPE))
311 n = n->parent;
313 assert(n->type == ROFFT_HEAD);
314 n = n->parent;
315 assert(n->type == ROFFT_BLOCK);
316 assert(man_macros[n->tok].flags & MAN_SCOPED);
318 mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
319 n->line, n->pos, "%s breaks %s",
320 tok == TOKEN_NONE ? "TS" : man_macronames[tok],
321 man_macronames[n->tok]);
323 roff_node_delete(man, n);
324 man->flags &= ~MAN_BLINE;
328 const struct mparse *
329 man_mparse(const struct roff_man *man)
332 assert(man && man->parse);
333 return man->parse;
336 void
337 man_state(struct roff_man *man, struct roff_node *n)
340 switch(n->tok) {
341 case MAN_nf:
342 case MAN_EX:
343 if (man->flags & MAN_LITERAL && ! (n->flags & MAN_VALID))
344 mandoc_msg(MANDOCERR_NF_SKIP, man->parse,
345 n->line, n->pos, "nf");
346 man->flags |= MAN_LITERAL;
347 break;
348 case MAN_fi:
349 case MAN_EE:
350 if ( ! (man->flags & MAN_LITERAL) &&
351 ! (n->flags & MAN_VALID))
352 mandoc_msg(MANDOCERR_FI_SKIP, man->parse,
353 n->line, n->pos, "fi");
354 man->flags &= ~MAN_LITERAL;
355 break;
356 default:
357 break;
359 man->last->flags |= MAN_VALID;
362 void
363 man_validate(struct roff_man *man)
366 man->last = man->first;
367 man_node_validate(man);
368 man->flags &= ~MAN_LITERAL;