=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.142 retrieving revision 1.148 diff -u -p -r1.142 -r1.148 --- mandoc/mdoc_macro.c 2014/08/21 12:57:17 1.142 +++ mandoc/mdoc_macro.c 2014/11/27 22:27:56 1.148 @@ -1,7 +1,7 @@ -/* $Id: mdoc_macro.c,v 1.142 2014/08/21 12:57:17 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.148 2014/11/27 22:27:56 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons - * Copyright (c) 2010, 2012, 2013 Ingo Schwarze + * Copyright (c) 2010, 2012, 2013, 2014 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 @@ -147,9 +147,8 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */ + { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* No */ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | - MDOC_IGNDELIM | MDOC_JOIN }, /* No */ - { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ @@ -172,7 +171,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT | MDOC_JOIN }, /* So */ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */ - { in_line_eoln, 0 }, /* Sm */ + { in_line_argn, 0 }, /* Sm */ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ @@ -210,7 +209,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { in_line_eoln, 0 }, /* sp */ { in_line_eoln, 0 }, /* %U */ { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */ - { in_line_eoln, 0 }, /* ll */ + { in_line_eoln, MDOC_PROLOGUE }, /* ll */ }; const struct mdoc_macro * const mdoc_macros = __mdoc_macros; @@ -438,9 +437,11 @@ rew_dohalt(enum mdoct tok, enum mdoc_type type, * Default block rewinding rules. * In particular, always skip block end markers, * and let all blocks rewind Nm children. + * Do not warn again when closing a block, + * since closing the body already warned. */ if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok || - (MDOC_BLOCK == p->type && + MDOC_BLOCK == type || (MDOC_BLOCK == p->type && ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))) return(REWIND_MORE); @@ -627,24 +628,22 @@ dword(struct mdoc *mdoc, int line, int col, const char if ( ! mdoc_word_alloc(mdoc, line, col, p)) return(0); - if (DELIM_OPEN == d) - mdoc->last->flags |= MDOC_DELIMO; - /* - * Closing delimiters only suppress the preceding space - * when they follow something, not when they start a new - * block or element, and not when they follow `No'. - * - * XXX Explicitly special-casing MDOC_No here feels - * like a layering violation. Find a better way - * and solve this in the code related to `No'! + * If the word consists of a bare delimiter, + * flag the new node accordingly, + * unless doing so was vetoed by the invoking macro. + * Always clear the veto, it is only valid for one word. */ - else if (DELIM_CLOSE == d && mdoc->last->prev && - mdoc->last->prev->tok != MDOC_No && + if (d == DELIM_OPEN) + mdoc->last->flags |= MDOC_DELIMO; + else if (d == DELIM_CLOSE && + ! (mdoc->flags & MDOC_NODELIMC) && mdoc->last->parent->tok != MDOC_Fd) mdoc->last->flags |= MDOC_DELIMC; + mdoc->flags &= ~MDOC_NODELIMC; + return(1); } @@ -694,6 +693,7 @@ static int blk_exp_close(MACRO_PROT_ARGS) { struct mdoc_node *body; /* Our own body. */ + struct mdoc_node *endbody; /* Our own end marker. */ struct mdoc_node *later; /* A sub-block starting later. */ struct mdoc_node *n; /* For searching backwards. */ @@ -720,7 +720,7 @@ blk_exp_close(MACRO_PROT_ARGS) * both of our own and of pending sub-blocks. */ atok = rew_alt(tok); - body = later = NULL; + body = endbody = later = NULL; for (n = mdoc->last; n; n = n->parent) { if (MDOC_VALID & n->flags) continue; @@ -759,6 +759,10 @@ blk_exp_close(MACRO_PROT_ARGS) if ( ! mdoc_endbody_alloc(mdoc, line, ppos, atok, body, ENDBODY_SPACE)) return(0); + if (maxargs) { + endbody = mdoc->last; + mdoc->next = MDOC_NEXT_CHILD; + } break; } @@ -788,15 +792,28 @@ blk_exp_close(MACRO_PROT_ARGS) if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos)) return(0); - if (NULL == later && maxargs > 0) - if ( ! mdoc_tail_alloc(mdoc, line, ppos, rew_alt(tok))) + if (maxargs && endbody == NULL) { + if (n == NULL) { + /* + * Stray .Ec without previous .Eo: + * Break the output line, ignore any arguments. + */ + if ( ! mdoc_elem_alloc(mdoc, line, ppos, + MDOC_br, NULL)) + return(0); + if ( ! rew_elem(mdoc, MDOC_br)) + return(0); + } else if ( ! mdoc_tail_alloc(mdoc, line, ppos, atok)) return(0); + } - for (flushed = j = 0; ; j++) { + flushed = n == NULL; + for (j = 0; ; j++) { lastarg = *pos; if (j == maxargs && ! flushed) { - if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos)) + if ( ! (endbody != NULL ? rew_last(mdoc, endbody) : + rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))) return(0); flushed = 1; } @@ -820,7 +837,8 @@ blk_exp_close(MACRO_PROT_ARGS) } if ( ! flushed) { - if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos)) + if ( ! (endbody != NULL ? rew_last(mdoc, endbody) : + rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))) return(0); flushed = 1; } @@ -832,7 +850,8 @@ blk_exp_close(MACRO_PROT_ARGS) break; } - if ( ! flushed && ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos)) + if ( ! flushed && ! (endbody != NULL ? rew_last(mdoc, endbody) : + rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))) return(0); if ( ! nl) @@ -843,7 +862,7 @@ blk_exp_close(MACRO_PROT_ARGS) static int in_line(MACRO_PROT_ARGS) { - int la, scope, cnt, mayopen, nc, nl; + int la, scope, cnt, firstarg, mayopen, nc, nl; enum margverr av; enum mdoct ntok; enum margserr ac; @@ -894,19 +913,43 @@ in_line(MACRO_PROT_ARGS) return(0); } + d = DELIM_NONE; + firstarg = 1; mayopen = 1; for (cnt = scope = 0;; ) { la = *pos; ac = mdoc_args(mdoc, line, pos, buf, tok, &p); - if (ARGS_ERROR == ac) + if (ac == ARGS_ERROR) return(0); - if (ARGS_EOLN == ac) + + /* + * At the end of a macro line, + * opening delimiters do not suppress spacing. + */ + + if (ac == ARGS_EOLN) { + if (d == DELIM_OPEN) + mdoc->last->flags &= ~MDOC_DELIMO; break; - if (ARGS_PUNCT == ac) + } + + /* + * The rest of the macro line is only punctuation, + * to be handled by append_delims(). + * If there were no other arguments, + * do not allow the first one to suppress spacing, + * even if it turns out to be a closing one. + */ + + if (ac == ARGS_PUNCT) { + if (cnt == 0 && nc == 0) + mdoc->flags |= MDOC_NODELIMC; break; + } - ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); + ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ? + MDOC_MAX : lookup(tok, p); /* * In this case, we've located a submacro and must @@ -949,20 +992,19 @@ in_line(MACRO_PROT_ARGS) if (DELIM_NONE != d) { /* * If we encounter closing punctuation, no word - * has been omitted, no scope is open, and we're + * has been emitted, no scope is open, and we're * allowed to have an empty element, then start * a new scope. */ if ((d == DELIM_CLOSE || (d == DELIM_MIDDLE && tok == MDOC_Fl)) && - (nc || tok == MDOC_Li) && - !scope && !cnt && mayopen) { + !cnt && !scope && nc && mayopen) { if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg)) return(0); scope = 1; cnt++; - if (MDOC_Li == tok || MDOC_Nm == tok) + if (MDOC_Nm == tok) mayopen = 0; } /* @@ -972,6 +1014,8 @@ in_line(MACRO_PROT_ARGS) if (scope && ! rew_elem(mdoc, tok)) return(0); scope = 0; + if (tok == MDOC_Fn) + mayopen = 0; } else if (mayopen && !scope) { if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg)) return(0); @@ -984,6 +1028,15 @@ in_line(MACRO_PROT_ARGS) return(0); /* + * If the first argument is a closing delimiter, + * do not suppress spacing before it. + */ + + if (firstarg && d == DELIM_CLOSE && !nc) + mdoc->last->flags &= ~MDOC_DELIMC; + firstarg = 0; + + /* * `Fl' macros have their scope re-opened with each new * word so that the `-' can be added to each one without * having to parse out spaces. @@ -1532,8 +1585,6 @@ in_line_argn(MACRO_PROT_ARGS) switch (tok) { case MDOC_Ap: - /* FALLTHROUGH */ - case MDOC_No: /* FALLTHROUGH */ case MDOC_Ns: /* FALLTHROUGH */