Print this page
5051 import mdocml-1.12.3
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Approved by: TBD

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/man_macro.c
          +++ new/usr/src/cmd/mandoc/man_macro.c
   1      -/*      $Id: man_macro.c,v 1.71 2012/01/03 15:16:24 kristaps Exp $ */
        1 +/*      $Id: man_macro.c,v 1.79 2013/12/25 00:50:05 schwarze Exp $ */
   2    2  /*
   3    3   * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
        4 + * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
        5 + * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
   4    6   *
   5    7   * Permission to use, copy, modify, and distribute this software for any
   6    8   * purpose with or without fee is hereby granted, provided that the above
   7    9   * copyright notice and this permission notice appear in all copies.
   8   10   *
   9   11   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10   12   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11   13   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12   14   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13   15   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
↓ open down ↓ 56 lines elided ↑ open up ↑
  70   72          { in_line_eoln, MAN_SCOPED }, /* R */
  71   73          { in_line_eoln, MAN_SCOPED }, /* B */
  72   74          { in_line_eoln, MAN_SCOPED }, /* I */
  73   75          { in_line_eoln, 0 }, /* IR */
  74   76          { in_line_eoln, 0 }, /* RI */
  75   77          { in_line_eoln, MAN_NSCOPED }, /* na */
  76   78          { in_line_eoln, MAN_NSCOPED }, /* sp */
  77   79          { in_line_eoln, MAN_BSCOPE }, /* nf */
  78   80          { in_line_eoln, MAN_BSCOPE }, /* fi */
  79   81          { blk_close, 0 }, /* RE */
  80      -        { blk_exp, MAN_EXPLICIT }, /* RS */
       82 +        { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */
  81   83          { in_line_eoln, 0 }, /* DT */
  82   84          { in_line_eoln, 0 }, /* UC */
  83   85          { in_line_eoln, 0 }, /* PD */
  84   86          { in_line_eoln, 0 }, /* AT */
  85   87          { in_line_eoln, 0 }, /* in */
  86   88          { in_line_eoln, 0 }, /* ft */
  87   89          { in_line_eoln, 0 }, /* OP */
       90 +        { in_line_eoln, MAN_BSCOPE }, /* EX */
       91 +        { in_line_eoln, MAN_BSCOPE }, /* EE */
       92 +        { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */
       93 +        { blk_close, 0 }, /* UE */
  88   94  };
  89   95  
  90   96  const   struct man_macro * const man_macros = __man_macros;
  91   97  
  92   98  
  93   99  /*
  94  100   * Warn when "n" is an explicit non-roff macro.
  95  101   */
  96  102  static void
  97      -rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
      103 +rew_warn(struct man *man, struct man_node *n, enum mandocerr er)
  98  104  {
  99  105  
 100  106          if (er == MANDOCERR_MAX || MAN_BLOCK != n->type)
 101  107                  return;
 102  108          if (MAN_VALID & n->flags)
 103  109                  return;
 104  110          if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
 105  111                  return;
 106  112  
 107  113          assert(er < MANDOCERR_FATAL);
 108      -        man_nmsg(m, n, er);
      114 +        man_nmsg(man, n, er);
 109  115  }
 110  116  
 111  117  
 112  118  /*
 113  119   * Rewind scope.  If a code "er" != MANDOCERR_MAX has been provided, it
 114  120   * will be used if an explicit block scope is being closed out.
 115  121   */
 116  122  int
 117      -man_unscope(struct man *m, const struct man_node *to, 
      123 +man_unscope(struct man *man, const struct man_node *to, 
 118  124                  enum mandocerr er)
 119  125  {
 120  126          struct man_node *n;
 121  127  
 122  128          assert(to);
 123  129  
 124      -        m->next = MAN_NEXT_SIBLING;
      130 +        man->next = MAN_NEXT_SIBLING;
 125  131  
 126  132          /* LINTED */
 127      -        while (m->last != to) {
      133 +        while (man->last != to) {
 128  134                  /*
 129  135                   * Save the parent here, because we may delete the
 130      -                 * m->last node in the post-validation phase and reset
 131      -                 * it to m->last->parent, causing a step in the closing
      136 +                 * man->last node in the post-validation phase and reset
      137 +                 * it to man->last->parent, causing a step in the closing
 132  138                   * out to be lost.
 133  139                   */
 134      -                n = m->last->parent;
 135      -                rew_warn(m, m->last, er);
 136      -                if ( ! man_valid_post(m))
      140 +                n = man->last->parent;
      141 +                rew_warn(man, man->last, er);
      142 +                if ( ! man_valid_post(man))
 137  143                          return(0);
 138      -                m->last = n;
 139      -                assert(m->last);
      144 +                man->last = n;
      145 +                assert(man->last);
 140  146          }
 141  147  
 142      -        rew_warn(m, m->last, er);
 143      -        if ( ! man_valid_post(m))
      148 +        rew_warn(man, man->last, er);
      149 +        if ( ! man_valid_post(man))
 144  150                  return(0);
 145  151  
 146  152          return(1);
 147  153  }
 148  154  
 149  155  
 150  156  static enum rew
 151  157  rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
 152  158  {
 153  159  
↓ open down ↓ 22 lines elided ↑ open up ↑
 176  182  
 177  183          /* Normal nodes shouldn't go to the level of the root. */
 178  184          if (MAN_ROOT == n->parent->type)
 179  185                  return(REW_REWIND);
 180  186  
 181  187          /* Already-validated nodes should be closed out. */
 182  188          if (MAN_VALID & n->flags)
 183  189                  return(REW_NOHALT);
 184  190  
 185  191          /* First: rewind to ourselves. */
 186      -        if (type == n->type && tok == n->tok)
 187      -                return(REW_REWIND);
      192 +        if (type == n->type && tok == n->tok) {
      193 +                if (MAN_EXPLICIT & man_macros[n->tok].flags)
      194 +                        return(REW_HALT);
      195 +                else
      196 +                        return(REW_REWIND);
      197 +        }
 188  198  
 189  199          /* 
 190  200           * Next follow the implicit scope-smashings as defined by man.7:
 191  201           * section, sub-section, etc.
 192  202           */
 193  203  
 194  204          switch (tok) {
 195  205          case (MAN_SH):
 196  206                  break;
 197  207          case (MAN_SS):
 198  208                  /* Rewind to a section, if a block. */
 199  209                  if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
 200  210                          return(c);
 201  211                  break;
 202  212          case (MAN_RS):
      213 +                /* Preserve empty paragraphs before RS. */
      214 +                if (0 == n->nchild && (MAN_P == n->tok ||
      215 +                    MAN_PP == n->tok || MAN_LP == n->tok))
      216 +                        return(REW_HALT);
 203  217                  /* Rewind to a subsection, if a block. */
 204  218                  if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
 205  219                          return(c);
 206  220                  /* Rewind to a section, if a block. */
 207  221                  if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
 208  222                          return(c);
 209  223                  break;
 210  224          default:
 211  225                  /* Rewind to an offsetter, if a block. */
 212  226                  if (REW_NOHALT != (c = rew_block(MAN_RS, type, n)))
↓ open down ↓ 10 lines elided ↑ open up ↑
 223  237          return(REW_NOHALT);
 224  238  }
 225  239  
 226  240  
 227  241  /*
 228  242   * Rewinding entails ascending the parse tree until a coherent point,
 229  243   * for example, the `SH' macro will close out any intervening `SS'
 230  244   * scopes.  When a scope is closed, it must be validated and actioned.
 231  245   */
 232  246  static int
 233      -rew_scope(enum man_type type, struct man *m, enum mant tok)
      247 +rew_scope(enum man_type type, struct man *man, enum mant tok)
 234  248  {
 235  249          struct man_node *n;
 236  250          enum rew         c;
 237  251  
 238  252          /* LINTED */
 239      -        for (n = m->last; n; n = n->parent) {
      253 +        for (n = man->last; n; n = n->parent) {
 240  254                  /* 
 241  255                   * Whether we should stop immediately (REW_HALT), stop
 242  256                   * and rewind until this point (REW_REWIND), or keep
 243  257                   * rewinding (REW_NOHALT).
 244  258                   */
 245  259                  c = rew_dohalt(tok, type, n);
 246  260                  if (REW_HALT == c)
 247  261                          return(1);
 248  262                  if (REW_REWIND == c)
 249  263                          break;
 250  264          }
 251  265  
 252  266          /* 
 253  267           * Rewind until the current point.  Warn if we're a roff
 254  268           * instruction that's mowing over explicit scopes.
 255  269           */
 256  270          assert(n);
 257  271  
 258      -        return(man_unscope(m, n, MANDOCERR_MAX));
      272 +        return(man_unscope(man, n, MANDOCERR_MAX));
 259  273  }
 260  274  
 261  275  
 262  276  /*
 263  277   * Close out a generic explicit macro.
 264  278   */
 265  279  /* ARGSUSED */
 266  280  int
 267  281  blk_close(MACRO_PROT_ARGS)
 268  282  {
 269  283          enum mant                ntok;
 270  284          const struct man_node   *nn;
 271  285  
 272  286          switch (tok) {
 273  287          case (MAN_RE):
 274  288                  ntok = MAN_RS;
 275  289                  break;
      290 +        case (MAN_UE):
      291 +                ntok = MAN_UR;
      292 +                break;
 276  293          default:
 277  294                  abort();
 278  295                  /* NOTREACHED */
 279  296          }
 280  297  
 281      -        for (nn = m->last->parent; nn; nn = nn->parent)
 282      -                if (ntok == nn->tok)
      298 +        for (nn = man->last->parent; nn; nn = nn->parent)
      299 +                if (ntok == nn->tok && MAN_BLOCK == nn->type)
 283  300                          break;
 284  301  
 285      -        if (NULL == nn)
 286      -                man_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);
      302 +        if (NULL == nn) {
      303 +                man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE);
      304 +                if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
      305 +                        return(0);
      306 +        } else 
      307 +                man_unscope(man, nn, MANDOCERR_MAX);
 287  308  
 288      -        if ( ! rew_scope(MAN_BODY, m, ntok))
 289      -                return(0);
 290      -        if ( ! rew_scope(MAN_BLOCK, m, ntok))
 291      -                return(0);
 292      -
 293  309          return(1);
 294  310  }
 295  311  
 296  312  
 297  313  /* ARGSUSED */
 298  314  int
 299  315  blk_exp(MACRO_PROT_ARGS)
 300  316  {
      317 +        struct man_node *n;
 301  318          int              la;
 302  319          char            *p;
 303  320  
 304      -        /* 
 305      -         * Close out prior scopes.  "Regular" explicit macros cannot be
 306      -         * nested, but we allow roff macros to be placed just about
 307      -         * anywhere.
 308      -         */
      321 +        /* Close out prior implicit scopes. */
 309  322  
 310      -        if ( ! man_block_alloc(m, line, ppos, tok))
      323 +        if ( ! rew_scope(MAN_BLOCK, man, tok))
 311  324                  return(0);
 312      -        if ( ! man_head_alloc(m, line, ppos, tok))
      325 +
      326 +        if ( ! man_block_alloc(man, line, ppos, tok))
 313  327                  return(0);
      328 +        if ( ! man_head_alloc(man, line, ppos, tok))
      329 +                return(0);
 314  330  
 315  331          for (;;) {
 316  332                  la = *pos;
 317      -                if ( ! man_args(m, line, pos, buf, &p))
      333 +                if ( ! man_args(man, line, pos, buf, &p))
 318  334                          break;
 319      -                if ( ! man_word_alloc(m, line, la, p))
      335 +                if ( ! man_word_alloc(man, line, la, p))
 320  336                          return(0);
 321  337          }
 322  338  
 323      -        assert(m);
      339 +        assert(man);
 324  340          assert(tok != MAN_MAX);
 325  341  
 326      -        if ( ! rew_scope(MAN_HEAD, m, tok))
 327      -                return(0);
 328      -        return(man_body_alloc(m, line, ppos, tok));
      342 +        for (n = man->last; n; n = n->parent) {
      343 +                if (n->tok != tok)
      344 +                        continue;
      345 +                assert(MAN_HEAD == n->type);
      346 +                man_unscope(man, n, MANDOCERR_MAX);
      347 +                break;
      348 +        }
      349 +
      350 +        return(man_body_alloc(man, line, ppos, tok));
 329  351  }
 330  352  
 331  353  
 332  354  
 333  355  /*
 334  356   * Parse an implicit-block macro.  These contain a MAN_HEAD and a
 335  357   * MAN_BODY contained within a MAN_BLOCK.  Rules for closing out other
 336  358   * scopes, such as `SH' closing out an `SS', are defined in the rew
 337  359   * routines.
 338  360   */
 339  361  /* ARGSUSED */
 340  362  int
 341  363  blk_imp(MACRO_PROT_ARGS)
 342  364  {
 343  365          int              la;
 344  366          char            *p;
 345  367          struct man_node *n;
 346  368  
 347  369          /* Close out prior scopes. */
 348  370  
 349      -        if ( ! rew_scope(MAN_BODY, m, tok))
      371 +        if ( ! rew_scope(MAN_BODY, man, tok))
 350  372                  return(0);
 351      -        if ( ! rew_scope(MAN_BLOCK, m, tok))
      373 +        if ( ! rew_scope(MAN_BLOCK, man, tok))
 352  374                  return(0);
 353  375  
 354  376          /* Allocate new block & head scope. */
 355  377  
 356      -        if ( ! man_block_alloc(m, line, ppos, tok))
      378 +        if ( ! man_block_alloc(man, line, ppos, tok))
 357  379                  return(0);
 358      -        if ( ! man_head_alloc(m, line, ppos, tok))
      380 +        if ( ! man_head_alloc(man, line, ppos, tok))
 359  381                  return(0);
 360  382  
 361      -        n = m->last;
      383 +        n = man->last;
 362  384  
 363  385          /* Add line arguments. */
 364  386  
 365  387          for (;;) {
 366  388                  la = *pos;
 367      -                if ( ! man_args(m, line, pos, buf, &p))
      389 +                if ( ! man_args(man, line, pos, buf, &p))
 368  390                          break;
 369      -                if ( ! man_word_alloc(m, line, la, p))
      391 +                if ( ! man_word_alloc(man, line, la, p))
 370  392                          return(0);
 371  393          }
 372  394  
 373  395          /* Close out head and open body (unless MAN_SCOPE). */
 374  396  
 375  397          if (MAN_SCOPED & man_macros[tok].flags) {
 376  398                  /* If we're forcing scope (`TP'), keep it open. */
 377  399                  if (MAN_FSCOPED & man_macros[tok].flags) {
 378      -                        m->flags |= MAN_BLINE;
      400 +                        man->flags |= MAN_BLINE;
 379  401                          return(1);
 380      -                } else if (n == m->last) {
 381      -                        m->flags |= MAN_BLINE;
      402 +                } else if (n == man->last) {
      403 +                        man->flags |= MAN_BLINE;
 382  404                          return(1);
 383  405                  }
 384  406          }
 385  407  
 386      -        if ( ! rew_scope(MAN_HEAD, m, tok))
      408 +        if ( ! rew_scope(MAN_HEAD, man, tok))
 387  409                  return(0);
 388      -        return(man_body_alloc(m, line, ppos, tok));
      410 +        return(man_body_alloc(man, line, ppos, tok));
 389  411  }
 390  412  
 391  413  
 392  414  /* ARGSUSED */
 393  415  int
 394  416  in_line_eoln(MACRO_PROT_ARGS)
 395  417  {
 396  418          int              la;
 397  419          char            *p;
 398  420          struct man_node *n;
 399  421  
 400      -        if ( ! man_elem_alloc(m, line, ppos, tok))
      422 +        if ( ! man_elem_alloc(man, line, ppos, tok))
 401  423                  return(0);
 402  424  
 403      -        n = m->last;
      425 +        n = man->last;
 404  426  
 405  427          for (;;) {
 406  428                  la = *pos;
 407      -                if ( ! man_args(m, line, pos, buf, &p))
      429 +                if ( ! man_args(man, line, pos, buf, &p))
 408  430                          break;
 409      -                if ( ! man_word_alloc(m, line, la, p))
      431 +                if ( ! man_word_alloc(man, line, la, p))
 410  432                          return(0);
 411  433          }
 412  434  
 413  435          /*
      436 +         * Append MAN_EOS in case the last snipped argument
      437 +         * ends with a dot, e.g. `.IR syslog (3).'
      438 +         */
      439 +
      440 +        if (n != man->last &&
      441 +            mandoc_eos(man->last->string, strlen(man->last->string), 0))
      442 +                man->last->flags |= MAN_EOS;
      443 +
      444 +        /*
 414  445           * If no arguments are specified and this is MAN_SCOPED (i.e.,
 415  446           * next-line scoped), then set our mode to indicate that we're
 416  447           * waiting for terms to load into our context.
 417  448           */
 418  449  
 419      -        if (n == m->last && MAN_SCOPED & man_macros[tok].flags) {
      450 +        if (n == man->last && MAN_SCOPED & man_macros[tok].flags) {
 420  451                  assert( ! (MAN_NSCOPED & man_macros[tok].flags));
 421      -                m->flags |= MAN_ELINE;
      452 +                man->flags |= MAN_ELINE;
 422  453                  return(1);
 423  454          } 
 424  455  
 425  456          /* Set ignorable context, if applicable. */
 426  457  
 427  458          if (MAN_NSCOPED & man_macros[tok].flags) {
 428  459                  assert( ! (MAN_SCOPED & man_macros[tok].flags));
 429      -                m->flags |= MAN_ILINE;
      460 +                man->flags |= MAN_ILINE;
 430  461          }
 431  462  
 432      -        assert(MAN_ROOT != m->last->type);
 433      -        m->next = MAN_NEXT_SIBLING;
      463 +        assert(MAN_ROOT != man->last->type);
      464 +        man->next = MAN_NEXT_SIBLING;
 434  465          
 435  466          /*
 436  467           * Rewind our element scope.  Note that when TH is pruned, we'll
 437  468           * be back at the root, so make sure that we don't clobber as
 438  469           * its sibling.
 439  470           */
 440  471  
 441      -        for ( ; m->last; m->last = m->last->parent) {
 442      -                if (m->last == n)
      472 +        for ( ; man->last; man->last = man->last->parent) {
      473 +                if (man->last == n)
 443  474                          break;
 444      -                if (m->last->type == MAN_ROOT)
      475 +                if (man->last->type == MAN_ROOT)
 445  476                          break;
 446      -                if ( ! man_valid_post(m))
      477 +                if ( ! man_valid_post(man))
 447  478                          return(0);
 448  479          }
 449  480  
 450      -        assert(m->last);
      481 +        assert(man->last);
 451  482  
 452  483          /*
 453  484           * Same here regarding whether we're back at the root. 
 454  485           */
 455  486  
 456      -        if (m->last->type != MAN_ROOT && ! man_valid_post(m))
      487 +        if (man->last->type != MAN_ROOT && ! man_valid_post(man))
 457  488                  return(0);
 458  489  
 459  490          return(1);
 460  491  }
 461  492  
 462  493  
 463  494  int
 464      -man_macroend(struct man *m)
      495 +man_macroend(struct man *man)
 465  496  {
 466  497  
 467      -        return(man_unscope(m, m->first, MANDOCERR_SCOPEEXIT));
      498 +        return(man_unscope(man, man->first, MANDOCERR_SCOPEEXIT));
 468  499  }
 469  500  
 470  501  static int
 471      -man_args(struct man *m, int line, int *pos, char *buf, char **v)
      502 +man_args(struct man *man, int line, int *pos, char *buf, char **v)
 472  503  {
 473  504          char     *start;
 474  505  
 475  506          assert(*pos);
 476  507          *v = start = buf + *pos;
 477  508          assert(' ' != *start);
 478  509  
 479  510          if ('\0' == *start)
 480  511                  return(0);
 481  512  
 482      -        *v = mandoc_getarg(m->parse, v, line, pos);
      513 +        *v = mandoc_getarg(man->parse, v, line, pos);
 483  514          return(1);
 484  515  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX