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

Diff for /mandoc/read.c between version 1.80 and 1.86

version 1.80, 2014/08/10 23:54:41 version 1.86, 2014/09/07 23:25:01
Line 19 
Line 19 
 #include "config.h"  #include "config.h"
   
 #include <sys/types.h>  #include <sys/types.h>
 #ifdef HAVE_MMAP  #if HAVE_MMAP
 #include <sys/stat.h>  
 #include <sys/mman.h>  #include <sys/mman.h>
   #include <sys/stat.h>
 #endif  #endif
   #include <sys/wait.h>
   
 #include <assert.h>  #include <assert.h>
 #include <ctype.h>  #include <ctype.h>
Line 50  struct buf {
Line 51  struct buf {
 };  };
   
 struct  mparse {  struct  mparse {
         enum mandoclevel  file_status; /* status of current parse */  
         enum mandoclevel  wlevel; /* ignore messages below this */  
         int               line; /* line number in the file */  
         int               options; /* parser options */  
         struct man       *pman; /* persistent man parser */          struct man       *pman; /* persistent man parser */
         struct mdoc      *pmdoc; /* persistent mdoc parser */          struct mdoc      *pmdoc; /* persistent mdoc parser */
         struct man       *man; /* man parser */          struct man       *man; /* man parser */
         struct mdoc      *mdoc; /* mdoc parser */          struct mdoc      *mdoc; /* mdoc parser */
         struct roff      *roff; /* roff parser (!NULL) */          struct roff      *roff; /* roff parser (!NULL) */
         char             *sodest; /* filename pointed to by .so */          char             *sodest; /* filename pointed to by .so */
         int               reparse_count; /* finite interp. stack */          const char       *file; /* filename of current input file */
         mandocmsg         mmsg; /* warning/error message handler */          struct buf       *primary; /* buffer currently being parsed */
         const char       *file;          struct buf       *secondary; /* preprocessed copy of input */
         struct buf       *secondary;  
         const char       *defos; /* default operating system */          const char       *defos; /* default operating system */
           mandocmsg         mmsg; /* warning/error message handler */
           enum mandoclevel  file_status; /* status of current parse */
           enum mandoclevel  wlevel; /* ignore messages below this */
           int               options; /* parser options */
           int               reparse_count; /* finite interp. stack */
           int               line; /* line number in the file */
 };  };
   
   static  void      choose_parser(struct mparse *);
 static  void      resize_buf(struct buf *, size_t);  static  void      resize_buf(struct buf *, size_t);
 static  void      mparse_buf_r(struct mparse *, struct buf, int);  static  void      mparse_buf_r(struct mparse *, struct buf, int);
 static  void      pset(const char *, int, struct mparse *);  
 static  int       read_whole_file(struct mparse *, const char *, int,  static  int       read_whole_file(struct mparse *, const char *, int,
                                 struct buf *, int *);                                  struct buf *, int *);
 static  void      mparse_end(struct mparse *);  static  void      mparse_end(struct mparse *);
Line 115  static const char * const mandocerrs[MANDOCERR_MAX] = 
Line 117  static const char * const mandocerrs[MANDOCERR_MAX] = 
         "sections out of conventional order",          "sections out of conventional order",
         "duplicate section title",          "duplicate section title",
         "unexpected section",          "unexpected section",
           "AUTHORS section without An macro",
   
         /* related to macros and nesting */          /* related to macros and nesting */
         "obsolete macro",          "obsolete macro",
Line 213  static const char * const mandocerrs[MANDOCERR_MAX] = 
Line 216  static const char * const mandocerrs[MANDOCERR_MAX] = 
         ".so request failed",          ".so request failed",
   
         /* system errors */          /* system errors */
           "cannot dup file descriptor",
           "cannot exec",
           "gunzip failed with code",
           "cannot fork",
         NULL,          NULL,
         "cannot stat file",          "cannot open pipe",
         "cannot read file",          "cannot read file",
           "gunzip died from signal",
           "cannot stat file",
           "wait failed",
 };  };
   
 static  const char * const      mandoclevels[MANDOCLEVEL_MAX] = {  static  const char * const      mandoclevels[MANDOCLEVEL_MAX] = {
Line 238  resize_buf(struct buf *buf, size_t initial)
Line 248  resize_buf(struct buf *buf, size_t initial)
 }  }
   
 static void  static void
 pset(const char *buf, int pos, struct mparse *curp)  choose_parser(struct mparse *curp)
 {  {
         int              i;          char            *cp, *ep;
           int              format;
   
         /*          /*
          * Try to intuit which kind of manual parser should be used.  If           * If neither command line arguments -mdoc or -man select
          * passed in by command-line (-man, -mdoc), then use that           * a parser nor the roff parser found a .Dd or .TH macro
          * explicitly.  If passed as -mandoc, then try to guess from the           * yet, look ahead in the main input buffer.
          * line: either skip dot-lines, use -mdoc when finding `.Dt', or  
          * default to -man, which is more lenient.  
          *  
          * Separate out pmdoc/pman from mdoc/man: the first persists  
          * through all parsers, while the latter is used per-parse.  
          */           */
   
         if ('.' == buf[0] || '\'' == buf[0]) {          if ((format = roff_getformat(curp->roff)) == 0) {
                 for (i = 1; buf[i]; i++)                  cp = curp->primary->buf;
                         if (' ' != buf[i] && '\t' != buf[i])                  ep = cp + curp->primary->sz;
                   while (cp < ep) {
                           if (*cp == '.' || *cp == '\'') {
                                   cp++;
                                   if (cp[0] == 'D' && cp[1] == 'd') {
                                           format = MPARSE_MDOC;
                                           break;
                                   }
                                   if (cp[0] == 'T' && cp[1] == 'H') {
                                           format = MPARSE_MAN;
                                           break;
                                   }
                           }
                           cp = memchr(cp, '\n', ep - cp);
                           if (cp == NULL)
                                 break;                                  break;
                 if ('\0' == buf[i])                          cp++;
                         return;                  }
         }          }
   
         if (MPARSE_MDOC & curp->options) {          if (format == MPARSE_MDOC) {
                 curp->mdoc = curp->pmdoc;  
                 return;  
         } else if (MPARSE_MAN & curp->options) {  
                 curp->man = curp->pman;  
                 return;  
         }  
   
         if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3))  {  
                 if (NULL == curp->pmdoc)                  if (NULL == curp->pmdoc)
                         curp->pmdoc = mdoc_alloc(                          curp->pmdoc = mdoc_alloc(
                             curp->roff, curp, curp->defos,                              curp->roff, curp, curp->defos,
Line 279  pset(const char *buf, int pos, struct mparse *curp)
Line 291  pset(const char *buf, int pos, struct mparse *curp)
                 return;                  return;
         }          }
   
           /* Fall back to man(7) as a last resort. */
   
         if (NULL == curp->pman)          if (NULL == curp->pman)
                 curp->pman = man_alloc(curp->roff, curp,                  curp->pman = man_alloc(curp->roff, curp,
                     MPARSE_QUICK & curp->options ? 1 : 0);                      MPARSE_QUICK & curp->options ? 1 : 0);
Line 528  rerun:
Line 542  rerun:
                  */                   */
   
                 if ( ! (curp->man || curp->mdoc))                  if ( ! (curp->man || curp->mdoc))
                         pset(ln.buf + of, pos - of, curp);                          choose_parser(curp);
   
                 /*                  /*
                  * Lastly, push down into the parsers themselves.  One                   * Lastly, push down into the parsers themselves.
                  * of these will have already been set in the pset()  
                  * routine.  
                  * If libroff returns ROFF_TBL, then add it to the                   * If libroff returns ROFF_TBL, then add it to the
                  * currently open parse.  Since we only get here if                   * currently open parse.  Since we only get here if
                  * there does exist data (see tbl_data.c), we're                   * there does exist data (see tbl_data.c), we're
Line 590  read_whole_file(struct mparse *curp, const char *file,
Line 602  read_whole_file(struct mparse *curp, const char *file,
         size_t           off;          size_t           off;
         ssize_t          ssz;          ssize_t          ssz;
   
 #ifdef  HAVE_MMAP  #if HAVE_MMAP
         struct stat      st;          struct stat      st;
         if (-1 == fstat(fd, &st)) {          if (-1 == fstat(fd, &st)) {
                 curp->file_status = MANDOCLEVEL_SYSERR;                  curp->file_status = MANDOCLEVEL_SYSERR;
Line 701  mparse_end(struct mparse *curp)
Line 713  mparse_end(struct mparse *curp)
 static void  static void
 mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)  mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
 {  {
           struct buf      *svprimary;
         const char      *svfile;          const char      *svfile;
         static int       recursion_depth;          static int       recursion_depth;
   
Line 712  mparse_parse_buffer(struct mparse *curp, struct buf bl
Line 725  mparse_parse_buffer(struct mparse *curp, struct buf bl
         /* Line number is per-file. */          /* Line number is per-file. */
         svfile = curp->file;          svfile = curp->file;
         curp->file = file;          curp->file = file;
           svprimary = curp->primary;
           curp->primary = &blk;
         curp->line = 1;          curp->line = 1;
         recursion_depth++;          recursion_depth++;
   
Line 720  mparse_parse_buffer(struct mparse *curp, struct buf bl
Line 735  mparse_parse_buffer(struct mparse *curp, struct buf bl
         if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)          if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)
                 mparse_end(curp);                  mparse_end(curp);
   
           curp->primary = svprimary;
         curp->file = svfile;          curp->file = svfile;
 }  }
   
Line 763  mparse_readfd(struct mparse *curp, int fd, const char 
Line 779  mparse_readfd(struct mparse *curp, int fd, const char 
   
         mparse_parse_buffer(curp, blk, file);          mparse_parse_buffer(curp, blk, file);
   
 #ifdef  HAVE_MMAP  #if HAVE_MMAP
         if (with_mmap)          if (with_mmap)
                 munmap(blk.buf, blk.sz);                  munmap(blk.buf, blk.sz);
         else          else
Line 774  mparse_readfd(struct mparse *curp, int fd, const char 
Line 790  mparse_readfd(struct mparse *curp, int fd, const char 
                 perror(file);                  perror(file);
 out:  out:
         return(curp->file_status);          return(curp->file_status);
   }
   
   enum mandoclevel
   mparse_open(struct mparse *curp, int *fd, const char *file,
           pid_t *child_pid)
   {
           int               pfd[2];
           char             *cp;
           enum mandocerr    err;
   
           pfd[1] = -1;
           curp->file = file;
           if ((cp = strrchr(file, '.')) == NULL ||
               strcmp(cp + 1, "gz")) {
                   *child_pid = 0;
                   if ((*fd = open(file, O_RDONLY)) == -1) {
                           err = MANDOCERR_SYSOPEN;
                           goto out;
                   }
                   return(MANDOCLEVEL_OK);
           }
   
           if (pipe(pfd) == -1) {
                   err = MANDOCERR_SYSPIPE;
                   goto out;
           }
   
           switch (*child_pid = fork()) {
           case -1:
                   err = MANDOCERR_SYSFORK;
                   close(pfd[0]);
                   close(pfd[1]);
                   pfd[1] = -1;
                   break;
           case 0:
                   close(pfd[0]);
                   if (dup2(pfd[1], STDOUT_FILENO) == -1) {
                           err = MANDOCERR_SYSDUP;
                           break;
                   }
                   execlp("gunzip", "gunzip", "-c", file, NULL);
                   err = MANDOCERR_SYSEXEC;
                   break;
           default:
                   close(pfd[1]);
                   *fd = pfd[0];
                   return(MANDOCLEVEL_OK);
           }
   
   out:
           *fd = -1;
           *child_pid = 0;
           curp->file_status = MANDOCLEVEL_SYSERR;
           if (curp->mmsg)
                   (*curp->mmsg)(err, curp->file_status, file,
                       0, 0, strerror(errno));
           if (pfd[1] != -1)
                   exit(1);
           return(curp->file_status);
   }
   
   enum mandoclevel
   mparse_wait(struct mparse *curp, pid_t child_pid)
   {
           int       status;
   
           if (waitpid(child_pid, &status, 0) == -1) {
                   mandoc_msg(MANDOCERR_SYSWAIT, curp, 0, 0,
                       strerror(errno));
                   curp->file_status = MANDOCLEVEL_SYSERR;
                   return(curp->file_status);
           }
           if (WIFSIGNALED(status)) {
                   mandoc_vmsg(MANDOCERR_SYSSIG, curp, 0, 0,
                       "%d", WTERMSIG(status));
                   curp->file_status = MANDOCLEVEL_SYSERR;
                   return(curp->file_status);
           }
           if (WEXITSTATUS(status)) {
                   mandoc_vmsg(MANDOCERR_SYSEXIT, curp, 0, 0,
                       "%d", WEXITSTATUS(status));
                   curp->file_status = MANDOCLEVEL_SYSERR;
                   return(curp->file_status);
           }
           return(MANDOCLEVEL_OK);
 }  }
   
 struct mparse *  struct mparse *

Legend:
Removed from v.1.80  
changed lines
  Added in v.1.86

CVSweb