]> granicus.if.org Git - yasm/commitdiff
Added command line parsing
authorStanislav Karchebny <madfire@users.sourceforge.net>
Fri, 28 Sep 2001 05:11:00 +0000 (05:11 -0000)
committerStanislav Karchebny <madfire@users.sourceforge.net>
Fri, 28 Sep 2001 05:11:00 +0000 (05:11 -0000)
svn path=/trunk/yasm/; revision=249

13 files changed:
frontends/yasm/yasm-options.c [new file with mode: 0644]
frontends/yasm/yasm-options.h [new file with mode: 0644]
frontends/yasm/yasm.c
libyasm/linemgr.c
libyasm/linemgr.h
src/Makefile.am
src/globals.c
src/globals.h
src/linemgr.c
src/linemgr.h
src/main.c
src/options.c [new file with mode: 0644]
src/options.h [new file with mode: 0644]

diff --git a/frontends/yasm/yasm-options.c b/frontends/yasm/yasm-options.c
new file mode 100644 (file)
index 0000000..efe7882
--- /dev/null
@@ -0,0 +1,193 @@
+/* $IdPath$
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001  Stanislav Karchebny <berk@madfire.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of other contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "util.h"
+
+#include <stdio.h>
+
+#ifdef STDC_HEADERS
+# include <string.h>
+#endif
+
+#include <libintl.h>
+#define _(String)       gettext(String)
+#ifdef gettext_noop
+#define N_(String)      gettext_noop(String)
+#else
+#define N_(String)      (String)
+#endif
+
+#include "options.h"
+#include "errwarn.h"
+
+
+#ifdef __DEBUG__
+#define DEBUG(x) fprintf ## x ;
+#else
+#define DEBUG(x)
+#endif
+
+
+/* Options Parser */
+int
+parse_cmdline(int argc, char **argv, opt_option *options, int nopts)
+{
+    int errors = 0;
+    int i;
+    int got_it;
+
+    DEBUG((stderr, "parse_cmdline: entered\n"));
+
+  fail:
+    while (--argc) {
+       argv++;
+
+       if (argv[0][0] == '-') {        /* opt */
+           got_it = 0;
+           if (argv[0][1] == '-') {    /* lopt */
+               for (i = 0; i < nopts; i++) {
+                   if (options[i].lopt &&
+                       strncmp(&argv[0][2], options[i].lopt,
+                               strlen(options[i].lopt)) == 0) {
+                       char *param;
+
+                       if (options[i].takes_param) {
+                           param = strchr(&argv[0][2], '=');
+                           if (!param) {
+                               ErrorNow(_
+                                        ("option '--%s' needs an argument!"),
+                                        options[i].lopt);
+                               errors++;
+                               goto fail;
+                           } else {
+                               *param = '\0';
+                               param++;
+                           }
+                       } else
+                           param = NULL;
+
+                       if (!options[i].
+                           handler(&argv[0][2], param, options[i].extra))
+                           got_it = 1;
+                       break;
+                   }
+               }
+               if (!got_it) {
+                   ErrorNow(_("unrecognized option '%s'"), argv[0]);
+                   errors++;
+               }
+           } else {            /* sopt */
+
+               for (i = 0; i < nopts; i++) {
+                   if (argv[0][1] == options[i].sopt) {
+                       char *cmd = &argv[0][1];
+                       char *param;
+
+                       if (options[i].takes_param) {
+                           param = argv[1];
+                           if (*param == '-' || param == NULL) {
+                               ErrorNow(_("option '-%c' needs an argument!"),
+                                        options[i].sopt);
+                               errors++;
+                               goto fail;
+                           } else {
+                               argc--;
+                               argv++;
+                           }
+                       } else
+                           param = NULL;
+
+                       if (!options[i].handler(cmd, param, options[i].extra))
+                           got_it = 1;
+                       break;
+                   }
+               }
+               if (!got_it) {
+                   ErrorNow(_("unrecognized option '%s'"), argv[0]);
+                   errors++;
+               }
+           }
+       } else {    /* not an option, then it should be a file or something */
+
+           if (not_an_option_handler(argv[0]))
+               errors++;
+       }
+    }
+
+    DEBUG((stderr, "parse_cmdline: finished\n"));
+    return errors;
+}
+
+void
+help_msg(char *msg, char *tail, opt_option *options, int nopts)
+{
+    char optbuf[100], optopt[100];
+    int i;
+
+    fprintf(stdout, msg);
+
+    for (i = 0; i < nopts; i++) {
+       optbuf[0] = 0;
+       optopt[0] = 0;
+
+       if (options[i].takes_param) {
+           if (options[i].sopt) {
+               sprintf(optbuf, "-%c <%s>", options[i].sopt,
+                       options[i].param_desc ? options[i].
+                       param_desc : "param");
+           }
+           if (options[i].sopt && options[i].lopt)
+               strcat(optbuf, ", ");
+           if (options[i].lopt) {
+               sprintf(optopt, "--%s <%s>", options[i].lopt,
+                       options[i].param_desc ? options[i].
+                       param_desc : "param");
+               strcat(optbuf, optopt);
+           }
+       } else {
+           if (options[i].sopt) {
+               sprintf(optbuf, "-%c", options[i].sopt);
+           }
+           if (options[i].sopt && options[i].lopt)
+               strcat(optbuf, ", ");
+           if (options[i].lopt) {
+               sprintf(optopt, "--%s", options[i].lopt);
+               strcat(optbuf, optopt);
+           }
+       }
+
+       fprintf(stdout, "    %-24s  %s\n", optbuf, options[i].description);
+    }
+
+    fprintf(stdout, tail);
+}
diff --git a/frontends/yasm/yasm-options.h b/frontends/yasm/yasm-options.h
new file mode 100644 (file)
index 0000000..121f9e6
--- /dev/null
@@ -0,0 +1,63 @@
+/* $IdPath$
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001  Stanislav Karchebny <berk@madfire.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of other contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef YASM_OPTIONS_H
+#define YASM_OPTIONS_H
+
+/* an option structure
+ * operate on either -sopt, --lopt, -sopt <val> or --lopt=<val>
+ */
+typedef struct opt_option_s
+{
+    char sopt;         /* short option letter if present, 0 otherwise */
+    char *lopt;                /* long option name if present, NULL otherwise */
+    int takes_param;   /* !=0 if option requires parameter, 0 if not */
+    int (*handler) (char *cmd, char *param, int extra);
+    int extra;         /* extra value for handler */
+    char *description; /* description to use in help_msg() */
+    char *param_desc;  /* optional description for the param taken */
+                       /*  (short - will be printed after option sopt/lopt) */
+} opt_option;
+
+/* handle everything that is not an option */
+int not_an_option_handler(char *param);
+
+/* parse command line calling handlers when appropriate
+ * argc, argv - pass directly from main(argc,argv)
+ * options - array of options
+ * nopts - options count
+ */
+int parse_cmdline(int argc, char **argv, opt_option *options, int nopts);
+
+/* display help message msg followed by list of options in options and followed
+ * by tail
+ */
+void help_msg(char *msg, char *tail, opt_option *options, int nopts);
+
+#endif
index 1e869dff26c7a818a663458728658bd64fe5e8e3..435ec46bb7d57b5c839cf976537b91281f6655d7 100644 (file)
@@ -43,6 +43,7 @@
 #include "bitvect.h"
 
 #include "globals.h"
+#include "options.h"
 #include "errwarn.h"
 
 #include "bytecode.h"
 
 RCSID("$IdPath$");
 
+#ifndef countof
+#define countof(x,y)   (sizeof(x)/sizeof(y))
+#endif
+
+static int files_open = 0;
+static FILE *in;
+
+/* Forward declarations: cmd line parser handlers */
+int not_an_option_handler(char *param);
+int opt_option_handler(char *cmd, char *param, int extra);
+int opt_format_handler(char *cmd, char *param, int extra);
+/* Fake handlers: remove them */
+int boo_boo_handler(char *cmd, char *param, int extra);
+int b_handler(char *cmd, char *param, int extra);
+
+/* values for asm_options */
+#define OPT_SHOW_HELP 0x01
+
+/* command line options */
+opt_option options[] =
+{
+    { 'h', "help",    0, opt_option_handler, OPT_SHOW_HELP, "show help text" },
+    { 'f', "oformat", 1, opt_format_handler, 0, "select output format", "<format>" },
+    /* Fake handlers: remove them */
+    { 'b', NULL,      0, b_handler, 0, "says boom!" },
+    {  0,  "boo-boo", 0, boo_boo_handler, 0, "says boo-boo!" },
+};
+
+/* help messages */
+char help_head[] = "yasm version 0.1 compiled " __DATE__ "\n"
+                  "copyright (c) 2001 Peter Johnson and Yasm developers\n"
+                  "mailto: asm-devel@bilogic.org\n"
+                  "\n"
+                  "usage: yasm [options|files]+\n"
+                  "where options are:\n";
+char help_tail[] = "\n"
+                  "   files are asm sources to be assembled\n"
+                  "\n"
+                  "sample invocation:\n"
+                  "   yasm -b --boo-boo -f elf -o test.o impl.asm\n"
+                  "\n";
+
+/* main function */
 int
 main(int argc, char *argv[])
 {
-    FILE *in;
+    if (parse_cmdline(argc, argv, options, countof(options, opt_option)))
+       return EXIT_FAILURE;
+
+    if (asm_options & OPT_SHOW_HELP) {
+       help_msg(help_head, help_tail, options, countof(options, opt_option));
+       return EXIT_FAILURE;
+    }
 
     /* Initialize BitVector (needed for floating point). */
     if (BitVector_Boot() != ErrCode_Ok) {
-       fprintf(stderr, _("Could not initialize BitVector"));
+       ErrorNow(_("Could not initialize BitVector"));
        return EXIT_FAILURE;
     }
 
-    if (argc == 2) {
-       in = fopen(argv[1], "rt");
-       if (!in) {
-           fprintf(stderr, "could not open file `%s'\n", argv[1]);
-           return EXIT_FAILURE;
-       }
-       filename = strdup(argv[1]);
-    } else {
+    /* if no files were specified, fallback to reading stdin */
+    if (!files_open)
+    {
        in = stdin;
        filename = strdup("<STDIN>");
     }
@@ -88,3 +133,55 @@ main(int argc, char *argv[])
        free(filename);
     return EXIT_SUCCESS;
 }
+
+/*
+ *  Command line options handlers
+ */
+int
+not_an_option_handler(char *param)
+{
+    if (files_open > 0) {
+       WarningNow("can open only one input file, only latest file will be processed");
+       free(filename);
+       fclose(in);
+    }
+
+    in = fopen(param, "rt");
+    if (!in) {
+       ErrorNow(_("could not open file `%s'"), param);
+       return 1;
+    }
+    filename = strdup(param);
+
+    files_open++;
+    return 0;
+}
+
+int
+opt_option_handler(char *cmd, char *param, int extra)
+{
+    asm_options |= extra;
+    return 0;
+}
+
+int
+opt_format_handler(char *cmd, char *param, int extra)
+{
+    printf("selected format: %s\n", param);
+    return 0;
+}
+
+/* Fake handlers: remove them */
+int
+boo_boo_handler(char *cmd, char *param, int extra)
+{
+    printf("boo-boo!\n");
+    return 0;
+}
+
+int
+b_handler(char *cmd, char *param, int extra)
+{
+    fprintf(stdout, "boom!\n");
+    return 0;
+}
index b86c1c11633a1ac0361686b6368005f193e8851d..92aa3e8905758131b9994455ebaec11eb6d05926 100644 (file)
@@ -32,3 +32,4 @@ RCSID("$IdPath$");
 char *filename = (char *)NULL;
 unsigned int line_number = 1;
 unsigned char mode_bits = 0;
+unsigned int asm_options = 0;
index 1d6716e02e2fd152cd2b110005c0bdc76e4af2ee..4cae3b833e2ff89f4f8a9d3a77096e129629d645 100644 (file)
@@ -25,5 +25,6 @@
 extern char *filename;
 extern unsigned int line_number;
 extern unsigned char mode_bits;
+extern unsigned int asm_options;
 
 #endif
index e4779e402af7f016ca2e1e2ae734db66f9edbaed..ac07f6918c2b16214ef66ed0e509df69bda45cfc 100644 (file)
@@ -35,6 +35,8 @@ libyasm_a_SOURCES = \
        section.c               \
        section.h               \
        objfmt.h                \
+       options.h               \
+       options.c               \
        preproc.h               \
        parser.c                \
        parser.h                \
index b86c1c11633a1ac0361686b6368005f193e8851d..92aa3e8905758131b9994455ebaec11eb6d05926 100644 (file)
@@ -32,3 +32,4 @@ RCSID("$IdPath$");
 char *filename = (char *)NULL;
 unsigned int line_number = 1;
 unsigned char mode_bits = 0;
+unsigned int asm_options = 0;
index 1d6716e02e2fd152cd2b110005c0bdc76e4af2ee..4cae3b833e2ff89f4f8a9d3a77096e129629d645 100644 (file)
@@ -25,5 +25,6 @@
 extern char *filename;
 extern unsigned int line_number;
 extern unsigned char mode_bits;
+extern unsigned int asm_options;
 
 #endif
index b86c1c11633a1ac0361686b6368005f193e8851d..92aa3e8905758131b9994455ebaec11eb6d05926 100644 (file)
@@ -32,3 +32,4 @@ RCSID("$IdPath$");
 char *filename = (char *)NULL;
 unsigned int line_number = 1;
 unsigned char mode_bits = 0;
+unsigned int asm_options = 0;
index 1d6716e02e2fd152cd2b110005c0bdc76e4af2ee..4cae3b833e2ff89f4f8a9d3a77096e129629d645 100644 (file)
@@ -25,5 +25,6 @@
 extern char *filename;
 extern unsigned int line_number;
 extern unsigned char mode_bits;
+extern unsigned int asm_options;
 
 #endif
index 1e869dff26c7a818a663458728658bd64fe5e8e3..435ec46bb7d57b5c839cf976537b91281f6655d7 100644 (file)
@@ -43,6 +43,7 @@
 #include "bitvect.h"
 
 #include "globals.h"
+#include "options.h"
 #include "errwarn.h"
 
 #include "bytecode.h"
 
 RCSID("$IdPath$");
 
+#ifndef countof
+#define countof(x,y)   (sizeof(x)/sizeof(y))
+#endif
+
+static int files_open = 0;
+static FILE *in;
+
+/* Forward declarations: cmd line parser handlers */
+int not_an_option_handler(char *param);
+int opt_option_handler(char *cmd, char *param, int extra);
+int opt_format_handler(char *cmd, char *param, int extra);
+/* Fake handlers: remove them */
+int boo_boo_handler(char *cmd, char *param, int extra);
+int b_handler(char *cmd, char *param, int extra);
+
+/* values for asm_options */
+#define OPT_SHOW_HELP 0x01
+
+/* command line options */
+opt_option options[] =
+{
+    { 'h', "help",    0, opt_option_handler, OPT_SHOW_HELP, "show help text" },
+    { 'f', "oformat", 1, opt_format_handler, 0, "select output format", "<format>" },
+    /* Fake handlers: remove them */
+    { 'b', NULL,      0, b_handler, 0, "says boom!" },
+    {  0,  "boo-boo", 0, boo_boo_handler, 0, "says boo-boo!" },
+};
+
+/* help messages */
+char help_head[] = "yasm version 0.1 compiled " __DATE__ "\n"
+                  "copyright (c) 2001 Peter Johnson and Yasm developers\n"
+                  "mailto: asm-devel@bilogic.org\n"
+                  "\n"
+                  "usage: yasm [options|files]+\n"
+                  "where options are:\n";
+char help_tail[] = "\n"
+                  "   files are asm sources to be assembled\n"
+                  "\n"
+                  "sample invocation:\n"
+                  "   yasm -b --boo-boo -f elf -o test.o impl.asm\n"
+                  "\n";
+
+/* main function */
 int
 main(int argc, char *argv[])
 {
-    FILE *in;
+    if (parse_cmdline(argc, argv, options, countof(options, opt_option)))
+       return EXIT_FAILURE;
+
+    if (asm_options & OPT_SHOW_HELP) {
+       help_msg(help_head, help_tail, options, countof(options, opt_option));
+       return EXIT_FAILURE;
+    }
 
     /* Initialize BitVector (needed for floating point). */
     if (BitVector_Boot() != ErrCode_Ok) {
-       fprintf(stderr, _("Could not initialize BitVector"));
+       ErrorNow(_("Could not initialize BitVector"));
        return EXIT_FAILURE;
     }
 
-    if (argc == 2) {
-       in = fopen(argv[1], "rt");
-       if (!in) {
-           fprintf(stderr, "could not open file `%s'\n", argv[1]);
-           return EXIT_FAILURE;
-       }
-       filename = strdup(argv[1]);
-    } else {
+    /* if no files were specified, fallback to reading stdin */
+    if (!files_open)
+    {
        in = stdin;
        filename = strdup("<STDIN>");
     }
@@ -88,3 +133,55 @@ main(int argc, char *argv[])
        free(filename);
     return EXIT_SUCCESS;
 }
+
+/*
+ *  Command line options handlers
+ */
+int
+not_an_option_handler(char *param)
+{
+    if (files_open > 0) {
+       WarningNow("can open only one input file, only latest file will be processed");
+       free(filename);
+       fclose(in);
+    }
+
+    in = fopen(param, "rt");
+    if (!in) {
+       ErrorNow(_("could not open file `%s'"), param);
+       return 1;
+    }
+    filename = strdup(param);
+
+    files_open++;
+    return 0;
+}
+
+int
+opt_option_handler(char *cmd, char *param, int extra)
+{
+    asm_options |= extra;
+    return 0;
+}
+
+int
+opt_format_handler(char *cmd, char *param, int extra)
+{
+    printf("selected format: %s\n", param);
+    return 0;
+}
+
+/* Fake handlers: remove them */
+int
+boo_boo_handler(char *cmd, char *param, int extra)
+{
+    printf("boo-boo!\n");
+    return 0;
+}
+
+int
+b_handler(char *cmd, char *param, int extra)
+{
+    fprintf(stdout, "boom!\n");
+    return 0;
+}
diff --git a/src/options.c b/src/options.c
new file mode 100644 (file)
index 0000000..efe7882
--- /dev/null
@@ -0,0 +1,193 @@
+/* $IdPath$
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001  Stanislav Karchebny <berk@madfire.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of other contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "util.h"
+
+#include <stdio.h>
+
+#ifdef STDC_HEADERS
+# include <string.h>
+#endif
+
+#include <libintl.h>
+#define _(String)       gettext(String)
+#ifdef gettext_noop
+#define N_(String)      gettext_noop(String)
+#else
+#define N_(String)      (String)
+#endif
+
+#include "options.h"
+#include "errwarn.h"
+
+
+#ifdef __DEBUG__
+#define DEBUG(x) fprintf ## x ;
+#else
+#define DEBUG(x)
+#endif
+
+
+/* Options Parser */
+int
+parse_cmdline(int argc, char **argv, opt_option *options, int nopts)
+{
+    int errors = 0;
+    int i;
+    int got_it;
+
+    DEBUG((stderr, "parse_cmdline: entered\n"));
+
+  fail:
+    while (--argc) {
+       argv++;
+
+       if (argv[0][0] == '-') {        /* opt */
+           got_it = 0;
+           if (argv[0][1] == '-') {    /* lopt */
+               for (i = 0; i < nopts; i++) {
+                   if (options[i].lopt &&
+                       strncmp(&argv[0][2], options[i].lopt,
+                               strlen(options[i].lopt)) == 0) {
+                       char *param;
+
+                       if (options[i].takes_param) {
+                           param = strchr(&argv[0][2], '=');
+                           if (!param) {
+                               ErrorNow(_
+                                        ("option '--%s' needs an argument!"),
+                                        options[i].lopt);
+                               errors++;
+                               goto fail;
+                           } else {
+                               *param = '\0';
+                               param++;
+                           }
+                       } else
+                           param = NULL;
+
+                       if (!options[i].
+                           handler(&argv[0][2], param, options[i].extra))
+                           got_it = 1;
+                       break;
+                   }
+               }
+               if (!got_it) {
+                   ErrorNow(_("unrecognized option '%s'"), argv[0]);
+                   errors++;
+               }
+           } else {            /* sopt */
+
+               for (i = 0; i < nopts; i++) {
+                   if (argv[0][1] == options[i].sopt) {
+                       char *cmd = &argv[0][1];
+                       char *param;
+
+                       if (options[i].takes_param) {
+                           param = argv[1];
+                           if (*param == '-' || param == NULL) {
+                               ErrorNow(_("option '-%c' needs an argument!"),
+                                        options[i].sopt);
+                               errors++;
+                               goto fail;
+                           } else {
+                               argc--;
+                               argv++;
+                           }
+                       } else
+                           param = NULL;
+
+                       if (!options[i].handler(cmd, param, options[i].extra))
+                           got_it = 1;
+                       break;
+                   }
+               }
+               if (!got_it) {
+                   ErrorNow(_("unrecognized option '%s'"), argv[0]);
+                   errors++;
+               }
+           }
+       } else {    /* not an option, then it should be a file or something */
+
+           if (not_an_option_handler(argv[0]))
+               errors++;
+       }
+    }
+
+    DEBUG((stderr, "parse_cmdline: finished\n"));
+    return errors;
+}
+
+void
+help_msg(char *msg, char *tail, opt_option *options, int nopts)
+{
+    char optbuf[100], optopt[100];
+    int i;
+
+    fprintf(stdout, msg);
+
+    for (i = 0; i < nopts; i++) {
+       optbuf[0] = 0;
+       optopt[0] = 0;
+
+       if (options[i].takes_param) {
+           if (options[i].sopt) {
+               sprintf(optbuf, "-%c <%s>", options[i].sopt,
+                       options[i].param_desc ? options[i].
+                       param_desc : "param");
+           }
+           if (options[i].sopt && options[i].lopt)
+               strcat(optbuf, ", ");
+           if (options[i].lopt) {
+               sprintf(optopt, "--%s <%s>", options[i].lopt,
+                       options[i].param_desc ? options[i].
+                       param_desc : "param");
+               strcat(optbuf, optopt);
+           }
+       } else {
+           if (options[i].sopt) {
+               sprintf(optbuf, "-%c", options[i].sopt);
+           }
+           if (options[i].sopt && options[i].lopt)
+               strcat(optbuf, ", ");
+           if (options[i].lopt) {
+               sprintf(optopt, "--%s", options[i].lopt);
+               strcat(optbuf, optopt);
+           }
+       }
+
+       fprintf(stdout, "    %-24s  %s\n", optbuf, options[i].description);
+    }
+
+    fprintf(stdout, tail);
+}
diff --git a/src/options.h b/src/options.h
new file mode 100644 (file)
index 0000000..121f9e6
--- /dev/null
@@ -0,0 +1,63 @@
+/* $IdPath$
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001  Stanislav Karchebny <berk@madfire.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of other contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef YASM_OPTIONS_H
+#define YASM_OPTIONS_H
+
+/* an option structure
+ * operate on either -sopt, --lopt, -sopt <val> or --lopt=<val>
+ */
+typedef struct opt_option_s
+{
+    char sopt;         /* short option letter if present, 0 otherwise */
+    char *lopt;                /* long option name if present, NULL otherwise */
+    int takes_param;   /* !=0 if option requires parameter, 0 if not */
+    int (*handler) (char *cmd, char *param, int extra);
+    int extra;         /* extra value for handler */
+    char *description; /* description to use in help_msg() */
+    char *param_desc;  /* optional description for the param taken */
+                       /*  (short - will be printed after option sopt/lopt) */
+} opt_option;
+
+/* handle everything that is not an option */
+int not_an_option_handler(char *param);
+
+/* parse command line calling handlers when appropriate
+ * argc, argv - pass directly from main(argc,argv)
+ * options - array of options
+ * nopts - options count
+ */
+int parse_cmdline(int argc, char **argv, opt_option *options, int nopts);
+
+/* display help message msg followed by list of options in options and followed
+ * by tail
+ */
+void help_msg(char *msg, char *tail, opt_option *options, int nopts);
+
+#endif