📄 popt.c
字号:
/*
*
* Written by Erik Troan (ewt@redhat.com).
*
*/
#include <config.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#ifdef HAVE_MMAP
# include <sys/mman.h>
#else
# include "util.h"
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef OS2_NT
# include <io.h>
#endif
#include "popt.h"
struct optionStackEntry {
int argc;
char ** argv;
int next;
char * nextArg;
char * nextCharArg;
struct poptAlias * currAlias;
};
struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH], * os;
char ** leftovers;
int numLeftovers;
int nextLeftover;
struct poptOption * options;
int restLeftover;
char * appName;
struct poptAlias * aliases;
int numAliases;
int flags;
};
poptContext poptGetContext(char * name ,int argc, char ** argv,
struct poptOption * options, int flags) {
poptContext con = malloc(sizeof(*con));
con->os = con->optionStack;
con->os->argc = argc;
con->os->argv = argv;
con->os->currAlias = NULL;
con->os->nextCharArg = NULL;
con->os->nextArg = NULL;
if (flags & POPT_KEEP_FIRST)
con->os->next = 0; /* include argv[0] */
else
con->os->next = 1; /* skip argv[0] */
con->leftovers = malloc(sizeof(char *) * (argc + 1));
con->numLeftovers = 0;
con->nextLeftover = 0;
con->restLeftover = 0;
con->options = options;
con->aliases = NULL;
con->numAliases = 0;
con->flags = 0;
if (!name)
con->appName = NULL;
else
con->appName = strcpy(malloc(strlen(name) + 1), name);
return con;
}
void poptResetContext(poptContext con) {
con->os = con->optionStack;
con->os->currAlias = NULL;
con->os->nextCharArg = NULL;
con->os->nextArg = NULL;
con->os->next = 1; /* skip argv[0] */
con->numLeftovers = 0;
con->nextLeftover = 0;
con->restLeftover = 0;
}
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt(poptContext con) {
char * optString, * chptr, * localOptString;
char * longArg = NULL;
char * origOptString;
long aLong;
char * end;
struct poptOption * opt = NULL;
int done = 0;
int i;
while (!done) {
while (!con->os->nextCharArg && con->os->next == con->os->argc
&& con->os > con->optionStack)
con->os--;
if (!con->os->nextCharArg && con->os->next == con->os->argc)
return -1;
if (!con->os->nextCharArg) {
origOptString = con->os->argv[con->os->next++];
if (con->restLeftover || *origOptString != '-') {
con->leftovers[con->numLeftovers++] = origOptString;
continue;
}
if (!origOptString[0])
return POPT_ERROR_BADOPT;
/* Make a copy we can hack at */
localOptString = optString =
strcpy(malloc(strlen(origOptString) + 1),
origOptString);
if (optString[1] == '-' && !optString[2]) {
con->restLeftover = 1;
free(localOptString);
continue;
} else if (optString[1] == '-') {
optString += 2;
if (!con->os->currAlias || !con->os->currAlias->longName ||
strcmp(con->os->currAlias->longName, optString)) {
i = con->numAliases - 1;
while (i >= 0 && (!con->aliases[i].longName ||
strcmp(con->aliases[i].longName, optString))) i--;
if (i >= 0) {
free(localOptString);
if ((con->os - con->optionStack + 1)
== POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
con->os++;
con->os->next = 0;
con->os->nextArg = con->os->nextCharArg = NULL;
con->os->currAlias = con->aliases + i;
con->os->argc = con->os->currAlias->argc;
con->os->argv = con->os->currAlias->argv;
continue;
}
}
chptr = optString;
while (*chptr && *chptr != '=') chptr++;
if (*chptr == '=') {
longArg = origOptString + (chptr - localOptString) + 1;
*chptr = '\0';
}
opt = con->options;
while (opt->longName || opt->shortName) {
if (opt->longName && !strcmp(optString, opt->longName))
break;
opt++;
}
if (!opt->longName && !opt->shortName) {
free(localOptString);
return POPT_ERROR_BADOPT;
}
} else
con->os->nextCharArg = origOptString + 1;
free(localOptString);
}
if (con->os->nextCharArg) {
origOptString = con->os->nextCharArg;
con->os->nextCharArg = NULL;
if (!con->os->currAlias || *origOptString !=
con->os->currAlias->shortName) {
i = con->numAliases - 1;
while (i >= 0 &&
con->aliases[i].shortName != *origOptString) i--;
if (i >= 0) {
if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
/* We'll need this on the way out */
origOptString++;
if (*origOptString)
con->os->nextCharArg = origOptString;
con->os++;
con->os->next = 0;
con->os->nextArg = con->os->nextCharArg = NULL;
con->os->currAlias = con->aliases + i;
con->os->argc = con->os->currAlias->argc;
con->os->argv = con->os->currAlias->argv;
continue;
}
}
opt = con->options;
while ((opt->longName || opt->shortName) &&
*origOptString != opt->shortName) opt++;
if (!opt->longName && !opt->shortName) return POPT_ERROR_BADOPT;
origOptString++;
if (*origOptString)
con->os->nextCharArg = origOptString;
}
if (opt->arg && opt->argInfo == POPT_ARG_NONE)
*((int *)opt->arg) = 1;
else if (opt->argInfo != POPT_ARG_NONE) {
if (longArg) {
con->os->nextArg = longArg;
} else if (con->os->nextCharArg) {
con->os->nextArg = con->os->nextCharArg;
con->os->nextCharArg = NULL;
} else {
while (con->os->next == con->os->argc &&
con->os > con->optionStack)
con->os--;
if (con->os->next == con->os->argc)
return POPT_ERROR_NOARG;
con->os->nextArg = con->os->argv[con->os->next++];
}
if (opt->arg) {
switch (opt->argInfo) {
case POPT_ARG_STRING:
*((char **) opt->arg) = con->os->nextArg;
break;
case POPT_ARG_INT:
case POPT_ARG_LONG:
aLong = strtol(con->os->nextArg, &end, 0);
if (*end)
return POPT_ERROR_BADNUMBER;
if (aLong == LONG_MIN || aLong == LONG_MAX)
return POPT_ERROR_OVERFLOW;
if (opt->argInfo == POPT_ARG_LONG) {
*((long *) opt->arg) = aLong;
} else {
if (aLong > INT_MAX || aLong < INT_MIN)
return POPT_ERROR_OVERFLOW;
*((int *) opt->arg) =aLong;
}
break;
default:
printf("option type not implemented in popt\n");
exit(1);
}
}
}
if (opt->val) done = 1;
}
return opt->val;
}
char * poptGetOptArg(poptContext con) {
char * ret = con->os->nextArg;
con->os->nextArg = NULL;
return ret;
}
char * poptGetArg(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
return (con->leftovers[con->nextLeftover++]);
}
char * poptPeekArg(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
return (con->leftovers[con->nextLeftover]);
}
char ** poptGetArgs(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
/* some apps like [like RPM ;-) ] need this NULL terminated */
con->leftovers[con->numLeftovers] = NULL;
return (con->leftovers + con->nextLeftover);
}
void poptFreeContext(poptContext con) {
int i;
for (i = 0; i < con->numAliases; i++) {
free(con->aliases[i].longName);
free(con->aliases[i].argv);
}
free(con->leftovers);
if (con->appName) free(con->appName);
if (con->aliases) free(con->aliases);
free(con);
}
int poptAddAlias(poptContext con, struct poptAlias newAlias, int flags) {
int aliasNum = con->numAliases++;
struct poptAlias * alias;
/* SunOS won't realloc(NULL, ...) */
if (!con->aliases)
con->aliases = malloc(sizeof(newAlias) * con->numAliases);
else
con->aliases = realloc(con->aliases,
sizeof(newAlias) * con->numAliases);
alias = con->aliases + aliasNum;
*alias = newAlias;
if (alias->longName)
alias->longName = strcpy(malloc(strlen(alias->longName) + 1),
alias->longName);
else
alias->longName = NULL;
return 0;
}
int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) {
char * buf = strcpy(malloc(strlen(s) + 1), s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -