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

Diff for /mandoc/roff.c between version 1.256 and 1.263

version 1.256, 2015/01/24 02:41:49 version 1.263, 2015/02/21 14:46:58
Line 396  static int   roff_evalcond(struct roff *r, int,
Line 396  static int   roff_evalcond(struct roff *r, int,
 static  int              roff_evalnum(struct roff *, int,  static  int              roff_evalnum(struct roff *, int,
                                 const char *, int *, int *, int);                                  const char *, int *, int *, int);
 static  int              roff_evalpar(struct roff *, int,  static  int              roff_evalpar(struct roff *, int,
                                 const char *, int *, int *);                                  const char *, int *, int *, int);
 static  int              roff_evalstrcond(const char *, int *);  static  int              roff_evalstrcond(const char *, int *);
 static  void             roff_free1(struct roff *);  static  void             roff_free1(struct roff *);
 static  void             roff_freereg(struct roffreg *);  static  void             roff_freereg(struct roffreg *);
 static  void             roff_freestr(struct roffkv *);  static  void             roff_freestr(struct roffkv *);
 static  size_t           roff_getname(struct roff *, char **, int, int);  static  size_t           roff_getname(struct roff *, char **, int, int);
 static  int              roff_getnum(const char *, int *, int *);  static  int              roff_getnum(const char *, int *, int *, int);
 static  int              roff_getop(const char *, int *, char *);  static  int              roff_getop(const char *, int *, char *);
 static  int              roff_getregn(const struct roff *,  static  int              roff_getregn(const struct roff *,
                                 const char *, size_t);                                  const char *, size_t);
Line 441  static enum rofferr  roff_userdef(ROFF_ARGS);
Line 441  static enum rofferr  roff_userdef(ROFF_ARGS);
 #define ASCII_LO         33  #define ASCII_LO         33
 #define HASHWIDTH       (ASCII_HI - ASCII_LO + 1)  #define HASHWIDTH       (ASCII_HI - ASCII_LO + 1)
   
   #define ROFFNUM_SCALE   (1 << 0)  /* Honour scaling in roff_getnum(). */
   #define ROFFNUM_WHITE   (1 << 1)  /* Skip whitespace in roff_evalnum(). */
   
 static  struct roffmac  *hash[HASHWIDTH];  static  struct roffmac  *hash[HASHWIDTH];
   
 static  struct roffmac   roffs[ROFF_MAX] = {  static  struct roffmac   roffs[ROFF_MAX] = {
Line 1050  roff_res(struct roff *r, struct buf *buf, int ln, int 
Line 1053  roff_res(struct roff *r, struct buf *buf, int ln, int 
                 case 'B':                  case 'B':
                         npos = 0;                          npos = 0;
                         ubuf[0] = arg_complete &&                          ubuf[0] = arg_complete &&
                             roff_evalnum(r, ln, stnam, &npos, NULL, 0) &&                              roff_evalnum(r, ln, stnam, &npos,
                                 NULL, ROFFNUM_SCALE) &&
                             stnam + npos + 1 == cp ? '1' : '0';                              stnam + npos + 1 == cp ? '1' : '0';
                         ubuf[1] = '\0';                          ubuf[1] = '\0';
                         break;                          break;
Line 1202  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1206  roff_parseln(struct roff *r, int ln, struct buf *buf, 
         if (r->eqn != NULL)          if (r->eqn != NULL)
                 return(eqn_read(&r->eqn, ln, buf->buf, ppos, offs));                  return(eqn_read(&r->eqn, ln, buf->buf, ppos, offs));
         if (r->tbl != NULL && ( ! ctl || buf->buf[pos] == '\0'))          if (r->tbl != NULL && ( ! ctl || buf->buf[pos] == '\0'))
                 return(tbl_read(r->tbl, ln, buf->buf, pos));                  return(tbl_read(r->tbl, ln, buf->buf, ppos));
         if ( ! ctl)          if ( ! ctl)
                 return(roff_parsetext(buf, pos, offs));                  return(roff_parsetext(buf, pos, offs));
   
Line 1237  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1241  roff_parseln(struct roff *r, int ln, struct buf *buf, 
         if (r->tbl != NULL && (t == ROFF_MAX || t == ROFF_TS)) {          if (r->tbl != NULL && (t == ROFF_MAX || t == ROFF_TS)) {
                 mandoc_msg(MANDOCERR_TBLMACRO, r->parse,                  mandoc_msg(MANDOCERR_TBLMACRO, r->parse,
                     ln, pos, buf->buf + spos);                      ln, pos, buf->buf + spos);
                 return(ROFF_IGN);                  if (t == ROFF_TS)
                           return(ROFF_IGN);
                   while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ')
                           pos++;
                   while (buf->buf[pos] != '\0' && buf->buf[pos] == ' ')
                           pos++;
                   return(tbl_read(r->tbl, ln, buf->buf, pos));
         }          }
   
         /*          /*
Line 1622  roff_cond_text(ROFF_ARGS)
Line 1632  roff_cond_text(ROFF_ARGS)
  * Ignore overflows, treat them just like the C language.   * Ignore overflows, treat them just like the C language.
  */   */
 static int  static int
 roff_getnum(const char *v, int *pos, int *res)  roff_getnum(const char *v, int *pos, int *res, int flags)
 {  {
         int      myres, n, p;          int      myres, scaled, n, p;
   
         if (NULL == res)          if (NULL == res)
                 res = &myres;                  res = &myres;
   
         p = *pos;          p = *pos;
         n = v[p] == '-';          n = v[p] == '-';
         if (n)          if (n || v[p] == '+')
                 p++;                  p++;
   
           if (flags & ROFFNUM_WHITE)
                   while (isspace((unsigned char)v[p]))
                           p++;
   
         for (*res = 0; isdigit((unsigned char)v[p]); p++)          for (*res = 0; isdigit((unsigned char)v[p]); p++)
                 *res = 10 * *res + v[p] - '0';                  *res = 10 * *res + v[p] - '0';
         if (p == *pos + n)          if (p == *pos + n)
Line 1646  roff_getnum(const char *v, int *pos, int *res)
Line 1660  roff_getnum(const char *v, int *pos, int *res)
   
         switch (v[p]) {          switch (v[p]) {
         case 'f':          case 'f':
                 *res *= 65536;                  scaled = *res * 65536;
                 break;                  break;
         case 'i':          case 'i':
                 *res *= 240;                  scaled = *res * 240;
                 break;                  break;
         case 'c':          case 'c':
                 *res *= 240;                  scaled = *res * 240 / 2.54;
                 *res /= 2.54;  
                 break;                  break;
         case 'v':          case 'v':
                 /* FALLTROUGH */                  /* FALLTROUGH */
         case 'P':          case 'P':
                 *res *= 40;                  scaled = *res * 40;
                 break;                  break;
         case 'm':          case 'm':
                 /* FALLTROUGH */                  /* FALLTROUGH */
         case 'n':          case 'n':
                 *res *= 24;                  scaled = *res * 24;
                 break;                  break;
         case 'p':          case 'p':
                 *res *= 10;                  scaled = *res * 10 / 3;
                 *res /= 3;  
                 break;                  break;
         case 'u':          case 'u':
                   scaled = *res;
                 break;                  break;
         case 'M':          case 'M':
                 *res *= 6;                  scaled = *res * 6 / 25;
                 *res /= 25;  
                 break;                  break;
         default:          default:
                   scaled = *res;
                 p--;                  p--;
                 break;                  break;
         }          }
           if (flags & ROFFNUM_SCALE)
                   *res = scaled;
   
         *pos = p + 1;          *pos = p + 1;
         return(1);          return(1);
Line 1768  roff_evalcond(struct roff *r, int ln, const char *v, i
Line 1783  roff_evalcond(struct roff *r, int ln, const char *v, i
         }          }
   
         savepos = *pos;          savepos = *pos;
         if (roff_evalnum(r, ln, v, pos, &number, 0))          if (roff_evalnum(r, ln, v, pos, &number, ROFFNUM_SCALE))
                 return((number > 0) == wanttrue);                  return((number > 0) == wanttrue);
         else if (*pos == savepos)          else if (*pos == savepos)
                 return(roff_evalstrcond(v, pos) == wanttrue);                  return(roff_evalstrcond(v, pos) == wanttrue);
Line 1991  roff_getop(const char *v, int *pos, char *res)
Line 2006  roff_getop(const char *v, int *pos, char *res)
  */   */
 static int  static int
 roff_evalpar(struct roff *r, int ln,  roff_evalpar(struct roff *r, int ln,
         const char *v, int *pos, int *res)          const char *v, int *pos, int *res, int flags)
 {  {
   
         if ('(' != v[*pos])          if ('(' != v[*pos])
                 return(roff_getnum(v, pos, res));                  return(roff_getnum(v, pos, res, flags));
   
         (*pos)++;          (*pos)++;
         if ( ! roff_evalnum(r, ln, v, pos, res, 1))          if ( ! roff_evalnum(r, ln, v, pos, res, flags | ROFFNUM_WHITE))
                 return(0);                  return(0);
   
         /*          /*
Line 2021  roff_evalpar(struct roff *r, int ln,
Line 2036  roff_evalpar(struct roff *r, int ln,
  */   */
 static int  static int
 roff_evalnum(struct roff *r, int ln, const char *v,  roff_evalnum(struct roff *r, int ln, const char *v,
         int *pos, int *res, int skipwhite)          int *pos, int *res, int flags)
 {  {
         int              mypos, operand2;          int              mypos, operand2;
         char             operator;          char             operator;
Line 2031  roff_evalnum(struct roff *r, int ln, const char *v,
Line 2046  roff_evalnum(struct roff *r, int ln, const char *v,
                 pos = &mypos;                  pos = &mypos;
         }          }
   
         if (skipwhite)          if (flags & ROFFNUM_WHITE)
                 while (isspace((unsigned char)v[*pos]))                  while (isspace((unsigned char)v[*pos]))
                         (*pos)++;                          (*pos)++;
   
         if ( ! roff_evalpar(r, ln, v, pos, res))          if ( ! roff_evalpar(r, ln, v, pos, res, flags))
                 return(0);                  return(0);
   
         while (1) {          while (1) {
                 if (skipwhite)                  if (flags & ROFFNUM_WHITE)
                         while (isspace((unsigned char)v[*pos]))                          while (isspace((unsigned char)v[*pos]))
                                 (*pos)++;                                  (*pos)++;
   
                 if ( ! roff_getop(v, pos, &operator))                  if ( ! roff_getop(v, pos, &operator))
                         break;                          break;
   
                 if (skipwhite)                  if (flags & ROFFNUM_WHITE)
                         while (isspace((unsigned char)v[*pos]))                          while (isspace((unsigned char)v[*pos]))
                                 (*pos)++;                                  (*pos)++;
   
                 if ( ! roff_evalpar(r, ln, v, pos, &operand2))                  if ( ! roff_evalpar(r, ln, v, pos, &operand2, flags))
                         return(0);                          return(0);
   
                 if (skipwhite)                  if (flags & ROFFNUM_WHITE)
                         while (isspace((unsigned char)v[*pos]))                          while (isspace((unsigned char)v[*pos]))
                                 (*pos)++;                                  (*pos)++;
   
Line 2257  roff_nr(ROFF_ARGS)
Line 2272  roff_nr(ROFF_ARGS)
         if (sign == '+' || sign == '-')          if (sign == '+' || sign == '-')
                 val++;                  val++;
   
         if (roff_evalnum(r, ln, val, NULL, &iv, 0))          if (roff_evalnum(r, ln, val, NULL, &iv, ROFFNUM_SCALE))
                 roff_setreg(r, key, iv, sign);                  roff_setreg(r, key, iv, sign);
   
         return(ROFF_IGN);          return(ROFF_IGN);
Line 2312  roff_rm(ROFF_ARGS)
Line 2327  roff_rm(ROFF_ARGS)
 static enum rofferr  static enum rofferr
 roff_it(ROFF_ARGS)  roff_it(ROFF_ARGS)
 {  {
         char            *cp;  
         size_t           len;  
         int              iv;          int              iv;
   
         /* Parse the number of lines. */          /* Parse the number of lines. */
         cp = buf->buf + pos;  
         len = strcspn(cp, " \t");          if ( ! roff_evalnum(r, ln, buf->buf, &pos, &iv, 0)) {
         cp[len] = '\0';  
         if ((iv = mandoc_strntoi(cp, len, 10)) <= 0) {  
                 mandoc_msg(MANDOCERR_IT_NONUM, r->parse,                  mandoc_msg(MANDOCERR_IT_NONUM, r->parse,
                     ln, ppos, buf->buf + 1);                      ln, ppos, buf->buf + 1);
                 return(ROFF_IGN);                  return(ROFF_IGN);
         }          }
         cp += len + 1;  
   
         /* Arm the input line trap. */          while (isspace((unsigned char)buf->buf[pos]))
                   pos++;
   
           /*
            * Arm the input line trap.
            * Special-casing "an-trap" is an ugly workaround to cope
            * with DocBook stupidly fiddling with man(7) internals.
            */
   
         roffit_lines = iv;          roffit_lines = iv;
         roffit_macro = mandoc_strdup(cp);          roffit_macro = mandoc_strdup(iv != 1 ||
               strcmp(buf->buf + pos, "an-trap") ?
               buf->buf + pos : "br");
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
Line 2370  roff_TE(ROFF_ARGS)
Line 2390  roff_TE(ROFF_ARGS)
         if (NULL == r->tbl)          if (NULL == r->tbl)
                 mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,                  mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
                     ln, ppos, "TE");                      ln, ppos, "TE");
         else          else if ( ! tbl_end(&r->tbl)) {
                 tbl_end(&r->tbl);                  free(buf->buf);
                   buf->buf = mandoc_strdup(".sp");
                   buf->sz = 4;
                   return(ROFF_REPARSE);
           }
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
Line 2529  roff_cc(ROFF_ARGS)
Line 2552  roff_cc(ROFF_ARGS)
                 r->control = 0;                  r->control = 0;
   
         if (*p != '\0')          if (*p != '\0')
                 mandoc_msg(MANDOCERR_ARGCOUNT, r->parse, ln, ppos, NULL);                  mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse,
                       ln, p - buf->buf, "cc ... %s", p);
   
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
Line 2544  roff_tr(ROFF_ARGS)
Line 2568  roff_tr(ROFF_ARGS)
         p = buf->buf + pos;          p = buf->buf + pos;
   
         if (*p == '\0') {          if (*p == '\0') {
                 mandoc_msg(MANDOCERR_ARGCOUNT, r->parse, ln, ppos, NULL);                  mandoc_msg(MANDOCERR_REQ_EMPTY, r->parse, ln, ppos, "tr");
                 return(ROFF_IGN);                  return(ROFF_IGN);
         }          }
   
Line 2572  roff_tr(ROFF_ARGS)
Line 2596  roff_tr(ROFF_ARGS)
                         }                          }
                         ssz = (size_t)(p - second);                          ssz = (size_t)(p - second);
                 } else if (*second == '\0') {                  } else if (*second == '\0') {
                         mandoc_msg(MANDOCERR_ARGCOUNT, r->parse,                          mandoc_vmsg(MANDOCERR_TR_ODD, r->parse,
                             ln, (int)(p - buf->buf), NULL);                              ln, first - buf->buf, "tr %s", first);
                         second = " ";                          second = " ";
                         p--;                          p--;
                 }                  }
Line 2629  roff_so(ROFF_ARGS)
Line 2653  roff_so(ROFF_ARGS)
 static enum rofferr  static enum rofferr
 roff_userdef(ROFF_ARGS)  roff_userdef(ROFF_ARGS)
 {  {
         const char       *arg[9];          const char       *arg[9], *ap;
         char             *cp, *n1, *n2;          char             *cp, *n1, *n2;
         int               i;          int               i;
           size_t            asz, rsz;
   
         /*          /*
          * Collect pointers to macro argument strings           * Collect pointers to macro argument strings
          * and NUL-terminate them.           * and NUL-terminate them.
          */           */
   
         cp = buf->buf + pos;          cp = buf->buf + pos;
         for (i = 0; i < 9; i++)          for (i = 0; i < 9; i++)
                 arg[i] = *cp == '\0' ? "" :                  arg[i] = *cp == '\0' ? "" :
Line 2645  roff_userdef(ROFF_ARGS)
Line 2671  roff_userdef(ROFF_ARGS)
         /*          /*
          * Expand macro arguments.           * Expand macro arguments.
          */           */
         buf->sz = 0;  
         n1 = cp = mandoc_strdup(r->current_string);          buf->sz = strlen(r->current_string) + 1;
         while ((cp = strstr(cp, "\\$")) != NULL) {          n1 = cp = mandoc_malloc(buf->sz);
                 i = cp[2] - '1';          memcpy(n1, r->current_string, buf->sz);
                 if (0 > i || 8 < i) {          while (*cp != '\0') {
                         /* Not an argument invocation. */  
                         cp += 2;                  /* Scan ahead for the next argument invocation. */
   
                   if (*cp++ != '\\')
                         continue;                          continue;
                   if (*cp++ != '$')
                           continue;
                   i = *cp - '1';
                   if (0 > i || 8 < i)
                           continue;
                   cp -= 2;
   
                   /*
                    * Determine the size of the expanded argument,
                    * taking escaping of quotes into account.
                    */
   
                   asz = 0;
                   for (ap = arg[i]; *ap != '\0'; ap++) {
                           asz++;
                           if (*ap == '"')
                                   asz += 3;
                 }                  }
                 *cp = '\0';                  if (asz != 3) {
                 buf->sz = mandoc_asprintf(&n2, "%s%s%s",  
                     n1, arg[i], cp + 3) + 1;                          /*
                 cp = n2 + (cp - n1);                           * Determine the size of the rest of the
                 free(n1);                           * unexpanded macro, including the NUL.
                 n1 = n2;                           */
   
                           rsz = buf->sz - (cp - n1) - 3;
   
                           /*
                            * When shrinking, move before
                            * releasing the storage.
                            */
   
                           if (asz < 3)
                                   memmove(cp + asz, cp + 3, rsz);
   
                           /*
                            * Resize the storage for the macro
                            * and readjust the parse pointer.
                            */
   
                           buf->sz += asz - 3;
                           n2 = mandoc_realloc(n1, buf->sz);
                           cp = n2 + (cp - n1);
                           n1 = n2;
   
                           /*
                            * When growing, make room
                            * for the expanded argument.
                            */
   
                           if (asz > 3)
                                   memmove(cp + asz, cp + 3, rsz);
                   }
   
                   /* Copy the expanded argument, escaping quotes. */
   
                   n2 = cp;
                   for (ap = arg[i]; *ap != '\0'; ap++) {
                           if (*ap == '"') {
                                   memcpy(n2, "\\(dq", 4);
                                   n2 += 4;
                           } else
                                   *n2++ = *ap;
                   }
         }          }
   
         /*          /*
          * Replace the macro invocation           * Replace the macro invocation
          * by the expanded macro.           * by the expanded macro.
          */           */
   
         free(buf->buf);          free(buf->buf);
         buf->buf = n1;          buf->buf = n1;
         if (buf->sz == 0)  
                 buf->sz = strlen(buf->buf) + 1;  
         *offs = 0;          *offs = 0;
   
         return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ?          return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ?

Legend:
Removed from v.1.256  
changed lines
  Added in v.1.263

CVSweb