/****************************************************************************** * Copyright (c) 2004, 2008 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ /* * includes ******************************************************************************* */ #include #include #include #include /* * global variables, types & constants * may be removed if already defined ******************************************************************************* */ int opterr = 1; int optopt = 0; int optind = 1; char *optarg = NULL; /* * internal values needed by getopt * DO NOT CHANGE or REMOVE */ enum { OPTIONAL_ARG = 0, MANDATORY_ARG = 1, NO_ARG = 2 }; /* * variables needed by getopt & getopt_long! * DO NOT REMOVE */ static char *optstart = NULL; int getopt(int argc, char **argv, const char *options) { char *optptr; char *argptr; int optman; int idx; int ret = 0; int argpresent; /* * reset used global values */ optopt = 0; optarg = NULL; /* * reset getopt if a new argv pointer is passed */ if (optstart != argv[0]) { optopt = 0; optind = 1; optarg = NULL; optstart = argv[0]; } /* * return if no more arguments are available */ if (optind >= argc) { return -1; } /* * start parsing argv[optind] */ idx = 0; /* * return if the option does not begin with a '-' or has more than 2 characters */ if (argv[optind][idx] != '-') { if (opterr != 0) { printf("unknown option \'%s\', expecting \'-\'\n", argv[optind]); } optopt = (int) argv[optind][idx]; optind++; return '?'; } /* * continue to the next character in argv[optind] */ idx++; /* * identify the option * make sure if an option contains a ':' to invalidate the option */ optptr = strchr(argv[optind], ':'); if (optptr == NULL) { optptr = strchr(options, (int) argv[optind][idx]); } else { optptr = NULL; } /* * check whether the option is present */ if (optptr == NULL) { /* * unknown option detected */ if (opterr != 0) { printf("unknown option \'%s\'\n", argv[optind]); } optopt = (int) argv[optind][idx]; optind++; return '?'; } /* * the option is present in the option string * setup return value */ ret = (int) *optptr; /* * get option argument if needed */ optptr++; /* * determine between mandatory and optional argument */ optman = NO_ARG; if (*optptr == ':') { optman--; // now set to MANDATORY_ARG } if (optman == MANDATORY_ARG) { optptr++; if (*optptr == ':') { optman--; // now set to OPTIONAL_ARG } } /* * if strlen( argv[optind ) is greater than 2, * the argument is in the same argv */ if (strlen(argv[optind]) > 2) { argptr = &argv[optind][2]; /* * do not allow '-' in an argument */ if (strchr(argptr, '-') != NULL) { if (opterr != 0) { printf ("illegal argument value \'%s\' for option \'-%c\'\n", argptr, ret); } optopt = ret; return '?'; } } else { /* * move on to the next argv * it now either contains an argument or the next option */ optind++; /* * make sure not to overflow */ if (optind < argc) { argptr = argv[optind]; } else { argptr = NULL; } } /* * do the needed actions for the argument state */ switch (optman) { case OPTIONAL_ARG: if (argptr == NULL) { break; } if (*argptr != '-') { /* * argument present */ optarg = argptr; optind++; } break; case MANDATORY_ARG: argpresent = (argptr != NULL); if (argpresent) { argpresent = (*argptr != '-'); } if (argpresent) { /* * argument present */ optarg = argptr; optind++; } else { /* * mandatory argument missing */ if (opterr != 0) { printf ("missing argument for option \'-%c\'\n", ret); } optopt = ret; /* * if the first character of options is a ':' * return a ':' instead of a '?' in case of * a missing argument */ if (*options == ':') { ret = ':'; } else { ret = '?'; } } break; case NO_ARG: if (strlen(argv[optind - 1]) > 2) { if (opterr != 0) { printf ("too many arguments for option \'-%c\'\n", ret); } optopt = ret; ret = '?'; } break; } return ret; } int getopt_long(int argc, char **argv, const char *shortopts, const struct option *longopts, int *indexptr) { struct option *optptr = (struct option *) longopts; int optidx = 0; int idx; int ret = 0; int argpresent; /* * reset used global values */ optopt = 0; optarg = NULL; /* * reset indexptr */ *indexptr = -1; /* * reset getopt if a new argv pointer is passed */ if (optstart != argv[0]) { optopt = 0; optind = 1; optarg = NULL; optstart = argv[0]; } /* * return if no more arguments are available */ if (optind >= argc) { return -1; } /* * start parsing argv[optind] */ idx = 0; /* * return if the option does not begin with a '-' */ if (argv[optind][idx] != '-') { printf("unknown option \'%s\', expecting \'-\'\n", argv[optind]); optind++; return '?'; } /* * move on to the next character in argv[optind] */ idx++; /* * return getopt() in case of a short option */ if (argv[optind][idx] != '-') { return getopt(argc, argv, shortopts); } /* * handle a long option */ idx++; while (optptr->name != NULL) { if (strcmp(&argv[optind][idx], optptr->name) == 0) { break; } optptr++; optidx++; } /* * no matching option found */ if (optptr->name == NULL) { printf("unknown option \'%s\'\n", argv[optind]); optind++; return '?'; } /* * option was found, set up index pointer */ *indexptr = optidx; /* * get argument */ optind++; switch (optptr->has_arg) { case no_argument: /* * nothing to do */ break; case required_argument: argpresent = (optind != argc); if (argpresent) { argpresent = (argv[optind][0] != '-'); } if (argpresent) { /* * argument present */ optarg = argv[optind]; optind++; } else { /* * mandatory argument missing */ printf("missing argument for option \'%s\'\n", argv[optind - 1]); ret = '?'; } break; case optional_argument: if (optind == argc) { break; } if (argv[optind][0] != '-') { /* * argument present */ optarg = argv[optind]; optind++; } break; default: printf("unknown argument option for option \'%s\'\n", argv[optind - 1]); ret = '?'; break; } /* * setup return values */ if (ret != '?') { if (optptr->flag == NULL) { ret = optptr->val; } else { *optptr->flag = optptr->val; ret = 0; } } return ret; }