=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.142 retrieving revision 1.146 diff -u -p -r1.142 -r1.146 --- mandoc/mdoc_macro.c 2014/08/21 12:57:17 1.142 +++ mandoc/mdoc_macro.c 2014/11/25 20:00:01 1.146 @@ -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.146 2014/11/25 20:00:01 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 */ @@ -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); } @@ -843,7 +842,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 +893,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 +972,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 +994,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 +1008,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 +1565,6 @@ in_line_argn(MACRO_PROT_ARGS) switch (tok) { case MDOC_Ap: - /* FALLTHROUGH */ - case MDOC_No: /* FALLTHROUGH */ case MDOC_Ns: /* FALLTHROUGH */