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

Diff for /mandoc/eqn.c between version 1.80 and 1.85

version 1.80, 2018/12/13 03:40:13 version 1.85, 2022/04/13 20:26:19
Line 1 
Line 1 
 /*      $Id$ */  /* $Id$ */
 /*  /*
    * Copyright (c) 2014, 2015, 2017, 2018, 2020, 2022
    *               Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>  
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 30 
Line 31 
 #include "mandoc_aux.h"  #include "mandoc_aux.h"
 #include "mandoc.h"  #include "mandoc.h"
 #include "roff.h"  #include "roff.h"
   #include "eqn.h"
 #include "libmandoc.h"  #include "libmandoc.h"
 #include "eqn_parse.h"  #include "eqn_parse.h"
   
Line 302  static void   eqn_undef(struct eqn_node *);
Line 304  static void   eqn_undef(struct eqn_node *);
   
   
 struct eqn_node *  struct eqn_node *
 eqn_alloc(struct mparse *parse)  eqn_alloc(void)
 {  {
         struct eqn_node *ep;          struct eqn_node *ep;
   
         ep = mandoc_calloc(1, sizeof(*ep));          ep = mandoc_calloc(1, sizeof(*ep));
         ep->parse = parse;  
         ep->gsize = EQN_DEFSIZE;          ep->gsize = EQN_DEFSIZE;
         return ep;          return ep;
 }  }
Line 375  eqn_def_find(struct eqn_node *ep)
Line 376  eqn_def_find(struct eqn_node *ep)
 static enum eqn_tok  static enum eqn_tok
 eqn_next(struct eqn_node *ep, enum parse_mode mode)  eqn_next(struct eqn_node *ep, enum parse_mode mode)
 {  {
         static int       last_len, lim;  
   
         struct eqn_def  *def;          struct eqn_def  *def;
         size_t           start;          size_t           start;
         int              diff, i, quoted;          int              diff, i, newlen, quoted;
         enum eqn_tok     tok;          enum eqn_tok     tok;
   
         /*          /*
          * Reset the recursion counter after advancing           * Reset the recursion counter after advancing
          * beyond the end of the previous substitution.           * beyond the end of the rightmost substitution.
          */           */
         if (ep->end - ep->data >= last_len)          if (ep->end - ep->data >= ep->sublen)
                 lim = 0;                  ep->subcnt = 0;
   
         ep->start = ep->end;          ep->start = ep->end;
         quoted = mode == MODE_QUOTED;          quoted = mode == MODE_QUOTED;
Line 399  eqn_next(struct eqn_node *ep, enum parse_mode mode)
Line 398  eqn_next(struct eqn_node *ep, enum parse_mode mode)
                 case '"':                  case '"':
                         quoted = 1;                          quoted = 1;
                         break;                          break;
                   case ' ':
                   case '\t':
                   case '~':
                   case '^':
                           if (quoted)
                                   break;
                           ep->start++;
                           continue;
                 default:                  default:
                         break;                          break;
                 }                  }
Line 406  eqn_next(struct eqn_node *ep, enum parse_mode mode)
Line 413  eqn_next(struct eqn_node *ep, enum parse_mode mode)
                         ep->end = strchr(ep->start + 1, *ep->start);                          ep->end = strchr(ep->start + 1, *ep->start);
                         ep->start++;  /* Skip opening quote. */                          ep->start++;  /* Skip opening quote. */
                         if (ep->end == NULL) {                          if (ep->end == NULL) {
                                 mandoc_msg(MANDOCERR_ARG_QUOTE, ep->parse,                                  mandoc_msg(MANDOCERR_ARG_QUOTE,
                                     ep->node->line, ep->node->pos, NULL);                                      ep->node->line, ep->node->pos, NULL);
                                 ep->end = strchr(ep->start, '\0');                                  ep->end = strchr(ep->start, '\0');
                         }                          }
Line 426  eqn_next(struct eqn_node *ep, enum parse_mode mode)
Line 433  eqn_next(struct eqn_node *ep, enum parse_mode mode)
                         return EQN_TOK__MAX;                          return EQN_TOK__MAX;
                 if ((def = eqn_def_find(ep)) == NULL)                  if ((def = eqn_def_find(ep)) == NULL)
                         break;                          break;
                 if (++lim > EQN_NEST_MAX) {                  if (++ep->subcnt > EQN_NEST_MAX) {
                         mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse,                          mandoc_msg(MANDOCERR_ROFFLOOP,
                             ep->node->line, ep->node->pos, NULL);                              ep->node->line, ep->node->pos, NULL);
                         return EQN_TOK_EOF;                          break;
                 }                  }
   
                 /* Replace a defined name with its string value. */                  /* Replace a defined name with its string value. */
Line 438  eqn_next(struct eqn_node *ep, enum parse_mode mode)
Line 445  eqn_next(struct eqn_node *ep, enum parse_mode mode)
                         ep->sz += diff;                          ep->sz += diff;
                         ep->data = mandoc_realloc(ep->data, ep->sz + 1);                          ep->data = mandoc_realloc(ep->data, ep->sz + 1);
                         ep->start = ep->data + start;                          ep->start = ep->data + start;
                           ep->sublen += diff;
                 }                  }
                 if (diff)                  if (diff)
                         memmove(ep->start + def->valsz, ep->start + ep->toksz,                          memmove(ep->start + def->valsz, ep->start + ep->toksz,
                             strlen(ep->start + ep->toksz) + 1);                              strlen(ep->start + ep->toksz) + 1);
                 memcpy(ep->start, def->val, def->valsz);                  memcpy(ep->start, def->val, def->valsz);
                 last_len = ep->start - ep->data + def->valsz;                  newlen = ep->start - ep->data + def->valsz;
                   if (ep->sublen < newlen)
                           ep->sublen = newlen;
         }          }
         if (mode != MODE_TOK)          if (mode != MODE_TOK)
                 return quoted ? EQN_TOK_QUOTED : EQN_TOK__MAX;                  return quoted ? EQN_TOK_QUOTED : EQN_TOK__MAX;
Line 491  eqn_box_free(struct eqn_box *bp)
Line 501  eqn_box_free(struct eqn_box *bp)
         free(bp);          free(bp);
 }  }
   
   struct eqn_box *
   eqn_box_new(void)
   {
           struct eqn_box  *bp;
   
           bp = mandoc_calloc(1, sizeof(*bp));
           bp->expectargs = UINT_MAX;
           return bp;
   }
   
 /*  /*
  * Allocate a box as the last child of the parent node.   * Allocate a box as the last child of the parent node.
  */   */
Line 499  eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par
Line 519  eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par
 {  {
         struct eqn_box  *bp;          struct eqn_box  *bp;
   
         bp = mandoc_calloc(1, sizeof(struct eqn_box));          bp = eqn_box_new();
         bp->parent = parent;          bp->parent = parent;
         bp->parent->args++;          bp->parent->args++;
         bp->expectargs = UINT_MAX;  
         bp->font = bp->parent->font;          bp->font = bp->parent->font;
         bp->size = ep->gsize;          bp->size = ep->gsize;
   
Line 551  static void
Line 570  static void
 eqn_delim(struct eqn_node *ep)  eqn_delim(struct eqn_node *ep)
 {  {
         if (ep->end[0] == '\0' || ep->end[1] == '\0') {          if (ep->end[0] == '\0' || ep->end[1] == '\0') {
                 mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                  mandoc_msg(MANDOCERR_REQ_EMPTY,
                     ep->node->line, ep->node->pos, "delim");                      ep->node->line, ep->node->pos, "delim");
                 if (ep->end[0] != '\0')                  if (ep->end[0] != '\0')
                         ep->end++;                          ep->end++;
Line 578  eqn_undef(struct eqn_node *ep)
Line 597  eqn_undef(struct eqn_node *ep)
         struct eqn_def  *def;          struct eqn_def  *def;
   
         if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {          if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {
                 mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                  mandoc_msg(MANDOCERR_REQ_EMPTY,
                     ep->node->line, ep->node->pos, "undef");                      ep->node->line, ep->node->pos, "undef");
                 return;                  return;
         }          }
Line 597  eqn_def(struct eqn_node *ep)
Line 616  eqn_def(struct eqn_node *ep)
         int              i;          int              i;
   
         if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {          if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {
                 mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                  mandoc_msg(MANDOCERR_REQ_EMPTY,
                     ep->node->line, ep->node->pos, "define");                      ep->node->line, ep->node->pos, "define");
                 return;                  return;
         }          }
Line 626  eqn_def(struct eqn_node *ep)
Line 645  eqn_def(struct eqn_node *ep)
         }          }
   
         if (eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF) {          if (eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF) {
                 mandoc_vmsg(MANDOCERR_REQ_EMPTY, ep->parse,                  mandoc_msg(MANDOCERR_REQ_EMPTY,
                     ep->node->line, ep->node->pos, "define %s", def->key);                      ep->node->line, ep->node->pos, "define %s", def->key);
                 free(def->key);                  free(def->key);
                 free(def->val);                  free(def->val);
Line 660  eqn_parse(struct eqn_node *ep)
Line 679  eqn_parse(struct eqn_node *ep)
         if (ep->data == NULL)          if (ep->data == NULL)
                 return;                  return;
   
         ep->start = ep->end = ep->data + strspn(ep->data, " ^~");          ep->start = ep->end = ep->data;
           ep->sublen = 0;
           ep->subcnt = 0;
   
 next_tok:  next_tok:
         tok = eqn_next(ep, MODE_TOK);          tok = eqn_next(ep, MODE_TOK);
Line 675  next_tok:
Line 696  next_tok:
         case EQN_TOK_TDEFINE:          case EQN_TOK_TDEFINE:
                 if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF ||                  if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF ||
                     eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF)                      eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF)
                         mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                          mandoc_msg(MANDOCERR_REQ_EMPTY,
                             ep->node->line, ep->node->pos, "tdefine");                              ep->node->line, ep->node->pos, "tdefine");
                 break;                  break;
         case EQN_TOK_DELIM:          case EQN_TOK_DELIM:
Line 683  next_tok:
Line 704  next_tok:
                 break;                  break;
         case EQN_TOK_GFONT:          case EQN_TOK_GFONT:
                 if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)                  if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)
                         mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                          mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                 break;                  break;
         case EQN_TOK_MARK:          case EQN_TOK_MARK:
         case EQN_TOK_LINEUP:          case EQN_TOK_LINEUP:
Line 699  next_tok:
Line 720  next_tok:
         case EQN_TOK_DOT:          case EQN_TOK_DOT:
         case EQN_TOK_DOTDOT:          case EQN_TOK_DOTDOT:
                 if (parent->last == NULL) {                  if (parent->last == NULL) {
                         mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,                          mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         cur = eqn_box_alloc(ep, parent);                          cur = eqn_box_alloc(ep, parent);
                         cur->type = EQN_TEXT;                          cur->type = EQN_TEXT;
                         cur->text = mandoc_strdup("");                          cur->text = mandoc_strdup("");
Line 744  next_tok:
Line 765  next_tok:
         case EQN_TOK_DOWN:          case EQN_TOK_DOWN:
         case EQN_TOK_UP:          case EQN_TOK_UP:
                 if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)                  if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)
                         mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                          mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                 break;                  break;
         case EQN_TOK_FAT:          case EQN_TOK_FAT:
         case EQN_TOK_ROMAN:          case EQN_TOK_ROMAN:
Line 782  next_tok:
Line 803  next_tok:
         case EQN_TOK_GSIZE:          case EQN_TOK_GSIZE:
                 /* Accept two values: integral size and a single. */                  /* Accept two values: integral size and a single. */
                 if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {                  if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
                         mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                          mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         break;                          break;
                 }                  }
                 size = mandoc_strntoi(ep->start, ep->toksz, 10);                  size = mandoc_strntoi(ep->start, ep->toksz, 10);
                 if (-1 == size) {                  if (-1 == size) {
                         mandoc_msg(MANDOCERR_IT_NONUM, ep->parse,                          mandoc_msg(MANDOCERR_IT_NONUM, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         break;                          break;
                 }                  }
                 if (EQN_TOK_GSIZE == tok) {                  if (EQN_TOK_GSIZE == tok) {
Line 813  next_tok:
Line 834  next_tok:
                  * and keep on reading.                   * and keep on reading.
                  */                   */
                 if (parent->last == NULL) {                  if (parent->last == NULL) {
                         mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,                          mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         cur = eqn_box_alloc(ep, parent);                          cur = eqn_box_alloc(ep, parent);
                         cur->type = EQN_TEXT;                          cur->type = EQN_TEXT;
                         cur->text = mandoc_strdup("");                          cur->text = mandoc_strdup("");
Line 880  next_tok:
Line 901  next_tok:
                  * rebalance and continue reading.                   * rebalance and continue reading.
                  */                   */
                 if (parent->last == NULL) {                  if (parent->last == NULL) {
                         mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,                          mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         cur = eqn_box_alloc(ep, parent);                          cur = eqn_box_alloc(ep, parent);
                         cur->type = EQN_TEXT;                          cur->type = EQN_TEXT;
                         cur->text = mandoc_strdup("");                          cur->text = mandoc_strdup("");
Line 907  next_tok:
Line 928  next_tok:
                              cur->left != NULL))                               cur->left != NULL))
                                 break;                                  break;
                 if (cur == NULL) {                  if (cur == NULL) {
                         mandoc_msg(MANDOCERR_BLK_NOTOPEN, ep->parse,                          mandoc_msg(MANDOCERR_BLK_NOTOPEN, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         break;                          break;
                 }                  }
                 parent = cur;                  parent = cur;
                 if (EQN_TOK_RIGHT == tok) {                  if (EQN_TOK_RIGHT == tok) {
                         if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {                          if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
                                 mandoc_msg(MANDOCERR_REQ_EMPTY,                                  mandoc_msg(MANDOCERR_REQ_EMPTY,
                                     ep->parse, ep->node->line,                                      ep->node->line, ep->node->pos,
                                     ep->node->pos, eqn_toks[tok]);                                      "%s", eqn_toks[tok]);
                                 break;                                  break;
                         }                          }
                         /* Handling depends on right/left. */                          /* Handling depends on right/left. */
Line 950  next_tok:
Line 971  next_tok:
                         parent = parent->parent;                          parent = parent->parent;
                 if (EQN_TOK_LEFT == tok &&                  if (EQN_TOK_LEFT == tok &&
                     eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {                      eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
                         mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,                          mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         break;                          break;
                 }                  }
                 parent = eqn_box_alloc(ep, parent);                  parent = eqn_box_alloc(ep, parent);
Line 984  next_tok:
Line 1005  next_tok:
                         if (cur->type == EQN_PILE)                          if (cur->type == EQN_PILE)
                                 break;                                  break;
                 if (cur == NULL) {                  if (cur == NULL) {
                         mandoc_msg(MANDOCERR_IT_STRAY, ep->parse,                          mandoc_msg(MANDOCERR_IT_STRAY, ep->node->line,
                             ep->node->line, ep->node->pos, eqn_toks[tok]);                              ep->node->pos, "%s", eqn_toks[tok]);
                         break;                          break;
                 }                  }
                 parent = eqn_box_alloc(ep, cur);                  parent = eqn_box_alloc(ep, cur);

Legend:
Removed from v.1.80  
changed lines
  Added in v.1.85

CVSweb