Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Brings the tools getopt(3) replacement into the main library #803

Merged
merged 3 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions hl/tools/h5watch/h5watch.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,27 @@ static void parse_command_line(int argc, const char *argv[]);
* The long-named ones can be partially spelled. When
* adding more, make sure that they don't clash with each other.
*/
static const char * s_opts = "?";
static struct long_options l_opts[] = {{"help", no_arg, 'h'}, {"hel", no_arg, 'h'},
{"dim", no_arg, 'd'}, {"di", no_arg, 'd'},
{"label", no_arg, 'l'}, {"labe", no_arg, 'l'},
{"lab", no_arg, 'l'}, {"la", no_arg, 'l'},
{"simple", no_arg, 'S'}, {"simpl", no_arg, 'S'},
{"simp", no_arg, 'S'}, {"sim", no_arg, 'S'},
{"si", no_arg, 'S'}, {"hexdump", no_arg, 'x'},
{"hexdum", no_arg, 'x'}, {"hexdu", no_arg, 'x'},
{"hexd", no_arg, 'x'}, {"hex", no_arg, 'x'},
{"width", require_arg, 'w'}, {"widt", require_arg, 'w'},
{"wid", require_arg, 'w'}, {"wi", require_arg, 'w'},
{"polling", require_arg, 'p'}, {"pollin", require_arg, 'p'},
{"polli", require_arg, 'p'}, {"poll", require_arg, 'p'},
{"pol", require_arg, 'p'}, {"po", require_arg, 'p'},
{"fields", require_arg, 'f'}, {"field", require_arg, 'f'},
{"fiel", require_arg, 'f'}, {"fie", require_arg, 'f'},
{"fi", require_arg, 'f'}, {"version", no_arg, 'V'},
{"versio", no_arg, 'V'}, {"versi", no_arg, 'V'},
{"vers", no_arg, 'V'}, {"ver", no_arg, 'V'},
{"ve", no_arg, 'V'}, {NULL, 0, '\0'}};
static const char * s_opts = "?";
static struct h5_long_options l_opts[] = {{"help", no_arg, 'h'}, {"hel", no_arg, 'h'},
{"dim", no_arg, 'd'}, {"di", no_arg, 'd'},
{"label", no_arg, 'l'}, {"labe", no_arg, 'l'},
{"lab", no_arg, 'l'}, {"la", no_arg, 'l'},
{"simple", no_arg, 'S'}, {"simpl", no_arg, 'S'},
{"simp", no_arg, 'S'}, {"sim", no_arg, 'S'},
{"si", no_arg, 'S'}, {"hexdump", no_arg, 'x'},
{"hexdum", no_arg, 'x'}, {"hexdu", no_arg, 'x'},
{"hexd", no_arg, 'x'}, {"hex", no_arg, 'x'},
{"width", require_arg, 'w'}, {"widt", require_arg, 'w'},
{"wid", require_arg, 'w'}, {"wi", require_arg, 'w'},
{"polling", require_arg, 'p'}, {"pollin", require_arg, 'p'},
{"polli", require_arg, 'p'}, {"poll", require_arg, 'p'},
{"pol", require_arg, 'p'}, {"po", require_arg, 'p'},
{"fields", require_arg, 'f'}, {"field", require_arg, 'f'},
{"fiel", require_arg, 'f'}, {"fie", require_arg, 'f'},
{"fi", require_arg, 'f'}, {"version", no_arg, 'V'},
{"versio", no_arg, 'V'}, {"versi", no_arg, 'V'},
{"vers", no_arg, 'V'}, {"ver", no_arg, 'V'},
{"ve", no_arg, 'V'}, {NULL, 0, '\0'}};

/*-------------------------------------------------------------------------
* Function: doprint()
Expand Down Expand Up @@ -677,7 +677,7 @@ parse_command_line(int argc, const char *argv[])
}

/* parse command line options */
while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) {
while ((opt = H5_get_option(argc, argv, s_opts, l_opts)) != EOF) {
switch ((char)opt) {
case '?':
case 'h': /* --help */
Expand All @@ -691,7 +691,7 @@ parse_command_line(int argc, const char *argv[])
break;

case 'w': /* --width=N */
g_display_width = (int)HDstrtol(opt_arg, NULL, 0);
g_display_width = (int)HDstrtol(H5_optarg, NULL, 0);
if (g_display_width < 0) {
usage(h5tools_getprogname());
leave(EXIT_FAILURE);
Expand All @@ -711,8 +711,8 @@ parse_command_line(int argc, const char *argv[])
break;

case 'p': /* --polling=N */
/* g_polling_interval = HDstrtod(opt_arg, NULL); */
if ((tmp = (int)HDstrtol(opt_arg, NULL, 10)) <= 0) {
/* g_polling_interval = HDstrtod(H5_optarg, NULL); */
if ((tmp = (int)HDstrtol(H5_optarg, NULL, 10)) <= 0) {
usage(h5tools_getprogname());
leave(EXIT_FAILURE);
}
Expand All @@ -721,15 +721,15 @@ parse_command_line(int argc, const char *argv[])

case 'f': /* --fields=<list_of_fields> */
if (g_list_of_fields == NULL) {
if ((g_list_of_fields = HDstrdup(opt_arg)) == NULL) {
if ((g_list_of_fields = HDstrdup(H5_optarg)) == NULL) {
error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__);
leave(EXIT_FAILURE);
}
}
else {
char *str;

if ((str = HDstrdup(opt_arg)) == NULL) {
if ((str = HDstrdup(H5_optarg)) == NULL) {
error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__);
leave(EXIT_FAILURE);
}
Expand All @@ -751,7 +751,7 @@ parse_command_line(int argc, const char *argv[])
}

/* check for object to be processed */
if (argc <= opt_ind) {
if (argc <= H5_optind) {
error_msg("missing dataset name\n");
usage(h5tools_getprogname());
leave(EXIT_FAILURE);
Expand Down Expand Up @@ -821,7 +821,7 @@ main(int argc, const char *argv[])
/* parse command line options */
parse_command_line(argc, argv);

if (argc <= opt_ind) {
if (argc <= H5_optind) {
error_msg("missing dataset name\n");
usage(h5tools_getprogname());
leave(EXIT_FAILURE);
Expand All @@ -845,7 +845,7 @@ main(int argc, const char *argv[])
* then there must have been something wrong with the file (perhaps it
* doesn't exist).
*/
if ((fname = HDstrdup(argv[opt_ind])) == NULL) {
if ((fname = HDstrdup(argv[H5_optind])) == NULL) {
error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__);
h5tools_setstatus(EXIT_FAILURE);
goto done;
Expand Down
51 changes: 51 additions & 0 deletions src/H5private.h
Original file line number Diff line number Diff line change
Expand Up @@ -2655,6 +2655,57 @@ H5_DLL double H5_get_time(void);
H5_DLL herr_t H5_build_extpath(const char *name, char **extpath /*out*/);
H5_DLL herr_t H5_combine_path(const char *path1, const char *path2, char **full_name /*out*/);

/* getopt(3) equivalent that papers over the lack of long options on BSD
* and lack of Windows support.
*/
H5_DLLVAR int H5_opterr; /* get_option prints errors if this is on */
H5_DLLVAR int H5_optind; /* token pointer */
H5_DLLVAR const char *H5_optarg; /* flag argument (or value) */

enum h5_arg_level {
no_arg = 0, /* doesn't take an argument */
require_arg, /* requires an argument */
optional_arg /* argument is optional */
};

/*
* get_option determines which options are specified on the command line and
* returns a pointer to any arguments possibly associated with the option in
* the ``H5_optarg'' variable. get_option returns the shortname equivalent of
* the option. The long options are specified in the following way:
*
* struct h5_long_options foo[] = {
* { "filename", require_arg, 'f' },
* { "append", no_arg, 'a' },
* { "width", require_arg, 'w' },
* { NULL, 0, 0 }
* };
*
* Long named options can have arguments specified as either:
*
* ``--param=arg'' or ``--param arg''
*
* Short named options can have arguments specified as either:
*
* ``-w80'' or ``-w 80''
*
* and can have more than one short named option specified at one time:
*
* -aw80
*
* in which case those options which expect an argument need to come at the
* end.
*/
struct h5_long_options {
const char * name; /* Name of the long option */
enum h5_arg_level has_arg; /* Whether we should look for an arg */
char shortval; /* The shortname equivalent of long arg
* this gets returned from get_option
*/
};

H5_DLL int H5_get_option(int argc, const char **argv, const char *opt, const struct h5_long_options *l_opt);

#ifdef H5_HAVE_PARALLEL
/* Generic MPI functions */
H5_DLL hsize_t H5_mpi_set_bigio_count(hsize_t new_count);
Expand Down
164 changes: 164 additions & 0 deletions src/H5system.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,3 +936,167 @@ H5_expand_windows_env_vars(char **env_var)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_expand_windows_env_vars() */
#endif /* H5_HAVE_WIN32_API */

/* Global variables */
int H5_opterr = 1; /* Get_option prints errors if this is on */
int H5_optind = 1; /* Token pointer */
const char *H5_optarg; /* Flag argument (or value) */

/*-------------------------------------------------------------------------
* Function: H5_get_option
*
* Purpose: Determine the command-line options a user specified. We can
* accept both short and long type command-lines.
*
* Return: Success: The short valued "name" of the command line
* parameter or EOF if there are no more
* parameters to process.
*
* Failure: A question mark.
*-------------------------------------------------------------------------
*/
int
H5_get_option(int argc, const char **argv, const char *opts, const struct h5_long_options *l_opts)
{
static int sp = 1; /* character index in current token */
int optopt = '?'; /* option character passed back to user */

if (sp == 1) {
/* check for more flag-like tokens */
if (H5_optind >= argc || argv[H5_optind][0] != '-' || argv[H5_optind][1] == '\0') {
return EOF;
}
else if (HDstrcmp(argv[H5_optind], "--") == 0) {
H5_optind++;
return EOF;
}
}

if (sp == 1 && argv[H5_optind][0] == '-' && argv[H5_optind][1] == '-') {
/* long command line option */
int i;
const char ch = '=';
char * arg = HDstrdup(&argv[H5_optind][2]);
size_t arg_len = 0;

H5_optarg = strchr(&argv[H5_optind][2], ch);
arg_len = HDstrlen(&argv[H5_optind][2]);
if (H5_optarg) {
arg_len -= HDstrlen(H5_optarg);
H5_optarg++; /* skip the equal sign */
}
arg[arg_len] = 0;

for (i = 0; l_opts && l_opts[i].name; i++) {
if (HDstrcmp(arg, l_opts[i].name) == 0) {
/* we've found a matching long command line flag */
optopt = l_opts[i].shortval;

if (l_opts[i].has_arg != no_arg) {
if (H5_optarg == NULL) {
if (l_opts[i].has_arg != optional_arg) {
if (H5_optind < (argc - 1))
if (argv[H5_optind + 1][0] != '-')
H5_optarg = argv[++H5_optind];
}
else if (l_opts[i].has_arg == require_arg) {
if (H5_opterr)
HDfprintf(stderr, "%s: option required for \"--%s\" flag\n", argv[0], arg);

optopt = '?';
}
}
}
else {
if (H5_optarg) {
if (H5_opterr)
HDfprintf(stderr, "%s: no option required for \"%s\" flag\n", argv[0], arg);

optopt = '?';
}
}
break;
}
}

if (l_opts[i].name == NULL) {
/* exhausted all of the l_opts we have and still didn't match */
if (H5_opterr)
HDfprintf(stderr, "%s: unknown option \"%s\"\n", argv[0], arg);

optopt = '?';
}

H5_optind++;
sp = 1;

HDfree(arg);
}
else {
register char *cp; /* pointer into current token */

/* short command line option */
optopt = argv[H5_optind][sp];

if (optopt == ':' || (cp = HDstrchr(opts, optopt)) == 0) {
if (H5_opterr)
HDfprintf(stderr, "%s: unknown option \"%c\"\n", argv[0], optopt);

/* if no chars left in this token, move to next token */
if (argv[H5_optind][++sp] == '\0') {
H5_optind++;
sp = 1;
}
return '?';
}

if (*++cp == ':') {
/* if a value is expected, get it */
if (argv[H5_optind][sp + 1] != '\0') {
/* flag value is rest of current token */
H5_optarg = &argv[H5_optind++][sp + 1];
}
else if (++H5_optind >= argc) {
if (H5_opterr)
HDfprintf(stderr, "%s: value expected for option \"%c\"\n", argv[0], optopt);

optopt = '?';
}
else {
/* flag value is next token */
H5_optarg = argv[H5_optind++];
}

sp = 1;
}
/* wildcard argument */
else if (*cp == '*') {
/* check the next argument */
H5_optind++;
/* we do have an extra argument, check if not last */
if ((H5_optind + 1) < argc) {
if (argv[H5_optind][0] != '-') {
H5_optarg = argv[H5_optind++];
}
else {
H5_optarg = NULL;
}
}
else {
H5_optarg = NULL;
}
}
else {
/* set up to look at next char in token, next time */
if (argv[H5_optind][++sp] == '\0') {
/* no more in current token, so setup next token */
H5_optind++;
sp = 1;
}
H5_optarg = NULL;
}
}

/* return the current flag character found */
return optopt;
}
Loading