blob: 64d6ac1e15d305580699265a8a0d38696cb00733 [file] [log] [blame]
/*
* 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 <module.h>
#include <getopt.h>
int opterr = 1;
int optind = 1;
int optopt;
char *optarg;
EXPORT_SYMBOL(optind);
EXPORT_SYMBOL(opterr);
EXPORT_SYMBOL(optopt);
EXPORT_SYMBOL(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;
}
EXPORT_SYMBOL(getopt_reset);
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;
}
EXPORT_SYMBOL(getopt);