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

Diff for /mandoc/eqn.c between version 1.64 and 1.69

version 1.64, 2017/06/21 18:04:34 version 1.69, 2017/06/23 21:04:57
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, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
Line 20 
Line 20 
 #include <sys/types.h>  #include <sys/types.h>
   
 #include <assert.h>  #include <assert.h>
   #include <ctype.h>
 #include <limits.h>  #include <limits.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
Line 83  enum eqn_tok {
Line 84  enum eqn_tok {
         EQN_TOK_ABOVE,          EQN_TOK_ABOVE,
         EQN_TOK__MAX,          EQN_TOK__MAX,
         EQN_TOK_FUNC,          EQN_TOK_FUNC,
           EQN_TOK_QUOTED,
           EQN_TOK_SYM,
         EQN_TOK_EOF          EQN_TOK_EOF
 };  };
   
Line 516  eqn_tok_parse(struct eqn_node *ep, char **p)
Line 519  eqn_tok_parse(struct eqn_node *ep, char **p)
         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_QUOTED;
         }          }
   
         for (i = 0; i < EQN_TOK__MAX; i++)          for (i = 0; i < EQN_TOK__MAX; i++)
                 if (STRNEQ(start, sz, eqn_toks[i], strlen(eqn_toks[i])))                  if (STRNEQ(start, sz, eqn_toks[i], strlen(eqn_toks[i])))
                         return i;                          return i;
   
           for (i = 0; i < EQNSYM__MAX; i++) {
                   if (STRNEQ(start, sz,
                       eqnsyms[i].str, strlen(eqnsyms[i].str))) {
                           mandoc_asprintf(p, "\\[%s]", eqnsyms[i].sym);
                           return EQN_TOK_SYM;
                   }
           }
   
         if (p != NULL)          if (p != NULL)
                 *p = mandoc_strndup(start, sz);                  *p = mandoc_strndup(start, sz);
   
Line 562  eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par
Line 573  eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par
         bp->parent = parent;          bp->parent = parent;
         bp->parent->args++;          bp->parent->args++;
         bp->expectargs = UINT_MAX;          bp->expectargs = UINT_MAX;
           bp->font = bp->parent->font;
         bp->size = ep->gsize;          bp->size = ep->gsize;
   
         if (NULL != parent->first) {          if (NULL != parent->first) {
Line 710  static enum rofferr
Line 722  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];          char             sym[64];
         struct eqn_box  *cur;          struct eqn_box  *cur, *nbox;
         const char      *start;          const char      *cp, *cpn, *start;
         char            *p;          char            *p;
         size_t           i, sz;          size_t           sz;
         enum eqn_tok     tok, subtok;          enum eqn_tok     tok, subtok;
         enum eqn_post    pos;          enum eqn_post    pos;
           enum { CCL_LET, CCL_DIG, CCL_PUN } ccl, ccln;
         int              size;          int              size;
   
         assert(parent != NULL);          assert(parent != NULL);
Line 776  this_tok:
Line 789  this_tok:
                 parent = eqn_box_makebinary(ep, EQNPOS_NONE, parent);                  parent = eqn_box_makebinary(ep, EQNPOS_NONE, parent);
                 parent->type = EQN_LISTONE;                  parent->type = EQN_LISTONE;
                 parent->expectargs = 1;                  parent->expectargs = 1;
                   parent->font = EQNFONT_ROMAN;
                 switch (tok) {                  switch (tok) {
                 case EQN_TOK_DOTDOT:                  case EQN_TOK_DOTDOT:
                         strlcpy(sym, "\\[ad]", sizeof(sym));                          strlcpy(sym, "\\[ad]", sizeof(sym));
Line 1075  this_tok:
Line 1089  this_tok:
                  * TODO: make sure we're not in an open subexpression.                   * TODO: make sure we're not in an open subexpression.
                  */                   */
                 return ROFF_EQN;                  return ROFF_EQN;
         case EQN_TOK_FUNC:  
         case EQN_TOK__MAX:          case EQN_TOK__MAX:
           case EQN_TOK_FUNC:
           case EQN_TOK_QUOTED:
           case EQN_TOK_SYM:
                 assert(p != NULL);                  assert(p != NULL);
                 /*                  /*
                  * If we already have something in the stack and we're                   * If we already have something in the stack and we're
Line 1084  this_tok:
Line 1100  this_tok:
                  */                   */
                 while (parent->args == parent->expectargs)                  while (parent->args == parent->expectargs)
                         parent = parent->parent;                          parent = parent->parent;
                 if (tok == EQN_TOK_FUNC) {  
                         for (cur = parent; cur != NULL; cur = cur->parent)  
                                 if (cur->font != EQNFONT_NONE)  
                                         break;  
                         if (cur == NULL || cur->font != EQNFONT_ROMAN) {  
                                 parent = eqn_box_alloc(ep, parent);  
                                 parent->type = EQN_LISTONE;  
                                 parent->font = EQNFONT_ROMAN;  
                                 parent->expectargs = 1;  
                         }  
                 }  
                 cur = eqn_box_alloc(ep, parent);                  cur = eqn_box_alloc(ep, parent);
                 cur->type = EQN_TEXT;                  cur->type = EQN_TEXT;
                 for (i = 0; i < EQNSYM__MAX; i++)                  cur->text = p;
                         if (0 == strcmp(eqnsyms[i].str, p)) {                  switch (tok) {
                                 (void)snprintf(sym, sizeof(sym),                  case EQN_TOK_FUNC:
                                         "\\[%s]", eqnsyms[i].sym);                          cur->font = EQNFONT_ROMAN;
                                 cur->text = mandoc_strdup(sym);                          break;
                                 free(p);                  case EQN_TOK_QUOTED:
                           if (cur->font == EQNFONT_NONE)
                                   cur->font = EQNFONT_ITALIC;
                           break;
                   case EQN_TOK_SYM:
                           break;
                   default:
                           if (cur->font != EQNFONT_NONE || *p == '\0')
                                 break;                                  break;
                           cpn = p - 1;
                           ccln = CCL_LET;
                           for (;;) {
                                   /* Advance to next character. */
                                   cp = cpn++;
                                   ccl = ccln;
                                   ccln = isalpha((unsigned char)*cpn) ? CCL_LET :
                                       isdigit((unsigned char)*cpn) ||
                                       (*cpn == '.' && (ccl == CCL_DIG ||
                                        isdigit((unsigned char)cpn[1]))) ?
                                       CCL_DIG : CCL_PUN;
                                   /* No boundary before first character. */
                                   if (cp < p)
                                           continue;
                                   cur->font = ccl == CCL_LET ?
                                       EQNFONT_ITALIC : EQNFONT_ROMAN;
                                   if (*cp == '\\')
                                           mandoc_escape(&cpn, NULL, NULL);
                                   /* No boundary after last character. */
                                   if (*cpn == '\0')
                                           break;
                                   if (ccln == ccl)
                                           continue;
                                   /* Boundary found, split the text. */
                                   if (parent->args == parent->expectargs) {
                                           /* Remove the text from the tree. */
                                           if (cur->prev == NULL)
                                                   parent->first = cur->next;
                                           else
                                                   cur->prev->next = NULL;
                                           parent->last = cur->prev;
                                           parent->args--;
                                           /* Set up a list instead. */
                                           nbox = eqn_box_alloc(ep, parent);
                                           nbox->type = EQN_LIST;
                                           /* Insert the word into the list. */
                                           nbox->first = nbox->last = cur;
                                           cur->parent = nbox;
                                           cur->prev = NULL;
                                           parent = nbox;
                                   }
                                   /* Append a new text box. */
                                   nbox = eqn_box_alloc(ep, parent);
                                   nbox->type = EQN_TEXT;
                                   nbox->text = mandoc_strdup(cpn);
                                   /* Truncate the old box. */
                                   p = mandoc_strndup(cur->text,
                                       cpn - cur->text);
                                   free(cur->text);
                                   cur->text = p;
                                   /* Setup to process the new box. */
                                   cur = nbox;
                                   p = nbox->text;
                                   cpn = p - 1;
                                   ccln = CCL_LET;
                         }                          }
                           break;
                 if (i == EQNSYM__MAX)                  }
                         cur->text = p;  
                 /*                  /*
                  * Post-process list status.                   * Post-process list status.
                  */                   */

Legend:
Removed from v.1.64  
changed lines
  Added in v.1.69

CVSweb