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

Diff for /mandoc/Attic/mmain.c between version 1.3 and 1.15

version 1.3, 2009/02/23 12:45:19 version 1.15, 2009/03/19 11:49:00
Line 1 
Line 1 
         /* $Id$ */  /* $Id$ */
 /*  /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>   * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the   * purpose with or without fee is hereby granted, provided that the
Line 30 
Line 30 
   
 #include "mmain.h"  #include "mmain.h"
   
 #define MD_LINE_SZ      (256)           /* Max input line size. */  #define MD_LINE_SZ      (256)           /* Input line step-size. */
   
 struct  mmain {  struct  mmain {
         int               warn;         /* Warning flags. */          int               warn;         /* Warning flags. */
Line 41  struct mmain {
Line 41  struct mmain {
         int               dbg;          /* Debug level. */          int               dbg;          /* Debug level. */
         struct mdoc      *mdoc;         /* Active parser. */          struct mdoc      *mdoc;         /* Active parser. */
         char             *buf;          /* Input buffer. */          char             *buf;          /* Input buffer. */
         u_long            bufsz;        /* Input buffer size. */          size_t            bufsz;        /* Input buffer size. */
         char             *in;           /* Input file name. */          const char       *in;           /* Input file name. */
         int               fdin;         /* Input file desc. */          int               fdin;         /* Input file desc. */
           int               pflags;       /* Parse flags. */
 };  };
   
 extern  char             *__progname;  extern  char             *__progname;
   
 static  int               getsopts(struct mmain *, char *);  static  void              usage(const char *, const char *);
   static  int               optswarn(struct mmain *, char *);
   static  int               optsopt(struct mmain *, char *);
 static  int               parse(struct mmain *);  static  int               parse(struct mmain *);
 static  void              msg_msg(void *, int, int, const char *);  static  void              msg_msg(void *, int, int, const char *);
 static  int               msg_err(void *, int, int, const char *);  static  int               msg_err(void *, int, int, const char *);
 static  int               msg_warn(void *, int, int,  static  int               msg_warn(void *, int, int,
                                 enum mdoc_warn, const char *);                                  enum mdoc_warn, const char *);
   
 #ifdef __linux__  
 extern  int               getsubopt(char **, char *const *, char **);  
 extern  size_t            strlcpy(char *, const char *, size_t);  
 extern  size_t            strlcat(char *, const char *, size_t);  
 #endif  
   
   
 /*  /*
  * Print our and our caller's usage message.   * Print our and our caller's usage message.
  */   */
 void  void
 mmain_usage(const char *help)  usage(const char *help, const char *args)
 {  {
   
         warnx("usage: %s %s%s[-v] [-Wwarn...] [infile]", __progname,          warnx("usage: %s %s%s[-v] [-foption...] [-Wwarn...]%s%s",
                         help ? help : "", help ? " " : "");                          __progname,
                           help ? help : "", help ? " " : "",
                           args ? " " : "", args ? args : "");
 }  }
   
   
Line 85  mmain_alloc(void)
Line 83  mmain_alloc(void)
         if (NULL == (p = calloc(1, sizeof(struct mmain))))          if (NULL == (p = calloc(1, sizeof(struct mmain))))
                 err(1, "malloc");                  err(1, "malloc");
   
         p->in = "-";  
         p->fdin = STDIN_FILENO;  
   
         return(p);          return(p);
 }  }
   
Line 100  mmain_alloc(void)
Line 95  mmain_alloc(void)
  */   */
 int  int
 mmain_getopt(struct mmain *p, int argc, char *argv[],  mmain_getopt(struct mmain *p, int argc, char *argv[],
                 const char *help, const char *u, void *arg,                  const char *help, const char *args,
                 int (*getopt_cb)(void *, int, const char *))                  const char *u, void *arg,
                   int (*getopt_cb)(void *, int, char *))
 {  {
         int              c;          int              c;
         char             opts[32]; /* XXX */          char             opts[32]; /* XXX */
Line 109  mmain_getopt(struct mmain *p, int argc, char *argv[], 
Line 105  mmain_getopt(struct mmain *p, int argc, char *argv[], 
   
         extern int       optind;          extern int       optind;
   
         sz = strlcpy(opts, "vW:", 32);          sz = strlcpy(opts, "VvW:f:", 32);
         assert(sz < 32);          assert(sz < 32);
   
         if (u) {          if (u) {
Line 122  mmain_getopt(struct mmain *p, int argc, char *argv[], 
Line 118  mmain_getopt(struct mmain *p, int argc, char *argv[], 
         /* LINTED */          /* LINTED */
         while (-1 != (c = getopt(argc, argv, opts)))          while (-1 != (c = getopt(argc, argv, opts)))
                 switch (c) {                  switch (c) {
                   case ('f'):
                           if ( ! optsopt(p, optarg))
                                   mmain_exit(p, 1);
                           break;
                 case ('v'):                  case ('v'):
                         p->dbg++;                          p->dbg++;
                         break;                          break;
                   case ('V'):
                           (void)printf("%s %s\n", __progname, VERSION);
                           mmain_exit(p, 0);
                           /* NOTREACHED */
                 case ('W'):                  case ('W'):
                         if ( ! getsopts(p, optarg))                          if ( ! optswarn(p, optarg))
                                 return(0);                                  mmain_exit(p, 1);
                         break;                          break;
                 case ('?'):                  case ('?'):
                         mmain_usage(help);                          usage(help, args);
                         return(0);                          mmain_exit(p, 1);
                           /* NOTREACHED */
                 default:                  default:
                         assert(getopt_cb);                          assert(getopt_cb);
                         if ((*getopt_cb)(arg, c, optarg))                          if ((*getopt_cb)(arg, c, optarg))
                                 break;                                  break;
                         return(0);                          mmain_exit(p, 1);
                           /* NOTREACHED */
                 }                  }
   
         argv += optind;          return(optind);
         if ((argc -= optind) > 0)  }
                 p->in = *argv++;  
   
         return(1);  
   void
   mmain_reset(struct mmain *p)
   {
   
           if (p->mdoc)
                   mdoc_free(p->mdoc);
           p->mdoc = NULL;
 }  }
   
   
 __dead void  void
 mmain_exit(struct mmain *p, int code)  mmain_free(struct mmain *p)
 {  {
   
         if (p->mdoc)          if (p->mdoc)
                 mdoc_free(p->mdoc);                  mdoc_free(p->mdoc);
         free(p);          free(p);
   }
   
   
   __dead void
   mmain_exit(struct mmain *p, int code)
   {
   
           mmain_free(p);
         exit(code);          exit(code);
 }  }
   
   
 struct mdoc *  void
 mmain_mdoc(struct mmain *p)  mmain_prepare(struct mmain *p, const char *in)
 {  {
         struct stat      st;          struct stat      st;
         int              c;  
         struct mdoc_cb   cb;  
   
         cb.mdoc_err = msg_err;          if ((p->in = in)) {
         cb.mdoc_warn = msg_warn;  
         cb.mdoc_msg = msg_msg;  
   
         if (0 != strcmp(p->in, "-"))  
                 if (-1 == (p->fdin = open(p->in, O_RDONLY, 0))) {                  if (-1 == (p->fdin = open(p->in, O_RDONLY, 0))) {
                         warn("%s", p->in);                          warn("%s", p->in);
                         return(0);                          mmain_exit(p, 1);
                 }                  }
           } else {
                   p->fdin = STDIN_FILENO;
                   p->in = "-";
           }
   
         /* Allocate a buffer to be BUFSIZ/block size. */  
   
         if (-1 == fstat(p->fdin, &st)) {          if (-1 == fstat(p->fdin, &st)) {
                 warn("%s", p->in);                  warn("%s", p->in);
                 p->bufsz = BUFSIZ;                  p->bufsz = BUFSIZ;
         } else          } else
                 p->bufsz = MAX(st.st_blksize, BUFSIZ);                  p->bufsz = (unsigned)BUFSIZ > st.st_blksize ?
                           (size_t)BUFSIZ : st.st_blksize;
   
         p->buf = malloc(p->bufsz);          if (NULL == (p->buf = realloc(p->buf, p->bufsz)))
         if (NULL == p->buf)                  err(1, "realloc");
                 err(1, "malloc");  }
   
   
   struct mdoc *
   mmain_process(struct mmain *p)
   {
           int              c;
           struct mdoc_cb   cb;
   
           /* XXX - in mmain_alloc.*/
           cb.mdoc_err = msg_err;
           cb.mdoc_warn = msg_warn;
           cb.mdoc_msg = msg_msg;
   
         /* Allocate the parser. */          /* Allocate the parser. */
   
         p->mdoc = mdoc_alloc(p, &cb);          p->mdoc = mdoc_alloc(p, p->pflags, &cb);
   
         /* Parse the input file. */          /* Parse the input file. */
   
Line 204  mmain_mdoc(struct mmain *p)
Line 233  mmain_mdoc(struct mmain *p)
 }  }
   
   
   struct mdoc *
   mmain_mdoc(struct mmain *p, const char *in)
   {
   
           mmain_prepare(p, in);
           return(mmain_process(p));
   }
   
   
 static int  static int
 getsopts(struct mmain *p, char *arg)  optsopt(struct mmain *p, char *arg)
 {  {
         char            *v;          char            *v;
           char            *toks[] = { "ign-scope", "ign-escape",
                                       "ign-macro", NULL };
   
           while (*arg)
                   switch (getsubopt(&arg, toks, &v)) {
                   case (0):
                           p->pflags |= MDOC_IGN_SCOPE;
                           break;
                   case (1):
                           p->pflags |= MDOC_IGN_ESCAPE;
                           break;
                   case (2):
                           p->pflags |= MDOC_IGN_MACRO;
                           break;
                   default:
                           warnx("unknown -f argument");
                           return(0);
                   }
   
           return(1);
   }
   
   
   static int
   optswarn(struct mmain *p, char *arg)
   {
           char            *v;
         char            *toks[] = { "all", "compat",          char            *toks[] = { "all", "compat",
                                 "syntax", "error", NULL };                                  "syntax", "error", NULL };
   
Line 226  getsopts(struct mmain *p, char *arg)
Line 291  getsopts(struct mmain *p, char *arg)
                         p->warn |= MD_WARN_ERR;                          p->warn |= MD_WARN_ERR;
                         break;                          break;
                 default:                  default:
                           warnx("unknown -W argument");
                         return(0);                          return(0);
                 }                  }
   
Line 236  getsopts(struct mmain *p, char *arg)
Line 302  getsopts(struct mmain *p, char *arg)
 static int  static int
 parse(struct mmain *p)  parse(struct mmain *p)
 {  {
         ssize_t          sz, i;          ssize_t          sz;
         size_t           pos;          int              j, i, pos, len, lnn;
         char             line[MD_LINE_SZ];          char            *ln;
         int              lnn;  
   
         /*          for (ln = NULL, lnn = 1, len = pos = 0; ; ) {
          * This is a little more complicated than fgets.  TODO: have  
          * some benchmarks that show it's faster (note that I want to  
          * check many, many manuals simultaneously, so speed is  
          * important).  Fill a buffer (sized to the block size) with a  
          * single read, then parse \n-terminated lines into a line  
          * buffer, which is passed to the parser.  Hard-code the line  
          * buffer to a particular size -- a reasonable assumption.  
          */  
   
         for (lnn = 1, pos = 0; ; ) {  
                 if (-1 == (sz = read(p->fdin, p->buf, p->bufsz))) {                  if (-1 == (sz = read(p->fdin, p->buf, p->bufsz))) {
                         warn("%s", p->in);                          warn("%s", p->in);
                         return(0);                          return(0);
                 } else if (0 == sz)                  } else if (0 == sz)
                         break;                          break;
   
                 for (i = 0; i < sz; i++) {                  for (i = 0; i < (int)sz; i++) {
                           if (pos >= len) {
                                   len += MD_LINE_SZ;
                                   ln = realloc(ln, (size_t)len);
                                   if (NULL == ln)
                                           err(1, "realloc");
                           }
   
                         if ('\n' != p->buf[i]) {                          if ('\n' != p->buf[i]) {
                                 if (pos < sizeof(line)) {                                  ln[pos++] = p->buf[i];
                                         line[(int)pos++] = p->buf[(int)i];                                  continue;
                           }
   
                           /* Check for escaped newline.  */
   
                           if (pos > 0 && '\\' == ln[pos - 1]) {
                                   for (j = pos - 1; j >= 0; j--)
                                           if ('\\' != ln[j])
                                                   break;
   
                                   if ( ! ((pos - j) % 2)) {
                                           pos--;
                                           lnn++;
                                         continue;                                          continue;
                                 }                                  }
                                 warnx("%s: line %d too long", p->in, lnn);  
                                 return(0);  
                         }                          }
   
                         line[(int)pos] = 0;  
                         if ( ! mdoc_parseln(p->mdoc, lnn, line))  
                                 return(0);  
   
                           ln[pos] = 0;
                           if ( ! mdoc_parseln(p->mdoc, lnn, ln)) {
                                   free(ln);
                                   return(0);
                           }
                         lnn++;                          lnn++;
                         pos = 0;                          pos = 0;
                 }                  }
         }          }
   
           if (ln)
                   free(ln);
           if (pos > 0)
                   warnx("%s: file not eof-terminated", p->in);
         return(mdoc_endparse(p->mdoc));          return(mdoc_endparse(p->mdoc));
 }  }
   
   
 static int  
 msg_err(void *arg, int line, int col, const char *msg)  
 {  
         struct mmain     *p;  
   
         p = (struct mmain *)arg;  
   
         warnx("%s:%d: error: %s (column %d)",  
                         p->in, line, msg, col);  
         return(0);  
 }  
   
   
 static void  
 msg_msg(void *arg, int line, int col, const char *msg)  
 {  
         struct mmain     *p;  
   
         p = (struct mmain *)arg;  
   
         if (0 == p->dbg)  
                 return;  
   
         warnx("%s:%d: debug: %s (column %d)",  
                         p->in, line, msg, col);  
 }  
   
   
 static int  
 msg_warn(void *arg, int line, int col,  
                 enum mdoc_warn type, const char *msg)  
 {  
         struct mmain     *p;  
   
         p = (struct mmain *)arg;  
   
         switch (type) {  
         case (WARN_COMPAT):  
                 if (p->warn & MD_WARN_COMPAT)  
                         break;  
                 return(1);  
         case (WARN_SYNTAX):  
                 if (p->warn & MD_WARN_SYNTAX)  
                         break;  
                 return(1);  
         }  
   
         warnx("%s:%d: warning: %s (column %d)",  
                         p->in, line, msg, col);  
   
         if ( ! (p->warn & MD_WARN_ERR))  
                 return(1);  
   
         warnx("%s: considering warnings as errors", __progname);  
         return(0);  
 }  

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.15

CVSweb