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

Diff for /mandoc/read.c between version 1.203 and 1.211

version 1.203, 2018/12/14 01:18:26 version 1.211, 2019/01/11 17:04:44
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org>   * Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
Line 47 
Line 47 
 struct  mparse {  struct  mparse {
         struct roff      *roff; /* roff parser (!NULL) */          struct roff      *roff; /* roff parser (!NULL) */
         struct roff_man  *man; /* man parser */          struct roff_man  *man; /* man parser */
         char             *sodest; /* filename pointed to by .so */  
         struct buf       *primary; /* buffer currently being parsed */          struct buf       *primary; /* buffer currently being parsed */
         struct buf       *secondary; /* copy of top level input */          struct buf       *secondary; /* copy of top level input */
         struct buf       *loop; /* open .while request line */          struct buf       *loop; /* open .while request line */
Line 65  static void   resize_buf(struct buf *, size_t);
Line 64  static void   resize_buf(struct buf *, size_t);
 static  int       mparse_buf_r(struct mparse *, struct buf, size_t, int);  static  int       mparse_buf_r(struct mparse *, struct buf, size_t, int);
 static  int       read_whole_file(struct mparse *, int, struct buf *, int *);  static  int       read_whole_file(struct mparse *, int, struct buf *, int *);
 static  void      mparse_end(struct mparse *);  static  void      mparse_end(struct mparse *);
 static  void      mparse_parse_buffer(struct mparse *, struct buf,  
                         const char *);  
   
   
 static void  static void
Line 125  choose_parser(struct mparse *curp)
Line 122  choose_parser(struct mparse *curp)
         }          }
   
         if (format == MPARSE_MDOC) {          if (format == MPARSE_MDOC) {
                 curp->man->macroset = MACROSET_MDOC;                  curp->man->meta.macroset = MACROSET_MDOC;
                 if (curp->man->mdocmac == NULL)                  if (curp->man->mdocmac == NULL)
                         curp->man->mdocmac = roffhash_alloc(MDOC_Dd, MDOC_MAX);                          curp->man->mdocmac = roffhash_alloc(MDOC_Dd, MDOC_MAX);
         } else {          } else {
                 curp->man->macroset = MACROSET_MAN;                  curp->man->meta.macroset = MACROSET_MAN;
                 if (curp->man->manmac == NULL)                  if (curp->man->manmac == NULL)
                         curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX);                          curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX);
         }          }
         curp->man->first->tok = TOKEN_NONE;          curp->man->meta.first->tok = TOKEN_NONE;
 }  }
   
 /*  /*
Line 210  mparse_buf_r(struct mparse *curp, struct buf blk, size
Line 207  mparse_buf_r(struct mparse *curp, struct buf blk, size
                         if (c & 0x80) {                          if (c & 0x80) {
                                 if ( ! (curp->filenc && preconv_encode(                                  if ( ! (curp->filenc && preconv_encode(
                                     &blk, &i, &ln, &pos, &curp->filenc))) {                                      &blk, &i, &ln, &pos, &curp->filenc))) {
                                         mandoc_vmsg(MANDOCERR_CHAR_BAD, curp,                                          mandoc_msg(MANDOCERR_CHAR_BAD,
                                             curp->line, pos, "0x%x", c);                                              curp->line, pos, "0x%x", c);
                                         ln.buf[pos++] = '?';                                          ln.buf[pos++] = '?';
                                         i++;                                          i++;
Line 223  mparse_buf_r(struct mparse *curp, struct buf blk, size
Line 220  mparse_buf_r(struct mparse *curp, struct buf blk, size
                          */                           */
   
                         if (c == 0x7f || (c < 0x20 && c != 0x09)) {                          if (c == 0x7f || (c < 0x20 && c != 0x09)) {
                                 mandoc_vmsg(c == 0x00 || c == 0x04 ||                                  mandoc_msg(c == 0x00 || c == 0x04 ||
                                     c > 0x0a ? MANDOCERR_CHAR_BAD :                                      c > 0x0a ? MANDOCERR_CHAR_BAD :
                                     MANDOCERR_CHAR_UNSUPP,                                      MANDOCERR_CHAR_UNSUPP,
                                     curp, curp->line, pos, "0x%x", c);                                      curp->line, pos, "0x%x", c);
                                 i++;                                  i++;
                                 if (c != '\r')                                  if (c != '\r')
                                         ln.buf[pos++] = '?';                                          ln.buf[pos++] = '?';
Line 300  rerun:
Line 297  rerun:
                                 if (loop == curp->loop)                                  if (loop == curp->loop)
                                         break;                                          break;
                                 mandoc_msg(MANDOCERR_WHILE_NEST,                                  mandoc_msg(MANDOCERR_WHILE_NEST,
                                     curp, curp->line, pos, NULL);                                      curp->line, pos, NULL);
                         }                          }
                         curp->loop = thisln;                          curp->loop = thisln;
                         loop = NULL;                          loop = NULL;
Line 310  rerun:
Line 307  rerun:
                 case ROFF_LOOPEXIT:                  case ROFF_LOOPEXIT:
                         if (curp->loop == NULL) {                          if (curp->loop == NULL) {
                                 mandoc_msg(MANDOCERR_WHILE_FAIL,                                  mandoc_msg(MANDOCERR_WHILE_FAIL,
                                     curp, curp->line, pos, NULL);                                      curp->line, pos, NULL);
                                 break;                                  break;
                         }                          }
                         if (inloop == 0) {                          if (inloop == 0) {
                                 mandoc_msg(MANDOCERR_WHILE_INTO,                                  mandoc_msg(MANDOCERR_WHILE_INTO,
                                     curp, curp->line, pos, NULL);                                      curp->line, pos, NULL);
                                 curp->loop = loop = NULL;                                  curp->loop = loop = NULL;
                                 break;                                  break;
                         }                          }
Line 336  rerun:
Line 333  rerun:
                 case ROFF_IGN:                  case ROFF_IGN:
                         break;                          break;
                 case ROFF_CONT:                  case ROFF_CONT:
                         if (curp->man->macroset == MACROSET_NONE)                          if (curp->man->meta.macroset == MACROSET_NONE)
                                 choose_parser(curp);                                  choose_parser(curp);
                         if ((curp->man->macroset == MACROSET_MDOC ?                          if ((curp->man->meta.macroset == MACROSET_MDOC ?
                              mdoc_parseln(curp->man, curp->line, ln.buf, of) :                               mdoc_parseln(curp->man, curp->line, ln.buf, of) :
                              man_parseln(curp->man, curp->line, ln.buf, of)                               man_parseln(curp->man, curp->line, ln.buf, of)
                             ) == 2)                              ) == 2)
Line 350  rerun:
Line 347  rerun:
                         if (++curp->reparse_count > REPARSE_LIMIT) {                          if (++curp->reparse_count > REPARSE_LIMIT) {
                                 /* Abort and return to the top level. */                                  /* Abort and return to the top level. */
                                 result = ROFF_IGN;                                  result = ROFF_IGN;
                                 mandoc_msg(MANDOCERR_ROFFLOOP, curp,                                  mandoc_msg(MANDOCERR_ROFFLOOP,
                                     curp->line, pos, NULL);                                      curp->line, pos, NULL);
                                 goto out;                                  goto out;
                         }                          }
Line 367  rerun:
Line 364  rerun:
                 case ROFF_SO:                  case ROFF_SO:
                         if ( ! (curp->options & MPARSE_SO) &&                          if ( ! (curp->options & MPARSE_SO) &&
                             (i >= blk.sz || blk.buf[i] == '\0')) {                              (i >= blk.sz || blk.buf[i] == '\0')) {
                                 curp->sodest = mandoc_strdup(ln.buf + of);                                  curp->man->meta.sodest =
                                       mandoc_strdup(ln.buf + of);
                                 goto out;                                  goto out;
                         }                          }
                         if ((fd = mparse_open(curp, ln.buf + of)) != -1) {                          if ((fd = mparse_open(curp, ln.buf + of)) != -1) {
                                 mparse_readfd(curp, fd, ln.buf + of);                                  mparse_readfd(curp, fd, ln.buf + of);
                                 close(fd);                                  close(fd);
                         } else {                          } else {
                                 mandoc_vmsg(MANDOCERR_SO_FAIL,                                  mandoc_msg(MANDOCERR_SO_FAIL,
                                     curp, curp->line, pos,                                      curp->line, of, ".so %s: %s",
                                     ".so %s", ln.buf + of);                                      ln.buf + of, strerror(errno));
                                 ln.sz = mandoc_asprintf(&cp,                                  ln.sz = mandoc_asprintf(&cp,
                                     ".sp\nSee the file %s.\n.sp",                                      ".sp\nSee the file %s.\n.sp",
                                     ln.buf + of);                                      ln.buf + of);
Line 411  rerun:
Line 409  rerun:
 out:  out:
         if (inloop) {          if (inloop) {
                 if (result != ROFF_USERRET)                  if (result != ROFF_USERRET)
                         mandoc_msg(MANDOCERR_WHILE_OUTOF, curp,                          mandoc_msg(MANDOCERR_WHILE_OUTOF,
                             curp->line, pos, NULL);                              curp->line, pos, NULL);
                 curp->loop = NULL;                  curp->loop = NULL;
         }          }
Line 431  read_whole_file(struct mparse *curp, int fd, struct bu
Line 429  read_whole_file(struct mparse *curp, int fd, struct bu
         int              gzerrnum, retval;          int              gzerrnum, retval;
   
         if (fstat(fd, &st) == -1) {          if (fstat(fd, &st) == -1) {
                 mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,                  mandoc_msg(MANDOCERR_FILE, 0, 0,
                     "fstat: %s", strerror(errno));                      "fstat: %s", strerror(errno));
                 return 0;                  return 0;
         }          }
Line 445  read_whole_file(struct mparse *curp, int fd, struct bu
Line 443  read_whole_file(struct mparse *curp, int fd, struct bu
   
         if (curp->gzip == 0 && S_ISREG(st.st_mode)) {          if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
                 if (st.st_size > 0x7fffffff) {                  if (st.st_size > 0x7fffffff) {
                         mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL);                          mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
                         return 0;                          return 0;
                 }                  }
                 *with_mmap = 1;                  *with_mmap = 1;
Line 464  read_whole_file(struct mparse *curp, int fd, struct bu
Line 462  read_whole_file(struct mparse *curp, int fd, struct bu
                  * which this function must not do.                   * which this function must not do.
                  */                   */
                 if ((fd = dup(fd)) == -1) {                  if ((fd = dup(fd)) == -1) {
                         mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,                          mandoc_msg(MANDOCERR_FILE, 0, 0,
                             "dup: %s", strerror(errno));                              "dup: %s", strerror(errno));
                         return 0;                          return 0;
                 }                  }
                 if ((gz = gzdopen(fd, "rb")) == NULL) {                  if ((gz = gzdopen(fd, "rb")) == NULL) {
                         mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,                          mandoc_msg(MANDOCERR_FILE, 0, 0,
                             "gzdopen: %s", strerror(errno));                              "gzdopen: %s", strerror(errno));
                         close(fd);                          close(fd);
                         return 0;                          return 0;
Line 490  read_whole_file(struct mparse *curp, int fd, struct bu
Line 488  read_whole_file(struct mparse *curp, int fd, struct bu
         for (;;) {          for (;;) {
                 if (off == fb->sz) {                  if (off == fb->sz) {
                         if (fb->sz == (1U << 31)) {                          if (fb->sz == (1U << 31)) {
                                 mandoc_msg(MANDOCERR_TOOLARGE, curp,                                  mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
                                     0, 0, NULL);  
                                 break;                                  break;
                         }                          }
                         resize_buf(fb, 65536);                          resize_buf(fb, 65536);
Line 507  read_whole_file(struct mparse *curp, int fd, struct bu
Line 504  read_whole_file(struct mparse *curp, int fd, struct bu
                 if (ssz == -1) {                  if (ssz == -1) {
                         if (curp->gzip)                          if (curp->gzip)
                                 (void)gzerror(gz, &gzerrnum);                                  (void)gzerror(gz, &gzerrnum);
                         mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "read: %s",                          mandoc_msg(MANDOCERR_FILE, 0, 0, "read: %s",
                             curp->gzip && gzerrnum != Z_ERRNO ?                              curp->gzip && gzerrnum != Z_ERRNO ?
                             zError(gzerrnum) : strerror(errno));                              zError(gzerrnum) : strerror(errno));
                         break;                          break;
Line 516  read_whole_file(struct mparse *curp, int fd, struct bu
Line 513  read_whole_file(struct mparse *curp, int fd, struct bu
         }          }
   
         if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK)          if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK)
                 mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "gzclose: %s",                  mandoc_msg(MANDOCERR_FILE, 0, 0, "gzclose: %s",
                     gzerrnum == Z_ERRNO ? strerror(errno) :                      gzerrnum == Z_ERRNO ? strerror(errno) :
                     zError(gzerrnum));                      zError(gzerrnum));
         if (retval == 0) {          if (retval == 0) {
Line 529  read_whole_file(struct mparse *curp, int fd, struct bu
Line 526  read_whole_file(struct mparse *curp, int fd, struct bu
 static void  static void
 mparse_end(struct mparse *curp)  mparse_end(struct mparse *curp)
 {  {
         if (curp->man->macroset == MACROSET_NONE)          if (curp->man->meta.macroset == MACROSET_NONE)
                 curp->man->macroset = MACROSET_MAN;                  curp->man->meta.macroset = MACROSET_MAN;
         if (curp->man->macroset == MACROSET_MDOC)          if (curp->man->meta.macroset == MACROSET_MDOC)
                 mdoc_endparse(curp->man);                  mdoc_endparse(curp->man);
         else          else
                 man_endparse(curp->man);                  man_endparse(curp->man);
         roff_endparse(curp->roff);          roff_endparse(curp->roff);
 }  }
   
 static void  /*
 mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)   * Read the whole file into memory and call the parsers.
    * Called recursively when an .so request is encountered.
    */
   void
   mparse_readfd(struct mparse *curp, int fd, const char *filename)
 {  {
         struct buf      *svprimary;  
         const char      *svfile;  
         size_t           offset;  
         static int       recursion_depth;          static int       recursion_depth;
   
         if (64 < recursion_depth) {          struct buf       blk;
                 mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, 0, NULL);          struct buf      *save_primary;
           const char      *save_filename;
           size_t           offset;
           int              save_filenc, save_lineno;
           int              with_mmap;
   
           if (recursion_depth > 64) {
                   mandoc_msg(MANDOCERR_ROFFLOOP, curp->line, 0, NULL);
                 return;                  return;
         }          }
           if (read_whole_file(curp, fd, &blk, &with_mmap) == 0)
                   return;
   
         /* Line number is per-file. */          /*
         svfile = mandoc_msg_getinfilename();           * Save some properties of the parent file.
         mandoc_msg_setinfilename(file);           */
         svprimary = curp->primary;  
           save_primary = curp->primary;
           save_filenc = curp->filenc;
           save_lineno = curp->line;
           save_filename = mandoc_msg_getinfilename();
   
         curp->primary = &blk;          curp->primary = &blk;
           curp->filenc = curp->options & (MPARSE_UTF8 | MPARSE_LATIN1);
         curp->line = 1;          curp->line = 1;
         recursion_depth++;          mandoc_msg_setinfilename(filename);
   
         /* Skip an UTF-8 byte order mark. */          /* Skip an UTF-8 byte order mark. */
         if (curp->filenc & MPARSE_UTF8 && blk.sz > 2 &&          if (curp->filenc & MPARSE_UTF8 && blk.sz > 2 &&
Line 569  mparse_parse_buffer(struct mparse *curp, struct buf bl
Line 582  mparse_parse_buffer(struct mparse *curp, struct buf bl
         } else          } else
                 offset = 0;                  offset = 0;
   
           recursion_depth++;
         mparse_buf_r(curp, blk, offset, 1);          mparse_buf_r(curp, blk, offset, 1);
   
         if (--recursion_depth == 0)          if (--recursion_depth == 0)
                 mparse_end(curp);                  mparse_end(curp);
   
         curp->primary = svprimary;          /*
         if (svfile != NULL)           * Clean up and restore saved parent properties.
                 mandoc_msg_setinfilename(svfile);           */
 }  
   
 enum mandoclevel          if (with_mmap)
 mparse_readmem(struct mparse *curp, void *buf, size_t len,                  munmap(blk.buf, blk.sz);
                 const char *file)          else
 {                  free(blk.buf);
         struct buf blk;  
   
         blk.buf = buf;          curp->primary = save_primary;
         blk.sz = len;          curp->filenc = save_filenc;
           curp->line = save_lineno;
         mparse_parse_buffer(curp, blk, file);          if (save_filename != NULL)
         return mandoc_msg_getrc();                  mandoc_msg_setinfilename(save_filename);
 }  }
   
 /*  
  * Read the whole file into memory and call the parsers.  
  * Called recursively when an .so request is encountered.  
  */  
 void  
 mparse_readfd(struct mparse *curp, int fd, const char *file)  
 {  
         struct buf       blk;  
         int              with_mmap;  
         int              save_filenc;  
   
         if (read_whole_file(curp, fd, &blk, &with_mmap)) {  
                 save_filenc = curp->filenc;  
                 curp->filenc = curp->options &  
                     (MPARSE_UTF8 | MPARSE_LATIN1);  
                 mparse_parse_buffer(curp, blk, file);  
                 curp->filenc = save_filenc;  
                 if (with_mmap)  
                         munmap(blk.buf, blk.sz);  
                 else  
                         free(blk.buf);  
         }  
 }  
   
 int  int
 mparse_open(struct mparse *curp, const char *file)  mparse_open(struct mparse *curp, const char *file)
 {  {
         char             *cp;          char             *cp;
         int               fd;          int               fd, save_errno;
   
         cp = strrchr(file, '.');          cp = strrchr(file, '.');
         curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz"));          curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz"));
Line 636  mparse_open(struct mparse *curp, const char *file)
Line 623  mparse_open(struct mparse *curp, const char *file)
          */           */
   
         if ( ! curp->gzip) {          if ( ! curp->gzip) {
                   save_errno = errno;
                 mandoc_asprintf(&cp, "%s.gz", file);                  mandoc_asprintf(&cp, "%s.gz", file);
                 fd = open(cp, O_RDONLY);                  fd = open(cp, O_RDONLY);
                 free(cp);                  free(cp);
                   errno = save_errno;
                 if (fd != -1) {                  if (fd != -1) {
                         curp->gzip = 1;                          curp->gzip = 1;
                         return fd;                          return fd;
Line 647  mparse_open(struct mparse *curp, const char *file)
Line 636  mparse_open(struct mparse *curp, const char *file)
   
         /* Neither worked, give up. */          /* Neither worked, give up. */
   
         mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno));  
         return -1;          return -1;
 }  }
   
Line 661  mparse_alloc(int options, enum mandoc_os os_e, const c
Line 649  mparse_alloc(int options, enum mandoc_os os_e, const c
         curp->options = options;          curp->options = options;
         curp->os_s = os_s;          curp->os_s = os_s;
   
         curp->roff = roff_alloc(curp, options);          curp->roff = roff_alloc(options);
         curp->man = roff_man_alloc(curp->roff, curp, curp->os_s,          curp->man = roff_man_alloc(curp->roff, curp->os_s,
                 curp->options & MPARSE_QUICK ? 1 : 0);                  curp->options & MPARSE_QUICK ? 1 : 0);
         if (curp->options & MPARSE_MDOC) {          if (curp->options & MPARSE_MDOC) {
                 curp->man->macroset = MACROSET_MDOC;                  curp->man->meta.macroset = MACROSET_MDOC;
                 if (curp->man->mdocmac == NULL)                  if (curp->man->mdocmac == NULL)
                         curp->man->mdocmac = roffhash_alloc(MDOC_Dd, MDOC_MAX);                          curp->man->mdocmac = roffhash_alloc(MDOC_Dd, MDOC_MAX);
         } else if (curp->options & MPARSE_MAN) {          } else if (curp->options & MPARSE_MAN) {
                 curp->man->macroset = MACROSET_MAN;                  curp->man->meta.macroset = MACROSET_MAN;
                 if (curp->man->manmac == NULL)                  if (curp->man->manmac == NULL)
                         curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX);                          curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX);
         }          }
         curp->man->first->tok = TOKEN_NONE;          curp->man->meta.first->tok = TOKEN_NONE;
         curp->man->meta.os_e = os_e;          curp->man->meta.os_e = os_e;
         return curp;          return curp;
 }  }
Line 685  mparse_reset(struct mparse *curp)
Line 673  mparse_reset(struct mparse *curp)
         roff_man_reset(curp->man);          roff_man_reset(curp->man);
         free_buf_list(curp->secondary);          free_buf_list(curp->secondary);
         curp->secondary = NULL;          curp->secondary = NULL;
         free(curp->sodest);  
         curp->sodest = NULL;  
         curp->gzip = 0;          curp->gzip = 0;
 }  }
   
Line 698  mparse_free(struct mparse *curp)
Line 684  mparse_free(struct mparse *curp)
         roff_man_free(curp->man);          roff_man_free(curp->man);
         roff_free(curp->roff);          roff_free(curp->roff);
         free_buf_list(curp->secondary);          free_buf_list(curp->secondary);
         free(curp->sodest);  
         free(curp);          free(curp);
 }  }
   
 void  struct roff_meta *
 mparse_result(struct mparse *curp, struct roff_man **man,  mparse_result(struct mparse *curp)
         char **sodest)  
 {  {
           roff_state_reset(curp->man);
         if (sodest && NULL != (*sodest = curp->sodest)) {          if (curp->options & MPARSE_VALIDATE) {
                 *man = NULL;                  if (curp->man->meta.macroset == MACROSET_MDOC)
                 return;                          mdoc_validate(curp->man);
                   else
                           man_validate(curp->man);
         }          }
         if (man)          return &curp->man->meta;
                 *man = curp->man;  
 }  }
   
 void  void

Legend:
Removed from v.1.203  
changed lines
  Added in v.1.211

CVSweb