Spaces:
Running
Running
/* | |
* parseargs.cc | |
* | |
* Command line argument parser. | |
* | |
* Copyright 1996-2003 Glyph & Cog, LLC | |
*/ | |
/*======================================================================== | |
Modified under the Poppler project - http://poppler.freedesktop.org | |
Poppler project changes to this file are under the GPLv2 or later license | |
All changes made under the Poppler project to this file are licensed | |
under GPL version 2 or later | |
Copyright (C) 2008, 2009, 2018 Albert Astals Cid <[email protected]> | |
Copyright (C) 2011, 2012 Adrian Johnson <[email protected]> | |
To see a description of the changes please see the Changelog file that | |
came with your tarball or type make ChangeLog if you are building from git | |
========================================================================*/ | |
static const ArgDesc *findArg(const ArgDesc *args, char *arg); | |
static bool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[]); | |
bool parseArgs(const ArgDesc *args, int *argc, char *argv[]) | |
{ | |
const ArgDesc *arg; | |
int i, j; | |
bool ok; | |
ok = true; | |
i = 1; | |
while (i < *argc) { | |
if (!strcmp(argv[i], "--")) { | |
--*argc; | |
for (j = i; j < *argc; ++j) { | |
argv[j] = argv[j + 1]; | |
} | |
break; | |
} else if ((arg = findArg(args, argv[i]))) { | |
if (!grabArg(arg, i, argc, argv)) { | |
ok = false; | |
} | |
} else { | |
++i; | |
} | |
} | |
return ok; | |
} | |
void printUsage(const char *program, const char *otherArgs, const ArgDesc *args) | |
{ | |
const ArgDesc *arg; | |
const char *typ; | |
int w, w1; | |
w = 0; | |
for (arg = args; arg->arg; ++arg) { | |
if ((w1 = strlen(arg->arg)) > w) { | |
w = w1; | |
} | |
} | |
fprintf(stderr, "Usage: %s [options]", program); | |
if (otherArgs) { | |
fprintf(stderr, " %s", otherArgs); | |
} | |
fprintf(stderr, "\n"); | |
for (arg = args; arg->arg; ++arg) { | |
fprintf(stderr, " %s", arg->arg); | |
w1 = 9 + w - strlen(arg->arg); | |
switch (arg->kind) { | |
case argInt: | |
case argIntDummy: | |
typ = " <int>"; | |
break; | |
case argFP: | |
case argFPDummy: | |
typ = " <fp>"; | |
break; | |
case argString: | |
case argStringDummy: | |
case argGooString: | |
typ = " <string>"; | |
break; | |
case argFlag: | |
case argFlagDummy: | |
default: | |
typ = ""; | |
break; | |
} | |
fprintf(stderr, "%-*s", w1, typ); | |
if (arg->usage) { | |
fprintf(stderr, ": %s", arg->usage); | |
} | |
fprintf(stderr, "\n"); | |
} | |
} | |
static const ArgDesc *findArg(const ArgDesc *args, char *arg) | |
{ | |
const ArgDesc *p; | |
for (p = args; p->arg; ++p) { | |
if (p->kind < argFlagDummy && !strcmp(p->arg, arg)) { | |
return p; | |
} | |
} | |
return nullptr; | |
} | |
static bool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[]) | |
{ | |
int n; | |
int j; | |
bool ok; | |
ok = true; | |
n = 0; | |
switch (arg->kind) { | |
case argFlag: | |
*(bool *)arg->val = true; | |
n = 1; | |
break; | |
case argInt: | |
if (i + 1 < *argc && isInt(argv[i + 1])) { | |
*(int *)arg->val = atoi(argv[i + 1]); | |
n = 2; | |
} else { | |
ok = false; | |
n = 1; | |
} | |
break; | |
case argFP: | |
if (i + 1 < *argc && isFP(argv[i + 1])) { | |
*(double *)arg->val = gatof(argv[i + 1]); | |
n = 2; | |
} else { | |
ok = false; | |
n = 1; | |
} | |
break; | |
case argString: | |
if (i + 1 < *argc) { | |
strncpy((char *)arg->val, argv[i + 1], arg->size - 1); | |
((char *)arg->val)[arg->size - 1] = '\0'; | |
n = 2; | |
} else { | |
ok = false; | |
n = 1; | |
} | |
break; | |
case argGooString: | |
if (i + 1 < *argc) { | |
((GooString *)arg->val)->Set(argv[i + 1]); | |
n = 2; | |
} else { | |
ok = false; | |
n = 1; | |
} | |
break; | |
default: | |
fprintf(stderr, "Internal error in arg table\n"); | |
n = 1; | |
break; | |
} | |
if (n > 0) { | |
*argc -= n; | |
for (j = i; j < *argc; ++j) { | |
argv[j] = argv[j + n]; | |
} | |
} | |
return ok; | |
} | |
bool isInt(const char *s) | |
{ | |
if (*s == '-' || *s == '+') { | |
++s; | |
} | |
while (isdigit(*s)) { | |
++s; | |
} | |
if (*s) { | |
return false; | |
} | |
return true; | |
} | |
bool isFP(const char *s) | |
{ | |
int n; | |
if (*s == '-' || *s == '+') { | |
++s; | |
} | |
n = 0; | |
while (isdigit(*s)) { | |
++s; | |
++n; | |
} | |
if (*s == '.') { | |
++s; | |
} | |
while (isdigit(*s)) { | |
++s; | |
++n; | |
} | |
if (n > 0 && (*s == 'e' || *s == 'E')) { | |
++s; | |
if (*s == '-' || *s == '+') { | |
++s; | |
} | |
n = 0; | |
if (!isdigit(*s)) { | |
return false; | |
} | |
do { | |
++s; | |
} while (isdigit(*s)); | |
} | |
if (*s) { | |
return false; | |
} | |
return true; | |
} | |