]>
git.cameronkatri.com Git - mandoc.git/blob - macro.c
1 /* $Id: macro.c,v 1.30 2009/01/09 14:45:44 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
30 /* FIXME: maxlineargs should be per LINE, no per TOKEN. */
32 static int rewind_elem(struct mdoc
*, int);
33 static int rewind_impblock(struct mdoc
*, int);
34 static int rewind_expblock(struct mdoc
*, int);
35 static int rewind_head(struct mdoc
*, int);
36 static int rewind_body(struct mdoc
*, int);
37 static int rewind_last(struct mdoc
*, struct mdoc_node
*);
38 static int append_delims(struct mdoc
*,
39 int, int, int *, char *);
40 static int lookup(struct mdoc
*, int, int, int, const char *);
44 lookup(struct mdoc
*mdoc
, int line
, int pos
, int from
, const char *p
)
48 res
= mdoc_find(mdoc
, p
);
49 if (MDOC_PARSED
& mdoc_macros
[from
].flags
)
54 if ( ! mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX_MACLIKE
))
61 rewind_last(struct mdoc
*mdoc
, struct mdoc_node
*to
)
65 mdoc
->next
= MDOC_NEXT_SIBLING
;
66 if (mdoc
->last
== to
) {
67 if ( ! mdoc_valid_post(mdoc
))
69 if ( ! mdoc_action_post(mdoc
))
75 mdoc
->last
= mdoc
->last
->parent
;
77 if ( ! mdoc_valid_post(mdoc
))
79 if ( ! mdoc_action_post(mdoc
))
81 } while (mdoc
->last
!= to
);
88 rewind_elem(struct mdoc
*mdoc
, int tok
)
93 if (MDOC_ELEM
!= n
->type
)
95 assert(MDOC_ELEM
== n
->type
);
96 assert(tok
== n
->data
.elem
.tok
);
98 return(rewind_last(mdoc
, n
));
103 rewind_body(struct mdoc
*mdoc
, int tok
)
111 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
112 if (MDOC_BODY
!= n
->type
)
114 if (tok
== (t
= n
->data
.head
.tok
))
116 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[t
].flags
))
118 return(mdoc_verr(mdoc
, n
, ERR_SCOPE_BREAK
));
122 return(rewind_last(mdoc
, n
));
127 rewind_head(struct mdoc
*mdoc
, int tok
)
135 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
136 if (MDOC_HEAD
!= n
->type
)
138 if (tok
== (t
= n
->data
.head
.tok
))
140 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[t
].flags
))
142 return(mdoc_verr(mdoc
, n
, ERR_SCOPE_BREAK
));
146 return(rewind_last(mdoc
, n
));
151 rewind_expblock(struct mdoc
*mdoc
, int tok
)
159 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
160 if (MDOC_BLOCK
!= n
->type
)
162 if (tok
== (t
= n
->data
.block
.tok
))
164 if (MDOC_NESTED
& mdoc_macros
[t
].flags
)
166 return(mdoc_verr(mdoc
, n
, ERR_SCOPE_BREAK
));
170 return(rewind_last(mdoc
, n
));
175 rewind_impblock(struct mdoc
*mdoc
, int tok
)
180 n
= mdoc
->last
? mdoc
->last
->parent
: NULL
;
183 for ( ; n
; n
= n
->parent
) {
184 if (MDOC_BLOCK
!= n
->type
)
186 if (tok
== (t
= n
->data
.block
.tok
))
188 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[t
].flags
))
190 if (MDOC_NESTED
& mdoc_macros
[t
].flags
)
192 return(mdoc_verr(mdoc
, n
, ERR_SCOPE_BREAK
));
197 return(rewind_last(mdoc
, n
));
202 append_delims(struct mdoc
*mdoc
, int tok
,
203 int line
, int *pos
, char *buf
)
213 c
= mdoc_args(mdoc
, line
, pos
, buf
, 0, &p
);
216 else if (ARGS_EOLN
== c
)
218 assert(mdoc_isdelim(p
));
219 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
221 mdoc
->next
= MDOC_NEXT_SIBLING
;
230 macro_close_explicit(MACRO_PROT_ARGS
)
232 int tt
, j
, c
, lastarg
, maxargs
, flushed
;
295 if ( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
)) {
297 return(rewind_expblock(mdoc
, tt
));
298 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_EQ0
));
301 if ( ! rewind_body(mdoc
, tt
))
308 if ( ! mdoc_tail_alloc(mdoc
, line
, ppos
, tt
))
310 mdoc
->next
= MDOC_NEXT_CHILD
;
313 for (j
= 0; j
< MDOC_LINEARG_MAX
; j
++) {
316 if (j
== maxargs
&& ! flushed
) {
317 if ( ! rewind_expblock(mdoc
, tt
))
322 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_DELIM
, &p
);
330 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
332 else if (MDOC_MAX
!= c
) {
334 if ( ! rewind_expblock(mdoc
, tt
))
338 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
343 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
345 mdoc
->next
= MDOC_NEXT_SIBLING
;
348 if (MDOC_LINEARG_MAX
== j
)
349 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
351 if ( ! flushed
&& ! rewind_expblock(mdoc
, tt
))
356 return(append_delims(mdoc
, tok
, line
, pos
, buf
));
361 * A general text domain macro. When invoked, this opens a scope that
362 * accepts words until either end-of-line, only-punctuation, or a
363 * callable macro. If the word is punctuation (not only-punctuation),
364 * then the scope is closed out, the punctuation appended, then the
365 * scope opened again. If any terminating conditions are met, the scope
366 * is closed out. If this is the first macro in the line and
367 * only-punctuation remains, this punctuation is flushed.
370 macro_text(MACRO_PROT_ARGS
)
372 int la
, lastpunct
, c
, sz
, fl
, argc
;
373 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
379 for (argc
= 0; argc
< MDOC_LINEARG_MAX
; argc
++) {
382 c
= mdoc_argv(mdoc
, line
, tok
, &argv
[argc
], pos
, buf
);
383 if (ARGV_EOLN
== c
|| ARGV_WORD
== c
)
385 else if (ARGV_ARG
== c
)
387 mdoc_argv_free(argc
, argv
);
391 if (MDOC_LINEARG_MAX
== argc
) {
392 mdoc_argv_free(argc
, argv
);
393 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
396 c
= mdoc_elem_alloc(mdoc
, line
, la
, tok
, argc
, argv
);
399 mdoc_argv_free(argc
, argv
);
403 mdoc
->next
= MDOC_NEXT_CHILD
;
406 if (MDOC_QUOTABLE
& mdoc_macros
[tok
].flags
)
409 for (lastpunct
= sz
= 0; sz
+ argc
< MDOC_LINEARG_MAX
; sz
++) {
413 c
= mdoc_elem_alloc(mdoc
, line
,
414 la
, tok
, argc
, argv
);
416 mdoc_argv_free(argc
, argv
);
419 mdoc
->next
= MDOC_NEXT_CHILD
;
423 c
= mdoc_args(mdoc
, line
, pos
, buf
, fl
, &p
);
424 if (ARGS_ERROR
== c
) {
425 mdoc_argv_free(argc
, argv
);
434 if (-1 == (c
= lookup(mdoc
, line
, la
, tok
, p
)))
436 else if (MDOC_MAX
!= c
) {
437 if ( ! rewind_elem(mdoc
, tok
)) {
438 mdoc_argv_free(argc
, argv
);
441 mdoc_argv_free(argc
, argv
);
443 c
= mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
);
448 return(append_delims(mdoc
, tok
, line
, pos
, buf
));
451 if (mdoc_isdelim(p
)) {
452 if ( ! rewind_elem(mdoc
, tok
)) {
453 mdoc_argv_free(argc
, argv
);
458 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
460 mdoc
->next
= MDOC_NEXT_SIBLING
;
463 mdoc_argv_free(argc
, argv
);
465 if (sz
== MDOC_LINEARG_MAX
)
466 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
468 if ( ! rewind_elem(mdoc
, tok
))
472 return(append_delims(mdoc
, tok
, line
, pos
, buf
));
477 * Implicit- or explicit-end multi-line scoped macro.
480 macro_scoped(MACRO_PROT_ARGS
)
482 int c
, lastarg
, argc
, j
;
483 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
486 assert ( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
));
488 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
))
489 if ( ! rewind_impblock(mdoc
, tok
))
492 for (argc
= 0; argc
< MDOC_LINEARG_MAX
; argc
++) {
494 c
= mdoc_argv(mdoc
, line
, tok
, &argv
[argc
], pos
, buf
);
495 if (ARGV_EOLN
== c
|| ARGV_WORD
== c
)
497 else if (ARGV_ARG
== c
)
499 mdoc_argv_free(argc
, argv
);
503 if (MDOC_LINEARG_MAX
== argc
) {
504 mdoc_argv_free(argc
, argv
);
505 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
508 c
= mdoc_block_alloc(mdoc
, line
, ppos
,
509 tok
, (size_t)argc
, argv
);
510 mdoc_argv_free(argc
, argv
);
515 mdoc
->next
= MDOC_NEXT_CHILD
;
517 if (0 == buf
[*pos
]) {
518 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
520 if ( ! rewind_head(mdoc
, tok
))
522 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
524 mdoc
->next
= MDOC_NEXT_CHILD
;
528 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
530 mdoc
->next
= MDOC_NEXT_CHILD
;
532 for (j
= 0; j
< MDOC_LINEARG_MAX
; j
++) {
534 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_DELIM
, &p
);
543 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
545 else if (MDOC_MAX
== c
) {
546 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
548 mdoc
->next
= MDOC_NEXT_SIBLING
;
552 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
557 if (j
== MDOC_LINEARG_MAX
)
558 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
560 if ( ! rewind_head(mdoc
, tok
))
562 if (1 == ppos
&& ! append_delims(mdoc
, tok
, line
, pos
, buf
))
565 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
567 mdoc
->next
= MDOC_NEXT_CHILD
;
574 * When scoped to a line, a macro encompasses all of the contents. This
575 * differs from constants or text macros, where a new macro will
576 * terminate the existing context.
579 macro_scoped_line(MACRO_PROT_ARGS
)
584 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, 0, NULL
))
586 mdoc
->next
= MDOC_NEXT_CHILD
;
588 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
590 mdoc
->next
= MDOC_NEXT_CHILD
;
592 /* XXX - no known argument macros. */
594 for (lastarg
= ppos
, j
= 0; j
< MDOC_LINEARG_MAX
; j
++) {
596 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_DELIM
, &p
);
605 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
607 else if (MDOC_MAX
== c
) {
608 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
610 mdoc
->next
= MDOC_NEXT_SIBLING
;
614 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
619 if (j
== MDOC_LINEARG_MAX
)
620 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
623 if ( ! rewind_head(mdoc
, tok
))
625 if ( ! append_delims(mdoc
, tok
, line
, pos
, buf
))
628 return(rewind_impblock(mdoc
, tok
));
633 * Constant-scope macros accept a fixed number of arguments and behave
634 * like constant macros except that they're scoped across lines.
637 macro_constant_scoped(MACRO_PROT_ARGS
)
639 int lastarg
, flushed
, j
, c
, maxargs
;
654 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, 0, NULL
))
656 mdoc
->next
= MDOC_NEXT_CHILD
;
659 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
661 if ( ! rewind_head(mdoc
, tok
))
663 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
666 } else if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
669 mdoc
->next
= MDOC_NEXT_CHILD
;
671 for (j
= 0; j
< MDOC_LINEARG_MAX
; j
++) {
674 if (j
== maxargs
&& ! flushed
) {
675 if ( ! rewind_head(mdoc
, tok
))
678 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
680 mdoc
->next
= MDOC_NEXT_CHILD
;
683 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_DELIM
, &p
);
691 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
693 else if (MDOC_MAX
!= c
) {
695 if ( ! rewind_head(mdoc
, tok
))
698 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
700 mdoc
->next
= MDOC_NEXT_CHILD
;
702 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
707 if ( ! flushed
&& mdoc_isdelim(p
)) {
708 if ( ! rewind_head(mdoc
, tok
))
711 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
713 mdoc
->next
= MDOC_NEXT_CHILD
;
716 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
718 mdoc
->next
= MDOC_NEXT_SIBLING
;
721 if (MDOC_LINEARG_MAX
== j
)
722 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
725 if ( ! rewind_head(mdoc
, tok
))
727 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
729 mdoc
->next
= MDOC_NEXT_CHILD
;
734 return(append_delims(mdoc
, tok
, line
, pos
, buf
));
739 * Delimited macros are like text macros except that, should punctuation
740 * be encountered, the macro isn't re-started with remaining tokens
741 * (it's only emitted once). Delimited macros can have a maximum number
745 macro_constant_delimited(MACRO_PROT_ARGS
)
747 int lastarg
, flushed
, j
, c
, maxargs
, argc
;
748 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
769 for (argc
= 0; argc
< MDOC_LINEARG_MAX
; argc
++) {
771 c
= mdoc_argv(mdoc
, line
, tok
, &argv
[argc
], pos
, buf
);
772 if (ARGV_EOLN
== c
|| ARGV_WORD
== c
)
774 else if (ARGV_ARG
== c
)
776 mdoc_argv_free(argc
, argv
);
780 c
= mdoc_elem_alloc(mdoc
, line
, lastarg
, tok
, argc
, argv
);
781 mdoc_argv_free(argc
, argv
);
786 mdoc
->next
= MDOC_NEXT_CHILD
;
788 for (j
= 0; j
< MDOC_LINEARG_MAX
; j
++) {
791 if (j
== maxargs
&& ! flushed
) {
792 if ( ! rewind_elem(mdoc
, tok
))
797 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_DELIM
, &p
);
805 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
807 else if (MDOC_MAX
!= c
) {
808 if ( ! flushed
&& ! rewind_elem(mdoc
, tok
))
811 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
816 if ( ! flushed
&& mdoc_isdelim(p
)) {
817 if ( ! rewind_elem(mdoc
, tok
))
822 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
824 mdoc
->next
= MDOC_NEXT_SIBLING
;
827 if (MDOC_LINEARG_MAX
== j
)
828 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
830 if ( ! flushed
&& rewind_elem(mdoc
, tok
))
835 return(append_delims(mdoc
, tok
, line
, pos
, buf
));
840 * Constant macros span an entire line: they constitute a macro and all
841 * of its arguments and child data.
844 macro_constant(MACRO_PROT_ARGS
)
846 int c
, lastarg
, argc
, sz
, fl
;
847 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
850 /* FIXME: parsing macros! */
853 if (MDOC_QUOTABLE
& mdoc_macros
[tok
].flags
)
856 for (argc
= 0; argc
< MDOC_LINEARG_MAX
; argc
++) {
858 c
= mdoc_argv(mdoc
, line
, tok
, &argv
[argc
], pos
, buf
);
861 else if (ARGV_ARG
== c
)
863 else if (ARGV_WORD
== c
)
866 mdoc_argv_free(argc
, argv
);
870 c
= mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, argc
, argv
);
871 mdoc_argv_free(argc
, argv
);
876 mdoc
->next
= MDOC_NEXT_CHILD
;
878 if (MDOC_LINEARG_MAX
== argc
)
879 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
881 for (sz
= 0; sz
+ argc
< MDOC_LINEARG_MAX
; sz
++) {
883 c
= mdoc_args(mdoc
, line
, pos
, buf
, fl
, &p
);
889 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
891 mdoc
->next
= MDOC_NEXT_SIBLING
;
894 if (MDOC_LINEARG_MAX
== sz
+ argc
)
895 return(mdoc_perr(mdoc
, line
, ppos
, ERR_ARGS_MANY
));
897 return(rewind_elem(mdoc
, tok
));
903 macro_obsolete(MACRO_PROT_ARGS
)
906 return(mdoc_pwarn(mdoc
, line
, ppos
, WARN_IGN_OBSOLETE
));
911 macro_end(struct mdoc
*mdoc
)
916 return(rewind_last(mdoc
, mdoc
->first
));