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/mdoc_validate.c
          +++ new/usr/src/cmd/mandoc/mdoc_validate.c
   1      -/*      $Id: mdoc_validate.c,v 1.182 2012/03/23 05:50:25 kristaps Exp $ */
        1 +/*      $Id: mdoc_validate.c,v 1.198 2013/12/15 21:23:52 schwarze Exp $ */
   2    2  /*
   3      - * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
   4      - * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
        3 + * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
        4 + * Copyright (c) 2010, 2011, 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
  15   15   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16   16   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17   17   */
  18   18  #ifdef HAVE_CONFIG_H
  19   19  #include "config.h"
  20   20  #endif
  21   21  
  22      -#ifndef OSNAME
       22 +#ifndef OSNAME
  23   23  #include <sys/utsname.h>
  24   24  #endif
  25   25  
  26   26  #include <sys/types.h>
  27   27  
  28   28  #include <assert.h>
  29   29  #include <ctype.h>
  30   30  #include <limits.h>
  31   31  #include <stdio.h>
  32   32  #include <stdlib.h>
↓ open down ↓ 57 lines elided ↑ open up ↑
  90   90  
  91   91  static  int      post_an(POST_ARGS);
  92   92  static  int      post_at(POST_ARGS);
  93   93  static  int      post_bf(POST_ARGS);
  94   94  static  int      post_bl(POST_ARGS);
  95   95  static  int      post_bl_block(POST_ARGS);
  96   96  static  int      post_bl_block_width(POST_ARGS);
  97   97  static  int      post_bl_block_tag(POST_ARGS);
  98   98  static  int      post_bl_head(POST_ARGS);
  99   99  static  int      post_bx(POST_ARGS);
      100 +static  int      post_defaults(POST_ARGS);
 100  101  static  int      post_dd(POST_ARGS);
 101  102  static  int      post_dt(POST_ARGS);
 102      -static  int      post_defaults(POST_ARGS);
 103      -static  int      post_literal(POST_ARGS);
 104  103  static  int      post_eoln(POST_ARGS);
      104 +static  int      post_hyph(POST_ARGS);
      105 +static  int      post_ignpar(POST_ARGS);
 105  106  static  int      post_it(POST_ARGS);
 106  107  static  int      post_lb(POST_ARGS);
      108 +static  int      post_literal(POST_ARGS);
 107  109  static  int      post_nm(POST_ARGS);
 108  110  static  int      post_ns(POST_ARGS);
 109  111  static  int      post_os(POST_ARGS);
 110      -static  int      post_ignpar(POST_ARGS);
      112 +static  int      post_par(POST_ARGS);
 111  113  static  int      post_prol(POST_ARGS);
 112  114  static  int      post_root(POST_ARGS);
 113  115  static  int      post_rs(POST_ARGS);
 114  116  static  int      post_sh(POST_ARGS);
 115  117  static  int      post_sh_body(POST_ARGS);
 116  118  static  int      post_sh_head(POST_ARGS);
 117  119  static  int      post_st(POST_ARGS);
 118  120  static  int      post_std(POST_ARGS);
 119  121  static  int      post_vt(POST_ARGS);
 120  122  static  int      pre_an(PRE_ARGS);
↓ open down ↓ 13 lines elided ↑ open up ↑
 134  136  static  v_post   posts_an[] = { post_an, NULL };
 135  137  static  v_post   posts_at[] = { post_at, post_defaults, NULL };
 136  138  static  v_post   posts_bd[] = { post_literal, hwarn_eq0, bwarn_ge1, NULL };
 137  139  static  v_post   posts_bf[] = { hwarn_le1, post_bf, NULL };
 138  140  static  v_post   posts_bk[] = { hwarn_eq0, bwarn_ge1, NULL };
 139  141  static  v_post   posts_bl[] = { bwarn_ge1, post_bl, NULL };
 140  142  static  v_post   posts_bx[] = { post_bx, NULL };
 141  143  static  v_post   posts_bool[] = { ebool, NULL };
 142  144  static  v_post   posts_eoln[] = { post_eoln, NULL };
 143  145  static  v_post   posts_defaults[] = { post_defaults, NULL };
      146 +static  v_post   posts_d1[] = { bwarn_ge1, post_hyph, NULL };
 144  147  static  v_post   posts_dd[] = { post_dd, post_prol, NULL };
 145  148  static  v_post   posts_dl[] = { post_literal, bwarn_ge1, NULL };
 146  149  static  v_post   posts_dt[] = { post_dt, post_prol, NULL };
 147  150  static  v_post   posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
      151 +static  v_post   posts_hyph[] = { post_hyph, NULL };
      152 +static  v_post   posts_hyphtext[] = { ewarn_ge1, post_hyph, NULL };
 148  153  static  v_post   posts_it[] = { post_it, NULL };
 149  154  static  v_post   posts_lb[] = { post_lb, NULL };
 150      -static  v_post   posts_nd[] = { berr_ge1, NULL };
      155 +static  v_post   posts_nd[] = { berr_ge1, post_hyph, NULL };
 151  156  static  v_post   posts_nm[] = { post_nm, NULL };
 152  157  static  v_post   posts_notext[] = { ewarn_eq0, NULL };
 153  158  static  v_post   posts_ns[] = { post_ns, NULL };
 154  159  static  v_post   posts_os[] = { post_os, post_prol, NULL };
      160 +static  v_post   posts_pp[] = { post_par, ewarn_eq0, NULL };
 155  161  static  v_post   posts_rs[] = { post_rs, NULL };
 156      -static  v_post   posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL };
 157      -static  v_post   posts_sp[] = { ewarn_le1, NULL };
 158      -static  v_post   posts_ss[] = { post_ignpar, hwarn_ge1, NULL };
      162 +static  v_post   posts_sh[] = { post_ignpar,hwarn_ge1,post_sh,post_hyph,NULL };
      163 +static  v_post   posts_sp[] = { post_par, ewarn_le1, NULL };
      164 +static  v_post   posts_ss[] = { post_ignpar, hwarn_ge1, post_hyph, NULL };
 159  165  static  v_post   posts_st[] = { post_st, NULL };
 160  166  static  v_post   posts_std[] = { post_std, NULL };
 161  167  static  v_post   posts_text[] = { ewarn_ge1, NULL };
 162  168  static  v_post   posts_text1[] = { ewarn_eq1, NULL };
 163  169  static  v_post   posts_vt[] = { post_vt, NULL };
 164      -static  v_post   posts_wline[] = { bwarn_ge1, NULL };
 165  170  static  v_pre    pres_an[] = { pre_an, NULL };
 166  171  static  v_pre    pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL };
 167  172  static  v_pre    pres_bl[] = { pre_bl, pre_par, NULL };
 168  173  static  v_pre    pres_d1[] = { pre_display, NULL };
 169  174  static  v_pre    pres_dl[] = { pre_literal, pre_display, NULL };
 170  175  static  v_pre    pres_dd[] = { pre_dd, NULL };
 171  176  static  v_pre    pres_dt[] = { pre_dt, NULL };
 172      -static  v_pre    pres_er[] = { NULL, NULL };
 173      -static  v_pre    pres_fd[] = { NULL, NULL };
 174  177  static  v_pre    pres_it[] = { pre_it, pre_par, NULL };
 175  178  static  v_pre    pres_os[] = { pre_os, NULL };
 176  179  static  v_pre    pres_pp[] = { pre_par, NULL };
 177  180  static  v_pre    pres_sh[] = { pre_sh, NULL };
 178  181  static  v_pre    pres_ss[] = { pre_ss, NULL };
 179  182  static  v_pre    pres_std[] = { pre_std, NULL };
 180  183  
 181  184  static  const struct valids mdoc_valids[MDOC_MAX] = {
 182  185          { NULL, NULL },                         /* Ap */
 183  186          { pres_dd, posts_dd },                  /* Dd */
 184  187          { pres_dt, posts_dt },                  /* Dt */
 185  188          { pres_os, posts_os },                  /* Os */
 186  189          { pres_sh, posts_sh },                  /* Sh */ 
 187  190          { pres_ss, posts_ss },                  /* Ss */ 
 188      -        { pres_pp, posts_notext },              /* Pp */ 
 189      -        { pres_d1, posts_wline },               /* D1 */
      191 +        { pres_pp, posts_pp },                  /* Pp */ 
      192 +        { pres_d1, posts_d1 },                  /* D1 */
 190  193          { pres_dl, posts_dl },                  /* Dl */
 191  194          { pres_bd, posts_bd },                  /* Bd */
 192  195          { NULL, NULL },                         /* Ed */
 193  196          { pres_bl, posts_bl },                  /* Bl */ 
 194  197          { NULL, NULL },                         /* El */
 195  198          { pres_it, posts_it },                  /* It */
 196  199          { NULL, NULL },                         /* Ad */ 
 197  200          { pres_an, posts_an },                  /* An */ 
 198  201          { NULL, posts_defaults },               /* Ar */
 199  202          { NULL, NULL },                         /* Cd */ 
 200  203          { NULL, NULL },                         /* Cm */
 201  204          { NULL, NULL },                         /* Dv */ 
 202      -        { pres_er, NULL },                      /* Er */ 
      205 +        { NULL, NULL },                         /* Er */ 
 203  206          { NULL, NULL },                         /* Ev */ 
 204  207          { pres_std, posts_std },                /* Ex */ 
 205  208          { NULL, NULL },                         /* Fa */ 
 206      -        { pres_fd, posts_text },                /* Fd */
      209 +        { NULL, posts_text },                   /* Fd */
 207  210          { NULL, NULL },                         /* Fl */
 208  211          { NULL, NULL },                         /* Fn */ 
 209  212          { NULL, NULL },                         /* Ft */ 
 210  213          { NULL, NULL },                         /* Ic */ 
 211  214          { NULL, posts_text1 },                  /* In */ 
 212  215          { NULL, posts_defaults },               /* Li */
 213  216          { NULL, posts_nd },                     /* Nd */
 214  217          { NULL, posts_nm },                     /* Nm */
 215  218          { NULL, NULL },                         /* Op */
 216  219          { NULL, NULL },                         /* Ot */
 217  220          { NULL, posts_defaults },               /* Pa */
 218  221          { pres_std, posts_std },                /* Rv */
 219  222          { NULL, posts_st },                     /* St */ 
 220  223          { NULL, NULL },                         /* Va */
 221  224          { NULL, posts_vt },                     /* Vt */ 
 222  225          { NULL, posts_text },                   /* Xr */ 
 223  226          { NULL, posts_text },                   /* %A */
 224      -        { NULL, posts_text },                   /* %B */ /* FIXME: can be used outside Rs/Re. */
      227 +        { NULL, posts_hyphtext },               /* %B */ /* FIXME: can be used outside Rs/Re. */
 225  228          { NULL, posts_text },                   /* %D */
 226  229          { NULL, posts_text },                   /* %I */
 227  230          { NULL, posts_text },                   /* %J */
 228      -        { NULL, posts_text },                   /* %N */
 229      -        { NULL, posts_text },                   /* %O */
      231 +        { NULL, posts_hyphtext },               /* %N */
      232 +        { NULL, posts_hyphtext },               /* %O */
 230  233          { NULL, posts_text },                   /* %P */
 231      -        { NULL, posts_text },                   /* %R */
 232      -        { NULL, posts_text },                   /* %T */ /* FIXME: can be used outside Rs/Re. */
      234 +        { NULL, posts_hyphtext },               /* %R */
      235 +        { NULL, posts_hyphtext },               /* %T */ /* FIXME: can be used outside Rs/Re. */
 233  236          { NULL, posts_text },                   /* %V */
 234  237          { NULL, NULL },                         /* Ac */
 235  238          { NULL, NULL },                         /* Ao */
 236  239          { NULL, NULL },                         /* Aq */
 237  240          { NULL, posts_at },                     /* At */ 
 238  241          { NULL, NULL },                         /* Bc */
 239  242          { NULL, posts_bf },                     /* Bf */
 240  243          { NULL, NULL },                         /* Bo */
 241  244          { NULL, NULL },                         /* Bq */
 242  245          { NULL, NULL },                         /* Bsx */
↓ open down ↓ 19 lines elided ↑ open up ↑
 262  265          { NULL, NULL },                         /* Qc */
 263  266          { NULL, NULL },                         /* Ql */
 264  267          { NULL, NULL },                         /* Qo */
 265  268          { NULL, NULL },                         /* Qq */
 266  269          { NULL, NULL },                         /* Re */
 267  270          { NULL, posts_rs },                     /* Rs */
 268  271          { NULL, NULL },                         /* Sc */
 269  272          { NULL, NULL },                         /* So */
 270  273          { NULL, NULL },                         /* Sq */
 271  274          { NULL, posts_bool },                   /* Sm */ 
 272      -        { NULL, NULL },                         /* Sx */
      275 +        { NULL, posts_hyph },                   /* Sx */
 273  276          { NULL, NULL },                         /* Sy */
 274  277          { NULL, NULL },                         /* Tn */
 275  278          { NULL, NULL },                         /* Ux */
 276  279          { NULL, NULL },                         /* Xc */
 277  280          { NULL, NULL },                         /* Xo */
 278  281          { NULL, posts_fo },                     /* Fo */ 
 279  282          { NULL, NULL },                         /* Fc */ 
 280  283          { NULL, NULL },                         /* Oo */
 281  284          { NULL, NULL },                         /* Oc */
 282  285          { NULL, posts_bk },                     /* Bk */
 283  286          { NULL, NULL },                         /* Ek */
 284  287          { NULL, posts_eoln },                   /* Bt */
 285  288          { NULL, NULL },                         /* Hf */
 286  289          { NULL, NULL },                         /* Fr */
 287  290          { NULL, posts_eoln },                   /* Ud */
 288  291          { NULL, posts_lb },                     /* Lb */
 289      -        { NULL, posts_notext },                 /* Lp */ 
      292 +        { pres_pp, posts_pp },                  /* Lp */ 
 290  293          { NULL, NULL },                         /* Lk */ 
 291  294          { NULL, posts_defaults },               /* Mt */ 
 292  295          { NULL, NULL },                         /* Brq */ 
 293  296          { NULL, NULL },                         /* Bro */ 
 294  297          { NULL, NULL },                         /* Brc */ 
 295  298          { NULL, posts_text },                   /* %C */
 296  299          { NULL, NULL },                         /* Es */
 297  300          { NULL, NULL },                         /* En */
 298  301          { NULL, NULL },                         /* Dx */
 299  302          { NULL, posts_text },                   /* %Q */
 300      -        { NULL, posts_notext },                 /* br */
 301      -        { pres_pp, posts_sp },                  /* sp */
      303 +        { NULL, posts_pp },                     /* br */
      304 +        { NULL, posts_sp },                     /* sp */
 302  305          { NULL, posts_text1 },                  /* %U */
 303  306          { NULL, NULL },                         /* Ta */
 304  307  };
 305  308  
 306  309  #define RSORD_MAX 14 /* Number of `Rs' blocks. */
 307  310  
 308  311  static  const enum mdoct rsord[RSORD_MAX] = {
 309  312          MDOC__A,
 310  313          MDOC__T,
 311  314          MDOC__B,
 312  315          MDOC__I,
 313  316          MDOC__J,
 314  317          MDOC__R,
 315  318          MDOC__N,
 316  319          MDOC__V,
      320 +        MDOC__U,
 317  321          MDOC__P,
 318  322          MDOC__Q,
 319      -        MDOC__D,
 320      -        MDOC__O,
 321  323          MDOC__C,
 322      -        MDOC__U
      324 +        MDOC__D,
      325 +        MDOC__O
 323  326  };
 324  327  
 325  328  static  const char * const secnames[SEC__MAX] = {
 326  329          NULL,
 327  330          "NAME",
 328  331          "LIBRARY",
 329  332          "SYNOPSIS",
 330  333          "DESCRIPTION",
 331  334          "IMPLEMENTATION NOTES",
 332  335          "RETURN VALUES",
↓ open down ↓ 74 lines elided ↑ open up ↑
 407  410          if (NULL == mdoc_valids[mdoc->last->tok].post)
 408  411                  return(1);
 409  412          for (p = mdoc_valids[mdoc->last->tok].post; *p; p++)
 410  413                  if ( ! (*p)(mdoc)) 
 411  414                          return(0);
 412  415  
 413  416          return(1);
 414  417  }
 415  418  
 416  419  static int
 417      -check_count(struct mdoc *m, enum mdoc_type type, 
      420 +check_count(struct mdoc *mdoc, enum mdoc_type type, 
 418  421                  enum check_lvl lvl, enum check_ineq ineq, int val)
 419  422  {
 420  423          const char      *p;
 421  424          enum mandocerr   t;
 422  425  
 423      -        if (m->last->type != type)
      426 +        if (mdoc->last->type != type)
 424  427                  return(1);
 425  428          
 426  429          switch (ineq) {
 427  430          case (CHECK_LT):
 428  431                  p = "less than ";
 429      -                if (m->last->nchild < val)
      432 +                if (mdoc->last->nchild < val)
 430  433                          return(1);
 431  434                  break;
 432  435          case (CHECK_GT):
 433  436                  p = "more than ";
 434      -                if (m->last->nchild > val)
      437 +                if (mdoc->last->nchild > val)
 435  438                          return(1);
 436  439                  break;
 437  440          case (CHECK_EQ):
 438  441                  p = "";
 439      -                if (val == m->last->nchild)
      442 +                if (val == mdoc->last->nchild)
 440  443                          return(1);
 441  444                  break;
 442  445          default:
 443  446                  abort();
 444  447                  /* NOTREACHED */
 445  448          }
 446  449  
 447  450          t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
 448      -        mandoc_vmsg(t, m->parse, m->last->line, m->last->pos,
      451 +        mandoc_vmsg(t, mdoc->parse, mdoc->last->line, mdoc->last->pos,
 449  452                          "want %s%d children (have %d)",
 450      -                        p, val, m->last->nchild);
      453 +                        p, val, mdoc->last->nchild);
 451  454          return(1);
 452  455  }
 453  456  
 454  457  static int
 455  458  berr_ge1(POST_ARGS)
 456  459  {
 457  460  
 458  461          return(check_count(mdoc, MDOC_BODY, CHECK_ERROR, CHECK_GT, 0));
 459  462  }
 460  463  
↓ open down ↓ 45 lines elided ↑ open up ↑
 506  509          return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_GT, 0));
 507  510  }
 508  511  
 509  512  static int
 510  513  hwarn_le1(POST_ARGS)
 511  514  {
 512  515          return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_LT, 2));
 513  516  }
 514  517  
 515  518  static void
 516      -check_args(struct mdoc *m, struct mdoc_node *n)
      519 +check_args(struct mdoc *mdoc, struct mdoc_node *n)
 517  520  {
 518  521          int              i;
 519  522  
 520  523          if (NULL == n->args)
 521  524                  return;
 522  525  
 523  526          assert(n->args->argc);
 524  527          for (i = 0; i < (int)n->args->argc; i++)
 525      -                check_argv(m, n, &n->args->argv[i]);
      528 +                check_argv(mdoc, n, &n->args->argv[i]);
 526  529  }
 527  530  
 528  531  static void
 529      -check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v)
      532 +check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v)
 530  533  {
 531  534          int              i;
 532  535  
 533  536          for (i = 0; i < (int)v->sz; i++)
 534      -                check_text(m, v->line, v->pos, v->value[i]);
      537 +                check_text(mdoc, v->line, v->pos, v->value[i]);
 535  538  
 536  539          /* FIXME: move to post_std(). */
 537  540  
 538  541          if (MDOC_Std == v->arg)
 539      -                if ( ! (v->sz || m->meta.name))
 540      -                        mdoc_nmsg(m, n, MANDOCERR_NONAME);
      542 +                if ( ! (v->sz || mdoc->meta.name))
      543 +                        mdoc_nmsg(mdoc, n, MANDOCERR_NONAME);
 541  544  }
 542  545  
 543  546  static void
 544      -check_text(struct mdoc *m, int ln, int pos, char *p)
      547 +check_text(struct mdoc *mdoc, int ln, int pos, char *p)
 545  548  {
 546  549          char            *cp;
 547  550  
 548      -        if (MDOC_LITERAL & m->flags)
      551 +        if (MDOC_LITERAL & mdoc->flags)
 549  552                  return;
 550  553  
 551  554          for (cp = p; NULL != (p = strchr(p, '\t')); p++)
 552      -                mdoc_pmsg(m, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
      555 +                mdoc_pmsg(mdoc, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
 553  556  }
 554  557  
 555  558  static int
 556  559  check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t)
 557  560  {
 558  561  
 559  562          assert(n->parent);
 560  563          if ((MDOC_ROOT == t || tok == n->parent->tok) &&
 561  564                          (t == n->parent->type))
 562  565                  return(1);
↓ open down ↓ 163 lines elided ↑ open up ↑
 726  729          /* Allow lists to default to LIST_item. */
 727  730  
 728  731          if (LIST__NONE == n->norm->Bl.type) {
 729  732                  mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE);
 730  733                  n->norm->Bl.type = LIST_item;
 731  734          }
 732  735  
 733  736          /* 
 734  737           * Validate the width field.  Some list types don't need width
 735  738           * types and should be warned about them.  Others should have it
 736      -         * and must also be warned.
      739 +         * and must also be warned.  Yet others have a default and need
      740 +         * no warning.
 737  741           */
 738  742  
 739  743          switch (n->norm->Bl.type) {
 740  744          case (LIST_tag):
 741      -                if (n->norm->Bl.width)
 742      -                        break;
 743      -                mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
      745 +                if (NULL == n->norm->Bl.width)
      746 +                        mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
 744  747                  break;
 745  748          case (LIST_column):
 746  749                  /* FALLTHROUGH */
 747  750          case (LIST_diag):
 748  751                  /* FALLTHROUGH */
 749  752          case (LIST_ohang):
 750  753                  /* FALLTHROUGH */
 751  754          case (LIST_inset):
 752  755                  /* FALLTHROUGH */
 753  756          case (LIST_item):
 754  757                  if (n->norm->Bl.width)
 755  758                          mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV);
 756  759                  break;
      760 +        case (LIST_bullet):
      761 +                /* FALLTHROUGH */
      762 +        case (LIST_dash):
      763 +                /* FALLTHROUGH */
      764 +        case (LIST_hyphen):
      765 +                if (NULL == n->norm->Bl.width)
      766 +                        n->norm->Bl.width = "2n";
      767 +                break;
      768 +        case (LIST_enum):
      769 +                if (NULL == n->norm->Bl.width)
      770 +                        n->norm->Bl.width = "3n";
      771 +                break;
 757  772          default:
 758  773                  break;
 759  774          }
 760  775  
 761  776          return(1);
 762  777  }
 763  778  
 764  779  
 765  780  static int
 766  781  pre_bd(PRE_ARGS)
↓ open down ↓ 100 lines elided ↑ open up ↑
 867  882          return(check_parent(mdoc, n, MDOC_Sh, MDOC_BODY));
 868  883  }
 869  884  
 870  885  
 871  886  static int
 872  887  pre_sh(PRE_ARGS)
 873  888  {
 874  889  
 875  890          if (MDOC_BLOCK != n->type)
 876  891                  return(1);
 877      -
 878      -        roff_regunset(mdoc->roff, REG_nS);
 879  892          return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
 880  893  }
 881  894  
 882  895  
 883  896  static int
 884  897  pre_it(PRE_ARGS)
 885  898  {
 886  899  
 887  900          if (MDOC_BLOCK != n->type)
 888  901                  return(1);
↓ open down ↓ 215 lines elided ↑ open up ↑
1104 1117          return(1);
1105 1118  }
1106 1119  
1107 1120  
1108 1121  static int
1109 1122  post_nm(POST_ARGS)
1110 1123  {
1111 1124          char             buf[BUFSIZ];
1112 1125          int              c;
1113 1126  
1114      -        /* If no child specified, make sure we have the meta name. */
1115      -
1116      -        if (NULL == mdoc->last->child && NULL == mdoc->meta.name) {
1117      -                mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
     1127 +        if (NULL != mdoc->meta.name)
1118 1128                  return(1);
1119      -        } else if (mdoc->meta.name)
1120      -                return(1);
1121 1129  
1122      -        /* If no meta name, set it from the child. */
     1130 +        /* Try to use our children for setting the meta name. */
1123 1131  
1124      -        buf[0] = '\0';
1125      -        if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) {
     1132 +        if (NULL != mdoc->last->child) {
     1133 +                buf[0] = '\0';
     1134 +                c = concat(buf, mdoc->last->child, BUFSIZ);
     1135 +        } else
     1136 +                c = 0;
     1137 +
     1138 +        switch (c) {
     1139 +        case (-1):
1126 1140                  mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM);
1127 1141                  return(0);
     1142 +        case (0):
     1143 +                mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
     1144 +                mdoc->meta.name = mandoc_strdup("UNKNOWN");
     1145 +                break;
     1146 +        default:
     1147 +                mdoc->meta.name = mandoc_strdup(buf);
     1148 +                break;
1128 1149          }
1129      -
1130      -        assert(c);
1131      -        mdoc->meta.name = mandoc_strdup(buf);
1132 1150          return(1);
1133 1151  }
1134 1152  
1135 1153  static int
1136 1154  post_literal(POST_ARGS)
1137 1155  {
1138 1156          
1139 1157          /*
1140 1158           * The `Dl' (note "el" not "one") and `Bd' macros unset the
1141 1159           * MDOC_LITERAL flag as they leave.  Note that `Bd' only sets
↓ open down ↓ 185 lines elided ↑ open up ↑
1327 1345          default:
1328 1346                  break;
1329 1347          }
1330 1348  
1331 1349          return(1);
1332 1350  }
1333 1351  
1334 1352  static int
1335 1353  post_bl_block(POST_ARGS) 
1336 1354  {
1337      -        struct mdoc_node *n;
     1355 +        struct mdoc_node *n, *ni, *nc;
1338 1356  
1339 1357          /*
1340 1358           * These are fairly complicated, so we've broken them into two
1341 1359           * functions.  post_bl_block_tag() is called when a -tag is
1342 1360           * specified, but no -width (it must be guessed).  The second
1343 1361           * when a -width is specified (macro indicators must be
1344 1362           * rewritten into real lengths).
1345 1363           */
1346 1364  
1347 1365          n = mdoc->last;
1348 1366  
1349 1367          if (LIST_tag == n->norm->Bl.type && 
1350 1368                          NULL == n->norm->Bl.width) {
1351 1369                  if ( ! post_bl_block_tag(mdoc))
1352 1370                          return(0);
     1371 +                assert(n->norm->Bl.width);
1353 1372          } else if (NULL != n->norm->Bl.width) {
1354 1373                  if ( ! post_bl_block_width(mdoc))
1355 1374                          return(0);
1356      -        } else 
1357      -                return(1);
     1375 +                assert(n->norm->Bl.width);
     1376 +        }
1358 1377  
1359      -        assert(n->norm->Bl.width);
     1378 +        for (ni = n->body->child; ni; ni = ni->next) {
     1379 +                if (NULL == ni->body)
     1380 +                        continue;
     1381 +                nc = ni->body->last;
     1382 +                while (NULL != nc) {
     1383 +                        switch (nc->tok) {
     1384 +                        case (MDOC_Pp):
     1385 +                                /* FALLTHROUGH */
     1386 +                        case (MDOC_Lp):
     1387 +                                /* FALLTHROUGH */
     1388 +                        case (MDOC_br):
     1389 +                                break;
     1390 +                        default:
     1391 +                                nc = NULL;
     1392 +                                continue;
     1393 +                        }
     1394 +                        if (NULL == ni->next) {
     1395 +                                mdoc_nmsg(mdoc, nc, MANDOCERR_MOVEPAR);
     1396 +                                if ( ! mdoc_node_relink(mdoc, nc))
     1397 +                                        return(0);
     1398 +                        } else if (0 == n->norm->Bl.comp &&
     1399 +                            LIST_column != n->norm->Bl.type) {
     1400 +                                mdoc_nmsg(mdoc, nc, MANDOCERR_IGNPAR);
     1401 +                                mdoc_node_delete(mdoc, nc);
     1402 +                        } else
     1403 +                                break;
     1404 +                        nc = ni->body->last;
     1405 +                }
     1406 +        }
1360 1407          return(1);
1361 1408  }
1362 1409  
1363 1410  static int
1364 1411  post_bl_block_width(POST_ARGS)
1365 1412  {
1366 1413          size_t            width;
1367 1414          int               i;
1368 1415          enum mdoct        tok;
1369 1416          struct mdoc_node *n;
↓ open down ↓ 167 lines elided ↑ open up ↑
1537 1584  
1538 1585          mdoc->last->nchild = 0;
1539 1586          mdoc->last->child = NULL;
1540 1587  
1541 1588          return(1);
1542 1589  }
1543 1590  
1544 1591  static int
1545 1592  post_bl(POST_ARGS)
1546 1593  {
1547      -        struct mdoc_node        *n;
     1594 +        struct mdoc_node        *nparent, *nprev; /* of the Bl block */
     1595 +        struct mdoc_node        *nblock, *nbody;  /* of the Bl */
     1596 +        struct mdoc_node        *nchild, *nnext;  /* of the Bl body */
1548 1597  
1549      -        if (MDOC_HEAD == mdoc->last->type) 
1550      -                return(post_bl_head(mdoc));
1551      -        if (MDOC_BLOCK == mdoc->last->type)
     1598 +        nbody = mdoc->last;
     1599 +        switch (nbody->type) {
     1600 +        case (MDOC_BLOCK):
1552 1601                  return(post_bl_block(mdoc));
1553      -        if (MDOC_BODY != mdoc->last->type)
     1602 +        case (MDOC_HEAD):
     1603 +                return(post_bl_head(mdoc));
     1604 +        case (MDOC_BODY):
     1605 +                break;
     1606 +        default:
1554 1607                  return(1);
     1608 +        }
1555 1609  
1556      -        for (n = mdoc->last->child; n; n = n->next) {
1557      -                switch (n->tok) {
1558      -                case (MDOC_Lp):
1559      -                        /* FALLTHROUGH */
1560      -                case (MDOC_Pp):
1561      -                        mdoc_nmsg(mdoc, n, MANDOCERR_CHILD);
1562      -                        /* FALLTHROUGH */
1563      -                case (MDOC_It):
1564      -                        /* FALLTHROUGH */
1565      -                case (MDOC_Sm):
     1610 +        nchild = nbody->child;
     1611 +        while (NULL != nchild) {
     1612 +                if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
     1613 +                        nchild = nchild->next;
1566 1614                          continue;
1567      -                default:
1568      -                        break;
1569 1615                  }
1570 1616  
1571      -                mdoc_nmsg(mdoc, n, MANDOCERR_SYNTCHILD);
1572      -                return(0);
     1617 +                mdoc_nmsg(mdoc, nchild, MANDOCERR_CHILD);
     1618 +
     1619 +                /*
     1620 +                 * Move the node out of the Bl block.
     1621 +                 * First, collect all required node pointers.
     1622 +                 */
     1623 +
     1624 +                nblock  = nbody->parent;
     1625 +                nprev   = nblock->prev;
     1626 +                nparent = nblock->parent;
     1627 +                nnext   = nchild->next;
     1628 +
     1629 +                /*
     1630 +                 * Unlink this child.
     1631 +                 */
     1632 +
     1633 +                assert(NULL == nchild->prev);
     1634 +                if (0 == --nbody->nchild) {
     1635 +                        nbody->child = NULL;
     1636 +                        nbody->last  = NULL;
     1637 +                        assert(NULL == nnext);
     1638 +                } else {
     1639 +                        nbody->child = nnext;
     1640 +                        nnext->prev = NULL;
     1641 +                }
     1642 +
     1643 +                /*
     1644 +                 * Relink this child.
     1645 +                 */
     1646 +
     1647 +                nchild->parent = nparent;
     1648 +                nchild->prev   = nprev;
     1649 +                nchild->next   = nblock;
     1650 +
     1651 +                nblock->prev = nchild;
     1652 +                nparent->nchild++;
     1653 +                if (NULL == nprev)
     1654 +                        nparent->child = nchild;
     1655 +                else
     1656 +                        nprev->next = nchild;
     1657 +
     1658 +                nchild = nnext;
1573 1659          }
1574 1660  
1575 1661          return(1);
1576 1662  }
1577 1663  
1578 1664  static int
1579 1665  ebool(struct mdoc *mdoc)
1580 1666  {
1581 1667  
1582 1668          if (NULL == mdoc->last->child) {
1583 1669                  mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY);
1584 1670                  mdoc_node_delete(mdoc, mdoc->last);
1585 1671                  return(1);
1586 1672          }
1587 1673          check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
1588 1674  
1589 1675          assert(MDOC_TEXT == mdoc->last->child->type);
1590 1676  
1591      -        if (0 == strcmp(mdoc->last->child->string, "on"))
     1677 +        if (0 == strcmp(mdoc->last->child->string, "on")) {
     1678 +                if (MDOC_Sm == mdoc->last->tok)
     1679 +                        mdoc->flags &= ~MDOC_SMOFF;
1592 1680                  return(1);
1593      -        if (0 == strcmp(mdoc->last->child->string, "off"))
     1681 +        }
     1682 +        if (0 == strcmp(mdoc->last->child->string, "off")) {
     1683 +                if (MDOC_Sm == mdoc->last->tok)
     1684 +                        mdoc->flags |= MDOC_SMOFF;
1594 1685                  return(1);
     1686 +        }
1595 1687  
1596 1688          mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL);
1597 1689          return(1);
1598 1690  }
1599 1691  
1600 1692  static int
1601 1693  post_root(POST_ARGS)
1602 1694  {
1603 1695          int               erc;
1604 1696          struct mdoc_node *n;
↓ open down ↓ 159 lines elided ↑ open up ↑
1764 1856                  } else {
1765 1857                          mdoc->last->child->prev = nn;
1766 1858                          nn->next = mdoc->last->child;
1767 1859                          mdoc->last->child = nn;
1768 1860                  }
1769 1861          }
1770 1862  
1771 1863          return(1);
1772 1864  }
1773 1865  
     1866 +/*
     1867 + * For some arguments of some macros,
     1868 + * convert all breakable hyphens into ASCII_HYPH.
     1869 + */
1774 1870  static int
     1871 +post_hyph(POST_ARGS)
     1872 +{
     1873 +        struct mdoc_node        *n, *nch;
     1874 +        char                    *cp;
     1875 +
     1876 +        n = mdoc->last;
     1877 +        switch (n->type) {
     1878 +        case (MDOC_HEAD):
     1879 +                if (MDOC_Sh == n->tok || MDOC_Ss == n->tok)
     1880 +                        break;
     1881 +                return(1);
     1882 +        case (MDOC_BODY):
     1883 +                if (MDOC_D1 == n->tok || MDOC_Nd == n->tok)
     1884 +                        break;
     1885 +                return(1);
     1886 +        case (MDOC_ELEM):
     1887 +                break;
     1888 +        default:
     1889 +                return(1);
     1890 +        }
     1891 +
     1892 +        for (nch = n->child; nch; nch = nch->next) {
     1893 +                if (MDOC_TEXT != nch->type)
     1894 +                        continue;
     1895 +                cp = nch->string;
     1896 +                if (3 > strnlen(cp, 3))
     1897 +                        continue;
     1898 +                while ('\0' != *(++cp))
     1899 +                        if ('-' == *cp &&
     1900 +                            isalpha((unsigned char)cp[-1]) &&
     1901 +                            isalpha((unsigned char)cp[1]))
     1902 +                                *cp = ASCII_HYPH;
     1903 +        }
     1904 +        return(1);
     1905 +}
     1906 +
     1907 +static int
1775 1908  post_ns(POST_ARGS)
1776 1909  {
1777 1910  
1778 1911          if (MDOC_LINE & mdoc->last->flags)
1779 1912                  mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNNS);
1780 1913          return(1);
1781 1914  }
1782 1915  
1783 1916  static int
1784 1917  post_sh(POST_ARGS)
↓ open down ↓ 65 lines elided ↑ open up ↑
1850 1983          } else if (1 == c)
1851 1984                  sec = a2sec(buf);
1852 1985  
1853 1986          /* The NAME should be first. */
1854 1987  
1855 1988          if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
1856 1989                  mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NAMESECFIRST);
1857 1990  
1858 1991          /* The SYNOPSIS gets special attention in other areas. */
1859 1992  
1860      -        if (SEC_SYNOPSIS == sec)
     1993 +        if (SEC_SYNOPSIS == sec) {
     1994 +                roff_setreg(mdoc->roff, "nS", 1, '=');
1861 1995                  mdoc->flags |= MDOC_SYNOPSIS;
1862      -        else
     1996 +        } else {
     1997 +                roff_setreg(mdoc->roff, "nS", 0, '=');
1863 1998                  mdoc->flags &= ~MDOC_SYNOPSIS;
     1999 +        }
1864 2000  
1865 2001          /* Mark our last section. */
1866 2002  
1867 2003          mdoc->lastsec = sec;
1868 2004  
1869 2005          /*
1870 2006           * Set the section attribute for the current HEAD, for its
1871 2007           * parent BLOCK, and for the HEAD children; the latter can
1872 2008           * only be TEXT nodes, so no recursion is needed.
1873 2009           * For other blocks and elements, including .Sh BODY, this is
↓ open down ↓ 35 lines elided ↑ open up ↑
1909 2045                  /* FALLTHROUGH */
1910 2046          case (SEC_ERRORS):
1911 2047                  /* FALLTHROUGH */
1912 2048          case (SEC_LIBRARY):
1913 2049                  if (*mdoc->meta.msec == '2')
1914 2050                          break;
1915 2051                  if (*mdoc->meta.msec == '3')
1916 2052                          break;
1917 2053                  if (*mdoc->meta.msec == '9')
1918 2054                          break;
1919      -                mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECMSEC);
     2055 +                mandoc_msg(MANDOCERR_SECMSEC, mdoc->parse,
     2056 +                                mdoc->last->line, mdoc->last->pos, buf);
1920 2057                  break;
1921 2058          default:
1922 2059                  break;
1923 2060          }
1924 2061  
1925 2062          return(1);
1926 2063  }
1927 2064  
1928 2065  static int
1929 2066  post_ignpar(POST_ARGS)
↓ open down ↓ 25 lines elided ↑ open up ↑
1955 2092          if (NULL == mdoc->last)
1956 2093                  return(1);
1957 2094          if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type)
1958 2095                  return(1);
1959 2096  
1960 2097          /* 
1961 2098           * Don't allow prior `Lp' or `Pp' prior to a paragraph-type
1962 2099           * block:  `Lp', `Pp', or non-compact `Bd' or `Bl'.
1963 2100           */
1964 2101  
1965      -        if (MDOC_Pp != mdoc->last->tok && MDOC_Lp != mdoc->last->tok)
     2102 +        if (MDOC_Pp != mdoc->last->tok &&
     2103 +            MDOC_Lp != mdoc->last->tok &&
     2104 +            MDOC_br != mdoc->last->tok)
1966 2105                  return(1);
1967 2106          if (MDOC_Bl == n->tok && n->norm->Bl.comp)
1968 2107                  return(1);
1969 2108          if (MDOC_Bd == n->tok && n->norm->Bd.comp)
1970 2109                  return(1);
1971 2110          if (MDOC_It == n->tok && n->parent->norm->Bl.comp)
1972 2111                  return(1);
1973 2112  
1974 2113          mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR);
1975 2114          mdoc_node_delete(mdoc, mdoc->last);
1976 2115          return(1);
1977 2116  }
1978 2117  
1979 2118  static int
     2119 +post_par(POST_ARGS)
     2120 +{
     2121 +
     2122 +        if (MDOC_ELEM != mdoc->last->type &&
     2123 +            MDOC_BLOCK != mdoc->last->type)
     2124 +                return(1);
     2125 +
     2126 +        if (NULL == mdoc->last->prev) {
     2127 +                if (MDOC_Sh != mdoc->last->parent->tok &&
     2128 +                    MDOC_Ss != mdoc->last->parent->tok)
     2129 +                        return(1);
     2130 +        } else {
     2131 +                if (MDOC_Pp != mdoc->last->prev->tok &&
     2132 +                    MDOC_Lp != mdoc->last->prev->tok &&
     2133 +                    (MDOC_br != mdoc->last->tok ||
     2134 +                     (MDOC_sp != mdoc->last->prev->tok &&
     2135 +                      MDOC_br != mdoc->last->prev->tok)))
     2136 +                        return(1);
     2137 +        }
     2138 +
     2139 +        mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR);
     2140 +        mdoc_node_delete(mdoc, mdoc->last);
     2141 +        return(1);
     2142 +}
     2143 +
     2144 +static int
1980 2145  pre_literal(PRE_ARGS)
1981 2146  {
1982 2147  
1983 2148          if (MDOC_BODY != n->type)
1984 2149                  return(1);
1985 2150  
1986 2151          /*
1987 2152           * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd
1988 2153           * -unfilled' macros set MDOC_LITERAL on entrance to the body.
1989 2154           */
↓ open down ↓ 132 lines elided ↑ open up ↑
2122 2287           *       format(VOL) : 
2123 2288           *           VOL is arch ? format(arch) : 
2124 2289           *               VOL
2125 2290           */
2126 2291  
2127 2292          cp = mdoc_a2vol(nn->string);
2128 2293          if (cp) {
2129 2294                  free(mdoc->meta.vol);
2130 2295                  mdoc->meta.vol = mandoc_strdup(cp);
2131 2296          } else {
2132      -                /* FIXME: warn about bad arch. */
2133 2297                  cp = mdoc_a2arch(nn->string);
2134 2298                  if (NULL == cp) {
     2299 +                        mdoc_nmsg(mdoc, nn, MANDOCERR_BADVOLARCH);
2135 2300                          free(mdoc->meta.vol);
2136 2301                          mdoc->meta.vol = mandoc_strdup(nn->string);
2137 2302                  } else 
2138 2303                          mdoc->meta.arch = mandoc_strdup(cp);
2139 2304          }       
2140 2305  
2141 2306          /* Ignore any subsequent parameters... */
2142 2307          /* FIXME: warn about subsequent parameters. */
2143 2308  
2144 2309          return(1);
↓ open down ↓ 40 lines elided ↑ open up ↑
2185 2350          struct mdoc_node *n;
2186 2351          char              buf[BUFSIZ];
2187 2352          int               c;
2188 2353  #ifndef OSNAME
2189 2354          struct utsname    utsname;
2190 2355  #endif
2191 2356  
2192 2357          n = mdoc->last;
2193 2358  
2194 2359          /*
2195      -         * Set the operating system by way of the `Os' macro.  Note that
2196      -         * if an argument isn't provided and -DOSNAME="\"foo\"" is
2197      -         * provided during compilation, this value will be used instead
2198      -         * of filling in "sysname release" from uname().
     2360 +         * Set the operating system by way of the `Os' macro.
     2361 +         * The order of precedence is:
     2362 +         * 1. the argument of the `Os' macro, unless empty
     2363 +         * 2. the -Ios=foo command line argument, if provided
     2364 +         * 3. -DOSNAME="\"foo\"", if provided during compilation
     2365 +         * 4. "sysname release" from uname(3)
2199 2366           */
2200 2367  
2201      -        if (mdoc->meta.os)
2202      -                free(mdoc->meta.os);
     2368 +        free(mdoc->meta.os);
2203 2369  
2204 2370          buf[0] = '\0';
2205 2371          if (-1 == (c = concat(buf, n->child, BUFSIZ))) {
2206 2372                  mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM);
2207 2373                  return(0);
2208 2374          }
2209 2375  
2210 2376          assert(c);
2211 2377  
2212      -        /* XXX: yes, these can all be dynamically-adjusted buffers, but
2213      -         * it's really not worth the extra hackery.
2214      -         */
2215      -
2216 2378          if ('\0' == buf[0]) {
     2379 +                if (mdoc->defos) {
     2380 +                        mdoc->meta.os = mandoc_strdup(mdoc->defos);
     2381 +                        return(1);
     2382 +                }
2217 2383  #ifdef OSNAME
2218 2384                  if (strlcat(buf, OSNAME, BUFSIZ) >= BUFSIZ) {
2219 2385                          mdoc_nmsg(mdoc, n, MANDOCERR_MEM);
2220 2386                          return(0);
2221 2387                  }
2222 2388  #else /*!OSNAME */
2223 2389                  if (-1 == uname(&utsname)) {
2224 2390                          mdoc_nmsg(mdoc, n, MANDOCERR_UNAME);
2225 2391                          mdoc->meta.os = mandoc_strdup("UNKNOWN");
2226 2392                          return(post_prol(mdoc));
↓ open down ↓ 177 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX