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

Diff for /mandoc/main.c between version 1.111 and 1.112

version 1.111, 2010/12/01 15:09:01 version 1.112, 2010/12/01 16:28:23
Line 83  struct curparse {
Line 83  struct curparse {
         enum mandoclevel  wlevel;       /* Ignore messages below this. */          enum mandoclevel  wlevel;       /* Ignore messages below this. */
         int               wstop;        /* Stop after a file with a warning. */          int               wstop;        /* Stop after a file with a warning. */
         enum intt         inttype;      /* which parser to use */          enum intt         inttype;      /* which parser to use */
           struct man       *pman;         /* persistent man 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) */
Line 202  static int    pfile(const char *, struct curparse *);
Line 204  static int    pfile(const char *, struct curparse *);
 static  int               moptions(enum intt *, char *);  static  int               moptions(enum intt *, char *);
 static  int               mmsg(enum mandocerr, void *,  static  int               mmsg(enum mandocerr, void *,
                                 int, int, const char *);                                  int, int, const char *);
 static  void              pset(const char *, int, struct curparse *,  static  void              pset(const char *, int, struct curparse *);
                                 struct man **, struct mdoc **);  
 static  int               toptions(struct curparse *, char *);  static  int               toptions(struct curparse *, char *);
 static  void              usage(void) __attribute__((noreturn));  static  void              usage(void) __attribute__((noreturn));
 static  void              version(void) __attribute__((noreturn));  static  void              version(void) __attribute__((noreturn));
Line 276  main(int argc, char *argv[])
Line 277  main(int argc, char *argv[])
   
         if (curp.outfree)          if (curp.outfree)
                 (*curp.outfree)(curp.outdata);                  (*curp.outfree)(curp.outdata);
         if (curp.mdoc)          if (curp.pmdoc)
                 mdoc_free(curp.mdoc);                  mdoc_free(curp.pmdoc);
         if (curp.man)          if (curp.pman)
                 man_free(curp.man);                  man_free(curp.pman);
         if (curp.roff)          if (curp.roff)
                 roff_free(curp.roff);                  roff_free(curp.roff);
   
Line 300  static void
Line 301  static void
 usage(void)  usage(void)
 {  {
   
         (void)fprintf(stderr, "usage: %s [-V] [-foption] "          (void)fprintf(stderr, "usage: %s "
                         "[-mformat] [-Ooption] [-Toutput] "                          "[-V] "
                         "[-Werr] [file...]\n", progname);                          "[-foption] "
                           "[-mformat] "
                           "[-Ooption] "
                           "[-Toutput] "
                           "[-Werr] "
                           "[file...]\n",
                           progname);
   
         exit((int)MANDOCLEVEL_BADARG);          exit((int)MANDOCLEVEL_BADARG);
 }  }
   
   
 static void  static void
 ffile(const char *file, struct curparse *curp)  ffile(const char *file, struct curparse *curp)
 {  {
   
           /*
            * Called once per input file.  Get the file ready for reading,
            * pass it through to the parser-driver, then close it out.
            * XXX: don't do anything special as this is only called for
            * files; stdin goes directly to fdesc().
            */
   
         curp->file = file;          curp->file = file;
   
         if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {          if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
                 perror(curp->file);                  perror(curp->file);
                 exit_status = MANDOCLEVEL_SYSERR;                  exit_status = MANDOCLEVEL_SYSERR;
Line 439  read_whole_file(struct curparse *curp, struct buf *fb,
Line 454  read_whole_file(struct curparse *curp, struct buf *fb,
 static void  static void
 fdesc(struct curparse *curp)  fdesc(struct curparse *curp)
 {  {
         struct man      *man;  
         struct mdoc     *mdoc;  
         struct roff     *roff;  
   
         pdesc(curp);          /*
            * Called once per file with an opened file descriptor.  All
            * pre-file-parse operations (whether stdin or a file) should go
            * here.
            *
            * This calls down into the nested parser, which drills down and
            * fully parses a file and all its dependences (i.e., `so').  It
            * then runs the cleanup validators and pushes to output.
            */
   
         man  = curp->man;          /* Zero the parse type. */
         mdoc = curp->mdoc;  
         roff = curp->roff;  
   
           curp->mdoc = NULL;
           curp->man = NULL;
   
           /* Make sure the mandotory roff parser is initialised. */
   
           if (NULL == curp->roff) {
                   curp->roff = roff_alloc(&curp->regs, curp, mmsg);
                   assert(curp->roff);
           }
   
           /* Fully parse the file. */
   
           pdesc(curp);
   
         if (MANDOCLEVEL_FATAL <= exit_status)          if (MANDOCLEVEL_FATAL <= exit_status)
                 goto cleanup;                  goto cleanup;
   
         /* NOTE a parser may not have been assigned, yet. */          /* NOTE a parser may not have been assigned, yet. */
   
         if ( ! (man || mdoc)) {          if ( ! (curp->man || curp->mdoc)) {
                 fprintf(stderr, "%s: Not a manual\n", curp->file);                  fprintf(stderr, "%s: Not a manual\n", curp->file);
                 exit_status = MANDOCLEVEL_FATAL;                  exit_status = MANDOCLEVEL_FATAL;
                 goto cleanup;                  goto cleanup;
Line 462  fdesc(struct curparse *curp)
Line 494  fdesc(struct curparse *curp)
   
         /* Clean up the parse routine ASTs. */          /* Clean up the parse routine ASTs. */
   
         if (mdoc && ! mdoc_endparse(mdoc)) {          if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
                 assert(MANDOCLEVEL_FATAL <= exit_status);                  assert(MANDOCLEVEL_FATAL <= exit_status);
                 goto cleanup;                  goto cleanup;
         }          }
         if (man && ! man_endparse(man)) {  
           if (curp->man && ! man_endparse(curp->man)) {
                 assert(MANDOCLEVEL_FATAL <= exit_status);                  assert(MANDOCLEVEL_FATAL <= exit_status);
                 goto cleanup;                  goto cleanup;
         }          }
         if (roff && ! roff_endparse(roff)) {  
           assert(curp->roff);
           if ( ! roff_endparse(curp->roff)) {
                 assert(MANDOCLEVEL_FATAL <= exit_status);                  assert(MANDOCLEVEL_FATAL <= exit_status);
                 goto cleanup;                  goto cleanup;
         }          }
Line 536  fdesc(struct curparse *curp)
Line 571  fdesc(struct curparse *curp)
   
         /* Execute the out device, if it exists. */          /* Execute the out device, if it exists. */
   
         if (man && curp->outman)          if (curp->man && curp->outman)
                 (*curp->outman)(curp->outdata, man);                  (*curp->outman)(curp->outdata, curp->man);
         if (mdoc && curp->outmdoc)          if (curp->mdoc && curp->outmdoc)
                 (*curp->outmdoc)(curp->outdata, mdoc);                  (*curp->outmdoc)(curp->outdata, curp->mdoc);
   
  cleanup:   cleanup:
   
         memset(&curp->regs, 0, sizeof(struct regset));          memset(&curp->regs, 0, sizeof(struct regset));
         if (mdoc)  
                 mdoc_reset(mdoc);  
         if (man)  
                 man_reset(man);  
         if (roff)  
                 roff_reset(roff);  
   
           /* Reset the current-parse compilers. */
   
           if (curp->mdoc)
                   mdoc_reset(curp->mdoc);
           if (curp->man)
                   man_reset(curp->man);
   
           assert(curp->roff);
           roff_reset(curp->roff);
   
         return;          return;
 }  }
   
   
 static void  static void
 pdesc(struct curparse *curp)  pdesc(struct curparse *curp)
 {  {
         struct buf       blk;          struct buf       blk;
         int              with_mmap;          int              with_mmap;
   
           /*
            * Run for each opened file; may be called more than once for
            * each full parse sequence if the opened file is nested (i.e.,
            * from `so').  Simply sucks in the whole file and moves into
            * the parse phase for the file.
            */
   
         if ( ! read_whole_file(curp, &blk, &with_mmap)) {          if ( ! read_whole_file(curp, &blk, &with_mmap)) {
                 exit_status = MANDOCLEVEL_SYSERR;                  exit_status = MANDOCLEVEL_SYSERR;
                 return;                  return;
         }          }
   
         if (NULL == curp->roff)          /* Line number is per-file. */
                 curp->roff = roff_alloc(&curp->regs, curp, mmsg);  
         assert(curp->roff);  
   
         curp->line = 1;          curp->line = 1;
   
         parsebuf(curp, blk, 1);          parsebuf(curp, blk, 1);
   
         if (with_mmap)          if (with_mmap)
Line 582  static void
Line 627  static void
 parsebuf(struct curparse *curp, struct buf blk, int start)  parsebuf(struct curparse *curp, struct buf blk, int start)
 {  {
         struct buf       ln;          struct buf       ln;
         int              i, pos, lnn, of;          int              i, of, rc;
           int              pos; /* byte number in the ln buffer */
           int              lnn; /* line number in the real file */
         unsigned char    c;          unsigned char    c;
         struct man      *man;  
         struct mdoc     *mdoc;  
         struct roff     *roff;  
   
         man  = curp->man;          /*
         mdoc = curp->mdoc;           * Main parse routine for an opened file.  This is called for
         roff = curp->roff;           * each opened file and simply loops around the full input file,
            * possibly nesting (i.e., with `so').
            */
   
         memset(&ln, 0, sizeof(struct buf));          memset(&ln, 0, sizeof(struct buf));
   
         lnn = curp->line;  /* line number in the real file */          lnn = curp->line;
         pos = 0;  /* byte number in the ln buffer */          pos = 0;
   
         for (i = 0; i < (int)blk.sz;) {          for (i = 0; i < (int)blk.sz; ) {
                 if (0 == pos && '\0' == blk.buf[i])                  if (0 == pos && '\0' == blk.buf[i])
                         break;                          break;
   
                 if (start)                  if (start)
                         curp->line = lnn;                          curp->line = lnn;
   
Line 620  parsebuf(struct curparse *curp, struct buf blk, int st
Line 667  parsebuf(struct curparse *curp, struct buf blk, int st
                          */                           */
   
                         c = (unsigned char) blk.buf[i];                          c = (unsigned char) blk.buf[i];
                         if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) {  
                           if ( ! (isascii(c) &&
                                           (isgraph(c) || isblank(c)))) {
                                 mmsg(MANDOCERR_BADCHAR, curp,                                  mmsg(MANDOCERR_BADCHAR, curp,
                                     curp->line, pos, "ignoring byte");                                      curp->line, pos, "ignoring byte");
                                 i++;                                  i++;
                                 continue;                                  continue;
                         }                          }
   
                         /* Trailing backslash is like a plain character. */                          /* Trailing backslash = a plain char. */
   
                         if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {                          if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
                                 if (pos >= (int)ln.sz)                                  if (pos >= (int)ln.sz)
                                         resize_buf(&ln, 256);                                          resize_buf(&ln, 256);
                                 ln.buf[pos++] = blk.buf[i++];                                  ln.buf[pos++] = blk.buf[i++];
                                 continue;                                  continue;
                         }                          }
                         /* Found an escape and at least one other character. */  
                           /* Found escape & at least one other char. */
   
                         if ('\n' == blk.buf[i + 1]) {                          if ('\n' == blk.buf[i + 1]) {
                                 /* Escaped newlines are skipped over */  
                                 i += 2;                                  i += 2;
                                   /* Escaped newlines are skipped over */
                                 ++lnn;                                  ++lnn;
                                 continue;                                  continue;
                         }                          }
   
                         if ('"' == blk.buf[i + 1]) {                          if ('"' == blk.buf[i + 1]) {
                                 i += 2;                                  i += 2;
                                 /* Comment, skip to end of line */                                  /* Comment, skip to end of line */
Line 651  parsebuf(struct curparse *curp, struct buf blk, int st
Line 704  parsebuf(struct curparse *curp, struct buf blk, int st
                                                 break;                                                  break;
                                         }                                          }
                                 }                                  }
   
                                 /* Backout trailing whitespaces */                                  /* Backout trailing whitespaces */
                                 for (; pos > 0; --pos) {                                  for (; pos > 0; --pos) {
                                         if (ln.buf[pos - 1] != ' ')                                          if (ln.buf[pos - 1] != ' ')
Line 660  parsebuf(struct curparse *curp, struct buf blk, int st
Line 714  parsebuf(struct curparse *curp, struct buf blk, int st
                                 }                                  }
                                 break;                                  break;
                         }                          }
                         /* Some other escape sequence, copy and continue. */  
                           /* Some other escape sequence, copy & cont. */
   
                         if (pos + 1 >= (int)ln.sz)                          if (pos + 1 >= (int)ln.sz)
                                 resize_buf(&ln, 256);                                  resize_buf(&ln, 256);
   
Line 670  parsebuf(struct curparse *curp, struct buf blk, int st
Line 726  parsebuf(struct curparse *curp, struct buf blk, int st
   
                 if (pos >= (int)ln.sz)                  if (pos >= (int)ln.sz)
                         resize_buf(&ln, 256);                          resize_buf(&ln, 256);
   
                 ln.buf[pos] = '\0';                  ln.buf[pos] = '\0';
   
                 /*                  /*
Line 682  parsebuf(struct curparse *curp, struct buf blk, int st
Line 739  parsebuf(struct curparse *curp, struct buf blk, int st
                  */                   */
   
                 of = 0;                  of = 0;
   
 rerun:  rerun:
                 switch (roff_parseln(roff, curp->line, &ln.buf, &ln.sz,                  rc = roff_parseln
                     of, &of)) {                          (curp->roff, curp->line,
                            &ln.buf, &ln.sz, of, &of);
   
                   switch (rc) {
                 case (ROFF_REPARSE):                  case (ROFF_REPARSE):
                         parsebuf(curp, ln, 0);                          parsebuf(curp, ln, 0);
                         pos = 0;                          pos = 0;
Line 717  rerun:
Line 778  rerun:
                  * parsers with each one.                   * parsers with each one.
                  */                   */
   
                 if ( ! (man || mdoc))                  if ( ! (curp->man || curp->mdoc))
                         pset(ln.buf + of, pos - of, curp, &man, &mdoc);                          pset(ln.buf + of, pos - of, curp);
   
                 /* Lastly, push down into the parsers themselves. */                  /*
                    * Lastly, push down into the parsers themselves.  One
                    * of these will have already been set in the pset()
                    * routine.
                    */
   
                 if (man && ! man_parseln(man, curp->line, ln.buf, of)) {                  if (curp->man || curp->mdoc) {
                         assert(MANDOCLEVEL_FATAL <= exit_status);                          rc = curp->man ?
                         break;                                  man_parseln(curp->man,
                                           curp->line, ln.buf, of) :
                                   mdoc_parseln(curp->mdoc,
                                           curp->line, ln.buf, of);
   
                           if ( ! rc) {
                                   assert(MANDOCLEVEL_FATAL <= exit_status);
                                   break;
                           }
                 }                  }
                 if (mdoc && ! mdoc_parseln(mdoc, curp->line, ln.buf, of)) {  
                         assert(MANDOCLEVEL_FATAL <= exit_status);  
                         break;  
                 }  
   
                 /* Temporary buffers typically are not full. */                  /* Temporary buffers typically are not full. */
   
                 if (0 == start && '\0' == blk.buf[i])                  if (0 == start && '\0' == blk.buf[i])
                         break;                          break;
   
                 /* Start the next input line. */                  /* Start the next input line. */
   
                 pos = 0;                  pos = 0;
         }          }
   
         free(ln.buf);          free(ln.buf);
 }  }
   
   
 static void  static void
 pset(const char *buf, int pos, struct curparse *curp,  pset(const char *buf, int pos, struct curparse *curp)
                 struct man **man, struct mdoc **mdoc)  
 {  {
         int              i;          int              i;
   
Line 755  pset(const char *buf, int pos, struct curparse *curp,
Line 824  pset(const char *buf, int pos, struct curparse *curp,
          * explicitly.  If passed as -mandoc, then try to guess from the           * explicitly.  If passed as -mandoc, then try to guess from the
          * line: either skip dot-lines, use -mdoc when finding `.Dt', or           * line: either skip dot-lines, use -mdoc when finding `.Dt', or
          * default to -man, which is more lenient.           * 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 ('.' == buf[0] || '\'' == buf[0]) {
Line 767  pset(const char *buf, int pos, struct curparse *curp,
Line 839  pset(const char *buf, int pos, struct curparse *curp,
   
         switch (curp->inttype) {          switch (curp->inttype) {
         case (INTT_MDOC):          case (INTT_MDOC):
                 if (NULL == curp->mdoc)                  if (NULL == curp->pmdoc)
                         curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg);                          curp->pmdoc = mdoc_alloc
                 assert(curp->mdoc);                                  (&curp->regs, curp, mmsg);
                 *mdoc = curp->mdoc;                  assert(curp->pmdoc);
                   curp->mdoc = curp->pmdoc;
                 return;                  return;
         case (INTT_MAN):          case (INTT_MAN):
                 if (NULL == curp->man)                  if (NULL == curp->pman)
                         curp->man = man_alloc(&curp->regs, curp, mmsg);                          curp->pman = man_alloc
                 assert(curp->man);                                  (&curp->regs, curp, mmsg);
                 *man = curp->man;                  assert(curp->pman);
                   curp->man = curp->pman;
                 return;                  return;
         default:          default:
                 break;                  break;
         }          }
   
         if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3))  {          if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3))  {
                 if (NULL == curp->mdoc)                  if (NULL == curp->pmdoc)
                         curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg);                          curp->pmdoc = mdoc_alloc
                 assert(curp->mdoc);                                  (&curp->regs, curp, mmsg);
                 *mdoc = curp->mdoc;                  assert(curp->pmdoc);
                   curp->mdoc = curp->pmdoc;
                 return;                  return;
         }          }
   
         if (NULL == curp->man)          if (NULL == curp->pman)
                 curp->man = man_alloc(&curp->regs, curp, mmsg);                  curp->pman = man_alloc(&curp->regs, curp, mmsg);
         assert(curp->man);          assert(curp->pman);
         *man = curp->man;          curp->man = curp->pman;
 }  }
   
   
 static int  static int
 moptions(enum intt *tflags, char *arg)  moptions(enum intt *tflags, char *arg)
 {  {
Line 815  moptions(enum intt *tflags, char *arg)
Line 889  moptions(enum intt *tflags, char *arg)
         return(1);          return(1);
 }  }
   
   
 static int  static int
 toptions(struct curparse *curp, char *arg)  toptions(struct curparse *curp, char *arg)
 {  {
Line 844  toptions(struct curparse *curp, char *arg)
Line 917  toptions(struct curparse *curp, char *arg)
         return(1);          return(1);
 }  }
   
   
 static int  static int
 woptions(struct curparse *curp, char *arg)  woptions(struct curparse *curp, char *arg)
 {  {
Line 883  woptions(struct curparse *curp, char *arg)
Line 955  woptions(struct curparse *curp, char *arg)
   
         return(1);          return(1);
 }  }
   
   
 static int  static int
 mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)  mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)

Legend:
Removed from v.1.111  
changed lines
  Added in v.1.112

CVSweb