|
From: <kin...@us...> - 2025-09-17 09:58:14
|
Revision: 7440
http://sourceforge.net/p/teem/code/7440
Author: kindlmann
Date: 2025-09-17 09:58:09 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
one API CHANGE but then lots of variable renaming (such as parm to hparm, and using less crytically short variable names inside parseHest.c) as part of making sense of hest code. The API CHANGE is that the hestSource* enum no longer has hestSourceUser; it was split into hestSourceCommandLine and hestSourceReponseFile. But to reduce disruption, a new hestSourceUser() helper function returns non-zero for those two source enum values; this affects lots of Teem-using code. This change sets the stage for the ongoing rewrite of hestParse
Modified Paths:
--------------
teem/trunk/src/bin/gprobe.c
teem/trunk/src/bin/ilk.c
teem/trunk/src/bin/overrgb.c
teem/trunk/src/bin/puller-with-Deft.c
teem/trunk/src/bin/puller.c
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parseHest.c
teem/trunk/src/hest/privateHest.h
teem/trunk/src/hest/test/ex3.c
teem/trunk/src/hest/test/ex6.c
teem/trunk/src/hest/usage.c
teem/trunk/src/meet/test/strace.c
teem/trunk/src/unrrdu/axinfo.c
teem/trunk/src/unrrdu/axinsert.c
teem/trunk/src/unrrdu/basinfo.c
teem/trunk/src/unrrdu/ilk.c
teem/trunk/src/unrrdu/make.c
teem/trunk/src/unrrdu/quantize.c
Modified: teem/trunk/src/bin/gprobe.c
===================================================================
--- teem/trunk/src/bin/gprobe.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/gprobe.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -438,7 +438,7 @@
/* we got the whole stack blar parm here */
gotOld = AIR_FALSE;
for (nsi = 0; nsi < NON_SBP_OPT_NUM; nsi++) {
- gotOld |= (hestSourceUser == hopt[nonSbpOpi[nsi]].source);
+ gotOld |= hestSourceUser(hopt[nonSbpOpi[nsi]].source);
}
if (gotOld) {
fprintf(stderr,
@@ -446,7 +446,7 @@
"scale-space options (used",
me);
for (nsi = 0; nsi < NON_SBP_OPT_NUM; nsi++) {
- if (hestSourceUser == hopt[nonSbpOpi[nsi]].source) {
+ if (hestSourceUser(hopt[nonSbpOpi[nsi]].source)) {
fprintf(stderr, " -%s", hopt[nonSbpOpi[nsi]].flag);
}
}
Modified: teem/trunk/src/bin/ilk.c
===================================================================
--- teem/trunk/src/bin/ilk.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/ilk.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -151,7 +151,7 @@
bkg = _bkg;
}
} else {
- if (hestSourceUser == hopt[bkgIdx].source) {
+ if (hestSourceUser(hopt[bkgIdx].source)) {
fprintf(stderr,
"%s: WARNING: got %u background colors, but with boundary %s, "
"they will not be used\n",
Modified: teem/trunk/src/bin/overrgb.c
===================================================================
--- teem/trunk/src/bin/overrgb.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/overrgb.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -132,7 +132,7 @@
return 1;
}
- if (hestSourceUser == hopt[srgbIdx].source && !nrrdFormatPNG->available()) {
+ if (hestSourceUser(hopt[srgbIdx].source) && !nrrdFormatPNG->available()) {
fprintf(stderr,
"%s: wanted to store sRGB intent \"%s\" in PNG output, but "
"this Teem build does not support the PNG file format.",
@@ -254,7 +254,7 @@
rgbaD += 4;
}
- if (hestSourceUser == hopt[srgbIdx].source) {
+ if (hestSourceUser(hopt[srgbIdx].source)) {
/* HEY copied to unrrdu/quantize.c */
nio = nrrdIoStateNew();
airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways);
Modified: teem/trunk/src/bin/puller-with-Deft.c
===================================================================
--- teem/trunk/src/bin/puller-with-Deft.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/puller-with-Deft.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -1124,13 +1124,13 @@
airMopError(mop);
return 1;
}
- if (!kssFinished && hestSourceUser == hopt[kssOpi].source) {
+ if (!kssFinished && hestSourceUser(hopt[kssOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified blurring kernels\n\n\n",
me, hopt[kssOpi].flag);
}
- if (!bspFinished && hestSourceUser == hopt[bspOpi].source) {
+ if (!bspFinished && hestSourceUser(hopt[bspOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified boundary specs\n\n\n",
Modified: teem/trunk/src/bin/puller.c
===================================================================
--- teem/trunk/src/bin/puller.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/puller.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -357,13 +357,13 @@
airMopError(mop);
return 1;
}
- if (!kssFinished && hestSourceUser == hopt[kssOpi].source) {
+ if (!kssFinished && hestSourceUser(hopt[kssOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified blurring kernels\n\n\n",
me, hopt[kssOpi].flag);
}
- if (!bspFinished && hestSourceUser == hopt[bspOpi].source) {
+ if (!bspFinished && hestSourceUser(hopt[bspOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified boundary specs\n\n\n",
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/hest/hest.h 2025-09-17 09:58:09 UTC (rev 7440)
@@ -45,13 +45,13 @@
******** hestSource* enum
**
** records whether the info to satisfy a particular option came from the default or from
-** the user (command-line or response file). Distinguishing command-line from response
-** file would take a much more significant code restructuring
+** the user: command-line or response file.
*/
enum {
- hestSourceUnknown, /* 0 */
- hestSourceDefault, /* 1 */
- hestSourceUser, /* 2 */
+ hestSourceUnknown, /* 0 */
+ hestSourceDefault, /* 1 */
+ hestSourceCommandLine, /* 2 (formerly called hestSourceUser) */
+ hestSourceResponseFile, /* 3 */
hestSourceLast
};
@@ -74,17 +74,16 @@
multiple parameter options. A non-zero return value is considered an error. Error
message goes in the err string */
void *(*destroy)(void *ptr);
- /* if non-NULL, this is the destructor that will be called by hestParseFree() (or by
- hestParse() if there is an error midway through parsing). The argument is NOT the
- same as passed to parse(): it is the result of dereferencing the argument to parse()
- */
+ /* if non-NULL, the destructor that will be called by hestParseFree() (or by
+ hestParse() if there is an error during parsing). The argument is NOT the same as
+ passed to parse(): it is the result of dereferencing the argument to parse() */
} hestCB;
/*
******** hestOpt struct
**
-** information which specifies one command-line option,
-** and describes it how it was parsed
+** information which specifies one command-line option, records state used during
+** parsing, and provides summary output info following parsing.
*/
typedef struct {
/* --------------------- "input" fields
@@ -97,7 +96,7 @@
int max; /* max # of parameters for option,
or -1 for "there is no max; # parms is unbounded" */
void *valueP; /* storage of parsed values */
- char *dflt, /* default value written out as string */
+ char *dflt, /* default value(s) written out as string */
*info; /* description to be printed with "glossary" info */
unsigned int *sawP; /* used ONLY for multiple variable parameter options
(min < max >= 2): storage of # of parsed values */
@@ -128,46 +127,50 @@
array of strings
3: free((*valueP)[i]) and free(*valueP), because it is a dynamically
allocated array of strings */
- /* Since hest's beginning, the basic container for a set of options was an array of
- hestOpt structs (not pointers to them, which rules out argv-style NULL-termination of
- the array), also unfortunately with no other top-level container (which is why
- helpWanted below is set only in the first hestOpt of the array). hestOptAdd has
- historically reallocated the entire array, incrementing the length only by one with
- each call, while maintaining a single terminating hestOpt, wherein some fields were set
- to special values to indicate termination. With the 2023 code revisit, that was deemed
- even uglier than this hack: the first hestOpt now stores here in arrAlloc the allocated
- length of the hestOpt array, and in arrLen the number of hestOpts actually used and
- set. This facilitates implementing something much like an airArray, but without the
- burden of extra calls for the user (like airArrayLenIncr), nor new kinds of containers
- for hest and its users to manage: it is just the same array of hestOpt structs */
+ /* Since hest's beginning in 2002, the basic container for a set of options was an
+ array of hestOpt structs (not pointers to them, which rules out argv-style
+ NULL-termination of the array), also unfortunately with no other top-level container
+ or hestContext (which is why helpWanted below is set only in the first hestOpt of the
+ array). hestOptAdd has historically reallocated the entire array, incrementing the
+ length only by one with each call, while maintaining a single terminating hestOpt,
+ wherein some fields were set to special values to indicate termination. With the 2023
+ code revisit, that was deemed even uglier than the new and current hack: the first
+ hestOpt now stores here in arrAlloc the allocated length of the hestOpt array, and in
+ arrLen the number of hestOpts actually used and set. This facilitates implementing
+ something much like an airArray, but without the burden of extra calls for the user
+ (like airArrayLenIncr), nor new kinds of containers for hest and its users to manage:
+ it is just the same array of hestOpt structs */
unsigned int arrAlloc, arrLen;
/* --------------------- Output
Things set/allocated by hestParse. */
- int source; /* from the hestSource* enum; from whence was this information learned,
- else hestSourceUnknown if not */
- char *parmStr; /* if non-NULL: a string (freed by hestParseFree) from which hestParse
- ultimately parsed whatever values were set in *valueP. All the
- parameters associated with this option are joined (with " " separation)
- into this single string. hestParse has always formed this string
- internally as part of its operation, but only belatedly (in 2023) is a
- copy of that string being made available here to the caller. Note that
- in the case of single variable parameter options used without a
- parameter, the value stored will be "inverted" from the string here. */
- int helpWanted; /* hestParse() saw something (like "--help") in one of the given
- arguments that looks like a call for help (and respectDashDashHelp is
- set in the hestParm), so it recorded that here. There is unfortunately
- no other top-level output container for info generated by hestParse(),
- so this field is going to be set only in the *first* hestOpt passed to
- hestParse(), even though that hestOpt has no particular relation to
- where hestParse() saw the call for help. */
+ /* from the hestSource* enum; from whence was this information learned, else
+ hestSourceUnknown if not */
+ int source;
+ /* if parseStr is non-NULL: a string (freed by hestParseFree) that is a lot like the
+ string (storing zero or many parameters), from which hestParse ultimately parsed
+ whatever values were set in *valueP above. Internally, hest maintains an argc,argv-like
+ representation of the info to parse, but here it is joined back together into a
+ space-delimited single string. Note that in the case of single variable parameter
+ options used without a parameter, the value stored will be "inverted" from the string
+ here. */
+ char *parmStr;
+ /* helpWanted indicates that hestParse() saw something (like "--help") in one of the
+ given arguments that looks like a call for help, and that respectDashDashHelp is set in
+ the hestParm. There is unfortunately no other top-level output container for info
+ generated by hestParse(), so this field is going to be set only in the *first* hestOpt
+ passed to hestParse(), even though that hestOpt has no particular relation to where
+ hestParse() saw the call for help. */
+ int helpWanted;
} hestOpt;
/*
******** hestParm struct
**
-** parameters to control behavior of hest functions.
+** parameters to control behavior of hest functions. Not to be confused with the
+** "parameters" to a hestOpt from which it parses values. Code should use "hparm" for
+** the pointer to this struct.
**
** GK: Don't even think about storing per-parse state in here.
*/
@@ -175,7 +178,7 @@
int verbosity, /* verbose diagnostic messages to stdout */
respFileEnable, /* whether or not to use response files */
elideSingleEnumType, /* if type is airTypeEnum, and if it's a single fixed parameter
- option, then don't bother printing the type information as
+ option, then don't bother printing the type information as
part of hestGlossary() */
elideSingleOtherType, /* like above, but for airTypeOther */
elideSingleOtherDefault, /* don't display default for single fixed airTypeOther
@@ -238,11 +241,22 @@
HEST_EXPORT char hestDefaultVarParamStopFlag;
HEST_EXPORT char hestDefaultMultiFlagSep;
+/* argvHest.c */
+HEST_EXPORT hestArg *hestArgNew(void);
+HEST_EXPORT hestArg *hestArgNix(hestArg *harg);
+HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
+HEST_EXPORT void hestArgAddString(hestArg *harg, const char *str);
+HEST_EXPORT hestArgVec *hestArgVecNew(void);
+HEST_EXPORT void hestArgVecAppendString(hestArgVec *havec, const char *str);
+HEST_EXPORT void hestArgVecPrint(const hestArgVec *havec);
+HEST_EXPORT hestInput *hestInputNew(void);
+
/* methodsHest.c */
HEST_EXPORT const int hestPresent;
+HEST_EXPORT int hestSourceUser(int src);
HEST_EXPORT hestParm *hestParmNew(void);
-HEST_EXPORT hestParm *hestParmFree(hestParm *parm);
-HEST_EXPORT void *hestParmFree_vp(void *parm);
+HEST_EXPORT hestParm *hestParmFree(hestParm *hparm);
+HEST_EXPORT void *hestParmFree_vp(void *hparm);
HEST_EXPORT int hestParmColumnsIoctl(hestParm *hparm, unsigned int nonIoctlColumns);
HEST_EXPORT void hestOptSingleSet(hestOpt *opt, const char *flag, const char *name,
int type, unsigned int min, int max, void *valueP,
@@ -269,34 +283,35 @@
/* parseHest.c */
HEST_EXPORT int hestParse(hestOpt *opt, int argc, const char **argv, char **errP,
- const hestParm *parm);
+ const hestParm *hparm);
HEST_EXPORT void *hestParseFree(hestOpt *opt);
HEST_EXPORT void hestParseOrDie(hestOpt *opt, int argc, const char **argv,
- hestParm *parm, const char *me, const char *info,
+ hestParm *hparm, const char *me, const char *info,
int doInfo, int doUsage, int doGlossary);
/* usage.c */
HEST_EXPORT void _hestPrintStr(FILE *f, unsigned int indent, unsigned int already,
unsigned int width, const char *_str, int bslash);
-HEST_EXPORT int hestMinNumArgs(hestOpt *opt);
-HEST_EXPORT void hestUsage(FILE *file, hestOpt *opt, const char *argv0,
- const hestParm *parm);
-HEST_EXPORT void hestGlossary(FILE *file, hestOpt *opt, const hestParm *parm);
+HEST_EXPORT int hestMinNumArgs(const hestOpt *opt);
+HEST_EXPORT void hestUsage(FILE *file, const hestOpt *opt, const char *argv0,
+ const hestParm *hparm);
+HEST_EXPORT void hestGlossary(FILE *file, const hestOpt *opt, const hestParm *hparm);
HEST_EXPORT void hestInfo(FILE *file, const char *argv0, const char *info,
- const hestParm *parm);
+ const hestParm *hparm);
/* adders.c */
HEST_EXPORT void hestOptAddDeclsPrint(FILE *f);
/* Many many non-var-args alternatives to hestOptAdd, also usefully type-specific for the
type of value to be parsed in a way that hestOptAdd_nva cannot match. These capture all
-the common uses (and then some) of hest within Teem. They can be categorized, like
-hestOpt->kind, in terms of the min, max number of (type T) parameters to the option:
+the common uses (and then some) of hest within Teem. They are named according
+to kind, and according to the type T parameters to the option:
- min == max == 0 hestOptAdd_Flag (stand-alone flag; no parameters)
- min == max == 1 hestOptAdd_1_T single fixed parameter
- min == max >= 2 hestOptAdd_{2,3,4,N}_T multiple fixed parameters
- min == 0; max == 1 hestOptAdd_1v_T single variable parameter
- min < max; max >= 2 hestOptAdd_Nv_T multiple variable parameters
+min, max function family kind description
+min == max == 0 hestOptAdd_Flag 1 (stand-alone flag; no parameters)
+min == max == 1 hestOptAdd_1_T 2 single fixed parameter
+min == max >= 2 hestOptAdd_{2,3,4,N}_T 3 multiple fixed parameters
+min == 0; max == 1 hestOptAdd_1v_T 4 single variable parameter
+min < max; max >= 2 hestOptAdd_Nv_T 5 multiple variable parameters
An airEnum* is passed for _Enum options; or a hestCB* for _Other options. The number of
parameters *sawP that hestParm saw on the command-line is passed for the _Nv_ options.
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -27,6 +27,11 @@
const int hestPresent = 42;
+int
+hestSourceUser(int src) {
+ return (hestSourceCommandLine == src || hestSourceResponseFile == src);
+}
+
/* INCR is like airArray->incr: granularity with which we (linearly) reallocate the
hestOpt array. Very few uses of hest within Teem use more than 32 options. Hopefully
this avoids all the reallocations in the past action of hestOptAdd and the like. */
@@ -34,33 +39,24 @@
hestParm *
hestParmNew() {
- hestParm *parm;
+ hestParm *hparm;
- parm = AIR_CALLOC(1, hestParm);
- assert(parm);
- parm->verbosity = hestDefaultVerbosity;
- parm->respFileEnable = hestDefaultRespFileEnable;
- parm->elideSingleEnumType = hestDefaultElideSingleEnumType;
- parm->elideSingleOtherType = hestDefaultElideSingleOtherType;
- parm->elideSingleOtherDefault = hestDefaultElideSingleOtherDefault;
- parm->greedySingleString = hestDefaultGreedySingleString;
- parm->elideSingleNonExistFloatDefault = hestDefaultElideSingleNonExistFloatDefault;
- parm->elideMultipleNonExistFloatDefault = hestDefaultElideMultipleNonExistFloatDefault;
- parm->elideSingleEmptyStringDefault = hestDefaultElideSingleEmptyStringDefault;
- parm->elideMultipleEmptyStringDefault = hestDefaultElideMultipleEmptyStringDefault;
- parm->cleverPluralizeOtherY = hestDefaultCleverPluralizeOtherY;
- parm->columns = hestDefaultColumns;
- parm->respFileFlag = hestDefaultRespFileFlag;
- parm->respFileComment = hestDefaultRespFileComment;
- parm->varParamStopFlag = hestDefaultVarParamStopFlag;
- parm->multiFlagSep = hestDefaultMultiFlagSep;
- /* for these most recent addition to the hestParm,
- abstaining from added yet another default global variable */
- parm->dieLessVerbose = AIR_FALSE;
- parm->noBlankLineBeforeUsage = AIR_FALSE;
+ hparm = AIR_CALLOC(1, hestParm);
+ assert(hparm);
+ hparm->verbosity = hestDefaultVerbosity;
+ hparm->respFileEnable = hestDefaultRespFileEnable;
+ hparm->elideSingleEnumType = hestDefaultElideSingleEnumType;
+ hparm->elideSingleOtherType = hestDefaultElideSingleOtherType;
+ hparm->elideSingleOtherDefault = hestDefaultElideSingleOtherDefault;
+ hparm->greedySingleString = hestDefaultGreedySingleString;
+ hparm->elideSingleNonExistFloatDefault = hestDefaultElideSingleNonExistFloatDefault;
+ hparm->elideMultipleNonExistFloatDefault
+ = hestDefaultElideMultipleNonExistFloatDefault;
+ hparm->elideSingleEmptyStringDefault = hestDefaultElideSingleEmptyStringDefault;
+ hparm->elideMultipleEmptyStringDefault = hestDefaultElideMultipleEmptyStringDefault;
/* It would be really nice for parm->respectDashDashHelp to default to true:
widespread conventions say what "--help" should mean e.g. https://clig.dev/#help
- HOWEVER, the problem is with how hestParse is called and how the return
+ HOWEVER, the problem is with how hestParse is called and how its return value
is interpreted as a boolean:
- zero has meant that hestParse could set values for all the options (either
from the command-line or from supplied defaults), and
@@ -70,17 +66,29 @@
is the precedent, so we have to work with it by default.
Now, with parm->respectDashDashHelp, upon seeing "--help", hestParse returns 0,
and sets helpWanted in the first hestOpt, and the caller will have to know
- to check for that. This logic is handled by hestParseOrDie, but maybe in
- the future there can be a different top-level parser function that turns on
- parm->respectDashDashHelp and knows how to check the results */
- parm->respectDashDashHelp = AIR_FALSE;
- return parm;
+ to check for that. This logic is handled by hestParse but maybe in the future there
+ can be a different top-level parser function that turns on parm->respectDashDashHelp
+ and knows how to check the results */
+ hparm->respectDashDashHelp = AIR_FALSE;
+ hparm->noArgsIsNoProblem = hestDefaultNoArgsIsNoProblem;
+ hparm->greedySingleString = hestDefaultGreedySingleString;
+ hparm->cleverPluralizeOtherY = hestDefaultCleverPluralizeOtherY;
+ /* for these most recent addition to the hestParm,
+ abstaining from added yet another default global variable */
+ hparm->dieLessVerbose = AIR_FALSE;
+ hparm->noBlankLineBeforeUsage = AIR_FALSE;
+ hparm->columns = hestDefaultColumns;
+ hparm->respFileFlag = hestDefaultRespFileFlag;
+ hparm->respFileComment = hestDefaultRespFileComment;
+ hparm->varParamStopFlag = hestDefaultVarParamStopFlag;
+ hparm->multiFlagSep = hestDefaultMultiFlagSep;
+ return hparm;
}
hestParm *
-hestParmFree(hestParm *parm) {
+hestParmFree(hestParm *hparm) {
- airFree(parm);
+ airFree(hparm);
return NULL;
}
@@ -387,8 +395,8 @@
/* experiments in adding a nixer/free-er that exactly matches the airMopper type,
as part of trying to avoid all "undefined behavior" */
void *
-hestParmFree_vp(void *_parm) {
- return AIR_VOIDP(hestParmFree((hestParm *)_parm));
+hestParmFree_vp(void *_hparm) {
+ return AIR_VOIDP(hestParmFree((hestParm *)_hparm));
}
void *
hestOptFree_vp(void *_opt) {
@@ -399,7 +407,7 @@
hestOptCheck(hestOpt *opt, char **errP) {
static const char me[] = "hestOptCheck";
char *err;
- hestParm *parm;
+ hestParm *hparm;
int big;
big = _hestErrStrlen(opt, 0, NULL);
@@ -411,8 +419,8 @@
if (errP) *errP = NULL;
return 1;
}
- parm = hestParmNew();
- if (_hestPanic(opt, err, parm)) {
+ hparm = hestParmNew();
+ if (_hestOptCheck(opt, err, hparm)) {
/* problems */
if (errP) {
/* they did give a pointer address; they'll free it */
@@ -421,12 +429,12 @@
/* they didn't give a pointer address; their loss */
free(err);
}
- hestParmFree(parm);
+ hestParmFree(hparm);
return 1;
}
/* else, no problems */
if (errP) *errP = NULL;
free(err);
- hestParmFree(parm);
+ hestParmFree(hparm);
return 0;
}
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/hest/parseHest.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -22,21 +22,32 @@
#include <string.h>
-#define ME ((parm && parm->verbosity) ? me : "")
+/* A little trickery for error reporting. For many of the functions here, if they hit an
+error and hparm->verbosity is set, then we should reveal the current function name (set
+by convention in `me`). But without verbosity, we hide that function name, so it appears
+that the error is coming from the caller (probably identified as argv[0]). However, that
+means that functions using this `ME` macro should (in defiance of convention) set to `me`
+to `functionname: ` (NOTE the `: `) so that all of that goes away without verbosity. And,
+that means that error message generation here should also defy convention and instead of
+being "%s: what happened" it should just be "%swhat happened" */
+#define ME ((hparm && hparm->verbosity) ? me : "")
/*
argsInResponseFiles()
-returns the number of "args" (i.e. the number of space-separated strings) that will be
-parsed from the response files. The role of this function is solely to simplify the task
-of avoiding memory leaks. By knowing exactly how many args we'll get in the response
-file, then hestParse() can allocate its local argv[] for exactly as long as it needs to
-be, and we can avoid using an airArray. The drawback is that we open and read through
-the response files twice. Alas.
+returns the number of "args" (i.e. the number of AIR_WHITESPACE-separated strings) that
+will be parsed from the response files. The role of this function is solely to simplify
+the task of avoiding memory leaks. By knowing exactly how many args we'll get in the
+response file, then hestParse() can allocate its local argv[] for exactly as long as it
+needs to be, and we can avoid using an airArray. The drawback is that we open and read
+through the response files twice. Alas.
+
+NOTE: Currently, this makes no effort to interpreted quoted strings "like this one" as a
+single arg, and we do not do any VTAB-separating of args here.
*/
static int
argsInResponseFiles(int *argsNumP, int *respFileNumP, const char **argv, char *err,
- const hestParm *parm) {
+ const hestParm *hparm) {
FILE *file;
static const char me[] = "argsInResponseFiles: ";
char line[AIR_STRLEN_HUGE + 1], *pound;
@@ -44,7 +55,7 @@
*argsNumP = 0;
*respFileNumP = 0;
- if (!parm->respFileEnable) {
+ if (!hparm->respFileEnable) {
/* don't do response files; we're done */
return 0;
}
@@ -51,7 +62,7 @@
argIdx = 0;
while (argv /* can be NULL for testing */ && argv[argIdx]) {
- if (parm->respFileFlag == argv[argIdx][0]) {
+ if (hparm->respFileFlag == argv[argIdx][0]) {
/* argv[argIdx] looks like its naming a response file */
/* NOTE: despite the repeated temptation: "-" aka stdin cannot be a response file,
because it is going to be read in twice: once by argsInResponseFiles, and then
@@ -68,7 +79,7 @@
len = airOneLine(file, line, AIR_STRLEN_HUGE + 1);
while (len > 0) {
/* first # (or #-alike char) is turned into line end */
- if ((pound = strchr(line, parm->respFileComment))) {
+ if ((pound = strchr(line, hparm->respFileComment))) {
*pound = '\0';
}
/* count words in line */
@@ -85,14 +96,14 @@
return 0;
}
-/* printArgv prints (for debugging) the given non-const argv array */
+/* prints (for debugging) the given non-const argv array */
static void
printArgv(int argc, char **argv, const char *pfx) {
- int a;
+ int ai;
printf("%sargc=%d : ", pfx ? pfx : "", argc);
- for (a = 0; a < argc; a++) {
- printf("%s%s ", pfx ? pfx : "", argv[a]);
+ for (ai = 0; ai < argc; ai++) {
+ printf("%s%s ", pfx ? pfx : "", argv[ai]);
}
printf("%s\n", pfx ? pfx : "");
}
@@ -101,14 +112,21 @@
copyArgv()
Copies given oldArgv to newArgv, including (if they are enabled) injecting the contents
-of response files. BUT: this stops upon seeing "--help" if parm->respectDashDashHelp.
+of response files. Returns the number of AIR_WHITESPACE-separated arguments in newArgv.
Allocations of the strings in newArgv are remembered (to be airFree'd later) in the given
-pmop. Returns the number of args set in newArgv, and sets sawHelp if saw "--help".
+pmop. Returns the number of args set in newArgv. BUT: upon seeing "--help" if
+parm->respectDashDashHelp, this sets *sawHelp=AIR_TRUE, and then finishes early.
-For a brief moment prior to the 2.0.0 release, this also stopped if it saw "--" (or
-whatever parm->varParamStopFlag implies), but that meant "--" is a brick wall that
-hestParse could never see past. But that misunderstands the relationship between how
-hestParse works and how the world uses "--". According to POSIX guidelines:
+NOTE: like argsInResponseFiles, this is totally naive about quoted strings that appear in
+response files! So "multiple words like this" would be processed as four args, the first
+one starting with '"', and the last one ending with '"'. The same naivety means that the
+'#' character is considered to mark the beginning of a comment, EVEN IF THAT '#' is
+inside a string. Sorry. (This is why hest parsing is being re-written ...)
+
+For a brief moment in 2023, this also stopped if it saw "--" (or whatever
+parm->varParamStopFlag implies), but that meant "--" is a brick wall that hestParse could
+never see past. But that misunderstands the relationship between how hestParse works and
+how the world uses "--". According to POSIX guidelines:
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_01
the elements of argv can be first "options" and then "operands", where "options" are
indicated by something starting with '-', and may have 0 or more "option-arguments".
@@ -131,7 +149,7 @@
what "--" should mean.
*/
static int
-copyArgv(int *sawHelp, char **newArgv, const char **oldArgv, const hestParm *parm,
+copyArgv(int *sawHelp, char **newArgv, const char **oldArgv, const hestParm *hparm,
airArray *pmop) {
static const char me[] = "copyArgv";
char line[AIR_STRLEN_HUGE + 1], *pound;
@@ -144,7 +162,7 @@
oldArgc++;
}
- if (parm->verbosity > 1) {
+ if (hparm->verbosity > 1) {
printf("%s: hello, oldArgc (number of input args) = %u:\n", me, oldArgc);
for (argIdx = 0; argIdx < oldArgc; argIdx++) {
printf(" oldArgv[%u] == |%s|\n", argIdx, oldArgv[argIdx]);
@@ -154,17 +172,17 @@
newArgc = 0;
*sawHelp = AIR_FALSE;
for (argIdx = 0; argIdx < oldArgc; argIdx++) {
- if (parm->respectDashDashHelp && !strcmp("--help", oldArgv[argIdx])) {
+ if (hparm->respectDashDashHelp && !strcmp("--help", oldArgv[argIdx])) {
*sawHelp = AIR_TRUE;
break;
}
/* else not a show-stopper argument */
- if (parm->verbosity) {
+ if (hparm->verbosity) {
printf("%s:________ newArgc = %u, argIdx = %u -> \"%s\"\n", me, newArgc, argIdx,
oldArgv[argIdx]);
printArgv(newArgc, newArgv, " ");
}
- if (!parm->respFileEnable || parm->respFileFlag != oldArgv[argIdx][0]) {
+ if (!hparm->respFileEnable || hparm->respFileFlag != oldArgv[argIdx][0]) {
/* either ignoring response files, or its not a response file:
we copy the arg, remember to free it, and increment the new arg idx */
newArgv[newArgc] = airStrdup(oldArgv[argIdx]);
@@ -178,13 +196,13 @@
len = airOneLine(file, line, AIR_STRLEN_HUGE + 1);
while (len > 0) {
unsigned rgi;
- if (parm->verbosity) printf("%s: line: |%s|\n", me, line);
+ if (hparm->verbosity) printf("%s: line: |%s|\n", me, line);
/* HEY HEY too bad for you if you put # inside a string */
- if ((pound = strchr(line, parm->respFileComment))) *pound = '\0';
- if (parm->verbosity) printf("%s: -0-> line: |%s|\n", me, line);
+ if ((pound = strchr(line, hparm->respFileComment))) *pound = '\0';
+ if (hparm->verbosity) printf("%s: -0-> line: |%s|\n", me, line);
airOneLinify(line);
incr = airStrntok(line, AIR_WHITESPACE);
- if (parm->verbosity) printf("%s: -1-> line: |%s|, incr=%d\n", me, line, incr);
+ if (hparm->verbosity) printf("%s: -1-> line: |%s|, incr=%d\n", me, line, incr);
airParseStrS(newArgv + newArgc, line, AIR_WHITESPACE, incr, AIR_FALSE);
for (rgi = 0; rgi < incr; rgi++) {
/* This time, we did allocate memory. We can use airFree and
@@ -196,7 +214,7 @@
}
fclose(file);
}
- if (parm->verbosity) {
+ if (hparm->verbosity) {
printArgv(newArgc, newArgv, " ");
printf("%s: ^^^^^^^ newArgc = %d, argIdx = %d\n", me, newArgc, argIdx);
}
@@ -208,48 +226,50 @@
}
/*
-** _hestPanic()
-**
-** all error checking on the given hest array itself (not the
-** command line to be parsed).
-**
-** Prior to 2023 code revisit; this used to set the "kind" in all the opts
-** but now that is more appropriately done at the time the option is added
-** (by hestOptAdd, hestOptAdd_nva, hestOptSingleSet, or hestOptAdd_*_*)
+_hestOptCheck() (formerly _hestPanic)
+
+This performs the validation of the given hestOpt array itself (not the command line to
+be parsed), with descriptive error messages sprintf'ed into err, if given. hestOptCheck()
+is the expected way for users to access this.
+
+Prior to 2023 code revisit; this used to set the "kind" in all the opts but now that is
+more appropriately done at the time the option is added (by hestOptAdd, hestOptAdd_nva,
+hestOptSingleSet, or hestOptAdd_*_*)
*/
int
-_hestPanic(hestOpt *opt, char *err, const hestParm *parm) {
- static const char me[] = "_hestPanic: ";
+_hestOptCheck(const hestOpt *opt, char *err, const hestParm *hparm) {
+ /* see note on ME (at top) for why me[] ends with ": " */
+ static const char me[] = "_hestOptCheck: ";
char tbuff[AIR_STRLEN_HUGE + 1], *sep;
- int numvar, op, numOpts;
+ int numvar, opi, optNum;
- numOpts = hestOptNum(opt);
+ optNum = hestOptNum(opt);
numvar = 0;
- for (op = 0; op < numOpts; op++) {
- if (!(AIR_IN_OP(airTypeUnknown, opt[op].type, airTypeLast))) {
+ for (opi = 0; opi < optNum; opi++) {
+ if (!(AIR_IN_OP(airTypeUnknown, opt[opi].type, airTypeLast))) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]", ME, op,
- opt[op].type, airTypeUnknown + 1, airTypeLast - 1);
+ sprintf(err, "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]", ME, opi,
+ opt[opi].type, airTypeUnknown + 1, airTypeLast - 1);
else
fprintf(stderr, "%s: panic 0\n", me);
return 1;
}
- if (!(opt[op].valueP)) {
+ if (!(opt[opi].valueP)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s valueP is NULL!", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d]'s valueP is NULL!", ME, opi);
else
fprintf(stderr, "%s: panic 0.5\n", me);
return 1;
}
- if (-1 == opt[op].kind) {
+ if (-1 == opt[opi].kind) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible", ME, op,
- opt[op].min, opt[op].max);
+ sprintf(err, "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible", ME, opi,
+ opt[opi].min, opt[opi].max);
else
fprintf(stderr, "%s: panic 1\n", me);
return 1;
}
- if (5 == opt[op].kind && !(opt[op].sawP)) {
+ if (5 == opt[opi].kind && !(opt[opi].sawP)) {
if (err)
sprintf(err,
"%s!!!!!! have multiple variable parameters, "
@@ -259,13 +279,13 @@
fprintf(stderr, "%s: panic 2\n", me);
return 1;
}
- if (airTypeEnum == opt[op].type) {
- if (!(opt[op].enm)) {
+ if (airTypeEnum == opt[opi].type) {
+ if (!(opt[opi].enm)) {
if (err) {
sprintf(err,
"%s!!!!!! opt[%d] (%s) is type \"enum\", but no "
"airEnum pointer given",
- ME, op, opt[op].flag ? opt[op].flag : "?");
+ ME, opi, opt[opi].flag ? opt[opi].flag : "?");
} else {
fprintf(stderr, "%s: panic 3\n", me);
}
@@ -272,54 +292,54 @@
return 1;
}
}
- if (airTypeOther == opt[op].type) {
- if (!(opt[op].CB)) {
+ if (airTypeOther == opt[opi].type) {
+ if (!(opt[opi].CB)) {
if (err) {
sprintf(err,
"%s!!!!!! opt[%d] (%s) is type \"other\", but no "
"callbacks given",
- ME, op, opt[op].flag ? opt[op].flag : "?");
+ ME, opi, opt[opi].flag ? opt[opi].flag : "?");
} else {
fprintf(stderr, "%s: panic 4\n", me);
}
return 1;
}
- if (!(opt[op].CB->size > 0)) {
+ if (!(opt[opi].CB->size > 0)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"size\" (%d) invalid", ME, op,
- (int)(opt[op].CB->size));
+ sprintf(err, "%s!!!!!! opt[%d]'s \"size\" (%d) invalid", ME, opi,
+ (int)(opt[opi].CB->size));
else
fprintf(stderr, "%s: panic 5\n", me);
return 1;
}
- if (!(opt[op].CB->type)) {
+ if (!(opt[opi].CB->type)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"type\" is NULL", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d]'s \"type\" is NULL", ME, opi);
else
fprintf(stderr, "%s: panic 6\n", me);
return 1;
}
- if (!(opt[op].CB->parse)) {
+ if (!(opt[opi].CB->parse)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"parse\" callback NULL", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d]'s \"parse\" callback NULL", ME, opi);
else
fprintf(stderr, "%s: panic 7\n", me);
return 1;
}
- if (opt[op].CB->destroy && (sizeof(void *) != opt[op].CB->size)) {
+ if (opt[opi].CB->destroy && (sizeof(void *) != opt[opi].CB->size)) {
if (err)
sprintf(err,
"%s!!!!!! opt[%d] has a \"destroy\", but size %lu isn't "
"sizeof(void*)",
- ME, op, (unsigned long)(opt[op].CB->size));
+ ME, opi, (unsigned long)(opt[opi].CB->size));
else
fprintf(stderr, "%s: panic 8\n", me);
return 1;
}
}
- if (opt[op].flag) {
- strcpy(tbuff, opt[op].flag);
- if ((sep = strchr(tbuff, parm->multiFlagSep))) {
+ if (opt[opi].flag) {
+ strcpy(tbuff, opt[opi].flag);
+ if ((sep = strchr(tbuff, hparm->multiFlagSep))) {
*sep = '\0';
if (!(strlen(tbuff) && strlen(sep + 1))) {
if (err)
@@ -326,32 +346,32 @@
sprintf(err,
"%s!!!!!! either short (\"%s\") or long (\"%s\") flag"
" of opt[%d] is zero length",
- ME, tbuff, sep + 1, op);
+ ME, tbuff, sep + 1, opi);
else
fprintf(stderr, "%s: panic 9\n", me);
return 1;
}
- if (parm->respectDashDashHelp && !strcmp("help", sep + 1)) {
+ if (hparm->respectDashDashHelp && !strcmp("help", sep + 1)) {
if (err)
sprintf(err,
"%s!!!!!! long \"--%s\" flag of opt[%d] is same as \"--help\" "
"that requested hparm->respectDashDashHelp handles separately",
- ME, sep + 1, op);
+ ME, sep + 1, opi);
else
fprintf(stderr, "%s: panic 9.5\n", me);
return 1;
}
} else {
- if (!strlen(opt[op].flag)) {
+ if (!strlen(opt[opi].flag)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d].flag is zero length", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d].flag is zero length", ME, opi);
else
fprintf(stderr, "%s: panic 10\n", me);
return 1;
}
}
- if (4 == opt[op].kind) {
- if (!opt[op].dflt) {
+ if (4 == opt[opi].kind) {
+ if (!opt[opi].dflt) {
if (err)
sprintf(err,
"%s!!!!!! flagged single variable parameter must "
@@ -361,7 +381,7 @@
fprintf(stderr, "%s: panic 11\n", me);
return 1;
}
- if (!strlen(opt[op].dflt)) {
+ if (!strlen(opt[opi].dflt)) {
if (err)
sprintf(err,
"%s!!!!!! flagged single variable parameter default "
@@ -382,8 +402,8 @@
}
*/
}
- if (1 == opt[op].kind) {
- if (!opt[op].flag) {
+ if (1 == opt[opi].kind) {
+ if (!opt[opi].flag) {
if (err)
sprintf(err, "%s!!!!!! flags must have flags", ME);
else
@@ -391,26 +411,26 @@
return 1;
}
} else {
- if (!opt[op].name) {
+ if (!opt[opi].name) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d] isn't a flag: must have \"name\"", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d] isn't a flag: must have \"name\"", ME, opi);
else
fprintf(stderr, "%s: panic 14\n", me);
return 1;
}
}
- if (4 == opt[op].kind && !opt[op].dflt) {
+ if (4 == opt[opi].kind && !opt[opi].dflt) {
if (err)
sprintf(err,
"%s!!!!!! opt[%d] is single variable parameter, but "
"no default set",
- ME, op);
+ ME, opi);
else
fprintf(stderr, "%s: panic 15\n", me);
return 1;
}
- numvar += ((int)opt[op].min < _hestMax(opt[op].max)
- && (NULL == opt[op].flag)); /* HEY scrutinize casts */
+ numvar += ((int)opt[opi].min < _hestMax(opt[opi].max)
+ && (NULL == opt[opi].flag)); /* HEY scrutinize casts */
}
if (numvar > 1) {
if (err)
@@ -425,23 +445,23 @@
int
_hestErrStrlen(const hestOpt *opt, int argc, const char **argv) {
- int a, numOpts, ret, other;
+ int ai, optNum, ret, other;
ret = 0;
- numOpts = hestOptNum(opt);
+ optNum = hestOptNum(opt);
other = AIR_FALSE;
if (argv) {
- for (a = 0; a < argc; a++) {
- ret = AIR_MAX(ret, (int)airStrlen(argv[a]));
+ for (ai = 0; ai < argc; ai++) {
+ ret = AIR_MAX(ret, (int)airStrlen(argv[ai]));
}
}
- for (a = 0; a < numOpts; a++) {
- ret = AIR_MAX(ret, (int)airStrlen(opt[a].flag));
- ret = AIR_MAX(ret, (int)airStrlen(opt[a].name));
- other |= opt[a].type == airTypeOther;
+ for (ai = 0; ai < optNum; ai++) {
+ ret = AIR_MAX(ret, (int)airStrlen(opt[ai].flag));
+ ret = AIR_MAX(ret, (int)airStrlen(opt[ai].name));
+ other |= opt[ai].type == airTypeOther;
}
- for (a = airTypeUnknown + 1; a < airTypeLast; a++) {
- ret = AIR_MAX(ret, (int)airStrlen(airTypeStr[a]));
+ for (ai = airTypeUnknown + 1; ai < airTypeLast; ai++) {
+ ret = AIR_MAX(ret, (int)airStrlen(airTypeStr[ai]));
}
if (other) {
/* the callback's error() function may sprintf an error message
@@ -459,15 +479,15 @@
copies into ident a string for identifying an option in error and usage messages
*/
static char *
-identStr(char *ident, hestOpt *opt, const hestParm *parm, int brief) {
+identStr(char *ident, const hestOpt *opt, const hestParm *hparm, int brief) {
char copy[AIR_STRLEN_HUGE + 1], *sep;
- if (opt->flag && (sep = strchr(opt->flag, parm->multiFlagSep))) {
+ if (opt->flag && (sep = strchr(opt->flag, hparm->multiFlagSep))) {
strcpy(copy, opt->flag);
- sep = strchr(copy, parm->multiFlagSep);
+ sep = strchr(copy, hparm->multiFlagSep);
*sep = '\0';
if (brief)
- sprintf(ident, "-%s%c--%s option", copy, parm->multiFlagSep, sep + 1);
+ sprintf(ident, "-%s%c--%s option", copy, hparm->multiFlagSep, sep + 1);
else
sprintf(ident, "-%s option", copy);
} else {
@@ -478,63 +498,72 @@
}
/*
-whichFlag()
+whichOptFlag()
-given a string in "flag" (with the hypen prefix) finds which of the flags in the given
-array of options matches that. Returns the index of the matching option, or -1 if
-there is no match, but returns -2 if the flag is the end-of-parameters
-marker "--" (or whatever parm->varParamStopFlag implies)
+given a string in "flag" (with the hypen prefix) finds which of the options in the given
+array of options has the matching flag. Returns the index of the matching option, or -1
+if there is no match, but returns -2 if the flag is the end-of-parameters marker "--" (or
+whatever parm->varParamStopFlag implies)
*/
static int
-whichFlag(hestOpt *opt, char *flag, const hestParm *parm) {
- static const char me[] = "whichFlag";
+whichOptFlag(const hestOpt *opt, const char *flag, const hestParm *hparm) {
+ static const char me[] = "whichOptFlag";
char buff[2 * AIR_STRLEN_HUGE + 1], copy[AIR_STRLEN_HUGE + 1], *sep;
- int op, numOpts;
+ int optIdx, optNum;
- numOpts = hestOptNum(opt);
- if (parm->verbosity)
- printf("%s: (a) looking for flag |%s| in numOpts=%d options\n", me, flag, numOpts);
- for (op = 0; op < numOpts; op++) {
- if (parm->verbosity) printf("%s: op = %d\n", me, op);
- if (!opt[op].flag) continue;
- if (strchr(opt[op].flag, parm->multiFlagSep)) {
- strcpy(copy, opt[op].flag);
- sep = strchr(copy, parm->multiFlagSep);
+ optNum = hestOptNum(opt);
+ if (hparm->verbosity)
+ printf("%s: (a) looking for maybe-is-flag |%s| in optNum=%d options\n", me, flag,
+ optNum);
+ for (optIdx = 0; optIdx < optNum; optIdx++) {
+ if (hparm->verbosity)
+ printf("%s: optIdx %d |%s| ?\n", me, optIdx,
+ opt[optIdx].flag ? opt[optIdx].flag : "(nullflag)");
+ if (!opt[optIdx].flag) continue;
+ if (strchr(opt[optIdx].flag, hparm->multiFlagSep)) {
+ strcpy(copy, opt[optIdx].flag);
+ sep = strchr(copy, hparm->multiFlagSep);
*sep = '\0';
/* first try the short version */
sprintf(buff, "-%s", copy);
- if (!strcmp(flag, buff)) return op;
+ if (!strcmp(flag, buff)) return optIdx;
/* then try the long version */
sprintf(buff, "--%s", sep + 1);
- if (!strcmp(flag, buff)) return op;
+ if (!strcmp(flag, buff)) return optIdx;
} else {
/* flag has only the short version */
- sprintf(buff, "-%s", opt[op].flag);
- if (!strcmp(flag, buff)) return op;
+ sprintf(buff, "-%s", opt[optIdx].flag);
+ if (!strcmp(flag, buff)) return optIdx;
}
}
- if (parm->verbosity) printf("%s: (b) numOpts = %d\n", me, numOpts);
- if (parm->varParamStopFlag) {
- sprintf(buff, "-%c", parm->varParamStopFlag);
- if (parm->verbosity)
- printf("%s: does flag |%s| == -parm->varParamStopFlag |%s| ?\n", me, flag, buff);
+ if (hparm->verbosity) printf("%s: (b) optNum = %d\n", me, optNum);
+ if (hparm->varParamStopFlag) {
+ sprintf(buff, "-%c", hparm->varParamStopFlag);
+ if (hparm->verbosity)
+ printf("%s: does maybe-is-flag |%s| == -parm->varParamStopFlag |%s| ?\n", me, flag,
+ buff);
if (!strcmp(flag, buff)) {
- if (parm->verbosity) printf("%s: yes, it does! returning -2\n", me);
+ if (hparm->verbosity) printf("%s: yes, it does! returning -2\n", me);
return -2;
}
}
- if (parm->verbosity) printf("%s: (c) returning -1\n", me);
+ if (hparm->verbosity) printf("%s: (c) returning -1\n", me);
return -1;
}
/*
-extractToStr: takes "pnum" parameters, starting at "base", out of the given argv, and
-puts them into a string WHICH THIS FUNCTION ALLOCATES, and also adjusts the argc value
-given as "*argcP".
+extractToStr: from the given *argcP,argv description of args, starting at arg index
+`base`, takes *UP TO* `pnum` parameters out of argv, and puts them into a new
+VTAB-separated qstring WHICH THIS FUNCTION ALLOCATES, and accordingly decreases `*argcP`.
+
+***** This is the function where VTAB starts being used.
+
+The number of parameters so extracted is stored in `*pnumGot` (if `pnumGot` non-NULL).
+`*pnumGot` can be less than `pnum` if we hit "--" (or the equivalent)
*/
static char *
extractToStr(int *argcP, char **argv, unsigned int base, unsigned int pnum,
- unsigned int *pnumGot, const hestParm *parm) {
+ unsigned int *pnumGot, const hestParm *hparm) {
unsigned int len, pidx, true_pnum;
char *ret;
char stops[3] = "";
@@ -541,9 +570,9 @@
if (!pnum) return NULL;
- if (parm) {
+ if (hparm) {
stops[0] = '-';
- stops[1] = parm->varParamStopFlag;
+ stops[1] = hparm->varParamStopFlag;
stops[2] = '\0';
} /* else stops stays as empty string */
@@ -551,7 +580,7 @@
len = 0;
for (pidx = 0; pidx < pnum; pidx++) {
if (base + pidx == AIR_UINT(*argcP)) {
- /* ran up against end of argv array */
+ /* ran up against end of argv array; game over */
return NULL;
}
if (!strcmp(argv[base + pidx], stops)) {
@@ -560,7 +589,7 @@
}
/* increment by strlen of current arg */
len += AIR_UINT(strlen(argv[base + pidx]));
- /* and by 2, for 2 '"'s around quoted parm */
+ /* and then increment by 2, for 2 '"'s around quoted parm */
if (strstr(argv[base + pidx], " ")) {
len += 2;
}
@@ -584,9 +613,11 @@
if (strstr(argv[base + pidx], " ")) {
strcat(ret, "\"");
}
- /* add space prior to anticipated next parm */
+ /* add space prior to anticipated next parm
+ HEY this needs to be re-written to extend an argv */
if (pidx < true_pnum - 1) strcat(ret, " ");
}
+ /* shuffle down later argv pointers */
for (pidx = base + true_pnum; pidx <= AIR_UINT(*argcP); pidx++) {
argv[pidx - true_pnum] = argv[pidx];
}
@@ -597,112 +628,129 @@
/*
extractFlagged()
-extracts the parameters associated with all flagged options from the given argc and argv,
-storing them in prms[], recording the number of parameters in nprm[], and whether or not
-the flagged option appeared in appr[].
+extracts the parameters associated with all flagged options from the given *argcP and
+argv (wherein the flag and subsequent parms were all separate strings), and here stores
+them in optParms[] as a single VTAB-separated string (VTABs originating in extractToStr),
+recording the number of parameters in optParmNum[], and whether or not the flagged option
+appeared in optAprd[].
The sawP information is not set here, since it is better set at value parsing time, which
happens after defaults are enstated.
-This is where, thanks to the action of whichFlag(), "--" (or whatever
+This is where, thanks to the action of whichOptFlag(), "--" (or whatever
parm->varParamStopFlag implies) is used as a marker for the end of a *flagged* variable
parameter option. AND, the "--" marker is removed from the argv.
*/
static int
-extractFlagged(char **prms, unsigned int *nprm, int *appr, int *argcP, char **argv,
- hestOpt *opt, char *err, const hestParm *parm, airArray *pmop) {
+extractFlagged(char **optParms, unsigned int *optParmNum, int *optAprd, int *argcP,
+ char **argv, hestOpt *opt, char *err, const hestParm *hparm,
+ airArray *pmop) {
+ /* see note on ME (at top) for why me[] ends with ": " */
static const char me[] = "extractFlagged: ";
char ident1[AIR_STRLEN_HUGE + 1], ident2[AIR_STRLEN_HUGE + 1];
- int a, np, flag, endflag, numOpts, op;
+ int argIdx, parmNum, optIdx, nextOptIdx, optNum, op;
- a = 0;
- if (parm->verbosity) printf("%s: *argcP = %d\n", me, *argcP);
- while (a <= *argcP - 1) {
- if (parm->verbosity) {
- printf("%s: ----------------- a = %d -> argv[a] = %s\n", me, a, argv[a]);
+ if (hparm->verbosity) printf("%s: *argcP = %d\n", me, *argcP);
+ argIdx = 0;
+ while (argIdx <= *argcP - 1) {
+ if (hparm->verbosity) {
+ printf("%s----------------- argIdx = %d -> argv[argIdx] = %s\n", me, argIdx,
+ argv[argIdx]);
}
- flag = whichFlag(opt, argv[a], parm);
- if (parm->verbosity) printf("%s: A: a = %d -> flag = %d\n", me, a, flag);
- if (!(0 <= flag)) {
+ optIdx = whichOptFlag(opt, argv[argIdx], hparm);
+ if (hparm->verbosity)
+ printf("%sA: argv[%d]=|%s| is flag of opt %d\n", me, argIdx, argv[argIdx], optIdx);
+ if (!(0 <= optIdx)) {
/* not a flag, move on */
- a++;
- if (parm->verbosity) printf("%s: !(0 <= %d), so: continue\n", me, flag);
+ argIdx++;
+ if (hparm->verbosity) printf("%s: !(0 <= %d), so: continue\n", me, optIdx);
continue;
}
/* see if we can associate some parameters with the flag */
- if (parm->verbosity) printf("%s: flag = %d; any parms?\n", me, flag);
- np = 0;
- endflag = 0;
- while (np < _hestMax(opt[flag].max) /* */
- && a + np + 1 <= *argcP - 1 /* */
- && -1 == (endflag = whichFlag(opt, argv[a + np + 1], parm))) {
- np++;
- if (parm->verbosity)
- printf("%s: np --> %d with flag = %d; endflag = %d\n", me, np, flag, endflag);
+ if (hparm->verbosity)
+ printf("%soptIdx %d |%s|: any parms?\n", me, optIdx, opt[optIdx].flag);
+ parmNum = 0;
+ nextOptIdx = 0; // what is index of option who's flag we see next
+ while (parmNum < _hestMax(opt[optIdx].max) /* */
+ && argIdx + parmNum + 1 <= *argcP - 1 /* */
+ && -1
+ == (nextOptIdx = whichOptFlag(opt, /* */
+ argv[argIdx + parmNum + 1], /* */
+ hparm))) {
+ parmNum++;
+ if (hparm->verbosity)
+ printf("%soptIdx %d |%s|: parmNum --> %d nextOptIdx = %d\n", me, optIdx,
+ opt[optIdx].flag, parmNum, nextOptIdx);
}
/* we stopped because we got the max number of parameters, or
because we hit the end of the command line, or
- because whichFlag() returned something other than -1,
- which means it returned -2, or a valid option index. If
- we stopped because of whichFlag()'s return value,
- endflag has been set to that return value */
- if (parm->verbosity)
- printf("%s: B: stopped with np = %d; flag = %d; endflag = %d\n", me, np, flag,
- endflag);
- if (np < (int)opt[flag].min) { /* HEY scrutinize casts */
+ because whichOptFlag() returned something other than -1,
+ which means it returned -2, or a valid option index.
+ If we stopped because of whichOptFlag()'s return value,
+ nextOptIdx has been set to that return value */
+ if (hparm->verbosity)
+ printf("%sB: optIdx %d |%s|: stopped with parmNum = %d nextOptIdx = %d\n", me,
+ optIdx, opt[optIdx].flag, parmNum, nextOptIdx);
+ if (parmNum < (int)opt[optIdx].min) { /* HEY scrutinize casts */
/* didn't get minimum number of parameters */
- if (!(a + np + 1 <= *argcP - 1)) {
+ if (!(argIdx + parmNum + 1 <= *argcP - 1)) {
sprintf(err,
- "%shit end of line before getting %d parameter%s "
+ "%sgot to end of line before getting %d parameter%s "
"for %s (got %d)",
- ME, opt[flag].min, opt[flag].min > 1 ? "s" : "",
- identStr(ident1, opt + flag, parm, AIR_TRUE), np);
- } else if (-2 != endflag) {
- sprintf(err, "%shit %s before getting %d parameter%s for %s (got %d)", ME,
- identStr(ident1, opt + endflag, parm, AIR_FALSE), opt[flag].min,
- opt[flag].min > 1 ? "s" : "",
- identStr(ident2, opt + flag, parm, AIR_FALSE), np);
+ ME, opt[optIdx].min, opt[optIdx].min > 1 ? "s" : "",
+ identStr(ident1, opt + optIdx, hparm, AIR_TRUE), parmNum);
+ } else if (-2 != nextOptIdx) {
+ sprintf(err, "%ssaw %s before getting %d parameter%s for %s (got %d)", ME,
+ identStr(ident1, opt + nextOptIdx, hparm, AIR_FALSE), opt[optIdx].min,
+ opt[optIdx].min > 1 ? "s" : "",
+ identStr(ident2, opt + optIdx, hparm, AIR_FALSE), parmNum);
} else {
sprintf(err,
- "%shit \"-%c\" (option-parameter-stop flag) before getting %d "
+ "%ssaw \"-%c\" (option-parameter-stop flag) before getting %d "
"parameter%s for %s (got %d)",
- ME, parm->varParamStopFlag, opt[flag].min, opt[flag].min > 1 ? "s" : "",
- identStr(ident2, opt + flag, parm, AIR_FALSE), np);
+ ME, hparm->varParamStopFlag, opt[optIdx].min,
+ opt[optIdx].min > 1 ? "s" : "",
+ identStr(ident2, opt + optIdx, hparm, AIR_FALSE), parmNum);
}
return 1;
}
- nprm[flag] = np;
- if (parm->verbosity) {
- printf("%s:________ a=%d, *argcP = %d -> flag = %d\n", me, a, *argcP, flag);
+ /* record number of parameters seen for this option */
+ optParmNum[optIdx] = parmNum;
+ if (hparm->verbosity) {
+ printf("%s________ argv[%d]=|%s|: *argcP = %d -> optIdx = %d\n", me, argIdx,
+ argv[argIdx], *argcP, optIdx);
printArgv(*argcP, argv, " ");
}
/* lose the flag argument */
- free(extractToStr(argcP, argv, a, 1, NULL, NULL));
+ free(extractToStr(argcP, argv, argIdx, 1, NULL, NULL));
/* extract the args after the flag */
- if (appr[flag]) {
- airMopSub(pmop, prms[flag], airFree);
- prms[flag] = (char *)airFree(prms[flag]);
+ if (optAprd[optIdx]) {
+ /* oh so this is not the first time we've seen this option;
+ so now forget everything triggered by having seen it already */
+ airMopSub(pmop, optParms[optIdx], airFree);
+ optParms[optIdx] = (char *)airFree(optParms[optIdx]);
}
- prms[flag] = extractToStr(argcP, argv, a, nprm[flag], NULL, NULL);
- airMopAdd(pmop, prms[flag], airFree, airMopAlways);
- appr[flag] = AIR_TRUE;
- if (-2 == endflag) {
+ optParms[optIdx] = extractToStr(argcP, argv, argIdx, optParmNum[optIdx], NULL, NULL);
+ airMopAdd(pmop, optParms[optIdx], airFree, airMopAlways);
+ optAprd[optIdx] = AIR_TRUE;
+ if (-2 == nextOptIdx) {
/* we drop the option-parameter-stop flag */
- free(extractToStr(argcP, argv, a, 1, NULL, NULL));
+ free(extractToStr(argcP, argv, argIdx, 1, NULL, NULL));
}
- if (parm->verbosity) {
+ if (hparm->verbosity) {
printArgv(*argcP, argv, " ");
- printf("%s:^^^^^^^^ *argcP = %d\n", me, *argcP);
- printf("%s: prms[%d] = %s\n", me, flag, prms[flag] ? prms[flag] : "(null)");
+ printf("%s^^^^^^^^ *argcP = %d\n", me, *argcP);
+ printf("%soptParms[%d] = |%s|\n", me, optIdx,
+ optParms[optIdx] ? optParms[optIdx] : "(null)");
}
}
/* make sure that flagged options without default were given */
- numOpts = hestOptNum(opt);
- for (op = 0; op < numOpts; op++) {
- if (1 != opt[op].kind && opt[op].flag && !opt[op].dflt && !appr[op]) {
+ optNum = hestOptNum(opt);
+ for (op = 0; op < optNum; op++) {
+ if (1 != opt[op].kind && opt[op].flag && !opt[op].dflt && !optAprd[op]) {
sprintf(err, "%sdidn't get required %s", ME,
- identStr(ident1, opt + op, parm, AIR_FALSE));
+ identStr(ident1, opt + op, hparm, AIR_FALSE));
return 1;
}
}
@@ -711,95 +759,108 @@
}
static int
-_hestNextUnflagged(int op, hestOpt *opt, int numOpts) {
+nextUnflagged(int op, hestOpt *opt, int optNum) {
- for (; op <= numOpts - 1; op++) {
+ for (; op <= optNum - 1; op++) {
if (!opt[op].flag) break;
}
return op;
}
+/*
+extractUnflagged()
+
+extracts the parameters associated with all unflagged options from the given *argcP and
+argv (wherein the flag and subsequent parms were all separate strings), and here stores
+them in optParms[] as a single VTAB-separated string (VTABs originating in extractToStr),
+recording the number of parameters in optParmNum[].
+
+This is the function that has to handle the trickly logic of allowing there to be
+multiple unflagged opti...
[truncated message content] |