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

Diff for /mandoc/roff.c between version 1.340 and 1.349

version 1.340, 2018/08/24 23:12:33 version 1.349, 2018/12/13 11:55:47
Line 28 
Line 28 
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
   
 #include "mandoc.h"  
 #include "mandoc_aux.h"  #include "mandoc_aux.h"
 #include "mandoc_ohash.h"  #include "mandoc_ohash.h"
   #include "mandoc.h"
 #include "roff.h"  #include "roff.h"
   #include "mandoc_parse.h"
 #include "libmandoc.h"  #include "libmandoc.h"
 #include "roff_int.h"  #include "roff_int.h"
 #include "libroff.h"  #include "tbl_parse.h"
   #include "eqn_parse.h"
   
 /* Maximum number of string expansions per line, to break infinite loops. */  /* Maximum number of string expansions per line, to break infinite loops. */
 #define EXPAND_LIMIT    1000  #define EXPAND_LIMIT    1000
Line 167  static int   roffnode_cleanscope(struct roff *);
Line 169  static int   roffnode_cleanscope(struct roff *);
 static  int              roffnode_pop(struct roff *);  static  int              roffnode_pop(struct roff *);
 static  void             roffnode_push(struct roff *, enum roff_tok,  static  void             roffnode_push(struct roff *, enum roff_tok,
                                 const char *, int, int);                                  const char *, int, int);
 static  void             roff_addtbl(struct roff_man *, struct tbl_node *);  static  void             roff_addtbl(struct roff_man *, int, struct tbl_node *);
 static  int              roff_als(ROFF_ARGS);  static  int              roff_als(ROFF_ARGS);
 static  int              roff_block(ROFF_ARGS);  static  int              roff_block(ROFF_ARGS);
 static  int              roff_block_text(ROFF_ARGS);  static  int              roff_block_text(ROFF_ARGS);
Line 176  static int   roff_br(ROFF_ARGS);
Line 178  static int   roff_br(ROFF_ARGS);
 static  int              roff_cblock(ROFF_ARGS);  static  int              roff_cblock(ROFF_ARGS);
 static  int              roff_cc(ROFF_ARGS);  static  int              roff_cc(ROFF_ARGS);
 static  int              roff_ccond(struct roff *, int, int);  static  int              roff_ccond(struct roff *, int, int);
   static  int              roff_char(ROFF_ARGS);
 static  int              roff_cond(ROFF_ARGS);  static  int              roff_cond(ROFF_ARGS);
 static  int              roff_cond_text(ROFF_ARGS);  static  int              roff_cond_text(ROFF_ARGS);
 static  int              roff_cond_sub(ROFF_ARGS);  static  int              roff_cond_sub(ROFF_ARGS);
Line 397  static struct roffmac  roffs[TOKEN_NONE] = {
Line 400  static struct roffmac  roffs[TOKEN_NONE] = {
         { roff_insec, NULL, NULL, 0 },  /* cf */          { roff_insec, NULL, NULL, 0 },  /* cf */
         { roff_line_ignore, NULL, NULL, 0 },  /* cflags */          { roff_line_ignore, NULL, NULL, 0 },  /* cflags */
         { roff_line_ignore, NULL, NULL, 0 },  /* ch */          { roff_line_ignore, NULL, NULL, 0 },  /* ch */
         { roff_unsupp, NULL, NULL, 0 },  /* char */          { roff_char, NULL, NULL, 0 },  /* char */
         { roff_unsupp, NULL, NULL, 0 },  /* chop */          { roff_unsupp, NULL, NULL, 0 },  /* chop */
         { roff_line_ignore, NULL, NULL, 0 },  /* class */          { roff_line_ignore, NULL, NULL, 0 },  /* class */
         { roff_insec, NULL, NULL, 0 },  /* close */          { roff_insec, NULL, NULL, 0 },  /* close */
Line 716  roffnode_push(struct roff *r, enum roff_tok tok, const
Line 719  roffnode_push(struct roff *r, enum roff_tok tok, const
 static void  static void
 roff_free1(struct roff *r)  roff_free1(struct roff *r)
 {  {
         struct tbl_node *tbl;  
         int              i;          int              i;
   
         while (NULL != (tbl = r->first_tbl)) {          tbl_free(r->first_tbl);
                 r->first_tbl = tbl->next;  
                 tbl_free(tbl);  
         }  
         r->first_tbl = r->last_tbl = r->tbl = NULL;          r->first_tbl = r->last_tbl = r->tbl = NULL;
   
         if (r->last_eqn != NULL)          eqn_free(r->last_eqn);
                 eqn_free(r->last_eqn);  
         r->last_eqn = r->eqn = NULL;          r->last_eqn = r->eqn = NULL;
   
         while (r->mstackpos >= 0)          while (r->mstackpos >= 0)
Line 1012  roff_body_alloc(struct roff_man *man, int line, int po
Line 1010  roff_body_alloc(struct roff_man *man, int line, int po
 }  }
   
 static void  static void
 roff_addtbl(struct roff_man *man, struct tbl_node *tbl)  roff_addtbl(struct roff_man *man, int line, struct tbl_node *tbl)
 {  {
         struct roff_node        *n;          struct roff_node        *n;
         const struct tbl_span   *span;          struct tbl_span         *span;
   
         if (man->macroset == MACROSET_MAN)          if (man->macroset == MACROSET_MAN)
                 man_breakscope(man, ROFF_TS);                  man_breakscope(man, ROFF_TS);
         while ((span = tbl_span(tbl)) != NULL) {          while ((span = tbl_span(tbl)) != NULL) {
                 n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE);                  n = roff_node_alloc(man, line, 0, ROFFT_TBL, TOKEN_NONE);
                 n->span = span;                  n->span = span;
                 roff_node_append(man, n);                  roff_node_append(man, n);
                 n->flags |= NODE_VALID | NODE_ENDED;                  n->flags |= NODE_VALID | NODE_ENDED;
Line 1066  roff_node_unlink(struct roff_man *man, struct roff_nod
Line 1064  roff_node_unlink(struct roff_man *man, struct roff_nod
 }  }
   
 void  void
   roff_node_relink(struct roff_man *man, struct roff_node *n)
   {
           roff_node_unlink(man, n);
           n->prev = n->next = NULL;
           roff_node_append(man, n);
   }
   
   void
 roff_node_free(struct roff_node *n)  roff_node_free(struct roff_node *n)
 {  {
   
Line 1073  roff_node_free(struct roff_node *n)
Line 1079  roff_node_free(struct roff_node *n)
                 mdoc_argv_free(n->args);                  mdoc_argv_free(n->args);
         if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM)          if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM)
                 free(n->norm);                  free(n->norm);
         if (n->eqn != NULL)          eqn_box_free(n->eqn);
                 eqn_box_free(n->eqn);  
         free(n->string);          free(n->string);
         free(n);          free(n);
 }  }
Line 1650  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1655  roff_parseln(struct roff *r, int ln, struct buf *buf, 
         }          }
         if (r->tbl != NULL && (ctl == 0 || buf->buf[pos] == '\0')) {          if (r->tbl != NULL && (ctl == 0 || buf->buf[pos] == '\0')) {
                 tbl_read(r->tbl, ln, buf->buf, ppos);                  tbl_read(r->tbl, ln, buf->buf, ppos);
                 roff_addtbl(r->man, r->tbl);                  roff_addtbl(r->man, ln, r->tbl);
                 return e;                  return e;
         }          }
         if ( ! ctl)          if ( ! ctl)
Line 1694  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1699  roff_parseln(struct roff *r, int ln, struct buf *buf, 
                 while (buf->buf[pos] == ' ')                  while (buf->buf[pos] == ' ')
                         pos++;                          pos++;
                 tbl_read(r->tbl, ln, buf->buf, pos);                  tbl_read(r->tbl, ln, buf->buf, pos);
                 roff_addtbl(r->man, r->tbl);                  roff_addtbl(r->man, ln, r->tbl);
                 return ROFF_IGN;                  return ROFF_IGN;
         }          }
   
Line 1757  roff_endparse(struct roff *r)
Line 1762  roff_endparse(struct roff *r)
         }          }
   
         if (r->tbl != NULL) {          if (r->tbl != NULL) {
                 mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,                  tbl_end(r->tbl, 1);
                     r->tbl->line, r->tbl->pos, "TS");  
                 tbl_end(r->tbl);  
                 r->tbl = NULL;                  r->tbl = NULL;
         }          }
 }  }
Line 2106  roff_cond_sub(ROFF_ARGS)
Line 2109  roff_cond_sub(ROFF_ARGS)
         if (ep[0] == '\\' && ep[1] == '}')          if (ep[0] == '\\' && ep[1] == '}')
                 rr = 0;                  rr = 0;
   
         /* Always check for the closing delimiter `\}'. */          /*
            * The closing delimiter `\}' rewinds the conditional scope
            * but is otherwise ignored when interpreting the line.
            */
   
         while ((ep = strchr(ep, '\\')) != NULL) {          while ((ep = strchr(ep, '\\')) != NULL) {
                 switch (ep[1]) {                  switch (ep[1]) {
Line 2149  roff_cond_text(ROFF_ARGS)
Line 2155  roff_cond_text(ROFF_ARGS)
         if (roffnode_cleanscope(r))          if (roffnode_cleanscope(r))
                 irc |= endloop;                  irc |= endloop;
   
           /*
            * If `\}' occurs on a text line with neither preceding
            * nor following characters, drop the line completely.
            */
   
         ep = buf->buf + pos;          ep = buf->buf + pos;
           if (strcmp(ep, "\\}") == 0)
                   rr = 0;
   
           /*
            * The closing delimiter `\}' rewinds the conditional scope
            * but is otherwise ignored when interpreting the line.
            */
   
         while ((ep = strchr(ep, '\\')) != NULL) {          while ((ep = strchr(ep, '\\')) != NULL) {
                 if (*(++ep) == '}') {                  switch (ep[1]) {
                         *ep = '&';                  case '}':
                         if (roff_ccond(r, ln, ep - buf->buf - 1))                          memmove(ep, ep + 2, strlen(ep + 2) + 1);
                           if (roff_ccond(r, ln, ep - buf->buf))
                                 irc |= endloop;                                  irc |= endloop;
                 }                          break;
                 if (*ep != '\0')                  case '\0':
                         ++ep;                          ++ep;
                           break;
                   default:
                           ep += 2;
                           break;
                   }
         }          }
         if (rr)          if (rr)
                 irc |= ROFF_CONT;                  irc |= ROFF_CONT;
Line 3028  roff_TE(ROFF_ARGS)
Line 3053  roff_TE(ROFF_ARGS)
                     ln, ppos, "TE");                      ln, ppos, "TE");
                 return ROFF_IGN;                  return ROFF_IGN;
         }          }
         if (tbl_end(r->tbl) == 0) {          if (tbl_end(r->tbl, 0) == 0) {
                 r->tbl = NULL;                  r->tbl = NULL;
                 free(buf->buf);                  free(buf->buf);
                 buf->buf = mandoc_strdup(".sp");                  buf->buf = mandoc_strdup(".sp");
Line 3129  roff_EQ(ROFF_ARGS)
Line 3154  roff_EQ(ROFF_ARGS)
         n = roff_node_alloc(r->man, ln, ppos, ROFFT_EQN, TOKEN_NONE);          n = roff_node_alloc(r->man, ln, ppos, ROFFT_EQN, TOKEN_NONE);
         if (ln > r->man->last->line)          if (ln > r->man->last->line)
                 n->flags |= NODE_LINE;                  n->flags |= NODE_LINE;
         n->eqn = mandoc_calloc(1, sizeof(*n->eqn));          n->eqn = eqn_box_new();
         n->eqn->expectargs = UINT_MAX;  
         roff_node_append(r->man, n);          roff_node_append(r->man, n);
         r->man->next = ROFF_NEXT_SIBLING;          r->man->next = ROFF_NEXT_SIBLING;
   
Line 3169  roff_TS(ROFF_ARGS)
Line 3193  roff_TS(ROFF_ARGS)
         if (r->tbl != NULL) {          if (r->tbl != NULL) {
                 mandoc_msg(MANDOCERR_BLK_BROKEN, r->parse,                  mandoc_msg(MANDOCERR_BLK_BROKEN, r->parse,
                     ln, ppos, "TS breaks TS");                      ln, ppos, "TS breaks TS");
                 tbl_end(r->tbl);                  tbl_end(r->tbl, 0);
         }          }
         r->tbl = tbl_alloc(ppos, ln, r->parse);          r->tbl = tbl_alloc(ppos, ln, r->parse, r->last_tbl);
         if (r->last_tbl)          if (r->last_tbl == NULL)
                 r->last_tbl->next = r->tbl;  
         else  
                 r->first_tbl = r->tbl;                  r->first_tbl = r->tbl;
         r->last_tbl = r->tbl;          r->last_tbl = r->tbl;
         return ROFF_IGN;          return ROFF_IGN;
Line 3318  roff_cc(ROFF_ARGS)
Line 3340  roff_cc(ROFF_ARGS)
                 mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse,                  mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse,
                     ln, p - buf->buf, "cc ... %s", p);                      ln, p - buf->buf, "cc ... %s", p);
   
           return ROFF_IGN;
   }
   
   static int
   roff_char(ROFF_ARGS)
   {
           const char      *p, *kp, *vp;
           size_t           ksz, vsz;
           int              font;
   
           /* Parse the character to be replaced. */
   
           kp = buf->buf + pos;
           p = kp + 1;
           if (*kp == '\0' || (*kp == '\\' &&
                mandoc_escape(&p, NULL, NULL) != ESCAPE_SPECIAL) ||
               (*p != ' ' && *p != '\0')) {
                   mandoc_vmsg(MANDOCERR_CHAR_ARG, r->parse,
                       ln, pos, "char %s", kp);
                   return ROFF_IGN;
           }
           ksz = p - kp;
           while (*p == ' ')
                   p++;
   
           /*
            * If the replacement string contains a font escape sequence,
            * we have to restore the font at the end.
            */
   
           vp = p;
           vsz = strlen(p);
           font = 0;
           while (*p != '\0') {
                   if (*p++ != '\\')
                           continue;
                   switch (mandoc_escape(&p, NULL, NULL)) {
                   case ESCAPE_FONT:
                   case ESCAPE_FONTROMAN:
                   case ESCAPE_FONTITALIC:
                   case ESCAPE_FONTBOLD:
                   case ESCAPE_FONTBI:
                   case ESCAPE_FONTCW:
                   case ESCAPE_FONTPREV:
                           font++;
                           break;
                   default:
                           break;
                   }
           }
           if (font > 1)
                   mandoc_msg(MANDOCERR_CHAR_FONT, r->parse,
                       ln, vp - buf->buf, vp);
   
           /*
            * Approximate the effect of .char using the .tr tables.
            * XXX In groff, .char and .tr interact differently.
            */
   
           if (ksz == 1) {
                   if (r->xtab == NULL)
                           r->xtab = mandoc_calloc(128, sizeof(*r->xtab));
                   assert((unsigned int)*kp < 128);
                   free(r->xtab[(int)*kp].p);
                   r->xtab[(int)*kp].sz = mandoc_asprintf(&r->xtab[(int)*kp].p,
                       "%s%s", vp, font ? "\fP" : "");
           } else {
                   roff_setstrn(&r->xmbtab, kp, ksz, vp, vsz, 0);
                   if (font)
                           roff_setstrn(&r->xmbtab, kp, ksz, "\\fP", 3, 1);
           }
         return ROFF_IGN;          return ROFF_IGN;
 }  }
   

Legend:
Removed from v.1.340  
changed lines
  Added in v.1.349

CVSweb