blob: cf2c0c10002f644931cda0827105440c9202533e [file] [log] [blame]
/* <@LICENSE>
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
* </@LICENSE>
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include "getopt.h"
#ifdef WIN32
#ifdef _MSC_VER
/* ignore MSVC++ warnings that are annoying and hard to remove:
4702 unreachable code
(there is an unreachable assert(0) in case somehow it is reached)
*/
#pragma warning( disable : 4702 )
#endif
#endif /* WIN32 */
#define OPTERRCOLON (1)
#define OPTERRNF (2)
#define OPTERRARG (3)
char *spamc_optarg;
int spamc_optreset = 0;
int spamc_optind = 1;
int spamc_opterr = 1;
int spamc_optopt;
static int
optiserr(int argc, char * const *argv, int oint, const char *optstr,
int optchr, int err)
{
(void) argc; /* not used */
(void) optstr; /* not used */
if(spamc_opterr)
{
fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1);
switch(err)
{
case OPTERRCOLON:
fprintf(stderr, ": in flags\n");
break;
case OPTERRNF:
fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
break;
case OPTERRARG:
fprintf(stderr, "argument required for option %c\n", argv[oint][optchr]);
break;
default:
fprintf(stderr, "unknown\n");
break;
}
}
spamc_optopt = argv[oint][optchr];
return('?');
}
static int
longoptiserr(int argc, char * const *argv, int oint, int err)
{
(void) argc; /* not used */
if(spamc_opterr)
{
fprintf(stderr, "Error in argument %d : ", oint);
switch(err)
{
case OPTERRCOLON:
fprintf(stderr, ": in flags\n");
break;
case OPTERRNF:
fprintf(stderr, "option not found %s\n", argv[oint]);
break;
case OPTERRARG:
fprintf(stderr, "argument required for option %s\n", argv[oint]);
break;
default:
fprintf(stderr, "unknown\n");
break;
}
}
return('?');
}
int
spamc_getopt(int argc, char* const *argv, const char *optstr)
{
static int optchr = 0;
static int dash = 0; /* have already seen the - */
char *cp;
if (spamc_optreset)
spamc_optreset = optchr = dash = 0;
if(spamc_optind >= argc)
return(EOF);
if(!dash && (argv[spamc_optind][0] != '-'))
return(EOF);
if(!dash && (argv[spamc_optind][0] == '-') && !argv[spamc_optind][1])
{
/*
* use to specify stdin. Need to let pgm process this and
* the following args
*/
return(EOF);
}
if((argv[spamc_optind][0] == '-') && (argv[spamc_optind][1] == '-'))
{
/* -- indicates end of args */
spamc_optind++;
return(EOF);
}
if(!dash)
{
assert((argv[spamc_optind][0] == '-') && argv[spamc_optind][1]);
dash = 1;
optchr = 1;
}
/* Check if the guy tries to do a -: kind of flag */
assert(dash);
if(argv[spamc_optind][optchr] == ':')
{
dash = 0;
spamc_optind++;
return(optiserr(argc, argv, spamc_optind-1, optstr, optchr, OPTERRCOLON));
}
cp = strchr(optstr, argv[spamc_optind][optchr]);
if(!cp)
{
int errind = spamc_optind;
int errchr = optchr;
if(!argv[spamc_optind][optchr+1])
{
dash = 0;
spamc_optind++;
}
else
optchr++;
return(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF));
}
if(cp[1] == ':')
{
dash = 0;
spamc_optind++;
if(spamc_optind == argc)
return(optiserr(argc, argv, spamc_optind-1, optstr, optchr, OPTERRARG));
spamc_optarg = argv[spamc_optind++];
return(*cp);
}
else
{
if(!argv[spamc_optind][optchr+1])
{
dash = 0;
spamc_optind++;
}
else
optchr++;
return(*cp);
}
assert(0);
return(0);
}
int
spamc_getopt_long(int argc, char * const argv[],
const char *optstring, struct option *longopts,
int *longindex)
{
static int optchr = 0;
static int dash = 0;
char *cp, *longopt;
char *bp, *opt = NULL;
int i, longoptlen;;
spamc_optarg = NULL; /* clear any left over state from previous option */
if(spamc_optreset)
spamc_optreset = optchr = dash = 0;
if(spamc_optind >= argc) {
return(EOF);
}
if(!dash && (argv[spamc_optind][0] != '-')) {
return(EOF);
}
if(!dash && (argv[spamc_optind][0] == '-') && !argv[spamc_optind][1]) {
/* used to specify stdin */
return(EOF);
}
if((argv[spamc_optind][0] == '-') && (argv[spamc_optind][1] == '-')
&& !argv[spamc_optind][2]) {
/* used to specify end of args */
return(EOF);
}
if((argv[spamc_optind][0] == '-') && argv[spamc_optind][1] &&
(argv[spamc_optind][1] != '-')) {
/* short option */
optchr = 1;
if(argv[spamc_optind][optchr] == ':')
return(optiserr(argc, argv, spamc_optind++, optstring, optchr, OPTERRCOLON));
cp = strchr(optstring, argv[spamc_optind++][optchr]);
if(cp == NULL)
return(optiserr(argc, argv, spamc_optind-1, optstring, optchr, OPTERRNF));
if(cp[1] == ':') {
/* requires an argument */
if(!argv[spamc_optind] || (argv[spamc_optind][0] == '-') ||
(spamc_optind >= argc)) {
return(optiserr(argc, argv, spamc_optind-1, optstring, optchr, OPTERRARG));
}
spamc_optarg = argv[spamc_optind++];
return(*cp);
} else {
dash = 0;
return(*cp);
}
}
if((argv[spamc_optind][0] == '-') && (argv[spamc_optind][1] == '-') &&
argv[spamc_optind][2]) {
/* long option */
optchr = 2;
longopt = argv[spamc_optind++];
if(longopt[2] == ':')
return(longoptiserr(argc, argv, spamc_optind, OPTERRCOLON));
longoptlen = strlen(longopt) - 2;
if((bp = strchr(longopt, '='))) {
opt = strdup(bp+1);
if (opt == NULL) {
fprintf(stderr, "%s: %s\n", argv[0], strerror(errno));
exit(1);
}
longoptlen -= strlen(bp);
}
for(i=0; ; i++) {
/* changed to longopts[i].name[0] == 0 - bug 7148 */
if((longopts[i].name == NULL) || (longopts[i].name[0] == 0)) {
free(opt);
return(longoptiserr(argc, argv, spamc_optind-1, OPTERRNF));
}
if(((strncmp(longopt+2, longopts[i].name, longoptlen)) == 0) && (strlen(longopts[i].name) == longoptlen)) {
*longindex = i;
if(longopts[i].has_arg == required_argument) {
if(((spamc_optind >= argc) || (!argv[spamc_optind]) || (argv[spamc_optind][0] == '-')) &&
(opt == NULL)) {
free(opt);
return(longoptiserr(argc, argv, spamc_optind-1, OPTERRARG));
}
if(opt != NULL) {
spamc_optarg = opt;
} else {
spamc_optarg = argv[spamc_optind++];
}
} else if(longopts[i].has_arg == optional_argument) {
if(((spamc_optind < argc) && (argv[spamc_optind]) && (argv[spamc_optind][0] != '-')) ||
(opt != NULL)) {
if(opt != NULL) {
spamc_optarg = opt;
} else {
spamc_optarg = argv[spamc_optind++];
}
}
}
if(longopts[i].flag == NULL) {
return(longopts[i].val);
} else {
*longopts[i].flag = longopts[i].val;
return(0);
}
}
}
}
return(0); /* should never reach here */
}
#ifdef TESTGETOPT
int
main (int argc, char **argv)
{
int c, l;
extern char *spamc_optarg;
extern int spamc_optind;
int aflg = 0;
int bflg = 0;
int errflg = 0;
char *ofile = NULL;
struct option longopts[] = {
{ "test", required_argument, 0, 't' },
};
while ((c = spamc_getopt(argc, argv, "abo:")) != EOF)
switch (c) {
case 'a':
if (bflg)
errflg++;
else
aflg++;
break;
case 'b':
if (aflg)
errflg++;
else
bflg++;
break;
case 'o':
ofile = spamc_optarg;
(void)printf("ofile = %s\n", ofile);
break;
case '?':
errflg++;
}
while((l = spamc_getopt_long(argc, argv, "t:", longopts, &l)) != EOF)
switch(l) {
case 't':
printf("--test = %s\n",spamc_optarg);
break;
}
if (errflg) {
(void)fprintf(stderr,
"usage: cmd [-a|-b] [-o <filename>] files...\n");
exit (2);
}
/*for ( ; spamc_optind < argc; spamc_optind++)
* (void)printf("%s\n", argv[spamc_optind]);
*/
return 0;
}
#endif /* TESTGETOPT */