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

Diff for /mandoc/main.c between version 1.65 and 1.68

version 1.65, 2010/05/15 04:46:10 version 1.68, 2010/05/15 09:46:31
Line 18 
Line 18 
 #include "config.h"  #include "config.h"
 #endif  #endif
   
   #include <sys/mman.h>
 #include <sys/stat.h>  #include <sys/stat.h>
   
 #include <assert.h>  #include <assert.h>
Line 76  struct curparse {
Line 77  struct curparse {
 #define FL_NIGN_ESCAPE   (1 << 1)       /* Don't ignore bad escapes. */  #define FL_NIGN_ESCAPE   (1 << 1)       /* Don't ignore bad escapes. */
 #define FL_NIGN_MACRO    (1 << 2)       /* Don't ignore bad macros. */  #define FL_NIGN_MACRO    (1 << 2)       /* Don't ignore bad macros. */
 #define FL_IGN_ERRORS    (1 << 4)       /* Ignore failed parse. */  #define FL_IGN_ERRORS    (1 << 4)       /* Ignore failed parse. */
   #define FL_STRICT         FL_NIGN_ESCAPE | \
                             FL_NIGN_MACRO
         enum intt         inttype;      /* Input parsers... */          enum intt         inttype;      /* Input parsers... */
         struct man       *man;          struct man       *man;
         struct mdoc      *mdoc;          struct mdoc      *mdoc;
Line 87  struct curparse {
Line 90  struct curparse {
         char              outopts[BUFSIZ];          char              outopts[BUFSIZ];
 };  };
   
 #define FL_STRICT         FL_NIGN_ESCAPE | \  static  void              fdesc(struct curparse *);
                           FL_NIGN_MACRO  static  void              ffile(const char *, struct curparse *);
   
 static  int               foptions(int *, char *);  static  int               foptions(int *, char *);
 static  int               toptions(struct curparse *, char *);  static  struct man       *man_init(struct curparse *);
 static  int               moptions(enum intt *, char *);  static  struct mdoc      *mdoc_init(struct curparse *);
 static  int               woptions(int *, char *);  
 static  int               merr(void *, int, int, const char *);  static  int               merr(void *, int, int, const char *);
   static  int               moptions(enum intt *, char *);
 static  int               mwarn(void *, int, int, const char *);  static  int               mwarn(void *, int, int, const char *);
 static  void              ffile(struct buf *, struct buf *,  
                                 const char *, struct curparse *);  
 static  void              fdesc(struct buf *, struct buf *,  
                                 struct curparse *);  
 static  int               pset(const char *, int, struct curparse *,  static  int               pset(const char *, int, struct curparse *,
                                 struct man **, struct mdoc **);                                  struct man **, struct mdoc **);
 static  struct man       *man_init(struct curparse *);  static  int               toptions(struct curparse *, char *);
 static  struct mdoc      *mdoc_init(struct curparse *);  
 static  void              version(void) __attribute__((noreturn));  
 static  void              usage(void) __attribute__((noreturn));  static  void              usage(void) __attribute__((noreturn));
   static  void              version(void) __attribute__((noreturn));
   static  int               woptions(int *, char *);
   
 static  const char       *progname;  static  const char       *progname;
 static  int               with_error, with_warning;  static  int               with_error;
   static  int               with_warning;
   
 int  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
 {  {
         int              c;          int              c;
         struct buf       ln, blk;  
         struct curparse  curp;          struct curparse  curp;
   
         progname = strrchr(argv[0], '/');          progname = strrchr(argv[0], '/');
Line 162  main(int argc, char *argv[])
Line 160  main(int argc, char *argv[])
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   
         memset(&ln, 0, sizeof(struct buf));  
         memset(&blk, 0, sizeof(struct buf));  
   
         if (NULL == *argv) {          if (NULL == *argv) {
                 curp.file = "<stdin>";                  curp.file = "<stdin>";
                 curp.fd = STDIN_FILENO;                  curp.fd = STDIN_FILENO;
   
                 fdesc(&blk, &ln, &curp);                  fdesc(&curp);
         }          }
   
         while (*argv) {          while (*argv) {
                 ffile(&blk, &ln, *argv, &curp);                  ffile(*argv, &curp);
   
                 if (with_error && !(curp.fflags & FL_IGN_ERRORS))                  if (with_error && !(curp.fflags & FL_IGN_ERRORS))
                         break;                          break;
                 ++argv;                  ++argv;
         }          }
   
         if (blk.buf)  
                 free(blk.buf);  
         if (ln.buf)  
                 free(ln.buf);  
         if (curp.outfree)          if (curp.outfree)
                 (*curp.outfree)(curp.outdata);                  (*curp.outfree)(curp.outdata);
   
         return((with_warning || with_error) ? EXIT_FAILURE :  EXIT_SUCCESS );          return((with_warning || with_error) ?
                           EXIT_FAILURE :  EXIT_SUCCESS);
 }  }
   
   
Line 258  mdoc_init(struct curparse *curp)
Line 250  mdoc_init(struct curparse *curp)
   
   
 static void  static void
 ffile(struct buf *blk, struct buf *ln,  ffile(const char *file, struct curparse *curp)
                 const char *file, struct curparse *curp)  
 {  {
   
         curp->file = file;          curp->file = file;
Line 269  ffile(struct buf *blk, struct buf *ln, 
Line 260  ffile(struct buf *blk, struct buf *ln, 
                 return;                  return;
         }          }
   
         fdesc(blk, ln, curp);          fdesc(curp);
   
         if (-1 == close(curp->fd))          if (-1 == close(curp->fd))
                 perror(curp->file);                  perror(curp->file);
 }  }
   
   
 static void  static int
 fdesc(struct buf *blk, struct buf *ln, struct curparse *curp)  resize_buf(struct buf *buf, size_t initial)
 {  {
         size_t           sz;          void *tmp;
         ssize_t          ssz;          size_t sz;
         struct stat      st;  
         int              j, i, pos, lnn, comment;  
         struct man      *man;  
         struct mdoc     *mdoc;  
   
         sz = BUFSIZ;          if (buf->sz == 0)
         man = NULL;                  sz = initial;
         mdoc = NULL;          else
                   sz = 2 * buf->sz;
           tmp = realloc(buf->buf, sz);
           if (NULL == tmp) {
                   perror(NULL);
                   return(0);
           }
           buf->buf = tmp;
           buf->sz = sz;
           return(1);
   }
   
         /*  
          * Two buffers: ln and buf.  buf is the input buffer optimised  
          * here for each file's block size.  ln is a line buffer.  Both  
          * growable, hence passed in by ptr-ptr.  
          */  
   
   static int
   read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
   {
           struct stat      st;
           size_t           off;
           ssize_t          ssz;
   
         if (-1 == fstat(curp->fd, &st)) {          if (-1 == fstat(curp->fd, &st)) {
                 perror(curp->file);                  perror(curp->file);
                 with_error = 1;                  with_error = 1;
                 return;                  return(0);
         }          }
         if ((size_t)st.st_blksize > sz)  
                 sz = st.st_blksize;  
   
         if (sz > blk->sz) {          /*
                 void *buf = realloc(blk->buf, sz);           * If we're a regular file, try just reading in the whole entry
            * via mmap().  This is faster than reading it into blocks, and
            * since each file is only a few bytes to begin with, I'm not
            * concerned that this is going to tank any machines.
            */
   
                 if (NULL == buf) {          if (S_ISREG(st.st_mode)) {
                         perror(NULL);                  if (st.st_size >= (1U << 31)) {
                           fprintf(stderr, "%s: input too large\n",
                                           curp->file);
                         with_error = 1;                          with_error = 1;
                         return;                          return(0);
                 }                  }
                 blk->buf = buf;                  *with_mmap = 1;
                 blk->sz = sz;                  fb->sz = st.st_size;
                   fb->buf = mmap(NULL, fb->sz, PROT_READ,
                                   MAP_FILE, curp->fd, 0);
                   if (fb->buf != MAP_FAILED)
                           return(1);
         }          }
   
         /* Fill buf with file blocksize. */          /*
            * If this isn't a regular file (like, say, stdin), then we must
            * go the old way and just read things in bit by bit.
            */
   
         for (lnn = pos = comment = 0; ; ) {          *with_mmap = 0;
                 if (-1 == (ssz = read(curp->fd, blk->buf, sz))) {          off = 0;
           fb->sz = 0;
           fb->buf = NULL;
           for (;;) {
                   if (off == fb->sz) {
                           if (fb->sz == (1U << 31)) {
                                   fprintf(stderr, "%s: input too large\n",
                                                   curp->file);
                                   break;
                           }
                           if (! resize_buf(fb, 65536))
                                   break;
                   }
                   ssz = read(curp->fd, fb->buf + off, fb->sz - off);
                   if (ssz == 0) {
                           fb->sz = off;
                           return(1);
                   }
                   if (ssz == -1) {
                         perror(curp->file);                          perror(curp->file);
                         goto bailout;  
                 } else if (0 == ssz)  
                         break;                          break;
                   }
                   off += ssz;
           }
   
                 /* Parse the read block into partial or full lines. */          free(fb->buf);
           fb->buf = NULL;
           with_error = 1;
           return(0);
   }
   
                 for (i = 0; i < (int)ssz; i++) {  
                         if (pos >= (int)ln->sz) {  
                                 ln->sz += 256; /* Step-size. */  
                                 ln->buf = realloc(ln->buf, ln->sz);  
                                 if (NULL == ln->buf) {  
                                         perror(NULL);  
                                         goto bailout;  
                                 }  
                         }  
   
                         if ('\n' != blk->buf[i]) {  static void
                                 if (comment)  fdesc(struct curparse *curp)
                                         continue;  {
                                 ln->buf[pos++] = blk->buf[i];          struct buf       ln, blk;
           int              j, i, pos, lnn, comment, with_mmap;
           struct man      *man;
           struct mdoc     *mdoc;
   
                                 /* Handle in-line `\"' comments. */          man = NULL;
           mdoc = NULL;
           memset(&ln, 0, sizeof(struct buf));
   
                                 if (1 == pos || '\"' != ln->buf[pos - 1])          /*
                                         continue;           * Two buffers: ln and buf.  buf is the input buffer optimised
            * here for each file's block size.  ln is a line buffer.  Both
            * growable, hence passed in by ptr-ptr.
            */
   
                                 for (j = pos - 2; j >= 0; j--)          if (!read_whole_file(curp, &blk, &with_mmap))
                                         if ('\\' != ln->buf[j])                  return;
                                                 break;  
   
                                 if ( ! ((pos - 2 - j) % 2))          /* Fill buf with file blocksize. */
                                         continue;  
   
                                 comment = 1;          for (i = lnn = pos = comment = 0; i < (int)blk.sz; ++i) {
                                 pos -= 2;                  if (pos >= (int)ln.sz) {
                                 for (; pos > 0; --pos) {                          if (! resize_buf(&ln, 256))
                                         if (ln->buf[pos - 1] != ' ')                                  goto bailout;
                                                 break;                  }
                                         if (pos > 2 && ln->buf[pos - 2] == '\\')  
                                                 break;                  if ('\n' != blk.buf[i]) {
                                 }                          if (comment)
                                 continue;                                  continue;
                         }                          ln.buf[pos++] = blk.buf[i];
   
                         /* Handle escaped `\\n' newlines. */                          /* Handle in-line `\"' comments. */
   
                         if (pos > 0 && 0 == comment &&                          if (1 == pos || '\"' != ln.buf[pos - 1])
                                         '\\' == ln->buf[pos - 1]) {                                  continue;
                                 for (j = pos - 1; j >= 0; j--)  
                                         if ('\\' != ln->buf[j])                          for (j = pos - 2; j >= 0; j--)
                                                 break;                                  if ('\\' != ln.buf[j])
                                 if ( ! ((pos - j) % 2)) {                                          break;
                                         pos--;  
                                         lnn++;                          if ( ! ((pos - 2 - j) % 2))
                                         continue;                                  continue;
                                 }  
                           comment = 1;
                           pos -= 2;
                           for (; pos > 0; --pos) {
                                   if (ln.buf[pos - 1] != ' ')
                                           break;
                                   if (pos > 2 && ln.buf[pos - 2] == '\\')
                                           break;
                         }                          }
                           continue;
                   }
   
                         ln->buf[pos] = 0;                  /* Handle escaped `\\n' newlines. */
                         lnn++;  
   
                         /* If unset, assign parser in pset(). */                  if (pos > 0 && 0 == comment && '\\' == ln.buf[pos - 1]) {
                           for (j = pos - 1; j >= 0; j--)
                                   if ('\\' != ln.buf[j])
                                           break;
                           if ( ! ((pos - j) % 2)) {
                                   pos--;
                                   lnn++;
                                   continue;
                           }
                   }
   
                         if ( ! (man || mdoc) && ! pset(ln->buf,                  ln.buf[pos] = 0;
                                                 pos, curp, &man, &mdoc))                  lnn++;
                                 goto bailout;  
   
                         pos = comment = 0;                  /* If unset, assign parser in pset(). */
   
                         /* Pass down into parsers. */                  if ( ! (man || mdoc) && ! pset(ln.buf, pos, curp, &man, &mdoc))
                           goto bailout;
   
                         if (man && ! man_parseln(man, lnn, ln->buf))                  pos = comment = 0;
                                 goto bailout;  
                         if (mdoc && ! mdoc_parseln(mdoc, lnn, ln->buf))                  /* Pass down into parsers. */
                                 goto bailout;  
                 }                  if (man && ! man_parseln(man, lnn, ln.buf))
                           goto bailout;
                   if (mdoc && ! mdoc_parseln(mdoc, lnn, ln.buf))
                           goto bailout;
         }          }
   
         /* NOTE a parser may not have been assigned, yet. */          /* NOTE a parser may not have been assigned, yet. */
Line 458  fdesc(struct buf *blk, struct buf *ln, struct curparse
Line 508  fdesc(struct buf *blk, struct buf *ln, struct curparse
                 man_free(curp->man);                  man_free(curp->man);
                 curp->man = NULL;                  curp->man = NULL;
         }          }
           if (ln.buf)
                   free(ln.buf);
           if (with_mmap)
                   munmap(blk.buf, blk.sz);
           else
                   free(blk.buf);
         return;          return;
   
  bailout:   bailout:

Legend:
Removed from v.1.65  
changed lines
  Added in v.1.68

CVSweb