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

Diff for /mandoc/roff.c between version 1.315 and 1.325

version 1.315, 2017/06/18 17:36:03 version 1.325, 2018/04/09 02:31:42
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 98  struct roff {
Line 99  struct roff {
         struct tbl_node *first_tbl; /* first table parsed */          struct tbl_node *first_tbl; /* first table parsed */
         struct tbl_node *last_tbl; /* last table parsed */          struct tbl_node *last_tbl; /* last table parsed */
         struct tbl_node *tbl; /* current table being parsed */          struct tbl_node *tbl; /* current table being parsed */
         struct eqn_node *last_eqn; /* last equation parsed */          struct eqn_node *last_eqn; /* equation parser */
         struct eqn_node *first_eqn; /* first equation parsed */          struct eqn_node *eqn; /* active equation parser */
         struct eqn_node *eqn; /* current equation being parsed */  
         int              eqn_inline; /* current equation is inline */          int              eqn_inline; /* current equation is inline */
         int              options; /* parse options */          int              options; /* parse options */
         int              rstacksz; /* current size limit of rstack */          int              rstacksz; /* current size limit of rstack */
Line 154  static void   roffnode_cleanscope(struct roff *);
Line 154  static void   roffnode_cleanscope(struct roff *);
 static  void             roffnode_pop(struct roff *);  static  void             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  enum rofferr     roff_als(ROFF_ARGS);  static  enum rofferr     roff_als(ROFF_ARGS);
 static  enum rofferr     roff_block(ROFF_ARGS);  static  enum rofferr     roff_block(ROFF_ARGS);
 static  enum rofferr     roff_block_text(ROFF_ARGS);  static  enum rofferr     roff_block_text(ROFF_ARGS);
Line 185  static int   roff_getregn(const struct roff *,
Line 186  static int   roff_getregn(const struct roff *,
                                 const char *, size_t);                                  const char *, size_t);
 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 330  const char *__roff_name[MAN_MAX + 1] = {
Line 331  const char *__roff_name[MAN_MAX + 1] = {
         "RE",           "RS",           "DT",           "UC",          "RE",           "RS",           "DT",           "UC",
         "PD",           "AT",           "in",          "PD",           "AT",           "in",
         "OP",           "EX",           "EE",           "UR",          "OP",           "EX",           "EE",           "UR",
         "UE",           NULL          "UE",           "MT",           "ME",           NULL
 };  };
 const   char *const *roff_name = __roff_name;  const   char *const *roff_name = __roff_name;
   
Line 695  static void
Line 696  static void
 roff_free1(struct roff *r)  roff_free1(struct roff *r)
 {  {
         struct tbl_node *tbl;          struct tbl_node *tbl;
         struct eqn_node *e;  
         int              i;          int              i;
   
         while (NULL != (tbl = r->first_tbl)) {          while (NULL != (tbl = r->first_tbl)) {
Line 704  roff_free1(struct roff *r)
Line 704  roff_free1(struct roff *r)
         }          }
         r->first_tbl = r->last_tbl = r->tbl = NULL;          r->first_tbl = r->last_tbl = r->tbl = NULL;
   
         while (NULL != (e = r->first_eqn)) {          if (r->last_eqn != NULL)
                 r->first_eqn = e->next;                  eqn_free(r->last_eqn);
                 eqn_free(e);          r->last_eqn = r->eqn = NULL;
         }  
         r->first_eqn = r->last_eqn = r->eqn = NULL;  
   
         while (r->last)          while (r->last)
                 roffnode_pop(r);                  roffnode_pop(r);
Line 819  roff_man_free(struct roff_man *man)
Line 817  roff_man_free(struct roff_man *man)
   
 struct roff_man *  struct roff_man *
 roff_man_alloc(struct roff *roff, struct mparse *parse,  roff_man_alloc(struct roff *roff, struct mparse *parse,
         const char *defos, int quick)          const char *os_s, int quick)
 {  {
         struct roff_man *man;          struct roff_man *man;
   
         man = mandoc_calloc(1, sizeof(*man));          man = mandoc_calloc(1, sizeof(*man));
         man->parse = parse;          man->parse = parse;
         man->roff = roff;          man->roff = roff;
         man->defos = defos;          man->os_s = os_s;
         man->quick = quick;          man->quick = quick;
         roff_man_alloc1(man);          roff_man_alloc1(man);
         roff->man = man;          roff->man = man;
Line 983  roff_body_alloc(struct roff_man *man, int line, int po
Line 981  roff_body_alloc(struct roff_man *man, int line, int po
         return n;          return n;
 }  }
   
 void  static void
 roff_addeqn(struct roff_man *man, const struct eqn *eqn)  roff_addtbl(struct roff_man *man, struct tbl_node *tbl)
 {  {
         struct roff_node        *n;          struct roff_node        *n;
           const struct tbl_span   *span;
   
         n = roff_node_alloc(man, eqn->ln, eqn->pos, ROFFT_EQN, TOKEN_NONE);  
         n->eqn = eqn;  
         if (eqn->ln > man->last->line)  
                 n->flags |= NODE_LINE;  
         roff_node_append(man, n);  
         man->next = ROFF_NEXT_SIBLING;  
 }  
   
 void  
 roff_addtbl(struct roff_man *man, const struct tbl_span *tbl)  
 {  
         struct roff_node        *n;  
   
         if (man->macroset == MACROSET_MAN)          if (man->macroset == MACROSET_MAN)
                 man_breakscope(man, ROFF_TS);                  man_breakscope(man, ROFF_TS);
         n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE);          while ((span = tbl_span(tbl)) != NULL) {
         n->span = tbl;                  n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE);
         roff_node_append(man, n);                  n->span = span;
         n->flags |= NODE_VALID | NODE_ENDED;                  roff_node_append(man, n);
         man->next = ROFF_NEXT_SIBLING;                  n->flags |= NODE_VALID | NODE_ENDED;
                   man->next = ROFF_NEXT_SIBLING;
           }
 }  }
   
 void  void
Line 1055  roff_node_free(struct roff_node *n)
Line 1043  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);
         free(n->string);          free(n->string);
         free(n);          free(n);
 }  }
Line 1138  roff_res(struct roff *r, struct buf *buf, int ln, int 
Line 1128  roff_res(struct roff *r, struct buf *buf, int ln, int 
         size_t           maxl;  /* expected length of the escape name */          size_t           maxl;  /* expected length of the escape name */
         size_t           naml;  /* actual length of the escape name */          size_t           naml;  /* actual length of the escape name */
         enum mandoc_esc  esc;   /* type of the escape sequence */          enum mandoc_esc  esc;   /* type of the escape sequence */
         enum mdoc_os     os_e;  /* kind of RCS id seen */  
         int              inaml; /* length returned from mandoc_escape() */          int              inaml; /* length returned from mandoc_escape() */
         int              expand_count;  /* to avoid infinite loops */          int              expand_count;  /* to avoid infinite loops */
         int              npos;  /* position in numeric expression */          int              npos;  /* position in numeric expression */
         int              arg_complete; /* argument not interrupted by eol */          int              arg_complete; /* argument not interrupted by eol */
         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 */
         char             term;  /* character terminating the escape */          char             term;  /* character terminating the escape */
   
         /* Search forward for comments. */          /* Search forward for comments. */
Line 1160  roff_res(struct roff *r, struct buf *buf, int ln, int 
Line 1150  roff_res(struct roff *r, struct buf *buf, int ln, int 
   
                 /* Comment found, look for RCS id. */                  /* Comment found, look for RCS id. */
   
                   rcsid = 0;
                 if ((cp = strstr(stesc, "$" "OpenBSD")) != NULL) {                  if ((cp = strstr(stesc, "$" "OpenBSD")) != NULL) {
                         os_e = MDOC_OS_OPENBSD;                          rcsid = 1 << MANDOC_OS_OPENBSD;
                         cp += 8;                          cp += 8;
                 } else if ((cp = strstr(stesc, "$" "NetBSD")) != NULL) {                  } else if ((cp = strstr(stesc, "$" "NetBSD")) != NULL) {
                         os_e = MDOC_OS_NETBSD;                          rcsid = 1 << MANDOC_OS_NETBSD;
                         cp += 7;                          cp += 7;
                 }                  }
                 if (cp != NULL &&                  if (cp != NULL &&
                     isalnum((unsigned char)*cp) == 0 &&                      isalnum((unsigned char)*cp) == 0 &&
                     strchr(cp, '$') != NULL) {                      strchr(cp, '$') != NULL) {
                         if (r->man->meta.rcsids & (1 << os_e))                          if (r->man->meta.rcsids & rcsid)
                                 mandoc_msg(MANDOCERR_RCS_REP, r->parse,                                  mandoc_msg(MANDOCERR_RCS_REP, r->parse,
                                     ln, stesc + 1 - buf->buf, stesc + 1);                                      ln, stesc + 1 - buf->buf, stesc + 1);
                         r->man->meta.rcsids |= 1 << os_e;                          r->man->meta.rcsids |= rcsid;
                 }                  }
   
                 /* Handle trailing whitespace. */                  /* Handle trailing whitespace. */
Line 1512  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1503  roff_parseln(struct roff *r, int ln, struct buf *buf, 
                         return e;                          return e;
                 assert(e == ROFF_CONT);                  assert(e == ROFF_CONT);
         }          }
         if (r->eqn != NULL)          if (r->eqn != NULL && strncmp(buf->buf + ppos, ".EN", 3)) {
                 return eqn_read(&r->eqn, ln, buf->buf, ppos, offs);                  eqn_read(r->eqn, buf->buf + ppos);
         if (r->tbl != NULL && ( ! ctl || buf->buf[pos] == '\0'))                  return ROFF_IGN;
                 return tbl_read(r->tbl, ln, buf->buf, ppos);          }
           if (r->tbl != NULL && (ctl == 0 || buf->buf[pos] == '\0')) {
                   tbl_read(r->tbl, ln, buf->buf, ppos);
                   roff_addtbl(r->man, r->tbl);
                   return ROFF_IGN;
           }
         if ( ! ctl)          if ( ! ctl)
                 return roff_parsetext(r, buf, pos, offs);                  return roff_parsetext(r, buf, pos, offs);
   
Line 1556  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1552  roff_parseln(struct roff *r, int ln, struct buf *buf, 
                         pos++;                          pos++;
                 while (buf->buf[pos] == ' ')                  while (buf->buf[pos] == ' ')
                         pos++;                          pos++;
                 return tbl_read(r->tbl, ln, buf->buf, pos);                  tbl_read(r->tbl, ln, buf->buf, pos);
                   roff_addtbl(r->man, r->tbl);
                   return ROFF_IGN;
         }          }
   
         /* 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 1585  roff_parseln(struct roff *r, int ln, struct buf *buf, 
Line 1584  roff_parseln(struct roff *r, int ln, struct buf *buf, 
 void  void
 roff_endparse(struct roff *r)  roff_endparse(struct roff *r)
 {  {
           if (r->last != NULL)
         if (r->last)  
                 mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,                  mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,
                     r->last->line, r->last->col,                      r->last->line, r->last->col,
                     roff_name[r->last->tok]);                      roff_name[r->last->tok]);
   
         if (r->eqn) {          if (r->eqn != NULL) {
                 mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,                  mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,
                     r->eqn->eqn.ln, r->eqn->eqn.pos, "EQ");                      r->eqn->node->line, r->eqn->node->pos, "EQ");
                 eqn_end(&r->eqn);                  eqn_parse(r->eqn);
                   r->eqn = NULL;
         }          }
   
         if (r->tbl) {          if (r->tbl != NULL) {
                 mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,                  mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,
                     r->tbl->line, r->tbl->pos, "TS");                      r->tbl->line, r->tbl->pos, "TS");
                 tbl_end(&r->tbl);                  tbl_end(r->tbl);
                   r->tbl = NULL;
         }          }
 }  }
   
Line 1640  roff_parse(struct roff *r, char *buf, int *pos, int ln
Line 1640  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 1926  roff_cond_sub(ROFF_ARGS)
Line 1931  roff_cond_sub(ROFF_ARGS)
   
         rr = r->last->rule;          rr = r->last->rule;
         roffnode_cleanscope(r);          roffnode_cleanscope(r);
         t = roff_parse(r, buf->buf, &pos, ln, ppos);  
   
         /*          /*
          * Fully handle known macros when they are structurally  
          * required or when the conditional evaluated to true.  
          */  
   
         if (t != TOKEN_NONE && (rr || roffs[t].flags & ROFFMAC_STRUCT))  
                 return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);  
   
         /*  
          * If `\}' occurs on a macro line without a preceding macro,           * If `\}' occurs on a macro line without a preceding macro,
          * drop the line completely.           * drop the line completely.
          */           */
Line 1948  roff_cond_sub(ROFF_ARGS)
Line 1944  roff_cond_sub(ROFF_ARGS)
         /* Always check for the closing delimiter `\}'. */          /* Always check for the closing delimiter `\}'. */
   
         while ((ep = strchr(ep, '\\')) != NULL) {          while ((ep = strchr(ep, '\\')) != NULL) {
                 if (*(++ep) == '}') {                  switch (ep[1]) {
                         *ep = '&';                  case '}':
                         roff_ccond(r, ln, ep - buf->buf - 1);                          memmove(ep, ep + 2, strlen(ep + 2) + 1);
                 }                          roff_ccond(r, ln, ep - buf->buf);
                 if (*ep != '\0')                          break;
                   case '\0':
                         ++ep;                          ++ep;
                           break;
                   default:
                           ep += 2;
                           break;
                   }
         }          }
         return rr ? ROFF_CONT : ROFF_IGN;  
           /*
            * Fully handle known macros when they are structurally
            * required or when the conditional evaluated to true.
            */
   
           t = roff_parse(r, buf->buf, &pos, ln, ppos);
           return t != TOKEN_NONE && (rr || roffs[t].flags & ROFFMAC_STRUCT)
               ? (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs) : rr
               ? ROFF_CONT : ROFF_IGN;
 }  }
   
 static enum rofferr  static enum rofferr
Line 2776  roff_Dd(ROFF_ARGS)
Line 2787  roff_Dd(ROFF_ARGS)
 static enum rofferr  static enum rofferr
 roff_TE(ROFF_ARGS)  roff_TE(ROFF_ARGS)
 {  {
           if (r->tbl == NULL) {
         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 if ( ! tbl_end(&r->tbl)) {                  return ROFF_IGN;
           }
           if (tbl_end(r->tbl) == 0) {
                   r->tbl = NULL;
                 free(buf->buf);                  free(buf->buf);
                 buf->buf = mandoc_strdup(".sp");                  buf->buf = mandoc_strdup(".sp");
                 buf->sz = 4;                  buf->sz = 4;
                 return ROFF_REPARSE;                  return ROFF_REPARSE;
         }          }
           r->tbl = NULL;
         return ROFF_IGN;          return ROFF_IGN;
 }  }
   
Line 2871  roff_eqndelim(struct roff *r, struct buf *buf, int pos
Line 2885  roff_eqndelim(struct roff *r, struct buf *buf, int pos
 static enum rofferr  static enum rofferr
 roff_EQ(ROFF_ARGS)  roff_EQ(ROFF_ARGS)
 {  {
         struct eqn_node *e;          struct roff_node        *n;
   
           if (r->man->macroset == MACROSET_MAN)
                   man_breakscope(r->man, ROFF_EQ);
           n = roff_node_alloc(r->man, ln, ppos, ROFFT_EQN, TOKEN_NONE);
           if (ln > r->man->last->line)
                   n->flags |= NODE_LINE;
           n->eqn = mandoc_calloc(1, sizeof(*n->eqn));
           n->eqn->expectargs = UINT_MAX;
           roff_node_append(r->man, n);
           r->man->next = ROFF_NEXT_SIBLING;
   
         assert(r->eqn == NULL);          assert(r->eqn == NULL);
         e = eqn_alloc(ppos, ln, r->parse);          if (r->last_eqn == NULL)
                   r->last_eqn = eqn_alloc(r->parse);
           else
                   eqn_reset(r->last_eqn);
           r->eqn = r->last_eqn;
           r->eqn->node = n;
   
         if (r->last_eqn) {  
                 r->last_eqn->next = e;  
                 e->delim = r->last_eqn->delim;  
                 e->odelim = r->last_eqn->odelim;  
                 e->cdelim = r->last_eqn->cdelim;  
         } else  
                 r->first_eqn = r->last_eqn = e;  
   
         r->eqn = r->last_eqn = e;  
   
         if (buf->buf[pos] != '\0')          if (buf->buf[pos] != '\0')
                 mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos,                  mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos,
                     ".EQ %s", buf->buf + pos);                      ".EQ %s", buf->buf + pos);
Line 2896  roff_EQ(ROFF_ARGS)
Line 2915  roff_EQ(ROFF_ARGS)
 static enum rofferr  static enum rofferr
 roff_EN(ROFF_ARGS)  roff_EN(ROFF_ARGS)
 {  {
           if (r->eqn != NULL) {
         mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, "EN");                  eqn_parse(r->eqn);
                   r->eqn = NULL;
           } else
                   mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, "EN");
           if (buf->buf[pos] != '\0')
                   mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos,
                       "EN %s", buf->buf + pos);
         return ROFF_IGN;          return ROFF_IGN;
 }  }
   
 static enum rofferr  static enum rofferr
 roff_TS(ROFF_ARGS)  roff_TS(ROFF_ARGS)
 {  {
         struct tbl_node *tbl;          if (r->tbl != NULL) {
   
         if (r->tbl) {  
                 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);
         }          }
           r->tbl = tbl_alloc(ppos, ln, r->parse);
         tbl = tbl_alloc(ppos, ln, r->parse);  
   
         if (r->last_tbl)          if (r->last_tbl)
                 r->last_tbl->next = tbl;                  r->last_tbl->next = r->tbl;
         else          else
                 r->first_tbl = r->last_tbl = tbl;                  r->first_tbl = r->tbl;
           r->last_tbl = r->tbl;
         r->tbl = r->last_tbl = tbl;  
         return ROFF_IGN;          return ROFF_IGN;
 }  }
   
Line 2931  roff_onearg(ROFF_ARGS)
Line 2951  roff_onearg(ROFF_ARGS)
         int                      npos;          int                      npos;
   
         if (r->man->flags & (MAN_BLINE | MAN_ELINE) &&          if (r->man->flags & (MAN_BLINE | MAN_ELINE) &&
             (tok == ROFF_sp || tok == ROFF_ti))              (tok == ROFF_ce || tok == ROFF_rj || tok == ROFF_sp ||
                tok == ROFF_ti))
                 man_breakscope(r->man, tok);                  man_breakscope(r->man, tok);
   
         if (roffce_node != NULL && (tok == ROFF_ce || tok == ROFF_rj)) {          if (roffce_node != NULL && (tok == ROFF_ce || tok == ROFF_rj)) {
Line 3522  roff_setstrn(struct roffkv **r, const char *name, size
Line 3543  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;
 }  }
Line 3596  roff_freestr(struct roffkv *r)
Line 3650  roff_freestr(struct roffkv *r)
 }  }
   
 /* --- accessors and utility functions ------------------------------------ */  /* --- accessors and utility functions ------------------------------------ */
   
 const struct tbl_span *  
 roff_span(const struct roff *r)  
 {  
   
         return r->tbl ? tbl_span(r->tbl) : NULL;  
 }  
   
 const struct eqn *  
 roff_eqn(const struct roff *r)  
 {  
   
         return r->last_eqn ? &r->last_eqn->eqn : NULL;  
 }  
   
 /*  /*
  * Duplicate an input string, making the appropriate character   * Duplicate an input string, making the appropriate character

Legend:
Removed from v.1.315  
changed lines
  Added in v.1.325

CVSweb