[BACK]Return to roff.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/roff.c between version 1.375 and 1.386

version 1.375, 2020/08/03 11:02:57 version 1.386, 2022/04/30 18:51:36
Line 1 
Line 1 
 /* $Id$ */  /* $Id$ */
 /*  /*
  * Copyright (c) 2010-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010-2015, 2017-2022 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
Line 227  static int   roff_line_ignore(ROFF_ARGS);
Line 227  static int   roff_line_ignore(ROFF_ARGS);
 static  void             roff_man_alloc1(struct roff_man *);  static  void             roff_man_alloc1(struct roff_man *);
 static  void             roff_man_free1(struct roff_man *);  static  void             roff_man_free1(struct roff_man *);
 static  int              roff_manyarg(ROFF_ARGS);  static  int              roff_manyarg(ROFF_ARGS);
   static  int              roff_mc(ROFF_ARGS);
 static  int              roff_noarg(ROFF_ARGS);  static  int              roff_noarg(ROFF_ARGS);
 static  int              roff_nop(ROFF_ARGS);  static  int              roff_nop(ROFF_ARGS);
 static  int              roff_nr(ROFF_ARGS);  static  int              roff_nr(ROFF_ARGS);
Line 236  static enum roff_tok  roff_parse(struct roff *, char *
Line 237  static enum roff_tok  roff_parse(struct roff *, char *
 static  int              roff_parsetext(struct roff *, struct buf *,  static  int              roff_parsetext(struct roff *, struct buf *,
                                 int, int *);                                  int, int *);
 static  int              roff_renamed(ROFF_ARGS);  static  int              roff_renamed(ROFF_ARGS);
   static  int              roff_req_or_macro(ROFF_ARGS);
 static  int              roff_return(ROFF_ARGS);  static  int              roff_return(ROFF_ARGS);
 static  int              roff_rm(ROFF_ARGS);  static  int              roff_rm(ROFF_ARGS);
 static  int              roff_rn(ROFF_ARGS);  static  int              roff_rn(ROFF_ARGS);
Line 379  static struct roffmac  roffs[TOKEN_NONE] = {
Line 381  static struct roffmac  roffs[TOKEN_NONE] = {
         { roff_noarg, NULL, NULL, 0 },  /* fi */          { roff_noarg, NULL, NULL, 0 },  /* fi */
         { roff_onearg, NULL, NULL, 0 },  /* ft */          { roff_onearg, NULL, NULL, 0 },  /* ft */
         { roff_onearg, NULL, NULL, 0 },  /* ll */          { roff_onearg, NULL, NULL, 0 },  /* ll */
         { roff_onearg, NULL, NULL, 0 },  /* mc */          { roff_mc, NULL, NULL, 0 },  /* mc */
         { roff_noarg, NULL, NULL, 0 },  /* nf */          { roff_noarg, NULL, NULL, 0 },  /* nf */
         { roff_onearg, NULL, NULL, 0 },  /* po */          { roff_onearg, NULL, NULL, 0 },  /* po */
         { roff_onearg, NULL, NULL, 0 },  /* rj */          { roff_onearg, NULL, NULL, 0 },  /* rj */
Line 861  void
Line 863  void
 roff_man_free(struct roff_man *man)  roff_man_free(struct roff_man *man)
 {  {
         roff_man_free1(man);          roff_man_free1(man);
           free(man->os_r);
         free(man);          free(man);
 }  }
   
Line 1400  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1403  roff_expand(struct roff *r, struct buf *buf, int ln, i
   
                 term = '\0';                  term = '\0';
                 cp = stesc + 1;                  cp = stesc + 1;
                 if (*cp == 'E')                  while (*cp == 'E')
                         cp++;                          cp++;
                 esct = cp;                  esct = cp;
                 switch (*esct) {                  switch (*esct) {
Line 1823  roff_parsetext(struct roff *r, struct buf *buf, int po
Line 1826  roff_parsetext(struct roff *r, struct buf *buf, int po
 }  }
   
 int  int
 roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)  roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs, size_t len)
 {  {
         enum roff_tok    t;          enum roff_tok    t;
         int              e;          int              e;
Line 1834  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1837  roff_parseln(struct roff *r, int ln, struct buf *buf, 
   
         ppos = pos = *offs;          ppos = pos = *offs;
   
           if (len > 80 && r->tbl == NULL && r->eqn == NULL &&
               (r->man->flags & ROFF_NOFILL) == 0 &&
               strchr(" .\\", buf->buf[pos]) == NULL &&
               buf->buf[pos] != r->control &&
               strcspn(buf->buf, " ") < 80)
                   mandoc_msg(MANDOCERR_TEXT_LONG, ln, (int)len - 1,
                       "%.20s...", buf->buf + pos);
   
         /* Handle in-line equation delimiters. */          /* Handle in-line equation delimiters. */
   
         if (r->tbl == NULL &&          if (r->tbl == NULL &&
Line 1895  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1906  roff_parseln(struct roff *r, int ln, struct buf *buf, 
         /*          /*
          * If a scope is open, go to the child handler for that macro,           * If a scope is open, go to the child handler for that macro,
          * as it may want to preprocess before doing anything with it.           * as it may want to preprocess before doing anything with it.
          * Don't do so if an equation is open.  
          */           */
   
         if (r->last) {          if (r->last) {
Line 1903  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1913  roff_parseln(struct roff *r, int ln, struct buf *buf, 
                 return (*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs);                  return (*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs);
         }          }
   
         /* No scope is open.  This is a new request or macro. */  
   
         r->options &= ~MPARSE_COMMENT;          r->options &= ~MPARSE_COMMENT;
         spos = pos;          spos = pos;
         t = roff_parse(r, buf->buf, &pos, ln, ppos);          t = roff_parse(r, buf->buf, &pos, ln, ppos);
           return roff_req_or_macro(r, t, buf, ln, spos, pos, offs);
   }
   
         /* Tables ignore most macros. */  /*
    * Handle a new request or macro.
    * May be called outside any scope or from inside a conditional scope.
    */
   static int
   roff_req_or_macro(ROFF_ARGS) {
   
         if (r->tbl != NULL && (t == TOKEN_NONE || t == ROFF_TS ||          /* For now, tables ignore most macros and some request. */
             t == ROFF_br || t == ROFF_ce || t == ROFF_rj || t == ROFF_sp)) {  
           if (r->tbl != NULL && (tok == TOKEN_NONE || tok == ROFF_TS ||
               tok == ROFF_br || tok == ROFF_ce || tok == ROFF_rj ||
               tok == ROFF_sp)) {
                 mandoc_msg(MANDOCERR_TBLMACRO,                  mandoc_msg(MANDOCERR_TBLMACRO,
                     ln, pos, "%s", buf->buf + spos);                      ln, ppos, "%s", buf->buf + ppos);
                 if (t != TOKEN_NONE)                  if (tok != TOKEN_NONE)
                         return ROFF_IGN;                          return ROFF_IGN;
                 while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ')                  while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ')
                         pos++;                          pos++;
Line 1928  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1946  roff_parseln(struct roff *r, int ln, struct buf *buf, 
   
         /* For now, let high level macros abort .ce mode. */          /* For now, let high level macros abort .ce mode. */
   
         if (ctl && roffce_node != NULL &&          if (roffce_node != NULL &&
             (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ ||              (tok == TOKEN_NONE || tok == ROFF_Dd || tok == ROFF_EQ ||
              t == ROFF_TH || t == ROFF_TS)) {               tok == ROFF_TH || tok == ROFF_TS)) {
                 r->man->last = roffce_node;                  r->man->last = roffce_node;
                 r->man->next = ROFF_NEXT_SIBLING;                  r->man->next = ROFF_NEXT_SIBLING;
                 roffce_lines = 0;                  roffce_lines = 0;
Line 1942  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1960  roff_parseln(struct roff *r, int ln, struct buf *buf, 
          * Let the standard macro set parsers handle it.           * Let the standard macro set parsers handle it.
          */           */
   
         if (t == TOKEN_NONE)          if (tok == TOKEN_NONE)
                 return ROFF_CONT;                  return ROFF_CONT;
   
         /* Execute a roff request or a user defined macro. */          /* Execute a roff request or a user-defined macro. */
   
         return (*roffs[t].proc)(r, t, buf, ln, spos, pos, offs);          return (*roffs[tok].proc)(r, tok, buf, ln, ppos, pos, offs);
 }  }
   
 /*  /*
Line 1990  roff_endparse(struct roff *r)
Line 2008  roff_endparse(struct roff *r)
 }  }
   
 /*  /*
  * Parse a roff node's type from the input buffer.  This must be in the   * Parse the request or macro name at buf[*pos].
  * form of ".foo xxx" in the usual way.   * Return ROFF_RENAMED, ROFF_USERDEF, or a ROFF_* token value.
    * For empty, undefined, mdoc(7), and man(7) macros, return TOKEN_NONE.
    * As a side effect, set r->current_string to the definition or to NULL.
  */   */
 static enum roff_tok  static enum roff_tok
 roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos)  roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos)
Line 2266  roff_block_sub(ROFF_ARGS)
Line 2286  roff_block_sub(ROFF_ARGS)
         int             i, j;          int             i, j;
   
         /*          /*
          * First check whether a custom macro exists at this level.  If           * If a custom end marker is a user-defined or predefined macro
          * it does, then check against it.  This is some of groff's           * or a request, interpret it.
          * stranger behaviours.  If we encountered a custom end-scope  
          * tag and that tag also happens to be a "real" macro, then we  
          * need to try interpreting it again as a real macro.  If it's  
          * not, then return ignore.  Else continue.  
          */           */
   
         if (r->last->end) {          if (r->last->end) {
Line 2297  roff_block_sub(ROFF_ARGS)
Line 2313  roff_block_sub(ROFF_ARGS)
                 }                  }
         }          }
   
         /*          /* Handle the standard end marker. */
          * If we have no custom end-query or lookup failed, then try  
          * pulling it out of the hashtable.  
          */  
   
         t = roff_parse(r, buf->buf, &pos, ln, ppos);          t = roff_parse(r, buf->buf, &pos, ln, ppos);
           if (t == ROFF_cblock)
                   return roff_cblock(r, t, buf, ln, ppos, pos, offs);
   
         if (t != ROFF_cblock) {          /* Not an end marker, so append the line to the block. */
                 if (tok != ROFF_ig)  
                         roff_setstr(r, r->last->name, buf->buf + ppos, 2);  
                 return ROFF_IGN;  
         }  
   
         return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);          if (tok != ROFF_ig)
                   roff_setstr(r, r->last->name, buf->buf + ppos, 2);
           return ROFF_IGN;
 }  }
   
 static int  static int
Line 2362  roff_cond_checkend(ROFF_ARGS)
Line 2375  roff_cond_checkend(ROFF_ARGS)
         while ((ep = strchr(ep, '\\')) != NULL) {          while ((ep = strchr(ep, '\\')) != NULL) {
                 switch (ep[1]) {                  switch (ep[1]) {
                 case '}':                  case '}':
                         if (rr)                          if (ep[2] == '\0')
                                   ep[0] = '\0';
                           else if (rr)
                                 ep[1] = '&';                                  ep[1] = '&';
                         else                          else
                                 memmove(ep, ep + 2, strlen(ep + 2) + 1);                                  memmove(ep, ep + 2, strlen(ep + 2) + 1);
Line 2388  static int
Line 2403  static int
 roff_cond_sub(ROFF_ARGS)  roff_cond_sub(ROFF_ARGS)
 {  {
         struct roffnode *bl;          struct roffnode *bl;
         int              irc, rr;          int              irc, rr, spos;
         enum roff_tok    t;          enum roff_tok    t;
   
         rr = 0;  /* If arguments follow "\}", skip them. */          rr = 0;  /* If arguments follow "\}", skip them. */
         irc = roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);          irc = roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
           spos = pos;
         t = roff_parse(r, buf->buf, &pos, ln, ppos);          t = roff_parse(r, buf->buf, &pos, ln, ppos);
   
         /* For now, let high level macros abort .ce mode. */  
   
         if (roffce_node != NULL &&  
             (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ ||  
              t == ROFF_TH || t == ROFF_TS)) {  
                 r->man->last = roffce_node;  
                 r->man->next = ROFF_NEXT_SIBLING;  
                 roffce_lines = 0;  
                 roffce_node = NULL;  
         }  
   
         /*          /*
          * Fully handle known macros when they are structurally           * Handle requests and macros if the conditional evaluated
          * required or when the conditional evaluated to true.           * to true or if they are structurally required.
            * The .break request is always handled specially.
          */           */
   
         if (t == ROFF_break) {          if (t == ROFF_break) {
Line 2421  roff_cond_sub(ROFF_ARGS)
Line 2427  roff_cond_sub(ROFF_ARGS)
                                         break;                                          break;
                         }                          }
                 }                  }
         } else if (t != TOKEN_NONE &&          } else if (rr || (t < TOKEN_NONE && roffs[t].flags & ROFFMAC_STRUCT)) {
             (rr || roffs[t].flags & ROFFMAC_STRUCT))                  irc |= roff_req_or_macro(r, t, buf, ln, spos, pos, offs);
                 irc |= (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);                  if (irc & ROFF_WHILE)
         else                          irc &= ~(ROFF_LOOPCONT | ROFF_LOOPEXIT);
                 irc |= rr ? ROFF_CONT : ROFF_IGN;          }
         return irc;          return irc;
 }  }
   
Line 3657  roff_char(ROFF_ARGS)
Line 3663  roff_char(ROFF_ARGS)
                 case ESCAPE_FONTITALIC:                  case ESCAPE_FONTITALIC:
                 case ESCAPE_FONTBOLD:                  case ESCAPE_FONTBOLD:
                 case ESCAPE_FONTBI:                  case ESCAPE_FONTBI:
                 case ESCAPE_FONTCW:                  case ESCAPE_FONTCR:
                   case ESCAPE_FONTCB:
                   case ESCAPE_FONTCI:
                 case ESCAPE_FONTPREV:                  case ESCAPE_FONTPREV:
                         font++;                          font++;
                         break;                          break;
Line 3717  roff_eo(ROFF_ARGS)
Line 3725  roff_eo(ROFF_ARGS)
 }  }
   
 static int  static int
   roff_mc(ROFF_ARGS)
   {
           struct roff_node        *n;
           char                    *cp;
   
           /* Parse the first argument. */
   
           cp = buf->buf + pos;
           if (*cp != '\0')
                   cp++;
           if (buf->buf[pos] == '\\') {
                   switch (mandoc_escape((const char **)&cp, NULL, NULL)) {
                   case ESCAPE_SPECIAL:
                   case ESCAPE_UNICODE:
                   case ESCAPE_NUMBERED:
                           break;
                   default:
                           *cp = '\0';
                           mandoc_msg(MANDOCERR_MC_ESC, ln, pos,
                               "mc %s", buf->buf + pos);
                           buf->buf[pos] = '\0';
                           break;
                   }
           }
   
           /* Ignore additional arguments. */
   
           while (*cp == ' ')
                   *cp++ = '\0';
           if (*cp != '\0') {
                   mandoc_msg(MANDOCERR_MC_DIST, ln, (int)(cp - buf->buf),
                       "mc ... %s", cp);
                   *cp = '\0';
           }
   
           /* Create the .mc node. */
   
           roff_elem_alloc(r->man, ln, ppos, tok);
           n = r->man->last;
           if (buf->buf[pos] != '\0')
                   roff_word_alloc(r->man, ln, pos, buf->buf + pos);
           n->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
           r->man->last = n;
           r->man->next = ROFF_NEXT_SIBLING;
           return ROFF_IGN;
   }
   
   static int
 roff_nop(ROFF_ARGS)  roff_nop(ROFF_ARGS)
 {  {
         while (buf->buf[pos] == ' ')          while (buf->buf[pos] == ' ')
Line 3857  static int
Line 3913  static int
 roff_shift(ROFF_ARGS)  roff_shift(ROFF_ARGS)
 {  {
         struct mctx     *ctx;          struct mctx     *ctx;
         int              levels, i;          int              argpos, levels, i;
   
           argpos = pos;
         levels = 1;          levels = 1;
         if (buf->buf[pos] != '\0' &&          if (buf->buf[pos] != '\0' &&
             roff_evalnum(r, ln, buf->buf, &pos, &levels, 0) == 0) {              roff_evalnum(r, ln, buf->buf, &pos, &levels, 0) == 0) {
Line 3873  roff_shift(ROFF_ARGS)
Line 3930  roff_shift(ROFF_ARGS)
         ctx = r->mstack + r->mstackpos;          ctx = r->mstack + r->mstackpos;
         if (levels > ctx->argc) {          if (levels > ctx->argc) {
                 mandoc_msg(MANDOCERR_SHIFT,                  mandoc_msg(MANDOCERR_SHIFT,
                     ln, pos, "%d, but max is %d", levels, ctx->argc);                      ln, argpos, "%d, but max is %d", levels, ctx->argc);
                 levels = ctx->argc;                  levels = ctx->argc;
         }          }
           if (levels < 0) {
                   mandoc_msg(MANDOCERR_ARG_NEG, ln, argpos, "shift %d", levels);
                   levels = 0;
           }
         if (levels == 0)          if (levels == 0)
                 return ROFF_IGN;                  return ROFF_IGN;
         for (i = 0; i < levels; i++)          for (i = 0; i < levels; i++)
Line 3937  roff_userdef(ROFF_ARGS)
Line 3998  roff_userdef(ROFF_ARGS)
                 r->mstacksz += 8;                  r->mstacksz += 8;
         }          }
         ctx = r->mstack + r->mstackpos;          ctx = r->mstack + r->mstackpos;
         ctx->argsz = 0;  
         ctx->argc = 0;          ctx->argc = 0;
         ctx->argv = NULL;  
   
         /*          /*
          * Collect pointers to macro argument strings,           * Collect pointers to macro argument strings,

Legend:
Removed from v.1.375  
changed lines
  Added in v.1.386

CVSweb