--- /dev/null
+/*****************************************************************
+ * SQUID - a library of functions for biological sequence analysis
+ * Copyright (C) 1992-2002 Washington University School of Medicine
+ *
+ * This source code is freely distributed under the terms of the
+ * GNU General Public License. See the files COPYRIGHT and LICENSE
+ * for details.
+ *****************************************************************/
+
+/* RCS $Id: getopt.c 217 2011-03-19 10:27:10Z andreas $ (Original squid RCS Id: getopt.c,v 1.7 2001/02/21 21:09:10 eddy Exp)
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "squid.h"
+
+/* Function: Getopt()
+ *
+ * Purpose: Portable command line option parsing with abbreviated
+ * option switches. Replaces UNIX getopt(). Using UNIX getopt()
+ * hinders portability to non-UNIX platforms, and getopt()
+ * is also limited to single letter options.
+ *
+ * Getopt() implements a superset of UNIX getopt().
+ * All of getopt()'s single-character switch behavior
+ * is emulated, and "--" by itself terminates the options.
+ * Additionally, Getopt() provides extended switches
+ * like "--youroptionhere", and Getopt() type checks
+ * arguments.
+ *
+ * Extended options must start with "--", as in "--option1".
+ * Normal options must start with "-", as in "-o".
+ * Normal options may be concatenated, as in "-a -b" == "-ab".
+ *
+ * See bottom of this .c file after #fdef GETOPT_TESTDRIVER
+ * for an example of calling Getopt().
+ *
+ * Args: argc - from main(). number of elems in argv.
+ * argv - from main(). argv[0] is the name of the command.
+ * opt - array of opt_s structures, defining option switches
+ * nopts - number of switches in opt
+ * usage - a (possibly long) string to print if usage error.
+ * ret_optind - RETURN: the index in argv[] of the next
+ * valid command-line token.
+ * ret_optname- RETURN: ptr to the name of option switch
+ * seen, or NULL if no option was seen.
+ * ret_optarg - RETURN: ptr to the optional argument, if any;
+ * NULL if option takes no argument.
+ *
+ * Return: 1 if a valid option was parsed.
+ * 0 if no option was found, and command-line parsing is complete.
+ * Die()'s here if an error is detected.
+ */
+int
+Getopt(int argc, char **argv, struct opt_s *opt, int nopts, char *usage,
+ int *ret_optind, char **ret_optname, char **ret_optarg)
+{
+ int i;
+ int arglen;
+ int nmatch;
+ static int optind = 1; /* init to 1 on first call */
+ static char *optptr = NULL; /* ptr to next valid switch */
+ int opti = 0; /* init only to silence gcc uninit warnings */
+
+ /* Check to see if we've run out of options.
+ * A '-' by itself is an argument (e.g. "read from stdin")
+ * not an option.
+ */
+ if (optind >= argc || argv[optind][0] != '-' || strcmp(argv[optind], "-") == 0)
+ {
+ *ret_optind = optind;
+ *ret_optarg = NULL;
+ *ret_optname = NULL;
+ return 0;
+ }
+
+ /* Check to see if we're being told that this is the end
+ * of the options with the special "--" flag.
+ */
+ if (strcmp(argv[optind], "--") == 0)
+ {
+ optind++;
+ *ret_optind = optind;
+ *ret_optname = NULL;
+ *ret_optarg = NULL;
+ return 0;
+ }
+
+ /* We have a real option. Find which one it is.
+ * We handle single letter switches "-o" separately
+ * from full switches "--option", based on the "-" vs. "--"
+ * prefix -- single letter switches can be concatenated
+ * as long as they don't have arguments.
+ */
+ /* full option */
+ if (optptr == NULL && strncmp(argv[optind], "--", 2) == 0)
+ {
+ /* Use optptr to parse argument in options of form "--foo=666"
+ */
+ if ((optptr = strchr(argv[optind], '=')) != NULL)
+ { *optptr = '\0'; optptr++; }
+
+ arglen = strlen(argv[optind]);
+ nmatch = 0;
+ for (i = 0; i < nopts; i++)
+ if (opt[i].single == FALSE &&
+ strncmp(opt[i].name, argv[optind], arglen) == 0)
+ {
+ nmatch++;
+ opti = i;
+ if (arglen == strlen(opt[i].name)) break; /* exact match, stop now */
+ }
+ if (nmatch > 1 && arglen != strlen(opt[i].name))
+ Die("Option \"%s\" is ambiguous; please be more specific.\n%s",
+ argv[optind], usage);
+ if (nmatch == 0)
+ Die("No such option \"%s\".\n%s", argv[optind], usage);
+
+ *ret_optname = opt[opti].name;
+
+ /* Set the argument, if there is one
+ */
+ if (opt[opti].argtype != sqdARG_NONE)
+ {
+ if (optptr != NULL)
+ { /* --foo=666 style */
+ *ret_optarg = optptr;
+ optptr = NULL;
+ optind++;
+ }
+ else if (optind+1 >= argc)
+ Die("Option %s requires an argument\n%s", opt[opti].name, usage);
+ else /* "--foo 666" style */
+ {
+ *ret_optarg = argv[optind+1];
+ optind+=2;
+ }
+ }
+ else /* sqdARG_NONE */
+ {
+ if (optptr != NULL)
+ Die("Option %s does not take an argument\n%s", opt[opti].name, usage);
+ *ret_optarg = NULL;
+ optind++;
+ }
+ }
+ else /* else, a single letter option "-o" */
+ {
+ /* find the option */
+ if (optptr == NULL)
+ optptr = argv[optind]+1;
+ for (opti = -1, i = 0; i < nopts; i++)
+ if (opt[i].single == TRUE && *optptr == opt[i].name[1])
+ { opti = i; break; }
+ if (opti == -1)
+ Die("No such option \"%c\".\n%s", *optptr, usage);
+ *ret_optname = opt[opti].name;
+
+ /* set the argument, if there is one */
+ if (opt[opti].argtype != sqdARG_NONE)
+ {
+ if (*(optptr+1) != '\0') /* attached argument */
+ {
+ *ret_optarg = optptr+1;
+ optind++;
+ }
+ else if (optind+1 < argc) /* unattached argument */
+ {
+ *ret_optarg = argv[optind+1];
+ optind+=2;
+ }
+ else Die("Option %s requires an argument\n%s", opt[opti].name, usage);
+
+ optptr = NULL; /* can't concatenate after an argument */
+ }
+ else /* sqdARG_NONE */
+ {
+ *ret_optarg = NULL;
+ if (*(optptr+1) != '\0') /* concatenation */
+ optptr++;
+ else
+ {
+ optind++; /* move to next field */
+ optptr = NULL;
+ }
+ }
+
+ }
+
+ /* Type check the argument, if there is one
+ */
+ if (opt[opti].argtype != sqdARG_NONE)
+ {
+ if (opt[opti].argtype == sqdARG_INT && ! IsInt(*ret_optarg))
+ Die("Option %s requires an integer argument\n%s",
+ opt[opti].name, usage);
+ else if (opt[opti].argtype == sqdARG_FLOAT && ! IsReal(*ret_optarg))
+ Die("Option %s requires a numerical argument\n%s",
+ opt[opti].name, usage);
+ else if (opt[opti].argtype == sqdARG_CHAR && strlen(*ret_optarg) != 1)
+ Die("Option %s requires a single-character argument\n%s",
+ opt[opti].name, usage);
+ /* sqdARG_STRING is always ok, no type check necessary */
+ }
+
+ *ret_optind = optind;
+ return 1;
+}
+
+
+
+#ifdef GETOPT_TESTDRIVER
+/* cc -DGETOPT_TESTDRIVER -L ~/lib/squid.linux/ getopt.c -lsquid
+ */
+struct opt_s OPTIONS[] = {
+ { "--test1", FALSE, sqdARG_INT },
+ { "--test2", FALSE, sqdARG_FLOAT },
+ { "--test3", FALSE, sqdARG_STRING },
+ { "--test4", FALSE, sqdARG_CHAR },
+ { "-a", TRUE, sqdARG_NONE },
+ { "-b", TRUE, sqdARG_INT },
+};
+#define NOPTIONS (sizeof(OPTIONS) / sizeof(struct opt_s))
+
+int
+main(int argc, char **argv)
+{
+ int optind;
+ char *optarg;
+ char *optname;
+
+ while (Getopt(argc, argv, OPTIONS, NOPTIONS, "Usage/help here",
+ &optind, &optname, &optarg))
+ {
+ printf("Option: index: %d name: %s argument: %s\n",
+ optind, optname, optarg);
+ }
+ while (optind < argc)
+ {
+ printf("Argument: index: %d name: %s\n", optind, argv[optind]);
+ optind++;
+ }
+
+
+}
+
+
+#endif /*GETOPT_TESTDRIVER*/