📄 popt.c
字号:
char * bufStart = buf;
char * src, * dst;
char quote = '\0';
int argvAlloced = 5;
char ** argv = malloc(sizeof(*argv) * argvAlloced);
char ** argv2;
int argc = 0;
int i;
src = s;
dst = buf;
argv[argc] = buf;
memset(buf, '\0', strlen(s) + 1);
while (*src) {
if (quote == *src) {
quote = '\0';
} else if (quote) {
if (*src == '\\') {
src++;
if (!*src) {
free(argv);
free(bufStart);
return POPT_ERROR_BADQUOTE;
}
if (*src != quote) *buf++ = '\\';
}
*buf++ = *src;
} else if (isspace(*src)) {
if (*argv[argc]) {
buf++, argc++;
if (argc == argvAlloced) {
argvAlloced += 5;
argv = realloc(argv, sizeof(*argv) * argvAlloced);
}
argv[argc] = buf;
}
} else switch (*src) {
case '"':
case '\'':
quote = *src;
break;
case '\\':
src++;
if (!*src) {
free(argv);
free(bufStart);
return POPT_ERROR_BADQUOTE;
}
/* fallthrough */
default:
*buf++ = *src;
}
src++;
}
if (strlen(argv[argc])) {
argc++;
buf++;
}
argv2 = malloc(argc * sizeof(*argv) + (buf - bufStart));
dst = (char *)argv2;
dst += argc * sizeof(*argv);
memcpy(argv2, argv, argc * sizeof(*argv));
memcpy(dst, bufStart, buf - bufStart);
for (i = 0; i < argc; i++) {
argv2[i] = dst + (argv[i] - bufStart);
}
free(argv);
free(bufStart);
*argvPtr = argv2;
*argcPtr = argc;
return 0;
}
static void configLine(poptContext con, char * line) {
int nameLength = strlen(con->appName);
char * opt;
struct poptAlias alias;
if (strncmp(line, con->appName, nameLength)) return;
line += nameLength;
if (!*line || !isspace(*line)) return;
while (*line && isspace(*line)) line++;
if (!strncmp(line, "alias", 5)) {
line += 5;
if (!*line || !isspace(*line)) return;
while (*line && isspace(*line)) line++;
if (!*line) return;
opt = line;
while (*line && !isspace(*line)) line++;
if (!*line) return;
*line++ = '\0';
while (*line && isspace(*line)) line++;
if (!*line) return;
if (!strlen(opt)) return;
if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
if (opt[0] == '-' && opt[1] == '-') {
alias.longName = opt + 2;
alias.shortName = '\0';
poptAddAlias(con, alias, 0);
} else if (opt[0] == '-' && !opt[2]) {
alias.longName = NULL;
alias.shortName = opt[1];
poptAddAlias(con, alias, 0);
}
}
}
int poptReadConfigFile(poptContext con, char * fn) {
char * file, * chptr, * end;
char * buf, * dst;
int fd, rc;
int fileLength;
fd = open(fn, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
return 0;
else
return POPT_ERROR_ERRNO;
}
fileLength = lseek(fd, 0, SEEK_END);
lseek(fd, 0, 0);
#ifndef HAVE_MMAP
file = (char*) xmalloc (fileLength, "poptReadConfigFile");
if (file == NULL)
#else /* HAVE_MMAP */
file = mmap(NULL, fileLength, PROT_READ, MAP_PRIVATE, fd, 0);
if (file == (void *) -1)
#endif /* HAVE_MMAP */
{
rc = errno;
close(fd);
errno = rc;
return POPT_ERROR_ERRNO;
}
#ifndef HAVE_MMAP
do
{
lseek(fd, 0, 0);
rc = read(fd, file, fileLength);
if (rc == -1 && errno != EINTR)
{
free(file);
return POPT_ERROR_ERRNO;
}
} while (rc != fileLength || (rc == -1 && errno == EINTR));
#endif /* HAVE_MMAP */
close(fd);
dst = buf = malloc(fileLength + 1);
chptr = file;
end = (file + fileLength);
while (chptr < end) {
switch (*chptr) {
case '\n':
*dst = '\0';
dst = buf;
while (*dst && isspace(*dst)) dst++;
if (*dst && *dst != '#') {
configLine(con, dst);
}
chptr++;
break;
case '\\':
*dst++ = *chptr++;
if (chptr < end) {
if (*chptr == '\n')
dst--, chptr++;
/* \ at the end of a line does not insert a \n */
else
*dst++ = *chptr++;
}
break;
default:
*dst++ = *chptr++;
}
}
free (buf);
#ifndef HAVE_MMAP
free (file);
#else
munmap (file, fileLength);
#endif
return 0;
}
int poptReadDefaultConfig(poptContext con, int useEnv) {
char * envName, * envValue, * envValueStart;
char * fn, * home, * chptr;
int rc, skip;
struct poptAlias alias;
if (!con->appName) return 0;
rc = poptReadConfigFile(con, "/etc/popt");
if (rc) return rc;
if ((home = getenv("HOME"))) {
fn = (char *) malloc (strlen(home) + 20);
sprintf(fn, "%s/.popt", home);
rc = poptReadConfigFile(con, fn);
free (fn);
if (rc) return rc;
}
envName = malloc(strlen(con->appName) + 20);
strcpy(envName, con->appName);
chptr = envName;
while (*chptr) {
*chptr = toupper(*chptr);
chptr++;
}
strcat(envName, "_POPT_ALIASES");
if (useEnv && (envValue = getenv(envName))) {
envValue = envValueStart = strcpy(malloc(strlen(envValue) + 1), envValue);
while (envValue && *envValue) {
chptr = strchr(envValue, '=');
if (!chptr) {
envValue = strchr(envValue, '\n');
if (envValue) envValue++;
continue;
}
*chptr = '\0';
skip = 0;
if (!strncmp(envValue, "--", 2)) {
alias.longName = envValue + 2;
alias.shortName = '\0';
} else if (*envValue == '-' && strlen(envValue) == 2) {
alias.longName = NULL;
alias.shortName = envValue[1];
} else {
skip = 1;
}
envValue = chptr + 1;
chptr = strchr(envValue, '\n');
if (chptr) *chptr = '\0';
if (!skip) {
poptParseArgvString(envValue, &alias.argc, &alias.argv);
poptAddAlias(con, alias, 0);
}
if (chptr)
envValue = chptr + 1;
else
envValue = NULL;
}
free(envValueStart);
}
free (envName);
return 0;
}
char * poptBadOption(poptContext con, int flags) {
struct optionStackEntry * os;
if (flags & POPT_BADOPTION_NOALIAS)
os = con->optionStack;
else
os = con->os;
return os->argv[os->next - 1];
}
#define POPT_ERROR_NOARG -10
#define POPT_ERROR_BADOPT -11
#define POPT_ERROR_OPTSTOODEEP -13
#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
const char * poptStrerror(const int error) {
switch (error) {
case POPT_ERROR_NOARG:
return "missing argument";
case POPT_ERROR_BADOPT:
return "unknown option";
case POPT_ERROR_OPTSTOODEEP:
return "aliases nested too deeply";
case POPT_ERROR_BADQUOTE:
return "error in paramter quoting";
case POPT_ERROR_BADNUMBER:
return "invalid numeric value";
case POPT_ERROR_OVERFLOW:
return "number too large or too small";
case POPT_ERROR_ERRNO:
#ifdef HAVE_STRERROR
return strerror (errno);
#else
{
extern int sys_nerr;
extern char *sys_errlist [];
if ((0 <= errno) && (errno < sys_nerr))
return sys_errlist[errno];
else
return "strange errno";
}
#endif
default:
return "unknown error";
}
}
int poptStuffArgs(poptContext con, char ** argv) {
int i;
if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
for (i = 0; argv[i]; i++);
con->os++;
con->os->next = 0;
con->os->nextArg = con->os->nextCharArg = NULL;
con->os->currAlias = NULL;
con->os->argc = i;
con->os->argv = argv;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -