From 68de92843597711bb6270974324a651aba5336be Mon Sep 17 00:00:00 2001 From: Stanislav Karchebny Date: Fri, 28 Sep 2001 05:11:00 +0000 Subject: [PATCH] Added command line parsing svn path=/trunk/yasm/; revision=249 --- frontends/yasm/yasm-options.c | 193 ++++++++++++++++++++++++++++++++++ frontends/yasm/yasm-options.h | 63 +++++++++++ frontends/yasm/yasm.c | 117 +++++++++++++++++++-- libyasm/linemgr.c | 1 + libyasm/linemgr.h | 1 + src/Makefile.am | 2 + src/globals.c | 1 + src/globals.h | 1 + src/linemgr.c | 1 + src/linemgr.h | 1 + src/main.c | 117 +++++++++++++++++++-- src/options.c | 193 ++++++++++++++++++++++++++++++++++ src/options.h | 63 +++++++++++ 13 files changed, 734 insertions(+), 20 deletions(-) create mode 100644 frontends/yasm/yasm-options.c create mode 100644 frontends/yasm/yasm-options.h create mode 100644 src/options.c create mode 100644 src/options.h diff --git a/frontends/yasm/yasm-options.c b/frontends/yasm/yasm-options.c new file mode 100644 index 00000000..efe7882e --- /dev/null +++ b/frontends/yasm/yasm-options.c @@ -0,0 +1,193 @@ +/* $IdPath$ + * Generic Options Support Header File + * + * Copyright (c) 2001 Stanislav Karchebny + * + * 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 + +#ifdef STDC_HEADERS +# include +#endif + +#include +#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 index 00000000..121f9e64 --- /dev/null +++ b/frontends/yasm/yasm-options.h @@ -0,0 +1,63 @@ +/* $IdPath$ + * Generic Options Support Header File + * + * Copyright (c) 2001 Stanislav Karchebny + * + * 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 or --lopt= + */ +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 diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index 1e869dff..435ec46b 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -43,6 +43,7 @@ #include "bitvect.h" #include "globals.h" +#include "options.h" #include "errwarn.h" #include "bytecode.h" @@ -53,25 +54,69 @@ 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", "" }, + /* 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(""); } @@ -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/libyasm/linemgr.c b/libyasm/linemgr.c index b86c1c11..92aa3e89 100644 --- a/libyasm/linemgr.c +++ b/libyasm/linemgr.c @@ -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; diff --git a/libyasm/linemgr.h b/libyasm/linemgr.h index 1d6716e0..4cae3b83 100644 --- a/libyasm/linemgr.h +++ b/libyasm/linemgr.h @@ -25,5 +25,6 @@ extern char *filename; extern unsigned int line_number; extern unsigned char mode_bits; +extern unsigned int asm_options; #endif diff --git a/src/Makefile.am b/src/Makefile.am index e4779e40..ac07f691 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,6 +35,8 @@ libyasm_a_SOURCES = \ section.c \ section.h \ objfmt.h \ + options.h \ + options.c \ preproc.h \ parser.c \ parser.h \ diff --git a/src/globals.c b/src/globals.c index b86c1c11..92aa3e89 100644 --- a/src/globals.c +++ b/src/globals.c @@ -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; diff --git a/src/globals.h b/src/globals.h index 1d6716e0..4cae3b83 100644 --- a/src/globals.h +++ b/src/globals.h @@ -25,5 +25,6 @@ extern char *filename; extern unsigned int line_number; extern unsigned char mode_bits; +extern unsigned int asm_options; #endif diff --git a/src/linemgr.c b/src/linemgr.c index b86c1c11..92aa3e89 100644 --- a/src/linemgr.c +++ b/src/linemgr.c @@ -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; diff --git a/src/linemgr.h b/src/linemgr.h index 1d6716e0..4cae3b83 100644 --- a/src/linemgr.h +++ b/src/linemgr.h @@ -25,5 +25,6 @@ extern char *filename; extern unsigned int line_number; extern unsigned char mode_bits; +extern unsigned int asm_options; #endif diff --git a/src/main.c b/src/main.c index 1e869dff..435ec46b 100644 --- a/src/main.c +++ b/src/main.c @@ -43,6 +43,7 @@ #include "bitvect.h" #include "globals.h" +#include "options.h" #include "errwarn.h" #include "bytecode.h" @@ -53,25 +54,69 @@ 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", "" }, + /* 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(""); } @@ -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 index 00000000..efe7882e --- /dev/null +++ b/src/options.c @@ -0,0 +1,193 @@ +/* $IdPath$ + * Generic Options Support Header File + * + * Copyright (c) 2001 Stanislav Karchebny + * + * 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 + +#ifdef STDC_HEADERS +# include +#endif + +#include +#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 index 00000000..121f9e64 --- /dev/null +++ b/src/options.h @@ -0,0 +1,63 @@ +/* $IdPath$ + * Generic Options Support Header File + * + * Copyright (c) 2001 Stanislav Karchebny + * + * 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 or --lopt= + */ +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 -- 2.40.0