]>
git.cameronkatri.com Git - mandoc.git/blob - macro.c
1 /* $Id: macro.c,v 1.7 2008/12/28 00:34:20 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.
27 #define _CC(p) ((const char **)p)
29 static int scope_rewind_exp(struct mdoc
*, int, int, int);
30 static int scope_rewind_imp(struct mdoc
*, int, int);
31 static int append_text(struct mdoc
*, int,
33 static int append_scoped(struct mdoc
*, int, int, int,
34 const char *[], int, const struct mdoc_arg
*);
35 static int append_delims(struct mdoc
*, int, int *, char *);
39 append_delims(struct mdoc
*mdoc
, int tok
, int *pos
, char *buf
)
47 mdoc_msg(mdoc
, *pos
, "appending delimiters");
51 c
= mdoc_args(mdoc
, tok
, pos
, buf
, 0, &p
);
54 else if (ARGS_EOLN
== c
)
56 assert(mdoc_isdelim(p
));
57 mdoc_word_alloc(mdoc
, lastarg
, p
);
65 scope_rewind_imp(struct mdoc
*mdoc
, int ppos
, int tok
)
70 n
= mdoc
->last
? mdoc
->last
->parent
: NULL
;
73 for ( ; n
; n
= n
->parent
) {
74 if (MDOC_BLOCK
!= n
->type
)
76 if (tok
== (t
= n
->data
.block
.tok
))
78 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[t
].flags
))
80 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SCOPE_BREAK
));
85 mdoc_msg(mdoc
, ppos
, "scope: rewound implicit `%s'",
86 mdoc_macronames
[tok
]);
90 mdoc_msg(mdoc
, ppos
, "scope: new implicit `%s'",
91 mdoc_macronames
[tok
]);
97 scope_rewind_exp(struct mdoc
*mdoc
, int ppos
, int tok
, int dst
)
104 for (n
= mdoc
->last
->parent
; n
; n
= n
->parent
) {
105 if (MDOC_BLOCK
!= n
->type
)
107 if (dst
== n
->data
.block
.tok
)
109 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SCOPE_BREAK
));
112 if (NULL
== (mdoc
->last
= n
))
113 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SCOPE_NOCTX
));
115 mdoc_msg(mdoc
, ppos
, "scope: rewound explicit `%s' to `%s'",
116 mdoc_macronames
[tok
], mdoc_macronames
[dst
]);
123 append_scoped(struct mdoc
*mdoc
, int tok
, int pos
,
124 int sz
, const char *args
[],
125 int argc
, const struct mdoc_arg
*argv
)
128 struct mdoc_node
*node
;
131 /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
134 return(mdoc_err(mdoc
, tok
, pos
, ERR_ARGS_GE1
));
136 sec
= mdoc_atosec((size_t)sz
, _CC(args
));
137 if (SEC_CUSTOM
!= sec
&& sec
< mdoc
->sec_lastn
)
138 if ( ! mdoc_warn(mdoc
, tok
, pos
, WARN_SEC_OO
))
141 if (SEC_BODY
== mdoc
->sec_last
&& SEC_NAME
!= sec
)
142 return(mdoc_err(mdoc
, tok
, pos
, ERR_SEC_NAME
));
144 if (SEC_CUSTOM
!= sec
)
145 mdoc
->sec_lastn
= sec
;
146 mdoc
->sec_last
= sec
;
151 return(mdoc_err(mdoc
, tok
, pos
, ERR_ARGS_GE1
));
156 for (node
= mdoc
->last
->parent
; node
; node
= node
->parent
) {
157 if (node
->type
!= MDOC_BLOCK
)
159 if (node
->data
.block
.tok
!= MDOC_Bd
)
161 return(mdoc_err(mdoc
, tok
, pos
, ERR_SCOPE_NONEST
));
168 /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
174 mdoc_block_alloc(mdoc
, pos
, tok
, (size_t)argc
, argv
);
175 mdoc_head_alloc(mdoc
, pos
, tok
, (size_t)sz
, _CC(args
));
176 mdoc_body_alloc(mdoc
, pos
, tok
);
182 append_text(struct mdoc
*mdoc
, int tok
,
183 int pos
, int sz
, char *args
[])
190 /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
194 if ( ! mdoc_warn(mdoc
, tok
, pos
, WARN_ARGS_EQ0
))
209 if ( ! mdoc_warn(mdoc
, tok
, pos
, WARN_ARGS_GE1
))
218 /* These can have no arguments. */
240 return(mdoc_err(mdoc
, tok
, pos
, ERR_ARGS_GE1
));
241 /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
247 mdoc_elem_alloc(mdoc
, pos
, tok
, 0, NULL
, (size_t)sz
, _CC(args
));
253 macro_text(MACRO_PROT_ARGS
)
255 int lastarg
, lastpunct
, c
, j
;
256 char *args
[MDOC_LINEARG_MAX
], *p
;
258 if (SEC_PROLOGUE
== mdoc
->sec_lastn
)
259 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE
));
261 /* Token pre-processing. */
265 /* `.Pp' ignored when following `.Sh' or `.Ss'. */
267 if (MDOC_BODY
!= mdoc
->last
->type
)
269 switch (mdoc
->last
->data
.body
.tok
) {
273 if ( ! mdoc_warn(mdoc
, tok
, ppos
, WARN_IGN_AFTER_BLK
))
284 /* Process line parameters. */
291 if (j
== MDOC_LINEARG_MAX
)
292 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_ARGS_MANY
));
295 * Parse out the next argument, unquoted and unescaped. If
296 * we're a word (which may be punctuation followed eventually by
297 * a real word), then fall into checking for callables. If
298 * only punctuation remains and we're the first, then flush
299 * arguments, punctuation and exit; else, return to the caller.
304 switch (mdoc_args(mdoc
, tok
, pos
, buf
, ARGS_DELIM
, &args
[j
])) {
310 if ( ! lastpunct
&& ! append_text(mdoc
, tok
, ppos
, j
, args
))
312 return(append_delims(mdoc
, tok
, pos
, buf
));
314 return(append_text(mdoc
, tok
, ppos
, j
, args
));
321 * Command found. First flush out arguments, then call the
322 * command. If we're the line macro when it exits, flush
323 * terminal punctuation.
326 if (MDOC_MAX
!= (c
= mdoc_find(mdoc
, args
[j
]))) {
327 if ( ! lastpunct
&& ! append_text(mdoc
, tok
, ppos
, j
, args
))
329 if ( ! mdoc_macro(mdoc
, c
, lastarg
, pos
, buf
))
333 return(append_delims(mdoc
, tok
, pos
, buf
));
336 /* Word/non-term-punctuation found. */
338 if ( ! mdoc_isdelim(args
[j
])) {
339 /* Words are appended to the array of arguments. */
346 * For punctuation, flush all collected words, then flush
347 * punctuation, then start collecting again. Of course, this
348 * is non-terminal punctuation.
352 if ( ! lastpunct
&& ! append_text(mdoc
, tok
, ppos
, j
, args
))
355 mdoc_word_alloc(mdoc
, lastarg
, p
);
366 macro_prologue_dtitle(MACRO_PROT_ARGS
)
369 char *args
[MDOC_LINEARG_MAX
];
371 if (SEC_PROLOGUE
!= mdoc
->sec_lastn
)
372 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_NPROLOGUE
));
373 if (0 == mdoc
->meta
.date
)
374 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE_OO
));
375 if (mdoc
->meta
.title
[0])
376 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE_REP
));
382 if (j
== MDOC_LINEARG_MAX
)
383 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_ARGS_MANY
));
387 switch (mdoc_args(mdoc
, tok
, pos
, buf
, 0, &args
[++j
])) {
389 if (mdoc
->meta
.title
)
391 if ( ! mdoc_warn(mdoc
, tok
, ppos
, WARN_ARGS_GE1
))
393 (void)xstrlcpy(mdoc
->meta
.title
,
394 "UNTITLED", META_TITLE_SZ
);
402 if (MDOC_MAX
!= mdoc_find(mdoc
, args
[j
]) && ! mdoc_warn
403 (mdoc
, tok
, lastarg
, WARN_SYNTAX_MACLIKE
))
407 if (xstrlcpy(mdoc
->meta
.title
, args
[0], META_TITLE_SZ
))
409 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_SYNTAX_ARGFORM
));
412 mdoc
->meta
.msec
= mdoc_atomsec(args
[1]);
413 if (MSEC_DEFAULT
!= mdoc
->meta
.msec
)
415 return(mdoc_err(mdoc
, tok
, -1, ERR_SYNTAX_ARGFORM
));
418 mdoc
->meta
.vol
= mdoc_atovol(args
[2]);
419 if (VOL_DEFAULT
!= mdoc
->meta
.vol
)
421 mdoc
->meta
.arch
= mdoc_atoarch(args
[2]);
422 if (ARCH_DEFAULT
!= mdoc
->meta
.arch
)
424 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_SYNTAX_ARGFORM
));
427 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_ARGS_MANY
));
432 macro_prologue_os(MACRO_PROT_ARGS
)
435 char *args
[MDOC_LINEARG_MAX
];
437 if (SEC_PROLOGUE
!= mdoc
->sec_lastn
)
438 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_NPROLOGUE
));
439 if (0 == mdoc
->meta
.title
[0])
440 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE_OO
));
441 if (mdoc
->meta
.os
[0])
442 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE_REP
));
448 if (j
== MDOC_LINEARG_MAX
)
449 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_ARGS_MANY
));
453 switch (mdoc_args(mdoc
, tok
, pos
, buf
,
454 ARGS_QUOTED
, &args
[++j
])) {
456 mdoc
->sec_lastn
= mdoc
->sec_last
= SEC_BODY
;
464 if ( ! xstrlcat(mdoc
->meta
.os
, args
[j
], sizeof(mdoc
->meta
.os
)))
465 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_SYNTAX_ARGFORM
));
466 if ( ! xstrlcat(mdoc
->meta
.os
, " ", sizeof(mdoc
->meta
.os
)))
467 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_SYNTAX_ARGFORM
));
475 macro_prologue_ddate(MACRO_PROT_ARGS
)
478 char *args
[MDOC_LINEARG_MAX
], date
[64];
480 if (SEC_PROLOGUE
!= mdoc
->sec_lastn
)
481 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_NPROLOGUE
));
482 if (mdoc
->meta
.title
[0])
483 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE_OO
));
485 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE_REP
));
492 if (j
== MDOC_LINEARG_MAX
)
493 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_ARGS_MANY
));
496 switch (mdoc_args(mdoc
, tok
, pos
, buf
, 0, &args
[++j
])) {
500 mdoc
->meta
.date
= mdoc_atotime(date
);
503 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SYNTAX_ARGFORM
));
510 if (MDOC_MAX
!= mdoc_find(mdoc
, args
[j
]) && ! mdoc_warn
511 (mdoc
, tok
, lastarg
, WARN_SYNTAX_MACLIKE
))
515 if (xstrcmp("$Mdocdate: December 28 2008 $", args
[j
])) {
516 mdoc
->meta
.date
= time(NULL
);
518 } else if (xstrcmp("$Mdocdate:", args
[j
]))
521 if ( ! xstrcmp("$", args
[j
]))
524 if ( ! xstrlcat(date
, args
[j
], sizeof(date
)))
525 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_SYNTAX_ARGFORM
));
526 if ( ! xstrlcat(date
, " ", sizeof(date
)))
527 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_SYNTAX_ARGFORM
));
535 macro_scoped_explicit(MACRO_PROT_ARGS
)
538 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
541 if (SEC_PROLOGUE
== mdoc
->sec_lastn
)
542 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE
));
545 * First close out the explicit scope. The `end' tags (such as
546 * `.El' to `.Bl' don't cause anything to happen: we merely
547 * readjust our last parse point.
552 return(scope_rewind_exp(mdoc
, ppos
, tok
, MDOC_Bl
));
554 return(scope_rewind_exp(mdoc
, ppos
, tok
, MDOC_Bd
));
559 assert(MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
);
561 /* Token pre-processing. */
567 /* `.Pp' ignored when preceding `.Bl' or `.Bd'. */
569 if (MDOC_ELEM
!= mdoc
->last
->type
)
571 if (MDOC_Pp
!= mdoc
->last
->data
.elem
.tok
)
573 if ( ! mdoc_warn(mdoc
, tok
, ppos
, WARN_IGN_BEFORE_BLK
))
575 assert(mdoc
->last
->prev
);
577 mdoc
->last
= mdoc
->last
->prev
;
578 mdoc
->last
->next
= NULL
;
587 for (j
= 0; j
< MDOC_LINEARG_MAX
; j
++) {
589 c
= mdoc_argv(mdoc
, tok
, &argv
[j
], pos
, buf
);
595 mdoc_argv_free(j
, argv
);
599 if (MDOC_LINEARG_MAX
== j
) {
600 mdoc_argv_free(j
, argv
);
601 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_ARGS_MANY
));
604 c
= append_scoped(mdoc
, tok
, ppos
, 0, NULL
, j
, argv
);
605 mdoc_argv_free(j
, argv
);
611 macro_scoped_implicit(MACRO_PROT_ARGS
)
614 char *args
[MDOC_LINEARG_MAX
];
617 assert( ! (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
));
619 if (SEC_PROLOGUE
== mdoc
->sec_lastn
)
620 return(mdoc_err(mdoc
, tok
, ppos
, ERR_SEC_PROLOGUE
));
622 /* Token pre-processing. */
628 /* `.Pp' ignored when preceding `.Ss' or `.Sh'. */
629 if (NULL
== mdoc
->last
)
631 if (MDOC_ELEM
!= mdoc
->last
->type
)
633 if (MDOC_Pp
!= mdoc
->last
->data
.elem
.tok
)
635 if ( ! mdoc_warn(mdoc
, tok
, ppos
, WARN_IGN_BEFORE_BLK
))
637 assert(mdoc
->last
->prev
);
639 mdoc
->last
= mdoc
->last
->prev
;
640 mdoc
->last
->next
= NULL
;
651 if ( ! scope_rewind_imp(mdoc
, ppos
, tok
))
662 if (j
== MDOC_LINEARG_MAX
)
663 return(mdoc_err(mdoc
, tok
, lastarg
, ERR_ARGS_MANY
));
667 switch (mdoc_args(mdoc
, tok
, pos
, buf
, 0, &args
[j
])) {
671 return(append_scoped(mdoc
, tok
, ppos
, j
, _CC(args
), 0, NULL
));
678 if (MDOC_MAX
!= mdoc_find(mdoc
, args
[j
]))
679 if ( ! mdoc_warn(mdoc
, tok
, lastarg
, WARN_SYNTAX_MACLIKE
))
692 macro_scoped_line(MACRO_PROT_ARGS
)