]>
git.cameronkatri.com Git - mandoc.git/blob - mdoc.c
1 /* $Id: mdoc.c,v 1.267 2017/06/17 13:06:16 schwarze Exp $ */
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/types.h>
30 #include "mandoc_aux.h"
34 #include "libmandoc.h"
38 const char *const __mdoc_argnames
[MDOC_ARG_MAX
] = {
39 "split", "nosplit", "ragged",
40 "unfilled", "literal", "file",
41 "offset", "bullet", "dash",
42 "hyphen", "item", "enum",
43 "tag", "diag", "hang",
44 "ohang", "inset", "column",
45 "width", "compact", "std",
46 "filled", "words", "emphasis",
47 "symbolic", "nested", "centered"
49 const char * const *mdoc_argnames
= __mdoc_argnames
;
51 static int mdoc_ptext(struct roff_man
*, int, char *, int);
52 static int mdoc_pmacro(struct roff_man
*, int, char *, int);
56 * Main parse routine. Parses a single line -- really just hands off to
57 * the macro (mdoc_pmacro()) or text parser (mdoc_ptext()).
60 mdoc_parseln(struct roff_man
*mdoc
, int ln
, char *buf
, int offs
)
63 if (mdoc
->last
->type
!= ROFFT_EQN
|| ln
> mdoc
->last
->line
)
64 mdoc
->flags
|= MDOC_NEWLINE
;
67 * Let the roff nS register switch SYNOPSIS mode early,
68 * such that the parser knows at all times
69 * whether this mode is on or off.
70 * Note that this mode is also switched by the Sh macro.
72 if (roff_getreg(mdoc
->roff
, "nS"))
73 mdoc
->flags
|= MDOC_SYNOPSIS
;
75 mdoc
->flags
&= ~MDOC_SYNOPSIS
;
77 return roff_getcontrol(mdoc
->roff
, buf
, &offs
) ?
78 mdoc_pmacro(mdoc
, ln
, buf
, offs
) :
79 mdoc_ptext(mdoc
, ln
, buf
, offs
);
83 mdoc_macro(MACRO_PROT_ARGS
)
85 assert(tok
>= MDOC_Dd
&& tok
< MDOC_MAX
);
86 (*mdoc_macros
[tok
].fp
)(mdoc
, tok
, line
, ppos
, pos
, buf
);
90 mdoc_tail_alloc(struct roff_man
*mdoc
, int line
, int pos
, enum roff_tok tok
)
94 p
= roff_node_alloc(mdoc
, line
, pos
, ROFFT_TAIL
, tok
);
95 roff_node_append(mdoc
, p
);
96 mdoc
->next
= ROFF_NEXT_CHILD
;
100 mdoc_endbody_alloc(struct roff_man
*mdoc
, int line
, int pos
,
101 enum roff_tok tok
, struct roff_node
*body
)
105 body
->flags
|= NODE_ENDED
;
106 body
->parent
->flags
|= NODE_ENDED
;
107 p
= roff_node_alloc(mdoc
, line
, pos
, ROFFT_BODY
, tok
);
109 p
->norm
= body
->norm
;
110 p
->end
= ENDBODY_SPACE
;
111 roff_node_append(mdoc
, p
);
112 mdoc
->next
= ROFF_NEXT_SIBLING
;
117 mdoc_block_alloc(struct roff_man
*mdoc
, int line
, int pos
,
118 enum roff_tok tok
, struct mdoc_arg
*args
)
122 p
= roff_node_alloc(mdoc
, line
, pos
, ROFFT_BLOCK
, tok
);
133 p
->norm
= mandoc_calloc(1, sizeof(union mdoc_data
));
138 roff_node_append(mdoc
, p
);
139 mdoc
->next
= ROFF_NEXT_CHILD
;
144 mdoc_elem_alloc(struct roff_man
*mdoc
, int line
, int pos
,
145 enum roff_tok tok
, struct mdoc_arg
*args
)
149 p
= roff_node_alloc(mdoc
, line
, pos
, ROFFT_ELEM
, tok
);
156 p
->norm
= mandoc_calloc(1, sizeof(union mdoc_data
));
161 roff_node_append(mdoc
, p
);
162 mdoc
->next
= ROFF_NEXT_CHILD
;
166 mdoc_node_relink(struct roff_man
*mdoc
, struct roff_node
*p
)
169 roff_node_unlink(mdoc
, p
);
170 p
->prev
= p
->next
= NULL
;
171 roff_node_append(mdoc
, p
);
175 * Parse free-form text, that is, a line that does not begin with the
179 mdoc_ptext(struct roff_man
*mdoc
, int line
, char *buf
, int offs
)
188 * If a column list contains plain text, assume an implicit item
189 * macro. This can happen one or more times at the beginning
190 * of such a list, intermixed with non-It mdoc macros and with
191 * nodes generated on the roff level, for example by tbl.
194 if ((n
->tok
== MDOC_Bl
&& n
->type
== ROFFT_BODY
&&
195 n
->end
== ENDBODY_NOT
&& n
->norm
->Bl
.type
== LIST_column
) ||
196 (n
->parent
!= NULL
&& n
->parent
->tok
== MDOC_Bl
&&
197 n
->parent
->norm
->Bl
.type
== LIST_column
)) {
198 mdoc
->flags
|= MDOC_FREECOL
;
199 mdoc_macro(mdoc
, MDOC_It
, line
, offs
, &offs
, buf
);
204 * Search for the beginning of unescaped trailing whitespace (ws)
205 * and for the first character not to be output (end).
208 /* FIXME: replace with strcspn(). */
210 for (c
= end
= buf
+ offs
; *c
; c
++) {
218 * Always warn about trailing tabs,
219 * even outside literal context,
220 * where they should be put on the next line.
225 * Strip trailing tabs in literal context only;
226 * outside, they affect the next line.
228 if (MDOC_LITERAL
& mdoc
->flags
)
232 /* Skip the escaped character, too, if any. */
245 mandoc_msg(MANDOCERR_SPACE_EOL
, mdoc
->parse
,
246 line
, (int)(ws
-buf
), NULL
);
249 * Blank lines are allowed in no-fill mode
250 * and cancel preceding \c,
251 * but add a single vertical space elsewhere.
254 if (buf
[offs
] == '\0' && ! (mdoc
->flags
& MDOC_LITERAL
)) {
255 switch (mdoc
->last
->type
) {
257 sp
= mdoc
->last
->string
;
258 cp
= end
= strchr(sp
, '\0') - 2;
259 if (cp
< sp
|| cp
[0] != '\\' || cp
[1] != 'c')
261 while (cp
> sp
&& cp
[-1] == '\\')
270 mandoc_msg(MANDOCERR_FI_BLANK
, mdoc
->parse
,
271 line
, (int)(c
- buf
), NULL
);
272 roff_elem_alloc(mdoc
, line
, offs
, ROFF_sp
);
273 mdoc
->last
->flags
|= NODE_VALID
| NODE_ENDED
;
274 mdoc
->next
= ROFF_NEXT_SIBLING
;
278 roff_word_alloc(mdoc
, line
, offs
, buf
+offs
);
280 if (mdoc
->flags
& MDOC_LITERAL
)
284 * End-of-sentence check. If the last character is an unescaped
285 * EOS character, then flag the node as being the end of a
286 * sentence. The front-end will know how to interpret this.
291 if (mandoc_eos(buf
+offs
, (size_t)(end
-buf
-offs
)))
292 mdoc
->last
->flags
|= NODE_EOS
;
294 for (c
= buf
+ offs
; c
!= NULL
; c
= strchr(c
+ 1, '.')) {
295 if (c
- buf
< offs
+ 2)
300 isalpha((unsigned char)c
[-2]) == 0 ||
301 isalpha((unsigned char)c
[-1]) == 0 ||
302 (c
[-2] == 'n' && c
[-1] == 'c') ||
303 (c
[-2] == 'v' && c
[-1] == 's'))
310 if (isupper((unsigned char)(*c
)))
311 mandoc_msg(MANDOCERR_EOS
, mdoc
->parse
,
312 line
, (int)(c
- buf
), NULL
);
319 * Parse a macro line, that is, a line beginning with the control
323 mdoc_pmacro(struct roff_man
*mdoc
, int ln
, char *buf
, int offs
)
331 /* Determine the line macro. */
335 for (sz
= 0; sz
< 4 && strchr(" \t\\", buf
[offs
]) == NULL
; sz
++)
337 if (sz
== 2 || sz
== 3)
338 tok
= roffhash_find(mdoc
->mdocmac
, buf
+ sv
, sz
);
339 if (tok
== TOKEN_NONE
) {
340 mandoc_msg(MANDOCERR_MACRO
, mdoc
->parse
,
341 ln
, sv
, buf
+ sv
- 1);
345 /* Skip a leading escape sequence or tab. */
350 mandoc_escape(&cp
, NULL
, NULL
);
360 /* Jump to the next non-whitespace word. */
362 while (buf
[offs
] == ' ')
366 * Trailing whitespace. Note that tabs are allowed to be passed
367 * into the parser as "text", so we only warn about spaces here.
370 if ('\0' == buf
[offs
] && ' ' == buf
[offs
- 1])
371 mandoc_msg(MANDOCERR_SPACE_EOL
, mdoc
->parse
,
375 * If an initial macro or a list invocation, divert directly
376 * into macro processing.
380 if (n
== NULL
|| tok
== MDOC_It
|| tok
== MDOC_El
) {
381 mdoc_macro(mdoc
, tok
, ln
, sv
, &offs
, buf
);
386 * If a column list contains a non-It macro, assume an implicit
387 * item macro. This can happen one or more times at the
388 * beginning of such a list, intermixed with text lines and
389 * with nodes generated on the roff level, for example by tbl.
392 if ((n
->tok
== MDOC_Bl
&& n
->type
== ROFFT_BODY
&&
393 n
->end
== ENDBODY_NOT
&& n
->norm
->Bl
.type
== LIST_column
) ||
394 (n
->parent
!= NULL
&& n
->parent
->tok
== MDOC_Bl
&&
395 n
->parent
->norm
->Bl
.type
== LIST_column
)) {
396 mdoc
->flags
|= MDOC_FREECOL
;
397 mdoc_macro(mdoc
, MDOC_It
, ln
, sv
, &sv
, buf
);
401 /* Normal processing of a macro. */
403 mdoc_macro(mdoc
, tok
, ln
, sv
, &offs
, buf
);
405 /* In quick mode (for mandocdb), abort after the NAME section. */
407 if (mdoc
->quick
&& MDOC_Sh
== tok
&&
408 SEC_NAME
!= mdoc
->last
->sec
)
415 mdoc_isdelim(const char *p
)
444 if (0 == strcmp(p
+ 1, "."))
446 if (0 == strcmp(p
+ 1, "fR|\\fP"))
453 mdoc_validate(struct roff_man
*mdoc
)
456 mdoc
->last
= mdoc
->first
;
457 mdoc_node_validate(mdoc
);
458 mdoc_state_reset(mdoc
);