143 lines
2.7 KiB
C
Executable File
143 lines
2.7 KiB
C
Executable File
/*
|
|
* getopt() - command option parsing
|
|
*
|
|
* Gunnar Ritter, Freiburg i. Br., Germany, March 2002.
|
|
*/
|
|
|
|
/* Sccsid @(#)getopt.c 1.7 (gritter) 12/16/07 */
|
|
|
|
#include "config.h"
|
|
#include <sys/types.h>
|
|
#ifdef HAVE_ALLOCA
|
|
#ifdef HAVE_ALLOCA_H
|
|
#include <alloca.h>
|
|
#else /* !HAVE_ALLOCA_H */
|
|
#include <stdlib.h>
|
|
#endif /* !HAVE_ALLOCA_H */
|
|
#endif /* HAVE_ALLOCA */
|
|
#include <string.h>
|
|
|
|
#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 <unistd.h>, 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 '?';
|
|
}
|