=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.217 retrieving revision 1.226 diff -u -p -r1.217 -r1.226 --- mandoc/mdoc_macro.c 2017/02/16 09:47:31 1.217 +++ mandoc/mdoc_macro.c 2018/12/04 02:53:51 1.226 @@ -1,7 +1,7 @@ -/* $Id: mdoc_macro.c,v 1.217 2017/02/16 09:47:31 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.226 2018/12/04 02:53:51 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons - * Copyright (c) 2010, 2012-2017 Ingo Schwarze + * Copyright (c) 2010, 2012-2018 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -46,21 +46,21 @@ static void phrase_ta(MACRO_PROT_ARGS); static void append_delims(struct roff_man *, int, int *, char *); static void dword(struct roff_man *, int, int, const char *, enum mdelim, int); -static int find_pending(struct roff_man *, int, int, int, - struct roff_node *); +static int find_pending(struct roff_man *, enum roff_tok, + int, int, struct roff_node *); static int lookup(struct roff_man *, int, int, int, const char *); static int macro_or_word(MACRO_PROT_ARGS, int); static void break_intermediate(struct roff_node *, - struct roff_node *); -static int parse_rest(struct roff_man *, int, int, int *, char *); -static int rew_alt(int); -static void rew_elem(struct roff_man *, int); + struct roff_node *); +static int parse_rest(struct roff_man *, enum roff_tok, + int, int *, char *); +static enum roff_tok rew_alt(enum roff_tok); +static void rew_elem(struct roff_man *, enum roff_tok); static void rew_last(struct roff_man *, const struct roff_node *); static void rew_pending(struct roff_man *, const struct roff_node *); -const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { - { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */ +static const struct mdoc_macro mdoc_macros[MDOC_MAX - MDOC_Dd] = { { in_line_eoln, MDOC_PROLOGUE }, /* Dd */ { in_line_eoln, MDOC_PROLOGUE }, /* Dt */ { in_line_eoln, MDOC_PROLOGUE }, /* Os */ @@ -76,6 +76,8 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | + MDOC_IGNDELIM | MDOC_JOIN }, /* Ap */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ @@ -196,15 +198,17 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* En */ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */ { in_line_eoln, MDOC_JOIN }, /* %Q */ - { in_line_eoln, 0 }, /* br */ - { in_line_eoln, 0 }, /* sp */ { in_line_eoln, 0 }, /* %U */ { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */ - { in_line_eoln, MDOC_PROLOGUE }, /* ll */ }; -const struct mdoc_macro * const mdoc_macros = __mdoc_macros; +const struct mdoc_macro * +mdoc_macro(enum roff_tok tok) +{ + assert(tok >= MDOC_Dd && tok < MDOC_MAX); + return mdoc_macros + (tok - MDOC_Dd); +} /* * This is called at the end of parsing. It must traverse up the tree, @@ -223,9 +227,9 @@ mdoc_endparse(struct roff_man *mdoc) for ( ; n; n = n->parent) if (n->type == ROFFT_BLOCK && - mdoc_macros[n->tok].flags & MDOC_EXPLICIT) + mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse, - n->line, n->pos, mdoc_macronames[n->tok]); + n->line, n->pos, roff_name[n->tok]); /* Rewind to the first. */ @@ -240,20 +244,19 @@ mdoc_endparse(struct roff_man *mdoc) static int lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p) { - int res; + enum roff_tok res; if (mdoc->flags & MDOC_PHRASEQF) { mdoc->flags &= ~MDOC_PHRASEQF; return TOKEN_NONE; } - if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) { - res = mdoc_hash_find(p); + if (from == TOKEN_NONE || mdoc_macro(from)->flags & MDOC_PARSED) { + res = roffhash_find(mdoc->mdocmac, p, 0); if (res != TOKEN_NONE) { - if (mdoc_macros[res].flags & MDOC_CALLABLE) + if (mdoc_macro(res)->flags & MDOC_CALLABLE) return res; - if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll) - mandoc_msg(MANDOCERR_MACRO_CALL, - mdoc->parse, line, ppos, p); + mandoc_msg(MANDOCERR_MACRO_CALL, + mdoc->parse, line, ppos, p); } } return TOKEN_NONE; @@ -324,8 +327,8 @@ rew_pending(struct roff_man *mdoc, const struct roff_n * For a block closing macro, return the corresponding opening one. * Otherwise, return the macro itself. */ -static int -rew_alt(int tok) +static enum roff_tok +rew_alt(enum roff_tok tok) { switch (tok) { case MDOC_Ac: @@ -366,7 +369,7 @@ rew_alt(int tok) } static void -rew_elem(struct roff_man *mdoc, int tok) +rew_elem(struct roff_man *mdoc, enum roff_tok tok) { struct roff_node *n; @@ -398,7 +401,7 @@ break_intermediate(struct roff_node *n, struct roff_no * the rew_pending() call closing out the sub-block. */ static int -find_pending(struct roff_man *mdoc, int tok, int line, int ppos, +find_pending(struct roff_man *mdoc, enum roff_tok tok, int line, int ppos, struct roff_node *target) { struct roff_node *n; @@ -412,7 +415,7 @@ find_pending(struct roff_man *mdoc, int tok, int line, if (n->flags & NODE_ENDED) continue; if (n->type == ROFFT_BLOCK && - mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { + mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) { irc = 1; break_intermediate(mdoc->last, target); if (target->type == ROFFT_HEAD) @@ -420,8 +423,8 @@ find_pending(struct roff_man *mdoc, int tok, int line, else if ( ! (target->flags & NODE_ENDED)) { mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, - "%s breaks %s", mdoc_macronames[tok], - mdoc_macronames[n->tok]); + "%s breaks %s", roff_name[tok], + roff_name[n->tok]); mdoc_endbody_alloc(mdoc, line, ppos, tok, target); } @@ -521,12 +524,13 @@ macro_or_word(MACRO_PROT_ARGS, int parsed) if (ntok == TOKEN_NONE) { dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE || - mdoc_macros[tok].flags & MDOC_JOIN); + mdoc_macro(tok)->flags & MDOC_JOIN); return 0; } else { - if (mdoc_macros[tok].fp == in_line_eoln) + if (tok != TOKEN_NONE && + mdoc_macro(tok)->fp == in_line_eoln) rew_elem(mdoc, tok); - mdoc_macro(mdoc, ntok, line, ppos, pos, buf); + (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, ppos, pos, buf); if (tok == TOKEN_NONE) append_delims(mdoc, line, pos, buf); return 1; @@ -548,7 +552,7 @@ blk_exp_close(MACRO_PROT_ARGS) int j, lastarg, maxargs, nl, pending; enum margserr ac; - int atok, ntok; + enum roff_tok atok, ntok; char *p; nl = MDOC_NEWLINE & mdoc->flags; @@ -633,8 +637,7 @@ blk_exp_close(MACRO_PROT_ARGS) mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, "%s breaks %s", - mdoc_macronames[atok], - mdoc_macronames[later->tok]); + roff_name[atok], roff_name[later->tok]); endbody = mdoc_endbody_alloc(mdoc, line, ppos, atok, body); @@ -676,14 +679,14 @@ blk_exp_close(MACRO_PROT_ARGS) if (body == NULL) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse, - line, ppos, mdoc_macronames[tok]); + line, ppos, roff_name[tok]); if (maxargs && endbody == NULL) { /* * Stray .Ec without previous .Eo: * Break the output line, keep the arguments. */ - roff_elem_alloc(mdoc, line, ppos, MDOC_br); - rew_elem(mdoc, MDOC_br); + roff_elem_alloc(mdoc, line, ppos, ROFF_br); + rew_elem(mdoc, ROFF_br); } } else if (endbody == NULL) { rew_last(mdoc, body); @@ -691,11 +694,11 @@ blk_exp_close(MACRO_PROT_ARGS) mdoc_tail_alloc(mdoc, line, ppos, atok); } - if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) { + if ((mdoc_macro(tok)->flags & MDOC_PARSED) == 0) { if (buf[*pos] != '\0') mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, line, ppos, - "%s %s", mdoc_macronames[tok], + "%s %s", roff_name[tok], buf + *pos); if (endbody == NULL && n != NULL) rew_pending(mdoc, n); @@ -716,19 +719,18 @@ blk_exp_close(MACRO_PROT_ARGS) if (ac == ARGS_PUNCT || ac == ARGS_EOLN) break; - ntok = ac == ARGS_QWORD ? TOKEN_NONE : - lookup(mdoc, tok, line, lastarg, p); + ntok = lookup(mdoc, tok, line, lastarg, p); if (ntok == TOKEN_NONE) { dword(mdoc, line, lastarg, p, DELIM_MAX, - MDOC_JOIN & mdoc_macros[tok].flags); + mdoc_macro(tok)->flags & MDOC_JOIN); continue; } if (n != NULL) rew_last(mdoc, n); mdoc->flags &= ~MDOC_NEWLINE; - mdoc_macro(mdoc, ntok, line, lastarg, pos, buf); + (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, lastarg, pos, buf); break; } @@ -752,7 +754,7 @@ static void in_line(MACRO_PROT_ARGS) { int la, scope, cnt, firstarg, mayopen, nc, nl; - int ntok; + enum roff_tok ntok; enum margserr ac; enum mdelim d; struct mdoc_arg *arg; @@ -813,7 +815,7 @@ in_line(MACRO_PROT_ARGS) break; } - ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ? + ntok = (tok == MDOC_Fn && !cnt) ? TOKEN_NONE : lookup(mdoc, tok, line, la, p); /* @@ -833,23 +835,21 @@ in_line(MACRO_PROT_ARGS) mdoc_argv_free(arg); mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, line, ppos, - mdoc_macronames[tok]); + roff_name[tok]); } - mdoc_macro(mdoc, ntok, line, la, pos, buf); + (*mdoc_macro(ntok)->fp)(mdoc, ntok, + line, la, pos, buf); if (nl) append_delims(mdoc, line, pos, buf); return; } /* - * Non-quote-enclosed punctuation. Set up our scope, if - * a word; rewind the scope, if a delimiter; then append - * the word. + * Handle punctuation. Set up our scope, if a word; + * rewind the scope, if a delimiter; then append the word. */ - d = ac == ARGS_QWORD ? DELIM_NONE : mdoc_isdelim(p); - - if (DELIM_NONE != d) { + if ((d = mdoc_isdelim(p)) != DELIM_NONE) { /* * If we encounter closing punctuation, no word * has been emitted, no scope is open, and we're @@ -869,11 +869,12 @@ in_line(MACRO_PROT_ARGS) * Close out our scope, if one is open, before * any punctuation. */ - if (scope) + if (scope && tok != MDOC_Lk) { rew_elem(mdoc, tok); - scope = 0; - if (tok == MDOC_Fn) - mayopen = 0; + scope = 0; + if (tok == MDOC_Fn) + mayopen = 0; + } } else if (mayopen && !scope) { mdoc_elem_alloc(mdoc, line, ppos, tok, arg); scope = 1; @@ -881,7 +882,7 @@ in_line(MACRO_PROT_ARGS) } dword(mdoc, line, la, p, d, - MDOC_JOIN & mdoc_macros[tok].flags); + mdoc_macro(tok)->flags & MDOC_JOIN); /* * If the first argument is a closing delimiter, @@ -903,8 +904,10 @@ in_line(MACRO_PROT_ARGS) } } - if (scope) + if (scope && tok != MDOC_Lk) { rew_elem(mdoc, tok); + scope = 0; + } /* * If no elements have been collected and we're allowed to have @@ -919,11 +922,13 @@ in_line(MACRO_PROT_ARGS) } else { mdoc_argv_free(arg); mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, mdoc_macronames[tok]); + line, ppos, roff_name[tok]); } } if (nl) append_delims(mdoc, line, pos, buf); + if (scope) + rew_elem(mdoc, tok); } static void @@ -942,11 +947,11 @@ blk_full(MACRO_PROT_ARGS) if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) { mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, mdoc_macronames[tok]); + line, ppos, roff_name[tok]); return; } - if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) { + if ((mdoc_macro(tok)->flags & MDOC_EXPLICIT) == 0) { /* Here, tok is one of Sh Ss Nm Nd It. */ @@ -965,21 +970,20 @@ blk_full(MACRO_PROT_ARGS) mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, "It breaks %s", - mdoc_macronames[blk->tok]); + roff_name[blk->tok]); rew_pending(mdoc, blk); } break; } - if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { + if (mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) { switch (tok) { case MDOC_Sh: case MDOC_Ss: mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, - "%s breaks %s", - mdoc_macronames[tok], - mdoc_macronames[n->tok]); + "%s breaks %s", roff_name[tok], + roff_name[n->tok]); rew_pending(mdoc, n); n = mdoc->last; continue; @@ -1005,8 +1009,7 @@ blk_full(MACRO_PROT_ARGS) if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, - "It breaks %s", - mdoc_macronames[blk->tok]); + "It breaks %s", roff_name[blk->tok]); rew_pending(mdoc, blk); blk = NULL; } @@ -1021,8 +1024,8 @@ blk_full(MACRO_PROT_ARGS) if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) { mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse, line, ppos, "It %s", buf + *pos); - roff_elem_alloc(mdoc, line, ppos, MDOC_br); - rew_elem(mdoc, MDOC_br); + roff_elem_alloc(mdoc, line, ppos, ROFF_br); + rew_elem(mdoc, ROFF_br); return; } } @@ -1099,7 +1102,7 @@ blk_full(MACRO_PROT_ARGS) if (tok == MDOC_Bd || tok == MDOC_Bk) { mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, line, la, "%s ... %s", - mdoc_macronames[tok], buf + la); + roff_name[tok], buf + la); break; } if (tok == MDOC_Rs) { @@ -1117,7 +1120,6 @@ blk_full(MACRO_PROT_ARGS) if (head == NULL && ac != ARGS_PHRASE && - ac != ARGS_QWORD && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); continue; @@ -1214,8 +1216,7 @@ blk_part_imp(MACRO_PROT_ARGS) if (ac == ARGS_EOLN || ac == ARGS_PUNCT) break; - if (body == NULL && ac != ARGS_QWORD && - mdoc_isdelim(p) == DELIM_OPEN) { + if (body == NULL && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); continue; } @@ -1242,7 +1243,7 @@ blk_part_imp(MACRO_PROT_ARGS) for (n = body->child; n && n->next; n = n->next) /* Do nothing. */ ; if (n && n->tok == MDOC_Ns) - mdoc_node_relink(mdoc, n); + roff_node_relink(mdoc, n); } static void @@ -1271,8 +1272,7 @@ blk_part_exp(MACRO_PROT_ARGS) /* Flush out leading punctuation. */ - if (head == NULL && ac != ARGS_QWORD && - mdoc_isdelim(p) == DELIM_OPEN) { + if (head == NULL && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); continue; } @@ -1307,7 +1307,7 @@ in_line_argn(MACRO_PROT_ARGS) struct mdoc_arg *arg; char *p; enum margserr ac; - int ntok; + enum roff_tok ntok; int state; /* arg#; -1: not yet open; -2: closed */ int la, maxargs, nl; @@ -1346,7 +1346,7 @@ in_line_argn(MACRO_PROT_ARGS) ac = mdoc_args(mdoc, line, pos, buf, tok, &p); if (ac == ARGS_WORD && state == -1 && - ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) && + (mdoc_macro(tok)->flags & MDOC_IGNDELIM) == 0 && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); continue; @@ -1371,7 +1371,7 @@ in_line_argn(MACRO_PROT_ARGS) state = -2; } - ntok = (ac == ARGS_QWORD || (tok == MDOC_Pf && state == 0)) ? + ntok = (tok == MDOC_Pf && state == 0) ? TOKEN_NONE : lookup(mdoc, tok, line, la, p); if (ntok != TOKEN_NONE) { @@ -1379,12 +1379,12 @@ in_line_argn(MACRO_PROT_ARGS) rew_elem(mdoc, tok); state = -2; } - mdoc_macro(mdoc, ntok, line, la, pos, buf); + (*mdoc_macro(ntok)->fp)(mdoc, ntok, + line, la, pos, buf); break; } - if (ac == ARGS_QWORD || - mdoc_macros[tok].flags & MDOC_IGNDELIM || + if (mdoc_macro(tok)->flags & MDOC_IGNDELIM || mdoc_isdelim(p) == DELIM_NONE) { if (state == -1) { mdoc_elem_alloc(mdoc, line, ppos, tok, arg); @@ -1397,12 +1397,12 @@ in_line_argn(MACRO_PROT_ARGS) } dword(mdoc, line, la, p, DELIM_MAX, - MDOC_JOIN & mdoc_macros[tok].flags); + mdoc_macro(tok)->flags & MDOC_JOIN); } if (state == -1) { mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, mdoc_macronames[tok]); + line, ppos, roff_name[tok]); return; } @@ -1430,9 +1430,9 @@ in_line_eoln(MACRO_PROT_ARGS) } if (buf[*pos] == '\0' && - (tok == MDOC_Fd || mdoc_macronames[tok][0] == '%')) { + (tok == MDOC_Fd || *roff_name[tok] == '%')) { mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, mdoc_macronames[tok]); + line, ppos, roff_name[tok]); return; } @@ -1449,7 +1449,8 @@ in_line_eoln(MACRO_PROT_ARGS) * or until the next macro, call that macro, and return 1. */ static int -parse_rest(struct roff_man *mdoc, int tok, int line, int *pos, char *buf) +parse_rest(struct roff_man *mdoc, enum roff_tok tok, + int line, int *pos, char *buf) { int la;