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

Diff for /mandoc/roff.c between version 1.323 and 1.328

version 1.323, 2017/07/14 16:49:39 version 1.328, 2018/04/11 17:11:13
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010-2015, 2017, 2018 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 46 
Line 46 
 #define ROFFDEF_STD     (1 << 4)  /* mdoc(7) or man(7) macro. */  #define ROFFDEF_STD     (1 << 4)  /* mdoc(7) or man(7) macro. */
 #define ROFFDEF_ANY     (ROFFDEF_USER | ROFFDEF_PRE | \  #define ROFFDEF_ANY     (ROFFDEF_USER | ROFFDEF_PRE | \
                          ROFFDEF_REN | ROFFDEF_STD)                           ROFFDEF_REN | ROFFDEF_STD)
   #define ROFFDEF_UNDEF   (1 << 5)  /* Completely undefined. */
   
 /* --- data types --------------------------------------------------------- */  /* --- data types --------------------------------------------------------- */
   
Line 72  struct roffkv {
Line 73  struct roffkv {
 struct  roffreg {  struct  roffreg {
         struct roffstr   key;          struct roffstr   key;
         int              val;          int              val;
           int              step;
         struct roffreg  *next;          struct roffreg  *next;
 };  };
   
Line 181  static void   roff_freestr(struct roffkv *);
Line 183  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 *, 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(struct roff *,
                                 const char *, size_t);                                  const char *, size_t, char);
 static  int              roff_getregro(const struct roff *,  static  int              roff_getregro(const struct roff *,
                                 const char *name);                                  const char *name);
 static  const char      *roff_getstrn(const struct roff *,  static  const char      *roff_getstrn(struct roff *,
                                 const char *, size_t, int *);                                  const char *, size_t, int *);
 static  int              roff_hasregn(const struct roff *,  static  int              roff_hasregn(const struct roff *,
                                 const char *, size_t);                                  const char *, size_t);
Line 206  static enum rofferr  roff_res(struct roff *, struct bu
Line 208  static enum rofferr  roff_res(struct roff *, struct bu
 static  enum rofferr     roff_rm(ROFF_ARGS);  static  enum rofferr     roff_rm(ROFF_ARGS);
 static  enum rofferr     roff_rn(ROFF_ARGS);  static  enum rofferr     roff_rn(ROFF_ARGS);
 static  enum rofferr     roff_rr(ROFF_ARGS);  static  enum rofferr     roff_rr(ROFF_ARGS);
   static  void             roff_setregn(struct roff *, const char *,
                                   size_t, int, char, int);
 static  void             roff_setstr(struct roff *,  static  void             roff_setstr(struct roff *,
                                 const char *, const char *, int);                                  const char *, const char *, int);
 static  void             roff_setstrn(struct roffkv **, const char *,  static  void             roff_setstrn(struct roffkv **, const char *,
Line 758  roff_alloc(struct mparse *parse, int options)
Line 762  roff_alloc(struct mparse *parse, int options)
   
         r = mandoc_calloc(1, sizeof(struct roff));          r = mandoc_calloc(1, sizeof(struct roff));
         r->parse = parse;          r->parse = parse;
         r->reqtab = roffhash_alloc(0, ROFF_USERDEF);          r->reqtab = roffhash_alloc(0, ROFF_RENAMED);
         r->options = options;          r->options = options;
         r->format = options & (MPARSE_MDOC | MPARSE_MAN);          r->format = options & (MPARSE_MDOC | MPARSE_MAN);
         r->rstackpos = -1;          r->rstackpos = -1;
Line 1118  static enum rofferr
Line 1122  static enum rofferr
 roff_res(struct roff *r, struct buf *buf, int ln, int pos)  roff_res(struct roff *r, struct buf *buf, int ln, int pos)
 {  {
         char             ubuf[24]; /* buffer to print the number */          char             ubuf[24]; /* buffer to print the number */
           struct roff_node *n;    /* used for header comments */
         const char      *start; /* start of the string to process */          const char      *start; /* start of the string to process */
         char            *stesc; /* start of an escape sequence ('\\') */          char            *stesc; /* start of an escape sequence ('\\') */
           char            *ep;    /* end of comment string */
         const char      *stnam; /* start of the name, after "[(*" */          const char      *stnam; /* start of the name, after "[(*" */
         const char      *cp;    /* end of the name, e.g. before ']' */          const char      *cp;    /* end of the name, e.g. before ']' */
         const char      *res;   /* the string to be substituted */          const char      *res;   /* the string to be substituted */
Line 1134  roff_res(struct roff *r, struct buf *buf, int ln, int 
Line 1140  roff_res(struct roff *r, struct buf *buf, int ln, int 
         int              done;  /* no more input available */          int              done;  /* no more input available */
         int              deftype; /* type of definition to paste */          int              deftype; /* type of definition to paste */
         int              rcsid; /* kind of RCS id seen */          int              rcsid; /* kind of RCS id seen */
           char             sign;  /* increment number register */
         char             term;  /* character terminating the escape */          char             term;  /* character terminating the escape */
   
         /* Search forward for comments. */          /* Search forward for comments. */
Line 1168  roff_res(struct roff *r, struct buf *buf, int ln, int 
Line 1175  roff_res(struct roff *r, struct buf *buf, int ln, int 
   
                 /* Handle trailing whitespace. */                  /* Handle trailing whitespace. */
   
                 cp = strchr(stesc--, '\0') - 1;                  ep = strchr(stesc--, '\0') - 1;
                 if (*cp == '\n') {                  if (*ep == '\n') {
                         done = 1;                          done = 1;
                         cp--;                          ep--;
                 }                  }
                 if (*cp == ' ' || *cp == '\t')                  if (*ep == ' ' || *ep == '\t')
                         mandoc_msg(MANDOCERR_SPACE_EOL, r->parse,                          mandoc_msg(MANDOCERR_SPACE_EOL, r->parse,
                             ln, cp - buf->buf, NULL);                              ln, ep - buf->buf, NULL);
   
                   /*
                    * Save comments preceding the title macro
                    * in the syntax tree.
                    */
   
                   if (r->format == 0) {
                           while (*ep == ' ' || *ep == '\t')
                                   ep--;
                           ep[1] = '\0';
                           n = roff_node_alloc(r->man,
                               ln, stesc + 1 - buf->buf,
                               ROFFT_COMMENT, TOKEN_NONE);
                           n->string = mandoc_strdup(stesc + 2);
                           roff_node_append(r->man, n);
                           n->flags |= NODE_VALID | NODE_ENDED;
                           r->man->next = ROFF_NEXT_SIBLING;
                   }
   
                   /* Discard comments. */
   
                 while (stesc > start && stesc[-1] == ' ')                  while (stesc > start && stesc[-1] == ' ')
                         stesc--;                          stesc--;
                 *stesc = '\0';                  *stesc = '\0';
Line 1244  roff_res(struct roff *r, struct buf *buf, int ln, int 
Line 1272  roff_res(struct roff *r, struct buf *buf, int ln, int 
                         term = cp[1];                          term = cp[1];
                         /* FALLTHROUGH */                          /* FALLTHROUGH */
                 case 'n':                  case 'n':
                           sign = cp[1];
                           if (sign == '+' || sign == '-')
                                   cp++;
                         res = ubuf;                          res = ubuf;
                         break;                          break;
                 default:                  default:
Line 1348  roff_res(struct roff *r, struct buf *buf, int ln, int 
Line 1379  roff_res(struct roff *r, struct buf *buf, int ln, int 
                 case 'n':                  case 'n':
                         if (arg_complete)                          if (arg_complete)
                                 (void)snprintf(ubuf, sizeof(ubuf), "%d",                                  (void)snprintf(ubuf, sizeof(ubuf), "%d",
                                     roff_getregn(r, stnam, naml));                                      roff_getregn(r, stnam, naml, sign));
                         else                          else
                                 ubuf[0] = '\0';                                  ubuf[0] = '\0';
                         break;                          break;
Line 1559  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1590  roff_parseln(struct roff *r, int ln, struct buf *buf, 
         /* For now, let high level macros abort .ce mode. */          /* For now, let high level macros abort .ce mode. */
   
         if (ctl && roffce_node != NULL &&          if (ctl && roffce_node != NULL &&
             (t == TOKEN_NONE || t == ROFF_EQ || t == ROFF_TS)) {              (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ ||
                t == ROFF_TH || t == ROFF_TS)) {
                 r->man->last = roffce_node;                  r->man->last = roffce_node;
                 r->man->next = ROFF_NEXT_SIBLING;                  r->man->next = ROFF_NEXT_SIBLING;
                 roffce_lines = 0;                  roffce_lines = 0;
Line 1638  roff_parse(struct roff *r, char *buf, int *pos, int ln
Line 1670  roff_parse(struct roff *r, char *buf, int *pos, int ln
         }          }
         if (t != TOKEN_NONE)          if (t != TOKEN_NONE)
                 *pos = cp - buf;                  *pos = cp - buf;
           else if (deftype == ROFFDEF_UNDEF) {
                   /* Using an undefined macro defines it to be empty. */
                   roff_setstrn(&r->strtab, mac, maclen, "", 0, 0);
                   roff_setstrn(&r->rentab, mac, maclen, NULL, 0, 0);
           }
         return t;          return t;
 }  }
   
Line 2514  roff_evalnum(struct roff *r, int ln, const char *v,
Line 2551  roff_evalnum(struct roff *r, int ln, const char *v,
 void  void
 roff_setreg(struct roff *r, const char *name, int val, char sign)  roff_setreg(struct roff *r, const char *name, int val, char sign)
 {  {
           roff_setregn(r, name, strlen(name), val, sign, INT_MIN);
   }
   
   static void
   roff_setregn(struct roff *r, const char *name, size_t len,
       int val, char sign, int step)
   {
         struct roffreg  *reg;          struct roffreg  *reg;
   
         /* Search for an existing register with the same name. */          /* Search for an existing register with the same name. */
         reg = r->regtab;          reg = r->regtab;
   
         while (reg && strcmp(name, reg->key.p))          while (reg != NULL && (reg->key.sz != len ||
               strncmp(reg->key.p, name, len) != 0))
                 reg = reg->next;                  reg = reg->next;
   
         if (NULL == reg) {          if (NULL == reg) {
                 /* Create a new register. */                  /* Create a new register. */
                 reg = mandoc_malloc(sizeof(struct roffreg));                  reg = mandoc_malloc(sizeof(struct roffreg));
                 reg->key.p = mandoc_strdup(name);                  reg->key.p = mandoc_strndup(name, len);
                 reg->key.sz = strlen(name);                  reg->key.sz = len;
                 reg->val = 0;                  reg->val = 0;
                   reg->step = 0;
                 reg->next = r->regtab;                  reg->next = r->regtab;
                 r->regtab = reg;                  r->regtab = reg;
         }          }
Line 2538  roff_setreg(struct roff *r, const char *name, int val,
Line 2584  roff_setreg(struct roff *r, const char *name, int val,
                 reg->val -= val;                  reg->val -= val;
         else          else
                 reg->val = val;                  reg->val = val;
           if (step != INT_MIN)
                   reg->step = step;
 }  }
   
 /*  /*
Line 2571  roff_getregro(const struct roff *r, const char *name)
Line 2619  roff_getregro(const struct roff *r, const char *name)
 }  }
   
 int  int
 roff_getreg(const struct roff *r, const char *name)  roff_getreg(struct roff *r, const char *name)
 {  {
         struct roffreg  *reg;          return roff_getregn(r, name, strlen(name), '\0');
         int              val;  
   
         if ('.' == name[0] && '\0' != name[1] && '\0' == name[2]) {  
                 val = roff_getregro(r, name + 1);  
                 if (-1 != val)  
                         return val;  
         }  
   
         for (reg = r->regtab; reg; reg = reg->next)  
                 if (0 == strcmp(name, reg->key.p))  
                         return reg->val;  
   
         return 0;  
 }  }
   
 static int  static int
 roff_getregn(const struct roff *r, const char *name, size_t len)  roff_getregn(struct roff *r, const char *name, size_t len, char sign)
 {  {
         struct roffreg  *reg;          struct roffreg  *reg;
         int              val;          int              val;
Line 2601  roff_getregn(const struct roff *r, const char *name, s
Line 2636  roff_getregn(const struct roff *r, const char *name, s
                         return val;                          return val;
         }          }
   
         for (reg = r->regtab; reg; reg = reg->next)          for (reg = r->regtab; reg; reg = reg->next) {
                 if (len == reg->key.sz &&                  if (len == reg->key.sz &&
                     0 == strncmp(name, reg->key.p, len))                      0 == strncmp(name, reg->key.p, len)) {
                           switch (sign) {
                           case '+':
                                   reg->val += reg->step;
                                   break;
                           case '-':
                                   reg->val -= reg->step;
                                   break;
                           default:
                                   break;
                           }
                         return reg->val;                          return reg->val;
                   }
           }
   
           roff_setregn(r, name, len, 0, '\0', INT_MIN);
         return 0;          return 0;
 }  }
   
Line 2645  roff_freereg(struct roffreg *reg)
Line 2693  roff_freereg(struct roffreg *reg)
 static enum rofferr  static enum rofferr
 roff_nr(ROFF_ARGS)  roff_nr(ROFF_ARGS)
 {  {
         char            *key, *val;          char            *key, *val, *step;
         size_t           keysz;          size_t           keysz;
         int              iv;          int              iv, is, len;
         char             sign;          char             sign;
   
         key = val = buf->buf + pos;          key = val = buf->buf + pos;
Line 2657  roff_nr(ROFF_ARGS)
Line 2705  roff_nr(ROFF_ARGS)
         keysz = roff_getname(r, &val, ln, pos);          keysz = roff_getname(r, &val, ln, pos);
         if (key[keysz] == '\\')          if (key[keysz] == '\\')
                 return ROFF_IGN;                  return ROFF_IGN;
         key[keysz] = '\0';  
   
         sign = *val;          sign = *val;
         if (sign == '+' || sign == '-')          if (sign == '+' || sign == '-')
                 val++;                  val++;
   
         if (roff_evalnum(r, ln, val, NULL, &iv, ROFFNUM_SCALE))          len = 0;
                 roff_setreg(r, key, iv, sign);          if (roff_evalnum(r, ln, val, &len, &iv, ROFFNUM_SCALE) == 0)
                   return ROFF_IGN;
   
           step = val + len;
           while (isspace((unsigned char)*step))
                   step++;
           if (roff_evalnum(r, ln, step, NULL, &is, 0) == 0)
                   is = INT_MIN;
   
           roff_setregn(r, key, keysz, iv, sign, is);
         return ROFF_IGN;          return ROFF_IGN;
 }  }
   
Line 3536  roff_setstrn(struct roffkv **r, const char *name, size
Line 3591  roff_setstrn(struct roffkv **r, const char *name, size
 }  }
   
 static const char *  static const char *
 roff_getstrn(const struct roff *r, const char *name, size_t len,  roff_getstrn(struct roff *r, const char *name, size_t len,
     int *deftype)      int *deftype)
 {  {
         const struct roffkv     *n;          const struct roffkv     *n;
         int                      i;          int                      found, i;
         enum roff_tok            tok;          enum roff_tok            tok;
   
         if (*deftype & ROFFDEF_USER) {          found = 0;
                 for (n = r->strtab; n != NULL; n = n->next) {          for (n = r->strtab; n != NULL; n = n->next) {
                         if (strncmp(name, n->key.p, len) == 0 &&                  if (strncmp(name, n->key.p, len) != 0 ||
                             n->key.p[len] == '\0' &&                      n->key.p[len] != '\0' || n->val.p == NULL)
                             n->val.p != NULL) {                          continue;
                                 *deftype = ROFFDEF_USER;                  if (*deftype & ROFFDEF_USER) {
                                 return n->val.p;                          *deftype = ROFFDEF_USER;
                         }                          return n->val.p;
                   } else {
                           found = 1;
                           break;
                 }                  }
         }          }
         if (*deftype & ROFFDEF_PRE) {          for (n = r->rentab; n != NULL; n = n->next) {
                 for (i = 0; i < PREDEFS_MAX; i++) {                  if (strncmp(name, n->key.p, len) != 0 ||
                         if (strncmp(name, predefs[i].name, len) == 0 &&                      n->key.p[len] != '\0' || n->val.p == NULL)
                             predefs[i].name[len] == '\0') {                          continue;
                                 *deftype = ROFFDEF_PRE;                  if (*deftype & ROFFDEF_REN) {
                                 return predefs[i].str;                          *deftype = ROFFDEF_REN;
                         }                          return n->val.p;
                   } else {
                           found = 1;
                           break;
                 }                  }
         }          }
         if (*deftype & ROFFDEF_REN) {          for (i = 0; i < PREDEFS_MAX; i++) {
                 for (n = r->rentab; n != NULL; n = n->next) {                  if (strncmp(name, predefs[i].name, len) != 0 ||
                         if (strncmp(name, n->key.p, len) == 0 &&                      predefs[i].name[len] != '\0')
                             n->key.p[len] == '\0' &&                          continue;
                             n->val.p != NULL) {                  if (*deftype & ROFFDEF_PRE) {
                                 *deftype = ROFFDEF_REN;                          *deftype = ROFFDEF_PRE;
                                 return n->val.p;                          return predefs[i].str;
                         }                  } else {
                           found = 1;
                           break;
                 }                  }
         }          }
         if (*deftype & ROFFDEF_STD) {          if (r->man->macroset != MACROSET_MAN) {
                 if (r->man->macroset != MACROSET_MAN) {                  for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) {
                         for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) {                          if (strncmp(name, roff_name[tok], len) != 0 ||
                                 if (strncmp(name, roff_name[tok], len) == 0 &&                              roff_name[tok][len] != '\0')
                                     roff_name[tok][len] == '\0') {                                  continue;
                                         *deftype = ROFFDEF_STD;                          if (*deftype & ROFFDEF_STD) {
                                         return NULL;                                  *deftype = ROFFDEF_STD;
                                 }                                  return NULL;
                           } else {
                                   found = 1;
                                   break;
                         }                          }
                 }                  }
                 if (r->man->macroset != MACROSET_MDOC) {          }
                         for (tok = MAN_TH; tok < MAN_MAX; tok++) {          if (r->man->macroset != MACROSET_MDOC) {
                                 if (strncmp(name, roff_name[tok], len) == 0 &&                  for (tok = MAN_TH; tok < MAN_MAX; tok++) {
                                     roff_name[tok][len] == '\0') {                          if (strncmp(name, roff_name[tok], len) != 0 ||
                                         *deftype = ROFFDEF_STD;                              roff_name[tok][len] != '\0')
                                         return NULL;                                  continue;
                                 }                          if (*deftype & ROFFDEF_STD) {
                                   *deftype = ROFFDEF_STD;
                                   return NULL;
                           } else {
                                   found = 1;
                                   break;
                         }                          }
                 }                  }
         }          }
   
           if (found == 0 && *deftype != ROFFDEF_ANY) {
                   if (*deftype & ROFFDEF_REN) {
                           /*
                            * This might still be a request,
                            * so do not treat it as undefined yet.
                            */
                           *deftype = ROFFDEF_UNDEF;
                           return NULL;
                   }
   
                   /* Using an undefined string defines it to be empty. */
   
                   roff_setstrn(&r->strtab, name, len, "", 0, 0);
                   roff_setstrn(&r->rentab, name, len, NULL, 0, 0);
           }
   
         *deftype = 0;          *deftype = 0;
         return NULL;          return NULL;
 }  }

Legend:
Removed from v.1.323  
changed lines
  Added in v.1.328

CVSweb