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

Diff for /mandoc/roff.c between version 1.389 and 1.400

version 1.389, 2022/05/30 23:03:47 version 1.400, 2023/10/24 20:53:12
Line 1 
Line 1 
 /* $Id$ */  /* $Id$ */
 /*  /*
  * Copyright (c) 2010-2015, 2017-2022 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010-2015, 2017-2023 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
Line 40 
Line 40 
 #include "tbl_parse.h"  #include "tbl_parse.h"
 #include "eqn_parse.h"  #include "eqn_parse.h"
   
 /*  
  * ASCII_ESC is used to signal from roff_getarg() to roff_expand()  
  * that an escape sequence resulted from copy-in processing and  
  * needs to be checked or interpolated.  As it is used nowhere  
  * else, it is defined here rather than in a header file.  
  */  
 #define ASCII_ESC       27  
   
 /* 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 375  const char *__roff_name[MAN_MAX + 1] = {
Line 367  const char *__roff_name[MAN_MAX + 1] = {
         "PD",           "AT",           "in",          "PD",           "AT",           "in",
         "SY",           "YS",           "OP",          "SY",           "YS",           "OP",
         "EX",           "EE",           "UR",          "EX",           "EE",           "UR",
         "UE",           "MT",           "ME",           NULL          "UE",           "MT",           "ME",           "MR",
           NULL
 };  };
 const   char *const *roff_name = __roff_name;  const   char *const *roff_name = __roff_name;
   
Line 1370  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1363  roff_expand(struct roff *r, struct buf *buf, int ln, i
         const char      *res;           /* the string to be pasted */          const char      *res;           /* the string to be pasted */
         const char      *src;           /* source for copying */          const char      *src;           /* source for copying */
         char            *dst;           /* destination for copying */          char            *dst;           /* destination for copying */
           enum mandoc_esc  subtype;       /* return value from roff_escape */
         int              iesc;          /* index of leading escape char */          int              iesc;          /* index of leading escape char */
         int              inam;          /* index of the escape name */          int              inam;          /* index of the escape name */
         int              iarg;          /* index beginning the argument */          int              iarg;          /* index beginning the argument */
         int              iendarg;       /* index right after the argument */          int              iendarg;       /* index right after the argument */
         int              iend;          /* index right after the sequence */          int              iend;          /* index right after the sequence */
           int              isrc, idst;    /* to reduce \\ and \. in names */
         int              deftype;       /* type of definition to paste */          int              deftype;       /* type of definition to paste */
         int              argi;          /* macro argument index */          int              argi;          /* macro argument index */
         int              quote_args;    /* true for \\$@, false for \\$* */          int              quote_args;    /* true for \\$@, false for \\$* */
Line 1394  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1389  roff_expand(struct roff *r, struct buf *buf, int ln, i
                  */                   */
   
                 if (buf->buf[pos] != ec) {                  if (buf->buf[pos] != ec) {
                         if (ec != ASCII_ESC && buf->buf[pos] == '\\') {                          if (buf->buf[pos] == '\\') {
                                 roff_expand_patch(buf, pos, "\\e", pos + 1);                                  roff_expand_patch(buf, pos, "\\e", pos + 1);
                                 pos++;                                  pos++;
                         }                          }
Line 1410  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1405  roff_expand(struct roff *r, struct buf *buf, int ln, i
                  * it to backslashes and translate backslashes to \e.                   * it to backslashes and translate backslashes to \e.
                  */                   */
   
                 if (roff_escape(buf->buf, ln, pos,                  if (roff_escape(buf->buf, ln, pos, &iesc, &inam,
                     &iesc, &iarg, &iendarg, &iend) != ESCAPE_EXPAND) {                      &iarg, &iendarg, &iend) != ESCAPE_EXPAND) {
                         while (pos < iend) {                          while (pos < iend) {
                                 if (buf->buf[pos] == ec) {                                  if (buf->buf[pos] == ec) {
                                         buf->buf[pos] = '\\';                                          buf->buf[pos] = '\\';
Line 1428  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1423  roff_expand(struct roff *r, struct buf *buf, int ln, i
                         continue;                          continue;
                 }                  }
   
                 /*                  /* Reduce \\ and \. in names. */
                  * Treat "\E" just like "\";  
                  * it only makes a difference in copy mode.  
                  */  
   
                 inam = iesc + 1;                  if (buf->buf[inam] == '*' || buf->buf[inam] == 'n') {
                 while (buf->buf[inam] == 'E')                          isrc = idst = iarg;
                         inam++;                          while (isrc < iendarg) {
                                   if (isrc + 1 < iendarg &&
                                       buf->buf[isrc] == '\\' &&
                                       (buf->buf[isrc + 1] == '\\' ||
                                        buf->buf[isrc + 1] == '.'))
                                           isrc++;
                                   buf->buf[idst++] = buf->buf[isrc++];
                           }
                           iendarg -= isrc - idst;
                   }
   
                 /* Handle expansion. */                  /* Handle expansion. */
   
Line 1450  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1451  roff_expand(struct roff *r, struct buf *buf, int ln, i
                                 break;                                  break;
   
                         /*                          /*
                          * If not overriden,                           * If not overridden,
                          * let \*(.T through to the formatters.                           * let \*(.T through to the formatters.
                          */                           */
   
Line 1520  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1521  roff_expand(struct roff *r, struct buf *buf, int ln, i
                                         *dst++ = '"';                                          *dst++ = '"';
                         }                          }
                         continue;                          continue;
                   case 'A':
                           ubuf[0] = iendarg > iarg ? '1' : '0';
                           ubuf[1] = '\0';
                           res = ubuf;
                           break;
                 case 'B':                  case 'B':
                         npos = 0;                          npos = 0;
                         ubuf[0] = iendarg > iarg && iend > iendarg &&                          ubuf[0] = iendarg > iarg && iend > iendarg &&
Line 1535  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1541  roff_expand(struct roff *r, struct buf *buf, int ln, i
                         roff_expand_patch(buf, iendarg, "}", iend);                          roff_expand_patch(buf, iendarg, "}", iend);
                         roff_expand_patch(buf, iesc, "${", iarg);                          roff_expand_patch(buf, iesc, "${", iarg);
                         continue;                          continue;
                   case 'g':
                           break;
                 case 'n':                  case 'n':
                         if (iendarg > iarg)                          if (iendarg > iarg)
                                 (void)snprintf(ubuf, sizeof(ubuf), "%d",                                  (void)snprintf(ubuf, sizeof(ubuf), "%d",
Line 1545  roff_expand(struct roff *r, struct buf *buf, int ln, i
Line 1553  roff_expand(struct roff *r, struct buf *buf, int ln, i
                         res = ubuf;                          res = ubuf;
                         break;                          break;
                 case 'w':                  case 'w':
                         (void)snprintf(ubuf, sizeof(ubuf),                          rsz = 0;
                             "%d", (iendarg - iarg) * 24);                          subtype = ESCAPE_UNDEF;
                           while (iarg < iendarg) {
                                   asz = subtype == ESCAPE_SKIPCHAR ? 0 : 1;
                                   if (buf->buf[iarg] != '\\') {
                                           rsz += asz;
                                           iarg++;
                                           continue;
                                   }
                                   switch ((subtype = roff_escape(buf->buf, 0,
                                       iarg, NULL, NULL, NULL, NULL, &iarg))) {
                                   case ESCAPE_SPECIAL:
                                   case ESCAPE_NUMBERED:
                                   case ESCAPE_UNICODE:
                                   case ESCAPE_OVERSTRIKE:
                                   case ESCAPE_UNDEF:
                                           break;
                                   case ESCAPE_DEVICE:
                                           asz *= 8;
                                           break;
                                   case ESCAPE_EXPAND:
                                           abort();
                                   default:
                                           continue;
                                   }
                                   rsz += asz;
                           }
                           (void)snprintf(ubuf, sizeof(ubuf), "%d", rsz * 24);
                         res = ubuf;                          res = ubuf;
                         break;                          break;
                 default:                  default:
Line 1626  roff_getarg(struct roff *r, char **cpp, int ln, int *p
Line 1660  roff_getarg(struct roff *r, char **cpp, int ln, int *p
                                 cp++;                                  cp++;
                                 break;                                  break;
                         case '\\':                          case '\\':
                                   cp[-pairs] = '\\';
                                 newesc = 1;                                  newesc = 1;
                                 cp[-pairs] = ASCII_ESC;  
                                 pairs++;                                  pairs++;
                                 cp++;                                  cp++;
                                 break;                                  break;
Line 1683  roff_getarg(struct roff *r, char **cpp, int ln, int *p
Line 1717  roff_getarg(struct roff *r, char **cpp, int ln, int *p
         buf.buf = start;          buf.buf = start;
         buf.sz = strlen(start) + 1;          buf.sz = strlen(start) + 1;
         buf.next = NULL;          buf.next = NULL;
         if (roff_expand(r, &buf, ln, 0, ASCII_ESC) & ROFF_IGN) {          if (roff_expand(r, &buf, ln, 0, '\\') == ROFF_IGN) {
                 free(buf.buf);                  free(buf.buf);
                 buf.buf = mandoc_strdup("");                  buf.buf = mandoc_strdup("");
         }          }
Line 2468  roff_getnum(const char *v, int *pos, int *res, int fla
Line 2502  roff_getnum(const char *v, int *pos, int *res, int fla
  * Evaluate a string comparison condition.   * Evaluate a string comparison condition.
  * The first character is the delimiter.   * The first character is the delimiter.
  * Succeed if the string up to its second occurrence   * Succeed if the string up to its second occurrence
  * matches the string up to its third occurence.   * matches the string up to its third occurrence.
  * Advance the cursor after the third occurrence   * Advance the cursor after the third occurrence
  * or lacking that, to the end of the line.   * or lacking that, to the end of the line.
  */   */
Line 3726  roff_tr(ROFF_ARGS)
Line 3760  roff_tr(ROFF_ARGS)
 {  {
         const char      *p, *first, *second;          const char      *p, *first, *second;
         size_t           fsz, ssz;          size_t           fsz, ssz;
         enum mandoc_esc  esc;  
   
         p = buf->buf + pos;          p = buf->buf + pos;
   
Line 3740  roff_tr(ROFF_ARGS)
Line 3773  roff_tr(ROFF_ARGS)
   
                 first = p++;                  first = p++;
                 if (*first == '\\') {                  if (*first == '\\') {
                         esc = mandoc_escape(&p, NULL, NULL);                          if (mandoc_escape(&p, NULL, NULL) == ESCAPE_ERROR)
                         if (esc == ESCAPE_ERROR) {  
                                 mandoc_msg(MANDOCERR_ESC_BAD, ln,  
                                     (int)(p - buf->buf), "%s", first);  
                                 return ROFF_IGN;                                  return ROFF_IGN;
                         }  
                         fsz = (size_t)(p - first);                          fsz = (size_t)(p - first);
                 }                  }
   
                 second = p++;                  second = p++;
                 if (*second == '\\') {                  if (*second == '\\') {
                         esc = mandoc_escape(&p, NULL, NULL);                          if (mandoc_escape(&p, NULL, NULL) == ESCAPE_ERROR)
                         if (esc == ESCAPE_ERROR) {  
                                 mandoc_msg(MANDOCERR_ESC_BAD, ln,  
                                     (int)(p - buf->buf), "%s", second);  
                                 return ROFF_IGN;                                  return ROFF_IGN;
                         }  
                         ssz = (size_t)(p - second);                          ssz = (size_t)(p - second);
                 } else if (*second == '\0') {                  } else if (*second == '\0') {
                         mandoc_msg(MANDOCERR_TR_ODD, ln,                          mandoc_msg(MANDOCERR_TR_ODD, ln,
Line 4004  static size_t
Line 4029  static size_t
 roff_getname(struct roff *r, char **cpp, int ln, int pos)  roff_getname(struct roff *r, char **cpp, int ln, int pos)
 {  {
         char     *name, *cp;          char     *name, *cp;
         size_t    namesz;          int       namesz, inam, iend;
   
         name = *cpp;          name = *cpp;
         if (*name == '\0')          if (*name == '\0')
Line 4012  roff_getname(struct roff *r, char **cpp, int ln, int p
Line 4037  roff_getname(struct roff *r, char **cpp, int ln, int p
   
         /* Advance cp to the byte after the end of the name. */          /* Advance cp to the byte after the end of the name. */
   
         for (cp = name; 1; cp++) {          cp = name;
                 namesz = cp - name;          namesz = 0;
           for (;;) {
                 if (*cp == '\0')                  if (*cp == '\0')
                         break;                          break;
                 if (*cp == ' ' || *cp == '\t') {                  if (*cp == ' ' || *cp == '\t') {
                         cp++;                          cp++;
                         break;                          break;
                 }                  }
                 if (*cp != '\\')                  if (*cp != '\\') {
                           if (name + namesz < cp) {
                                   name[namesz] = *cp;
                                   *cp = ' ';
                           }
                           namesz++;
                           cp++;
                         continue;                          continue;
                   }
                 if (cp[1] == '{' || cp[1] == '}')                  if (cp[1] == '{' || cp[1] == '}')
                         break;                          break;
                 if (*++cp == '\\')                  if (roff_escape(cp, 0, 0, NULL, &inam,
                         continue;                      NULL, NULL, &iend) != ESCAPE_UNDEF) {
                 mandoc_msg(MANDOCERR_NAMESC, ln, pos,                          mandoc_msg(MANDOCERR_NAMESC, ln, pos,
                     "%.*s", (int)(cp - name + 1), name);                              "%.*s%.*s", namesz, name, iend, cp);
                 mandoc_escape((const char **)&cp, NULL, NULL);                          cp += iend;
                 break;                          break;
                   }
   
                   /*
                    * In an identifier, \\, \., \G and so on
                    * are reduced to \, ., G and so on,
                    * vaguely similar to copy mode.
                    */
   
                   name[namesz++] = cp[inam];
                   while (iend--) {
                           if (cp >= name + namesz)
                                   *cp = ' ';
                           cp++;
                   }
         }          }
   
         /* Read past spaces. */          /* Read past spaces. */
Line 4347  roff_getformat(const struct roff *r)
Line 4394  roff_getformat(const struct roff *r)
  * return zero and don't change the current position.   * return zero and don't change the current position.
  * If the control character has been set with `.cc', then let that grain   * If the control character has been set with `.cc', then let that grain
  * precedence.   * precedence.
  * This is slighly contrary to groff, where using the non-breaking   * This is slightly contrary to groff, where using the non-breaking
  * control character when `cc' has been invoked will cause the   * control character when `cc' has been invoked will cause the
  * non-breaking macro contents to be printed verbatim.   * non-breaking macro contents to be printed verbatim.
  */   */

Legend:
Removed from v.1.389  
changed lines
  Added in v.1.400

CVSweb