/* * getopt() - command option parsing * * Gunnar Ritter, Freiburg i. Br., Germany, March 2002. */ /* Sccsid @(#)getopt.c 1.6 (gritter) 10/2/04 */ #include "config.h" #include #ifdef HAVE_ALLOCA #ifdef HAVE_ALLOCA_H #include #else /* !HAVE_ALLOCA_H */ #include #endif /* !HAVE_ALLOCA_H */ #endif /* HAVE_ALLOCA */ #include #ifdef HAVE_ALLOCA #define ac_alloc(n) alloca(n) #define ac_free(n) #else /* !HAVE_ALLOCA */ extern void *smalloc(size_t); #define ac_alloc(n) smalloc(n) #define ac_free(n) free(n) #endif /* !HAVE_ALLOCA */ #ifndef HAVE_SSIZE_T typedef int ssize_t; #endif /* !HAVE_SSIZE_T */ /* * One should not think that re-implementing this is necessary, but * * - Some libcs print weird messages. * * - GNU libc getopt() is totally brain-damaged, as it requires special * care _not_ to reorder parameters and can't be told to work correctly * with ':' as first optstring character at all. */ char *optarg; int optind = 1; int opterr = 1; int optopt; static void error(const char *s, int c) { /* * Avoid including , in case its getopt() declaration * conflicts. */ extern ssize_t write(int, const void *, size_t); const char *msg = 0; char *buf, *bp; switch (c) { case '?': msg = ": illegal option -- "; break; case ':': msg = ": option requires an argument -- "; break; } bp = buf = ac_alloc(strlen(s) + strlen(msg) + 2); while (*s) *bp++ = *s++; while (*msg) *bp++ = *msg++; *bp++ = optopt; *bp++ = '\n'; write(2, buf, bp - buf); ac_free(buf); } int getopt(int argc, char *const argv[], const char *optstring) { int colon; static const char *lastp; const char *curp; if (optstring[0] == ':') { colon = 1; optstring++; } else colon = 0; if (lastp) { curp = lastp; lastp = 0; } else { if (optind >= argc || argv[optind] == 0 || argv[optind][0] != '-' || argv[optind][1] == '\0') return -1; if (argv[optind][1] == '-' && argv[optind][2] == '\0') { optind++; return -1; } curp = &argv[optind][1]; } optopt = curp[0] & 0377; while (optstring[0]) { if (optstring[0] == ':') { optstring++; continue; } if ((optstring[0] & 0377) == optopt) { if (optstring[1] == ':') { if (curp[1] != '\0') { optarg = (char *)&curp[1]; optind++; } else { if ((optind += 2) > argc) { if (!colon && opterr) error(argv[0], ':'); return colon ? ':' : '?'; } optarg = argv[optind - 1]; } } else { if (curp[1] != '\0') lastp = &curp[1]; else optind++; optarg = 0; } return optopt; } optstring++; } if (!colon && opterr) error(argv[0], '?'); if (curp[1] != '\0') lastp = &curp[1]; else optind++; optarg = 0; return '?'; }