]> git.cameronkatri.com Git - mandoc.git/blobdiff - mmain.c
Memory-corruption fix.
[mandoc.git] / mmain.c
diff --git a/mmain.c b/mmain.c
index 5e41683a0dfbefe9388e9cc3f77f81437146fc9a..5932d0ac271672a67e11350d91ced0b16c2f1b1e 100644 (file)
--- a/mmain.c
+++ b/mmain.c
@@ -1,4 +1,4 @@
-       /* $Id: mmain.c,v 1.1 2009/02/22 22:58:39 kristaps Exp $ */
+       /* $Id: mmain.c,v 1.6 2009/03/08 11:41:22 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -42,13 +42,15 @@ struct      mmain {
        struct mdoc      *mdoc;         /* Active parser. */
        char             *buf;          /* Input buffer. */
        u_long            bufsz;        /* Input buffer size. */
-       char              in[MAXPATHLEN]; /* Input file name. */
+       char             *in;           /* Input file name. */
        int               fdin;         /* Input file desc. */
+       int               pflags;       /* Parse flags. */
 };
 
 extern char             *__progname;
 
-static int               getsopts(struct mmain *, char *);
+static int               optswarn(struct mmain *, char *);
+static int               optsopt(struct mmain *, char *);
 static int               parse(struct mmain *);
 static void              msg_msg(void *, int, int, const char *);
 static int               msg_err(void *, int, int, const char *);
@@ -57,9 +59,14 @@ static       int               msg_warn(void *, int, int,
 
 #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.
+ */
 void
 mmain_usage(const char *help)
 {
@@ -69,6 +76,9 @@ mmain_usage(const char *help)
 }
 
 
+/*
+ * Allocate the convenience library and initialise some values.
+ */ 
 struct mmain *
 mmain_alloc(void)
 {
@@ -77,67 +87,77 @@ mmain_alloc(void)
        if (NULL == (p = calloc(1, sizeof(struct mmain))))
                err(1, "malloc");
 
-       (void)strlcpy(p->in, "-", MAXPATHLEN);
+       p->in = "-";
        p->fdin = STDIN_FILENO;
 
        return(p);
 }
 
 
+/*
+ * Parse command-line options.  Accepts a small (<28 char) opstring "u"
+ * parameter (e.g. "ho:") or NULL, a corresponding "help" string (e.g.
+ * "[-h] [-o output]" or NULL, a callback function for parsed arguments
+ * and an opaque pointer argument for that function.
+ */
 int
-mmain_isopt(int c)
+mmain_getopt(struct mmain *p, int argc, char *argv[], 
+               const char *help, const char *u, void *arg,
+               int (*getopt_cb)(void *, int, const char *))
 {
-       
-       switch (c) {
-       case ('v'):
-               /* FALLTHROUGH */
-       case ('W'):
-               return(1);
-       default:
-               break;
-       }
-       return(0);
-}
+       int              c;
+       char             opts[32]; /* XXX */
+       size_t           sz;
 
+       extern int       optind;
 
-int
-mmain_getopt(struct mmain *p, int argc,
-               char *argv[], const char *help)
-{
-       int              c;
+       sz = strlcpy(opts, "VvW:f:", 32);
+       assert(sz < 32);
+
+       if (u) {
+               sz = strlcat(opts, u, 32);
+               assert(sz < 32);
+       }
+
+       optind = 1;
 
-       while (-1 != (c = getopt(argc, argv, ":vW:")))
+       /* LINTED */
+       while (-1 != (c = getopt(argc, argv, opts)))
                switch (c) {
+               case ('f'):
+                       if ( ! optsopt(p, optarg))
+                               return(-1);
+                       break;
                case ('v'):
                        p->dbg++;
                        break;
+               case ('V'):
+                       (void)printf("%s %s\n", __progname, VERSION);
+                       return(0);
                case ('W'):
-                       if ( ! getsopts(p, optarg))
-                               return(0);
+                       if ( ! optswarn(p, optarg))
+                               return(-1);
                        break;
                case ('?'):
-                       break;
-               default:
                        mmain_usage(help);
-                       return(0);
+                       return(-1);
+               default:
+                       assert(getopt_cb);
+                       if ((*getopt_cb)(arg, c, optarg))
+                               break;
+                       return(-1);
                }
 
        argv += optind;
-       argc -= optind;
-
-       if (0 == argc)
-               return(1);
+       if ((argc -= optind) > 0)
+               p->in = *argv++;
 
-       if (strlcpy(p->in, *argv++, MAXPATHLEN) < MAXPATHLEN)
-               return(1);
-
-       warnx("filename too long");
-       return(0);
+       return(1);
 }
 
 
-__dead void
-mmain_exit(struct mmain *p, int code)
+dead_pre void
+mmain_exit(struct mmain *p, int code) 
 {
 
        if (p->mdoc)
@@ -194,7 +214,26 @@ mmain_mdoc(struct mmain *p)
 
 
 static int
-getsopts(struct mmain *p, char *arg)
+optsopt(struct mmain *p, char *arg)
+{
+       char            *v;
+       char            *toks[] = { "ignore-scope", NULL };
+
+       while (*arg) 
+               switch (getsubopt(&arg, toks, &v)) {
+               case (0):
+                       p->pflags |= MDOC_IGN_SCOPE;
+                       break;
+               default:
+                       return(0);
+               }
+
+       return(1);
+}
+
+
+static int
+optswarn(struct mmain *p, char *arg)
 {
        char            *v;
        char            *toks[] = { "all", "compat",