You can subscribe to this list here.
| 2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(19) |
Nov
(45) |
Dec
(80) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2004 |
Jan
(58) |
Feb
(127) |
Mar
(74) |
Apr
(34) |
May
(117) |
Jun
(14) |
Jul
(26) |
Aug
(13) |
Sep
(1) |
Oct
(38) |
Nov
(13) |
Dec
(5) |
| 2005 |
Jan
(108) |
Feb
(134) |
Mar
(54) |
Apr
(133) |
May
(16) |
Jun
(54) |
Jul
(128) |
Aug
(99) |
Sep
(157) |
Oct
(182) |
Nov
(236) |
Dec
(212) |
| 2006 |
Jan
(86) |
Feb
(76) |
Mar
(121) |
Apr
(27) |
May
(7) |
Jun
(1) |
Jul
(6) |
Aug
(28) |
Sep
(1) |
Oct
(27) |
Nov
(5) |
Dec
|
| 2007 |
Jan
(32) |
Feb
(22) |
Mar
(22) |
Apr
(11) |
May
(3) |
Jun
(12) |
Jul
(11) |
Aug
(9) |
Sep
(37) |
Oct
(4) |
Nov
(9) |
Dec
(51) |
| 2008 |
Jan
(7) |
Feb
(31) |
Mar
(46) |
Apr
(31) |
May
(5) |
Jun
(27) |
Jul
(12) |
Aug
(5) |
Sep
(13) |
Oct
(24) |
Nov
(112) |
Dec
(15) |
| 2009 |
Jan
(6) |
Feb
(103) |
Mar
(66) |
Apr
(9) |
May
(8) |
Jun
(1) |
Jul
(20) |
Aug
(9) |
Sep
(2) |
Oct
(81) |
Nov
(88) |
Dec
(30) |
| 2010 |
Jan
(65) |
Feb
(57) |
Mar
(22) |
Apr
(12) |
May
(4) |
Jun
(12) |
Jul
(43) |
Aug
(6) |
Sep
(6) |
Oct
(4) |
Nov
(6) |
Dec
(3) |
| 2011 |
Jan
(10) |
Feb
(27) |
Mar
(11) |
Apr
(9) |
May
(69) |
Jun
(73) |
Jul
(67) |
Aug
(116) |
Sep
(40) |
Oct
(11) |
Nov
(34) |
Dec
(19) |
| 2012 |
Jan
|
Feb
(4) |
Mar
(28) |
Apr
(18) |
May
(9) |
Jun
(7) |
Jul
(4) |
Aug
(155) |
Sep
(264) |
Oct
(172) |
Nov
(15) |
Dec
(40) |
| 2013 |
Jan
(1) |
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
(20) |
Jul
(76) |
Aug
(67) |
Sep
(49) |
Oct
(27) |
Nov
(3) |
Dec
(3) |
| 2014 |
Jan
(7) |
Feb
(7) |
Mar
(16) |
Apr
|
May
(4) |
Jun
(1) |
Jul
(18) |
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
| 2015 |
Jan
(6) |
Feb
(5) |
Mar
(3) |
Apr
(23) |
May
(5) |
Jun
|
Jul
(2) |
Aug
(4) |
Sep
|
Oct
|
Nov
(2) |
Dec
(4) |
| 2016 |
Jan
(2) |
Feb
(7) |
Mar
(2) |
Apr
(1) |
May
(14) |
Jun
(3) |
Jul
|
Aug
(3) |
Sep
|
Oct
|
Nov
(1) |
Dec
(3) |
| 2017 |
Jan
(6) |
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(12) |
Sep
(6) |
Oct
|
Nov
(3) |
Dec
|
| 2018 |
Jan
(4) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(8) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2019 |
Jan
|
Feb
|
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(3) |
Sep
(8) |
Oct
|
Nov
(2) |
Dec
(25) |
| 2020 |
Jan
|
Feb
(3) |
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
(3) |
Oct
(53) |
Nov
(33) |
Dec
|
| 2021 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(4) |
Dec
(5) |
| 2022 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(5) |
Jul
(93) |
Aug
(206) |
Sep
(39) |
Oct
(19) |
Nov
(11) |
Dec
|
| 2023 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(2) |
Jun
(150) |
Jul
(124) |
Aug
(14) |
Sep
(5) |
Oct
|
Nov
(1) |
Dec
|
| 2024 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(12) |
Jul
(62) |
Aug
|
Sep
(7) |
Oct
|
Nov
(7) |
Dec
|
| 2025 |
Jan
|
Feb
|
Mar
|
Apr
(14) |
May
(3) |
Jun
|
Jul
|
Aug
(76) |
Sep
(214) |
Oct
(6) |
Nov
|
Dec
|
|
From: <kin...@us...> - 2025-09-28 08:52:57
|
Revision: 7511
http://sourceforge.net/p/teem/code/7511
Author: kindlmann
Date: 2025-09-28 08:52:54 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
now with clang-format
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-28 08:50:07 UTC (rev 7510)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-28 08:52:54 UTC (rev 7511)
@@ -165,7 +165,9 @@
if (ret) {
if (strlen(myerr)) {
snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "error parsing \"%s\" as %s:\n%s\n", str,
- hpp->CB->type, airStrtrunc(myerr, AIR_STRLEN_HUGE + 1, strlen(str) + strlen(hpp->CB->type) + 100));
+ hpp->CB->type,
+ airStrtrunc(myerr, AIR_STRLEN_HUGE + 1,
+ strlen(str) + strlen(hpp->CB->type) + 100));
} else {
snprintf(hpp->err, AIR_STRLEN_HUGE + 1,
"error parsing \"%s\" as %s: returned %d\n", str, hpp->CB->type, ret);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 08:51:03
|
Revision: 7510
http://sourceforge.net/p/teem/code/7510
Author: kindlmann
Date: 2025-09-28 08:50:07 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
fewer warnings
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-28 08:49:41 UTC (rev 7509)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-28 08:50:07 UTC (rev 7510)
@@ -165,7 +165,7 @@
if (ret) {
if (strlen(myerr)) {
snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "error parsing \"%s\" as %s:\n%s\n", str,
- hpp->CB->type, myerr);
+ hpp->CB->type, airStrtrunc(myerr, AIR_STRLEN_HUGE + 1, strlen(str) + strlen(hpp->CB->type) + 100));
} else {
snprintf(hpp->err, AIR_STRLEN_HUGE + 1,
"error parsing \"%s\" as %s: returned %d\n", str, hpp->CB->type, ret);
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-28 08:49:41 UTC (rev 7509)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-28 08:50:07 UTC (rev 7510)
@@ -84,7 +84,7 @@
hparm->respectDashDashHelp = AIR_TRUE;
hparm->noArgsIsNoProblem = AIR_TRUE;
hparm->dieLessVerbose = AIR_TRUE;
- hparm->verbosity = 1;
+ hparm->verbosity = 0;
opt = NULL;
/* going past C89 to have declarations here */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 08:49:43
|
Revision: 7509
http://sourceforge.net/p/teem/code/7509
Author: kindlmann
Date: 2025-09-28 08:49:41 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
helper function to avoid warnings about snprintf %s directive output may be truncated writing up to ...
Modified Paths:
--------------
teem/trunk/src/air/air.h
teem/trunk/src/air/string.c
Modified: teem/trunk/src/air/air.h
===================================================================
--- teem/trunk/src/air/air.h 2025-09-28 08:25:44 UTC (rev 7508)
+++ teem/trunk/src/air/air.h 2025-09-28 08:49:41 UTC (rev 7509)
@@ -514,6 +514,7 @@
AIR_EXPORT char *airStrdup(const char *s);
AIR_EXPORT size_t airStrlen(const char *s);
/* ---- BEGIN non-NrrdIO */
+AIR_EXPORT char *airStrtrunc(char *s, size_t bsize, size_t drop);
AIR_EXPORT int airStrcmp(const char *s1, const char *s2);
/* ---- END non-NrrdIO */
AIR_EXPORT char *airStrtok(char *s, const char *ct, char **last);
Modified: teem/trunk/src/air/string.c
===================================================================
--- teem/trunk/src/air/string.c 2025-09-28 08:25:44 UTC (rev 7508)
+++ teem/trunk/src/air/string.c 2025-09-28 08:49:41 UTC (rev 7509)
@@ -65,6 +65,21 @@
/* ---- BEGIN non-NrrdIO */
/*
+(possibly) truncates a given string `str` stored in a buffer of size `bsize`
+to ensure that its strlen does not exceed bsize-1-drop. But main purpose is
+to hide compile-time info about static buffer sizes to avoid warnings about:
+snprintf ...'%s' directive output may be truncated writing up to ... */
+char *
+airStrtrunc(char *str, size_t bsize, size_t drop) {
+ if (str) {
+ if (1 + drop < bsize) {
+ str[bsize - (1 + drop)] = '\0';
+ }
+ }
+ return str;
+}
+
+/*
******** airStrcmp
**
** like strcmp, but:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 08:25:46
|
Revision: 7508
http://sourceforge.net/p/teem/code/7508
Author: kindlmann
Date: 2025-09-28 08:25:44 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
more testing
Modified Paths:
--------------
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-28 08:20:59 UTC (rev 7507)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-28 08:25:44 UTC (rev 7508)
@@ -150,7 +150,6 @@
char *s1;
hestOptAdd_1_String(&opt, "s1", "string1", &s1, "\"bingo bob\"",
"test of hestOptAdd_1_String");
- /*
int e1;
hestOptAdd_1_Enum(&opt, "e1", "enum1", &e1, "little", "test of hestOptAdd_1_Enum",
airEndian);
@@ -160,7 +159,6 @@
Quat *q1;
hestOptAdd_1_Other(&opt, "q1", "quat", &q1, "12.34", "test of hestOptAdd_1_Other B",
&quatCB);
- */
#if 0
int b2[2];
@@ -441,11 +439,9 @@
printf("db1 = %g\n", db1);
printf("c1 = |%c| (%d)\n", c1, c1);
printf("s1 = |%s|\n", s1);
- /*
printf("e1 = %d\n", e1);
printf("p1 = %g,%g\n", p1[0], p1[1]);
printf("q1 (@ %p) = %g(%s)\n", q1, q1->val, q1->str);
- */
printf("\n");
#if 0
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 08:21:01
|
Revision: 7507
http://sourceforge.net/p/teem/code/7507
Author: kindlmann
Date: 2025-09-28 08:20:59 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
one less memory leak
Modified Paths:
--------------
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-28 08:18:42 UTC (rev 7506)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-28 08:20:59 UTC (rev 7507)
@@ -383,11 +383,13 @@
if (hestParse2(opt, argc - 1, argv + 1, NULL, hparm)) {
// have already fprintf'd to stderr
hestUsage(stderr, opt, argv[0], hparm);
+ hestParmFree(hparm);
hestOptFree(opt);
exit(0);
}
if (opt->helpWanted) {
hestGlossary(stdout, opt, hparm);
+ hestParmFree(hparm);
hestOptFree(opt);
exit(0);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 08:18:45
|
Revision: 7506
http://sourceforge.net/p/teem/code/7506
Author: kindlmann
Date: 2025-09-28 08:18:42 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
testing
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-28 08:06:12 UTC (rev 7505)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-28 08:18:42 UTC (rev 7506)
@@ -92,10 +92,6 @@
#define _PARSE_1_BODY(typstr, format) \
if (!(out && str && hpp)) return 1; \
int ret = (1 != airSingleSscanf(str, format, out)); \
- if (!strcmp("parseSingleI", __func__)) { \
- printf("!%s: sscanf(|%s|, %s, %p)-> (ret=%d) %d\n", __func__, str, format, out, \
- ret, *((int *)out)); \
- } \
if (ret) { \
snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "couldn't parse \"%s\" as", typstr); \
} else { \
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-28 08:06:12 UTC (rev 7505)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-28 08:18:42 UTC (rev 7506)
@@ -380,7 +380,17 @@
hestOptAdd_Nv_Other(&opt, "qv", "quat1", 1, -1, &qv, "12.34 43.21",
"test of hestOptAdd_Nv_Other B", &qvSaw, &quatCB);
#endif
- hestParse2(opt, argc - 1, argv + 1, NULL, hparm);
+ if (hestParse2(opt, argc - 1, argv + 1, NULL, hparm)) {
+ // have already fprintf'd to stderr
+ hestUsage(stderr, opt, argv[0], hparm);
+ hestOptFree(opt);
+ exit(0);
+ }
+ if (opt->helpWanted) {
+ hestGlossary(stdout, opt, hparm);
+ hestOptFree(opt);
+ exit(0);
+ }
/*
hestParseOrDie(opt, argc - 1, argv + 1, hparm, argv[0], info, AIR_TRUE, AIR_TRUE,
AIR_TRUE);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 08:06:14
|
Revision: 7505
http://sourceforge.net/p/teem/code/7505
Author: kindlmann
Date: 2025-09-28 08:06:12 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
more testing
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-28 07:53:28 UTC (rev 7504)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-28 08:06:12 UTC (rev 7505)
@@ -121,7 +121,8 @@
int ret;
if (1 != slen) {
snprintf(hpp->err, AIR_STRLEN_HUGE + 1,
- "expected single char but got string length %u", AIR_UINT(slen));
+ "expected single char but got string \"%s\" length %u", str,
+ AIR_UINT(slen));
ret = 1;
} else {
char *out = (char *)_out;
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-28 07:53:28 UTC (rev 7504)
+++ teem/trunk/src/hest/parsest.c 2025-09-28 08:06:12 UTC (rev 7505)
@@ -1347,7 +1347,7 @@
} // end case 4 {
case 2: // -------- one required parameter --------
if (_hestParseSingle[type](valueP, opt[opi].havec->harg[0]->str, hpp)) {
- biffAddf(HEST, "%s%sproblem parsing for %s[%u]", _ME_, ident, opi);
+ biffAddf(HEST, "%s%sproblem parsing for %s[%u]: %s", _ME_, ident, opi, hpp->err);
return 1;
}
opt[opi].alloc = hpp->alloc;
@@ -1610,7 +1610,7 @@
free(err); \
}
- // --0--0--0--0--0-- check on validity of the hestOpt array
+ // --1--1--1--1--1-- check on validity of the hestOpt array
if (_hestOPCheck(opt, HPARM)) {
DO_ERR("problem with given hestOpt array");
airMopError(mop);
@@ -1631,7 +1631,7 @@
printf("%s: parsing state allocated\n", __func__);
}
- // --1--1--1--1--1-- initialize input stack w/ given argc,argv, process it
+ // --2--2--2--2--2-- initialize input stack w/ given argc,argv, process it
if (histPushCommandLine(hist, argc, argv, HPARM)
|| histProcess(havec, &(opt->helpWanted), tharg, hist, HPARM)) {
DO_ERR("problem with initial processing of command-line");
@@ -1648,8 +1648,9 @@
return 0;
}
- // --2--2--2--2--2-- extract args associated with flagged and unflagged opt
+ // --3--3--3--3--3-- extract args associated with flagged options
if (havecExtractFlagged(opt, havec, HPARM)
+ // --4--4--4--4--4-- extract args associated with unflagged options
// this will detect extraneous args after unflagged opts are extracted
|| havecExtractUnflagged(opt, havec, HPARM)) {
DO_ERR("problem extracting args for options");
@@ -1657,7 +1658,7 @@
return 1;
}
- /* --3--3--3--3--3-- process defaults strings for opts that weren't user-supplied
+ /* --5--5--5--5--5-- process defaults strings for opts that weren't user-supplied
Like havecExtract{,Un}Flagged, this builds up opt->havec, but does not parse it */
if (optProcessDefaults(opt, tharg, hist, HPARM)) {
DO_ERR("problem with processing defaults");
@@ -1665,7 +1666,7 @@
return 1;
}
- // --4--4--4--4--4-- Finally, parse the args and set values
+ // --6--6--6--6--6-- Finally, parse the args and set values
if (optSetValues(opt, HPARM, mop)) {
DO_ERR("problem with setting values");
airMopError(mop);
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-28 07:53:28 UTC (rev 7504)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-28 08:06:12 UTC (rev 7505)
@@ -84,7 +84,7 @@
hparm->respectDashDashHelp = AIR_TRUE;
hparm->noArgsIsNoProblem = AIR_TRUE;
hparm->dieLessVerbose = AIR_TRUE;
- hparm->verbosity = 0;
+ hparm->verbosity = 1;
opt = NULL;
/* going past C89 to have declarations here */
@@ -147,10 +147,10 @@
"test of hestOptAdd_1_Double");
char c1;
hestOptAdd_1_Char(&opt, "c1", "char1", &c1, "x", "test of hestOptAdd_1_Char");
- /*
char *s1;
hestOptAdd_1_String(&opt, "s1", "string1", &s1, "\"bingo bob\"",
"test of hestOptAdd_1_String");
+ /*
int e1;
hestOptAdd_1_Enum(&opt, "e1", "enum1", &e1, "little", "test of hestOptAdd_1_Enum",
airEndian);
@@ -428,8 +428,8 @@
printf("fl1 = %g\n", fl1);
printf("db1 = %g\n", db1);
printf("c1 = |%c| (%d)\n", c1, c1);
+ printf("s1 = |%s|\n", s1);
/*
- printf("s1 = |%s|\n", s1);
printf("e1 = %d\n", e1);
printf("p1 = %g,%g\n", p1[0], p1[1]);
printf("q1 (@ %p) = %g(%s)\n", q1, q1->val, q1->str);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 07:53:29
|
Revision: 7504
http://sourceforge.net/p/teem/code/7504
Author: kindlmann
Date: 2025-09-28 07:53:28 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
maybe one less memory bug
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-28 07:51:51 UTC (rev 7503)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-28 07:53:28 UTC (rev 7504)
@@ -786,7 +786,6 @@
_ME_, opi, flag, MULTI_FLAG_SEP);
return (free(tbuff), 1);
}
- free(tbuff);
} else {
if (!strlen(opt[opi].flag)) {
biffAddf(HEST, "%s%sopt[%u].flag is zero length", _ME_, opi);
@@ -793,6 +792,7 @@
return (free(tbuff), 1);
}
}
+ free(tbuff);
if (hparm->respectDashBraceComments && (strchr(flag, '{') || strchr(flag, '}'))) {
biffAddf(HEST,
"%s%srequested hparm->respectDashBraceComments but opt[%u]'s flag "
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 07:51:53
|
Revision: 7503
http://sourceforge.net/p/teem/code/7503
Author: kindlmann
Date: 2025-09-28 07:51:51 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
maybe one less memory bug
Modified Paths:
--------------
teem/trunk/src/hest/parseHest.c
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-28 07:44:41 UTC (rev 7502)
+++ teem/trunk/src/hest/parseHest.c 2025-09-28 07:51:51 UTC (rev 7503)
@@ -1455,7 +1455,7 @@
hestParseFree(hestOpt *opt) {
uint optNum = opt->arrLen;
for (uint op = 0; op < optNum; op++) {
- hestArgVecNix(opt[op].havec);
+ airArrayLenSet(opt[op].havec->hargArr, 0); // but not hestArgVecNix(opt[op].havec);
opt[op].parmStr = airFree(opt[op].parmStr);
/*
printf("!hestParseFree: op = %d/%d -> kind = %d; type = %d; alloc = %d\n",
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-28 07:44:44
|
Revision: 7502
http://sourceforge.net/p/teem/code/7502
Author: kindlmann
Date: 2025-09-28 07:44:41 +0000 (Sun, 28 Sep 2025)
Log Message:
-----------
still hacking
Modified Paths:
--------------
teem/trunk/src/hest/README.md
teem/trunk/src/hest/argvHest.c
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/privateHest.h
teem/trunk/src/hest/test/ex6.c
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/README.md
===================================================================
--- teem/trunk/src/hest/README.md 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/README.md 2025-09-28 07:44:41 UTC (rev 7502)
@@ -8,6 +8,8 @@
`hest` is powerful and not simple. This note attempts to give a technical description useful for someone thinking about using `hest`, as well as anyone trying wrap their head around the `hest` source code, including its author.
+First, some examples ...
+
## Terminology and concepts
`hest` has possibly non-standard terminology for the elements of command-line parsing. Here is a bottom-up description of the command-line and what `hest` can do with it:
@@ -15,11 +17,11 @@
- What `main()` gets as `char *argv[]` is the vector of _arguments_ or _args_; each one is a `char*` string. An arg can contain spaces and other arbitrary characters if the user quoted strings or escaped characters; that is between the user and shell (the shell is responsible for taking the command-line and tokenizing it into `char *argv[]`).
- Arguments like `-v` and `-size`, which identify the variable to be set, are called _flags_.
- Some flags are really just flags; no further information is given beyond their presence or absence. Other flags introduce subsequent arguments that together supply information for setting one variable.
-- The set of arguments that logically belong together (often following a flag) in the service of setting a variable are called _parameters_ (or _parms_). There is some slippage of terminology between the `char *` string that communicates the parameter, and the value (such an `int`) parsed from the parameter string.
+- The sub-sequence of arguments that logically belong together (often following a flag) in the service of setting a variable are called _parameters_ (or _parms_). There is some slippage of terminology between the `char *` string that communicates the parameter, and the value (such an `int`) parsed from the parameter string.
- Separately, and possibly confusingly, `hest`'s behavior has many knobs and controls, stored in the `hestParm` struct. The pointer-to-struct is always named `hparm` in the code, to try to distinguish it from the parameters appearing on the command-line.
-- An _option_ determines how to set one C variable. In the C code, one `hestOpt` struct stores everything about how to parse one option, _and_ the results of that parsing. An array of `hestOpt` structs (not pointers to structs) is how a `hest`-using program communicates what it wants to learn from the command-line. The `hestOpt` array is usually built up by calls to one of the `hestOptAdd` functions.
-- On the command-line, the option may be specified by a flag and its associated parms; this is a _flagged_ option. Options may also be _unflagged_, or what others call "positional" arguments, because which C variable is set by parsing that option is disambiguated by the option's position on the command-line, and the corresponding ordering of `hestOpt` structs in the `hestOpt` array.
-- An option may have no parms, one parm, a fixed number of parms, or a variable number of parms; `hest` calls these _variadic_ options to separate the description of the options from the information (the C _variable_) that the option describes. Unflagged options must have one or more parms. With `mv *.txt dir`, the `*.txt` filenames could be parsed as a variadic parm list for an unflagged option, and `dir` would be a fixed single parm for a second unflagged option.
+- One _option_ determines how to set one C variable. In the C code, one `hestOpt` struct stores everything about how to parse one option, _and_ intermediate state during the parsing process, _and_ the final results of that parsing. An _array_ of `hestOpt` structs (which we can call an _option list_) is how a `hest`-using program communicates what it wants to learn from the command-line, and how to interpret the contents of the command-line. The `hestOpt` array is usually built up by calls to one of the `hestOptAdd` functions.
+- On the command-line, the option may be communicated by a flag (e.g. `-sz`) and its associated parms (e.g. `3 640 480`); this is a _flagged_ option. Options may also be _unflagged_, or what others call "positional" arguments, because determining which option a given argument belongs to is disambiguated by where that option's `hestOpt` struct occurs with the option list.
+- An option may have no parms, one parm, a fixed number of parms, or a variable number of parms; `hest` calls these _variadic_ options to separate the description of the options from the information (the C _variable_) that the option describes. Unflagged options must have one or more parms. With `mv *.txt dir`, the `*.txt` filenames could be parsed as the variadic parms for an unflagged option, and `dir` would be a fixed single parm for a second unflagged option.
- Sometimes multiple command-line options need to be saved and re-used together, over a time span longer than any one shell. Command-line options can thus be stored in _response files_, and the contents of response files effecively expanded into the command-line. Response files can have comments (from `#` to end of line, just like shell scripts), and response files can in turn name other response files.
- The main `hest` function that does the parsing is `hestParse`. Its job is to set one variable (which may have multiple components) for every `hestOpt`. Information for setting each variable can come from the command-line, or from the default string set in the `hestOpt`, but it has to come from somewhere. Essentially, if no default string is given, then the option _must_ be set on the command-line (or a response file named there). In this sense, `hest`'s "options" are badly named, because they are not really optional.
@@ -60,34 +62,36 @@
The `kind` of option is mostly independent of whether it is flagged or unflagged, and independent of being optional (due to the `hestOpt` having a default string) versus required (when no default is given). The one wrinkle is that unflagged options must have at least one parameter (i.e. `min` > 0), either by the command-line or via a default string. An unflagged option allowed to have zero parameters has no explicit textual existence, which seems out-of-bounds for a command-line parser. Thus for unflagged options, `kind`s 1 and 4 are ruled out, and kind 5 is possible only with `min` >= 1. This is likely already too much low-level information: users of `hest` will probably never need to worry about `kind`, and certainly `kind` is not part of the API calls to create options and parse command-lines.
-Some **concrete examples** may be helpful for understanding `hest`'s utility ... (IN PROGRESS) ...
+More examples may help show `hest`'s utility ... (IN PROGRESS) ...
... Give some specific examples, flagged and unflagged ...
.. show a response file being used, show -{ }- commenting
## The over-all process `hestParse`, its limits, and the `--` flag
-Given an `argc`,`argv` command-line and a `hestOpt` array describing the options to parse, `hestParse` must first answer: **which elements of `argv` are associated with which options?** If there are no variadic options (i.e. limiting oneself to kinds 1, 2, and 3), then the answer is straight-forward, even flagged options being able to appear on the command-line in any order. The option set has some fixed number of slots. The flag arguments for the flagged options, and the position of arguments of unflagged options, implies how to put each `argv` element into each slot.
+Given an `argc`,`argv` command-line and a `hestOpt` array describing the options to parse, `hestParse` must first answer: **which elements of `argv` are associated with which options?** If there are no variadic options (i.e. limiting oneself to kinds 1, 2, and 3), then the answer is straight-forward, even with flagged options being able to appear on the command-line in any order. The option set has some fixed number of slots. The flag arguments for the flagged options, and the position of arguments of unflagged options, implies how to put each `argv` element into each slot.
Things became more complicated with variadic options. Suppose ... two unflagged variadic options wouldn't make sense ...
Understanding how `hest` attributes arguments to options starts with knowing the main phases of `hestParse`:
-0. Validate the given `hestOpt` array
+1. Validate the given `hestOpt` array
1. Convert given `argc`,`argv`, to an internal (`hestArgVec`) representation of the argument vector (called `havec` in the code). This is the phase in which response files are expanded and `-{`,`}-` comments are interpreted.
-1. 1. Extract from `havec` all the arguments associated with flagged options: the flag args, any immediately subsequent associated parm args.
- 1. What remains in `havec` are the concatenation of args associated with the unflagged (positional) options. As long as there is at most one unflagged variadic option, there is an unambigious assignment of arguments to options.
-1. For any options not yet processed, tokenize into arguments the option's default string, and save these per-option.
-1. Finally, parse the per-option arguments to set the value(s) of C variable pointed to by each `hestOpt`. Each `hestOpt` also remembers the source of information for setting the variable (e.g. command-line vs default string).
+1. Extract from `havec` all the arguments associated with flagged options: the flag args, plus any immediately subsequent associated parm args. Arguments are transferred to the per-option arg vector within the `hestOpt` struct.
+1. What remains in the command-line `havec` should be the concatenation of args associated with the unflagged (positional) options. As long as there is at most one unflagged variadic option, there is an unambigious assignment of arguments to options, so transfer these args to their corresponding option.
+1. For any option that did not receive any args from the command-line, tokenize the option's default string and save into its per-option arg vector. Whether by command-line, response file, or default, every option should have the information it needs.
+1. Parse the per-option arg vectors (of strings) to set the value(s) of C variable pointed to by each `hestOpt`. Each `hestOpt` also remembers the source of information for setting the variable (command-line vs response-file vs default string).
Fans of [POSIX Guidelines](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02) may know that Guideline 10 describes the role of `--`:
> The first -- argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the `-` character. So `--` marks the end of some "option-arguments".
-Even though, as noted above, `hest` itself does not traffic in "operands" or follow POSIX, it does borrow `--` in a limited way to help with step 2.1 above: `--` marks the end of arguments for a _flagged_ variadic option, to demarcate them from any arguments intended for _unflagged_ options (variadic or not). In this sense, the `--` mark is more about seperating steps 2.1 and 2.2 above, than it is about separating options from operands.
+Even though, as noted above, `hest` itself does not traffic in "operands" or follow POSIX, it does borrow `--` in a limited way to help with phase 3 above: `--` marks the end of arguments for a _flagged_ variadic option, to demarcate them from any arguments intended for _unflagged_ options (variadic or not). In this sense, the `--` mark is more about seperating phases 3 and 4 above, than it is about separating options from operands.
-`hest`'s limitations in option variety and processing are:
+With this context, some further details and limitations of `hest`' processing can be outlined:
-- There can be only one _unflagged_ multiple variadic option (kind 5). Having more than one creates ambiguity about which option consumes which arguments, and `hest` currently attempts nothing (not even `--`) to resolve this. There can be, however, more than one _flagged_ multiple variadic options.
-- The `--` flag indicates the explicit end of arguments for a _flagged_ variadic option.
-- `hest` strives to interpret the entire `argv` argument vector; there is currently no way to tell `hest` (via `--` or otherwise): "stop processing `argv` here, and leave the as operands for something else to interpret".
-- Flagged options can appear in any order on the command-line, and the same option can be repeated: the last appearances over-rides all earlier appearances. `hest` currently cannot remember a list of occurance of repeated options (unlike, say, `sed -e ... -e ... `. )
+- There can be only one _unflagged_ multiple variadic option (kind 5). Having more than one could create ambiguity about which option consumes which arguments, and `hest` currently attempts nothing (not even `--`) to resolve this. There can be, however, more than one _flagged_ multiple variadic options.
+- The `--` flag indicates the explicit end of arguments for a _flagged_ variadic option. But the `--` is not necessary: any option flag also marks the end of variadic args, as does the end of the command-line.
+- `hestProc` strives to interpret the entire `argc`,`argv` argument vector you give it; there is currently no way to tell `hest` (via `--` or otherwise): "stop processing `argv` here, and leave the rest as operands for something else to interpret".
+- Arguments for options (flagged or unflagged) can only come from the user (the `argc`,`argv` command-line or a response file it invokes) or from the option's default string, but not from any mix of both: there is no way to supplement arguments from the user with those from the default string. Though it will probably be more confusing than helpful, options can get arguments from a mix of the command-line and response files, since response files are effectively expanded into the command-line prior to any per-option processing.
+- Flagged options can appear in any order on the command-line, and the same option can be repeated: the last appearance over-rides all earlier appearances. `hest` currently cannot remember a list of occurance of repeated options (unlike, say, `sed -e ... -e ... `. )
+- By their nature, unflagged options can appear at most once on the command-line, or not at all if they have a default. The attribution of arguments to unflagged options depends on the ordering of the options in the option list (later arguments are always attributed to later options), but arguments are not extracted from the command-line (and moved to the per-option arg vec) if the option has a default. .... forward and back order ...
Modified: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/argvHest.c 2025-09-28 07:44:41 UTC (rev 7502)
@@ -180,7 +180,8 @@
/* hestArgVecSprint goes is opposite of the shell-style tokenization of
parsest.c/argstGo: generate a single human-friendly string that could be tokenized to
recover the hestArgVec we started with.
-ChatGPT helped with prototyping.
+ChatGPT helped with prototyping plainWord and argAddQuotedString
+(and in this file, only those two functions)
Here are instructive examples of the same kind of argv pretty-printing:
https://github.com/git/git/blob/master/quote.c
and here https://www.opencoverage.net/coreutils/index_html/source_213.html
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/hest.h 2025-09-28 07:44:41 UTC (rev 7502)
@@ -221,8 +221,7 @@
5: min < max; max >= 2 multiple variadic parameters
This is set by hest functions as part of building up an array of hestOpt,
and informs the later action of hestOptFree */
- alloc; /* Information (set by hestParse) about whether flag is non-NULL, and what
- parameters were used, that determines whether or not memory was allocated
+ alloc; /* Information (set by hestParse) about how (if at all) memory was allocated
by hestParse(). Informs later action of hestParseFree():
0: no free()ing needed
1: free(*valueP), either because it is a single string, or because was a
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-28 07:44:41 UTC (rev 7502)
@@ -70,70 +70,121 @@
/* now (in 2025) that we've done all this work to preserve the command-line argv[]
tokens, and to properly tokenize default strings and response files, we should stop using
-the airParseStrT functions that internally did airStrtok(): we have exactly one token to
+the airParseStrT functions that internally use airStrtok(): we have exactly one token to
parse. These functions thus return non-zero in case of error, instead of returning the
number of parsed values. */
static int
-parseSingleB(void *_out, const char *str, const void *ptr) {
- AIR_UNUSED(ptr);
- // we got NULL, there's nothing to do
- if (!(_out && str)) return 1;
+parseSingleB(void *_out, const char *str, _hestPPack *hpp) {
+ if (!(_out && str && hpp)) return 1;
int *out = (int *)_out;
*out = airEnumVal(airBool, str);
- return (airEnumUnknown(airBool) /* which is -1 */ == *out);
+ int ret = airEnumUnknown(airBool) /* which is -1 */ == *out;
+ if (ret) {
+ snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "couldnt parse \"%s\" as %s", str,
+ airBool->name);
+ } else {
+ hpp->err[0] = '\0';
+ }
+ return ret;
}
-#define _PARSE_1_ARGS(type) void *out, const char *str, const void *ptr
-#define _PARSE_1_BODY(format) \
- AIR_UNUSED(ptr); \
- /* we got NULL, there's nothing to do */ \
- if (!(out && str)) return 1; \
- return (1 != airSingleSscanf(str, format, out))
+#define _PARSE_1_ARGS void *out, const char *str, _hestPPack *hpp
+#define _PARSE_1_BODY(typstr, format) \
+ if (!(out && str && hpp)) return 1; \
+ int ret = (1 != airSingleSscanf(str, format, out)); \
+ if (!strcmp("parseSingleI", __func__)) { \
+ printf("!%s: sscanf(|%s|, %s, %p)-> (ret=%d) %d\n", __func__, str, format, out, \
+ ret, *((int *)out)); \
+ } \
+ if (ret) { \
+ snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "couldn't parse \"%s\" as", typstr); \
+ } else { \
+ hpp->err[0] = '\0'; \
+ } \
+ return ret
// clang-format off
-static int parseSingleH (_PARSE_1_ARGS(short)) { _PARSE_1_BODY("%hd"); }
-static int parseSingleUH(_PARSE_1_ARGS(unsigned short)) { _PARSE_1_BODY("%hu"); }
-static int parseSingleI (_PARSE_1_ARGS(int)) { _PARSE_1_BODY("%d"); }
-static int parseSingleUI(_PARSE_1_ARGS(unsigned int)) { _PARSE_1_BODY("%u"); }
-static int parseSingleL (_PARSE_1_ARGS(long int)) { _PARSE_1_BODY("%ld"); }
-static int parseSingleUL(_PARSE_1_ARGS(unsigned long int)) { _PARSE_1_BODY("%lu"); }
-static int parseSingleZ (_PARSE_1_ARGS(size_t)) { _PARSE_1_BODY("%z"); }
-static int parseSingleF (_PARSE_1_ARGS(float)) { _PARSE_1_BODY("%f"); }
-static int parseSingleD (_PARSE_1_ARGS(double)) { _PARSE_1_BODY("%lf"); }
+static int parseSingleH (_PARSE_1_ARGS) { _PARSE_1_BODY("short", "%hd"); }
+static int parseSingleUH(_PARSE_1_ARGS) { _PARSE_1_BODY("unsigned short", "%hu"); }
+static int parseSingleI (_PARSE_1_ARGS) { _PARSE_1_BODY("int", "%d" ); }
+static int parseSingleUI(_PARSE_1_ARGS) { _PARSE_1_BODY("unsigned int", "%u" ); }
+static int parseSingleL (_PARSE_1_ARGS) { _PARSE_1_BODY("long", "%ld"); }
+static int parseSingleUL(_PARSE_1_ARGS) { _PARSE_1_BODY("unsigned long", "%lu"); }
+static int parseSingleZ (_PARSE_1_ARGS) { _PARSE_1_BODY("size_t", "%z" ); }
+static int parseSingleF (_PARSE_1_ARGS) { _PARSE_1_BODY("float", "%f" ); }
+static int parseSingleD (_PARSE_1_ARGS) { _PARSE_1_BODY("double", "%lf"); }
// clang-format on
static int
-parseSingleC(void *_out, const char *str, const void *ptr) {
- AIR_UNUSED(ptr);
- // we got NULL, there's nothing to do
- if (!(_out && str)) return 1;
- if (1 != strlen(str)) {
- // really just want single char
- return 1;
+parseSingleC(void *_out, const char *str, _hestPPack *hpp) {
+ if (!(_out && str && hpp)) return 1;
+ size_t slen = strlen(str);
+ int ret;
+ if (1 != slen) {
+ snprintf(hpp->err, AIR_STRLEN_HUGE + 1,
+ "expected single char but got string length %u", AIR_UINT(slen));
+ ret = 1;
+ } else {
+ char *out = (char *)_out;
+ *out = str[0];
+ hpp->err[0] = '\0';
+ ret = 0;
}
- char *out = (char *)_out;
- *out = str[0];
- return 0;
+ return ret;
}
static int
-parseSingleS(void *_out, const char *str, const void *ptr) {
- AIR_UNUSED(ptr);
- // we got NULL, there's nothing to do
- if (!(_out && str)) return 1;
+parseSingleS(void *_out, const char *str, _hestPPack *hpp) {
+ if (!(_out && str && hpp)) return 1;
char **out = (char **)_out;
*out = airStrdup(str);
- return !!(*out); // check that we got a non-NULL strdup
+ int ret = !(*out); // a NULL pointer result of strdup is a problem
+ if (ret) {
+ snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "airStrdup failed!");
+ } else {
+ hpp->alloc = 1;
+ airMopMem(hpp->cmop, *out, airMopOnError);
+ hpp->err[0] = '\0';
+ }
+ return ret;
}
static int
-parseSingleE(void *_out, const char *str, const void *_enm) {
- // we got NULL, there's nothing to do
- if (!(_out && str && _enm)) return 1;
+parseSingleE(void *_out, const char *str, _hestPPack *hpp) {
+ if (!(_out && str && hpp)) return 1;
int *out = (int *)_out;
- const airEnum *enm = (const airEnum *)_enm;
- *out = airEnumVal(enm, str);
- return (airEnumUnknown(enm) == *out);
+ *out = airEnumVal(hpp->enm, str);
+ int ret = (airEnumUnknown(hpp->enm) == *out);
+ if (ret) {
+ snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "couldn't parse \"%s\" as %s", str,
+ hpp->enm->name);
+ } else {
+ hpp->err[0] = '\0';
+ }
+ return ret;
}
+static int
+parseSingleO(void *out, const char *str, _hestPPack *hpp) {
+ if (!(out && str && hpp)) return 1;
+ char myerr[AIR_STRLEN_HUGE + 1];
+ int ret = hpp->CB->parse(out, str, myerr);
+ if (ret) {
+ if (strlen(myerr)) {
+ snprintf(hpp->err, AIR_STRLEN_HUGE + 1, "error parsing \"%s\" as %s:\n%s\n", str,
+ hpp->CB->type, myerr);
+ } else {
+ snprintf(hpp->err, AIR_STRLEN_HUGE + 1,
+ "error parsing \"%s\" as %s: returned %d\n", str, hpp->CB->type, ret);
+ }
+ } else {
+ if (hpp->CB->destroy) {
+ /* out is the address of a void*, we manage the void* */
+ hpp->alloc = 1;
+ airMopAdd(hpp->cmop, (void **)out, (airMopper)airSetNull, airMopOnError);
+ airMopAdd(hpp->cmop, *((void **)out), hpp->CB->destroy, airMopOnError);
+ }
+ }
+ return ret;
+}
-int (*const _hestParseSingle[_HEST_TYPE_MAX + 1])(void *, const char *, const void *) = {
+int (*const _hestParseSingle[_HEST_TYPE_MAX + 1])(void *, const char *, _hestPPack *) = {
NULL, //
parseSingleB, //
parseSingleH, //
@@ -147,8 +198,8 @@
parseSingleD, //
parseSingleC, //
parseSingleS, //
- parseSingleE,
- NULL // "other"
+ parseSingleE, //
+ parseSingleO //
};
#define _INVERT_SCALAR(TT, ctype) \
@@ -501,6 +552,10 @@
opt->source = hestSourceUnknown;
opt->parmStr = NULL;
opt->helpWanted = AIR_FALSE;
+
+ if (airTypeInt == type && 1 == min && 1 == max) {
+ printf("!something like %s: got valueP %p\n", "hestOptAdd_1_Int", AIR_VOIDP(valueP));
+ }
return;
}
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/parsest.c 2025-09-28 07:44:41 UTC (rev 7502)
@@ -88,7 +88,7 @@
(although hest does not do rule 5 about parameter expansion, command substitution,
or arithmetic expansion), and here are the details about quoting:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02
-ChatGPT helped with prototyping.
+ChatGPT helped with prototyping argstGo (and in this file, only that function)
Here is instructive example code https://github.com/nyuichi/dash.git
in src/parser.c see the readtoken1() function and the DFA there.
*/
@@ -670,11 +670,9 @@
/* whichOptFlag(): for which option (by index) is this the flag?
-Given an arg string `flarg` (which may be an flag arg like "-size" or parm arg like
-"512"), this finds which one, of the options in the given hestOpt array `opt` is
-identified by `flarg`. Returns the index of the matching option, if there is a match.
-
-If there is no match, returns UINT_MAX.
+Given an arg string `flarg` (which may be an flag arg (like "-size") or not (like "512"),
+this finds which one, of the options in the given hestOpt array `opt`, is identified by
+`flarg`. If there is a match, returns the index of that option, else returns UINT_MAX.
*/
static uint
whichOptFlag(const hestOpt *opt, const char *flarg, const hestParm *hparm) {
@@ -735,13 +733,11 @@
}
/* havecTransfer
-(if `num`) moves `num` args from `hvsrc` (starting at `srcIdx`) to `opt->havec`
-This takes `hestOpt *opt` instead of `opt->havec` so that we can also take this
-time to set `opt->source` according to the incoming `hvsrc->harg[]->source`. To
-minimize cleverness, we set `opt->source` with every transferred argument, which
-means that the per-option source remembered is the source of the *last* argument of the
-option.
-*/
+(if `num`) moves `num` args from `hvsrc` (starting at `srcIdx`) to `opt->havec`. This
+takes `hestOpt *opt` instead of `opt->havec` so that we can also set `opt->source`
+according to the incoming `hvsrc->harg[]->source`. To minimize cleverness, we set
+`opt->source` with every transferred argument, which means that the per-option source
+remembered is the source of the *last* argument of the option. */
static int
havecTransfer(hestOpt *opt, hestArgVec *hvsrc, uint srcIdx, uint num,
const hestParm *hparm) {
@@ -761,7 +757,7 @@
hvsrc->len, num, srcIdx);
return 1;
}
- // okay now do the work, starting with empty destination havec
+ // okay now do the work, starting with emptying destination havec
hestArgVecReset(opt->havec);
for (uint ai = 0; ai < num; ai++) {
hestArg *harg = hestArgVecRemove(hvsrc, srcIdx);
@@ -856,7 +852,7 @@
AIR_INT(parmNum) < _hestMax(theOpt->max)
// and looking ahead by parmNum still gives us a valid index pai
&& !(hitEnd = !((pai = argIdx + 1 + parmNum) < havec->len))
- // and either this isn't a variadic parm opt
+ // and either this isn't a flagged variadic opt
&& (!varParm || // or, it is a varparm opt, and we aren't looking at "--"
!(hitVPS = !strcmp(VPS, havec->harg[pai]->str)))
&& UINT_MAX // and we aren't looking at start of another flagged option
@@ -990,7 +986,7 @@
with a little Nx2 array ufOpi2 of option indices */
uint *ufOpi2 = NULL;
if (!ufOptNum) {
- /* no unflagged options; we're ~done */
+ /* no unflagged options; we're done-ish */
goto finishingup;
}
ufOpi2 = AIR_CALLOC(2 * ufOptNum, uint);
@@ -1043,10 +1039,10 @@
if (hparm->verbosity) {
printf("%s: looking at opi = %u kind %d\n", __func__, opi, opt[opi].kind);
}
- /* Either we're not using the defaults because we know we have enough args,
- else we know we do not have enough args and yet we also don't have a default.
- Either way, we try extracting the args; in the later case just to generate a
- descriptive error message about the situation */
+ /* Either we have enough args to satisfy this option (and thus don't care if it has a
+ default), or, we do *not* have enough args and hence want to use the default. In the
+ later case, we don't have a default, that's a problem that needs an error message.
+ So, either way, we try extracting the args and report any problems encountered. */
if (opt[opi].min /* == max */ < havec->len || !opt[opi].dflt) {
havStr = hestArgVecSprint(havec, AIR_TRUE);
if (havecTransfer(opt + opi, havec, 0, opt[opi].min, hparm)) {
@@ -1075,7 +1071,7 @@
}
// same logic as above
if (opt[opi].min /* == max */ < havec->len || !opt[opi].dflt) {
- uint idx0 = (opt[opi].min < havec->len //
+ uint idx0 = (opt[opi].min < havec->len // index of first arg for this option
? havec->len - opt[opi].min //
: 0);
havStr = hestArgVecSprint(havec, AIR_TRUE);
@@ -1089,8 +1085,7 @@
}
}
- /* now, finally, we grab the parameters of the sole variadic parameter unflagged opt;
- the one with index ufVarOpi < optNum (and we're only here because it exists) */
+ // We're here because there is an unflagged variadic option (index ufVarOpi < optNum)
if (hparm->verbosity) {
printf("%s: ufVarOpi=%u min, have, max = %u %u %d\n", __func__, ufVarOpi,
opt[ufVarOpi].min, havec->len, _hestMax(opt[ufVarOpi].max));
@@ -1109,35 +1104,33 @@
if (minArg <= havec->len) {
// can satisfy option from havec, no need to use default
uint getArg = havec->len; // want to grab as many args as possible
- if (-1 != opt[ufVarOpi].max) { // but no more than needed
+ if (-1 != opt[ufVarOpi].max) { // but no more than the option asks for
getArg = AIR_MIN(getArg, AIR_UINT(opt[ufVarOpi].max));
}
if (havecTransfer(opt + ufVarOpi, havec, 0, getArg, hparm)) {
havStr = hestArgVecSprint(havec, AIR_TRUE);
biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
- biffAddf(HEST, "%s%strouble getting args for variadic unflagged %s[%u]", _ME_,
+ biffAddf(HEST, "%s%strouble getting args for unflagged variadic %s[%u]", _ME_,
identStr(ident, opt + ufVarOpi), ufVarOpi);
return (free(havStr), free(ufOpi2), 1);
}
}
- // else minArg > havec->len so can't satisfy from havec,
- // but its ok since we do have default
+ /* else minArg > havec->len so can't satisfy from havec, but that's ok for
+ opt[ufVarOpi] since it has default. The erroneous presence of extraneous args will be
+ caught next */
- /* make sure that unflagged options without default were given */
+finishingup:
+
+ // make sure that unflagged options without default were given
for (upii = 0; upii < ufOptNum; upii++) {
uint opi = ufOpi2[2 * upii + 0];
if (!(opt[opi].dflt) && hestSourceUnknown == opt[opi].source) {
- biffAddf(HEST, "%s%sdidn't see required (default-less) unflagged %s[%u]", _ME_,
+ biffAddf(HEST, "%s%sdidn't get required (default-less) unflagged %s[%u]", _ME_,
identStr(ident, opt + opi), opi);
return (free(ufOpi2), 1);
}
}
-
-finishingup:
- if (hparm->verbosity) {
- optAllPrint(__func__, "end of havecExtractUnflagged", opt);
- hestArgVecPrint(__func__, "end of havecExtractUnflagged", havec);
- }
+ // currently it's an error to have un-accounted-for args left overå
if (havec->len) {
havStr = hestArgVecSprint(havec, AIR_TRUE);
biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
@@ -1148,6 +1141,11 @@
havec->len > 1 ? "starting with " : "", havec->harg[0]->str);
return (free(havStr), airFree(ufOpi2), 1);
}
+
+ if (hparm->verbosity) {
+ optAllPrint(__func__, "end of havecExtractUnflagged", opt);
+ hestArgVecPrint(__func__, "end of havecExtractUnflagged", havec);
+ }
return (airFree(havStr), airFree(ufOpi2), 0);
}
@@ -1238,12 +1236,12 @@
}
/* optSetValues
-Does the parsing of opt[opi].havec to set values in whatever opt[opi].valueP points to.
-The parent mop `pmop` is passed so that we can remember what to free up ONLY IN CASE OF
-ERROR. Otherwise, the allocations persist with the successful return of hestParse(2), and
-are freed with hestParseFree. */
+Finally: the parsing of opt[opi].havec to set values in whatever opt[opi].valueP points
+to. The parent mop `pmop` is passed so that we can remember what to free up ONLY IN CASE
+OF ERROR. Otherwise, the allocations persist (pointed to by fields in hestOpt) with the
+successful return of hestParse(2), and are freed with hestParseFree. */
static int
-optSetValues(hestOpt *opt, const hestParm *hparm, airArray *pmop) {
+optSetValues(hestOpt *opt, const hestParm *hparm, airArray *cmop) {
char ident[AIR_STRLEN_HUGE + 1];
/*
char cberr[AIR_STRLEN_HUGE + 1], *tok, *last, *optParmsCopy;
@@ -1253,7 +1251,6 @@
void *valueP;
char *cvalueP;
int *ivalueP;
-
uint optNum = opt->arrLen;
for (uint opi = 0; opi < optNum; opi++) {
identStr(ident, opt + opi);
@@ -1287,9 +1284,20 @@
if (opt[opi].sawP) {
*(opt[opi].sawP) = 0;
}
+ _hestPPack _hpp;
+ _hestPPack *hpp;
+ if (1 == opt[opi].kind) {
+ hpp = NULL;
+ } else {
+ hpp = &_hpp;
+ hpp->cmop = cmop;
+ hpp->enm = opt[opi].enm; // will be non-NULL when needed
+ hpp->CB = opt[opi].CB;
+ hpp->alloc = 0; // may get over-written
+ // hpp->err set by parseSingleT
+ }
switch (opt[opi].kind) {
- case 1:
- /* -------- parameter-less boolean flags -------- */
+ case 1: // -------- parameter-less boolean flags --------
/* valueP is always assumed to be an int* */
*ivalueP = hestSourceDefault != opt[opi].source;
if (hparm->verbosity) {
@@ -1296,10 +1304,9 @@
printf(" --> set value %d\n", *ivalueP);
}
break;
- case 4: {
+ case 4: { // -------- optional single variadics --------
const char *strsrc;
int invert;
- /* -------- optional single variadics -------- */
/* 2025 _hestOPCheck now restricts possible types; these are no longer allowed:
airTypeChar, airTypeString, airTypeEnum, airTypeOther. As for the semantics,
the old web page seems to be clear (though we now disallow unflagged kind 4):
@@ -1310,7 +1317,7 @@
(*this* is the "inversion" that is mentioned at places in the code)
- option flag appears, with single parm
--> value is set from parsing that parm
- In any case, some string has to be parsed */
+ In any case, some string has to be parsed; we call it `strsrc` */
if (hestSourceDefault == opt[opi].source) {
// option flag does not appear
strsrc = opt[opi].dflt;
@@ -1328,7 +1335,7 @@
opi, airEnumStr(hestSource, opt[opi].source), opt[opi].havec->len);
return 1;
}
- if (_hestParseSingle[type](valueP, strsrc, NULL /* because type simple */)) {
+ if (_hestParseSingle[type](valueP, strsrc, hpp)) {
biffAddf(HEST, "%s%sfor %s[%u] could not parse |%s| as single %s", _ME_, ident,
opi, strsrc, _hestTypeStr[type]);
return 1;
@@ -1338,67 +1345,14 @@
}
break;
} // end case 4 {
-#if 0
- case 2:
- /* -------- one required parameter -------- */
- /* 2023 GLK is really curious why "if (optParms[op] && valueP) {" is (repeatedly)
- guarding all the work in these blocks, and why that wasn't factored out */
- if (optParms[opi] && valueP) {
- switch (type) {
- case airTypeEnum:
- if (1 != airParseStrE((int *)valueP, optParms[opi], " ", 1, opt[opi].enm)) {
- fprintf(stderr, "%scouldn\'t parse %s\"%s\" as %s for %s\n", ME,
- optDfltd[opi] ? "(default) " : "", optParms[opi], opt[opi].enm->name,
- ident);
- return 1;
- }
- break;
- case airTypeOther:
- strcpy(cberr, "");
- ret = opt[opi].CB->parse(valueP, optParms[opi], cberr);
- if (ret) {
- if (strlen(cberr)) {
- fprintf(stderr, "%serror parsing \"%s\" as %s for %s:\n%s\n", ME,
- optParms[opi], opt[opi].CB->type, ident, cberr);
- } else {
- fprintf(stderr, "%serror parsing \"%s\" as %s for %s: returned %d\n", ME,
- optParms[opi], opt[opi].CB->type, ident, ret);
- }
- return ret;
- }
- if (opt[opi].CB->destroy) {
- /* vP is the address of a void*, we manage the void * */
- opt[opi].alloc = 1;
- airMopAdd(pmop, (void **)valueP, (airMopper)airSetNull, airMopOnError);
- airMopAdd(pmop, *((void **)valueP), opt[opi].CB->destroy, airMopOnError);
- }
- break;
- case airTypeString:
- if (1
- != airParseStrS((char **)valueP, optParms[opi], " ", 1
- /*, hparm->greedySingleString */)) {
- fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
- optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
- ident);
- return 1;
- }
- /* vP is the address of a char* (a char **), but what we
- manage with airMop is the char * */
- opt[opi].alloc = 1;
- airMopMem(pmop, valueP, airMopOnError);
- break;
- default:
- /* type isn't string or enum, so no last arg to hestParseStr[type] */
- if (1 != _hestParseStr[type](valueP, optParms[opi], " ", 1)) {
- fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
- optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
- ident);
- return 1;
- }
- break;
- }
+ case 2: // -------- one required parameter --------
+ if (_hestParseSingle[type](valueP, opt[opi].havec->harg[0]->str, hpp)) {
+ biffAddf(HEST, "%s%sproblem parsing for %s[%u]", _ME_, ident, opi);
+ return 1;
}
+ opt[opi].alloc = hpp->alloc;
break;
+#if 0
case 3:
/* -------- multiple required parameters -------- */
if (optParms[opi] && valueP) {
Modified: teem/trunk/src/hest/privateHest.h
===================================================================
--- teem/trunk/src/hest/privateHest.h 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/privateHest.h 2025-09-28 07:44:41 UTC (rev 7502)
@@ -72,8 +72,15 @@
HEST_EXPORT const char _hestTypeStr[_HEST_TYPE_MAX + 1][AIR_STRLEN_SMALL + 1];
HEST_EXPORT const size_t _hestTypeSize[_HEST_TYPE_MAX + 1];
HEST_EXPORT void (*const _hestInvertScalar[_HEST_TYPE_MAX + 1])(void *);
+typedef struct {
+ airArray *cmop; // caller's mop to clean up things if airMopError
+ const airEnum *enm; // for parsing an airTypeEnum value
+ const hestCB *CB; // for parsing an airTypeOther
+ int alloc; // our single-arg parsing work allocated something
+ char err[AIR_STRLEN_HUGE + 1]; // error message can go for any type
+} _hestPPack;
HEST_EXPORT int (*const _hestParseSingle[_HEST_TYPE_MAX + 1])(void *, const char *,
- const void *);
+ _hestPPack *);
// HEY these are sticking around just for the old implementation of hestParse
HEST_EXPORT unsigned int (*const _hestParseStr[_HEST_TYPE_MAX + 1])(void *, const char *,
const char *,
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-28 07:44:41 UTC (rev 7502)
@@ -47,7 +47,7 @@
ptrP = _ptr;
ptr = (*ptrP) = AIR_MALLOC(1, Quat);
- /* printf("%s: ptrP = %p ---malloc--> ptr = *ptrP = %p\n", __func__, ptrP, *ptrP); */
+ printf("%s: ptrP = %p ---malloc--> ptr = *ptrP = %p\n", __func__, ptrP, *ptrP);
ptr->str = NULL;
if (1 != sscanf(str, "%lf", &(ptr->val))) {
sprintf(err, "didn't parse a double from %s", str);
@@ -84,7 +84,7 @@
hparm->respectDashDashHelp = AIR_TRUE;
hparm->noArgsIsNoProblem = AIR_TRUE;
hparm->dieLessVerbose = AIR_TRUE;
- hparm->verbosity = 1;
+ hparm->verbosity = 0;
opt = NULL;
/* going past C89 to have declarations here */
@@ -91,38 +91,6 @@
int flag;
hestOptAdd_Flag(&opt, "f,flag", &flag, "a flag created via hestOptAdd_Flag");
- int b1;
- hestOptAdd_1_Bool(&opt, "b1", "bool1", &b1, "false", "test of hestOptAdd_1_Bool");
- int i1;
- hestOptAdd_1_Int(&opt, "i1", "int1", &i1, "42", "test of hestOptAdd_1_Int");
- unsigned int ui1;
- hestOptAdd_1_UInt(&opt, "ui1", "uint1", &ui1, "42", "test of hestOptAdd_1_UInt");
- long int li1;
- hestOptAdd_1_Long(&opt, "li1", "lint1", &li1, "42", "test of hestOptAdd_1_Long");
- unsigned long int uli1;
- hestOptAdd_1_ULong(&opt, "uli1", "ulint1", &uli1, "42", "test of hestOptAdd_1_ULong");
- size_t sz1;
- hestOptAdd_1_Size_t(&opt, "sz1", "size1", &sz1, "42", "test of hestOptAdd_1_Size_t");
- float fl1;
- hestOptAdd_1_Float(&opt, "fl1", "float1", &fl1, "4.2", "test of hestOptAdd_1_Float");
- double db1;
- hestOptAdd_1_Double(&opt, "db1", "double1", &db1, "4.2",
- "test of hestOptAdd_1_Double");
- char c1;
- hestOptAdd_1_Char(&opt, "c1", "char1", &c1, "x", "test of hestOptAdd_1_Char");
- char *s1;
- hestOptAdd_1_String(&opt, "s1", "string1", &s1, "\"bingo bob\"",
- "test of hestOptAdd_1_String");
- int e1;
- hestOptAdd_1_Enum(&opt, "e1", "enum1", &e1, "little", "test of hestOptAdd_1_Enum",
- airEndian);
- double p1[2];
- hestOptAdd_1_Other(&opt, "p1", "pos", &p1, "1.5,5.25", "test of hestOptAdd_1_Other A",
- &posCB);
- Quat *q1;
- hestOptAdd_1_Other(&opt, "q1", "quat", &q1, "12.34", "test of hestOptAdd_1_Other B",
- &quatCB);
-
int b1v;
hestOptAdd_1v_Bool(&opt, "b1v", "bool1", &b1v, "false", "test of hestOptAdd_1v_Bool");
int i1v;
@@ -159,6 +127,42 @@
hestOptAdd_1v_Other(&opt, "q1v", "quat", &q1v, "12.34",
"test of hestOptAdd_1v_Other B", &quatCB);
*/
+ int b1;
+ hestOptAdd_1_Bool(&opt, "b1", "bool1", &b1, "false", "test of hestOptAdd_1_Bool");
+ int i1;
+ printf("!%s: &i1 = %p (passed to hestOptAdd_1_Int)\n", __func__, AIR_VOIDP(&i1));
+ hestOptAdd_1_Int(&opt, "i1", "int1", &i1, "42", "test of hestOptAdd_1_Int");
+ unsigned int ui1;
+ hestOptAdd_1_UInt(&opt, "ui1", "uint1", &ui1, "42", "test of hestOptAdd_1_UInt");
+ long int li1;
+ hestOptAdd_1_Long(&opt, "li1", "lint1", &li1, "42", "test of hestOptAdd_1_Long");
+ unsigned long int uli1;
+ hestOptAdd_1_ULong(&opt, "uli1", "ulint1", &uli1, "42", "test of hestOptAdd_1_ULong");
+ size_t sz1;
+ hestOptAdd_1_Size_t(&opt, "sz1", "size1", &sz1, "42", "test of hestOptAdd_1_Size_t");
+ float fl1;
+ hestOptAdd_1_Float(&opt, "fl1", "float1", &fl1, "4.2", "test of hestOptAdd_1_Float");
+ double db1;
+ hestOptAdd_1_Double(&opt, "db1", "double1", &db1, "4.2",
+ "test of hestOptAdd_1_Double");
+ char c1;
+ hestOptAdd_1_Char(&opt, "c1", "char1", &c1, "x", "test of hestOptAdd_1_Char");
+ /*
+ char *s1;
+ hestOptAdd_1_String(&opt, "s1", "string1", &s1, "\"bingo bob\"",
+ "test of hestOptAdd_1_String");
+ int e1;
+ hestOptAdd_1_Enum(&opt, "e1", "enum1", &e1, "little", "test of hestOptAdd_1_Enum",
+ airEndian);
+ double p1[2];
+ hestOptAdd_1_Other(&opt, "p1", "pos", &p1, "1.5,5.25", "test of hestOptAdd_1_Other A",
+ &posCB);
+ Quat *q1;
+ hestOptAdd_1_Other(&opt, "q1", "quat", &q1, "12.34", "test of hestOptAdd_1_Other B",
+ &quatCB);
+ */
+
+#if 0
int b2[2];
hestOptAdd_2_Bool(&opt, "b2", "bool1 bool2", b2, "true false",
"test of hestOptAdd_2_Bool");
@@ -375,6 +379,7 @@
unsigned int qvSaw;
hestOptAdd_Nv_Other(&opt, "qv", "quat1", 1, -1, &qv, "12.34 43.21",
"test of hestOptAdd_Nv_Other B", &qvSaw, &quatCB);
+#endif
hestParse2(opt, argc - 1, argv + 1, NULL, hparm);
/*
hestParseOrDie(opt, argc - 1, argv + 1, hparm, argv[0], info, AIR_TRUE, AIR_TRUE,
@@ -414,7 +419,6 @@
*/
printf("\n");
-#if 0
printf("b1 = %d\n", b1);
printf("i1 = %d\n", i1);
printf("ui1 = %u\n", ui1);
@@ -424,12 +428,15 @@
printf("fl1 = %g\n", fl1);
printf("db1 = %g\n", db1);
printf("c1 = |%c| (%d)\n", c1, c1);
+ /*
printf("s1 = |%s|\n", s1);
printf("e1 = %d\n", e1);
printf("p1 = %g,%g\n", p1[0], p1[1]);
printf("q1 (@ %p) = %g(%s)\n", q1, q1->val, q1->str);
+ */
printf("\n");
+#if 0
printf("b2 = %d %d\n", b2[0], b2[1]);
printf("i2 = %d %d\n", i2[0], i2[1]);
printf("ui2 = %u %u\n", ui2[0], ui2[1]);
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-26 11:50:43 UTC (rev 7501)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-28 07:44:41 UTC (rev 7502)
@@ -47,11 +47,12 @@
unsigned int slen;
hestOptAdd_Nv_Int(&opt, "s,sizes", "sx sy", 2, -1, &size, NULL, "image resolutions",
&slen);
-
+#if 0
int *unpB;
unsigned int sawB;
hestOptAdd_Nv_Int(&opt, NULL, "B B", 2, -1, &unpB, /* "BBBB" */ NULL, "unflagged B",
&sawB);
+#endif
/* int unpB[2];
hestOptAdd_2_Int(&opt, NULL, "B B", unpB, NULL, "unflagged B"); */
int unpC[2];
@@ -68,7 +69,7 @@
ret = 1;
}
if (opt->helpWanted) {
- printf("%s: help wanted!\n", argv[0]);
+ printf("\n\n%s: help wanted!\n\n\n", argv[0]);
}
hestOptFree(opt);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-26 11:50:46
|
Revision: 7501
http://sourceforge.net/p/teem/code/7501
Author: kindlmann
Date: 2025-09-26 11:50:43 +0000 (Fri, 26 Sep 2025)
Log Message:
-----------
debugging ...
Modified Paths:
--------------
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-26 11:47:39 UTC (rev 7500)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-26 11:50:43 UTC (rev 7501)
@@ -397,21 +397,6 @@
printf("(err = %s)\n", err ? err : "(null)");
printf("flag = %d\n\n", flag);
- printf("b1 = %d\n", b1);
- printf("i1 = %d\n", i1);
- printf("ui1 = %u\n", ui1);
- printf("li1 = %ld\n", li1);
- printf("uli1 = %lu\n", uli1);
- printf("sz1 = %zu\n", sz1);
- printf("fl1 = %g\n", fl1);
- printf("db1 = %g\n", db1);
- printf("c1 = |%c| (%d)\n", c1, c1);
- printf("s1 = |%s|\n", s1);
- printf("e1 = %d\n", e1);
- printf("p1 = %g,%g\n", p1[0], p1[1]);
- printf("q1 (@ %p) = %g(%s)\n", q1, q1->val, q1->str);
- printf("\n");
-
printf("b1v = %d\n", b1v);
printf("i1v = %d\n", i1v);
printf("ui1v = %u\n", ui1v);
@@ -430,6 +415,21 @@
printf("\n");
#if 0
+ printf("b1 = %d\n", b1);
+ printf("i1 = %d\n", i1);
+ printf("ui1 = %u\n", ui1);
+ printf("li1 = %ld\n", li1);
+ printf("uli1 = %lu\n", uli1);
+ printf("sz1 = %zu\n", sz1);
+ printf("fl1 = %g\n", fl1);
+ printf("db1 = %g\n", db1);
+ printf("c1 = |%c| (%d)\n", c1, c1);
+ printf("s1 = |%s|\n", s1);
+ printf("e1 = %d\n", e1);
+ printf("p1 = %g,%g\n", p1[0], p1[1]);
+ printf("q1 (@ %p) = %g(%s)\n", q1, q1->val, q1->str);
+ printf("\n");
+
printf("b2 = %d %d\n", b2[0], b2[1]);
printf("i2 = %d %d\n", i2[0], i2[1]);
printf("ui2 = %u %u\n", ui2[0], ui2[1]);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-26 11:47:42
|
Revision: 7500
http://sourceforge.net/p/teem/code/7500
Author: kindlmann
Date: 2025-09-26 11:47:39 +0000 (Fri, 26 Sep 2025)
Log Message:
-----------
debugging ...
Modified Paths:
--------------
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-26 11:40:03 UTC (rev 7499)
+++ teem/trunk/src/hest/parsest.c 2025-09-26 11:47:39 UTC (rev 7500)
@@ -1228,7 +1228,7 @@
int haveArg = AIR_INT(opt[opi].havec->len);
if (!(AIR_INT(opt[opi].min) <= haveArg && haveArg <= maxArg)) {
biffAddf(HEST,
- "%s%s %s[%u] got (from user or from default) %u args, but that is "
+ "%s%s%s[%u] got (from user or from default) %u args, but that is "
"outside [min,max]=[%u,%d] range",
_ME_, ident, opi, opt[opi].havec->len, opt[opi].min, maxArg);
return 1;
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-26 11:40:03 UTC (rev 7499)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-26 11:47:39 UTC (rev 7500)
@@ -84,7 +84,7 @@
hparm->respectDashDashHelp = AIR_TRUE;
hparm->noArgsIsNoProblem = AIR_TRUE;
hparm->dieLessVerbose = AIR_TRUE;
- hparm->verbosity = 0;
+ hparm->verbosity = 1;
opt = NULL;
/* going past C89 to have declarations here */
@@ -111,7 +111,7 @@
char c1;
hestOptAdd_1_Char(&opt, "c1", "char1", &c1, "x", "test of hestOptAdd_1_Char");
char *s1;
- hestOptAdd_1_String(&opt, "s1", "string1", &s1, "bingo bob",
+ hestOptAdd_1_String(&opt, "s1", "string1", &s1, "\"bingo bob\"",
"test of hestOptAdd_1_String");
int e1;
hestOptAdd_1_Enum(&opt, "e1", "enum1", &e1, "little", "test of hestOptAdd_1_Enum",
@@ -376,7 +376,6 @@
hestOptAdd_Nv_Other(&opt, "qv", "quat1", 1, -1, &qv, "12.34 43.21",
"test of hestOptAdd_Nv_Other B", &qvSaw, &quatCB);
hestParse2(opt, argc - 1, argv + 1, NULL, hparm);
- exit(0);
/*
hestParseOrDie(opt, argc - 1, argv + 1, hparm, argv[0], info, AIR_TRUE, AIR_TRUE,
AIR_TRUE);
@@ -421,7 +420,7 @@
printf("sz1v = %zu\n", sz1v);
printf("fl1v = %g\n", fl1v);
printf("db1v = %g\n", db1v);
- /*
+ /* gone in 2025
printf("c1v = |%c| (%d)\n", c1v, c1v);
printf("s1v = |%s|\n", s1v);
printf("e1v = %d\n", e1v);
@@ -430,6 +429,7 @@
*/
printf("\n");
+#if 0
printf("b2 = %d %d\n", b2[0], b2[1]);
printf("i2 = %d %d\n", i2[0], i2[1]);
printf("ui2 = %u %u\n", ui2[0], ui2[1]);
@@ -561,6 +561,7 @@
}
printf("\n");
+#endif
/* free the memory allocated by parsing ... */
hestParseFree(opt);
/* ... and the other stuff */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-26 11:40:06
|
Revision: 7499
http://sourceforge.net/p/teem/code/7499
Author: kindlmann
Date: 2025-09-26 11:40:03 +0000 (Fri, 26 Sep 2025)
Log Message:
-----------
fixing pointer glitch
Modified Paths:
--------------
teem/trunk/src/hest/parsest.c
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-26 11:35:14 UTC (rev 7498)
+++ teem/trunk/src/hest/parsest.c 2025-09-26 11:40:03 UTC (rev 7499)
@@ -978,7 +978,7 @@
*/
static int
havecExtractUnflagged(hestOpt *opt, hestArgVec *havec, const hestParm *hparm) {
- char *havStr, ident[AIR_STRLEN_HUGE + 1];
+ char *havStr = NULL, ident[AIR_STRLEN_HUGE + 1];
uint optNum = opt->arrLen; // number of options (flagged or unflagged)
uint ufOptNum = 0; // number of unflagged options
for (uint opi = 0; opi < optNum; opi++) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-26 11:35:18
|
Revision: 7498
http://sourceforge.net/p/teem/code/7498
Author: kindlmann
Date: 2025-09-26 11:35:14 +0000 (Fri, 26 Sep 2025)
Log Message:
-----------
updating information about what happened to airParseStr[], though it is not quite try yet
Modified Paths:
--------------
teem/trunk/src/air/air.h
Modified: teem/trunk/src/air/air.h
===================================================================
--- teem/trunk/src/air/air.h 2025-09-26 11:33:53 UTC (rev 7497)
+++ teem/trunk/src/air/air.h 2025-09-26 11:35:14 UTC (rev 7498)
@@ -468,16 +468,16 @@
* *** added airTypeShort and airTypeUShort
* *** renamed airTypeLongInt --> airTypeLong
* *** renamed airTypeULongInt --> airTypeULong
- *** Removed the following from air to hest, renamed them, and made them private.
+ *** Moved the following from air to hest, renamed them, and made them private.
* They were only used to implement hest, no where else in Teem, so they never
* deserved to be in air:
* #define AIR_TYPE_MAX --> _HEST_TYPE_MAX
* const char airTypeStr[HEST_TYPE_MAX + 1][AIR_STRLEN_SMALL + 1] --> _hestTypeStr
* const size_t airTypeSize[HEST_TYPE_MAX + 1] --> _hestTypeSize
+ *** Removed the following, since it was only used in the pre-TeemV2 hest
* unsigned int (*const airParseStr[AIR_TYPE_MAX + 1])(void *,
* const char *, *const char *,
* *unsigned int);
- * --> _hestParseStr
*/
/* parseAir.c */
AIR_EXPORT double airAtod(const char *str);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-26 11:33:58
|
Revision: 7497
http://sourceforge.net/p/teem/code/7497
Author: kindlmann
Date: 2025-09-26 11:33:53 +0000 (Fri, 26 Sep 2025)
Log Message:
-----------
still hacking
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/privateHest.h
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-26 11:32:56 UTC (rev 7496)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-26 11:33:53 UTC (rev 7497)
@@ -64,10 +64,133 @@
sizeof(char),
sizeof(char*),
sizeof(int),
- 0 /* we don't know anything about type "other" */
+ 0 /* we don't know anything about size of type "other" */
};
/* clang-format on */
+/* now (in 2025) that we've done all this work to preserve the command-line argv[]
+tokens, and to properly tokenize default strings and response files, we should stop using
+the airParseStrT functions that internally did airStrtok(): we have exactly one token to
+parse. These functions thus return non-zero in case of error, instead of returning the
+number of parsed values. */
+static int
+parseSingleB(void *_out, const char *str, const void *ptr) {
+ AIR_UNUSED(ptr);
+ // we got NULL, there's nothing to do
+ if (!(_out && str)) return 1;
+ int *out = (int *)_out;
+ *out = airEnumVal(airBool, str);
+ return (airEnumUnknown(airBool) /* which is -1 */ == *out);
+}
+
+#define _PARSE_1_ARGS(type) void *out, const char *str, const void *ptr
+#define _PARSE_1_BODY(format) \
+ AIR_UNUSED(ptr); \
+ /* we got NULL, there's nothing to do */ \
+ if (!(out && str)) return 1; \
+ return (1 != airSingleSscanf(str, format, out))
+
+// clang-format off
+static int parseSingleH (_PARSE_1_ARGS(short)) { _PARSE_1_BODY("%hd"); }
+static int parseSingleUH(_PARSE_1_ARGS(unsigned short)) { _PARSE_1_BODY("%hu"); }
+static int parseSingleI (_PARSE_1_ARGS(int)) { _PARSE_1_BODY("%d"); }
+static int parseSingleUI(_PARSE_1_ARGS(unsigned int)) { _PARSE_1_BODY("%u"); }
+static int parseSingleL (_PARSE_1_ARGS(long int)) { _PARSE_1_BODY("%ld"); }
+static int parseSingleUL(_PARSE_1_ARGS(unsigned long int)) { _PARSE_1_BODY("%lu"); }
+static int parseSingleZ (_PARSE_1_ARGS(size_t)) { _PARSE_1_BODY("%z"); }
+static int parseSingleF (_PARSE_1_ARGS(float)) { _PARSE_1_BODY("%f"); }
+static int parseSingleD (_PARSE_1_ARGS(double)) { _PARSE_1_BODY("%lf"); }
+// clang-format on
+static int
+parseSingleC(void *_out, const char *str, const void *ptr) {
+ AIR_UNUSED(ptr);
+ // we got NULL, there's nothing to do
+ if (!(_out && str)) return 1;
+ if (1 != strlen(str)) {
+ // really just want single char
+ return 1;
+ }
+ char *out = (char *)_out;
+ *out = str[0];
+ return 0;
+}
+static int
+parseSingleS(void *_out, const char *str, const void *ptr) {
+ AIR_UNUSED(ptr);
+ // we got NULL, there's nothing to do
+ if (!(_out && str)) return 1;
+ char **out = (char **)_out;
+ *out = airStrdup(str);
+ return !!(*out); // check that we got a non-NULL strdup
+}
+static int
+parseSingleE(void *_out, const char *str, const void *_enm) {
+ // we got NULL, there's nothing to do
+ if (!(_out && str && _enm)) return 1;
+ int *out = (int *)_out;
+ const airEnum *enm = (const airEnum *)_enm;
+ *out = airEnumVal(enm, str);
+ return (airEnumUnknown(enm) == *out);
+}
+
+int (*const _hestParseSingle[_HEST_TYPE_MAX + 1])(void *, const char *, const void *) = {
+ NULL, //
+ parseSingleB, //
+ parseSingleH, //
+ parseSingleUH, //
+ parseSingleI, //
+ parseSingleUI, //
+ parseSingleL, //
+ parseSingleUL, //
+ parseSingleZ, //
+ parseSingleF, //
+ parseSingleD, //
+ parseSingleC, //
+ parseSingleS, //
+ parseSingleE,
+ NULL // "other"
+};
+
+#define _INVERT_SCALAR(TT, ctype) \
+ static void _invertScalar##TT(void *_valP) { \
+ ctype *valP = (ctype *)_valP; \
+ ctype val = *valP; \
+ *valP = !val; \
+ }
+_INVERT_SCALAR(B, int)
+_INVERT_SCALAR(H, short)
+_INVERT_SCALAR(UH, unsigned short)
+_INVERT_SCALAR(I, int)
+_INVERT_SCALAR(UI, unsigned int)
+_INVERT_SCALAR(L, long)
+_INVERT_SCALAR(UL, unsigned long)
+_INVERT_SCALAR(Z, size_t)
+_INVERT_SCALAR(F, float)
+_INVERT_SCALAR(D, double)
+// not: C, char
+// not: S, char *
+// not: E, int
+// not: ?, "other"
+
+void (*const _hestInvertScalar[_HEST_TYPE_MAX + 1])(void *) = {
+ NULL, //
+ _invertScalarB, //
+ _invertScalarH, //
+ _invertScalarUH, //
+ _invertScalarI, //
+ _invertScalarUI, //
+ _invertScalarL, //
+ _invertScalarUL, //
+ _invertScalarZ, //
+ _invertScalarF, //
+ _invertScalarD, //
+ NULL, // not C, char
+ NULL, // not S, char *
+ NULL, // not E, int
+ NULL // not ?, "other"
+};
+
+// HEY these are sticking around just for the old implementation of hestParse
unsigned int (*const _hestParseStr[_HEST_TYPE_MAX + 1])(void *, const char *,
const char *, unsigned int)
= {NULL,
@@ -229,55 +352,47 @@
return max;
}
-/* opt_kind determines the kind (1,2,3,4, or 5) of an opt,
- from being passed its min and max fields */
+/* minmaxKind determines the kind (1,2,3,4, or 5) of an opt,
+ based on the min and max fields from the hestOpt */
static int
-opt_kind(unsigned int min, int _max) {
- int max;
-
- max = _hestMax(_max);
- if (!(AIR_INT(min) <= max)) {
+minmaxKind(unsigned int min, int _max) {
+ int ret;
+ int max = _hestMax(_max);
+ if (AIR_INT(min) > max) {
/* invalid */
- return -1;
+ ret = -1;
+ } else { // else min <= max
+ if (AIR_INT(min) == max) {
+ if (0 == min) {
+ // stand-alone flag
+ ret = 1;
+ } else if (1 == min) {
+ // single fixed parm
+ ret = 2;
+ } else { // min==max >= 2
+ // multiple fixed parms
+ ret = 3;
+ }
+ } else { // else min < max
+ if (0 == min && 1 == max) {
+ // weirdo: single optional parameter
+ ret = 4;
+ } else {
+ // multiple variadic parameters
+ ret = 5;
+ }
+ }
}
-
- if (0 == min && 0 == max) {
- /* flag */
- return 1;
- }
-
- if (1 == min && 1 == max) {
- /* single fixed parameter */
- return 2;
- }
-
- if (2 <= min && 2 <= max && AIR_INT(min) == max) {
- /* multiple fixed parameters */
- return 3;
- }
-
- if (0 == min && 1 == max) {
- /* single optional parameter */
- return 4;
- }
-
- /* else multiple variadic parameters */
- return 5;
+ return ret;
}
-/* "private" wrapper around opt_kind, taking a hestOpt pointer */
-int
-_hestKind(const hestOpt *opt) {
-
- return opt_kind(opt->min, opt->max);
-}
-
-/* opt_init initializes all of a hestOpt, even arrAlloc and arrLen */
+/* initializes all of a hestOpt, even arrAlloc and arrLen */
static void
-opt_init(hestOpt *opt) {
+optInit(hestOpt *opt) {
- opt->flag = opt->name = NULL;
- opt->type = airTypeUnknown; /* == 0 */
+ opt->flag = NULL;
+ opt->name = NULL;
+ opt->type = airTypeUnknown; /* h== 0 */
opt->min = 0;
opt->max = 0;
opt->valueP = NULL;
@@ -310,12 +425,12 @@
/* like airArrayNew: create an initial segment of the hestOpt array */
static void
-optarr_new(hestOpt **optP) {
+optarrNew(hestOpt **optP) {
unsigned int opi;
hestOpt *ret = AIR_CALLOC(INCR, hestOpt);
assert(ret);
for (opi = 0; opi < INCR; opi++) {
- opt_init(ret + opi);
+ optInit(ret + opi);
}
ret->arrAlloc = INCR;
ret->arrLen = 0;
@@ -326,7 +441,7 @@
/* line airArrayLenIncr(1): increments logical length by 1,
and returns index of newly-available element */
static unsigned int
-optarr_incr(hestOpt **optP) {
+optarrIncr(hestOpt **optP) {
unsigned int olen, nlen;
olen = (*optP)->arrLen; /* == index of new element */
nlen = olen + 1;
@@ -338,7 +453,7 @@
memcpy(nopt, *optP, olen * sizeof(hestOpt));
nopt->arrAlloc = (*optP)->arrAlloc + INCR;
for (opi = olen; opi < nopt->arrAlloc; opi++) {
- opt_init(nopt + opi);
+ optInit(nopt + opi);
}
free(*optP);
*optP = nopt;
@@ -368,7 +483,7 @@
opt->dflt = airStrdup(dflt);
opt->info = airStrdup(info);
// need to set kind now so can be used in later conditionals
- opt->kind = opt_kind(min, max);
+ opt->kind = minmaxKind(min, max);
// deal with (what used to be) var args
opt->sawP = (5 == opt->kind /* */
? sawP
@@ -382,7 +497,7 @@
// alloc set by hestParse
opt->havec = hestArgVecNew();
// leave arrAlloc, arrLen untouched: managed by caller
- // yes, redundant with opt_init()
+ // yes, redundant with optInit()
opt->source = hestSourceUnknown;
opt->parmStr = NULL;
opt->helpWanted = AIR_FALSE;
@@ -393,14 +508,14 @@
hestOptAdd_nva: A new (as of 2023) non-var-args ("_nva") version of hestOptAdd;
The per-hestOpt logic (including setting opt->kind) has now been moved to
hestOptSingleSet. The venerable var-args hestOptAdd is now a wrapper around this.
-and the 99 non-var-args hestOptAdd_* functions also all call this.
+and all the 99 non-var-args fully typed hestOptAdd_* functions also call this.
Like hestOptAdd has done since 2013: returns UINT_MAX in case of error.
NOTE that we do NOT do here ANY error checking on the validity of the arguments passed,
-e.g. enforcing that we have a non-NULL sawP if min != max (a variadic parameter option),
-or that without a flag (`flag` is NULL) we must have min > 0. All of that is done later,
-in _hestOPCheck.
+e.g. enforcing that we have a non-NULL sawP iff this is a multi-variadic parameter
+option, or that without a flag (`flag` is NULL) we must have min > 0. All of that is
+done later, in _hestOPCheck.
*/
unsigned int
hestOptAdd_nva(hestOpt **optP, const char *flag, const char *name, int type,
@@ -413,10 +528,10 @@
if (!optP) return UINT_MAX;
/* initialize hestOpt array if necessary */
if (!(*optP)) {
- optarr_new(optP);
+ optarrNew(optP);
}
/* increment logical length of hestOpt array; return index of opt being set here */
- retIdx = optarr_incr(optP);
+ retIdx = optarrIncr(optP);
/* set all elements of the opt */
hestOptSingleSet(*optP + retIdx, flag, name, type, min, max, /* */
valueP, dflt, info, /* */
@@ -436,8 +551,8 @@
* hestOptAdd_Nv_T for T=Bool, Short, UShort, Int, UInt, LongInt, ULongInt, Size_t,
* Float, Double, Char, String, Enum, or Other.
*
- * This returns the index of the option just added, to so the caller can remember it and
- * this speed up later checking the `hestOpt->source` to learn where how the option was
+ * This returns the index of the option just added, so the caller can remember it and
+ * thus speed up later checking the `hestOpt->source` to learn where how the option was
* parsed. Returns UINT_MAX in case of error.
*/
unsigned int
@@ -451,7 +566,7 @@
if (!optP) return UINT_MAX;
/* deal with var args */
- if (5 == opt_kind(min, max)) {
+ if (5 == minmaxKind(min, max)) {
va_start(ap, info);
sawP = va_arg(ap, unsigned int *);
va_end(ap);
@@ -533,10 +648,6 @@
opt[opi].type, airTypeUnknown + 1, airTypeLast - 1);
return 1;
}
- if (!(opt[opi].valueP)) {
- biffAddf(HEST, "%s%sopt[%u]'s valueP is NULL!", _ME_, opi);
- return 1;
- }
// `kind` set by hestOptSingleSet
if (-1 == opt[opi].kind) {
biffAddf(HEST, "%s%sopt[%u]'s min (%d) and max (%d) incompatible", _ME_, opi,
@@ -543,50 +654,31 @@
opt[opi].min, opt[opi].max);
return 1;
}
- if (5 == opt[opi].kind && !(opt[opi].sawP)) {
- biffAddf(HEST,
- "%s%sopt[%u] has multiple variadic parameters (min=%u,max=%d), "
- "but sawP is NULL",
- _ME_, opi, opt[opi].min, opt[opi].max);
+ if (!(opt[opi].valueP)) {
+ biffAddf(HEST, "%s%sopt[%u]'s valueP is NULL!", _ME_, opi);
return 1;
}
- if (airTypeEnum == opt[opi].type) {
- if (!(opt[opi].enm)) {
- biffAddf(HEST,
- "%s%sopt[%u] (%s) is type \"enum\", but no "
- "airEnum pointer given",
- _ME_, opi, opt[opi].flag ? opt[opi].flag : "unflagged");
+ if (1 == opt[opi].kind) {
+ if (!opt[opi].flag) {
+ biffAddf(HEST, "%s%sstand-alone flag opt[%u] must have a flag", _ME_, opi);
return 1;
}
- }
- if (airTypeOther == opt[opi].type) {
- if (!(opt[opi].CB)) {
- biffAddf(HEST,
- "%s%sopt[%u] (%s) is type \"other\", but no "
- "callbacks given",
- _ME_, opi, opt[opi].flag ? opt[opi].flag : "unflagged");
+ if (opt[opi].dflt) {
+ biffAddf(HEST, "%s%sstand-alone flag (opt[%u] %s) should not have a default",
+ _ME_, opi, opt[opi].flag);
return 1;
}
- if (!(opt[opi].CB->size > 0)) {
- biffAddf(HEST, "%s%sopt[%u]'s \"size\" (%u) invalid", _ME_, opi,
- (uint)(opt[opi].CB->size));
+ if (opt[opi].name) {
+ biffAddf(HEST, "%s%sstand-alone flag (opt[%u] %s) should not have a name", _ME_,
+ opi, opt[opi].flag);
return 1;
}
- if (!(opt[opi].CB->type)) {
- biffAddf(HEST, "%s%sopt[%u]'s \"type\" is NULL", _ME_, opi);
+ } else { // ------ end of if (1 == opt[opi].kind)
+ if (!opt[opi].name) {
+ biffAddf(HEST, "%s%sopt[%u] isn't stand-alone flag: must have \"name\"", _ME_,
+ opi);
return 1;
}
- if (!(opt[opi].CB->parse)) {
- biffAddf(HEST, "%s%sopt[%u]'s \"parse\" callback NULL", _ME_, opi);
- return 1;
- }
- if (opt[opi].CB->destroy && (sizeof(void *) != opt[opi].CB->size)) {
- biffAddf(HEST,
- "%s%sopt[%u] has a \"destroy\", but size %lu isn't "
- "sizeof(void*)",
- _ME_, opi, (unsigned long)(opt[opi].CB->size));
- return 1;
- }
}
if (opt[opi].flag) {
const char *flag = opt[opi].flag;
@@ -606,13 +698,9 @@
flag, chi, flag[chi]);
return 1;
}
- }
- if (1 == opt[opi].kind) {
- if (opt[opi].dflt) {
- biffAddf(HEST,
- "%s%sstand-alone flag (opt[%u] %s) should not give a default; will "
- "be ignored",
- _ME_, opi, opt[opi].flag);
+ if (strchr(AIR_WHITESPACE, flag[chi])) {
+ biffAddf(HEST, "%s%sopt[%u].flag \"%s\" char %u '%c' is whitespace", _ME_, opi,
+ flag, chi, flag[chi]);
return 1;
}
}
@@ -643,6 +731,7 @@
_ME_, opi, flag, MULTI_FLAG_SEP);
return (free(tbuff), 1);
}
+ free(tbuff);
} else {
if (!strlen(opt[opi].flag)) {
biffAddf(HEST, "%s%sopt[%u].flag is zero length", _ME_, opi);
@@ -662,7 +751,7 @@
"%s%sflagged single variadic parameter must "
"specify a default",
_ME_);
- return (free(tbuff), 1);
+ return 1;
}
if (!strlen(opt[opi].dflt)) {
biffAddf(HEST,
@@ -669,45 +758,100 @@
"%s%sflagged single variadic parameter default "
"must be non-zero length",
_ME_);
- return (free(tbuff), 1);
+ return 1;
}
}
- /*
- sprintf(tbuff, "-%s", opt[op].flag);
- if (1 == sscanf(tbuff, "%f", &tmpF)) {
- if (err)
- sprintf(err, "%sopt[%u].flag (\"%s\") is numeric, bad news",
- ME, op, opt[op].flag);
- return 1;
- }
- */
- free(tbuff);
} else { // ------ end of if (opt[opi].flag)
// opt[opi] is unflagged
if (!opt[opi].min) {
+ // this rules out all unflagged kind 1 and kind 4
+ // and prevents unflagged kind 5 w/ min=0
biffAddf(HEST, "%s%sunflagged opt[%u] (name %s) must have min >= 1, not 0", _ME_,
opi, opt[opi].name ? opt[opi].name : "not set");
return 1;
}
}
- if (1 == opt[opi].kind) {
- if (!opt[opi].flag) {
- biffAddf(HEST, "%s%sopt[%u] flag must have a flag", _ME_, opi);
+ if (4 == opt[opi].kind) { // single variadic parameter
+ // immediately above have ruled out unflagged kind 4
+ if (!opt[opi].dflt) {
+ biffAddf(HEST,
+ "%s%sopt[%u] -%s is single variadic parameter, but "
+ "no default set",
+ _ME_, opi, opt[opi].flag);
return 1;
}
- } else {
- if (!opt[opi].name) {
- biffAddf(HEST, "%s%sopt[%u] isn't a flag: must have \"name\"", _ME_, opi);
+ /* pre 2025, these types were allowed kind 4, but the semantics are just so weird
+ and thus hard to test + debug, that it no longer makes sense to support them */
+ if (airTypeChar == opt[opi].type || airTypeString == opt[opi].type
+ || airTypeEnum == opt[opi].type || airTypeOther == opt[opi].type) {
+ biffAddf(HEST,
+ "%s%sopt[%u] -%s is single variadic parameter, but sorry, "
+ "type %s no longer supported",
+ _ME_, opi, opt[opi].flag, _hestTypeStr[opt[opi].type]);
return 1;
}
}
- if (4 == opt[opi].kind && !opt[opi].dflt) {
+ if (5 == opt[opi].kind && !(opt[opi].sawP)) {
biffAddf(HEST,
- "%s%sopt[%u] is single variadic parameter, but "
- "no default set",
- _ME_, opi);
+ "%s%sopt[%u] has multiple variadic parameters (min=%u,max=%d), "
+ "but sawP is NULL",
+ _ME_, opi, opt[opi].min, opt[opi].max);
return 1;
}
+ if (opt[opi].sawP && 5 != opt[opi].kind) {
+ biffAddf(HEST,
+ "%s%sopt[%u] has non-NULL sawP but is not a (kind=5) "
+ "multiple variadic parm option (min=%u,max=%d)",
+ _ME_, opi, opt[opi].min, opt[opi].max);
+ return 1;
+ }
+ if (airTypeEnum == opt[opi].type && !(opt[opi].enm)) {
+ biffAddf(HEST,
+ "%s%sopt[%u] (%s) is type \"enum\", but no "
+ "airEnum pointer given",
+ _ME_, opi, opt[opi].flag ? opt[opi].flag : "unflagged");
+ return 1;
+ }
+ if (opt[opi].enm && airTypeEnum != opt[opi].type) {
+ biffAddf(HEST,
+ "%s%sopt[%u] (%s) has non-NULL airEnum pointer, but is not airTypeEnum",
+ _ME_, opi, opt[opi].flag ? opt[opi].flag : "unflagged");
+ return 1;
+ }
+ if (airTypeOther == opt[opi].type) {
+ if (!(opt[opi].CB)) {
+ biffAddf(HEST,
+ "%s%sopt[%u] (%s) is type \"other\", but no "
+ "callbacks given",
+ _ME_, opi, opt[opi].flag ? opt[opi].flag : "unflagged");
+ return 1;
+ }
+ if (!(opt[opi].CB->size > 0)) {
+ biffAddf(HEST, "%s%sopt[%u]'s \"size\" (%u) invalid", _ME_, opi,
+ (uint)(opt[opi].CB->size));
+ return 1;
+ }
+ if (!(opt[opi].CB->type)) {
+ biffAddf(HEST, "%s%sopt[%u]'s \"type\" is NULL", _ME_, opi);
+ return 1;
+ }
+ if (!(opt[opi].CB->parse)) {
+ biffAddf(HEST, "%s%sopt[%u]'s \"parse\" callback NULL", _ME_, opi);
+ return 1;
+ }
+ if (opt[opi].CB->destroy && (sizeof(void *) != opt[opi].CB->size)) {
+ biffAddf(HEST,
+ "%s%sopt[%u] has a \"destroy\", but size %lu isn't "
+ "sizeof(void*)",
+ _ME_, opi, (unsigned long)(opt[opi].CB->size));
+ return 1;
+ }
+ }
+ if (opt[opi].CB && airTypeOther != opt[opi].type) {
+ biffAddf(HEST, "%s%sopt[%u] (%s) has non-NULL callbacks, but is not airTypeOther",
+ _ME_, opi, opt[opi].flag ? opt[opi].flag : "unflagged");
+ return 1;
+ }
// kind 4 = single variadic parm; kind 5 = multiple variadic parm
ufvarNum += (opt[opi].kind > 3 && (!opt[opi].flag));
}
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-26 11:32:56 UTC (rev 7496)
+++ teem/trunk/src/hest/parsest.c 2025-09-26 11:33:53 UTC (rev 7497)
@@ -800,9 +800,8 @@
/* havecExtractFlagged
Extracts the parameter args associated with all flagged options from the given
`hestArgVec *havec` (as generated by histProc()) and stores them the corresponding
-opt->havec. Also sets opt->source according to where that flag arg appeared (we don't
-notice if the parameters were weirdly split between the comamnd-line and a response file;
-only the source of the flag arg is recorded).
+opt->havec. Also sets opt->source according to where that flag arg appeared in the case
+of stand-alone flags, or (via havecTransfer) wherever the last parm arg came from.
In the case of variadic parameter options, this does the work of figuring out which args
belong with the option. In any case, this only extracts and preserves (in opt->havec) the
@@ -911,7 +910,9 @@
if (hparm->verbosity > 1) {
hestArgVecPrint(__func__, "main havec as it came", havec);
}
- // remember from whence this flagged option came
+ /* remember from whence this flagged option came, which is necessary when there are
+ zero parms. For nonzero parmNum, havecTransfer will also (overriding this) set
+ theOpt->source to every source of each arg extracted */
theOpt->source = havec->harg[argIdx]->source;
// lose the flag argument
hestArgNix(hestArgVecRemove(havec, argIdx));
@@ -924,7 +925,7 @@
}
havStr = airFree(havStr);
if (hitVPS) {
- // drop the variadic-parameter-stop flag
+ // lose the variadic-parameter-stop flag
hestArgNix(hestArgVecRemove(havec, argIdx));
}
if (hparm->verbosity) {
@@ -967,8 +968,7 @@
}
/* havecExtractUnflagged()
-
-extracts the parameter args associated with all unflagged options (of `hestOpt *opt`)
+Extracts the parameter args associated with all unflagged options (of `hestOpt *opt`)
from the given `hestArgVec *havec` and (like havecExtractFlagged) extracts those args and
saves them in the corresponding opt[].havec
@@ -1162,6 +1162,7 @@
static int
optProcessDefaults(hestOpt *opt, hestArg *tharg, hestInputStack *hist,
const hestParm *hparm) {
+ char ident[AIR_STRLEN_HUGE + 1];
uint optNum = opt->arrLen;
for (uint opi = 0; opi < optNum; opi++) {
if (hparm->verbosity) {
@@ -1181,7 +1182,6 @@
the flag was not given by user */
goto nextopt;
}
- char ident[AIR_STRLEN_HUGE + 1];
identStr(ident, opt + opi);
// should have already checked for this but just to make sure
if (!opt[opi].dflt) {
@@ -1203,7 +1203,7 @@
return 1;
}
/* havecExtractFlagged and havecExtractUnflagged have done the work of ensuring that
- the minimum number of parm args have been extracted for each option. We have to do
+ the minimum number of parm args have been extracted for each option. We should do
something analogous for args tokenized from the default strings. */
if (opt[opi].havec->len < opt[opi].min) {
biffAddf(
@@ -1218,12 +1218,32 @@
optPrint(opt + opi, opi);
}
}
+ for (uint opi = 0; opi < optNum; opi++) {
+ identStr(ident, opt + opi);
+ /* (Yes, half of this test is redundant with check above on whether the default
+ string supplied at least opt[opi].min args, but erring with doing more checks).
+ Now that we've made a opt[opi].havec array, and will soon parse strings to set
+ values, we can check that the number of args matches what the option needs */
+ int maxArg = _hestMax(opt[opi].max);
+ int haveArg = AIR_INT(opt[opi].havec->len);
+ if (!(AIR_INT(opt[opi].min) <= haveArg && haveArg <= maxArg)) {
+ biffAddf(HEST,
+ "%s%s %s[%u] got (from user or from default) %u args, but that is "
+ "outside [min,max]=[%u,%d] range",
+ _ME_, ident, opi, opt[opi].havec->len, opt[opi].min, maxArg);
+ return 1;
+ }
+ }
return 0;
}
-#if 0
+/* optSetValues
+Does the parsing of opt[opi].havec to set values in whatever opt[opi].valueP points to.
+The parent mop `pmop` is passed so that we can remember what to free up ONLY IN CASE OF
+ERROR. Otherwise, the allocations persist with the successful return of hestParse(2), and
+are freed with hestParseFree. */
static int
-optSetValues(hestOpt *opt, const hestParm *hparm) {
+optSetValues(hestOpt *opt, const hestParm *hparm, airArray *pmop) {
char ident[AIR_STRLEN_HUGE + 1];
/*
char cberr[AIR_STRLEN_HUGE + 1], *tok, *last, *optParmsCopy;
@@ -1232,6 +1252,7 @@
*/
void *valueP;
char *cvalueP;
+ int *ivalueP;
uint optNum = opt->arrLen;
for (uint opi = 0; opi < optNum; opi++) {
@@ -1244,7 +1265,7 @@
and it turns out that adding this was as simple as adding this one following
line. The inscrutability of the hest code (or really the self-reinforcing
learned fear of working with the hest code) seems to have been the barrier.
- (2025 GLK notes that the fear is justified, given how long the re-write took!) */
+ (2025 GLK notes that the fear was justified, given how long the re-write took ...) */
opt[opi].parmStr = hestArgVecSprint(opt[opi].havec, AIR_FALSE);
/* not: airStrdup(optParms[opi]); since 2025 havec adoption */
int type = opt[opi].type;
@@ -1255,10 +1276,11 @@
: _hestTypeSize[type]));
valueP = opt[opi].valueP;
cvalueP = (char *)valueP;
+ ivalueP = (int *)valueP;
if (hparm->verbosity) {
- printf("%s: opt[%u/%u]: havec|%s| |%s| --> kind=%d, type=%d, size=%u\n", __func__,
- opi, optNum, opt[opi].parmStr, ident, opt[opi].kind, type,
- (unsigned int)size);
+ printf("%s: opt[%u/%u]: havec_%c|%s| \t|%s| \t--> kind=%d, type=%d, size=%u\n",
+ __func__, opi, optNum, airEnumStr(hestSource, opt[opi].source)[0],
+ opt[opi].parmStr, ident, opt[opi].kind, type, (unsigned int)size);
}
/* we may over-write these */
opt[opi].alloc = 0;
@@ -1268,15 +1290,60 @@
switch (opt[opi].kind) {
case 1:
/* -------- parameter-less boolean flags -------- */
- /* the value pointer is always assumed to be an int* */
- if (valueP) *((int *)valueP) = hestSourceDefault != opt[opi].source;
+ /* valueP is always assumed to be an int* */
+ *ivalueP = hestSourceDefault != opt[opi].source;
+ if (hparm->verbosity) {
+ printf(" --> set value %d\n", *ivalueP);
+ }
break;
-# if 0
- case 2:
+ case 4: {
+ const char *strsrc;
+ int invert;
+ /* -------- optional single variadics -------- */
+ /* 2025 _hestOPCheck now restricts possible types; these are no longer allowed:
+ airTypeChar, airTypeString, airTypeEnum, airTypeOther. As for the semantics,
+ the old web page seems to be clear (though we now disallow unflagged kind 4):
+ - option flag does not appear
+ --> value is set from the default
+ - option flag appears, but with no parm
+ --> default is parsed, say, as value V, then the value is set to !V
+ (*this* is the "inversion" that is mentioned at places in the code)
+ - option flag appears, with single parm
+ --> value is set from parsing that parm
+ In any case, some string has to be parsed */
+ if (hestSourceDefault == opt[opi].source) {
+ // option flag does not appear
+ strsrc = opt[opi].dflt;
+ invert = AIR_FALSE;
+ } else if (hestSourceDefault != opt[opi].source && 0 == opt[opi].havec->len) {
+ // option flag appears, but with no parm
+ strsrc = opt[opi].dflt;
+ invert = AIR_TRUE;
+ } else if (hestSourceDefault != opt[opi].source && 1 == opt[opi].havec->len) {
+ // option flag appears, with single parm
+ strsrc = opt[opi].havec->harg[0]->str;
+ invert = AIR_FALSE;
+ } else {
+ biffAddf(HEST, "%s%sconfused by %s[%u] source %s and havec->len %u", _ME_, ident,
+ opi, airEnumStr(hestSource, opt[opi].source), opt[opi].havec->len);
+ return 1;
+ }
+ if (_hestParseSingle[type](valueP, strsrc, NULL /* because type simple */)) {
+ biffAddf(HEST, "%s%sfor %s[%u] could not parse |%s| as single %s", _ME_, ident,
+ opi, strsrc, _hestTypeStr[type]);
+ return 1;
+ }
+ if (invert) {
+ _hestInvertScalar[type](valueP);
+ }
+ break;
+ } // end case 4 {
+#if 0
+ case 2:
/* -------- one required parameter -------- */
- /* 2023 GLK is really curious why "if (optParms[op] && vP) {" is (repeatedly)
+ /* 2023 GLK is really curious why "if (optParms[op] && valueP) {" is (repeatedly)
guarding all the work in these blocks, and why that wasn't factored out */
- if (optParms[opi]) {
+ if (optParms[opi] && valueP) {
switch (type) {
case airTypeEnum:
if (1 != airParseStrE((int *)valueP, optParms[opi], " ", 1, opt[opi].enm)) {
@@ -1406,100 +1473,6 @@
}
}
break;
- case 4:
- /* -------- optional single variadics -------- */
- if (optParms[opi] && valueP) {
- int pret;
- switch (type) {
- case airTypeChar:
- /* no "inversion" for chars: using the flag with no parameter is the same as
- not using the flag i.e. we just parse from the default string */
- if (1 != _hestParseStr[type](valueP, optParms[opi], " ", 1)) {
- fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
- optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
- ident);
- return 1;
- }
- opt[opi].alloc = 0;
- break;
- case airTypeString:
- /* this is a bizarre case: optional single string, with some kind of value
- "inversion". 2023 GLK would prefer to make this like Char, Enum, and Other: for
- which there is no attempt at "inversion". But for some reason the inversion of
- a non-empty default string to a NULL string value, when the flag is used
- without a parameter, was implemented from the early days of hest. Assuming
- that a younger GLK long ago had a reason for that, that functionality now
- persists. */
- pret = _hestParseStr[type](valueP, optParms[opi], " ",
- 1 /*, hparm->greedySingleString */);
- if (1 != pret) {
- fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
- optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
- ident);
- return 1;
- }
- opt[opi].alloc = 1;
- if (opt[opi].flag && 1 == whichCase(opt, optDfltd, optParmNum, appr, opi)) {
- /* we just parsed the default, but now we want to "invert" it */
- *((char **)valueP) = (char *)airFree(*((char **)valueP));
- opt[opi].alloc = 0;
- }
- /* vP is the address of a char* (a char**), and what we
- manage with airMop is the char * */
- airMopMem(pmop, valueP, airMopOnError);
- break;
- case airTypeEnum:
- if (1 != airParseStrE((int *)valueP, optParms[opi], " ", 1, opt[opi].enm)) {
- fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
- optDfltd[opi] ? "(default) " : "", optParms[opi], opt[opi].enm->name,
- ident);
- return 1;
- }
- break;
- case airTypeOther:
- /* we're parsing an single "other". We will not perform the special flagged
- single variadic parameter games as done above, so whether this option is
- flagged or unflagged, we're going to treat it like an unflagged single variadic
- parameter option: if the parameter didn't appear, we'll parse it from the
- default, if it did appear, we'll parse it from the command line. Setting up
- optParms[op] thusly has already been done by _hestDefaults() */
- strcpy(cberr, "");
- ret = opt[opi].CB->parse(valueP, optParms[opi], cberr);
- if (ret) {
- if (strlen(cberr))
- fprintf(stderr, "%serror parsing \"%s\" as %s for %s:\n%s\n", ME,
- optParms[opi], opt[opi].CB->type, ident, cberr);
- else
- fprintf(stderr, "%serror parsing \"%s\" as %s for %s: returned %d\n", ME,
- optParms[opi], opt[opi].CB->type, ident, ret);
- return 1;
- }
- if (opt[opi].CB->destroy) {
- /* vP is the address of a void*, we manage the void* */
- opt[opi].alloc = 1;
- airMopAdd(pmop, valueP, (airMopper)airSetNull, airMopOnError);
- airMopAdd(pmop, *((void **)valueP), opt[opi].CB->destroy, airMopOnError);
- }
- break;
- default:
- if (1 != _hestParseStr[type](valueP, optParms[opi], " ", 1)) {
- fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
- optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
- ident);
- return 1;
- }
- opt[opi].alloc = 0;
- /* HEY sorry about confusion about hestOpt->parmStr versus the value set
- here, due to this "inversion" */
- if (1 == whichCase(opt, optDfltd, optParmNum, appr, opi)) {
- /* we just parsed the default, but now we want to "invert" it */
- tmpD = airDLoad(valueP, type);
- airIStore(valueP, type, tmpD ? 0 : 1);
- }
- break;
- }
- }
- break;
case 5:
/* -------- multiple variadic parameters -------- */
if (optParms[opi] && valueP) {
@@ -1622,12 +1595,11 @@
}
}
break;
-# endif
- }
- }
+#endif
+ } // end switch
+ } // for opi ...
return 0;
}
-#endif
/* hestParse2
Parse the `argc`,`argv` commandline according to the hestOpt array `opt`, and as
@@ -1641,16 +1613,17 @@
0) Error checking on given `opt` array
-1) Generate internal representation of command-line that includes expanding any response
-files; this all goes into the `hestArgVec *havec`.
+1) Generate internal representation of command-line that includes expanding any
+response files; this all goes into the `hestArgVec *havec`.
-2) From `havec`, extract the args that are attributable to flagged and unflagged options,
-moving each `hestArg` out of main `havec` and into the per-hestOpt opt->havec
+2) From `havec`, extract the args that are attributable to flagged and unflagged
+options, moving each `hestArg` out of main `havec` and into the per-hestOpt
+opt->havec
3) For options not user-supplied, process the opt's `dflt` string to set opt->havec
-4) Now, every option should have a opt->havec set, regardless of where it came from. So
-parse those per-opt args to set final values for the user to see
+4) Now, every option should have a opt->havec set, regardless of where it came from.
+So parse those per-opt args to set final values for the user to see
What is allocated as result of work here should be freed by hestParseFree
*/
@@ -1737,14 +1710,13 @@
airMopError(mop);
return 1;
}
-#if 0
+
// --4--4--4--4--4-- Finally, parse the args and set values
- if (optSetValues(opt, HPARM)) {
+ if (optSetValues(opt, HPARM, mop)) {
DO_ERR("problem with setting values");
airMopError(mop);
return 1;
}
-#endif
#undef DO_ERR
#undef HPARM
Modified: teem/trunk/src/hest/privateHest.h
===================================================================
--- teem/trunk/src/hest/privateHest.h 2025-09-26 11:32:56 UTC (rev 7496)
+++ teem/trunk/src/hest/privateHest.h 2025-09-26 11:33:53 UTC (rev 7497)
@@ -71,11 +71,14 @@
#define _HEST_TYPE_MAX 14
HEST_EXPORT const char _hestTypeStr[_HEST_TYPE_MAX + 1][AIR_STRLEN_SMALL + 1];
HEST_EXPORT const size_t _hestTypeSize[_HEST_TYPE_MAX + 1];
+HEST_EXPORT void (*const _hestInvertScalar[_HEST_TYPE_MAX + 1])(void *);
+HEST_EXPORT int (*const _hestParseSingle[_HEST_TYPE_MAX + 1])(void *, const char *,
+ const void *);
+// HEY these are sticking around just for the old implementation of hestParse
HEST_EXPORT unsigned int (*const _hestParseStr[_HEST_TYPE_MAX + 1])(void *, const char *,
const char *,
unsigned int);
extern const char *const _hestBiffKey;
-extern int _hestKind(const hestOpt *opt);
extern int _hestMax(int max);
extern int _hestOPCheck(const hestOpt *opt, const hestParm *parm);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-26 11:33:00
|
Revision: 7496
http://sourceforge.net/p/teem/code/7496
Author: kindlmann
Date: 2025-09-26 11:32:56 +0000 (Fri, 26 Sep 2025)
Log Message:
-----------
tweaking for 2025
Modified Paths:
--------------
teem/trunk/src/hest/test/ex6.c
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-26 11:31:55 UTC (rev 7495)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-26 11:32:56 UTC (rev 7496)
@@ -72,7 +72,7 @@
int
main(int argc, const char **argv) {
hestOpt *opt = NULL;
- hestParm *parm;
+ hestParm *hparm;
char *err = NULL,
info[] = "This program does nothing in particular, though it does attempt "
"to pose as some sort of command-line image processing program. "
@@ -79,12 +79,12 @@
"As usual, any implied functionality is purely coincidental, "
"especially since this is the output of a gray-haired unicyclist.";
- parm = hestParmNew();
- parm->responseFileEnable = AIR_TRUE;
- parm->respectDashDashHelp = AIR_TRUE;
- parm->noArgsIsNoProblem = AIR_TRUE;
- parm->dieLessVerbose = AIR_TRUE;
- parm->verbosity = 0;
+ hparm = hestParmNew();
+ hparm->responseFileEnable = AIR_TRUE;
+ hparm->respectDashDashHelp = AIR_TRUE;
+ hparm->noArgsIsNoProblem = AIR_TRUE;
+ hparm->dieLessVerbose = AIR_TRUE;
+ hparm->verbosity = 0;
opt = NULL;
/* going past C89 to have declarations here */
@@ -143,6 +143,7 @@
double db1v;
hestOptAdd_1v_Double(&opt, "db1v", "double1", &db1v, "4.2",
"test of hestOptAdd_1v_Double");
+ /* gone in 2025
char c1v;
hestOptAdd_1v_Char(&opt, "c1v", "char1", &c1v, "x", "test of hestOptAdd_1v_Char");
char *s1v;
@@ -157,7 +158,7 @@
Quat *q1v;
hestOptAdd_1v_Other(&opt, "q1v", "quat", &q1v, "12.34",
"test of hestOptAdd_1v_Other B", &quatCB);
-
+ */
int b2[2];
hestOptAdd_2_Bool(&opt, "b2", "bool1 bool2", b2, "true false",
"test of hestOptAdd_2_Bool");
@@ -374,8 +375,12 @@
unsigned int qvSaw;
hestOptAdd_Nv_Other(&opt, "qv", "quat1", 1, -1, &qv, "12.34 43.21",
"test of hestOptAdd_Nv_Other B", &qvSaw, &quatCB);
- hestParseOrDie(opt, argc - 1, argv + 1, parm, argv[0], info, AIR_TRUE, AIR_TRUE,
+ hestParse2(opt, argc - 1, argv + 1, NULL, hparm);
+ exit(0);
+ /*
+ hestParseOrDie(opt, argc - 1, argv + 1, hparm, argv[0], info, AIR_TRUE, AIR_TRUE,
AIR_TRUE);
+ */
if (0) {
unsigned int opi, numO;
@@ -416,11 +421,13 @@
printf("sz1v = %zu\n", sz1v);
printf("fl1v = %g\n", fl1v);
printf("db1v = %g\n", db1v);
+ /*
printf("c1v = |%c| (%d)\n", c1v, c1v);
printf("s1v = |%s|\n", s1v);
printf("e1v = %d\n", e1v);
printf("p1v = %g,%g\n", p1v[0], p1v[1]);
printf("q1v (@ %p) = %g(%s)\n", q1v, q1v->val, q1v->str);
+ */
printf("\n");
printf("b2 = %d %d\n", b2[0], b2[1]);
@@ -558,6 +565,6 @@
hestParseFree(opt);
/* ... and the other stuff */
opt = hestOptFree(opt);
- parm = hestParmFree(parm);
+ hparm = hestParmFree(hparm);
exit(0);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-26 11:31:57
|
Revision: 7495
http://sourceforge.net/p/teem/code/7495
Author: kindlmann
Date: 2025-09-26 11:31:55 +0000 (Fri, 26 Sep 2025)
Log Message:
-----------
tweaking
Modified Paths:
--------------
teem/trunk/src/hest/README.md
Modified: teem/trunk/src/hest/README.md
===================================================================
--- teem/trunk/src/hest/README.md 2025-09-25 21:55:39 UTC (rev 7494)
+++ teem/trunk/src/hest/README.md 2025-09-26 11:31:55 UTC (rev 7495)
@@ -58,7 +58,7 @@
min > 0 1 2
```
-The `kind` of option is mostly independent of whether it is flagged or unflagged, and independent of being optional (due to the `hestOpt` having a default string) versus required (when no default is given). The one wrinkle is that unflagged options must have at least one parameter (i.e. `min` > 0), either by the command-line or via a default string. An unflagged option allowed to have zero parameters has no explicit textual existence, which seems out-of-bounds for a command-line parser. Thus for unflagged options, `kind`s 1 and 4 are ruled out, and kind 5 is possible with `min` >= 1. This is likely already too much low-level information: users of `hest` will probably never need to worry about `kind`, and certainly `kind` is not part of the API calls to create options and parse command-lines.
+The `kind` of option is mostly independent of whether it is flagged or unflagged, and independent of being optional (due to the `hestOpt` having a default string) versus required (when no default is given). The one wrinkle is that unflagged options must have at least one parameter (i.e. `min` > 0), either by the command-line or via a default string. An unflagged option allowed to have zero parameters has no explicit textual existence, which seems out-of-bounds for a command-line parser. Thus for unflagged options, `kind`s 1 and 4 are ruled out, and kind 5 is possible only with `min` >= 1. This is likely already too much low-level information: users of `hest` will probably never need to worry about `kind`, and certainly `kind` is not part of the API calls to create options and parse command-lines.
Some **concrete examples** may be helpful for understanding `hest`'s utility ... (IN PROGRESS) ...
... Give some specific examples, flagged and unflagged ...
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 21:55:40
|
Revision: 7494
http://sourceforge.net/p/teem/code/7494
Author: kindlmann
Date: 2025-09-25 21:55:39 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
starting code for setting values, but wow this will need re-writing
Modified Paths:
--------------
teem/trunk/src/hest/argvHest.c
teem/trunk/src/hest/parsest.c
Modified: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c 2025-09-25 21:27:03 UTC (rev 7493)
+++ teem/trunk/src/hest/argvHest.c 2025-09-25 21:55:39 UTC (rev 7494)
@@ -244,6 +244,7 @@
return NULL;
}
hestArg *retArg = hestArgNew();
+ // if we got an empty havec, then we'll leave with an appropriately empty string
for (uint ai = 0; ai < havec->len; ai++) {
if (ai) {
// add the space between previous and this arg
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 21:27:03 UTC (rev 7493)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 21:55:39 UTC (rev 7494)
@@ -1221,6 +1221,414 @@
return 0;
}
+#if 0
+static int
+optSetValues(hestOpt *opt, const hestParm *hparm) {
+ char ident[AIR_STRLEN_HUGE + 1];
+ /*
+ char cberr[AIR_STRLEN_HUGE + 1], *tok, *last, *optParmsCopy;
+ double tmpD;
+ int p, ret;
+ */
+ void *valueP;
+ char *cvalueP;
+
+ uint optNum = opt->arrLen;
+ for (uint opi = 0; opi < optNum; opi++) {
+ identStr(ident, opt + opi);
+ // opt[opi].source has already been set
+ /* 2023 GLK notes that r6388 2020-05-14 GLK was asking:
+ How is it that, once the command-line has been parsed, there isn't an
+ easy way to see (or print, for an error message) the parameter (or
+ concatenation of parameters) that was passed for a given option?
+ and it turns out that adding this was as simple as adding this one following
+ line. The inscrutability of the hest code (or really the self-reinforcing
+ learned fear of working with the hest code) seems to have been the barrier.
+ (2025 GLK notes that the fear is justified, given how long the re-write took!) */
+ opt[opi].parmStr = hestArgVecSprint(opt[opi].havec, AIR_FALSE);
+ /* not: airStrdup(optParms[opi]); since 2025 havec adoption */
+ int type = opt[opi].type;
+ size_t size = (airTypeEnum == type /* */
+ ? sizeof(int)
+ : (airTypeOther == type /* */
+ ? opt[opi].CB->size
+ : _hestTypeSize[type]));
+ valueP = opt[opi].valueP;
+ cvalueP = (char *)valueP;
+ if (hparm->verbosity) {
+ printf("%s: opt[%u/%u]: havec|%s| |%s| --> kind=%d, type=%d, size=%u\n", __func__,
+ opi, optNum, opt[opi].parmStr, ident, opt[opi].kind, type,
+ (unsigned int)size);
+ }
+ /* we may over-write these */
+ opt[opi].alloc = 0;
+ if (opt[opi].sawP) {
+ *(opt[opi].sawP) = 0;
+ }
+ switch (opt[opi].kind) {
+ case 1:
+ /* -------- parameter-less boolean flags -------- */
+ /* the value pointer is always assumed to be an int* */
+ if (valueP) *((int *)valueP) = hestSourceDefault != opt[opi].source;
+ break;
+# if 0
+ case 2:
+ /* -------- one required parameter -------- */
+ /* 2023 GLK is really curious why "if (optParms[op] && vP) {" is (repeatedly)
+ guarding all the work in these blocks, and why that wasn't factored out */
+ if (optParms[opi]) {
+ switch (type) {
+ case airTypeEnum:
+ if (1 != airParseStrE((int *)valueP, optParms[opi], " ", 1, opt[opi].enm)) {
+ fprintf(stderr, "%scouldn\'t parse %s\"%s\" as %s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], opt[opi].enm->name,
+ ident);
+ return 1;
+ }
+ break;
+ case airTypeOther:
+ strcpy(cberr, "");
+ ret = opt[opi].CB->parse(valueP, optParms[opi], cberr);
+ if (ret) {
+ if (strlen(cberr)) {
+ fprintf(stderr, "%serror parsing \"%s\" as %s for %s:\n%s\n", ME,
+ optParms[opi], opt[opi].CB->type, ident, cberr);
+ } else {
+ fprintf(stderr, "%serror parsing \"%s\" as %s for %s: returned %d\n", ME,
+ optParms[opi], opt[opi].CB->type, ident, ret);
+ }
+ return ret;
+ }
+ if (opt[opi].CB->destroy) {
+ /* vP is the address of a void*, we manage the void * */
+ opt[opi].alloc = 1;
+ airMopAdd(pmop, (void **)valueP, (airMopper)airSetNull, airMopOnError);
+ airMopAdd(pmop, *((void **)valueP), opt[opi].CB->destroy, airMopOnError);
+ }
+ break;
+ case airTypeString:
+ if (1
+ != airParseStrS((char **)valueP, optParms[opi], " ", 1
+ /*, hparm->greedySingleString */)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
+ ident);
+ return 1;
+ }
+ /* vP is the address of a char* (a char **), but what we
+ manage with airMop is the char * */
+ opt[opi].alloc = 1;
+ airMopMem(pmop, valueP, airMopOnError);
+ break;
+ default:
+ /* type isn't string or enum, so no last arg to hestParseStr[type] */
+ if (1 != _hestParseStr[type](valueP, optParms[opi], " ", 1)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
+ ident);
+ return 1;
+ }
+ break;
+ }
+ }
+ break;
+ case 3:
+ /* -------- multiple required parameters -------- */
+ if (optParms[opi] && valueP) {
+ switch (type) {
+ case airTypeEnum:
+ if (opt[opi].min != /* min == max */
+ airParseStrE((int *)valueP, optParms[opi], " ", opt[opi].min,
+ opt[opi].enm)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %d %s%s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], opt[opi].min,
+ opt[opi].enm->name, opt[opi].min > 1 ? "s" : "", ident);
+ return 1;
+ }
+ break;
+ case airTypeOther:
+ optParmsCopy = airStrdup(optParms[opi]);
+ for (p = 0; p < (int)opt[opi].min; p++) { /* HEY scrutinize casts */
+ tok = airStrtok(!p ? optParmsCopy : NULL, " ", &last);
+ strcpy(cberr, "");
+ ret = opt[opi].CB->parse(cvalueP + p * size, tok, cberr);
+ if (ret) {
+ if (strlen(cberr))
+ fprintf(stderr,
+ "%serror parsing \"%s\" (in \"%s\") as %s "
+ "for %s:\n%s\n",
+ ME, tok, optParms[opi], opt[opi].CB->type, ident, cberr);
+ else
+ fprintf(stderr,
+ "%serror parsing \"%s\" (in \"%s\") as %s "
+ "for %s: returned %d\n",
+ ME, tok, optParms[opi], opt[opi].CB->type, ident, ret);
+ free(optParmsCopy);
+ return 1;
+ }
+ }
+ free(optParmsCopy);
+ if (opt[opi].CB->destroy) {
+ /* vP is an array of void*s, we manage the individual void*s */
+ opt[opi].alloc = 2;
+ for (p = 0; p < (int)opt[opi].min; p++) { /* HEY scrutinize casts */
+ airMopAdd(pmop, ((void **)valueP) + p, (airMopper)airSetNull,
+ airMopOnError);
+ airMopAdd(pmop, *(((void **)valueP) + p), opt[opi].CB->destroy,
+ airMopOnError);
+ }
+ }
+ break;
+ case airTypeString:
+ if (opt[opi].min != /* min == max */
+ _hestParseStr[type](valueP, optParms[opi], " ", opt[opi].min)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %d %s%s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], opt[opi].min,
+ _hestTypeStr[type], opt[opi].min > 1 ? "s" : "", ident);
+ return 1;
+ }
+ /* vP is an array of char*s, (a char**), and what we manage
+ with airMop are the individual vP[p]. */
+ opt[opi].alloc = 2;
+ for (p = 0; p < (int)opt[opi].min; p++) { /* HEY scrutinize casts */
+ airMopMem(pmop, &(((char **)valueP)[p]), airMopOnError);
+ }
+ break;
+ default:
+ if (opt[opi].min != /* min == max */
+ _hestParseStr[type](valueP, optParms[opi], " ", opt[opi].min)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %d %s%s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], opt[opi].min,
+ _hestTypeStr[type], opt[opi].min > 1 ? "s" : "", ident);
+ return 1;
+ }
+ break;
+ }
+ }
+ break;
+ case 4:
+ /* -------- optional single variadics -------- */
+ if (optParms[opi] && valueP) {
+ int pret;
+ switch (type) {
+ case airTypeChar:
+ /* no "inversion" for chars: using the flag with no parameter is the same as
+ not using the flag i.e. we just parse from the default string */
+ if (1 != _hestParseStr[type](valueP, optParms[opi], " ", 1)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
+ ident);
+ return 1;
+ }
+ opt[opi].alloc = 0;
+ break;
+ case airTypeString:
+ /* this is a bizarre case: optional single string, with some kind of value
+ "inversion". 2023 GLK would prefer to make this like Char, Enum, and Other: for
+ which there is no attempt at "inversion". But for some reason the inversion of
+ a non-empty default string to a NULL string value, when the flag is used
+ without a parameter, was implemented from the early days of hest. Assuming
+ that a younger GLK long ago had a reason for that, that functionality now
+ persists. */
+ pret = _hestParseStr[type](valueP, optParms[opi], " ",
+ 1 /*, hparm->greedySingleString */);
+ if (1 != pret) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
+ ident);
+ return 1;
+ }
+ opt[opi].alloc = 1;
+ if (opt[opi].flag && 1 == whichCase(opt, optDfltd, optParmNum, appr, opi)) {
+ /* we just parsed the default, but now we want to "invert" it */
+ *((char **)valueP) = (char *)airFree(*((char **)valueP));
+ opt[opi].alloc = 0;
+ }
+ /* vP is the address of a char* (a char**), and what we
+ manage with airMop is the char * */
+ airMopMem(pmop, valueP, airMopOnError);
+ break;
+ case airTypeEnum:
+ if (1 != airParseStrE((int *)valueP, optParms[opi], " ", 1, opt[opi].enm)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], opt[opi].enm->name,
+ ident);
+ return 1;
+ }
+ break;
+ case airTypeOther:
+ /* we're parsing an single "other". We will not perform the special flagged
+ single variadic parameter games as done above, so whether this option is
+ flagged or unflagged, we're going to treat it like an unflagged single variadic
+ parameter option: if the parameter didn't appear, we'll parse it from the
+ default, if it did appear, we'll parse it from the command line. Setting up
+ optParms[op] thusly has already been done by _hestDefaults() */
+ strcpy(cberr, "");
+ ret = opt[opi].CB->parse(valueP, optParms[opi], cberr);
+ if (ret) {
+ if (strlen(cberr))
+ fprintf(stderr, "%serror parsing \"%s\" as %s for %s:\n%s\n", ME,
+ optParms[opi], opt[opi].CB->type, ident, cberr);
+ else
+ fprintf(stderr, "%serror parsing \"%s\" as %s for %s: returned %d\n", ME,
+ optParms[opi], opt[opi].CB->type, ident, ret);
+ return 1;
+ }
+ if (opt[opi].CB->destroy) {
+ /* vP is the address of a void*, we manage the void* */
+ opt[opi].alloc = 1;
+ airMopAdd(pmop, valueP, (airMopper)airSetNull, airMopOnError);
+ airMopAdd(pmop, *((void **)valueP), opt[opi].CB->destroy, airMopOnError);
+ }
+ break;
+ default:
+ if (1 != _hestParseStr[type](valueP, optParms[opi], " ", 1)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], _hestTypeStr[type],
+ ident);
+ return 1;
+ }
+ opt[opi].alloc = 0;
+ /* HEY sorry about confusion about hestOpt->parmStr versus the value set
+ here, due to this "inversion" */
+ if (1 == whichCase(opt, optDfltd, optParmNum, appr, opi)) {
+ /* we just parsed the default, but now we want to "invert" it */
+ tmpD = airDLoad(valueP, type);
+ airIStore(valueP, type, tmpD ? 0 : 1);
+ }
+ break;
+ }
+ }
+ break;
+ case 5:
+ /* -------- multiple variadic parameters -------- */
+ if (optParms[opi] && valueP) {
+ if (1 == whichCase(opt, optDfltd, optParmNum, appr, opi)) {
+ *((void **)valueP) = NULL;
+ /* alloc and sawP set above */
+ } else {
+ if (airTypeString == type) {
+ /* this is sneakiness: we allocate one more element so that
+ the resulting char** is, like argv, NULL-terminated */
+ *((void **)valueP) = calloc(optParmNum[opi] + 1, size);
+ } else {
+ if (optParmNum[opi]) {
+ /* only allocate if there's something to allocate */
+ *((void **)valueP) = calloc(optParmNum[opi], size);
+ } else {
+ *((void **)valueP) = NULL;
+ }
+ }
+ if (hparm->verbosity) {
+ printf("%s: optParmNum[%d] = %u\n", me, opi, optParmNum[opi]);
+ printf("%s: new array (size %u*%u) is at 0x%p\n", me, optParmNum[opi],
+ (unsigned int)size, *((void **)valueP));
+ }
+ if (*((void **)valueP)) {
+ airMopMem(pmop, valueP, airMopOnError);
+ }
+ *(opt[opi].sawP) = optParmNum[opi];
+ /* so far everything we've done is regardless of type */
+ switch (type) {
+ case airTypeEnum:
+ opt[opi].alloc = 1;
+ if (optParmNum[opi]
+ != airParseStrE((int *)(*((void **)valueP)), optParms[opi], " ",
+ optParmNum[opi], opt[opi].enm)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %u %s%s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], optParmNum[opi],
+ opt[opi].enm->name, optParmNum[opi] > 1 ? "s" : "", ident);
+ return 1;
+ }
+ break;
+ case airTypeOther:
+ cvalueP = (char *)(*((void **)valueP));
+ optParmsCopy = airStrdup(optParms[opi]);
+ opt[opi].alloc = (opt[opi].CB->destroy ? 3 : 1);
+ for (p = 0; p < (int)optParmNum[opi]; p++) { /* HEY scrutinize casts */
+ tok = airStrtok(!p ? optParmsCopy : NULL, " ", &last);
+ /* (Note from 2023-06-24: "hammerhead" was hammerhead.ucsd.edu, an Intel
+ Itanium ("IA-64") machine that GLK had access to in 2003, presumably with
+ an Intel compiler, providing a different debugging opportunity for this
+ code. Revision r1985 from 2003-12-20 documented some issues discovered, in
+ comments like the one below. Valgrind has hopefully resolved these issues
+ now, but the comment below is preserved out of respect for the goals of
+ Itanium, and nostalgia for that time at the end of grad school.)
+ hammerhead problems went away when this line
+ was replaced by the following one:
+ strcpy(cberr, "");
+ */
+ cberr[0] = 0;
+ ret = opt[opi].CB->parse(cvalueP + p * size, tok, cberr);
+ if (ret) {
+ if (strlen(cberr))
+ fprintf(stderr,
+ "%serror parsing \"%s\" (in \"%s\") as %s "
+ "for %s:\n%s\n",
+ ME, tok, optParms[opi], opt[opi].CB->type, ident, cberr);
+
+ else
+ fprintf(stderr,
+ "%serror parsing \"%s\" (in \"%s\") as %s "
+ "for %s: returned %d\n",
+ ME, tok, optParms[opi], opt[opi].CB->type, ident, ret);
+ free(optParmsCopy);
+ return 1;
+ }
+ }
+ free(optParmsCopy);
+ if (opt[opi].CB->destroy) {
+ for (p = 0; p < (int)optParmNum[opi]; p++) { /* HEY scrutinize casts */
+ /* avert your eyes. vP is the address of an array of void*s.
+ We manage the void*s */
+ airMopAdd(pmop, (*((void ***)valueP)) + p, (airMopper)airSetNull,
+ airMopOnError);
+ airMopAdd(pmop, *((*((void ***)valueP)) + p), opt[opi].CB->destroy,
+ airMopOnError);
+ }
+ }
+ break;
+ case airTypeString:
+ opt[opi].alloc = 3;
+ if (optParmNum[opi]
+ != airParseStrS((char **)(*((void **)valueP)), optParms[opi], " ",
+ optParmNum[opi] /*, hparm->greedySingleString */)) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %d %s%s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], optParmNum[opi],
+ _hestTypeStr[type], optParmNum[opi] > 1 ? "s" : "", ident);
+ return 1;
+ }
+ /* vP is the address of an array of char*s (a char ***), and
+ what we manage with airMop is the individual (*vP)[p],
+ as well as vP itself (above). */
+ for (p = 0; p < (int)optParmNum[opi]; p++) { /* HEY scrutinize casts */
+ airMopAdd(pmop, (*((char ***)valueP))[p], airFree, airMopOnError);
+ }
+ /* do the NULL-termination described above */
+ (*((char ***)valueP))[optParmNum[opi]] = NULL;
+ break;
+ default:
+ opt[opi].alloc = 1;
+ if (optParmNum[opi]
+ != _hestParseStr[type](*((void **)valueP), optParms[opi], " ",
+ optParmNum[opi])) {
+ fprintf(stderr, "%scouldn't parse %s\"%s\" as %d %s%s for %s\n", ME,
+ optDfltd[opi] ? "(default) " : "", optParms[opi], optParmNum[opi],
+ _hestTypeStr[type], optParmNum[opi] > 1 ? "s" : "", ident);
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+ break;
+# endif
+ }
+ }
+ return 0;
+}
+#endif
+
/* hestParse2
Parse the `argc`,`argv` commandline according to the hestOpt array `opt`, and as
tweaked by settings in (if non-NULL) the given `hestParm *_hparm`. If there is an
@@ -1329,15 +1737,17 @@
airMopError(mop);
return 1;
}
-
#if 0
// --4--4--4--4--4-- Finally, parse the args and set values
- if (optSetValues) {
+ if (optSetValues(opt, HPARM)) {
DO_ERR("problem with setting values");
airMopError(mop);
return 1;
}
#endif
+
+#undef DO_ERR
+#undef HPARM
airMopOkay(mop);
return 0;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 21:27:06
|
Revision: 7493
http://sourceforge.net/p/teem/code/7493
Author: kindlmann
Date: 2025-09-25 21:27:03 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
more use of hestArgVecSprint to give context with error messages
Modified Paths:
--------------
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 21:11:09 UTC (rev 7492)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 21:27:03 UTC (rev 7493)
@@ -820,7 +820,7 @@
*/
static int
havecExtractFlagged(hestOpt *opt, hestArgVec *havec, const hestParm *hparm) {
- char ident1[AIR_STRLEN_HUGE + 1], ident2[AIR_STRLEN_HUGE + 1];
+ char *havStr, ident1[AIR_STRLEN_HUGE + 1], ident2[AIR_STRLEN_HUGE + 1];
uint argIdx = 0;
hestOpt *theOpt = NULL;
while (argIdx < havec->len) { // NOTE: havec->len may decrease within an interation!
@@ -876,8 +876,8 @@
"parmNum=%u hitEnd=%d hitVPS=%d nextOptIdx=%u\n",
__func__, optIdx, theOpt->flag, parmNum, hitEnd, hitVPS, nextOptIdx);
if (parmNum < theOpt->min) { // didn't get required min # parameters
- char *havStr = hestArgVecSprint(havec, AIR_TRUE);
- biffAddf(HEST, "%s%sworking on argv: %s", _ME_, havStr);
+ havStr = hestArgVecSprint(havec, AIR_TRUE);
+ biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
if (hitEnd) {
biffAddf(HEST,
"%s%shit end of args before getting %u parameter%s "
@@ -915,11 +915,14 @@
theOpt->source = havec->harg[argIdx]->source;
// lose the flag argument
hestArgNix(hestArgVecRemove(havec, argIdx));
+ havStr = hestArgVecSprint(havec, AIR_TRUE);
if (havecTransfer(theOpt, havec, argIdx, parmNum, hparm)) {
+ biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
biffAddf(HEST, "%s%strouble transferring %u args for %s", _ME_, parmNum,
identStr(ident1, theOpt));
- return 1;
+ return (free(havStr), 1);
}
+ havStr = airFree(havStr);
if (hitVPS) {
// drop the variadic-parameter-stop flag
hestArgNix(hestArgVecRemove(havec, argIdx));
@@ -949,7 +952,8 @@
}
// if needs to be set but hasn't been
if (needing && hestSourceUnknown == theOpt->source) {
- biffAddf(HEST, "%s%sdidn't see required %s", _ME_, identStr(ident1, theOpt));
+ biffAddf(HEST, "%s%sdidn't get required (default-less) %s[%u]", _ME_,
+ identStr(ident1, theOpt), opi);
return 1;
}
}
@@ -974,7 +978,7 @@
*/
static int
havecExtractUnflagged(hestOpt *opt, hestArgVec *havec, const hestParm *hparm) {
- char ident[AIR_STRLEN_HUGE + 1];
+ char *havStr, ident[AIR_STRLEN_HUGE + 1];
uint optNum = opt->arrLen; // number of options (flagged or unflagged)
uint ufOptNum = 0; // number of unflagged options
for (uint opi = 0; opi < optNum; opi++) {
@@ -1044,11 +1048,14 @@
Either way, we try extracting the args; in the later case just to generate a
descriptive error message about the situation */
if (opt[opi].min /* == max */ < havec->len || !opt[opi].dflt) {
+ havStr = hestArgVecSprint(havec, AIR_TRUE);
if (havecTransfer(opt + opi, havec, 0, opt[opi].min, hparm)) {
+ biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
biffAddf(HEST, "%s%strouble getting args for %sunflagged %s[%u]", _ME_,
!opt[opi].dflt ? "default-less " : "", identStr(ident, opt + opi), opi);
- return (free(ufOpi2), 1);
+ return (free(havStr), free(ufOpi2), 1);
}
+ havStr = airFree(havStr);
}
}
if (ufVarOpi == optNum) {
@@ -1071,11 +1078,14 @@
uint idx0 = (opt[opi].min < havec->len //
? havec->len - opt[opi].min //
: 0);
+ havStr = hestArgVecSprint(havec, AIR_TRUE);
if (havecTransfer(opt + opi, havec, idx0, opt[opi].min, hparm)) {
+ biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
biffAddf(HEST, "%s%strouble getting args for (later) %sunflagged %s[%u]", _ME_,
!opt[opi].dflt ? "default-less " : "", identStr(ident, opt + opi), opi);
- return (free(ufOpi2), 1);
+ return (free(havStr), free(ufOpi2), 1);
}
+ havStr = airFree(havStr);
}
}
@@ -1087,11 +1097,13 @@
}
uint minArg = opt[ufVarOpi].min; /* min < max ! */
if (minArg > havec->len && !opt[ufVarOpi].dflt) {
+ havStr = hestArgVecSprint(havec, AIR_TRUE);
+ biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
biffAddf(HEST,
"%s%shave only %u args left but need %u for "
"(default-less) variadic unflagged %s[%u]",
_ME_, havec->len, minArg, identStr(ident, opt + ufVarOpi), ufVarOpi);
- return (free(ufOpi2), 1);
+ return (free(havStr), free(ufOpi2), 1);
}
// else minArg <= havec->len, or, minArg > havec->len and do have default
if (minArg <= havec->len) {
@@ -1101,9 +1113,11 @@
getArg = AIR_MIN(getArg, AIR_UINT(opt[ufVarOpi].max));
}
if (havecTransfer(opt + ufVarOpi, havec, 0, getArg, hparm)) {
+ havStr = hestArgVecSprint(havec, AIR_TRUE);
+ biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
biffAddf(HEST, "%s%strouble getting args for variadic unflagged %s[%u]", _ME_,
identStr(ident, opt + ufVarOpi), ufVarOpi);
- return (free(ufOpi2), 1);
+ return (free(havStr), free(ufOpi2), 1);
}
}
// else minArg > havec->len so can't satisfy from havec,
@@ -1113,7 +1127,7 @@
for (upii = 0; upii < ufOptNum; upii++) {
uint opi = ufOpi2[2 * upii + 0];
if (!(opt[opi].dflt) && hestSourceUnknown == opt[opi].source) {
- biffAddf(HEST, "%s%sdidn't see required (unflagged) %s[%u]", _ME_,
+ biffAddf(HEST, "%s%sdidn't see required (default-less) unflagged %s[%u]", _ME_,
identStr(ident, opt + opi), opi);
return (free(ufOpi2), 1);
}
@@ -1125,14 +1139,16 @@
hestArgVecPrint(__func__, "end of havecExtractUnflagged", havec);
}
if (havec->len) {
+ havStr = hestArgVecSprint(havec, AIR_TRUE);
+ biffAddf(HEST, "%s%sgiven (labeled) argv=|%s|", _ME_, havStr);
biffAddf(HEST,
"%s%safter getting %u unflagged opts, have %u unexpected arg%s "
"%s\"%s\"",
_ME_, ufOptNum, havec->len, havec->len > 1 ? "s," : "",
havec->len > 1 ? "starting with " : "", havec->harg[0]->str);
- return (airFree(ufOpi2), 1);
+ return (free(havStr), airFree(ufOpi2), 1);
}
- return (airFree(ufOpi2), 0);
+ return (airFree(havStr), airFree(ufOpi2), 0);
}
/* optProcessDefaults
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-25 21:11:09 UTC (rev 7492)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-25 21:27:03 UTC (rev 7493)
@@ -50,7 +50,7 @@
int *unpB;
unsigned int sawB;
- hestOptAdd_Nv_Int(&opt, NULL, "B B", 1, -1, &unpB, /* "BBBB" */ NULL, "unflagged B",
+ hestOptAdd_Nv_Int(&opt, NULL, "B B", 2, -1, &unpB, /* "BBBB" */ NULL, "unflagged B",
&sawB);
/* int unpB[2];
hestOptAdd_2_Int(&opt, NULL, "B B", unpB, NULL, "unflagged B"); */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 21:11:14
|
Revision: 7492
http://sourceforge.net/p/teem/code/7492
Author: kindlmann
Date: 2025-09-25 21:11:09 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
bug fix
Modified Paths:
--------------
teem/trunk/src/hest/parsest.c
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 21:09:48 UTC (rev 7491)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 21:11:09 UTC (rev 7492)
@@ -877,7 +877,7 @@
__func__, optIdx, theOpt->flag, parmNum, hitEnd, hitVPS, nextOptIdx);
if (parmNum < theOpt->min) { // didn't get required min # parameters
char *havStr = hestArgVecSprint(havec, AIR_TRUE);
- biffAddf(HEST, "%s%sworking on argv: %s", havStr);
+ biffAddf(HEST, "%s%sworking on argv: %s", _ME_, havStr);
if (hitEnd) {
biffAddf(HEST,
"%s%shit end of args before getting %u parameter%s "
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 21:09:55
|
Revision: 7491
http://sourceforge.net/p/teem/code/7491
Author: kindlmann
Date: 2025-09-25 21:09:48 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
added hestArgVecSprint but still debugging
Modified Paths:
--------------
teem/trunk/src/hest/argvHest.c
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c 2025-09-25 11:28:19 UTC (rev 7490)
+++ teem/trunk/src/hest/argvHest.c 2025-09-25 21:09:48 UTC (rev 7491)
@@ -90,10 +90,12 @@
return;
}
-void
-hestArgSetString(hestArg *harg, const char *str) {
+static void
+arg_AddOrSet_String(hestArg *harg, int resetFirst, const char *str) {
assert(harg && str);
- hestArgReset(harg);
+ if (resetFirst) {
+ hestArgReset(harg);
+ }
uint len = AIR_UINT(strlen(str));
for (uint si = 0; si < len; si++) {
hestArgAddChar(harg, str[si]);
@@ -101,6 +103,18 @@
return;
}
+void
+hestArgSetString(hestArg *harg, const char *str) {
+ arg_AddOrSet_String(harg, AIR_TRUE, str);
+ return;
+}
+
+void
+hestArgAddString(hestArg *harg, const char *str) {
+ arg_AddOrSet_String(harg, AIR_FALSE, str);
+ return;
+}
+
/* ---------------------- hestArgVec = havec = hestArgVec = havec ------------------ */
/* to avoid strict aliasing warnings */
@@ -145,6 +159,7 @@
return NULL;
}
+// return havec->harg[popIdx] and shift higher indices down
hestArg *
hestArgVecRemove(hestArgVec *havec, uint popIdx) {
hestArg *ret = NULL;
@@ -152,18 +167,7 @@
ret = havec->harg[popIdx];
uint ai;
for (ai = popIdx; ai < havec->len - 1; ai++) {
- // shuffle down info inside the hestArg elements of havec->harg
havec->harg[ai] = havec->harg[ai + 1];
- // hestArgSetString(havec->harg + ai, (havec->harg + ai + 1)->str);
- // (havec->harg + ai)->source = (havec->harg + ai + 1)->source;
- /* why cannot just memcpy:
- because then the last hestArg element of havec->harg
- (the one that is being forgotten)
- and the second-to-last element (the last one being kept)
- will share ->str pointers.
- When hargDone is called on the last hestArg's address
- as the callack from airArrayLenIncr(), then it will also
- free the str inside the second-to-last element; oops */
}
// NULL out final out, using final value of ai
havec->harg[ai] = NULL;
@@ -173,7 +177,99 @@
return ret;
}
+/* hestArgVecSprint goes is opposite of the shell-style tokenization of
+parsest.c/argstGo: generate a single human-friendly string that could be tokenized to
+recover the hestArgVec we started with.
+ChatGPT helped with prototyping.
+Here are instructive examples of the same kind of argv pretty-printing:
+https://github.com/git/git/blob/master/quote.c
+and here https://www.opencoverage.net/coreutils/index_html/source_213.html
+with its (more baroque) quotearg_buffer_restyled() function
+*/
+
+// plainWord(str) is true if nothing in str needs quoting or escaping
+static int
+plainWord(const char *s) {
+ if (*s == '\0') {
+ // wut - we got the empty string, yes needs quoting
+ return 0;
+ }
+ int plain = AIR_TRUE;
+ for (; *s; s++) {
+ plain &= (isalnum(*s) //
+ || *s == '_' || *s == '-' //
+ || *s == '.' || *s == '/');
+ if (!plain) break;
+ }
+ return plain;
+}
+
+/* Assuming that `str` needs some quoting or ecaping to be retokenized as a single arg
+then figure out if that should be via single or double quoting, by doing both and picking
+the shorter one */
void
+argAddQuotedString(hestArg *harg, const char *str) {
+ hestArg *singQ = hestArgNew();
+ hestArg *doubQ = hestArgNew();
+ hestArgAddChar(singQ, '\'');
+ hestArgAddChar(doubQ, '"');
+ const char *src = str;
+ for (; *src; src++) {
+ // -- single quoting to singQ
+ if ('\'' == *src) {
+ // can't escape ' inside ''-quoting, so have to:
+ // stop ''-quoting, write (escaped) \', then re-start ''-quoting
+ hestArgAddString(singQ, "'\\''");
+ } else {
+ hestArgAddChar(singQ, *src);
+ }
+ // -- double quoting to doubQ
+ if ('"' == *src || '\\' == *src || '`' == *src || '$' == *src) {
+ // this character needs escaping
+ hestArgAddChar(doubQ, '\\');
+ }
+ hestArgAddChar(doubQ, *src);
+ }
+ hestArgAddChar(singQ, '\'');
+ hestArgAddChar(doubQ, '"');
+ // use single-quoting when it is shorter, else double-quoting
+ hestArgAddString(harg, singQ->len < doubQ->len ? singQ->str : doubQ->str);
+ hestArgNix(singQ);
+ hestArgNix(doubQ);
+}
+
+char *
+hestArgVecSprint(const hestArgVec *havec, int showIdx) {
+ if (!havec) {
+ return NULL;
+ }
+ hestArg *retArg = hestArgNew();
+ for (uint ai = 0; ai < havec->len; ai++) {
+ if (ai) {
+ // add the space between previous and this arg
+ hestArgAddChar(retArg, ' ');
+ }
+ if (showIdx) {
+ char buff[AIR_STRLEN_SMALL + 1];
+ sprintf(buff, "%u", ai);
+ hestArgAddString(retArg, buff);
+ hestArgAddChar(retArg, ':');
+ }
+ const char *astr = havec->harg[ai]->str;
+ if (plainWord(astr)) {
+ hestArgAddString(retArg, astr);
+ } else {
+ argAddQuotedString(retArg, astr);
+ }
+ }
+ // the real hestArgNix: keep the string but lose everything around it
+ char *ret = retArg->str;
+ airArrayNix(retArg->strArr);
+ free(retArg);
+ return ret;
+}
+
+void
hestArgVecAppendString(hestArgVec *havec, const char *str) {
uint idx = airArrayLenIncr(havec->hargArr, 1);
hestArgSetString(havec->harg[idx], str);
@@ -209,6 +305,11 @@
printf(" %u%c:<%s>", idx, srcch[harg->source], harg->str ? harg->str : "NULL");
}
printf("\n");
+ char *ppargs = hestArgVecSprint(havec, AIR_FALSE);
+ printf("%s%s%s OR pretty-printed as:\n%s\n", airStrlen(caller) ? caller : "", //
+ airStrlen(caller) ? ": " : "", info, ppargs);
+ free(ppargs);
+ return;
}
/* ------------------------- hestInput = hin = hestInput = hin --------------------- */
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-25 11:28:19 UTC (rev 7490)
+++ teem/trunk/src/hest/hest.h 2025-09-25 21:09:48 UTC (rev 7491)
@@ -340,10 +340,12 @@
HEST_EXPORT void hestArgReset(hestArg *harg);
HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
HEST_EXPORT void hestArgSetString(hestArg *harg, const char *str);
+HEST_EXPORT void hestArgAddString(hestArg *harg, const char *str);
HEST_EXPORT hestArgVec *hestArgVecNew(void);
HEST_EXPORT void hestArgVecReset(hestArgVec *havec);
HEST_EXPORT hestArgVec *hestArgVecNix(hestArgVec *havec);
HEST_EXPORT hestArg *hestArgVecRemove(hestArgVec *havec, unsigned int popIdx);
+HEST_EXPORT char *hestArgVecSprint(const hestArgVec *havec, int showIndices);
HEST_EXPORT void hestArgVecAppendString(hestArgVec *havec, const char *str);
HEST_EXPORT void hestArgVecAppendArg(hestArgVec *havec, hestArg *harg);
HEST_EXPORT void hestArgVecPrint(const char *caller, const char *info,
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 11:28:19 UTC (rev 7490)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 21:09:48 UTC (rev 7491)
@@ -88,6 +88,7 @@
(although hest does not do rule 5 about parameter expansion, command substitution,
or arithmetic expansion), and here are the details about quoting:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02
+ChatGPT helped with prototyping.
Here is instructive example code https://github.com/nyuichi/dash.git
in src/parser.c see the readtoken1() function and the DFA there.
*/
@@ -327,7 +328,7 @@
biffAddf(HEST, "%s%sconfused by input source %d", _ME_, hin->source);
return 1;
}
- if (argstGo(nastP, tharg, &state, icc, hparm->verbosity > 3)) {
+ if (argstGo(nastP, tharg, &state, icc, hparm->verbosity > 4)) {
if (hestSourceResponseFile == hin->source) {
biffAddf(HEST, "%s%strouble at character %u of %s \"%s\"", _ME_, hin->carIdx,
airEnumStr(hestSource, hin->source), hin->rfname);
@@ -756,7 +757,7 @@
return 1;
}
if (!(srcIdx + num <= hvsrc->len)) {
- biffAddf(HEST, "%s%shave only %u args but want %u starting at %u", _ME_,
+ biffAddf(HEST, "%s%shave only %u args but want %u starting at index %u", _ME_,
hvsrc->len, num, srcIdx);
return 1;
}
@@ -775,9 +776,10 @@
optPrint(const hestOpt *opt, uint opi) {
printf("--- opt %u:", opi);
printf("\t%s%s", opt->flag ? "flag-" : "", opt->flag ? opt->flag : "UNflag");
- printf("\tname|%s|\t k%d (%u)--(%d) \t%s \tdflt|%s|\n",
- opt->name ? opt->name : "(null)", opt->kind, opt->min, opt->max,
- _hestTypeStr[opt->type], opt->dflt ? opt->dflt : "(null)");
+ printf("\tname|%s|\t k%d (%u)--(%d) \t%s ", opt->name ? opt->name : "(null)",
+ opt->kind, opt->min, opt->max, _hestTypeStr[opt->type]);
+ printf("\t%sdflt%s%s%s\n", opt->dflt ? "" : "NO-", opt->dflt ? "|" : "",
+ opt->dflt ? opt->dflt : "", opt->dflt ? "|" : "");
printf(" source %s\n", airEnumStr(hestSource, opt->source));
hestArgVecPrint("", " havec:", opt->havec);
return;
@@ -850,7 +852,8 @@
uint nextOptIdx = 0, // what is index of option who's flag we hit next
parmNum = 0, // how many parm args have we counted up
pai; // tmp parm arg index
- while ( // parmNum is plausible # parms
+
+ while ( // parmNum is plausible # parms
AIR_INT(parmNum) < _hestMax(theOpt->max)
// and looking ahead by parmNum still gives us a valid index pai
&& !(hitEnd = !((pai = argIdx + 1 + parmNum) < havec->len))
@@ -873,6 +876,8 @@
"parmNum=%u hitEnd=%d hitVPS=%d nextOptIdx=%u\n",
__func__, optIdx, theOpt->flag, parmNum, hitEnd, hitVPS, nextOptIdx);
if (parmNum < theOpt->min) { // didn't get required min # parameters
+ char *havStr = hestArgVecSprint(havec, AIR_TRUE);
+ biffAddf(HEST, "%s%sworking on argv: %s", havStr);
if (hitEnd) {
biffAddf(HEST,
"%s%shit end of args before getting %u parameter%s "
@@ -896,6 +901,7 @@
_ME_, theOpt->min, theOpt->min > 1 ? "s" : "", identStr(ident1, theOpt),
parmNum);
}
+ free(havStr);
return 1;
}
if (hparm->verbosity) {
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-25 11:28:19 UTC (rev 7490)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-25 21:09:48 UTC (rev 7491)
@@ -34,27 +34,28 @@
hestParm *hparm = hestParmNew();
hparm->respectDashDashHelp = AIR_TRUE;
hparm->responseFileEnable = AIR_TRUE;
- hparm->verbosity = 10;
+ hparm->verbosity = 4;
+ int flag;
+ hestOptAdd_Flag(&opt, "b,bingo", &flag, "a flag");
int verb;
hestOptAdd_1_Int(&opt, "v", "verb", &verb, "0", "verbosity");
- int *res;
int unpA[2];
hestOptAdd_2_Int(&opt, NULL, "A A", unpA, NULL, "unflagged A");
+
+ int *size;
unsigned int slen;
- hestOptAdd_Nv_Int(&opt, "s,sizes", "sx sy", 0, -1, &res, NULL, "image resolutions",
+ hestOptAdd_Nv_Int(&opt, "s,sizes", "sx sy", 2, -1, &size, NULL, "image resolutions",
&slen);
+
int *unpB;
unsigned int sawB;
- hestOptAdd_Nv_Int(&opt, NULL, "B B", 1, -1, &unpB, "BBBB", "unflagged B", &sawB);
+ hestOptAdd_Nv_Int(&opt, NULL, "B B", 1, -1, &unpB, /* "BBBB" */ NULL, "unflagged B",
+ &sawB);
/* int unpB[2];
hestOptAdd_2_Int(&opt, NULL, "B B", unpB, NULL, "unflagged B"); */
- int flag;
- hestOptAdd_Flag(&opt, "b,bingo", &flag, "a flag");
- int glaf;
- hestOptAdd_Flag(&opt, "c,cingo", &glaf, "a flag");
int unpC[2];
- hestOptAdd_2_Int(&opt, NULL, "C C", unpC, "dfltC0 dfltC1", "unflagged C");
+ hestOptAdd_2_Int(&opt, NULL, "C C", unpC, /* "dfltC0 dfltC1" */ NULL, "unflagged C");
/*
int *unpC;
unsigned int sawC;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 11:28:21
|
Revision: 7490
http://sourceforge.net/p/teem/code/7490
Author: kindlmann
Date: 2025-09-25 11:28:19 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
better error messages
Modified Paths:
--------------
teem/trunk/src/hest/parsest.c
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 11:24:21 UTC (rev 7489)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 11:28:19 UTC (rev 7490)
@@ -1039,8 +1039,8 @@
descriptive error message about the situation */
if (opt[opi].min /* == max */ < havec->len || !opt[opi].dflt) {
if (havecTransfer(opt + opi, havec, 0, opt[opi].min, hparm)) {
- biffAddf(HEST, "%s%strouble getting args for unflagged %s[%u]", _ME_,
- identStr(ident, opt + opi), opi);
+ biffAddf(HEST, "%s%strouble getting args for %sunflagged %s[%u]", _ME_,
+ !opt[opi].dflt ? "default-less " : "", identStr(ident, opt + opi), opi);
return (free(ufOpi2), 1);
}
}
@@ -1066,8 +1066,8 @@
? havec->len - opt[opi].min //
: 0);
if (havecTransfer(opt + opi, havec, idx0, opt[opi].min, hparm)) {
- biffAddf(HEST, "%s%strouble getting args for (later) unflagged %s[%u]", _ME_,
- identStr(ident, opt + opi), opi);
+ biffAddf(HEST, "%s%strouble getting args for (later) %sunflagged %s[%u]", _ME_,
+ !opt[opi].dflt ? "default-less " : "", identStr(ident, opt + opi), opi);
return (free(ufOpi2), 1);
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 11:24:24
|
Revision: 7489
http://sourceforge.net/p/teem/code/7489
Author: kindlmann
Date: 2025-09-25 11:24:21 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
removing errant debugging printf
Modified Paths:
--------------
teem/trunk/src/hest/parsest.c
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 11:17:20 UTC (rev 7488)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 11:24:21 UTC (rev 7489)
@@ -551,9 +551,9 @@
topHin = (hist->len //
? hist->hin + hist->len - 1
: NULL);
- printf("!%s: nast = %s, |stack| = %u, topHin = %p\n", __func__,
- airEnumStr(nast_ae, nast), hist->len, AIR_VOIDP(topHin));
- // we have a token, is it turning off commenting?
+ // printf("!%s: nast = %s, |stack| = %u, topHin = %p\n", __func__,
+ // airEnumStr(nast_ae, nast), hist->len, AIR_VOIDP(topHin));
+ // we have a token, is it turning off commenting?
if (hparm->respectDashBraceComments && !strcmp("}-", tharg->str)) {
if (!topHin) {
biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (0)", _ME_, iters,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 11:17:24
|
Revision: 7488
http://sourceforge.net/p/teem/code/7488
Author: kindlmann
Date: 2025-09-25 11:17:20 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
updated or changed logic of how to use available args for unflagged options
Modified Paths:
--------------
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 09:50:12 UTC (rev 7487)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 11:17:20 UTC (rev 7488)
@@ -956,15 +956,6 @@
return 0;
}
-static uint
-nextUnflagged(uint opi, hestOpt *opt) {
- uint optNum = opt->arrLen;
- for (; opi < optNum; opi++) {
- if (!opt[opi].flag) break;
- }
- return opi;
-}
-
/* havecExtractUnflagged()
extracts the parameter args associated with all unflagged options (of `hestOpt *opt`)
@@ -980,20 +971,19 @@
char ident[AIR_STRLEN_HUGE + 1];
uint optNum = opt->arrLen; // number of options (flagged or unflagged)
uint ufOptNum = 0; // number of unflagged options
- uint ufParmMin = 0; // over all the unflagged options, summing opt->min
for (uint opi = 0; opi < optNum; opi++) {
if (!opt[opi].flag) {
ufOptNum += 1;
- ufParmMin += opt[opi].min;
}
}
+ /* simplify indexing into unflagged options, forward and backward,
+ with a little Nx2 array ufOpi2 of option indices */
+ uint *ufOpi2 = NULL;
if (!ufOptNum) {
/* no unflagged options; we're ~done */
goto finishingup;
}
- /* simplify indexing into unflagged options, forward and backward,
- with a little array of pairs of option indices */
- uint *ufOpi2 = AIR_CALLOC(2 * ufOptNum, uint);
+ ufOpi2 = AIR_CALLOC(2 * ufOptNum, uint);
assert(ufOpi2);
uint upii = 0; // index into ufOpi2
for (uint opi = 0; opi < optNum; opi++) {
@@ -1002,11 +992,9 @@
upii++;
}
}
- for (uint opi = optNum; opi-- > 0; opi--) {
- if (!opt[opi].flag) {
- upii--;
- ufOpi2[2 * upii + 1] = opi;
- }
+ for (upii = 0; upii < ufOptNum; upii++) {
+ // fill in backward side
+ ufOpi2[2 * upii + 1] = ufOpi2[2 * (ufOptNum - 1 - upii) + 0];
}
if (hparm->verbosity) {
printf("%s: ufOpi2 helper array:\n up:", __func__);
@@ -1018,23 +1006,13 @@
printf(" \t%u", ufOpi2[2 * upii + 1]);
}
printf("\n");
- exit(0);
}
- /* if we need more args than we actually have, we assume that the opt->default strings
- can be used to generate those args later, which shifts our logic for consuming args */
- int asumDflt = ufParmMin > havec->len;
- if (hparm->verbosity) {
- printf("%s: ufParmMin %u vs havec->len %u --> asumDflt %d\n", __func__, ufParmMin,
- havec->len, asumDflt);
- }
- uint ufVarOpi; // the index of the unflagged variadic parm option
- for (ufVarOpi = nextUnflagged(0, opt); //
- ufVarOpi < optNum;
- ufVarOpi = nextUnflagged(ufVarOpi + 1, opt)) {
- if (opt[ufVarOpi].kind > 3) {
- if (5 == opt[ufVarOpi].kind) { // multiple variadic parm
- break;
- }
+ uint ufVarOpi = optNum; // index (if < optNum) of the unflagged variadic parm option
+ for (upii = 0; upii < ufOptNum; upii++) {
+ uint opi = ufOpi2[2 * upii + 0];
+ if (5 == opt[opi].kind) { // (unflagged) multiple variadic parm
+ ufVarOpi = opi;
+ break;
}
}
/* now, if there is an unflagged variadic option (NOTE that _hestOPCheck()
@@ -1041,92 +1019,97 @@
ensured that there is at most one of these), then ufVarOpi is its index in opt[].
If there is no unflagged variadic option, ufVarOpi is optNum. */
if (hparm->verbosity) {
- printf("%s: ufVarOpi %u %s\n", __func__, ufVarOpi,
- (ufVarOpi == optNum ? "==> there is no unflagged var parm opt"
- : "is index of single unflagged var parm opt"));
+ printf("%s: ufVarOpi = %u %s\n", __func__, ufVarOpi,
+ (ufVarOpi == optNum ? "==> there is no unflagged variadic opt"
+ : "is index of single unflagged variadic opt"));
}
- /* grab parameters for all unflagged opts before opt[ufVarOpi] */
- for (uint opi = nextUnflagged(0, opt); //
- opi < ufVarOpi;
- opi = nextUnflagged(opi + 1, opt)) {
+ // grab parameters for all unflagged opts before opt[ufVarOpi]
+ for (upii = 0; upii < ufOptNum; upii++) {
+ uint opi = ufOpi2[2 * upii + 0]; // 0: increasing index direction
+ if (opi == ufVarOpi) {
+ break;
+ }
if (hparm->verbosity) {
printf("%s: looking at opi = %u kind %d\n", __func__, opi, opt[opi].kind);
}
- /* either we're not leaning on the defaults (because we know we have enough args).
- or we are learning on defaults, but this option doesn't have a default,
- so we need to extract the args here */
- if (!asumDflt || !opt[opi].dflt) {
- if (havecTransfer(opt + opi, havec, 0, opt[opi].min /* min == max */, hparm)) {
- biffAddf(HEST, "%s%strouble getting (early) args for unflagged %s", _ME_,
- identStr(ident, opt + opi));
- return 1;
+ /* Either we're not using the defaults because we know we have enough args,
+ else we know we do not have enough args and yet we also don't have a default.
+ Either way, we try extracting the args; in the later case just to generate a
+ descriptive error message about the situation */
+ if (opt[opi].min /* == max */ < havec->len || !opt[opi].dflt) {
+ if (havecTransfer(opt + opi, havec, 0, opt[opi].min, hparm)) {
+ biffAddf(HEST, "%s%strouble getting args for unflagged %s[%u]", _ME_,
+ identStr(ident, opt + opi), opi);
+ return (free(ufOpi2), 1);
}
}
}
- /* we skip over the variadic parameter unflagged option, subtract from havec->len the
- number of parameters in all the opts which follow it, in order to get the number of
- parameters in the sole variadic parameter option; store this in nvp */
- int nvp = AIR_INT(havec->len);
- for (uint opi = nextUnflagged(ufVarOpi + 1, opt); opi < optNum;
- opi = nextUnflagged(opi + 1, opt)) {
- nvp -= AIR_INT(opt[opi].min); // min == max
+ if (ufVarOpi == optNum) {
+ // if there is no unflagged multiple variadic option, we're done-ish
+ goto finishingup;
}
- if (nvp < 0) {
- uint opi = nextUnflagged(ufVarOpi + 1, opt);
- uint np = opt[opi].min;
- biffAddf(HEST,
- "%s%sremaining %u args not enough for the %u parameter%s "
- "needed for unflagged %s or later options",
- _ME_, havec->len, np, np > 1 ? "s" : "", identStr(ident, opt + opi));
- return 1;
- }
- /* else we had enough args for all the unflagged options following
- the sole variadic parameter unflagged option, so snarf them up */
- for (uint opi = nextUnflagged(ufVarOpi + 1, opt); opi < optNum;
- opi = nextUnflagged(opi + 1, opt)) {
- if (havecTransfer(opt + opi, havec, nvp, opt[opi].min /* min == max */, hparm)) {
- biffAddf(HEST, "%s%strouble getting args for unflagged %s", _ME_,
- identStr(ident, opt + opi));
- return 1;
+ /* else we do have an unflagged multiple variadic option, so we work down to it
+ from other end of arg vec */
+ // HEY COPY-PASTA
+ for (upii = 0; upii < ufOptNum; upii++) {
+ uint opi = ufOpi2[2 * upii + 1]; // 1: decreasing index direction
+ if (opi == ufVarOpi) {
+ break;
}
- }
-
- /* now, finally, we grab the parameters of the sole variadic parameter unflagged opt,
- if it exists (ufVarOpi < optNum) */
- if (ufVarOpi < optNum) { // so there is a variadic parameter unflagged opt
if (hparm->verbosity) {
- printf("%s: ufVarOpi=%u: min, nvp, max = %u %d %d\n", __func__, ufVarOpi,
- opt[ufVarOpi].min, nvp, _hestMax(opt[ufVarOpi].max));
+ printf("%s: looking at (later) opi = %u kind %d\n", __func__, opi, opt[opi].kind);
}
- /* we'll do error checking for unexpected args next */
- if (nvp) {
- /* pre-2023: this check used to be done regardless of nvp, but that incorrectly
- triggered this error message when there were zero given parms, but the default
- could have supplied them */
- if (nvp < AIR_INT(opt[ufVarOpi].min)) {
- biffAddf(HEST, "%s%sdidn't get minimum of %d arg%s for %s (got %d)", _ME_,
- opt[ufVarOpi].min, opt[ufVarOpi].min > 1 ? "s" : "",
- identStr(ident, opt + ufVarOpi), nvp);
- return 1;
+ // same logic as above
+ if (opt[opi].min /* == max */ < havec->len || !opt[opi].dflt) {
+ uint idx0 = (opt[opi].min < havec->len //
+ ? havec->len - opt[opi].min //
+ : 0);
+ if (havecTransfer(opt + opi, havec, idx0, opt[opi].min, hparm)) {
+ biffAddf(HEST, "%s%strouble getting args for (later) unflagged %s[%u]", _ME_,
+ identStr(ident, opt + opi), opi);
+ return (free(ufOpi2), 1);
}
- if (havecTransfer(opt + ufVarOpi, havec, 0, nvp, hparm)) {
- biffAddf(HEST, "%s%strouble getting args for unflagged %s", _ME_,
- identStr(ident, opt + ufVarOpi));
- return 1;
- }
}
}
+ /* now, finally, we grab the parameters of the sole variadic parameter unflagged opt;
+ the one with index ufVarOpi < optNum (and we're only here because it exists) */
+ if (hparm->verbosity) {
+ printf("%s: ufVarOpi=%u min, have, max = %u %u %d\n", __func__, ufVarOpi,
+ opt[ufVarOpi].min, havec->len, _hestMax(opt[ufVarOpi].max));
+ }
+ uint minArg = opt[ufVarOpi].min; /* min < max ! */
+ if (minArg > havec->len && !opt[ufVarOpi].dflt) {
+ biffAddf(HEST,
+ "%s%shave only %u args left but need %u for "
+ "(default-less) variadic unflagged %s[%u]",
+ _ME_, havec->len, minArg, identStr(ident, opt + ufVarOpi), ufVarOpi);
+ return (free(ufOpi2), 1);
+ }
+ // else minArg <= havec->len, or, minArg > havec->len and do have default
+ if (minArg <= havec->len) {
+ // can satisfy option from havec, no need to use default
+ uint getArg = havec->len; // want to grab as many args as possible
+ if (-1 != opt[ufVarOpi].max) { // but no more than needed
+ getArg = AIR_MIN(getArg, AIR_UINT(opt[ufVarOpi].max));
+ }
+ if (havecTransfer(opt + ufVarOpi, havec, 0, getArg, hparm)) {
+ biffAddf(HEST, "%s%strouble getting args for variadic unflagged %s[%u]", _ME_,
+ identStr(ident, opt + ufVarOpi), ufVarOpi);
+ return (free(ufOpi2), 1);
+ }
+ }
+ // else minArg > havec->len so can't satisfy from havec,
+ // but its ok since we do have default
+
/* make sure that unflagged options without default were given */
- for (uint opi = nextUnflagged(0, opt); //
- opi < optNum;
- opi = nextUnflagged(opi + 1, opt)) {
+ for (upii = 0; upii < ufOptNum; upii++) {
+ uint opi = ufOpi2[2 * upii + 0];
if (!(opt[opi].dflt) && hestSourceUnknown == opt[opi].source) {
- char ident1[AIR_STRLEN_HUGE + 1];
- biffAddf(HEST, "%s%sdidn't see required (unflagged) %s", _ME_,
- identStr(ident1, opt + opi));
- return 1;
+ biffAddf(HEST, "%s%sdidn't see required (unflagged) %s[%u]", _ME_,
+ identStr(ident, opt + opi), opi);
+ return (free(ufOpi2), 1);
}
}
@@ -1141,9 +1124,9 @@
"%s\"%s\"",
_ME_, ufOptNum, havec->len, havec->len > 1 ? "s," : "",
havec->len > 1 ? "starting with " : "", havec->harg[0]->str);
- return 1;
+ return (airFree(ufOpi2), 1);
}
- return 0;
+ return (airFree(ufOpi2), 0);
}
/* optProcessDefaults
@@ -1180,8 +1163,8 @@
identStr(ident, opt + opi);
// should have already checked for this but just to make sure
if (!opt[opi].dflt) {
- biffAddf(HEST, "%s%sopt[%u] %s needs default string but it is NULL", _ME_, opi,
- ident);
+ biffAddf(HEST, "%s%s %s[%u] needs default string but it is NULL", _ME_, ident,
+ opi);
return 1;
}
/* in some circumstances the default may be empty "", even if non-NULL, which means
@@ -1189,13 +1172,12 @@
we set the source above to hestSourceDefault, so that we'd know the source even if it
isn't apparent in any of the (non-existant) args. */
if (hparm->verbosity) {
- printf("%s: looking at opt[%u] %s default string |%s|\n", __func__, opi, ident,
+ printf("%s: looking at %s[%u] default string |%s|\n", __func__, ident, opi,
opt[opi].dflt);
}
if (histPushDefault(hist, opt[opi].dflt, hparm)
|| histProcess(opt[opi].havec, NULL, tharg, hist, hparm)) {
- biffAddf(HEST, "%s%sproblem tokenizing opt[%u] %s default string", _ME_, opi,
- ident);
+ biffAddf(HEST, "%s%sproblem tokenizing %s[%u] default string", _ME_, ident, opi);
return 1;
}
/* havecExtractFlagged and havecExtractUnflagged have done the work of ensuring that
@@ -1203,9 +1185,9 @@
something analogous for args tokenized from the default strings. */
if (opt[opi].havec->len < opt[opi].min) {
biffAddf(
- HEST,
- "%s%sopt[%u] %s default string supplied %u args but option wants at least %u",
- _ME_, opi, ident, opt[opi].havec->len, opt[opi].min);
+ HEST, "%s%s %s[%u] default string \"%s\" supplied %u arg%s but need at least %u",
+ _ME_, ident, opi, opt[opi].dflt, opt[opi].havec->len,
+ opt[opi].havec->len > 1 ? "s" : "", opt[opi].min);
return 1;
}
nextopt:
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-25 09:50:12 UTC (rev 7487)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-25 11:17:20 UTC (rev 7488)
@@ -54,7 +54,7 @@
int glaf;
hestOptAdd_Flag(&opt, "c,cingo", &glaf, "a flag");
int unpC[2];
- hestOptAdd_2_Int(&opt, NULL, "C C", unpC, "dfltC0", "unflagged C");
+ hestOptAdd_2_Int(&opt, NULL, "C C", unpC, "dfltC0 dfltC1", "unflagged C");
/*
int *unpC;
unsigned int sawC;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-25 09:50:16
|
Revision: 7487
http://sourceforge.net/p/teem/code/7487
Author: kindlmann
Date: 2025-09-25 09:50:12 +0000 (Thu, 25 Sep 2025)
Log Message:
-----------
still hacking
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parsest.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-25 08:56:49 UTC (rev 7486)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-25 09:50:12 UTC (rev 7487)
@@ -526,7 +526,7 @@
return 1;
}
uint optNum = opt->arrLen;
- uint varNum = 0; // number of variadic-parameter options
+ uint ufvarNum = 0; // number of unflagged variadic-parameter options
for (uint opi = 0; opi < optNum; opi++) {
if (!(AIR_IN_OP(airTypeUnknown, opt[opi].type, airTypeLast))) {
biffAddf(HEST, "%s%sopt[%u].type (%d) not in valid range [%d,%d]", _ME_, opi,
@@ -709,11 +709,11 @@
return 1;
}
// kind 4 = single variadic parm; kind 5 = multiple variadic parm
- varNum += (opt[opi].kind > 3 && (NULL == opt[opi].flag));
+ ufvarNum += (opt[opi].kind > 3 && (!opt[opi].flag));
}
- if (varNum > 1) {
- biffAddf(HEST, "%s%scan't have %u unflagged min<max options, only one", _ME_,
- varNum);
+ if (ufvarNum > 1) {
+ biffAddf(HEST, "%s%scan have at most 1 unflagged min<max options, not %u", _ME_,
+ ufvarNum);
return 1;
}
return 0;
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-25 08:56:49 UTC (rev 7486)
+++ teem/trunk/src/hest/parsest.c 2025-09-25 09:50:12 UTC (rev 7487)
@@ -549,14 +549,15 @@
}
// annoyingly, we may get here with an empty stack (HEY fix this?)
topHin = (hist->len //
- ? hist->hin + hist->len - 1
- : NULL);
- printf("!%s: nast = %s, |stack| = %u, topHin = %p\n", __func__, airEnumStr(nast_ae, nast),
- hist->len, AIR_VOIDP(topHin));
+ ? hist->hin + hist->len - 1
+ : NULL);
+ printf("!%s: nast = %s, |stack| = %u, topHin = %p\n", __func__,
+ airEnumStr(nast_ae, nast), hist->len, AIR_VOIDP(topHin));
// we have a token, is it turning off commenting?
if (hparm->respectDashBraceComments && !strcmp("}-", tharg->str)) {
if (!topHin) {
- biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (0)", _ME_, iters, srcstr);
+ biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (0)", _ME_, iters,
+ srcstr);
return 1;
}
if (topHin->dashBraceComment) {
@@ -577,7 +578,8 @@
// not ending comment, are we starting (or deepening) one?
if (hparm->respectDashBraceComments && !strcmp("-{", tharg->str)) {
if (!topHin) {
- biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (1)", _ME_, iters, srcstr);
+ biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (1)", _ME_, iters,
+ srcstr);
return 1;
}
topHin->dashBraceComment += 1;
@@ -598,7 +600,8 @@
// else this arg is not in a comment and is not related to commenting
if (hparm->respectDashDashHelp && !strcmp("--help", tharg->str)) {
if (!topHin) {
- biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (2)", _ME_, iters, srcstr);
+ biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (2)", _ME_, iters,
+ srcstr);
return 1;
}
if (hestSourceCommandLine == topHin->source) {
@@ -623,7 +626,8 @@
}
if (hparm->responseFileEnable && tharg->str[0] == RESPONSE_FILE_FLAG) {
if (!topHin) {
- biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (3)", _ME_, iters, srcstr);
+ biffAddf(HEST, "%s%s(iter %u, on %s) unexpected empty stack (3)", _ME_, iters,
+ srcstr);
return 1;
}
if (hestSourceDefault == topHin->source) {
@@ -974,56 +978,90 @@
static int
havecExtractUnflagged(hestOpt *opt, hestArgVec *havec, const hestParm *hparm) {
char ident[AIR_STRLEN_HUGE + 1];
- uint optNum = opt->arrLen;
- uint unflagNum = 0;
+ uint optNum = opt->arrLen; // number of options (flagged or unflagged)
+ uint ufOptNum = 0; // number of unflagged options
+ uint ufParmMin = 0; // over all the unflagged options, summing opt->min
for (uint opi = 0; opi < optNum; opi++) {
- unflagNum += !opt[opi].flag;
+ if (!opt[opi].flag) {
+ ufOptNum += 1;
+ ufParmMin += opt[opi].min;
+ }
}
- if (!unflagNum) {
+ if (!ufOptNum) {
/* no unflagged options; we're ~done */
goto finishingup;
}
- uint unflag1st = nextUnflagged(0, opt);
+ /* simplify indexing into unflagged options, forward and backward,
+ with a little array of pairs of option indices */
+ uint *ufOpi2 = AIR_CALLOC(2 * ufOptNum, uint);
+ assert(ufOpi2);
+ uint upii = 0; // index into ufOpi2
+ for (uint opi = 0; opi < optNum; opi++) {
+ if (!opt[opi].flag) {
+ ufOpi2[2 * upii + 0] = opi;
+ upii++;
+ }
+ }
+ for (uint opi = optNum; opi-- > 0; opi--) {
+ if (!opt[opi].flag) {
+ upii--;
+ ufOpi2[2 * upii + 1] = opi;
+ }
+ }
if (hparm->verbosity) {
- printf("%s: optNum %u != unflag1st %u: have %u (of %u) unflagged options\n",
- __func__, optNum, unflag1st, unflagNum, optNum);
+ printf("%s: ufOpi2 helper array:\n up:", __func__);
+ for (upii = 0; upii < ufOptNum; upii++) {
+ printf(" \t%u", ufOpi2[2 * upii + 0]);
+ }
+ printf("\n down:");
+ for (upii = 0; upii < ufOptNum; upii++) {
+ printf(" \t%u", ufOpi2[2 * upii + 1]);
+ }
+ printf("\n");
+ exit(0);
}
- uint unflagVar; // the index of the unflagged variadic parm option
- for (unflagVar = unflag1st; //
- unflagVar < optNum;
- unflagVar = nextUnflagged(unflagVar + 1, opt)) {
- if (opt[unflagVar].kind > 3) {
- if (4 == opt[unflagVar].kind) {
- // (should have been enforced by _hestOPCheck)
- biffAddf(HEST, "%s%sopt[%u] is (disallowed) unflagged single var parm (kind 4)",
- _ME_, unflagVar);
- return 1;
- } else {
- // kind 5 = multiple variadic parm; we allow one of these
+ /* if we need more args than we actually have, we assume that the opt->default strings
+ can be used to generate those args later, which shifts our logic for consuming args */
+ int asumDflt = ufParmMin > havec->len;
+ if (hparm->verbosity) {
+ printf("%s: ufParmMin %u vs havec->len %u --> asumDflt %d\n", __func__, ufParmMin,
+ havec->len, asumDflt);
+ }
+ uint ufVarOpi; // the index of the unflagged variadic parm option
+ for (ufVarOpi = nextUnflagged(0, opt); //
+ ufVarOpi < optNum;
+ ufVarOpi = nextUnflagged(ufVarOpi + 1, opt)) {
+ if (opt[ufVarOpi].kind > 3) {
+ if (5 == opt[ufVarOpi].kind) { // multiple variadic parm
break;
}
}
}
- /* now, if there is a variadic parameter unflagged opt (NOTE that _hestOPCheck()
- ensured that there is at most one of these), then unflagVar is its index in opt[].
- If there is no variadic parameter unflagged opt, unflagVar is optNum. */
+ /* now, if there is an unflagged variadic option (NOTE that _hestOPCheck()
+ ensured that there is at most one of these), then ufVarOpi is its index in opt[].
+ If there is no unflagged variadic option, ufVarOpi is optNum. */
if (hparm->verbosity) {
- printf("%s: unflagVar %u %s\n", __func__, unflagVar,
- (unflagVar == optNum ? "==> there is no unflagged var parm opt"
- : "is index of single unflagged var parm opt"));
+ printf("%s: ufVarOpi %u %s\n", __func__, ufVarOpi,
+ (ufVarOpi == optNum ? "==> there is no unflagged var parm opt"
+ : "is index of single unflagged var parm opt"));
}
- /* grab parameters for all unflagged opts before opt[unflagVar] */
+ /* grab parameters for all unflagged opts before opt[ufVarOpi] */
for (uint opi = nextUnflagged(0, opt); //
- opi < unflagVar;
+ opi < ufVarOpi;
opi = nextUnflagged(opi + 1, opt)) {
if (hparm->verbosity) {
printf("%s: looking at opi = %u kind %d\n", __func__, opi, opt[opi].kind);
}
- if (havecTransfer(opt + opi, havec, 0, opt[opi].min /* min == max */, hparm)) {
- biffAddf(HEST, "%s%strouble getting args for unflagged %s", _ME_,
- identStr(ident, opt + opi));
- return 1;
+ /* either we're not leaning on the defaults (because we know we have enough args).
+ or we are learning on defaults, but this option doesn't have a default,
+ so we need to extract the args here */
+ if (!asumDflt || !opt[opi].dflt) {
+ if (havecTransfer(opt + opi, havec, 0, opt[opi].min /* min == max */, hparm)) {
+ biffAddf(HEST, "%s%strouble getting (early) args for unflagged %s", _ME_,
+ identStr(ident, opt + opi));
+ return 1;
+ }
}
}
/* we skip over the variadic parameter unflagged option, subtract from havec->len the
@@ -1030,12 +1068,12 @@
number of parameters in all the opts which follow it, in order to get the number of
parameters in the sole variadic parameter option; store this in nvp */
int nvp = AIR_INT(havec->len);
- for (uint opi = nextUnflagged(unflagVar + 1, opt); opi < optNum;
+ for (uint opi = nextUnflagged(ufVarOpi + 1, opt); opi < optNum;
opi = nextUnflagged(opi + 1, opt)) {
nvp -= AIR_INT(opt[opi].min); // min == max
}
if (nvp < 0) {
- uint opi = nextUnflagged(unflagVar + 1, opt);
+ uint opi = nextUnflagged(ufVarOpi + 1, opt);
uint np = opt[opi].min;
biffAddf(HEST,
"%s%sremaining %u args not enough for the %u parameter%s "
@@ -1045,7 +1083,7 @@
}
/* else we had enough args for all the unflagged options following
the sole variadic parameter unflagged option, so snarf them up */
- for (uint opi = nextUnflagged(unflagVar + 1, opt); opi < optNum;
+ for (uint opi = nextUnflagged(ufVarOpi + 1, opt); opi < optNum;
opi = nextUnflagged(opi + 1, opt)) {
if (havecTransfer(opt + opi, havec, nvp, opt[opi].min /* min == max */, hparm)) {
biffAddf(HEST, "%s%strouble getting args for unflagged %s", _ME_,
@@ -1055,15 +1093,11 @@
}
/* now, finally, we grab the parameters of the sole variadic parameter unflagged opt,
- if it exists (unflagVar < optNum) */
- if (hparm->verbosity) {
- printf("%s: (still here) unflagVar %u vs optNum %u (nvp %d)\n", __func__, unflagVar,
- optNum, nvp);
- }
- if (unflagVar < optNum) { // so there is a variadic parameter unflagged opt
+ if it exists (ufVarOpi < optNum) */
+ if (ufVarOpi < optNum) { // so there is a variadic parameter unflagged opt
if (hparm->verbosity) {
- printf("%s: unflagVar=%u: min, nvp, max = %u %d %d\n", __func__, unflagVar,
- opt[unflagVar].min, nvp, _hestMax(opt[unflagVar].max));
+ printf("%s: ufVarOpi=%u: min, nvp, max = %u %d %d\n", __func__, ufVarOpi,
+ opt[ufVarOpi].min, nvp, _hestMax(opt[ufVarOpi].max));
}
/* we'll do error checking for unexpected args next */
if (nvp) {
@@ -1070,15 +1104,15 @@
/* pre-2023: this check used to be done regardless of nvp, but that incorrectly
triggered this error message when there were zero given parms, but the default
could have supplied them */
- if (nvp < AIR_INT(opt[unflagVar].min)) {
+ if (nvp < AIR_INT(opt[ufVarOpi].min)) {
biffAddf(HEST, "%s%sdidn't get minimum of %d arg%s for %s (got %d)", _ME_,
- opt[unflagVar].min, opt[unflagVar].min > 1 ? "s" : "",
- identStr(ident, opt + unflagVar), nvp);
+ opt[ufVarOpi].min, opt[ufVarOpi].min > 1 ? "s" : "",
+ identStr(ident, opt + ufVarOpi), nvp);
return 1;
}
- if (havecTransfer(opt + unflagVar, havec, 0, nvp, hparm)) {
+ if (havecTransfer(opt + ufVarOpi, havec, 0, nvp, hparm)) {
biffAddf(HEST, "%s%strouble getting args for unflagged %s", _ME_,
- identStr(ident, opt + unflagVar));
+ identStr(ident, opt + ufVarOpi));
return 1;
}
}
@@ -1105,7 +1139,7 @@
biffAddf(HEST,
"%s%safter getting %u unflagged opts, have %u unexpected arg%s "
"%s\"%s\"",
- _ME_, unflagNum, havec->len, havec->len > 1 ? "s," : "",
+ _ME_, ufOptNum, havec->len, havec->len > 1 ? "s," : "",
havec->len > 1 ? "starting with " : "", havec->harg[0]->str);
return 1;
}
@@ -1164,10 +1198,6 @@
ident);
return 1;
}
- if (hparm->verbosity) {
- printf("%s: DONE looking at opt[%u] %s default string |%s|\n", __func__, opi,
- ident, opt[opi].dflt);
- }
/* havecExtractFlagged and havecExtractUnflagged have done the work of ensuring that
the minimum number of parm args have been extracted for each option. We have to do
something analogous for args tokenized from the default strings. */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|