diff --git a/include/getopt.h b/include/getopt.h index 53ad99f9ebf..1687206d76d 100644 --- a/include/getopt.h +++ b/include/getopt.h @@ -1,56 +1,23 @@ /**************************************************************************** * include/getopt.h * - * Copyright (C) 2018 Pinecone Inc. All rights reserved. - * Author: Xiang Xiao + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * http://www.apache.org/licenses/LICENSE-2.0 * - * 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 NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 - * COPYRIGHT OWNER OR 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. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. * ****************************************************************************/ -/**************************************************************************** - * AUTHOR: Gregory Pietsch - * CREATED Thu Jan 09 22:37:00 1997 - * - * COPYRIGHT NOTICE AND DISCLAIMER: - * - * Copyright (C) 1997 Gregory Pietsch - * - * This file and the accompanying getopt.c implementation file are hereby - * placed in the public domain without restrictions. Just give the author - * credit, don't claim you wrote it or prevent anyone else from using it. - * - * Gregory Pietsch's current e-mail address: - * gpietsch@comcast.net - ***************************************************************************/ - -/* This is a glibc-extension header file. */ - #ifndef __INCLUDE_GETOPT_H #define __INCLUDE_GETOPT_H @@ -61,28 +28,18 @@ #include #include +#include + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Names for the values of the `has_arg' field of `struct option'. */ - #define no_argument 0 #define required_argument 1 #define optional_argument 2 -#define NO_ARG no_argument -#define REQUIRED_ARG required_argument -#define OPTIONAL_ARG optional_argument - -/* The GETOPT_DATA_INITIALIZER macro is used to initialize a statically- - * allocated variable of type struct getopt_data. - */ - -#define GETOPT_DATA_INITIALIZER {0, 0, 1, 0, 0, 0, 0} - /**************************************************************************** - * Public Data + * Public Type Definitions ****************************************************************************/ #undef EXTERN @@ -94,136 +51,22 @@ extern "C" #define EXTERN extern #endif -/* Used by getopt (obviously NOT thread safe!). These variables cannot be - * accessed directly by an external NXFLAT module. In that case, accessor - * functions must be used. - */ - -#ifndef __NXFLAT__ - -/* For communication from `getopt' to the caller. - * When `getopt' finds an option that takes an argument, - * the argument value is returned here. - * Also, when `ordering' is RETURN_IN_ORDER, - * each non-option ARGV-element is returned here. - */ - -EXTERN FAR char *optarg; - -/* Index in ARGV of the next element to be scanned. - * This is used for communication to and from the caller - * and for communication between successive calls to `getopt'. - * - * On entry to `getopt', zero means this is the first call; initialize. - * - * When `getopt' returns -1, this is the index of the first of the - * non-option elements that the caller should itself scan. - * - * Otherwise, `optind' communicates from one call to the next - * how much of ARGV has been scanned so far. - */ - -EXTERN int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - * for unrecognized options. - */ - -EXTERN int opterr; - -/* Set to an option character which was unrecognized. */ - -EXTERN int optopt; -#else -# define optarg (*(getoptargp())) -# define optind (*(getoptindp())) -# define optopt (*(getoptoptp())) -#endif - -/**************************************************************************** - * Public Type Definitions - ****************************************************************************/ - -/* Describe the long-named options requested by the application. - * The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - * of `struct option' terminated by an element containing a name which is - * zero. - * - * The field `has_arg' is: - * no_argument (or 0) if the option does not take an argument, - * required_argument (or 1) if the option requires an argument, - * optional_argument (or 2) if the option takes an optional argument. - * - * If the field `flag' is not NULL, it points to a variable that is set - * to the value given in the field `val' when the option is found, but - * left unchanged if the option is not found. - * - * To have a long-named option do something other than set an `int' to - * a compiled-in constant, such as set a value from `optarg', set the - * option's `flag' field to zero and its `val' field to a nonzero - * value (the equivalent single-letter option character, if there is - * one). For long options that have a zero `flag' field, `getopt' - * returns the contents of the `val' field. - */ - struct option { - FAR const char *name; /* The name of the long option */ - int has_arg; /* One of the above macros */ - FAR int *flag; /* Determines if getopt_long() returns a - * value for a long option; if it is - * non-NULL, 0 is returned as a function - * value and the value of val is stored in - * the area pointed to by flag. Otherwise, - * val is returned. - */ - int val; /* Determines the value to return if flag is - * NULL. - */ + FAR const char *name; + int has_arg; + FAR int *flag; + int val; }; -/* The getopt_data structure is for reentrancy. Its members are similar to - * the externally-defined variables. - */ - -typedef struct getopt_data -{ - FAR char *optarg; - int optind, opterr, optopt, optwhere; - int permute_from, num_nonopts; -} getopt_data; - /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -int getopt(int argc, FAR char *const argv[], FAR const char *optstring); - -int getopt_long(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind); - -int getopt_long_only(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind); - -int getopt_r(int argc, FAR char *const argv[], FAR const char *optstring, - FAR struct getopt_data *data); - -int getopt_long_r(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind, - FAR struct getopt_data *data); - -int getopt_long_only_r(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind, - FAR struct getopt_data *data); - -/* Accessor functions intended for use only by external NXFLAT - * modules. The global variables optarg, optind, and optopt cannot - * be referenced directly from external modules. - */ - -FAR char **getoptargp(void); /* Optional argument following option */ -FAR int *getoptindp(void); /* Index into argv */ -FAR int *getoptoptp(void); /* Unrecognized option character */ +int getopt_long(int argc, FAR char *const argv[], + FAR const char *shortopts, + FAR const struct option *longopts, + FAR int *longind); #undef EXTERN #if defined(__cplusplus) diff --git a/include/unistd.h b/include/unistd.h index 9b595d90f3f..627eb1a7b44 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -44,8 +44,6 @@ #include #include -#include - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -291,6 +289,23 @@ extern "C" #define EXTERN extern #endif +/* Used by getopt (obviously NOT thread safe!). These variables cannot be + * accessed directly by an external NXFLAT module. In that case, accessor + * functions must be used. + */ + +#ifndef __NXFLAT__ +EXTERN FAR char *optarg; /* Optional argument following option */ +EXTERN int opterr; /* Print error message */ +EXTERN int optind; /* Index into argv */ +EXTERN int optopt; /* Unrecognized option character */ +#else +# define optarg (*(getoptargp())) +# define opterr (*(getopterrp())) +# define optind (*(getoptindp())) +# define optopt (*(getoptoptp())) +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -366,6 +381,20 @@ int execv(FAR const char *path, FAR char * const argv[]); void swab(FAR const void *src, FAR void *dest, ssize_t nbytes); +/* getopt and friends */ + +int getopt(int argc, FAR char * const argv[], FAR const char *optstring); + +/* Accessor functions intended for use only by external NXFLAT + * modules. The global variables optarg, optind, and optopt cannot + * be referenced directly from external modules. + */ + +FAR char **getoptargp(void); /* Optional argument following option */ +FAR int *getopterrp(void); /* Print error message */ +FAR int *getoptindp(void); /* Index into argv */ +FAR int *getoptoptp(void); /* Unrecognized option character */ + int gethostname(FAR char *name, size_t size); int sethostname(FAR const char *name, size_t size); diff --git a/libs/libc/unistd/lib_getopt.c b/libs/libc/unistd/lib_getopt.c index 829f0d64e71..4600a71c30d 100644 --- a/libs/libc/unistd/lib_getopt.c +++ b/libs/libc/unistd/lib_getopt.c @@ -1,9 +1,8 @@ /**************************************************************************** * libs/libc/unistd/lib_getopt.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt - * Author: Xiang Xiao * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,609 +33,272 @@ * ****************************************************************************/ -/**************************************************************************** - * AUTHOR: Gregory Pietsch - * CREATED Fri Jan 10 21:13:05 1997 - * - * Copyright (C) 1997 Gregory Pietsch - * - * This file and the accompanying getopt.h header file are hereby placed in the - * public domain without restrictions. Just give the author credit, don't - * claim you wrote it or prevent anyone else from using it. - * - * Gregory Pietsch's current e-mail address: - * gpietsch@comcast.net - ***************************************************************************/ - /**************************************************************************** * Included Files ****************************************************************************/ #include -#include -#include -#include +#include #include +#include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#define PERMUTE 0 -#define RETURN_IN_ORDER 1 -#define REQUIRE_ORDER 2 - /**************************************************************************** * Public Data ****************************************************************************/ FAR char *optarg; /* Optional argument following option */ +int opterr = 0; /* Print error message */ int optind = 1; /* Index into argv */ -int opterr = 1; int optopt = '?'; /* unrecognized option character */ /**************************************************************************** * Private Data ****************************************************************************/ -static int optwhere = 1; -static int permute_from = 0; -static int num_nonopts = 0; - -static int g_argc; -static FAR char *const *g_argv; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/* reverse_argv_elements: reverses num elements starting at argv */ - -static void -reverse_argv_elements(FAR char **argv, int num) -{ - int i; - FAR char *tmp; - - for (i = 0; i < (num >> 1); i++) - { - tmp = argv[i]; - argv[i] = argv[num - i - 1]; - argv[num - i - 1] = tmp; - } -} - -/* permute: swap two blocks of argv-elements given their lengths */ - -static void -permute(FAR char *const argv[], int len1, int len2) -{ - reverse_argv_elements((FAR char **)argv, len1); - reverse_argv_elements((FAR char **)argv, len1 + len2); - reverse_argv_elements((FAR char **)argv, len2); -} - -/* is_option: is this argv-element an option or the end of the option list? */ - -static int -is_option(FAR char *argv_element, int only) -{ - return ((argv_element == 0) || - (argv_element[0] == '-') || (only && argv_element[0] == '+')); -} - -/* read_globals: read the values from the globals into a getopt_data - * structure - */ - -static void -read_globals(int argc, FAR char *const argv[], - FAR struct getopt_data *data) -{ - bool reinit = false; - - if (g_argc != argc || g_argv != argv) - { - g_argc = argc; - g_argv = argv; - reinit = true; - } - - data->optarg = optarg; - data->optind = reinit ? 0 : optind; - data->opterr = opterr; - data->optopt = optopt; - data->optwhere = optwhere; - data->permute_from = permute_from; - data->num_nonopts = num_nonopts; -} - -/* write_globals: write the values into the globals from a getopt_data - * structure - */ - -static void -write_globals(int r, FAR struct getopt_data *data) -{ - if (r == EOF) - { - g_argc = 0; - g_argv = NULL; - } - optarg = data->optarg; - optind = data->optind; - opterr = data->opterr; - optopt = data->optopt; - optwhere = data->optwhere; - permute_from = data->permute_from; - num_nonopts = data->num_nonopts; -} - -/* getopt_internal: the function that does all the dirty work - * NOTE: to reduce the code and RAM footprint this function uses - * fputs()/fputc() to do output to stderr instead of fprintf(). - */ - -static int -getopt_internal(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind, int only, - FAR struct getopt_data *data) -{ - int ordering = PERMUTE; - int optindex = 0; - size_t match_chars = 0; - FAR char *possible_arg = 0; - int longopt_match = -1; - int has_arg = -1; - FAR char *cp = 0; - int arg_next = 0; - int initial_colon = 0; - - /* If this is our first time through */ - - if (data->optind < 1) - { - data->optind = 1; - data->optwhere = 1; - data->permute_from = 0; - data->num_nonopts = 0; - } - - /* First, deal with silly parameters and easy stuff */ - - if (argc == 0 || argv == 0 || (shortopts == 0 && longopts == 0) - || data->optind >= argc || argv[data->optind] == 0) - { - return EOF; - } - if (strcmp(argv[data->optind], "--") == 0) - { - data->optind++; - return EOF; - } - - /* Define ordering */ - - if (shortopts != 0 && (*shortopts == '-' || *shortopts == '+')) - { - ordering = (*shortopts == '-') ? RETURN_IN_ORDER : REQUIRE_ORDER; - shortopts++; - } -#ifndef CONFIG_DISABLE_ENVIRON - else - { - ordering = (getenv("POSIXLY_CORRECT") != 0) ? REQUIRE_ORDER : PERMUTE; - } -#endif - - /* Check for initial colon in shortopts */ - - if (shortopts != 0 && *shortopts == ':') - { - ++shortopts; - initial_colon = 1; - } - - /* Based on ordering, find our next option, if we're at the beginning of - * one - */ - - if (data->optwhere == 1) - { - switch (ordering) - { - default: /* Shouldn't happen */ - case PERMUTE: - data->permute_from = data->optind; - data->num_nonopts = 0; - while (!is_option(argv[data->optind], only)) - { - data->optind++; - data->num_nonopts++; - } - if (argv[data->optind] == 0) - { - /* No more options */ - - data->optind = data->permute_from; - return EOF; - } - else if (strcmp(argv[data->optind], "--") == 0) - { - /* No more options, but have to get `--' out of the way */ - - permute(argv + data->permute_from, data->num_nonopts, 1); - data->optind = data->permute_from + 1; - return EOF; - } - break; - - case RETURN_IN_ORDER: - if (!is_option(argv[data->optind], only)) - { - data->optarg = argv[data->optind++]; - return (data->optopt = 1); - } - break; - - case REQUIRE_ORDER: - if (!is_option(argv[data->optind], only)) - { - return EOF; - } - break; - } - } - - /* We've got an option, so parse it */ - - /* First, is it a long option? */ - - if (longopts != 0 && - (memcmp(argv[data->optind], "--", 2) == 0 || - (only && argv[data->optind][0] == '+')) && data->optwhere == 1) - { - /* Handle long options */ - - if (memcmp(argv[data->optind], "--", 2) == 0) - { - data->optwhere = 2; - } - possible_arg = strchr(argv[data->optind] + data->optwhere, '='); - if (possible_arg == 0) - { - /* No =, so next argv might be arg */ - - match_chars = strlen(argv[data->optind]); - possible_arg = argv[data->optind] + match_chars; - match_chars = match_chars - data->optwhere; - } - else - { - match_chars = (possible_arg - argv[data->optind]) - data->optwhere; - } - - for (optindex = 0; longopts[optindex].name != 0; ++optindex) - { - if (memcmp(argv[data->optind] + data->optwhere, - longopts[optindex].name, match_chars) == 0) - { - /* Do we have an exact match? */ - - if (match_chars == strlen(longopts[optindex].name)) - { - longopt_match = optindex; - break; - } - - /* Do any characters match? */ - - else - { - if (longopt_match < 0) - { - longopt_match = optindex; - } - else - { - /* We have ambiguous options */ - - if (data->opterr) - { - fputs(argv[0], stderr); - fputs(": option `", stderr); - fputs(argv[data->optind], stderr); - fputs("' is ambiguous (could be `--", stderr); - fputs(longopts[longopt_match].name, stderr); - fputs("' or `--", stderr); - fputs(longopts[optindex].name, stderr); - fputs("')\n", stderr); - } - data->optind++; - return (data->optopt = '?'); - } - } - } - } - if (longopt_match >= 0) - { - has_arg = longopts[longopt_match].has_arg; - } - } - - /* If we didn't find a long option, is it a short option? */ - - if (longopt_match < 0 && shortopts != 0) - { - cp = strchr(shortopts, argv[data->optind][data->optwhere]); - if (cp == 0) - { - /* Couldn't find option in shortopts */ - - if (data->opterr) - { - fputs(argv[0], stderr); - fputs(": invalid option -- `-", stderr); - fputc(argv[data->optind][data->optwhere], stderr); - fputs("'\n", stderr); - } - data->optwhere++; - if (argv[data->optind][data->optwhere] == '\0') - { - data->optind++; - data->optwhere = 1; - } - return (data->optopt = '?'); - } - has_arg = ((cp[1] == ':') ? - ((cp[2] == ':') ? OPTIONAL_ARG : REQUIRED_ARG) : NO_ARG); - possible_arg = argv[data->optind] + data->optwhere + 1; - data->optopt = *cp; - } - - /* Get argument and reset data->optwhere */ - - switch (has_arg) - { - case OPTIONAL_ARG: - if (*possible_arg == '=') - { - possible_arg++; - } - data->optarg = (*possible_arg != '\0') ? possible_arg : 0; - data->optwhere = 1; - break; - - case REQUIRED_ARG: - if (*possible_arg == '=') - { - possible_arg++; - } - if (*possible_arg != '\0') - { - data->optarg = possible_arg; - data->optwhere = 1; - } - else if (data->optind + 1 >= argc) - { - if (data->opterr) - { - fputs(argv[0], stderr); - fputs(": argument required for option `-", stderr); - if (longopt_match >= 0) - { - fputc('-', stderr); - fputs(longopts[longopt_match].name, stderr); - data->optopt = initial_colon ? ':' : '\?'; - } - else - { - fputc(*cp, stderr); - data->optopt = *cp; - } - fputs("'\n", stderr); - } - data->optind++; - return initial_colon ? ':' : '\?'; - } - else - { - data->optarg = argv[data->optind + 1]; - arg_next = 1; - data->optwhere = 1; - } - break; - - default: /* Shouldn't happen */ - case NO_ARG: - if (longopt_match < 0) - { - data->optwhere++; - if (argv[data->optind][data->optwhere] == '\0') - { - data->optwhere = 1; - } - } - else - { - data->optwhere = 1; - } - data->optarg = 0; - break; - } - - /* Do we have to permute or otherwise modify data->optind? */ - - if (ordering == PERMUTE && data->optwhere == 1 && data->num_nonopts != 0) - { - permute(argv + data->permute_from, data->num_nonopts, 1 + arg_next); - data->optind = data->permute_from + 1 + arg_next; - } - else if (data->optwhere == 1) - { - data->optind = data->optind + 1 + arg_next; - } - - /* Finally return */ - - if (longopt_match >= 0) - { - if (longind != 0) - { - *longind = longopt_match; - } - if (longopts[longopt_match].flag != 0) - { - *(longopts[longopt_match].flag) = longopts[longopt_match].val; - return 0; - } - else - { - return longopts[longopt_match].val; - } - } - else - { - return data->optopt; - } -} +static FAR char *g_optptr = NULL; +static FAR char * const *g_argv = NULL; +static int g_argc = 0; +static bool g_binitialized = false; /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** -The getopt() function parses the command line arguments. Its arguments argc -and argv are the argument count and array as passed to the main() function -on program invocation. The argument optstring is a list of available option -characters. If such a character is followed by a colon (`:'), the option -takes an argument, which is placed in optarg. If such a character is -followed by two colons, the option takes an optional argument, which is -placed in optarg. If the option does not take an argument, optarg is NULL. + * Name: getopt + * + * Description: + * getopt() parses command-line arguments. Its arguments argc and argv + * are the argument count and array as passed to the main() function on + * program invocation. An element of argv that starts with '-' is an + * option element. The characters of this element (aside from the initial + * '-') are option characters. If getopt() is called repeatedly, it + * returns successively each of the option characters from each of the + * option elements. + * + * If getopt() finds another option character, it returns that character, + * updating the external variable optind and a static variable nextchar so + * that the next call to getopt() can resume the scan with the following + * option character or argv-element. + * + * If there are no more option characters, getopt() returns -1. Then optind + * is the index in argv of the first argv-element that is not an option. + * + * The 'optstring' argument is a string containing the legitimate option + * characters. If such a character is followed by a colon, this indicates + * that the option requires an argument. If an argument is required for an + * option so getopt() places a pointer to the following text in the same + * argv-element, or the text of the following argv-element, in optarg. + * + * NOTES: + * 1. opterr is not supported and this implementation of getopt() never + * printfs error messages. + * 2. getopt is NOT threadsafe! + * 3. This version of getopt() does not reset global variables until + * -1 is returned. As a result, your command line parsing loops + * must call getopt() repeatedly and continue to parse if other + * errors are returned ('?' or ':') until getopt() finally returns -1. + * (You can also set optind to -1 to force a reset). + * + * Returned Value: + * If an option was successfully found, then getopt() returns the option + * character. If all command-line options have been parsed, then getopt() + * returns -1. If getopt() encounters an option character that was not + * in optstring, then '?' is returned. If getopt() encounters an option + * with a missing argument, then the return value depends on the first + * character in optstring: if it is ':', then ':' is returned; otherwise + * '?' is returned. + * + ****************************************************************************/ -The external variable optind is the index of the next array element of argv -to be processed; it communicates from one call to the next which element to -process. - -The getopt_long() function works like getopt() except that it also accepts -long options started by two dashes `--'. If these take values, it is either -in the form - ---arg=value - - or - ---arg value - -It takes the additional arguments longopts which is a pointer to the first -element of an array of type struct option. The last element of the array -has to be filled with NULL for the name field. - -The longind pointer points to the index of the current long option relative -to longopts if it is non-NULL. - -The getopt() function returns the option character if the option was found -successfully, `:' if there was a missing parameter for one of the options, -`?' for an unknown option character, and EOF for the end of the option list. - -The getopt_long() function's return value is described in the header file. - -The function getopt_long_only() is identical to getopt_long(), except that a -plus sign `+' can introduce long options as well as `--'. - -The following describes how to deal with options that follow non-option -argv-elements. - -If the caller did not specify anything, the default is REQUIRE_ORDER if the -environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. - -REQUIRE_ORDER means don't recognize them as options; stop option processing -when the first non-option is seen. This is what Unix does. This mode of -operation is selected by either setting the environment variable -POSIXLY_CORRECT, or using `+' as the first character of the optstring -parameter. - -PERMUTE is the default. We permute the contents of ARGV as we scan, so that -eventually all the non-options are at the end. This allows options to be -given in any order, even with programs that were not written to expect this. - -RETURN_IN_ORDER is an option available to programs that were written to -expect options and other argv-elements in any order and that care about the -ordering of the two. We describe each non-option argv-element as if it were -the argument of an option with character code 1. Using `-' as the first -character of the optstring parameter selects this mode of operation. - -The special argument `--' forces an end of option-scanning regardless of the -value of ordering. In the case of RETURN_IN_ORDER, only `--' can cause -getopt() and friends to return EOF with optind != argc. - -2012-08-26: Tried to make the error handling more sus4-like. The functions -return a colon if getopt() and friends detect a missing argument and the -first character of shortopts/optstring starts with a colon (`:'). If getopt() -and friends detect a missing argument and shortopts/optstring does not start -with a colon, the function returns a question mark (`?'). If it was a missing -argument to a short option, optopt is set to the character in question. The -colon goes after the ordering character (`+' or `-'). -****************************************************************************/ - -int -getopt(int argc, FAR char *const argv[], FAR const char *optstring) +int getopt(int argc, FAR char * const argv[], FAR const char *optstring) { - struct getopt_data data; - int r; + /* Were new argc or argv passed in? This detects misuse of getopt() by + * applications that break out of the getopt() loop before getop() returns + * -1. + */ - read_globals(argc, argv, &data); - r = getopt_internal(argc, argv, optstring, 0, 0, 0, &data); - write_globals(r, &data); - return r; + if (argc != g_argc || argv != g_argv) + { + /* Yes, clear the internal state */ + + g_binitialized = false; + g_argc = argc; + g_argv = argv; + } + + /* Verify input parameters. */ + + if (argv != NULL && optstring != NULL && argc > 1) + { + FAR char *optchar; + int noarg_ret = '?'; + + /* The initial value of optind is 1. If getopt() is called again in + * the program, optind must be reset to some value <= 1. + */ + + if (optind < 1 || !g_binitialized) + { + optarg = NULL; + optind = 1; /* Skip over the program name */ + optopt = '?'; + g_optptr = NULL; /* Start at the beginning of the first argument */ + g_binitialized = true; /* Now we are initialized */ + } + + /* If the first character of opstring s ':', then ':' is in the event + * of a missing argument. Otherwise '?' is returned. + */ + + if (*optstring == ':') + { + noarg_ret = ':'; + optstring++; + } + + /* Are we resuming in the middle, or at the end of a string of + * arguments? g_optptr == NULL means that we are started at the + * beginning of argv[optind]; *g_optptr == \0 means that we are + * starting at the beginning of optind+1 + */ + + while (!g_optptr || !*g_optptr) + { + /* We need to start at the beginning of the next argv. Check if we + * need to increment optind + */ + + if (g_optptr) + { + /* Yes.. Increment it and check for the case where where we + * have processed everything in the argv[] array. + */ + + optind++; + } + + /* Check for the end of the argument list */ + + g_optptr = argv[optind]; + if (!g_optptr) + { + /* There are no more arguments, we are finished */ + + g_binitialized = false; + return ERROR; + } + + /* We are starting at the beginning of argv[optind]. In this case, + * the first character must be '-' + */ + + if (*g_optptr != '-') + { + /* The argument does not start with '-', we are finished */ + + g_binitialized = false; + return ERROR; + } + + /* Skip over the '-' */ + + g_optptr++; + } + + /* Special case handling of "-" and "-:" */ + + if (!*g_optptr) + { + optopt = '\0'; /* We'll fix up g_optptr the next time we are called */ + return '?'; + } + + /* Handle the case of "-:" */ + + if (*g_optptr == ':') + { + optopt = ':'; + g_optptr++; + return '?'; + } + + /* g_optptr now points at the next option and it is not something + * crazy. check if the option is in the list of valid options. + */ + + optchar = strchr(optstring, *g_optptr); + if (!optchar) + { + /* No this character is not in the list of valid options */ + + optopt = *g_optptr; + g_optptr++; + return '?'; + } + + /* Yes, the character is in the list of valid options. Does it have an + * required argument? + */ + + if (optchar[1] != ':') + { + /* No, no arguments. Just return the character that we found */ + + g_optptr++; + return *optchar; + } + + /* Yes, it has a required argument. Is the required argument + * immediately after the command in this same argument? + */ + + if (g_optptr[1] != '\0') + { + /* Yes, return a pointer into the current argument */ + + optarg = &g_optptr[1]; + optind++; + g_optptr = NULL; + return *optchar; + } + + /* No.. is the optional argument the next argument in argv[] ? */ + + if (argv[optind + 1] && *argv[optind + 1] != '-') + { + /* Yes.. return that */ + + optarg = argv[optind + 1]; + optind += 2; + g_optptr = NULL; + return *optchar; + } + + /* No argument was supplied */ + + g_optptr = NULL; + optarg = NULL; + optopt = *optchar; + optind++; + return noarg_ret; + } + + /* Restore the initial, uninitialized state */ + + g_binitialized = false; + return ERROR; } -int -getopt_long(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind) +int getopt_long(int argc, FAR char *const argv[], + FAR const char *shortopts, + FAR const struct option *longopts, + FAR int *longind) { - struct getopt_data data; - int r; - - read_globals(argc, argv, &data); - r = getopt_internal(argc, argv, shortopts, longopts, longind, 0, &data); - write_globals(r, &data); - return r; -} - -int -getopt_long_only(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind) -{ - struct getopt_data data; - int r; - - read_globals(argc, argv, &data); - r = getopt_internal(argc, argv, shortopts, longopts, longind, 1, &data); - write_globals(r, &data); - return r; -} - -int -getopt_r(int argc, FAR char *const argv[], FAR const char *optstring, - FAR struct getopt_data *data) -{ - return getopt_internal(argc, argv, optstring, 0, 0, 0, data); -} - -int -getopt_long_r(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind, - FAR struct getopt_data *data) -{ - return getopt_internal(argc, argv, shortopts, longopts, longind, 0, data); -} - -int -getopt_long_only_r(int argc, FAR char *const argv[], FAR const char *shortopts, - FAR const struct option *longopts, FAR int *longind, - FAR struct getopt_data *data) -{ - return getopt_internal(argc, argv, shortopts, longopts, longind, 1, data); + return getopt(argc, argv, shortopts); }