Print this page
Update to 1.12.3.

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/mdoc_macro.c
          +++ new/usr/src/cmd/mandoc/mdoc_macro.c
   1      -/*      $Id: mdoc_macro.c,v 1.115 2012/01/05 00:43:51 schwarze Exp $ */
        1 +/*      $Id: mdoc_macro.c,v 1.125 2013/12/24 20:45:27 schwarze Exp $ */
   2    2  /*
   3      - * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
   4      - * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
        3 + * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
        4 + * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
   5    5   *
   6    6   * Permission to use, copy, modify, and distribute this software for any
   7    7   * purpose with or without fee is hereby granted, provided that the above
   8    8   * copyright notice and this permission notice appear in all copies.
   9    9   *
  10   10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11   11   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12   12   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13   13   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14   14   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
↓ open down ↓ 29 lines elided ↑ open up ↑
  44   44  static  int             blk_exp_close(MACRO_PROT_ARGS);
  45   45  static  int             blk_part_exp(MACRO_PROT_ARGS);
  46   46  static  int             blk_part_imp(MACRO_PROT_ARGS);
  47   47  static  int             ctx_synopsis(MACRO_PROT_ARGS);
  48   48  static  int             in_line_eoln(MACRO_PROT_ARGS);
  49   49  static  int             in_line_argn(MACRO_PROT_ARGS);
  50   50  static  int             in_line(MACRO_PROT_ARGS);
  51   51  static  int             obsolete(MACRO_PROT_ARGS);
  52   52  static  int             phrase_ta(MACRO_PROT_ARGS);
  53   53  
  54      -static  int             dword(struct mdoc *, int, int, 
  55      -                                const char *, enum mdelim);
       54 +static  int             dword(struct mdoc *, int, int, const char *,
       55 +                                 enum mdelim, int);
  56   56  static  int             append_delims(struct mdoc *, 
  57   57                                  int, int *, char *);
  58   58  static  enum mdoct      lookup(enum mdoct, const char *);
  59   59  static  enum mdoct      lookup_raw(const char *);
  60   60  static  int             make_pending(struct mdoc_node *, enum mdoct,
  61   61                                  struct mdoc *, int, int);
  62   62  static  int             phrase(struct mdoc *, int, int, char *);
  63   63  static  enum mdoct      rew_alt(enum mdoct);
  64   64  static  enum rew        rew_dohalt(enum mdoct, enum mdoc_type, 
  65   65                                  const struct mdoc_node *);
  66   66  static  int             rew_elem(struct mdoc *, enum mdoct);
  67   67  static  int             rew_last(struct mdoc *, 
  68   68                                  const struct mdoc_node *);
  69   69  static  int             rew_sub(enum mdoc_type, struct mdoc *, 
  70   70                                  enum mdoct, int, int);
  71   71  
  72   72  const   struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
  73      -        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
       73 +        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
  74   74          { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
  75   75          { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
  76   76          { in_line_eoln, MDOC_PROLOGUE }, /* Os */
  77      -        { blk_full, MDOC_PARSED }, /* Sh */
  78      -        { blk_full, MDOC_PARSED }, /* Ss */ 
  79      -        { in_line_eoln, 0 }, /* Pp */ 
  80      -        { blk_part_imp, MDOC_PARSED }, /* D1 */
  81      -        { blk_part_imp, MDOC_PARSED }, /* Dl */
       77 +        { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */
       78 +        { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Ss */
       79 +        { in_line_eoln, 0 }, /* Pp */
       80 +        { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* D1 */
       81 +        { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* Dl */
  82   82          { blk_full, MDOC_EXPLICIT }, /* Bd */
  83      -        { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
       83 +        { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */
  84   84          { blk_full, MDOC_EXPLICIT }, /* Bl */
  85      -        { blk_exp_close, MDOC_EXPLICIT }, /* El */
  86      -        { blk_full, MDOC_PARSED }, /* It */
  87      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ 
  88      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
       85 +        { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* El */
       86 +        { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */
       87 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
       88 +        { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */
  89   89          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
  90   90          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
  91   91          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
  92      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ 
  93      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ 
  94      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ 
       92 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
       93 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
       94 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
  95   95          { in_line_eoln, 0 }, /* Ex */
  96      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ 
  97      -        { in_line_eoln, 0 }, /* Fd */ 
       96 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
       97 +        { in_line_eoln, 0 }, /* Fd */
  98   98          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
  99      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ 
 100      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ 
 101      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ 
       99 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
      100 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
      101 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
 102  102          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
 103      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
 104      -        { blk_full, 0 }, /* Nd */ 
 105      -        { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ 
      103 +        { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Li */
      104 +        { blk_full, MDOC_JOIN }, /* Nd */
      105 +        { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
 106  106          { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
 107  107          { obsolete, 0 }, /* Ot */
 108  108          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
 109  109          { in_line_eoln, 0 }, /* Rv */
 110      -        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 
      110 +        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
 111  111          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
 112      -        { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ 
      112 +        { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
 113  113          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
 114      -        { in_line_eoln, 0 }, /* %A */
 115      -        { in_line_eoln, 0 }, /* %B */
 116      -        { in_line_eoln, 0 }, /* %D */
 117      -        { in_line_eoln, 0 }, /* %I */
 118      -        { in_line_eoln, 0 }, /* %J */
      114 +        { in_line_eoln, MDOC_JOIN }, /* %A */
      115 +        { in_line_eoln, MDOC_JOIN }, /* %B */
      116 +        { in_line_eoln, MDOC_JOIN }, /* %D */
      117 +        { in_line_eoln, MDOC_JOIN }, /* %I */
      118 +        { in_line_eoln, MDOC_JOIN }, /* %J */
 119  119          { in_line_eoln, 0 }, /* %N */
 120      -        { in_line_eoln, 0 }, /* %O */
      120 +        { in_line_eoln, MDOC_JOIN }, /* %O */
 121  121          { in_line_eoln, 0 }, /* %P */
 122      -        { in_line_eoln, 0 }, /* %R */
 123      -        { in_line_eoln, 0 }, /* %T */
      122 +        { in_line_eoln, MDOC_JOIN }, /* %R */
      123 +        { in_line_eoln, MDOC_JOIN }, /* %T */
 124  124          { in_line_eoln, 0 }, /* %V */
 125      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
 126      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
 127      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
      125 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      126 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Ac */
      127 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      128 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* Ao */
      129 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Aq */
 128  130          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
 129      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
 130      -        { blk_full, MDOC_EXPLICIT }, /* Bf */ 
 131      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
 132      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
      131 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      132 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Bc */
      133 +        { blk_full, MDOC_EXPLICIT }, /* Bf */
      134 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      135 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* Bo */
      136 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Bq */
 133  137          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
 134  138          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
 135  139          { in_line_eoln, 0 }, /* Db */
 136      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
 137      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
 138      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
 139      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
 140      -        { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
 141      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ 
      140 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      141 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Dc */
      142 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      143 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* Do */
      144 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Dq */
      145 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ec */
      146 +        { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ef */
      147 +        { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Em */
 142  148          { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
 143  149          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
 144  150          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
 145      -        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* No */
 146      -        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Ns */
      151 +        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
      152 +                        MDOC_IGNDELIM | MDOC_JOIN }, /* No */
      153 +        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
      154 +                        MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */
 147  155          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
 148  156          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
 149      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
      157 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      158 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Pc */
 150  159          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
 151      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
 152      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
 153      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
 154      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
 155      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
 156      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
 157      -        { blk_exp_close, MDOC_EXPLICIT }, /* Re */
      160 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      161 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* Po */
      162 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Pq */
      163 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      164 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Qc */
      165 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ql */
      166 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      167 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* Qo */
      168 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Qq */
      169 +        { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Re */
 158  170          { blk_full, MDOC_EXPLICIT }, /* Rs */
 159      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
 160      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
 161      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
      171 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      172 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Sc */
      173 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      174 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* So */
      175 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */
 162  176          { in_line_eoln, 0 }, /* Sm */
 163      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
 164      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
      177 +        { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */
      178 +        { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */
 165  179          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
 166      -        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
      180 +        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ux */
 167  181          { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
 168  182          { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
 169      -        { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ 
 170      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ 
 171      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
 172      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
      183 +        { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
      184 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      185 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Fc */
      186 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      187 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* Oo */
      188 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      189 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Oc */
 173  190          { blk_full, MDOC_EXPLICIT }, /* Bk */
 174      -        { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
      191 +        { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ek */
 175  192          { in_line_eoln, 0 }, /* Bt */
 176  193          { in_line_eoln, 0 }, /* Hf */
 177  194          { obsolete, 0 }, /* Fr */
 178  195          { in_line_eoln, 0 }, /* Ud */
 179  196          { in_line, 0 }, /* Lb */
 180      -        { in_line_eoln, 0 }, /* Lp */ 
 181      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ 
 182      -        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ 
 183      -        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
 184      -        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
 185      -        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
 186      -        { in_line_eoln, 0 }, /* %C */
      197 +        { in_line_eoln, 0 }, /* Lp */
      198 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
      199 +        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
      200 +        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */
      201 +        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
      202 +                        MDOC_EXPLICIT | MDOC_JOIN }, /* Bro */
      203 +        { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
      204 +                         MDOC_EXPLICIT | MDOC_JOIN }, /* Brc */
      205 +        { in_line_eoln, MDOC_JOIN }, /* %C */
 187  206          { obsolete, 0 }, /* Es */
 188  207          { obsolete, 0 }, /* En */
 189  208          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
 190      -        { in_line_eoln, 0 }, /* %Q */
      209 +        { in_line_eoln, MDOC_JOIN }, /* %Q */
 191  210          { in_line_eoln, 0 }, /* br */
 192  211          { in_line_eoln, 0 }, /* sp */
 193  212          { in_line_eoln, 0 }, /* %U */
 194      -        { phrase_ta, MDOC_CALLABLE | MDOC_PARSED }, /* Ta */
      213 +        { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
 195  214  };
 196  215  
 197  216  const   struct mdoc_macro * const mdoc_macros = __mdoc_macros;
 198  217  
 199  218  
 200  219  /*
 201  220   * This is called at the end of parsing.  It must traverse up the tree,
 202  221   * closing out open [implicit] scopes.  Obviously, open explicit scopes
 203  222   * are errors.
 204  223   */
 205  224  int
 206      -mdoc_macroend(struct mdoc *m)
      225 +mdoc_macroend(struct mdoc *mdoc)
 207  226  {
 208  227          struct mdoc_node *n;
 209  228  
 210  229          /* Scan for open explicit scopes. */
 211  230  
 212      -        n = MDOC_VALID & m->last->flags ?  m->last->parent : m->last;
      231 +        n = MDOC_VALID & mdoc->last->flags ?
      232 +                        mdoc->last->parent : mdoc->last;
 213  233  
 214  234          for ( ; n; n = n->parent)
 215  235                  if (MDOC_BLOCK == n->type &&
 216  236                      MDOC_EXPLICIT & mdoc_macros[n->tok].flags)
 217      -                        mdoc_nmsg(m, n, MANDOCERR_SCOPEEXIT);
      237 +                        mdoc_nmsg(mdoc, n, MANDOCERR_SCOPEEXIT);
 218  238  
 219  239          /* Rewind to the first. */
 220  240  
 221      -        return(rew_last(m, m->first));
      241 +        return(rew_last(mdoc, mdoc->first));
 222  242  }
 223  243  
 224  244  
 225  245  /*
 226  246   * Look up a macro from within a subsequent context.
 227  247   */
 228  248  static enum mdoct
 229  249  lookup(enum mdoct from, const char *p)
 230  250  {
 231  251  
↓ open down ↓ 24 lines elided ↑ open up ↑
 256  276  {
 257  277          struct mdoc_node *n, *np;
 258  278  
 259  279          assert(to);
 260  280          mdoc->next = MDOC_NEXT_SIBLING;
 261  281  
 262  282          /* LINTED */
 263  283          while (mdoc->last != to) {
 264  284                  /*
 265  285                   * Save the parent here, because we may delete the
 266      -                 * m->last node in the post-validation phase and reset
 267      -                 * it to m->last->parent, causing a step in the closing
      286 +                 * mdoc->last node in the post-validation phase and reset
      287 +                 * it to mdoc->last->parent, causing a step in the closing
 268  288                   * out to be lost.
 269  289                   */
 270  290                  np = mdoc->last->parent;
 271  291                  if ( ! mdoc_valid_post(mdoc))
 272  292                          return(0);
 273  293                  n = mdoc->last;
 274  294                  mdoc->last = np;
 275  295                  assert(mdoc->last);
 276  296                  mdoc->last->last = n;
 277  297          }
↓ open down ↓ 175 lines elided ↑ open up ↑
 453  473  
 454  474  
 455  475  /*
 456  476   * We are trying to close a block identified by tok,
 457  477   * but the child block *broken is still open.
 458  478   * Thus, postpone closing the tok block
 459  479   * until the rew_sub call closing *broken.
 460  480   */
 461  481  static int
 462  482  make_pending(struct mdoc_node *broken, enum mdoct tok,
 463      -                struct mdoc *m, int line, int ppos)
      483 +                struct mdoc *mdoc, int line, int ppos)
 464  484  {
 465  485          struct mdoc_node *breaker;
 466  486  
 467  487          /*
 468  488           * Iterate backwards, searching for the block matching tok,
 469  489           * that is, the block breaking the *broken block.
 470  490           */
 471  491          for (breaker = broken->parent; breaker; breaker = breaker->parent) {
 472  492  
 473  493                  /*
↓ open down ↓ 34 lines elided ↑ open up ↑
 508  528                           * Graphically, this is the following situation:
 509  529                           * "[A [B breaker=[C->B B] broken=[D->A A] tok=C] D]"
 510  530                           * "[A taker=[B->A breaker=[C->B B] [D->C A] C] D]"
 511  531                           */
 512  532                          taker = breaker;
 513  533                          while (taker->pending)
 514  534                                  taker = taker->pending;
 515  535                          taker->pending = broken->pending;
 516  536                  }
 517  537                  broken->pending = breaker;
 518      -                mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos,
      538 +                mandoc_vmsg(MANDOCERR_SCOPENEST, mdoc->parse, line, ppos,
 519  539                                  "%s breaks %s", mdoc_macronames[tok],
 520  540                                  mdoc_macronames[broken->tok]);
 521  541                  return(1);
 522  542          }
 523  543  
 524  544          /*
 525  545           * Found no matching block for tok.
 526  546           * Are you trying to close a block that is not open?
 527  547           */
 528  548          return(0);
 529  549  }
 530  550  
 531  551  
 532  552  static int
 533      -rew_sub(enum mdoc_type t, struct mdoc *m, 
      553 +rew_sub(enum mdoc_type t, struct mdoc *mdoc, 
 534  554                  enum mdoct tok, int line, int ppos)
 535  555  {
 536  556          struct mdoc_node *n;
 537  557  
 538      -        n = m->last;
      558 +        n = mdoc->last;
 539  559          while (n) {
 540  560                  switch (rew_dohalt(tok, t, n)) {
 541  561                  case (REWIND_NONE):
 542  562                          return(1);
 543  563                  case (REWIND_THIS):
      564 +                        n->lastline = line -
      565 +                            (MDOC_NEWLINE & mdoc->flags &&
      566 +                             ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
 544  567                          break;
 545  568                  case (REWIND_FORCE):
 546      -                        mandoc_vmsg(MANDOCERR_SCOPEBROKEN, m->parse, 
      569 +                        mandoc_vmsg(MANDOCERR_SCOPEBROKEN, mdoc->parse, 
 547  570                                          line, ppos, "%s breaks %s", 
 548  571                                          mdoc_macronames[tok],
 549  572                                          mdoc_macronames[n->tok]);
 550  573                          /* FALLTHROUGH */
 551  574                  case (REWIND_MORE):
      575 +                        n->lastline = line -
      576 +                            (MDOC_NEWLINE & mdoc->flags ? 1 : 0);
 552  577                          n = n->parent;
 553  578                          continue;
 554  579                  case (REWIND_LATER):
 555      -                        if (make_pending(n, tok, m, line, ppos) ||
      580 +                        if (make_pending(n, tok, mdoc, line, ppos) ||
 556  581                              MDOC_BLOCK != t)
 557  582                                  return(1);
 558  583                          /* FALLTHROUGH */
 559  584                  case (REWIND_ERROR):
 560      -                        mdoc_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);
      585 +                        mdoc_pmsg(mdoc, line, ppos, MANDOCERR_NOSCOPE);
 561  586                          return(1);
 562  587                  }
 563  588                  break;
 564  589          }
 565  590  
 566  591          assert(n);
 567      -        if ( ! rew_last(m, n))
      592 +        if ( ! rew_last(mdoc, n))
 568  593                  return(0);
 569  594  
 570  595          /*
 571  596           * The current block extends an enclosing block.
 572  597           * Now that the current block ends, close the enclosing block, too.
 573  598           */
 574  599          while (NULL != (n = n->pending)) {
 575      -                if ( ! rew_last(m, n))
      600 +                if ( ! rew_last(mdoc, n))
 576  601                          return(0);
 577  602                  if (MDOC_HEAD == n->type &&
 578      -                    ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
      603 +                    ! mdoc_body_alloc(mdoc, n->line, n->pos, n->tok))
 579  604                          return(0);
 580  605          }
 581  606  
 582  607          return(1);
 583  608  }
 584  609  
 585  610  /*
 586  611   * Allocate a word and check whether it's punctuation or not.
 587  612   * Punctuation consists of those tokens found in mdoc_isdelim().
 588  613   */
 589  614  static int
 590      -dword(struct mdoc *m, int line, 
 591      -                int col, const char *p, enum mdelim d)
      615 +dword(struct mdoc *mdoc, int line, int col, const char *p,
      616 +                enum mdelim d, int may_append)
 592  617  {
 593  618          
 594  619          if (DELIM_MAX == d)
 595  620                  d = mdoc_isdelim(p);
 596  621  
 597      -        if ( ! mdoc_word_alloc(m, line, col, p))
      622 +        if (may_append &&
      623 +            ! ((MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF) & mdoc->flags) &&
      624 +            DELIM_NONE == d && MDOC_TEXT == mdoc->last->type &&
      625 +            DELIM_NONE == mdoc_isdelim(mdoc->last->string)) {
      626 +                mdoc_word_append(mdoc, p);
      627 +                return(1);
      628 +        }
      629 +
      630 +        if ( ! mdoc_word_alloc(mdoc, line, col, p))
 598  631                  return(0);
 599  632  
 600  633          if (DELIM_OPEN == d)
 601      -                m->last->flags |= MDOC_DELIMO;
      634 +                mdoc->last->flags |= MDOC_DELIMO;
 602  635  
 603  636          /*
 604  637           * Closing delimiters only suppress the preceding space
 605  638           * when they follow something, not when they start a new
 606  639           * block or element, and not when they follow `No'.
 607  640           *
 608  641           * XXX  Explicitly special-casing MDOC_No here feels
 609  642           *      like a layering violation.  Find a better way
 610  643           *      and solve this in the code related to `No'!
 611  644           */
 612  645  
 613      -        else if (DELIM_CLOSE == d && m->last->prev &&
 614      -                        m->last->prev->tok != MDOC_No)
 615      -                m->last->flags |= MDOC_DELIMC;
      646 +        else if (DELIM_CLOSE == d && mdoc->last->prev &&
      647 +                        mdoc->last->prev->tok != MDOC_No &&
      648 +                        mdoc->last->parent->tok != MDOC_Fd)
      649 +                mdoc->last->flags |= MDOC_DELIMC;
 616  650  
 617  651          return(1);
 618  652  }
 619  653  
 620  654  static int
 621      -append_delims(struct mdoc *m, int line, int *pos, char *buf)
      655 +append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
 622  656  {
 623  657          int              la;
 624  658          enum margserr    ac;
 625  659          char            *p;
 626  660  
 627  661          if ('\0' == buf[*pos])
 628  662                  return(1);
 629  663  
 630  664          for (;;) {
 631  665                  la = *pos;
 632      -                ac = mdoc_zargs(m, line, pos, buf, &p);
      666 +                ac = mdoc_zargs(mdoc, line, pos, buf, &p);
 633  667  
 634  668                  if (ARGS_ERROR == ac)
 635  669                          return(0);
 636  670                  else if (ARGS_EOLN == ac)
 637  671                          break;
 638  672  
 639      -                dword(m, line, la, p, DELIM_MAX);
      673 +                dword(mdoc, line, la, p, DELIM_MAX, 1);
 640  674  
 641  675                  /*
 642  676                   * If we encounter end-of-sentence symbols, then trigger
 643  677                   * the double-space.
 644  678                   *
 645  679                   * XXX: it's easy to allow this to propagate outward to
 646  680                   * the last symbol, such that `. )' will cause the
 647  681                   * correct double-spacing.  However, (1) groff isn't
 648  682                   * smart enough to do this and (2) it would require
 649  683                   * knowing which symbols break this behaviour, for
 650  684                   * example, `.  ;' shouldn't propagate the double-space.
 651  685                   */
 652  686                  if (mandoc_eos(p, strlen(p), 0))
 653      -                        m->last->flags |= MDOC_EOS;
      687 +                        mdoc->last->flags |= MDOC_EOS;
 654  688          }
 655  689  
 656  690          return(1);
 657  691  }
 658  692  
 659  693  
 660  694  /*
 661  695   * Close out block partial/full explicit.  
 662  696   */
 663  697  static int
↓ open down ↓ 1 lines elided ↑ open up ↑
 665  699  {
 666  700          struct mdoc_node *body;         /* Our own body. */
 667  701          struct mdoc_node *later;        /* A sub-block starting later. */
 668  702          struct mdoc_node *n;            /* For searching backwards. */
 669  703  
 670  704          int              j, lastarg, maxargs, flushed, nl;
 671  705          enum margserr    ac;
 672  706          enum mdoct       atok, ntok;
 673  707          char            *p;
 674  708  
 675      -        nl = MDOC_NEWLINE & m->flags;
      709 +        nl = MDOC_NEWLINE & mdoc->flags;
 676  710  
 677  711          switch (tok) {
 678  712          case (MDOC_Ec):
 679  713                  maxargs = 1;
 680  714                  break;
      715 +        case (MDOC_Ek):
      716 +                mdoc->flags &= ~MDOC_KEEP;
 681  717          default:
 682  718                  maxargs = 0;
 683  719                  break;
 684  720          }
 685  721  
 686  722          /*
 687  723           * Search backwards for beginnings of blocks,
 688  724           * both of our own and of pending sub-blocks.
 689  725           */
 690  726          atok = rew_alt(tok);
 691  727          body = later = NULL;
 692      -        for (n = m->last; n; n = n->parent) {
      728 +        for (n = mdoc->last; n; n = n->parent) {
 693  729                  if (MDOC_VALID & n->flags)
 694  730                          continue;
 695  731  
 696  732                  /* Remember the start of our own body. */
 697  733                  if (MDOC_BODY == n->type && atok == n->tok) {
 698  734                          if (ENDBODY_NOT == n->end)
 699  735                                  body = n;
 700  736                          continue;
 701  737                  }
 702  738  
↓ open down ↓ 8 lines elided ↑ open up ↑
 711  747                           * just proceed to closing out.
 712  748                           */
 713  749                          if (NULL == later)
 714  750                                  break;
 715  751  
 716  752                          /* 
 717  753                           * When there is a pending sub block,
 718  754                           * postpone closing out the current block
 719  755                           * until the rew_sub() closing out the sub-block.
 720  756                           */
 721      -                        make_pending(later, tok, m, line, ppos);
      757 +                        make_pending(later, tok, mdoc, line, ppos);
 722  758  
 723  759                          /*
 724  760                           * Mark the place where the formatting - but not
 725  761                           * the scope - of the current block ends.
 726  762                           */
 727      -                        if ( ! mdoc_endbody_alloc(m, line, ppos,
      763 +                        if ( ! mdoc_endbody_alloc(mdoc, line, ppos,
 728  764                              atok, body, ENDBODY_SPACE))
 729  765                                  return(0);
 730  766                          break;
 731  767                  }
 732  768  
 733  769                  /*
 734  770                   * When finding an open sub block, remember the last
 735  771                   * open explicit block, or, in case there are only
 736  772                   * implicit ones, the first open implicit block.
 737  773                   */
 738  774                  if (later &&
 739  775                      MDOC_EXPLICIT & mdoc_macros[later->tok].flags)
 740  776                          continue;
 741      -                if (MDOC_CALLABLE & mdoc_macros[n->tok].flags)
      777 +                if (MDOC_It != n->tok)
 742  778                          later = n;
 743  779          }
 744  780  
 745  781          if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
 746  782                  /* FIXME: do this in validate */
 747  783                  if (buf[*pos]) 
 748      -                        mdoc_pmsg(m, line, ppos, MANDOCERR_ARGSLOST);
      784 +                        mdoc_pmsg(mdoc, line, ppos, MANDOCERR_ARGSLOST);
 749  785  
 750      -                if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
      786 +                if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
 751  787                          return(0);
 752      -                return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
      788 +                return(rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos));
 753  789          }
 754  790  
 755      -        if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
      791 +        if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
 756  792                  return(0);
 757  793  
 758  794          if (NULL == later && maxargs > 0) 
 759      -                if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
      795 +                if ( ! mdoc_tail_alloc(mdoc, line, ppos, rew_alt(tok)))
 760  796                          return(0);
 761  797  
 762  798          for (flushed = j = 0; ; j++) {
 763  799                  lastarg = *pos;
 764  800  
 765  801                  if (j == maxargs && ! flushed) {
 766      -                        if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
      802 +                        if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
 767  803                                  return(0);
 768  804                          flushed = 1;
 769  805                  }
 770  806  
 771      -                ac = mdoc_args(m, line, pos, buf, tok, &p);
      807 +                ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
 772  808  
 773  809                  if (ARGS_ERROR == ac)
 774  810                          return(0);
 775  811                  if (ARGS_PUNCT == ac)
 776  812                          break;
 777  813                  if (ARGS_EOLN == ac)
 778  814                          break;
 779  815  
 780  816                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 781  817  
 782  818                  if (MDOC_MAX == ntok) {
 783      -                        if ( ! dword(m, line, lastarg, p, DELIM_MAX))
      819 +                        if ( ! dword(mdoc, line, lastarg, p, DELIM_MAX,
      820 +                            MDOC_JOIN & mdoc_macros[tok].flags))
 784  821                                  return(0);
 785  822                          continue;
 786  823                  }
 787  824  
 788  825                  if ( ! flushed) {
 789      -                        if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
      826 +                        if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
 790  827                                  return(0);
 791  828                          flushed = 1;
 792  829                  }
 793      -                if ( ! mdoc_macro(m, ntok, line, lastarg, pos, buf))
      830 +
      831 +                mdoc->flags &= ~MDOC_NEWLINE;
      832 +
      833 +                if ( ! mdoc_macro(mdoc, ntok, line, lastarg, pos, buf))
 794  834                          return(0);
 795  835                  break;
 796  836          }
 797  837  
 798      -        if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
      838 +        if ( ! flushed && ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
 799  839                  return(0);
 800  840  
 801  841          if ( ! nl)
 802  842                  return(1);
 803      -        return(append_delims(m, line, pos, buf));
      843 +        return(append_delims(mdoc, line, pos, buf));
 804  844  }
 805  845  
 806  846  
 807  847  static int
 808  848  in_line(MACRO_PROT_ARGS)
 809  849  {
 810  850          int              la, scope, cnt, nc, nl;
 811  851          enum margverr    av;
 812  852          enum mdoct       ntok;
 813  853          enum margserr    ac;
 814  854          enum mdelim      d;
 815  855          struct mdoc_arg *arg;
 816  856          char            *p;
 817  857  
 818      -        nl = MDOC_NEWLINE & m->flags;
      858 +        nl = MDOC_NEWLINE & mdoc->flags;
 819  859  
 820  860          /*
 821  861           * Whether we allow ignored elements (those without content,
 822  862           * usually because of reserved words) to squeak by.
 823  863           */
 824  864  
 825  865          switch (tok) {
 826  866          case (MDOC_An):
 827  867                  /* FALLTHROUGH */
 828  868          case (MDOC_Ar):
↓ open down ↓ 7 lines elided ↑ open up ↑
 836  876          case (MDOC_Pa):
 837  877                  nc = 1;
 838  878                  break;
 839  879          default:
 840  880                  nc = 0;
 841  881                  break;
 842  882          }
 843  883  
 844  884          for (arg = NULL;; ) {
 845  885                  la = *pos;
 846      -                av = mdoc_argv(m, line, tok, &arg, pos, buf);
      886 +                av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
 847  887  
 848  888                  if (ARGV_WORD == av) {
 849  889                          *pos = la;
 850  890                          break;
 851  891                  } 
 852  892                  if (ARGV_EOLN == av)
 853  893                          break;
 854  894                  if (ARGV_ARG == av)
 855  895                          continue;
 856  896  
 857  897                  mdoc_argv_free(arg);
 858  898                  return(0);
 859  899          }
 860  900  
 861  901          for (cnt = scope = 0;; ) {
 862  902                  la = *pos;
 863      -                ac = mdoc_args(m, line, pos, buf, tok, &p);
      903 +                ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
 864  904  
 865  905                  if (ARGS_ERROR == ac)
 866  906                          return(0);
 867  907                  if (ARGS_EOLN == ac)
 868  908                          break;
 869  909                  if (ARGS_PUNCT == ac)
 870  910                          break;
 871  911  
 872  912                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 873  913  
 874  914                  /* 
 875  915                   * In this case, we've located a submacro and must
 876  916                   * execute it.  Close out scope, if open.  If no
 877  917                   * elements have been generated, either create one (nc)
 878  918                   * or raise a warning.
 879  919                   */
 880  920  
 881  921                  if (MDOC_MAX != ntok) {
 882      -                        if (scope && ! rew_elem(m, tok))
      922 +                        if (scope && ! rew_elem(mdoc, tok))
 883  923                                  return(0);
 884  924                          if (nc && 0 == cnt) {
 885      -                                if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
      925 +                                if ( ! mdoc_elem_alloc(mdoc, line,
      926 +                                                ppos, tok, arg))
 886  927                                          return(0);
 887      -                                if ( ! rew_last(m, m->last))
      928 +                                if ( ! rew_last(mdoc, mdoc->last))
 888  929                                          return(0);
 889  930                          } else if ( ! nc && 0 == cnt) {
 890  931                                  mdoc_argv_free(arg);
 891      -                                mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY);
      932 +                                mdoc_pmsg(mdoc, line, ppos,
      933 +                                        MANDOCERR_MACROEMPTY);
 892  934                          }
 893  935  
 894      -                        if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
      936 +                        if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
 895  937                                  return(0);
 896  938                          if ( ! nl)
 897  939                                  return(1);
 898      -                        return(append_delims(m, line, pos, buf));
      940 +                        return(append_delims(mdoc, line, pos, buf));
 899  941                  } 
 900  942  
 901  943                  /* 
 902  944                   * Non-quote-enclosed punctuation.  Set up our scope, if
 903  945                   * a word; rewind the scope, if a delimiter; then append
 904  946                   * the word. 
 905  947                   */
 906  948  
 907  949                  d = ARGS_QWORD == ac ? DELIM_NONE : mdoc_isdelim(p);
 908  950  
↓ open down ↓ 1 lines elided ↑ open up ↑
 910  952                          /*
 911  953                           * If we encounter closing punctuation, no word
 912  954                           * has been omitted, no scope is open, and we're
 913  955                           * allowed to have an empty element, then start
 914  956                           * a new scope.  `Ar', `Fl', and `Li', only do
 915  957                           * this once per invocation.  There may be more
 916  958                           * of these (all of them?).
 917  959                           */
 918  960                          if (0 == cnt && (nc || MDOC_Li == tok) && 
 919  961                                          DELIM_CLOSE == d && ! scope) {
 920      -                                if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
      962 +                                if ( ! mdoc_elem_alloc(mdoc, line,
      963 +                                                ppos, tok, arg))
 921  964                                          return(0);
 922  965                                  if (MDOC_Ar == tok || MDOC_Li == tok || 
 923  966                                                  MDOC_Fl == tok)
 924  967                                          cnt++;
 925  968                                  scope = 1;
 926  969                          }
 927  970                          /*
 928  971                           * Close out our scope, if one is open, before
 929  972                           * any punctuation.
 930  973                           */
 931      -                        if (scope && ! rew_elem(m, tok))
      974 +                        if (scope && ! rew_elem(mdoc, tok))
 932  975                                  return(0);
 933  976                          scope = 0;
 934  977                  } else if ( ! scope) {
 935      -                        if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
      978 +                        if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
 936  979                                  return(0);
 937  980                          scope = 1;
 938  981                  }
 939  982  
 940  983                  if (DELIM_NONE == d)
 941  984                          cnt++;
 942  985  
 943      -                if ( ! dword(m, line, la, p, d))
      986 +                if ( ! dword(mdoc, line, la, p, d,
      987 +                    MDOC_JOIN & mdoc_macros[tok].flags))
 944  988                          return(0);
 945  989  
 946  990                  /*
 947  991                   * `Fl' macros have their scope re-opened with each new
 948  992                   * word so that the `-' can be added to each one without
 949  993                   * having to parse out spaces.
 950  994                   */
 951  995                  if (scope && MDOC_Fl == tok) {
 952      -                        if ( ! rew_elem(m, tok))
      996 +                        if ( ! rew_elem(mdoc, tok))
 953  997                                  return(0);
 954  998                          scope = 0;
 955  999                  }
 956 1000          }
 957 1001  
 958      -        if (scope && ! rew_elem(m, tok))
     1002 +        if (scope && ! rew_elem(mdoc, tok))
 959 1003                  return(0);
 960 1004  
 961 1005          /*
 962 1006           * If no elements have been collected and we're allowed to have
 963 1007           * empties (nc), open a scope and close it out.  Otherwise,
 964 1008           * raise a warning.
 965 1009           */
 966 1010  
 967 1011          if (nc && 0 == cnt) {
 968      -                if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
     1012 +                if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
 969 1013                          return(0);
 970      -                if ( ! rew_last(m, m->last))
     1014 +                if ( ! rew_last(mdoc, mdoc->last))
 971 1015                          return(0);
 972 1016          } else if ( ! nc && 0 == cnt) {
 973 1017                  mdoc_argv_free(arg);
 974      -                mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY);
     1018 +                mdoc_pmsg(mdoc, line, ppos, MANDOCERR_MACROEMPTY);
 975 1019          }
 976 1020  
 977 1021          if ( ! nl)
 978 1022                  return(1);
 979      -        return(append_delims(m, line, pos, buf));
     1023 +        return(append_delims(mdoc, line, pos, buf));
 980 1024  }
 981 1025  
 982 1026  
 983 1027  static int
 984 1028  blk_full(MACRO_PROT_ARGS)
 985 1029  {
 986 1030          int               la, nl, nparsed;
 987 1031          struct mdoc_arg  *arg;
 988 1032          struct mdoc_node *head; /* save of head macro */
 989 1033          struct mdoc_node *body; /* save of body macro */
 990 1034          struct mdoc_node *n;
 991 1035          enum mdoc_type    mtt;
 992 1036          enum mdoct        ntok;
 993 1037          enum margserr     ac, lac;
 994 1038          enum margverr     av;
 995 1039          char             *p;
 996 1040  
 997      -        nl = MDOC_NEWLINE & m->flags;
     1041 +        nl = MDOC_NEWLINE & mdoc->flags;
 998 1042  
 999 1043          /* Close out prior implicit scope. */
1000 1044  
1001 1045          if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
1002      -                if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
     1046 +                if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
1003 1047                          return(0);
1004      -                if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
     1048 +                if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
1005 1049                          return(0);
1006 1050          }
1007 1051  
1008 1052          /*
1009 1053           * This routine accommodates implicitly- and explicitly-scoped
1010 1054           * macro openings.  Implicit ones first close out prior scope
1011 1055           * (seen above).  Delay opening the head until necessary to
1012 1056           * allow leading punctuation to print.  Special consideration
1013 1057           * for `It -column', which has phrase-part syntax instead of
1014 1058           * regular child nodes.
1015 1059           */
1016 1060  
1017 1061          for (arg = NULL;; ) {
1018 1062                  la = *pos;
1019      -                av = mdoc_argv(m, line, tok, &arg, pos, buf);
     1063 +                av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1020 1064  
1021 1065                  if (ARGV_WORD == av) {
1022 1066                          *pos = la;
1023 1067                          break;
1024 1068                  } 
1025 1069  
1026 1070                  if (ARGV_EOLN == av)
1027 1071                          break;
1028 1072                  if (ARGV_ARG == av)
1029 1073                          continue;
1030 1074  
1031 1075                  mdoc_argv_free(arg);
1032 1076                  return(0);
1033 1077          }
1034 1078  
1035      -        if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
     1079 +        if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg))
1036 1080                  return(0);
1037 1081  
1038 1082          head = body = NULL;
1039 1083  
1040 1084          /*
1041 1085           * Exception: Heads of `It' macros in `-diag' lists are not
1042 1086           * parsed, even though `It' macros in general are parsed.
1043 1087           */
1044 1088          nparsed = MDOC_It == tok &&
1045      -                MDOC_Bl == m->last->parent->tok &&
1046      -                LIST_diag == m->last->parent->norm->Bl.type;
     1089 +                MDOC_Bl == mdoc->last->parent->tok &&
     1090 +                LIST_diag == mdoc->last->parent->norm->Bl.type;
1047 1091  
1048 1092          /*
1049 1093           * The `Nd' macro has all arguments in its body: it's a hybrid
1050 1094           * of block partial-explicit and full-implicit.  Stupid.
1051 1095           */
1052 1096  
1053 1097          if (MDOC_Nd == tok) {
1054      -                if ( ! mdoc_head_alloc(m, line, ppos, tok))
     1098 +                if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1055 1099                          return(0);
1056      -                head = m->last;
1057      -                if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
     1100 +                head = mdoc->last;
     1101 +                if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
1058 1102                          return(0);
1059      -                if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1103 +                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1060 1104                          return(0);
1061      -                body = m->last;
1062      -        } 
     1105 +                body = mdoc->last;
     1106 +        }
1063 1107  
     1108 +        if (MDOC_Bk == tok)
     1109 +                mdoc->flags |= MDOC_KEEP;
     1110 +
1064 1111          ac = ARGS_ERROR;
1065 1112  
1066 1113          for ( ; ; ) {
1067 1114                  la = *pos;
1068 1115                  /* Initialise last-phrase-type with ARGS_PEND. */
1069 1116                  lac = ARGS_ERROR == ac ? ARGS_PEND : ac;
1070      -                ac = mdoc_args(m, line, pos, buf, tok, &p);
     1117 +                ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1071 1118  
1072 1119                  if (ARGS_PUNCT == ac)
1073 1120                          break;
1074 1121  
1075 1122                  if (ARGS_ERROR == ac)
1076 1123                          return(0);
1077 1124  
1078 1125                  if (ARGS_EOLN == ac) {
1079 1126                          if (ARGS_PPHRASE != lac && ARGS_PHRASE != lac)
1080 1127                                  break;
1081 1128                          /*
1082 1129                           * This is necessary: if the last token on a
1083 1130                           * line is a `Ta' or tab, then we'll get
1084 1131                           * ARGS_EOLN, so we must be smart enough to
1085 1132                           * reopen our scope if the last parse was a
1086 1133                           * phrase or partial phrase.
1087 1134                           */
1088      -                        if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
     1135 +                        if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
1089 1136                                  return(0);
1090      -                        if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1137 +                        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1091 1138                                  return(0);
1092      -                        body = m->last;
     1139 +                        body = mdoc->last;
1093 1140                          break;
1094 1141                  }
1095 1142  
1096 1143                  /* 
1097 1144                   * Emit leading punctuation (i.e., punctuation before
1098 1145                   * the MDOC_HEAD) for non-phrase types.
1099 1146                   */
1100 1147  
1101 1148                  if (NULL == head && 
1102 1149                                  ARGS_PEND != ac &&
1103 1150                                  ARGS_PHRASE != ac &&
1104 1151                                  ARGS_PPHRASE != ac &&
1105 1152                                  ARGS_QWORD != ac &&
1106 1153                                  DELIM_OPEN == mdoc_isdelim(p)) {
1107      -                        if ( ! dword(m, line, la, p, DELIM_OPEN))
     1154 +                        if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
1108 1155                                  return(0);
1109 1156                          continue;
1110 1157                  }
1111 1158  
1112 1159                  /* Open a head if one hasn't been opened. */
1113 1160  
1114 1161                  if (NULL == head) {
1115      -                        if ( ! mdoc_head_alloc(m, line, ppos, tok))
     1162 +                        if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1116 1163                                  return(0);
1117      -                        head = m->last;
     1164 +                        head = mdoc->last;
1118 1165                  }
1119 1166  
1120 1167                  if (ARGS_PHRASE == ac || 
1121 1168                                  ARGS_PEND == ac ||
1122 1169                                  ARGS_PPHRASE == ac) {
1123 1170                          /*
1124 1171                           * If we haven't opened a body yet, rewind the
1125 1172                           * head; if we have, rewind that instead.
1126 1173                           */
1127 1174  
1128 1175                          mtt = body ? MDOC_BODY : MDOC_HEAD;
1129      -                        if ( ! rew_sub(mtt, m, tok, line, ppos))
     1176 +                        if ( ! rew_sub(mtt, mdoc, tok, line, ppos))
1130 1177                                  return(0);
1131 1178                          
1132 1179                          /* Then allocate our body context. */
1133 1180  
1134      -                        if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1181 +                        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1135 1182                                  return(0);
1136      -                        body = m->last;
     1183 +                        body = mdoc->last;
1137 1184  
1138 1185                          /*
1139 1186                           * Process phrases: set whether we're in a
1140 1187                           * partial-phrase (this effects line handling)
1141 1188                           * then call down into the phrase parser.
1142 1189                           */
1143 1190  
1144 1191                          if (ARGS_PPHRASE == ac)
1145      -                                m->flags |= MDOC_PPHRASE;
     1192 +                                mdoc->flags |= MDOC_PPHRASE;
1146 1193                          if (ARGS_PEND == ac && ARGS_PPHRASE == lac)
1147      -                                m->flags |= MDOC_PPHRASE;
     1194 +                                mdoc->flags |= MDOC_PPHRASE;
1148 1195  
1149      -                        if ( ! phrase(m, line, la, buf))
     1196 +                        if ( ! phrase(mdoc, line, la, buf))
1150 1197                                  return(0);
1151 1198  
1152      -                        m->flags &= ~MDOC_PPHRASE;
     1199 +                        mdoc->flags &= ~MDOC_PPHRASE;
1153 1200                          continue;
1154 1201                  }
1155 1202  
1156 1203                  ntok = nparsed || ARGS_QWORD == ac ? 
1157 1204                          MDOC_MAX : lookup(tok, p);
1158 1205  
1159 1206                  if (MDOC_MAX == ntok) {
1160      -                        if ( ! dword(m, line, la, p, DELIM_MAX))
     1207 +                        if ( ! dword(mdoc, line, la, p, DELIM_MAX,
     1208 +                            MDOC_JOIN & mdoc_macros[tok].flags))
1161 1209                                  return(0);
1162 1210                          continue;
1163 1211                  }
1164 1212  
1165      -                if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
     1213 +                if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1166 1214                          return(0);
1167 1215                  break;
1168 1216          }
1169 1217  
1170 1218          if (NULL == head) {
1171      -                if ( ! mdoc_head_alloc(m, line, ppos, tok))
     1219 +                if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1172 1220                          return(0);
1173      -                head = m->last;
     1221 +                head = mdoc->last;
1174 1222          }
1175 1223          
1176      -        if (nl && ! append_delims(m, line, pos, buf))
     1224 +        if (nl && ! append_delims(mdoc, line, pos, buf))
1177 1225                  return(0);
1178 1226  
1179 1227          /* If we've already opened our body, exit now. */
1180 1228  
1181 1229          if (NULL != body)
1182 1230                  goto out;
1183 1231  
1184 1232          /*
1185 1233           * If there is an open (i.e., unvalidated) sub-block requiring
1186 1234           * explicit close-out, postpone switching the current block from
1187 1235           * head to body until the rew_sub() call closing out that
1188 1236           * sub-block.
1189 1237           */
1190      -        for (n = m->last; n && n != head; n = n->parent) {
     1238 +        for (n = mdoc->last; n && n != head; n = n->parent) {
1191 1239                  if (MDOC_BLOCK == n->type && 
1192 1240                                  MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1193 1241                                  ! (MDOC_VALID & n->flags)) {
1194 1242                          n->pending = head;
1195 1243                          return(1);
1196 1244                  }
1197 1245          }
1198 1246  
1199 1247          /* Close out scopes to remain in a consistent state. */
1200 1248  
1201      -        if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
     1249 +        if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
1202 1250                  return(0);
1203      -        if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1251 +        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1204 1252                  return(0);
1205 1253  
1206 1254  out:
1207      -        if ( ! (MDOC_FREECOL & m->flags))
     1255 +        if ( ! (MDOC_FREECOL & mdoc->flags))
1208 1256                  return(1);
1209 1257  
1210      -        if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
     1258 +        if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
1211 1259                  return(0);
1212      -        if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
     1260 +        if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
1213 1261                  return(0);
1214 1262  
1215      -        m->flags &= ~MDOC_FREECOL;
     1263 +        mdoc->flags &= ~MDOC_FREECOL;
1216 1264          return(1);
1217 1265  }
1218 1266  
1219 1267  
1220 1268  static int
1221 1269  blk_part_imp(MACRO_PROT_ARGS)
1222 1270  {
1223 1271          int               la, nl;
1224 1272          enum mdoct        ntok;
1225 1273          enum margserr     ac;
1226 1274          char             *p;
1227 1275          struct mdoc_node *blk; /* saved block context */
1228 1276          struct mdoc_node *body; /* saved body context */
1229 1277          struct mdoc_node *n;
1230 1278  
1231      -        nl = MDOC_NEWLINE & m->flags;
     1279 +        nl = MDOC_NEWLINE & mdoc->flags;
1232 1280  
1233 1281          /*
1234 1282           * A macro that spans to the end of the line.  This is generally
1235 1283           * (but not necessarily) called as the first macro.  The block
1236 1284           * has a head as the immediate child, which is always empty,
1237 1285           * followed by zero or more opening punctuation nodes, then the
1238 1286           * body (which may be empty, depending on the macro), then zero
1239 1287           * or more closing punctuation nodes.
1240 1288           */
1241 1289  
1242      -        if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
     1290 +        if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
1243 1291                  return(0);
1244 1292  
1245      -        blk = m->last;
     1293 +        blk = mdoc->last;
1246 1294  
1247      -        if ( ! mdoc_head_alloc(m, line, ppos, tok))
     1295 +        if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1248 1296                  return(0);
1249      -        if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
     1297 +        if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
1250 1298                  return(0);
1251 1299  
1252 1300          /*
1253 1301           * Open the body scope "on-demand", that is, after we've
1254 1302           * processed all our the leading delimiters (open parenthesis,
1255 1303           * etc.).
1256 1304           */
1257 1305  
1258 1306          for (body = NULL; ; ) {
1259 1307                  la = *pos;
1260      -                ac = mdoc_args(m, line, pos, buf, tok, &p);
     1308 +                ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1261 1309  
1262 1310                  if (ARGS_ERROR == ac)
1263 1311                          return(0);
1264 1312                  if (ARGS_EOLN == ac)
1265 1313                          break;
1266 1314                  if (ARGS_PUNCT == ac)
1267 1315                          break;
1268 1316  
1269 1317                  if (NULL == body && ARGS_QWORD != ac &&
1270 1318                                  DELIM_OPEN == mdoc_isdelim(p)) {
1271      -                        if ( ! dword(m, line, la, p, DELIM_OPEN))
     1319 +                        if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
1272 1320                                  return(0);
1273 1321                          continue;
1274      -                } 
     1322 +                }
1275 1323  
1276 1324                  if (NULL == body) {
1277      -                       if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1325 +                       if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1278 1326                                 return(0);
1279      -                        body = m->last;
     1327 +                        body = mdoc->last;
1280 1328                  }
1281 1329  
1282 1330                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1283 1331  
1284 1332                  if (MDOC_MAX == ntok) {
1285      -                        if ( ! dword(m, line, la, p, DELIM_MAX))
     1333 +                        if ( ! dword(mdoc, line, la, p, DELIM_MAX,
     1334 +                            MDOC_JOIN & mdoc_macros[tok].flags))
1286 1335                                  return(0);
1287 1336                          continue;
1288 1337                  }
1289 1338  
1290      -                if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
     1339 +                if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1291 1340                          return(0);
1292 1341                  break;
1293 1342          }
1294 1343  
1295 1344          /* Clean-ups to leave in a consistent state. */
1296 1345  
1297 1346          if (NULL == body) {
1298      -                if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1347 +                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1299 1348                          return(0);
1300      -                body = m->last;
     1349 +                body = mdoc->last;
1301 1350          }
1302 1351  
1303 1352          for (n = body->child; n && n->next; n = n->next)
1304 1353                  /* Do nothing. */ ;
1305 1354          
1306 1355          /* 
1307 1356           * End of sentence spacing: if the last node is a text node and
1308 1357           * has a trailing period, then mark it as being end-of-sentence.
1309 1358           */
1310 1359  
↓ open down ↓ 6 lines elided ↑ open up ↑
1317 1366          if (n && (MDOC_EOS & n->flags)) {
1318 1367                  body->flags |= MDOC_EOS;
1319 1368                  body->parent->flags |= MDOC_EOS;
1320 1369          }
1321 1370  
1322 1371          /*
1323 1372           * If there is an open sub-block requiring explicit close-out,
1324 1373           * postpone closing out the current block
1325 1374           * until the rew_sub() call closing out the sub-block.
1326 1375           */
1327      -        for (n = m->last; n && n != body && n != blk->parent; n = n->parent) {
     1376 +        for (n = mdoc->last; n && n != body && n != blk->parent;
     1377 +                        n = n->parent) {
1328 1378                  if (MDOC_BLOCK == n->type &&
1329 1379                      MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1330 1380                      ! (MDOC_VALID & n->flags)) {
1331      -                        make_pending(n, tok, m, line, ppos);
1332      -                        if ( ! mdoc_endbody_alloc(m, line, ppos,
     1381 +                        make_pending(n, tok, mdoc, line, ppos);
     1382 +                        if ( ! mdoc_endbody_alloc(mdoc, line, ppos,
1333 1383                              tok, body, ENDBODY_NOSPACE))
1334 1384                                  return(0);
1335 1385                          return(1);
1336 1386                  }
1337 1387          }
1338 1388  
1339 1389          /* 
1340 1390           * If we can't rewind to our body, then our scope has already
1341 1391           * been closed by another macro (like `Oc' closing `Op').  This
1342 1392           * is ugly behaviour nodding its head to OpenBSD's overwhelming
1343 1393           * crufty use of `Op' breakage.
1344 1394           */
1345 1395          if (n != body)
1346      -                mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos, 
     1396 +                mandoc_vmsg(MANDOCERR_SCOPENEST, mdoc->parse, line, ppos, 
1347 1397                                  "%s broken", mdoc_macronames[tok]);
1348 1398  
1349      -        if (n && ! rew_sub(MDOC_BODY, m, tok, line, ppos))
     1399 +        if (n && ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
1350 1400                  return(0);
1351 1401  
1352 1402          /* Standard appending of delimiters. */
1353 1403  
1354      -        if (nl && ! append_delims(m, line, pos, buf))
     1404 +        if (nl && ! append_delims(mdoc, line, pos, buf))
1355 1405                  return(0);
1356 1406  
1357 1407          /* Rewind scope, if applicable. */
1358 1408  
1359      -        if (n && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
     1409 +        if (n && ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
1360 1410                  return(0);
1361 1411  
     1412 +        /* Move trailing .Ns out of scope. */
     1413 +
     1414 +        for (n = body->child; n && n->next; n = n->next)
     1415 +                /* Do nothing. */ ;
     1416 +        if (n && MDOC_Ns == n->tok)
     1417 +                mdoc_node_relink(mdoc, n);
     1418 +
1362 1419          return(1);
1363 1420  }
1364 1421  
1365 1422  
1366 1423  static int
1367 1424  blk_part_exp(MACRO_PROT_ARGS)
1368 1425  {
1369 1426          int               la, nl;
1370 1427          enum margserr     ac;
1371 1428          struct mdoc_node *head; /* keep track of head */
1372 1429          struct mdoc_node *body; /* keep track of body */
1373 1430          char             *p;
1374 1431          enum mdoct        ntok;
1375 1432  
1376      -        nl = MDOC_NEWLINE & m->flags;
     1433 +        nl = MDOC_NEWLINE & mdoc->flags;
1377 1434  
1378 1435          /*
1379 1436           * The opening of an explicit macro having zero or more leading
1380 1437           * punctuation nodes; a head with optional single element (the
1381 1438           * case of `Eo'); and a body that may be empty.
1382 1439           */
1383 1440  
1384      -        if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
     1441 +        if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
1385 1442                  return(0); 
1386 1443  
1387 1444          for (head = body = NULL; ; ) {
1388 1445                  la = *pos;
1389      -                ac = mdoc_args(m, line, pos, buf, tok, &p);
     1446 +                ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1390 1447  
1391 1448                  if (ARGS_ERROR == ac)
1392 1449                          return(0);
1393 1450                  if (ARGS_PUNCT == ac)
1394 1451                          break;
1395 1452                  if (ARGS_EOLN == ac)
1396 1453                          break;
1397 1454  
1398 1455                  /* Flush out leading punctuation. */
1399 1456  
1400 1457                  if (NULL == head && ARGS_QWORD != ac &&
1401 1458                                  DELIM_OPEN == mdoc_isdelim(p)) {
1402 1459                          assert(NULL == body);
1403      -                        if ( ! dword(m, line, la, p, DELIM_OPEN))
     1460 +                        if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
1404 1461                                  return(0);
1405 1462                          continue;
1406      -                } 
     1463 +                }
1407 1464  
1408 1465                  if (NULL == head) {
1409 1466                          assert(NULL == body);
1410      -                        if ( ! mdoc_head_alloc(m, line, ppos, tok))
     1467 +                        if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1411 1468                                  return(0);
1412      -                        head = m->last;
     1469 +                        head = mdoc->last;
1413 1470                  }
1414 1471  
1415 1472                  /*
1416 1473                   * `Eo' gobbles any data into the head, but most other
1417 1474                   * macros just immediately close out and begin the body.
1418 1475                   */
1419 1476  
1420 1477                  if (NULL == body) {
1421 1478                          assert(head);
1422 1479                          /* No check whether it's a macro! */
1423 1480                          if (MDOC_Eo == tok)
1424      -                                if ( ! dword(m, line, la, p, DELIM_MAX))
     1481 +                                if ( ! dword(mdoc, line, la, p, DELIM_MAX, 0))
1425 1482                                          return(0);
1426 1483  
1427      -                        if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
     1484 +                        if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
1428 1485                                  return(0);
1429      -                        if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1486 +                        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1430 1487                                  return(0);
1431      -                        body = m->last;
     1488 +                        body = mdoc->last;
1432 1489  
1433 1490                          if (MDOC_Eo == tok)
1434 1491                                  continue;
1435 1492                  }
1436 1493  
1437 1494                  assert(NULL != head && NULL != body);
1438 1495  
1439 1496                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1440 1497  
1441 1498                  if (MDOC_MAX == ntok) {
1442      -                        if ( ! dword(m, line, la, p, DELIM_MAX))
     1499 +                        if ( ! dword(mdoc, line, la, p, DELIM_MAX,
     1500 +                            MDOC_JOIN & mdoc_macros[tok].flags))
1443 1501                                  return(0);
1444 1502                          continue;
1445 1503                  }
1446 1504  
1447      -                if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
     1505 +                if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1448 1506                          return(0);
1449 1507                  break;
1450 1508          }
1451 1509  
1452 1510          /* Clean-up to leave in a consistent state. */
1453 1511  
1454 1512          if (NULL == head)
1455      -                if ( ! mdoc_head_alloc(m, line, ppos, tok))
     1513 +                if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1456 1514                          return(0);
1457 1515  
1458 1516          if (NULL == body) {
1459      -                if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
     1517 +                if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
1460 1518                          return(0);
1461      -                if ( ! mdoc_body_alloc(m, line, ppos, tok))
     1519 +                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1462 1520                          return(0);
1463 1521          }
1464 1522  
1465 1523          /* Standard appending of delimiters. */
1466 1524  
1467 1525          if ( ! nl)
1468 1526                  return(1);
1469      -        return(append_delims(m, line, pos, buf));
     1527 +        return(append_delims(mdoc, line, pos, buf));
1470 1528  }
1471 1529  
1472 1530  
1473 1531  /* ARGSUSED */
1474 1532  static int
1475 1533  in_line_argn(MACRO_PROT_ARGS)
1476 1534  {
1477 1535          int              la, flushed, j, maxargs, nl;
1478 1536          enum margserr    ac;
1479 1537          enum margverr    av;
1480 1538          struct mdoc_arg *arg;
1481 1539          char            *p;
1482 1540          enum mdoct       ntok;
1483 1541  
1484      -        nl = MDOC_NEWLINE & m->flags;
     1542 +        nl = MDOC_NEWLINE & mdoc->flags;
1485 1543  
1486 1544          /*
1487 1545           * A line macro that has a fixed number of arguments (maxargs).
1488 1546           * Only open the scope once the first non-leading-punctuation is
1489 1547           * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then
1490 1548           * keep it open until the maximum number of arguments are
1491 1549           * exhausted.
1492 1550           */
1493 1551  
1494 1552          switch (tok) {
↓ open down ↓ 11 lines elided ↑ open up ↑
1506 1564          case (MDOC_Xr):
1507 1565                  maxargs = 2;
1508 1566                  break;
1509 1567          default:
1510 1568                  maxargs = 1;
1511 1569                  break;
1512 1570          }
1513 1571  
1514 1572          for (arg = NULL; ; ) {
1515 1573                  la = *pos;
1516      -                av = mdoc_argv(m, line, tok, &arg, pos, buf);
     1574 +                av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1517 1575  
1518 1576                  if (ARGV_WORD == av) {
1519 1577                          *pos = la;
1520 1578                          break;
1521 1579                  } 
1522 1580  
1523 1581                  if (ARGV_EOLN == av)
1524 1582                          break;
1525 1583                  if (ARGV_ARG == av)
1526 1584                          continue;
1527 1585  
1528 1586                  mdoc_argv_free(arg);
1529 1587                  return(0);
1530 1588          }
1531 1589  
1532 1590          for (flushed = j = 0; ; ) {
1533 1591                  la = *pos;
1534      -                ac = mdoc_args(m, line, pos, buf, tok, &p);
     1592 +                ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1535 1593  
1536 1594                  if (ARGS_ERROR == ac)
1537 1595                          return(0);
1538 1596                  if (ARGS_PUNCT == ac)
1539 1597                          break;
1540 1598                  if (ARGS_EOLN == ac)
1541 1599                          break;
1542 1600  
1543 1601                  if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 
1544 1602                                  ARGS_QWORD != ac && 0 == j && 
1545 1603                                  DELIM_OPEN == mdoc_isdelim(p)) {
1546      -                        if ( ! dword(m, line, la, p, DELIM_OPEN))
     1604 +                        if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
1547 1605                                  return(0);
1548 1606                          continue;
1549 1607                  } else if (0 == j)
1550      -                       if ( ! mdoc_elem_alloc(m, line, la, tok, arg))
     1608 +                       if ( ! mdoc_elem_alloc(mdoc, line, la, tok, arg))
1551 1609                                 return(0);
1552 1610  
1553 1611                  if (j == maxargs && ! flushed) {
1554      -                        if ( ! rew_elem(m, tok))
     1612 +                        if ( ! rew_elem(mdoc, tok))
1555 1613                                  return(0);
1556 1614                          flushed = 1;
1557 1615                  }
1558 1616  
1559 1617                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1560 1618  
1561 1619                  if (MDOC_MAX != ntok) {
1562      -                        if ( ! flushed && ! rew_elem(m, tok))
     1620 +                        if ( ! flushed && ! rew_elem(mdoc, tok))
1563 1621                                  return(0);
1564 1622                          flushed = 1;
1565      -                        if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
     1623 +                        if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1566 1624                                  return(0);
1567 1625                          j++;
1568 1626                          break;
1569 1627                  }
1570 1628  
1571 1629                  if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1572 1630                                  ARGS_QWORD != ac &&
1573 1631                                  ! flushed &&
1574 1632                                  DELIM_NONE != mdoc_isdelim(p)) {
1575      -                        if ( ! rew_elem(m, tok))
     1633 +                        if ( ! rew_elem(mdoc, tok))
1576 1634                                  return(0);
1577 1635                          flushed = 1;
1578 1636                  }
1579 1637  
1580      -                if ( ! dword(m, line, la, p, DELIM_MAX))
     1638 +                if ( ! dword(mdoc, line, la, p, DELIM_MAX,
     1639 +                    MDOC_JOIN & mdoc_macros[tok].flags))
1581 1640                          return(0);
1582 1641                  j++;
1583 1642          }
1584 1643  
1585      -        if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg))
     1644 +        if (0 == j && ! mdoc_elem_alloc(mdoc, line, la, tok, arg))
1586 1645                 return(0);
1587 1646  
1588 1647          /* Close out in a consistent state. */
1589 1648  
1590      -        if ( ! flushed && ! rew_elem(m, tok))
     1649 +        if ( ! flushed && ! rew_elem(mdoc, tok))
1591 1650                  return(0);
1592 1651          if ( ! nl)
1593 1652                  return(1);
1594      -        return(append_delims(m, line, pos, buf));
     1653 +        return(append_delims(mdoc, line, pos, buf));
1595 1654  }
1596 1655  
1597 1656  
1598 1657  static int
1599 1658  in_line_eoln(MACRO_PROT_ARGS)
1600 1659  {
1601 1660          int              la;
1602 1661          enum margserr    ac;
1603 1662          enum margverr    av;
1604 1663          struct mdoc_arg *arg;
1605 1664          char            *p;
1606 1665          enum mdoct       ntok;
1607 1666  
1608 1667          assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1609 1668  
1610 1669          if (tok == MDOC_Pp)
1611      -                rew_sub(MDOC_BLOCK, m, MDOC_Nm, line, ppos);
     1670 +                rew_sub(MDOC_BLOCK, mdoc, MDOC_Nm, line, ppos);
1612 1671  
1613 1672          /* Parse macro arguments. */
1614 1673  
1615 1674          for (arg = NULL; ; ) {
1616 1675                  la = *pos;
1617      -                av = mdoc_argv(m, line, tok, &arg, pos, buf);
     1676 +                av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1618 1677  
1619 1678                  if (ARGV_WORD == av) {
1620 1679                          *pos = la;
1621 1680                          break;
1622 1681                  }
1623 1682                  if (ARGV_EOLN == av) 
1624 1683                          break;
1625 1684                  if (ARGV_ARG == av)
1626 1685                          continue;
1627 1686  
1628 1687                  mdoc_argv_free(arg);
1629 1688                  return(0);
1630 1689          }
1631 1690  
1632 1691          /* Open element scope. */
1633 1692  
1634      -        if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
     1693 +        if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
1635 1694                  return(0);
1636 1695  
1637 1696          /* Parse argument terms. */
1638 1697  
1639 1698          for (;;) {
1640 1699                  la = *pos;
1641      -                ac = mdoc_args(m, line, pos, buf, tok, &p);
     1700 +                ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1642 1701  
1643 1702                  if (ARGS_ERROR == ac)
1644 1703                          return(0);
1645 1704                  if (ARGS_EOLN == ac)
1646 1705                          break;
1647 1706  
1648 1707                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1649 1708  
1650 1709                  if (MDOC_MAX == ntok) {
1651      -                        if ( ! dword(m, line, la, p, DELIM_MAX))
     1710 +                        if ( ! dword(mdoc, line, la, p, DELIM_MAX,
     1711 +                            MDOC_JOIN & mdoc_macros[tok].flags))
1652 1712                                  return(0);
1653 1713                          continue;
1654 1714                  }
1655 1715  
1656      -                if ( ! rew_elem(m, tok))
     1716 +                if ( ! rew_elem(mdoc, tok))
1657 1717                          return(0);
1658      -                return(mdoc_macro(m, ntok, line, la, pos, buf));
     1718 +                return(mdoc_macro(mdoc, ntok, line, la, pos, buf));
1659 1719          }
1660 1720  
1661 1721          /* Close out (no delimiters). */
1662 1722  
1663      -        return(rew_elem(m, tok));
     1723 +        return(rew_elem(mdoc, tok));
1664 1724  }
1665 1725  
1666 1726  
1667 1727  /* ARGSUSED */
1668 1728  static int
1669 1729  ctx_synopsis(MACRO_PROT_ARGS)
1670 1730  {
1671 1731          int              nl;
1672 1732  
1673      -        nl = MDOC_NEWLINE & m->flags;
     1733 +        nl = MDOC_NEWLINE & mdoc->flags;
1674 1734  
1675 1735          /* If we're not in the SYNOPSIS, go straight to in-line. */
1676      -        if ( ! (MDOC_SYNOPSIS & m->flags))
1677      -                return(in_line(m, tok, line, ppos, pos, buf));
     1736 +        if ( ! (MDOC_SYNOPSIS & mdoc->flags))
     1737 +                return(in_line(mdoc, tok, line, ppos, pos, buf));
1678 1738  
1679 1739          /* If we're a nested call, same place. */
1680 1740          if ( ! nl)
1681      -                return(in_line(m, tok, line, ppos, pos, buf));
     1741 +                return(in_line(mdoc, tok, line, ppos, pos, buf));
1682 1742  
1683 1743          /*
1684 1744           * XXX: this will open a block scope; however, if later we end
1685 1745           * up formatting the block scope, then child nodes will inherit
1686 1746           * the formatting.  Be careful.
1687 1747           */
1688 1748          if (MDOC_Nm == tok)
1689      -                return(blk_full(m, tok, line, ppos, pos, buf));
     1749 +                return(blk_full(mdoc, tok, line, ppos, pos, buf));
1690 1750          assert(MDOC_Vt == tok);
1691      -        return(blk_part_imp(m, tok, line, ppos, pos, buf));
     1751 +        return(blk_part_imp(mdoc, tok, line, ppos, pos, buf));
1692 1752  }
1693 1753  
1694 1754  
1695 1755  /* ARGSUSED */
1696 1756  static int
1697 1757  obsolete(MACRO_PROT_ARGS)
1698 1758  {
1699 1759  
1700      -        mdoc_pmsg(m, line, ppos, MANDOCERR_MACROOBS);
     1760 +        mdoc_pmsg(mdoc, line, ppos, MANDOCERR_MACROOBS);
1701 1761          return(1);
1702 1762  }
1703 1763  
1704 1764  
1705 1765  /*
1706 1766   * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1707 1767   * They're unusual because they're basically free-form text until a
1708 1768   * macro is encountered.
1709 1769   */
1710 1770  static int
1711      -phrase(struct mdoc *m, int line, int ppos, char *buf)
     1771 +phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
1712 1772  {
1713 1773          int              la, pos;
1714 1774          enum margserr    ac;
1715 1775          enum mdoct       ntok;
1716 1776          char            *p;
1717 1777  
1718 1778          for (pos = ppos; ; ) {
1719 1779                  la = pos;
1720 1780  
1721      -                ac = mdoc_zargs(m, line, &pos, buf, &p);
     1781 +                ac = mdoc_zargs(mdoc, line, &pos, buf, &p);
1722 1782  
1723 1783                  if (ARGS_ERROR == ac)
1724 1784                          return(0);
1725 1785                  if (ARGS_EOLN == ac)
1726 1786                          break;
1727 1787  
1728 1788                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
1729 1789  
1730 1790                  if (MDOC_MAX == ntok) {
1731      -                        if ( ! dword(m, line, la, p, DELIM_MAX))
     1791 +                        if ( ! dword(mdoc, line, la, p, DELIM_MAX, 1))
1732 1792                                  return(0);
1733 1793                          continue;
1734 1794                  }
1735 1795  
1736      -                if ( ! mdoc_macro(m, ntok, line, la, &pos, buf))
     1796 +                if ( ! mdoc_macro(mdoc, ntok, line, la, &pos, buf))
1737 1797                          return(0);
1738      -                return(append_delims(m, line, &pos, buf));
     1798 +                return(append_delims(mdoc, line, &pos, buf));
1739 1799          }
1740 1800  
1741 1801          return(1);
1742 1802  }
1743 1803  
1744 1804  
1745 1805  /* ARGSUSED */
1746 1806  static int
1747 1807  phrase_ta(MACRO_PROT_ARGS)
1748 1808  {
     1809 +        struct mdoc_node *n;
1749 1810          int               la;
1750 1811          enum mdoct        ntok;
1751 1812          enum margserr     ac;
1752 1813          char             *p;
1753 1814  
1754      -        /*
1755      -         * FIXME: this is overly restrictive: if the `Ta' is unexpected,
1756      -         * it should simply error out with ARGSLOST.
1757      -         */
     1815 +        /* Make sure we are in a column list or ignore this macro. */
     1816 +        n = mdoc->last;
     1817 +        while (NULL != n && MDOC_Bl != n->tok)
     1818 +                n = n->parent;
     1819 +        if (NULL == n || LIST_column != n->norm->Bl.type) {
     1820 +                mdoc_pmsg(mdoc, line, ppos, MANDOCERR_STRAYTA);
     1821 +                return(1);
     1822 +        }
1758 1823  
1759      -        if ( ! rew_sub(MDOC_BODY, m, MDOC_It, line, ppos))
     1824 +        /* Advance to the next column. */
     1825 +        if ( ! rew_sub(MDOC_BODY, mdoc, MDOC_It, line, ppos))
1760 1826                  return(0);
1761      -        if ( ! mdoc_body_alloc(m, line, ppos, MDOC_It))
     1827 +        if ( ! mdoc_body_alloc(mdoc, line, ppos, MDOC_It))
1762 1828                  return(0);
1763 1829  
1764 1830          for (;;) {
1765 1831                  la = *pos;
1766      -                ac = mdoc_zargs(m, line, pos, buf, &p);
     1832 +                ac = mdoc_zargs(mdoc, line, pos, buf, &p);
1767 1833  
1768 1834                  if (ARGS_ERROR == ac)
1769 1835                          return(0);
1770 1836                  if (ARGS_EOLN == ac)
1771 1837                          break;
1772 1838  
1773 1839                  ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
1774 1840  
1775 1841                  if (MDOC_MAX == ntok) {
1776      -                        if ( ! dword(m, line, la, p, DELIM_MAX))
     1842 +                        if ( ! dword(mdoc, line, la, p, DELIM_MAX,
     1843 +                            MDOC_JOIN & mdoc_macros[tok].flags))
1777 1844                                  return(0);
1778 1845                          continue;
1779 1846                  }
1780 1847  
1781      -                if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
     1848 +                if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1782 1849                          return(0);
1783      -                return(append_delims(m, line, pos, buf));
     1850 +                return(append_delims(mdoc, line, pos, buf));
1784 1851          }
1785 1852  
1786 1853          return(1);
1787 1854  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX