diff options
Diffstat (limited to 'lib/getopt.c')
-rw-r--r-- | lib/getopt.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/getopt.c b/lib/getopt.c new file mode 100644 index 0000000000..c054e1365f --- /dev/null +++ b/lib/getopt.c @@ -0,0 +1,143 @@ +/* + * getopt.c - a simple getopt(3) implementation. See getopt.h for explanation. + * + * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <getopt.h> + +int opterr = 1; +int optind = 1; +int optopt; +char *optarg; + +static int optindex = 1; /* option index in the current argv[] element */ +static int nonopts = 0; /* number of nonopts found */ + +void getopt_reset(void) +{ + optind = opterr = optindex = 1; + nonopts = 0; +} + +int getopt(int argc, char *argv[], char *optstring) +{ + char curopt; /* current option character */ + char *curoptp; /* pointer to the current option in optstring */ + + while(1) { +// printf("optindex: %d nonopts: %d optind: %d\n", optindex, nonopts, optind); + + /* first put nonopts to the end */ + while (optind + nonopts < argc && *argv[optind] != '-') { + int i; + char *tmp; + + nonopts++; + tmp = argv[optind]; + for (i = optind; i + 1 < argc; i++) + argv[i] = argv[i + 1]; + argv[argc - 1] = tmp; + } + + if (optind + nonopts >= argc) + return -1; + + /* We have found an option */ + curopt = argv[optind][optindex]; + if (curopt) + break; + /* no more options in current argv[] element. Start + * over with looking for nonopts + */ + optind++; + optindex = 1; + } + + /* look up current option in optstring */ + curoptp = strchr(optstring, curopt); + + if (!curoptp) { + if (opterr) + printf("%s: invalid option -- %c\n", argv[0], curopt); + optopt = curopt; + optindex++; + return '?'; + } + + if (*(curoptp + 1) != ':') { + /* option with no argument. Just return it */ + optarg = NULL; + optindex++; + return curopt; + } + + if (*(curoptp + 1) && *(curoptp + 2) == ':') { + /* optional argument */ + if (argv[optind][optindex + 1]) { + /* optional argument with directly following optarg */ + optarg = argv[optind] + optindex + 1; + optindex = 1; + optind++; + return curopt; + } + if (optind + nonopts + 1 == argc) { + /* We are at the last argv[] element */ + optarg = NULL; + optind++; + return curopt; + } + if (*argv[optind + 1] != '-') { + /* optional argument with optarg in next argv[] element + */ + optind++; + optarg = argv[optind]; + optind++; + optindex = 1; + return curopt; + } + + /* no optional argument found */ + optarg = NULL; + optindex = 1; + optind++; + return curopt; + } + + if (argv[optind][optindex + 1]) { + /* required argument with directly following optarg */ + optarg = argv[optind] + optindex + 1; + optind++; + optindex = 1; + return curopt; + } + + optind++; + optindex = 1; + + if (optind + nonopts >= argc || argv[optind][0] == '-') { + if (opterr) + printf("option requires an argument -- %c\n", + curopt); + optopt = curopt; + return ':'; + } + + optarg = argv[optind]; + optind++; + return curopt; +} |