[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.66

version 1.65, 2010/05/15 04:46:10 version 1.66, 2010/05/15 05:11:50
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 int
   read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
   {
           struct stat      st;
           char            *buf;
           size_t           sz, off;
           ssize_t          ssz;
   
           if (-1 == fstat(curp->fd, &st)) {
                   perror(curp->file);
                   with_error = 1;
                   return(0);
           }
   
           /*
            * 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 (S_ISREG(st.st_mode)) {
                   if (st.st_size >= (1U << 31)) {
                           fprintf(stderr, "%s: input too large\n",
                                           curp->file);
                           with_error = 1;
                           return(0);
                   }
                   *with_mmap = 1;
                   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);
           }
   
           /*
            * 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.
            */
   
           *with_mmap = 0;
           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 (fb->sz == 0)
                                   sz = 65536;
                           else
                                   sz = 2 * fb->sz;
                           buf = realloc(fb->buf, sz);
                           if (NULL == buf) {
                                   perror(NULL);
                                   break;
                           }
                           fb->buf = buf;
                           fb->sz = sz;
                   }
                   ssz = read(curp->fd, fb->buf + off, fb->sz - off);
                   if (ssz == 0) {
                           fb->sz = off;
                           return(1);
                   }
                   if (ssz == -1) {
                           perror(curp->file);
                           break;
                   }
                   off += ssz;
           }
   
           free(fb->buf);
           fb->buf = NULL;
           with_error = 1;
           return(0);
   }
   
   
 static void  static void
 fdesc(struct buf *blk, struct buf *ln, struct curparse *curp)  fdesc(struct curparse *curp)
 {  {
         size_t           sz;          size_t           sz;
         ssize_t          ssz;          struct buf       ln, blk;
         struct stat      st;          int              j, i, pos, lnn, comment, with_mmap;
         int              j, i, pos, lnn, comment;  
         struct man      *man;          struct man      *man;
         struct mdoc     *mdoc;          struct mdoc     *mdoc;
   
         sz = BUFSIZ;          sz = BUFSIZ;
         man = NULL;          man = NULL;
         mdoc = NULL;          mdoc = NULL;
           memset(&ln, 0, sizeof(struct buf));
   
         /*          /*
          * Two buffers: ln and buf.  buf is the input buffer optimised           * Two buffers: ln and buf.  buf is the input buffer optimised
Line 296  fdesc(struct buf *blk, struct buf *ln, struct curparse
Line 370  fdesc(struct buf *blk, struct buf *ln, struct curparse
          * growable, hence passed in by ptr-ptr.           * growable, hence passed in by ptr-ptr.
          */           */
   
         if (-1 == fstat(curp->fd, &st)) {          if (!read_whole_file(curp, &blk, &with_mmap))
                 perror(curp->file);  
                 with_error = 1;  
                 return;                  return;
         }  
         if ((size_t)st.st_blksize > sz)  
                 sz = st.st_blksize;  
   
         if (sz > blk->sz) {  
                 void *buf = realloc(blk->buf, sz);  
   
                 if (NULL == buf) {  
                         perror(NULL);  
                         with_error = 1;  
                         return;  
                 }  
                 blk->buf = buf;  
                 blk->sz = sz;  
         }  
   
         /* Fill buf with file blocksize. */          /* Fill buf with file blocksize. */
   
         for (lnn = pos = comment = 0; ; ) {          for (i = lnn = pos = comment = 0; i < (int)blk.sz; ++i) {
                 if (-1 == (ssz = read(curp->fd, blk->buf, sz))) {                          if (pos >= (int)ln.sz) {
                         perror(curp->file);                                  ln.sz += 256; /* Step-size. */
                         goto bailout;                                  ln.buf = realloc(ln.buf, ln.sz);
                 } else if (0 == ssz)                                  if (NULL == ln.buf) {
                         break;  
   
                 /* Parse the read block into partial or full lines. */  
   
                 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);                                          perror(NULL);
                                         goto bailout;                                          goto bailout;
                                 }                                  }
                         }                          }
   
                         if ('\n' != blk->buf[i]) {                          if ('\n' != blk.buf[i]) {
                                 if (comment)                                  if (comment)
                                         continue;                                          continue;
                                 ln->buf[pos++] = blk->buf[i];                                  ln.buf[pos++] = blk.buf[i];
   
                                 /* Handle in-line `\"' comments. */                                  /* Handle in-line `\"' comments. */
   
                                 if (1 == pos || '\"' != ln->buf[pos - 1])                                  if (1 == pos || '\"' != ln.buf[pos - 1])
                                         continue;                                          continue;
   
                                 for (j = pos - 2; j >= 0; j--)                                  for (j = pos - 2; j >= 0; j--)
                                         if ('\\' != ln->buf[j])                                          if ('\\' != ln.buf[j])
                                                 break;                                                  break;
   
                                 if ( ! ((pos - 2 - j) % 2))                                  if ( ! ((pos - 2 - j) % 2))
Line 357  fdesc(struct buf *blk, struct buf *ln, struct curparse
Line 405  fdesc(struct buf *blk, struct buf *ln, struct curparse
                                 comment = 1;                                  comment = 1;
                                 pos -= 2;                                  pos -= 2;
                                 for (; pos > 0; --pos) {                                  for (; pos > 0; --pos) {
                                         if (ln->buf[pos - 1] != ' ')                                          if (ln.buf[pos - 1] != ' ')
                                                 break;                                                  break;
                                         if (pos > 2 && ln->buf[pos - 2] == '\\')                                          if (pos > 2 && ln.buf[pos - 2] == '\\')
                                                 break;                                                  break;
                                 }                                  }
                                 continue;                                  continue;
Line 368  fdesc(struct buf *blk, struct buf *ln, struct curparse
Line 416  fdesc(struct buf *blk, struct buf *ln, struct curparse
                         /* Handle escaped `\\n' newlines. */                          /* Handle escaped `\\n' newlines. */
   
                         if (pos > 0 && 0 == comment &&                          if (pos > 0 && 0 == comment &&
                                         '\\' == ln->buf[pos - 1]) {                                          '\\' == ln.buf[pos - 1]) {
                                 for (j = pos - 1; j >= 0; j--)                                  for (j = pos - 1; j >= 0; j--)
                                         if ('\\' != ln->buf[j])                                          if ('\\' != ln.buf[j])
                                                 break;                                                  break;
                                 if ( ! ((pos - j) % 2)) {                                  if ( ! ((pos - j) % 2)) {
                                         pos--;                                          pos--;
Line 379  fdesc(struct buf *blk, struct buf *ln, struct curparse
Line 427  fdesc(struct buf *blk, struct buf *ln, struct curparse
                                 }                                  }
                         }                          }
   
                         ln->buf[pos] = 0;                          ln.buf[pos] = 0;
                         lnn++;                          lnn++;
   
                         /* If unset, assign parser in pset(). */                          /* If unset, assign parser in pset(). */
   
                         if ( ! (man || mdoc) && ! pset(ln->buf,                          if ( ! (man || mdoc) && ! pset(ln.buf,
                                                 pos, curp, &man, &mdoc))                                                  pos, curp, &man, &mdoc))
                                 goto bailout;                                  goto bailout;
   
Line 392  fdesc(struct buf *blk, struct buf *ln, struct curparse
Line 440  fdesc(struct buf *blk, struct buf *ln, struct curparse
   
                         /* Pass down into parsers. */                          /* Pass down into parsers. */
   
                         if (man && ! man_parseln(man, lnn, ln->buf))                          if (man && ! man_parseln(man, lnn, ln.buf))
                                 goto bailout;                                  goto bailout;
                         if (mdoc && ! mdoc_parseln(mdoc, lnn, ln->buf))                          if (mdoc && ! mdoc_parseln(mdoc, lnn, ln.buf))
                                 goto bailout;                                  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 505  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.66

CVSweb