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

Diff for /mandoc/eqn.c between version 1.55 and 1.60

version 1.55, 2014/10/25 14:35:37 version 1.60, 2016/01/07 20:19:01
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2014, 2015 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 31 
Line 31 
 #include "libmandoc.h"  #include "libmandoc.h"
 #include "libroff.h"  #include "libroff.h"
   
 #define EQN_MSG(t, x) \  
         mandoc_msg((t), (x)->parse, (x)->eqn.ln, (x)->eqn.pos, NULL)  
 #define EQN_NEST_MAX     128 /* maximum nesting of defines */  #define EQN_NEST_MAX     128 /* maximum nesting of defines */
 #define STRNEQ(p1, sz1, p2, sz2) \  #define STRNEQ(p1, sz1, p2, sz2) \
         ((sz1) == (sz2) && 0 == strncmp((p1), (p2), (sz1)))          ((sz1) == (sz2) && 0 == strncmp((p1), (p2), (sz1)))
Line 196  enum eqn_symt {
Line 194  enum eqn_symt {
         EQNSYM_equiv,          EQNSYM_equiv,
         EQNSYM_lessequal,          EQNSYM_lessequal,
         EQNSYM_moreequal,          EQNSYM_moreequal,
           EQNSYM_minus,
         EQNSYM__MAX          EQNSYM__MAX
 };  };
   
Line 251  static const struct eqnsym eqnsyms[EQNSYM__MAX] = {
Line 250  static const struct eqnsym eqnsyms[EQNSYM__MAX] = {
         { "cdot", "pc" }, /* EQNSYM_cdot */          { "cdot", "pc" }, /* EQNSYM_cdot */
         { "nothing", "&" }, /* EQNSYM_nothing */          { "nothing", "&" }, /* EQNSYM_nothing */
         { "approx", "~~" }, /* EQNSYM_approx */          { "approx", "~~" }, /* EQNSYM_approx */
         { "prime", "aq" }, /* EQNSYM_prime */          { "prime", "fm" }, /* EQNSYM_prime */
         { "half", "12" }, /* EQNSYM_half */          { "half", "12" }, /* EQNSYM_half */
         { "partial", "pd" }, /* EQNSYM_partial */          { "partial", "pd" }, /* EQNSYM_partial */
         { "inf", "if" }, /* EQNSYM_inf */          { "inf", "if" }, /* EQNSYM_inf */
Line 264  static const struct eqnsym eqnsyms[EQNSYM__MAX] = {
Line 263  static const struct eqnsym eqnsyms[EQNSYM__MAX] = {
         { "==", "==" }, /* EQNSYM_equiv */          { "==", "==" }, /* EQNSYM_equiv */
         { "<=", "<=" }, /* EQNSYM_lessequal */          { "<=", "<=" }, /* EQNSYM_lessequal */
         { ">=", ">=" }, /* EQNSYM_moreequal */          { ">=", ">=" }, /* EQNSYM_moreequal */
           { "-", "mi" }, /* EQNSYM_minus */
 };  };
   
   static  struct eqn_box  *eqn_box_alloc(struct eqn_node *, struct eqn_box *);
   static  void             eqn_box_free(struct eqn_box *);
   static  struct eqn_box  *eqn_box_makebinary(struct eqn_node *,
                                   enum eqn_post, struct eqn_box *);
   static  void             eqn_def(struct eqn_node *);
   static  struct eqn_def  *eqn_def_find(struct eqn_node *, const char *, size_t);
   static  void             eqn_delim(struct eqn_node *);
   static  const char      *eqn_next(struct eqn_node *, char, size_t *, int);
   static  const char      *eqn_nextrawtok(struct eqn_node *, size_t *);
   static  const char      *eqn_nexttok(struct eqn_node *, size_t *);
   static  enum rofferr     eqn_parse(struct eqn_node *, struct eqn_box *);
   static  enum eqn_tok     eqn_tok_parse(struct eqn_node *, char **);
   static  void             eqn_undef(struct eqn_node *);
   
   
 enum rofferr  enum rofferr
 eqn_read(struct eqn_node **epp, int ln,  eqn_read(struct eqn_node **epp, int ln,
                 const char *p, int pos, int *offs)                  const char *p, int pos, int *offs)
Line 287  eqn_read(struct eqn_node **epp, int ln,
Line 302  eqn_read(struct eqn_node **epp, int ln,
                 while (' ' == *p || '\t' == *p)                  while (' ' == *p || '\t' == *p)
                         p++;                          p++;
                 if ('\0' == *p)                  if ('\0' == *p)
                         return(er);                          return er;
                 mandoc_vmsg(MANDOCERR_ARG_SKIP, ep->parse,                  mandoc_vmsg(MANDOCERR_ARG_SKIP, ep->parse,
                     ln, pos, "EN %s", p);                      ln, pos, "EN %s", p);
                 return(er);                  return er;
         }          }
   
         /*          /*
Line 309  eqn_read(struct eqn_node **epp, int ln,
Line 324  eqn_read(struct eqn_node **epp, int ln,
         ep->sz += sz;          ep->sz += sz;
         strlcat(ep->data, p + pos, ep->sz + 1);          strlcat(ep->data, p + pos, ep->sz + 1);
         strlcat(ep->data, " ", ep->sz + 1);          strlcat(ep->data, " ", ep->sz + 1);
         return(ROFF_IGN);          return ROFF_IGN;
 }  }
   
 struct eqn_node *  struct eqn_node *
Line 324  eqn_alloc(int pos, int line, struct mparse *parse)
Line 339  eqn_alloc(int pos, int line, struct mparse *parse)
         p->eqn.pos = pos;          p->eqn.pos = pos;
         p->gsize = EQN_DEFSIZE;          p->gsize = EQN_DEFSIZE;
   
         return(p);          return p;
 }  }
   
 /*  /*
Line 338  eqn_def_find(struct eqn_node *ep, const char *key, siz
Line 353  eqn_def_find(struct eqn_node *ep, const char *key, siz
         for (i = 0; i < (int)ep->defsz; i++)          for (i = 0; i < (int)ep->defsz; i++)
                 if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key,                  if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key,
                     ep->defs[i].keysz, key, sz))                      ep->defs[i].keysz, key, sz))
                         return(&ep->defs[i]);                          return &ep->defs[i];
   
         return(NULL);          return NULL;
 }  }
   
 /*  /*
Line 365  again:
Line 380  again:
         /* Prevent self-definitions. */          /* Prevent self-definitions. */
   
         if (lim >= EQN_NEST_MAX) {          if (lim >= EQN_NEST_MAX) {
                 EQN_MSG(MANDOCERR_ROFFLOOP, ep);                  mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse,
                 return(NULL);                      ep->eqn.ln, ep->eqn.pos, NULL);
                   return NULL;
         }          }
   
         ep->cur = ep->rew;          ep->cur = ep->rew;
Line 374  again:
Line 390  again:
         q = 0;          q = 0;
   
         if ('\0' == *start)          if ('\0' == *start)
                 return(NULL);                  return NULL;
   
         if (quote == *start) {          if (quote == *start) {
                 ep->cur++;                  ep->cur++;
Line 406  again:
Line 422  again:
                         ep->cur++;                          ep->cur++;
         } else {          } else {
                 if (q)                  if (q)
                         EQN_MSG(MANDOCERR_ARG_QUOTE, ep);                          mandoc_msg(MANDOCERR_ARG_QUOTE, ep->parse,
                               ep->eqn.ln, ep->eqn.pos, NULL);
                 next = strchr(start, '\0');                  next = strchr(start, '\0');
                 *sz = (size_t)(next - start);                  *sz = (size_t)(next - start);
                 ep->cur += *sz;                  ep->cur += *sz;
Line 415  again:
Line 432  again:
         /* Quotes aren't expanded for values. */          /* Quotes aren't expanded for values. */
   
         if (q || ! repl)          if (q || ! repl)
                 return(start);                  return start;
   
         if (NULL != (def = eqn_def_find(ep, start, *sz))) {          if (NULL != (def = eqn_def_find(ep, start, *sz))) {
                 diff = def->valsz - *sz;                  diff = def->valsz - *sz;
Line 431  again:
Line 448  again:
                 memmove(start + *sz + diff, start + *sz,                  memmove(start + *sz + diff, start + *sz,
                     (strlen(start) - *sz) + 1);                      (strlen(start) - *sz) + 1);
                 memcpy(start, def->val, def->valsz);                  memcpy(start, def->val, def->valsz);
                   lim++;
                 goto again;                  goto again;
         }          }
   
         return(start);          return start;
 }  }
   
 /*  /*
Line 445  static const char *
Line 463  static const char *
 eqn_nexttok(struct eqn_node *ep, size_t *sz)  eqn_nexttok(struct eqn_node *ep, size_t *sz)
 {  {
   
         return(eqn_next(ep, '"', sz, 1));          return eqn_next(ep, '"', sz, 1);
 }  }
   
 /*  /*
Line 455  static const char *
Line 473  static const char *
 eqn_nextrawtok(struct eqn_node *ep, size_t *sz)  eqn_nextrawtok(struct eqn_node *ep, size_t *sz)
 {  {
   
         return(eqn_next(ep, '"', sz, 0));          return eqn_next(ep, '"', sz, 0);
 }  }
   
 /*  /*
Line 481  eqn_tok_parse(struct eqn_node *ep, char **p)
Line 499  eqn_tok_parse(struct eqn_node *ep, char **p)
         quoted = ep->data[ep->cur] == '"';          quoted = ep->data[ep->cur] == '"';
   
         if (NULL == (start = eqn_nexttok(ep, &sz)))          if (NULL == (start = eqn_nexttok(ep, &sz)))
                 return(EQN_TOK_EOF);                  return EQN_TOK_EOF;
   
         if (quoted) {          if (quoted) {
                 if (p != NULL)                  if (p != NULL)
                         *p = mandoc_strndup(start, sz);                          *p = mandoc_strndup(start, sz);
                 return(EQN_TOK__MAX);                  return EQN_TOK__MAX;
         }          }
   
         for (i = 0; i < EQN_TOK__MAX; i++) {          for (i = 0; i < EQN_TOK__MAX; i++) {
Line 499  eqn_tok_parse(struct eqn_node *ep, char **p)
Line 517  eqn_tok_parse(struct eqn_node *ep, char **p)
         if (i == EQN_TOK__MAX && NULL != p)          if (i == EQN_TOK__MAX && NULL != p)
                 *p = mandoc_strndup(start, sz);                  *p = mandoc_strndup(start, sz);
   
         return(i);          return i;
 }  }
   
 static void  static void
Line 540  eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par
Line 558  eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par
                 parent->first = bp;                  parent->first = bp;
   
         parent->last = bp;          parent->last = bp;
         return(bp);          return bp;
 }  }
   
 /*  /*
Line 570  eqn_box_makebinary(struct eqn_node *ep,
Line 588  eqn_box_makebinary(struct eqn_node *ep,
         newb->first = newb->last = b;          newb->first = newb->last = b;
         newb->first->next = NULL;          newb->first->next = NULL;
         b->parent = newb;          b->parent = newb;
         return(newb);          return newb;
 }  }
   
 /*  /*
Line 600  eqn_delim(struct eqn_node *ep)
Line 618  eqn_delim(struct eqn_node *ep)
 /*  /*
  * Undefine a previously-defined string.   * Undefine a previously-defined string.
  */   */
 static int  static void
 eqn_undef(struct eqn_node *ep)  eqn_undef(struct eqn_node *ep)
 {  {
         const char      *start;          const char      *start;
         struct eqn_def  *def;          struct eqn_def  *def;
         size_t           sz;          size_t           sz;
   
         if (NULL == (start = eqn_nextrawtok(ep, &sz))) {          if ((start = eqn_nextrawtok(ep, &sz)) == NULL) {
                 EQN_MSG(MANDOCERR_EQNEOF, ep);                  mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
                 return(0);                      ep->eqn.ln, ep->eqn.pos, "undef");
         } else if (NULL != (def = eqn_def_find(ep, start, sz)))                  return;
                 def->keysz = 0;          }
           if ((def = eqn_def_find(ep, start, sz)) == NULL)
         return(1);                  return;
           free(def->key);
           free(def->val);
           def->key = def->val = NULL;
           def->keysz = def->valsz = 0;
 }  }
   
 static int  static void
 eqn_def(struct eqn_node *ep)  eqn_def(struct eqn_node *ep)
 {  {
         const char      *start;          const char      *start;
Line 624  eqn_def(struct eqn_node *ep)
Line 646  eqn_def(struct eqn_node *ep)
         struct eqn_def  *def;          struct eqn_def  *def;
         int              i;          int              i;
   
         if (NULL == (start = eqn_nextrawtok(ep, &sz))) {          if ((start = eqn_nextrawtok(ep, &sz)) == NULL) {
                 EQN_MSG(MANDOCERR_EQNEOF, ep);                  mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
                 return(0);                      ep->eqn.ln, ep->eqn.pos, "define");
                   return;
         }          }
   
         /*          /*
Line 646  eqn_def(struct eqn_node *ep)
Line 669  eqn_def(struct eqn_node *ep)
                         ep->defs[i].key = ep->defs[i].val = NULL;                          ep->defs[i].key = ep->defs[i].val = NULL;
                 }                  }
   
                 ep->defs[i].keysz = sz;                  def = ep->defs + i;
                 ep->defs[i].key = mandoc_realloc(                  free(def->key);
                     ep->defs[i].key, sz + 1);                  def->key = mandoc_strndup(start, sz);
                   def->keysz = sz;
                 memcpy(ep->defs[i].key, start, sz);  
                 ep->defs[i].key[(int)sz] = '\0';  
                 def = &ep->defs[i];  
         }          }
   
         start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0);          start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0);
           if (start == NULL) {
         if (NULL == start) {                  mandoc_vmsg(MANDOCERR_REQ_EMPTY, ep->parse,
                 EQN_MSG(MANDOCERR_EQNEOF, ep);                      ep->eqn.ln, ep->eqn.pos, "define %s", def->key);
                 return(-1);                  free(def->key);
                   free(def->val);
                   def->key = def->val = NULL;
                   def->keysz = def->valsz = 0;
                   return;
         }          }
           free(def->val);
           def->val = mandoc_strndup(start, sz);
         def->valsz = sz;          def->valsz = sz;
         def->val = mandoc_realloc(def->val, sz + 1);  
         memcpy(def->val, start, sz);  
         def->val[(int)sz] = '\0';  
         return(1);  
 }  }
   
 /*  /*
  * Recursively parse an eqn(7) expression.   * Recursively parse an eqn(7) expression.
  */   */
 static int  static enum rofferr
 eqn_parse(struct eqn_node *ep, struct eqn_box *parent)  eqn_parse(struct eqn_node *ep, struct eqn_box *parent)
 {  {
           char             sym[64];
           struct eqn_box  *cur;
           const char      *start;
         char            *p;          char            *p;
           size_t           i, sz;
         enum eqn_tok     tok, subtok;          enum eqn_tok     tok, subtok;
         enum eqn_post    pos;          enum eqn_post    pos;
         struct eqn_box  *cur;          int              size;
         int              rc, size;  
         size_t           i, sz;  
         char             sym[64];  
         const char      *start;  
   
         assert(NULL != parent);          assert(parent != NULL);
   
           /*
            * Empty equation.
            * Do not add it to the high-level syntax tree.
            */
   
           if (ep->data == NULL)
                   return ROFF_IGN;
   
 next_tok:  next_tok:
         tok = eqn_tok_parse(ep, &p);          tok = eqn_tok_parse(ep, &p);
   
 this_tok:  this_tok:
         switch (tok) {          switch (tok) {
         case (EQN_TOK_UNDEF):          case (EQN_TOK_UNDEF):
                 if ((rc = eqn_undef(ep)) <= 0)                  eqn_undef(ep);
                         return(rc);  
                 break;                  break;
         case (EQN_TOK_NDEFINE):          case (EQN_TOK_NDEFINE):
         case (EQN_TOK_DEFINE):          case (EQN_TOK_DEFINE):
                 if ((rc = eqn_def(ep)) <= 0)                  eqn_def(ep);
                         return(rc);  
                 break;                  break;
         case (EQN_TOK_TDEFINE):          case (EQN_TOK_TDEFINE):
                 if (NULL == eqn_nextrawtok(ep, NULL))                  if (eqn_nextrawtok(ep, NULL) == NULL ||
                         EQN_MSG(MANDOCERR_EQNEOF, ep);                      eqn_next(ep, ep->data[(int)ep->cur], NULL, 0) == NULL)
                 else if (NULL == eqn_next(ep,                          mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
                                 ep->data[(int)ep->cur], NULL, 0))                              ep->eqn.ln, ep->eqn.pos, "tdefine");
                         EQN_MSG(MANDOCERR_EQNEOF, ep);  
                 break;                  break;
         case (EQN_TOK_DELIM):          case (EQN_TOK_DELIM):
                 eqn_delim(ep);                  eqn_delim(ep);
Line 1035  this_tok:
Line 1061  this_tok:
                  * End of file!                   * End of file!
                  * TODO: make sure we're not in an open subexpression.                   * TODO: make sure we're not in an open subexpression.
                  */                   */
                 return(0);                  return ROFF_EQN;
         default:          default:
                 assert(tok == EQN_TOK__MAX);                  assert(tok == EQN_TOK__MAX);
                 assert(NULL != p);                  assert(NULL != p);
Line 1079  eqn_end(struct eqn_node **epp)
Line 1105  eqn_end(struct eqn_node **epp)
   
         ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box));          ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box));
         ep->eqn.root->expectargs = UINT_MAX;          ep->eqn.root->expectargs = UINT_MAX;
         return(0 == eqn_parse(ep, ep->eqn.root) ? ROFF_EQN : ROFF_IGN);          return eqn_parse(ep, ep->eqn.root);
 }  }
   
 void  void

Legend:
Removed from v.1.55  
changed lines
  Added in v.1.60

CVSweb