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-21 10:22:04
|
Revision: 7461
http://sourceforge.net/p/teem/code/7461
Author: kindlmann
Date: 2025-09-21 10:22:03 +0000 (Sun, 21 Sep 2025)
Log Message:
-----------
adding little utility to call hestOptAddDeclsPrint
Modified Paths:
--------------
teem/trunk/src/hest/GNUmakefile
Added Paths:
-----------
teem/trunk/src/hest/test/decls.c
Modified: teem/trunk/src/hest/GNUmakefile
===================================================================
--- teem/trunk/src/hest/GNUmakefile 2025-09-19 08:57:32 UTC (rev 7460)
+++ teem/trunk/src/hest/GNUmakefile 2025-09-21 10:22:03 UTC (rev 7461)
@@ -48,7 +48,7 @@
$(L).Obj = $(patsubst %.c,%.o, \
adders.c argvHest.c defaultsHest.c methodsHest.c parseHest.c parsest.c usage.c \
)
-$(L).Test = argv tparse ex1 ex2 ex3 ex4 ex5 ex6 strings bday tmpl
+$(L).Test = decls argv tparse ex1 ex2 ex3 ex4 ex5 ex6 strings bday tmpl
####
####
####
Added: teem/trunk/src/hest/test/decls.c
===================================================================
--- teem/trunk/src/hest/test/decls.c (rev 0)
+++ teem/trunk/src/hest/test/decls.c 2025-09-21 10:22:03 UTC (rev 7461)
@@ -0,0 +1,30 @@
+/*
+ Teem: Tools to process and visualize scientific data and images
+ Copyright (C) 2009--2023 University of Chicago
+ Copyright (C) 2005--2008 Gordon Kindlmann
+ Copyright (C) 1998--2004 University of Utah
+
+ This library is free software; you can redistribute it and/or modify it under the terms
+ of the GNU Lesser General Public License (LGPL) as published by the Free Software
+ Foundation; either version 2.1 of the License, or (at your option) any later version.
+ The terms of redistributing and/or modifying this software also include exceptions to
+ the LGPL that facilitate static linking.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "../hest.h"
+
+int
+main() {
+ printf("Writing decls.h and then bailing\n");
+ FILE *ff = fopen("decls.h", "w");
+ hestOptAddDeclsPrint(ff);
+ fclose(ff);
+
+ 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-19 08:57:33
|
Revision: 7460
http://sourceforge.net/p/teem/code/7460
Author: kindlmann
Date: 2025-09-19 08:57:32 +0000 (Fri, 19 Sep 2025)
Log Message:
-----------
one less memory leak
Modified Paths:
--------------
teem/trunk/src/hest/argvHest.c
Modified: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c 2025-09-19 08:54:38 UTC (rev 7459)
+++ teem/trunk/src/hest/argvHest.c 2025-09-19 08:57:32 UTC (rev 7460)
@@ -183,7 +183,9 @@
static void
hinDone(void *_hin) {
hestInput *hin = (hestInput *)_hin;
- /* nothing, for now*/
+ if (hin->rfile) {
+ airFclose(hin->rfile);
+ }
AIR_UNUSED(hin);
return;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-19 08:54:42
|
Revision: 7459
http://sourceforge.net/p/teem/code/7459
Author: kindlmann
Date: 2025-09-19 08:54:38 +0000 (Fri, 19 Sep 2025)
Log Message:
-----------
one less memory leak
Modified Paths:
--------------
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-19 08:50:37 UTC (rev 7458)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-19 08:54:38 UTC (rev 7459)
@@ -40,9 +40,10 @@
hestOptAdd_2_Int(&opt, "res", "sx sy", res, NULL, "image resolution");
int flag;
hestOptAdd_Flag(&opt, "b,bingo", &flag, "a flag");
- char *err;
+ char *err = NULL;
if (hestParse2(opt, argc - 1, argv + 1, &err, hparm)) {
fprintf(stderr, "%s: problem:\n%s\n", argv[0], err);
+ free(err);
ret = 1;
}
if (opt->helpWanted) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-19 08:50:42
|
Revision: 7458
http://sourceforge.net/p/teem/code/7458
Author: kindlmann
Date: 2025-09-19 08:50:37 +0000 (Fri, 19 Sep 2025)
Log Message:
-----------
hest re-write still underway, but the big change is that now hest internally depends on biff: it has gotten too annoying to not have biff's error message accumulation to diagnose what is going wrong with the new more modular and less monolithic parsing functions
Modified Paths:
--------------
teem/trunk/src/GNUmakefile
teem/trunk/src/_util/gen_biffdata.py
teem/trunk/src/hest/GNUmakefile
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/tparse.c
Modified: teem/trunk/src/GNUmakefile
===================================================================
--- teem/trunk/src/GNUmakefile 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/GNUmakefile 2025-09-19 08:50:37 UTC (rev 7458)
@@ -110,7 +110,7 @@
## DepLibs, RevLibs: strings of N/L (number/library) pairs, in either order
## (TEEM_LIB_LIST)
##
-Libs := air hest biff nrrd ell moss unrrdu alan tijk gage dye bane limn echo hoover seek ten elf pull coil push mite meet
+Libs := air biff hest nrrd ell moss unrrdu alan tijk gage dye bane limn echo hoover seek ten elf pull coil push mite meet
DepNums := 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M
ifneq ($(words $(Libs)),$(words $(DepNums)))
$(error Sorry, |Libs| == $(words $(Libs)) != $(words $(DepNums)) == |DepNums|)
Modified: teem/trunk/src/_util/gen_biffdata.py
===================================================================
--- teem/trunk/src/_util/gen_biffdata.py 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/_util/gen_biffdata.py 2025-09-19 08:50:37 UTC (rev 7458)
@@ -34,10 +34,11 @@
VERB = 1
# TEEM_LIB_LIST
-TLIBS = [ # 'air', 'hest', 'biff', (these libraries cannot not use biff, by their nature)
+TLIBS = [ # 'air', 'biff', (these libraries cannot not use biff, by their nature)
# the following lists ALL the other Teem libraries. It may be that some
# (like elf, tijk, unrrdu) do not use biff, but that is something we discover
# now as part of our operation, rather than decreeing from the outset.
+ 'hest', # in TeemV2 now depends on biff
'nrrd',
'ell',
'moss',
Modified: teem/trunk/src/hest/GNUmakefile
===================================================================
--- teem/trunk/src/hest/GNUmakefile 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/hest/GNUmakefile 2025-09-19 08:50:37 UTC (rev 7458)
@@ -42,7 +42,7 @@
#### Describe library L here
####
####
-$(L).Depends = air
+$(L).Depends = air biff # private biff dependency new for TeemV2
$(L).PublicHdr = hest.h
$(L).PrivateHdr = privateHest.h
$(L).Obj = $(patsubst %.c,%.o, \
Modified: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/hest/argvHest.c 2025-09-19 08:50:37 UTC (rev 7458)
@@ -55,7 +55,6 @@
/* initialize with \0 so that harg->str is "" */
airArrayLenIncr(harg->strArr, 1);
/* now harg->str = {0:'\0'} and harg->len = 1; */
- harg->finished = AIR_FALSE;
return;
}
@@ -89,6 +88,15 @@
}
void
+hestArgReset(hestArg *harg) {
+ assert(harg);
+ airArrayLenSet(harg->strArr, 0);
+ /* initialize with \0 so that harg->str is "" */
+ airArrayLenIncr(harg->strArr, 1);
+ return;
+}
+
+void
hestArgAddChar(hestArg *harg, char cc) {
assert(harg);
airArrayLenIncr(harg->strArr, 1);
@@ -105,9 +113,6 @@
for (uint si = 0; si < len; si++) {
hestArgAddChar(harg, str[si]);
}
- /* The assumption is that if you have a string to put here; then you know that the
- string is finished. User can modify this if that's not the case. */
- harg->finished = AIR_TRUE;
return;
}
@@ -146,7 +151,7 @@
for (uint idx = 0; idx < havec->hargArr->len; idx++) {
const hestArg *harg;
harg = havec->harg + idx;
- printf(" %u:<%s>%c", idx, harg->str, harg->finished ? '.' : '~');
+ printf(" %u:<%s>", idx, harg->str);
}
printf("\n");
}
@@ -214,98 +219,3 @@
free(hist);
return NULL;
}
-
-#define ME ((hparm && hparm->verbosity) ? me : "")
-
-int
-hestInputStackPushCommandLine(hestInputStack *hist, int argc, const char **argv,
- char *err, const hestParm *hparm) {
- static const char me[] = "hestInputStackPushCommandLine: ";
- if (!(hist && argv && hparm)) { // (as if all this can go wrong but err is non-NULL)
- sprintf(err, "%s: got NULL pointer (hist %p, argv %p, hparm %p)", __func__,
- AIR_VOIDP(hist), AIR_VOIDP(argv), AIR_VOIDP(hparm));
- return 1;
- }
- if (hparm->verbosity) {
- printf("%s: changing stack height: %u --> %u with argc=%d,argv=%p; "
- "setting argIdx to 0\n",
- __func__, hist->hinArr->len, hist->hinArr->len + 1, argc, AIR_VOIDP(argv));
- }
- uint idx = airArrayLenIncr(hist->hinArr, 1);
- if (hparm->verbosity > 1) {
- printf("%snew hinTop = %p\n", ME, AIR_VOIDP(hist->hin + idx));
- }
- hist->hin[idx].source = hestSourceCommandLine;
- hist->hin[idx].argc = argc;
- hist->hin[idx].argv = argv;
- hist->hin[idx].argIdx = 0;
- return 0;
-}
-
-int
-hestInputStackPushResponseFile(hestInputStack *hist, const char *rfname, char *err,
- const hestParm *hparm) {
- static const char me[] = "hestInputStackPushResponseFile: ";
- if (!(hist && rfname && hparm)) {
- sprintf(err, "%s: got NULL pointer (hist %p, rfname %p, hparm %p)", __func__,
- AIR_VOIDP(hist), AIR_VOIDP(rfname), AIR_VOIDP(hparm));
- return 1;
- }
- if (!strlen(rfname)) {
- sprintf(err,
- "%ssaw arg start with response file flag \"%c\" "
- "but no filename followed",
- ME, RESPONSE_FILE_FLAG);
- return 1;
- }
- // "- 1" safe because hestParse always starts with argc/argv, not a response file
- uint topHinIdx = hist->len - 1;
- // have we seen rfname before?
- for (uint hidx = 0; hidx < topHinIdx; hidx++) {
- hestInput *oldHin = hist->hin + hidx;
- if (hestSourceResponseFile == oldHin->source //
- && !strcmp(oldHin->rfname, rfname)) {
- // HEY test this error
- sprintf(err, "%salready currently reading \"%s\" as response file", ME, rfname);
- return 1;
- }
- }
- // are we trying to read stdin twice?
- if (!strcmp("-", rfname) && hist->stdinRead) {
- // HEY test this error
- sprintf(err, "%sresponse filename \"%s\" but previously read stdin", ME, rfname);
- return 1;
- }
- // try to open response file
- FILE *rfile = airFopen(rfname, stdin, "r");
- if (!(rfile)) {
- // HEY test this error
- sprintf(err, "%scouldn't fopen(\"%s\",\"r\"): %s", ME, rfname, strerror(errno));
- return 1;
- }
- // okay, we actually opened the response file; put it on the stack
- uint idx = airArrayLenIncr(hist->hinArr, 1);
- if (hparm->verbosity > 1) {
- printf("%snew hinTop = %p\n", ME, AIR_VOIDP(hist->hin + idx));
- }
- hist->hin[idx].source = hestSourceResponseFile;
- hist->hin[idx].rfname = rfname;
- hist->hin[idx].rfile = rfile;
- return 0;
-}
-
-int
-hestInputStackPop(hestInputStack *hist, char *err, const hestParm *hparm) {
- assert(hist);
- uint len = hist->hinArr->len;
- if (!len) {
- sprintf(err, "%s: cannot pop from stack height 0", __func__);
- return 1;
- }
- if (hparm->verbosity) {
- printf("%s: changing stack height: %u --> %u; popping %s source\n", __func__, len,
- len - 1, airEnumStr(hestSource, hist->hin[len - 1].source));
- }
- airArrayLenIncr(hist->hinArr, -1);
- return 0;
-}
\ No newline at end of file
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/hest/hest.h 2025-09-19 08:50:37 UTC (rev 7458)
@@ -26,6 +26,7 @@
#include <string.h>
#include <teem/air.h>
+// and see privateHest.h for why we internally also use biff
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(TEEM_STATIC)
# if defined(TEEM_BUILD) || defined(hest_EXPORTS) || defined(teem_EXPORTS)
@@ -235,7 +236,6 @@
char *str;
unsigned int len; // NOT strlen; this includes '\0'-termination
airArray *strArr;
- int finished; // we have finished building up this string
} hestArg;
// hestArgVec: for building up a "vector" of arguments
@@ -288,6 +288,7 @@
// argvHest.c
HEST_EXPORT hestArg *hestArgNew(void);
HEST_EXPORT hestArg *hestArgNix(hestArg *harg);
+HEST_EXPORT void hestArgReset(hestArg *harg);
HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
HEST_EXPORT void hestArgAddString(hestArg *harg, const char *str);
HEST_EXPORT hestArgVec *hestArgVecNew(void);
@@ -298,13 +299,6 @@
HEST_EXPORT hestInput *hestInputNix(hestInput *hin);
HEST_EXPORT hestInputStack *hestInputStackNew(void);
HEST_EXPORT hestInputStack *hestInputStackNix(hestInputStack *hist);
-HEST_EXPORT int hestInputStackPushCommandLine(hestInputStack *hist, int argc,
- const char **argv, char *err,
- const hestParm *hparm);
-HEST_EXPORT int hestInputStackPushResponseFile(hestInputStack *hist, const char *rfname,
- char *err, const hestParm *hparm);
-HEST_EXPORT int hestInputStackPop(hestInputStack *hist, char *err,
- const hestParm *hparm);
// parsest.c
HEST_EXPORT int hestParse2(hestOpt *opt, int argc, const char **argv, char **errP,
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-19 08:50:37 UTC (rev 7458)
@@ -27,7 +27,9 @@
const int hestPresent = 42;
-// enjoying how C99 greatly simplifies creating an airEnum at compile-time
+const char *const _hestBiffKey = "hest";
+
+// loving how C99 simplifies creating an airEnum at compile-time
static const airEnum _hestSource
= {.name = "source",
.M = 3,
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/hest/parsest.c 2025-09-19 08:50:37 UTC (rev 7458)
@@ -20,111 +20,327 @@
#include "hest.h"
#include "privateHest.h"
-/* parse, parser, parsest: may this be the final implmentation of hestParse */
+/* parse, Parser, PARSEST: may this be the final implementation of hestParse */
#include <assert.h>
+#include <sys/errno.h>
-/* A little trickery for error reporting. For many of the functions here, if they hit an
-error and hparm->verbosity is set, then we should reveal the current function name (set
-by convention in `me`). But without verbosity, we hide that function name, so it appears
-that the error is coming from the caller (probably identified as argv[0]). However, that
-means that functions using this `ME` macro should (in defiance of convention) set to `me`
-to `functionname: ` (NOTE the `: `) so that all of that goes away without verbosity. And,
-that means that error message generation here should also defy convention and instead of
-being "%s: what happened" it should just be "%swhat happened" */
-// how to const-correctly use either given (const) _hparm or own (non-const) hparm
-#define HPARM (_hparm ? _hparm : hparm)
-#define HMME (HPARM->verbosity ? me : "")
-#define ME ((hparm && hparm->verbosity) ? me : "")
+int
+histPop(hestInputStack *hist, const hestParm *hparm) {
+ if (!(hist && hparm)) {
+ biffAddf(HEST, "%s: got NULL pointer (hist %p hparm %p)", __func__, AIR_VOIDP(hist),
+ AIR_VOIDP(hparm));
+ return 1;
+ }
+ if (!(hist->len)) {
+ biffAddf(HEST, "%s: cannot pop from input stack height 0", __func__);
+ return 1;
+ }
+ hestInput *topHin = hist->hin + hist->len - 1;
+ if (topHin->dashBraceComment) {
+ biffAddf(HEST,
+ "%s: %u start comment marker%s \"-{\" not balanced by equal later \"}-\"",
+ __func__, topHin->dashBraceComment,
+ topHin->dashBraceComment > 1 ? "s" : "");
+ return 1;
+ }
+ if (hparm->verbosity) {
+ printf("%s: changing stack height: %u --> %u; popping %s source\n", __func__,
+ hist->len, hist->len - 1,
+ airEnumStr(hestSource, hist->hin[hist->len - 1].source));
+ }
+ airArrayLenIncr(hist->hinArr, -1);
+ return 0;
+}
+// possible *statP values set by histProcNextArg
+enum {
+ procStatUnknown, // 0: don't know
+ procStatEmpty, // 1: we have no arg to give
+ procStatTryAgain, // 2: inconclusive because had to manage things
+ procStatBehold // 3: have produced an arg, here it is
+};
+
+/*
+histProcNextArgSub draws on whatever the top input source is, to produce another arg.
+It sets in *statP the status of the arg production process. Allowing procStatTryAgain
+is a way to acknowledge the fact that we are called iteratively by a loop we don't
+control, and managing the machinery of arg production is itself a multi-step process that
+doesn't always produce an arg. We should need to do look-ahead to make progress, even if
+we don't produce an arg.
+*/
static int
-histProc(hestArgVec *havec, int *helpWantedP, hestInputStack *hist, char *err,
- const hestParm *hparm) {
- static const char me[] = "histProc: ";
- int popAtEnd = AIR_FALSE;
- *helpWantedP = AIR_FALSE; // may over-write later
- hestInput *theHin = hist->hin + hist->len - 1;
- switch (theHin->source) {
- case hestSourceDefault: // ---------------------------------
- sprintf(err, "%ssorry hestSourceDefault not implemented", ME);
+histProcNextArgSub(int *statP, hestArg *tharg, hestInputStack *hist,
+ const hestParm *hparm) {
+ if (!(statP && tharg && hist && hparm)) {
+ biffAddf(HEST, "%s: got NULL pointer (statP %p tharg %p hist %p hparm %p)", __func__,
+ AIR_VOIDP(statP), AIR_VOIDP(tharg), AIR_VOIDP(hist), AIR_VOIDP(hparm));
return 1;
- break;
- case hestSourceCommandLine: // ---------------------------------
- // argv[] 0 1 2 3 (argc=4)
- // cmd arg1 arg2 arg3
+ }
+ // printf("!%s: hello hist->len %u\n", __func__, hist->len);
+ hestArgReset(tharg);
+ *statP = procStatUnknown;
+ if (!hist->len) {
+ // the stack is empty; say so
+ *statP = procStatEmpty;
+ return 0;
+ }
+ uint hinIdx = hist->len - 1;
+ hestInput *hin = hist->hin + hinIdx;
+ // printf("!%s: source %s\n", __func__, airEnumStr(hestSource, hin->source));
+ if (hestSourceCommandLine == hin->source) {
+ // argv[] 0 1 2 3 (argc=4)
+ // cmd arg1 arg2 arg3
+ uint argi = hin->argIdx;
+ // printf("!%s: argi %u vs argc %u\n", __func__, argi, hin->argc);
+ if (argi < hin->argc) {
+ // there are args left to parse
+ hestArgAddString(tharg, hin->argv[argi]);
+ // printf("!%s: now tharg->str=|%s|\n", __func__, tharg->str);
+ *statP = procStatBehold;
+ hin->argIdx++;
+ } else {
+ // we have gotten to the end of the given argv array, pop it */
+ if (histPop(hist, hparm)) {
+ biffAddf(HEST, "%s: trouble popping", __func__);
+ return 1;
+ }
+ *statP = procStatTryAgain;
+ }
+ } else {
+ // source is default string or response file
+ biffAddf(HEST, "%s: source %s not yet implemented", __func__,
+ airEnumStr(hestSource, hin->source));
+ return 1;
+ }
+ return 0;
+}
+
+static int
+histProcNextArg(int *statP, hestArg *tharg, hestInputStack *hist,
+ const hestParm *hparm) {
+ // printf("!%s: hello hist->len %u\n", __func__, hist->len);
+ do {
+ if (histProcNextArgSub(statP, tharg, hist, hparm)) {
+ biffAddf(HEST, "%s: trouble getting next arg", __func__);
+ return 1;
+ }
if (hparm->verbosity > 1) {
- printf("%shist->len=%u -> theHin=%p\n", me, hist->len, AIR_VOIDP(theHin));
+ printf("%s: histProcNextArgSub set *statP = %d\n", __func__, *statP);
}
- if (theHin->argIdx < theHin->argc) {
- // there are args left to parse
- uint thisArgIdx = theHin->argIdx;
- const char *theArg = theHin->argv[thisArgIdx];
- if (hparm->verbosity > 1) {
- printf("%slooking at argv[%u] |%s|\n", me, theHin->argIdx, theArg);
+ } while (*statP == procStatTryAgain);
+ return 0;
+}
+
+static int
+histPushCommandLine(hestInputStack *hist, int argc, const char **argv,
+ const hestParm *hparm) {
+ if (!(hist && argv && hparm)) {
+ biffAddf(HEST, "%s: got NULL pointer (hist %p, argv %p, hparm %p)", __func__,
+ AIR_VOIDP(hist), AIR_VOIDP(argv), AIR_VOIDP(hparm));
+ return 1;
+ }
+ if (HIST_DEPTH_MAX == hist->len) {
+ biffAddf(HEST, "%s: input stack depth already at max %u", __func__, HIST_DEPTH_MAX);
+ return 1;
+ }
+ if (hparm->verbosity) {
+ printf("%s: changing stack height: %u --> %u with argc=%d,argv=%p; "
+ "setting argIdx to 0\n",
+ __func__, hist->hinArr->len, hist->hinArr->len + 1, argc, AIR_VOIDP(argv));
+ }
+ uint idx = airArrayLenIncr(hist->hinArr, 1);
+ if (hparm->verbosity > 1) {
+ printf("%s: new hinTop = %p\n", __func__, AIR_VOIDP(hist->hin + idx));
+ }
+ hist->hin[idx].source = hestSourceCommandLine;
+ hist->hin[idx].argc = argc;
+ hist->hin[idx].argv = argv;
+ hist->hin[idx].argIdx = 0;
+ return 0;
+}
+
+static int
+histPushResponseFile(hestInputStack *hist, const char *rfname, const hestParm *hparm) {
+ if (!(hist && rfname && hparm)) {
+ biffAddf(HEST, "%s: got NULL pointer (hist %p, rfname %p, hparm %p)", __func__,
+ AIR_VOIDP(hist), AIR_VOIDP(rfname), AIR_VOIDP(hparm));
+ return 1;
+ }
+ if (HIST_DEPTH_MAX == hist->len) {
+ // HEY test this error
+ biffAddf(HEST, "%s: input stack depth already at max %u", __func__, HIST_DEPTH_MAX);
+ return 1;
+ }
+ if (!strlen(rfname)) {
+ // HEY test this error
+ biffAddf(HEST,
+ "%s: saw arg start with response file flag \"%c\" "
+ "but no filename followed",
+ __func__, RESPONSE_FILE_FLAG);
+ return 1;
+ }
+ // have we seen rfname before?
+ if (hist->len) {
+ uint topHinIdx = hist->len - 1;
+ for (uint hidx = 0; hidx < topHinIdx; hidx++) {
+ hestInput *oldHin = hist->hin + hidx;
+ if (hestSourceResponseFile == oldHin->source //
+ && !strcmp(oldHin->rfname, rfname)) {
+ // HEY test this error
+ biffAddf(HEST,
+ "%s: already reading \"%s\" as response file; "
+ "cannot recursively read it again",
+ __func__, rfname);
+ return 1;
}
- theHin->argIdx++;
- // process theArg we just acquired
- if (hparm->respectDashBraceComments && !strcmp("-{", theArg)) {
- // start of -{ }- commenting (or increase in nesting level)
- theHin->dashBraceComment += 1;
+ }
+ }
+ // are we trying to read stdin twice?
+ if (!strcmp("-", rfname) && hist->stdinRead) {
+ // HEY test this error
+ biffAddf(HEST, "%s: response filename \"%s\" but previously read stdin", __func__,
+ rfname);
+ return 1;
+ }
+ // try to open response file
+ FILE *rfile = airFopen(rfname, stdin, "r");
+ if (!(rfile)) {
+ biffAddf(HEST, "%s: couldn't fopen(\"%s\",\"r\"): %s", __func__, rfname,
+ strerror(errno));
+ return 1;
+ }
+ // okay, we actually opened the response file; put it on the stack
+ uint idx = airArrayLenIncr(hist->hinArr, 1);
+ if (hparm->verbosity > 1) {
+ printf("%s: (hist depth %u) new hinTop = %p\n", __func__, hist->len,
+ AIR_VOIDP(hist->hin + idx));
+ }
+ hist->hin[idx].source = hestSourceResponseFile;
+ hist->hin[idx].rfname = rfname;
+ hist->hin[idx].rfile = rfile;
+ return 0;
+}
+
+/*
+histProcess consumes args (tokens) from the stack `hist`, mostly just copying
+them into `havec`, but this does interpret the tokens just enough to implement:
+ (what) (allowed sources)
+ - commenting with -{ , }- all (even a default string, may regret this)
+ - ask for --help command-line
+ - response files command-line, response file
+since these are the things that histProcNextArg does not understand (it just produces
+finished tokens). On the other hand, we do NOT know anything about individual hestOpts
+and their flags, which is why they weren't passed to us (--help is special).
+Upon seeing a request for a response file, we push it to the input stack. This function
+never pops from the input stack (that is the responsibility of histProcNextArg).
+
+This function takes no ownership of anything so avoids any mopping responsibility, not
+even for the tmp arg holder `tharg`; that is passed in here and cleaned up caller.
+*/
+static int
+histProcess(hestArgVec *havec, int *helpWantedP, hestArg *tharg, hestInputStack *hist,
+ const hestParm *hparm) {
+ *helpWantedP = AIR_FALSE;
+ int stat = procStatUnknown;
+ uint iters = 0;
+ hestInput *topHin;
+ // printf("!%s: hello hist->len %u\n", __func__, hist->len);
+ /* We `return` directly from this loop ONLY when we MUST stop processing the stack,
+ because of an error, or because of user asking for help.
+ Otherwise, we loop again. */
+ while (1) {
+ iters += 1;
+ /* if this loop just pushed a response file, the top hestInput is different
+ from what it was when this function started, so re-learn it. */
+ topHin = hist->hin + hist->len - 1;
+ const char *srcstr = airEnumStr(hestSource, topHin->source);
+ // read next arg into tharg
+ if (histProcNextArg(&stat, tharg, hist, hparm)) {
+ biffAddf(HEST, "%s: (arg %u src %s) unable to get next arg", __func__, iters,
+ srcstr);
+ return 1;
+ }
+ if (procStatEmpty == stat) {
+ // the stack has no more tokens to give, stop looped requests for mre
+ if (hparm->verbosity) {
+ printf("%s: (arg %u src %s) empty!\n", __func__, iters, srcstr);
}
- if (theHin->dashBraceComment) {
- if (hparm->verbosity > 1) {
- printf("%sskipping commented-out |%s|\n", me, theArg);
+ break;
+ }
+ // we have a token, is it turning off commenting?
+ if (hparm->respectDashBraceComments && !strcmp("}-", tharg->str)) {
+ if (topHin->dashBraceComment) {
+ topHin->dashBraceComment -= 1;
+ if (hparm->verbosity) {
+ printf("%s: topHin->dashBraceComment now %u\n", __func__,
+ topHin->dashBraceComment);
}
+ continue; // since }- does not belong in havec
} else {
- // not commenting out thisArg
- if (!hparm->responseFileEnable || theArg[0] != RESPONSE_FILE_FLAG) {
- // not a response file, just an arg
- hestArgVecAppendString(havec, theArg);
- } else {
- /* theArg is asking to be a response file; try pushing it. With or without an
- error, we return early because there's nothing more for us to do */
- return hestInputStackPushResponseFile(hist, theArg + 1, err, hparm);
- }
+ biffAddf(HEST,
+ "%s: (arg %u src %s) end comment marker \"}-\" not "
+ "balanced by prior \"-{\"",
+ __func__, iters, srcstr);
+ return 1;
}
- if (hparm->respectDashBraceComments && !strcmp("}-", theArg)) {
- if (theHin->dashBraceComment) {
- theHin->dashBraceComment -= 1;
- } else {
- sprintf(err, "%send comment arg \"}-\" not balanced by prior \"-{\"", ME);
- return 1;
- }
+ }
+ // not ending comment, are we starting (or deepening) one?
+ if (hparm->respectDashBraceComments && !strcmp("-{", tharg->str)) {
+ topHin->dashBraceComment += 1;
+ if (hparm->verbosity) {
+ printf("%s: topHin->dashBraceComment now %u\n", __func__,
+ topHin->dashBraceComment);
}
- } // NOT else
- if (theHin->argIdx == theHin->argc) {
- // we have gotten to the end of the given argv array */
- if (theHin->dashBraceComment) {
- sprintf(err, "%sstart comment arg \"-{\" not balanced by later \"}-\"", ME);
+ continue;
+ }
+ // if in comment, move along
+ if (topHin->dashBraceComment) {
+ if (hparm->verbosity > 1) {
+ printf("%s: (arg %u src %s) skipping commented-out |%s|\n", __func__, iters,
+ srcstr, tharg->str);
+ }
+ continue;
+ }
+ // else this arg is not in a comment and is not related to commenting
+ if (hparm->respectDashDashHelp && !strcmp("--help", tharg->str)) {
+ if (hestSourceCommandLine == topHin->source) {
+ *helpWantedP = AIR_TRUE;
+ /* user asking for help halts further parsing work: user is not looking
+ for parsing results nor error messages about that process */
+ return 0;
+ } else {
+ biffAddf(HEST, "%s: (arg %u src %s) \"--help\" not expected here", __func__,
+ iters, srcstr);
return 1;
- } else {
- popAtEnd = AIR_TRUE;
- // but don't pop now because we still need to check for --help
}
}
- break;
- case hestSourceResponseFile: // ---------------------------------
- sprintf(err, "%ssorry hestSourceResponseFile not implemented", ME);
- return 1;
- break;
- }
- /* when processing command-line or response file, check for --help
- (it makes no sense for --help to appear in a default string) */
- if (hestSourceResponseFile == theHin->source
- || hestSourceCommandLine == theHin->source) {
- const hestArg *hlast;
- if (hparm->respectDashDashHelp // watching for "--help"
- && havec->len // have at least one arg
- && (hlast = havec->harg + havec->len - 1)->finished // latest arg is finished
- && !strcmp("--help", hlast->str)) { // and it equals "--help"
- *helpWantedP = AIR_TRUE;
+ if (hparm->verbosity > 1) {
+ printf("%s: (arg %u src %s) looking at latest tharg |%s|\n", __func__, iters,
+ srcstr, tharg->str);
}
- }
- if (popAtEnd) {
- if (hestInputStackPop(hist, err, hparm)) {
- return 1;
+ if (hparm->responseFileEnable && tharg->str[0] == RESPONSE_FILE_FLAG) {
+ // tharg->str is asking to open a response file; try pushing it
+ if (histPushResponseFile(hist, tharg->str + 1, hparm)) {
+ biffAddf(HEST, "%s: (arg %u src %s) unable to process response file %s",
+ __func__, iters, srcstr, tharg->str);
+ return 1;
+ }
+ // have just added response file to stack, next iter will read from it
+ continue;
}
+ // this arg is not specially handled by us; add it to the arg vec
+ hestArgVecAppendString(havec, tharg->str);
+ if (hparm->verbosity > 1) {
+ printf("%s: (arg %u src %s) added |%s| to havec, now len %u\n", __func__, iters,
+ srcstr, tharg->str, havec->len);
+ }
}
+ if (hist->len && stat == procStatEmpty) {
+ biffAddf(HEST, "%s: non-empty stack (depth %u) can't generate args???", __func__,
+ hist->len);
+ return 1;
+ }
return 0;
}
@@ -131,9 +347,10 @@
int
hestParse2(hestOpt *opt, int argc, const char **argv, char **_errP,
const hestParm *_hparm) {
- /* see note on HMME (at top) for why me[] ends with ": " */
- static const char me[] = "hestParse2: ";
+ /* how to const-correctly use hparm or _hparm in an expression */
+#define HPARM (_hparm ? _hparm : hparm)
+
// -------- initialize the mop
airArray *mop = airMopNew();
@@ -144,11 +361,11 @@
airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
}
if (HPARM->verbosity > 1) {
- printf("%shparm->verbosity %d\n", HMME, HPARM->verbosity);
+ printf("%s: hparm->verbosity %d\n", __func__, HPARM->verbosity);
}
// -------- allocate the err string. We do it a dumb way for now.
- // TODO: make this smarter
+ // TODO: make this allocation smarter
uint eslen = 2 * AIR_STRLEN_HUGE;
char *err = AIR_CALLOC(eslen + 1, char);
assert(err);
@@ -163,7 +380,7 @@
airMopAdd(mop, err, airFree, airMopAlways);
}
if (HPARM->verbosity > 1) {
- printf("%serr %p\n", HMME, AIR_VOIDP(err));
+ printf("%s: err %p\n", __func__, AIR_VOIDP(err));
}
// -------- check on validity of the hestOpt array
@@ -173,7 +390,7 @@
return 1;
}
if (HPARM->verbosity > 1) {
- printf("%s_hestOptCheck passed\n", HMME);
+ printf("%s: _hestOptCheck passed\n", __func__);
}
// -------- allocate the state we use during parsing
@@ -181,29 +398,37 @@
airMopAdd(mop, hist, (airMopper)hestInputStackNix, airMopAlways);
hestArgVec *havec = hestArgVecNew();
airMopAdd(mop, havec, (airMopper)hestArgVecNix, airMopAlways);
+ hestArg *tharg = hestArgNew(); // tmp hestArg
+ airMopAdd(mop, tharg, (airMopper)hestArgNix, airMopAlways);
if (HPARM->verbosity > 1) {
- printf("%shavec and hist allocated\n", HMME);
+ printf("%s: parsing state allocated\n", __func__);
}
// -------- initialize input stack w/ given argc,argv, then process it
- if (hestInputStackPushCommandLine(hist, argc, argv, err, HPARM)) {
+ if (histPushCommandLine(hist, argc, argv, HPARM)
+ || histProcess(havec, &(opt->helpWanted), tharg, hist, HPARM)) {
+ char *bferr = biffGetDone(HEST);
+ airMopAdd(mop, bferr, airFree, airMopAlways);
+ strcpy(err, bferr);
airMopError(mop);
return 1;
}
- do {
- /* Every iteration of this will work on one argv[] element, or, one character of a
- response file. As long as we avoid giving ourselves infinite work, eventually,
- bird by bird, we will finish. */
- if (histProc(havec, &(opt->helpWanted), hist, err, HPARM)) {
- // error message in err
- airMopError(mop);
- return 1;
- }
- // keep going while there's something on stack and no calls for help have been seen
- } while (hist->len && !(opt->helpWanted));
+ // (debugging) have finished input stack, what argvec did it leave us with?
hestArgVecPrint(__func__, havec);
+ if (opt->helpWanted) {
+ // once the call for help is made, we respect it: clean up and return
+ airMopOkay(mop);
+ return 0;
+ }
+
+ // ( extract, process: make little argvec for each opt )
+ // extract given flagged options
+ // extract given unflagged options
+ // process default strings of not-given options
+ // set value(s) from per-opt argvec
+
airMopOkay(mop);
return 0;
}
Modified: teem/trunk/src/hest/privateHest.h
===================================================================
--- teem/trunk/src/hest/privateHest.h 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/hest/privateHest.h 2025-09-19 08:50:37 UTC (rev 7458)
@@ -21,6 +21,14 @@
extern "C" {
#endif
+/* Having hest depend on biff is new for TeemV2: with the new and more modular
+re-write of hestParse, not having a useful way to accumulate error messages across a
+deeper call stack was getting just too annoying.
+It is still the case, however, the hest users do not need to call into biff */
+#include <teem/biff.h>
+
+typedef unsigned int uint;
+
// pre-TeemV2, these used to be change-able defaults in defaultsHest.c:
// char hestDefaultRespFileFlag = '@';
// char hestDefaultRespFileComment = '#';
@@ -47,9 +55,12 @@
#define VAR_PARM_STOP_FLAG '-'
#define MULTI_FLAG_SEP ','
-typedef unsigned int uint;
+#define HEST _hestBiffKey
+#define HIST_DEPTH_MAX 10 // max sensibly depth of hestInputStack
+
/* methodsHest.c */
+extern const char *const _hestBiffKey;
extern int _hestKind(const hestOpt *opt);
extern int _hestMax(int max);
extern int _hestOptCheck(const hestOpt *opt, char *err, const hestParm *parm);
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-18 20:46:47 UTC (rev 7457)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-19 08:50:37 UTC (rev 7458)
@@ -34,12 +34,13 @@
hestParm *hparm = hestParmNew();
hparm->respectDashDashHelp = AIR_TRUE;
hparm->responseFileEnable = AIR_TRUE;
+ hparm->verbosity = 10;
+
int res[2];
hestOptAdd_2_Int(&opt, "res", "sx sy", res, NULL, "image resolution");
int flag;
hestOptAdd_Flag(&opt, "b,bingo", &flag, "a flag");
char *err;
- hparm->verbosity = 0;
if (hestParse2(opt, argc - 1, argv + 1, &err, hparm)) {
fprintf(stderr, "%s: problem:\n%s\n", argv[0], err);
ret = 1;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 20:46:52
|
Revision: 7457
http://sourceforge.net/p/teem/code/7457
Author: kindlmann
Date: 2025-09-18 20:46:47 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
(should have been part of previous commit about hparm->respFileEnable --> hparm->responseFileEnable. Other changes just from clang-format being belatedly applied.
Modified Paths:
--------------
teem/trunk/src/dye/test/mchist.c
teem/trunk/src/hest/test/ex1.c
teem/trunk/src/hest/test/ex2.c
teem/trunk/src/hest/test/ex3.c
teem/trunk/src/hest/test/ex6.c
teem/trunk/src/hest/test/tparse.c
teem/trunk/src/meet/test/strace.c
teem/trunk/src/meet/test/vpnts.c
Modified: teem/trunk/src/dye/test/mchist.c
===================================================================
--- teem/trunk/src/dye/test/mchist.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/dye/test/mchist.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -90,7 +90,7 @@
hopt = NULL;
hparm = hestParmNew();
airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hestOptAdd(&hopt, "i", "images", airTypeString, 1, -1, &ninStr, NULL,
"input image sequence", &ninLen, NULL, NULL);
hestOptAdd(&hopt, "sh", "histo size", airTypeUInt, 1, 1, &sH, "500", "histogram size");
Modified: teem/trunk/src/hest/test/ex1.c
===================================================================
--- teem/trunk/src/hest/test/ex1.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/hest/test/ex1.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -65,7 +65,7 @@
"this software was written by a sleep-deprived grad student.";
parm = hestParmNew();
- parm->respFileEnable = AIR_TRUE;
+ parm->responseFileEnable = AIR_TRUE;
if (1 == argc) {
/* didn't get anything at all on command line */
Modified: teem/trunk/src/hest/test/ex2.c
===================================================================
--- teem/trunk/src/hest/test/ex2.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/hest/test/ex2.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -33,7 +33,7 @@
"especially since this is the output of a unicyclist.";
parm = hestParmNew();
- parm->respFileEnable = AIR_TRUE;
+ parm->responseFileEnable = AIR_TRUE;
opt = NULL;
hestOptAdd(&opt, "res", "sx sy", airTypeInt, 2, 2, res, NULL, "image resolution");
Modified: teem/trunk/src/hest/test/ex3.c
===================================================================
--- teem/trunk/src/hest/test/ex3.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/hest/test/ex3.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -33,7 +33,7 @@
"especially since this is the output of a unicyclist.";
parm = hestParmNew();
- parm->respFileEnable = AIR_TRUE;
+ parm->responseFileEnable = AIR_TRUE;
parm->respectDashDashHelp = AIR_TRUE;
parm->verbosity = 3;
Modified: teem/trunk/src/hest/test/ex6.c
===================================================================
--- teem/trunk/src/hest/test/ex6.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/hest/test/ex6.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -80,7 +80,7 @@
"especially since this is the output of a gray-haired unicyclist.";
parm = hestParmNew();
- parm->respFileEnable = AIR_TRUE;
+ parm->responseFileEnable = AIR_TRUE;
parm->respectDashDashHelp = AIR_TRUE;
parm->noArgsIsNoProblem = AIR_TRUE;
parm->dieLessVerbose = AIR_TRUE;
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -33,7 +33,7 @@
hestOpt *opt = NULL;
hestParm *hparm = hestParmNew();
hparm->respectDashDashHelp = AIR_TRUE;
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
int res[2];
hestOptAdd_2_Int(&opt, "res", "sx sy", res, NULL, "image resolution");
int flag;
Modified: teem/trunk/src/meet/test/strace.c
===================================================================
--- teem/trunk/src/meet/test/strace.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/meet/test/strace.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -247,7 +247,7 @@
nfilt = nrrdNew();
airMopAdd(mop, nfilt, (airMopper)nrrdNuke, airMopAlways);
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
me = argv[0];
/* these don't need to be visible on the command-line */
Modified: teem/trunk/src/meet/test/vpnts.c
===================================================================
--- teem/trunk/src/meet/test/vpnts.c 2025-09-18 20:39:52 UTC (rev 7456)
+++ teem/trunk/src/meet/test/vpnts.c 2025-09-18 20:46:47 UTC (rev 7457)
@@ -20,14 +20,14 @@
#include <teem/pull.h>
#include "../meet.h"
-static const char *info =
- ("For the simple task of generating N locations inside a volume. As "
- "controlled by \"-m\", can be per voxel, uniform quasi-random, or "
- "or uniform random.");
+static const char *info
+ = ("For the simple task of generating N locations inside a volume. As "
+ "controlled by \"-m\", can be per voxel, uniform quasi-random, or "
+ "or uniform random.");
int
main(int argc, const char **argv) {
- hestOpt *hopt=NULL;
+ hestOpt *hopt = NULL;
hestParm *hparm;
airArray *mop;
const char *me;
@@ -38,8 +38,8 @@
pullEnergySpec *enspR;
meetPullInfo *minf[3];
NrrdKernelSpec *k00, *k11, *k22;
- pullContext *pctx=NULL;
- int ret=0, verbose, method;
+ pullContext *pctx = NULL;
+ int ret = 0, verbose, method;
unsigned int num, ss;
double jitter;
@@ -50,7 +50,7 @@
npos = nrrdNew();
airMopAdd(mop, npos, (airMopper)nrrdNuke, airMopAlways);
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
me = argv[0];
/* these don't need to be visible on the command-line */
@@ -58,8 +58,8 @@
airMopAdd(mop, enspR, (airMopper)pullEnergySpecNix, airMopAlways);
pullEnergySpecParse(enspR, "cotan");
- hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, NULL,
- "input volume", NULL, NULL, nrrdHestNrrd);
+ hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, NULL, "input volume", NULL,
+ NULL, nrrdHestNrrd);
hestOptAdd(&hopt, "k", "kind", airTypeOther, 1, 1, &kind, "scalar",
"\"kind\" of volume (\"scalar\", \"vector\", "
"\"tensor\", or \"dwi\")",
@@ -85,8 +85,8 @@
"amount of jittering to do with ppv");
hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "out.nrrd",
"filename for saving positions");
- hestParseOrDie(hopt, argc-1, argv+1, hparm,
- me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
+ hestParseOrDie(hopt, argc - 1, argv + 1, hparm, me, info, AIR_TRUE, AIR_TRUE,
+ AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
@@ -102,14 +102,15 @@
if (pullEnergySpecParse(enspR, "cotan")) {
airMopAdd(mop, err = biffGetDone(PULL), airFree, airMopAlways);
fprintf(stderr, "%s: trouble setting up faux energies:\n%s", me, err);
- airMopError(mop); return 1;
+ airMopError(mop);
+ return 1;
}
- if (nrrdKernelSpecParse(k00, "box")
- || nrrdKernelSpecParse(k11, "zero")
+ if (nrrdKernelSpecParse(k00, "box") || nrrdKernelSpecParse(k11, "zero")
|| nrrdKernelSpecParse(k22, "zero")) {
airMopAdd(mop, err = biffGetDone(PULL), airFree, airMopAlways);
fprintf(stderr, "%s: trouble setting up faux kernels:\n%s", me, err);
- airMopError(mop); return 1;
+ airMopError(mop);
+ return 1;
}
#define VNAME "bingo"
@@ -131,24 +132,25 @@
if (!E) E |= pullRngSeedSet(pctx, ss);
if (!E) E |= pullInitPointPerVoxelSet(pctx, num, 1, 0, 0, jitter);
} else if (pullInitMethodGivenPos == method) {
- fprintf(stderr, "%s: this utility is for making point positions; "
- "init method %s not available", me,
- airEnumStr(pullInitMethod, method));
- airMopError(mop); return 1;
+ fprintf(stderr,
+ "%s: this utility is for making point positions; "
+ "init method %s not available",
+ me, airEnumStr(pullInitMethod, method));
+ airMopError(mop);
+ return 1;
} else {
fprintf(stderr, "%s: unsupported %s %s\n", me, pullInitMethod->name,
airEnumStr(pullInitMethod, method));
- airMopError(mop); return 1;
+ airMopError(mop);
+ return 1;
}
- if (E
- || pullFlagSet(pctx, pullFlagNixAtVolumeEdgeSpaceInitRorH, AIR_TRUE)
- || pullInterEnergySet(pctx, pullInterTypeJustR,
- enspR, NULL, NULL)
- || pullVolumeSingleAdd(pctx, kind, VNAME, nin,
- k00, k11, k22)) {
+ if (E || pullFlagSet(pctx, pullFlagNixAtVolumeEdgeSpaceInitRorH, AIR_TRUE)
+ || pullInterEnergySet(pctx, pullInterTypeJustR, enspR, NULL, NULL)
+ || pullVolumeSingleAdd(pctx, kind, VNAME, nin, k00, k11, k22)) {
airMopAdd(mop, err = biffGetDone(PULL), airFree, airMopAlways);
fprintf(stderr, "%s: trouble starting system:\n%s", me, err);
- airMopError(mop); return 1;
+ airMopError(mop);
+ return 1;
}
/* figure out how big a voxel is, so that the bins set up don't
get overflowed. The fact that there is binning happening
@@ -155,7 +157,7 @@
at all is a sign that we shouldn't have to rely on so much
pull infrastructure just to figure out this sampling ... */
const double *spc = pctx->vol[0]->gctx->shape->spacing;
- double vlen = (spc[0] + spc[1] + spc[2])/3;
+ double vlen = (spc[0] + spc[1] + spc[2]) / 3;
/* "<info>[-c]:<volname>:<item>[:<zero>:<scale>]" */
if (meetPullInfoParse(minf[0], "h:" VNAME ":val:0:1")
|| meetPullInfoParse(minf[1], "hgvec:" VNAME ":gvec")
@@ -164,24 +166,25 @@
|| meetPullInfoAddMulti(pctx, minf, 3)) {
airMopAdd(mop, err = biffGetDone(MEET), airFree, airMopAlways);
fprintf(stderr, "%s: trouble setting up faux info:\n%s", me, err);
- airMopError(mop); return 1;
+ airMopError(mop);
+ return 1;
}
- if (pullSysParmSet(pctx, pullSysParmRadiusSpace, vlen)
- || pullStart(pctx)
+ if (pullSysParmSet(pctx, pullSysParmRadiusSpace, vlen) || pullStart(pctx)
|| pullOutputGet(npos, NULL, NULL, NULL, 0.0, pctx)) {
airMopAdd(mop, err = biffGetDone(PULL), airFree, airMopAlways);
fprintf(stderr, "%s: trouble starting or getting output:\n%s", me, err);
- airMopError(mop); return 1;
+ airMopError(mop);
+ return 1;
}
nout = nrrdNew();
airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
- size_t cmin[2] = {0,0};
- size_t cmax[2] = {2,npos->axis[1].size-1};
- if (nrrdCrop(nout, npos, cmin, cmax)
- || nrrdSave(outS, nout, NULL)) {
+ size_t cmin[2] = {0, 0};
+ size_t cmax[2] = {2, npos->axis[1].size - 1};
+ if (nrrdCrop(nout, npos, cmin, cmax) || nrrdSave(outS, nout, NULL)) {
airMopAdd(mop, err = biffGetDone(PULL), airFree, airMopAlways);
fprintf(stderr, "%s: trouble saving output:\n%s", me, err);
- airMopError(mop); return 1;
+ airMopError(mop);
+ return 1;
}
pullFinish(pctx);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 20:39:54
|
Revision: 7456
http://sourceforge.net/p/teem/code/7456
Author: kindlmann
Date: 2025-09-18 20:39:52 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
(work is ongoing on a hestParse re-write, but also this:)
API CHANGE:
rename hestParm->respFileEnable --> responseFileEnable
rename hestDefaultRespFileEnable --> hestDefaultResponseFileEnable
because it was inconsistent to have that "response" abbreviated,
when the pattern in hest has long bin to write out long things with whole words.
ALSO API CHANGE:
removing fields from hestParm in hest.h:
char respFileFlag, /* the character at the beginning of an argument
indicating that this is a response file name */
respFileComment, /* comment character for the response files */
varParamStopFlag, /* prefixed by '-' to form the flag (usually "--") that signals the
end of a *flagged* variable parameter option (single or
multiple). This is important to use if there is a flagged
variable parameter option preceeding an unflagged variable
parameter option, because otherwise how will you know where the
first stops and the second begins */
multiFlagSep; /* character in flag which signifies that there is a long and short
version, and which separates the two. Or, can be set to '\0' to
disable this behavior entirely. */
and removing the corresponding defaults:
HEST_EXPORT char hestDefaultRespFileFlag;
HEST_EXPORT char hestDefaultRespFileComment;
HEST_EXPORT char hestDefaultVarParamStopFlag;
HEST_EXPORT char hestDefaultMultiFlagSep;
Why the change: there is more confusion than utility created by allowing these
special characters change. The actual value in giving these things names was in
code legibility by removing magic constants. That's now the role of some new
#defines in privateHest.h.
Modified Paths:
--------------
teem/trunk/src/bin/ilk.c
teem/trunk/src/bin/miter.c
teem/trunk/src/bin/mrender.c
teem/trunk/src/bin/puller.c
teem/trunk/src/hest/argvHest.c
teem/trunk/src/hest/defaultsHest.c
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parseHest.c
teem/trunk/src/hest/parsest.c
teem/trunk/src/hest/privateHest.h
teem/trunk/src/hest/test/tparse.c
teem/trunk/src/hest/usage.c
teem/trunk/src/ten/tendBfit.c
teem/trunk/src/ten/tendGlyph.c
teem/trunk/src/unrrdu/join.c
teem/trunk/src/unrrdu/make.c
teem/trunk/src/unrrdu/shuffle.c
Modified: teem/trunk/src/bin/ilk.c
===================================================================
--- teem/trunk/src/bin/ilk.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/bin/ilk.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -57,7 +57,7 @@
hparm->elideSingleOtherType = AIR_TRUE;
hparm->elideSingleOtherDefault = AIR_FALSE;
hparm->elideMultipleNonExistFloatDefault = AIR_TRUE;
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hestParmColumnsIoctl(hparm, hestDefaultColumns);
hestOptAdd_1_Other(&hopt, "i", "image", &nin, "-", "input image", nrrdHestNrrd);
Modified: teem/trunk/src/bin/miter.c
===================================================================
--- teem/trunk/src/bin/miter.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/bin/miter.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -50,7 +50,7 @@
airMopAdd(mop, muu, (airMopper)miteUserNix, airMopAlways);
hparm->respectDashDashHelp = AIR_TRUE;
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hparm->elideMultipleNonExistFloatDefault = AIR_TRUE;
hestOptAdd_1_Other(&hopt, "i", "nsin", &(muu->nsin), "",
"input scalar volume to render", nrrdHestNrrd);
Modified: teem/trunk/src/bin/mrender.c
===================================================================
--- teem/trunk/src/bin/mrender.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/bin/mrender.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -453,7 +453,7 @@
mop = airMopNew();
hparm = hestParmNew();
airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hparm->respectDashDashHelp = AIR_TRUE;
uu = mrendUserNew();
airMopAdd(mop, uu, (airMopper)mrendUserNix, airMopAlways);
Modified: teem/trunk/src/bin/puller.c
===================================================================
--- teem/trunk/src/bin/puller.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/bin/puller.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -74,7 +74,7 @@
nPosOut = nrrdNew();
airMopAdd(mop, nPosOut, (airMopper)nrrdNuke, airMopAlways);
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hparm->respectDashDashHelp = AIR_TRUE;
me = argv[0];
Modified: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/argvHest.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -21,6 +21,7 @@
#include "privateHest.h"
#include <assert.h>
+#include <sys/errno.h>
#define INCR 32
@@ -32,7 +33,7 @@
void **v;
} hestPtrPtrUnion;
-/* ---------------------- hestArg = harg = hestArg = harg ------------------ */
+/* -------------------------- hestArg = harg = hestArg = harg ---------------------- */
/* dereferences as char *, sets to '\0' */
static void
@@ -110,7 +111,7 @@
return;
}
-/* ------------------ hestArgVec = havec = hestArgVec = havec -------------- */
+/* ---------------------- hestArgVec = havec = hestArgVec = havec ------------------ */
hestArgVec *
hestArgVecNew() {
@@ -150,7 +151,7 @@
printf("\n");
}
-/* --------------------- hestInput = hin = hestInput = hin ----------------- */
+/* ------------------------- hestInput = hin = hestInput = hin --------------------- */
static void
hinInit(void *_hin) {
@@ -160,8 +161,8 @@
hin->argc = 0;
hin->argv = NULL;
hin->argIdx = 0;
- hin->fname = NULL;
- hin->file = NULL;
+ hin->rfname = NULL;
+ hin->rfile = NULL;
hin->dashBraceComment = 0;
return;
}
@@ -190,6 +191,8 @@
return NULL;
}
+/* ------------------- hestInputStack = hist = hestInputStack = hist --------------- */
+
hestInputStack *
hestInputStackNew(void) {
hestInputStack *hist = AIR_CALLOC(1, hestInputStack);
@@ -200,6 +203,7 @@
hppu.hin = &(hist->hin);
hist->hinArr = airArrayNew(hppu.v, &(hist->len), sizeof(hestInput), INCR);
airArrayStructCB(hist->hinArr, hinInit, hinDone);
+ hist->stdinRead = AIR_FALSE;
return hist;
}
@@ -211,11 +215,17 @@
return NULL;
}
+#define ME ((hparm && hparm->verbosity) ? me : "")
+
int
hestInputStackPushCommandLine(hestInputStack *hist, int argc, const char **argv,
char *err, const hestParm *hparm) {
- assert(hist);
- AIR_UNUSED(err);
+ static const char me[] = "hestInputStackPushCommandLine: ";
+ if (!(hist && argv && hparm)) { // (as if all this can go wrong but err is non-NULL)
+ sprintf(err, "%s: got NULL pointer (hist %p, argv %p, hparm %p)", __func__,
+ AIR_VOIDP(hist), AIR_VOIDP(argv), AIR_VOIDP(hparm));
+ return 1;
+ }
if (hparm->verbosity) {
printf("%s: changing stack height: %u --> %u with argc=%d,argv=%p; "
"setting argIdx to 0\n",
@@ -223,7 +233,7 @@
}
uint idx = airArrayLenIncr(hist->hinArr, 1);
if (hparm->verbosity > 1) {
- printf("%s: new hinTop = %p\n", __func__, AIR_VOIDP(hist->hin + idx));
+ printf("%snew hinTop = %p\n", ME, AIR_VOIDP(hist->hin + idx));
}
hist->hin[idx].source = hestSourceCommandLine;
hist->hin[idx].argc = argc;
@@ -233,6 +243,58 @@
}
int
+hestInputStackPushResponseFile(hestInputStack *hist, const char *rfname, char *err,
+ const hestParm *hparm) {
+ static const char me[] = "hestInputStackPushResponseFile: ";
+ if (!(hist && rfname && hparm)) {
+ sprintf(err, "%s: got NULL pointer (hist %p, rfname %p, hparm %p)", __func__,
+ AIR_VOIDP(hist), AIR_VOIDP(rfname), AIR_VOIDP(hparm));
+ return 1;
+ }
+ if (!strlen(rfname)) {
+ sprintf(err,
+ "%ssaw arg start with response file flag \"%c\" "
+ "but no filename followed",
+ ME, RESPONSE_FILE_FLAG);
+ return 1;
+ }
+ // "- 1" safe because hestParse always starts with argc/argv, not a response file
+ uint topHinIdx = hist->len - 1;
+ // have we seen rfname before?
+ for (uint hidx = 0; hidx < topHinIdx; hidx++) {
+ hestInput *oldHin = hist->hin + hidx;
+ if (hestSourceResponseFile == oldHin->source //
+ && !strcmp(oldHin->rfname, rfname)) {
+ // HEY test this error
+ sprintf(err, "%salready currently reading \"%s\" as response file", ME, rfname);
+ return 1;
+ }
+ }
+ // are we trying to read stdin twice?
+ if (!strcmp("-", rfname) && hist->stdinRead) {
+ // HEY test this error
+ sprintf(err, "%sresponse filename \"%s\" but previously read stdin", ME, rfname);
+ return 1;
+ }
+ // try to open response file
+ FILE *rfile = airFopen(rfname, stdin, "r");
+ if (!(rfile)) {
+ // HEY test this error
+ sprintf(err, "%scouldn't fopen(\"%s\",\"r\"): %s", ME, rfname, strerror(errno));
+ return 1;
+ }
+ // okay, we actually opened the response file; put it on the stack
+ uint idx = airArrayLenIncr(hist->hinArr, 1);
+ if (hparm->verbosity > 1) {
+ printf("%snew hinTop = %p\n", ME, AIR_VOIDP(hist->hin + idx));
+ }
+ hist->hin[idx].source = hestSourceResponseFile;
+ hist->hin[idx].rfname = rfname;
+ hist->hin[idx].rfile = rfile;
+ return 0;
+}
+
+int
hestInputStackPop(hestInputStack *hist, char *err, const hestParm *hparm) {
assert(hist);
uint len = hist->hinArr->len;
Modified: teem/trunk/src/hest/defaultsHest.c
===================================================================
--- teem/trunk/src/hest/defaultsHest.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/defaultsHest.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -21,7 +21,7 @@
#include "privateHest.h"
int hestDefaultVerbosity = 0;
-int hestDefaultRespFileEnable = AIR_FALSE;
+int hestDefaultResponseFileEnable = AIR_FALSE;
unsigned int hestDefaultColumns = 79;
int hestDefaultElideSingleEnumType = AIR_FALSE;
int hestDefaultElideSingleOtherType = AIR_FALSE;
@@ -33,7 +33,3 @@
int hestDefaultNoArgsIsNoProblem = AIR_FALSE;
int hestDefaultGreedySingleString = AIR_TRUE;
int hestDefaultCleverPluralizeOtherY = AIR_FALSE;
-char hestDefaultRespFileFlag = '@';
-char hestDefaultRespFileComment = '#';
-char hestDefaultVarParamStopFlag = '-';
-char hestDefaultMultiFlagSep = ',';
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/hest.h 2025-09-18 20:39:52 UTC (rev 7456)
@@ -174,7 +174,7 @@
*/
typedef struct {
int verbosity, /* verbose diagnostic messages to stdout */
- respFileEnable, /* whether or not to use response files */
+ responseFileEnable, /* whether or not to use response files */
elideSingleEnumType, /* if type is airTypeEnum, and if it's a single fixed parameter
option, then don't bother printing the type information as
part of hestGlossary() */
@@ -212,18 +212,6 @@
might: only print info and glossary when they "ask for it" */
noBlankLineBeforeUsage; /* like it says */
unsigned int columns; /* number of printable columns in output */
- char respFileFlag, /* the character at the beginning of an argument
- indicating that this is a response file name */
- respFileComment, /* comment character for the response files */
- varParamStopFlag, /* prefixed by '-' to form the flag (usually "--") that signals the
- end of a *flagged* variable parameter option (single or
- multiple). This is important to use if there is a flagged
- variable parameter option preceeding an unflagged variable
- parameter option, because otherwise how will you know where the
- first stops and the second begins */
- multiFlagSep; /* character in flag which signifies that there is a long and short
- version, and which separates the two. Or, can be set to '\0' to
- disable this behavior entirely. */
} hestParm;
/*
@@ -267,8 +255,8 @@
const char **argv; // we do NOT own
unsigned int argIdx;
// ------ if source == hestSourceResponseFile ------
- char *fname; // we do NOT own
- FILE *file; // someone opened this for us
+ const char *rfname; // we do NOT own: points into an argv or a hestArg
+ FILE *rfile; // user opens and closes this
// ------ general for all inputs ------
unsigned int dashBraceComment; /* not a boolean: how many -{ }- comment levels
deep are we currently; tracked this way to
@@ -279,11 +267,12 @@
hestInput *hin; // array of hestInputs
unsigned int len;
airArray *hinArr;
+ int stdinRead; // while processing this stack we have read in "-" aka stdin
} hestInputStack;
// defaultsHest.c
HEST_EXPORT int hestDefaultVerbosity;
-HEST_EXPORT int hestDefaultRespFileEnable;
+HEST_EXPORT int hestDefaultResponseFileEnable;
HEST_EXPORT int hestDefaultElideSingleEnumType;
HEST_EXPORT int hestDefaultElideSingleOtherType;
HEST_EXPORT int hestDefaultElideSingleOtherDefault;
@@ -295,10 +284,6 @@
HEST_EXPORT int hestDefaultGreedySingleString;
HEST_EXPORT int hestDefaultCleverPluralizeOtherY;
HEST_EXPORT unsigned int hestDefaultColumns;
-HEST_EXPORT char hestDefaultRespFileFlag;
-HEST_EXPORT char hestDefaultRespFileComment;
-HEST_EXPORT char hestDefaultVarParamStopFlag;
-HEST_EXPORT char hestDefaultMultiFlagSep;
// argvHest.c
HEST_EXPORT hestArg *hestArgNew(void);
@@ -316,6 +301,8 @@
HEST_EXPORT int hestInputStackPushCommandLine(hestInputStack *hist, int argc,
const char **argv, char *err,
const hestParm *hparm);
+HEST_EXPORT int hestInputStackPushResponseFile(hestInputStack *hist, const char *rfname,
+ char *err, const hestParm *hparm);
HEST_EXPORT int hestInputStackPop(hestInputStack *hist, char *err,
const hestParm *hparm);
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -70,7 +70,7 @@
hparm = AIR_CALLOC(1, hestParm);
assert(hparm);
hparm->verbosity = hestDefaultVerbosity;
- hparm->respFileEnable = hestDefaultRespFileEnable;
+ hparm->responseFileEnable = hestDefaultResponseFileEnable;
hparm->elideSingleEnumType = hestDefaultElideSingleEnumType;
hparm->elideSingleOtherType = hestDefaultElideSingleOtherType;
hparm->elideSingleOtherDefault = hestDefaultElideSingleOtherDefault;
@@ -106,10 +106,11 @@
hparm->dieLessVerbose = AIR_FALSE;
hparm->noBlankLineBeforeUsage = AIR_FALSE;
hparm->columns = hestDefaultColumns;
- hparm->respFileFlag = hestDefaultRespFileFlag;
- hparm->respFileComment = hestDefaultRespFileComment;
- hparm->varParamStopFlag = hestDefaultVarParamStopFlag;
- hparm->multiFlagSep = hestDefaultMultiFlagSep;
+ // see note in privateHest.h about the removal of these
+ // hparm->responseFileFlag = hestDefaultRespFileFlag;
+ // hparm->responseFileComment = hestDefaultRespFileComment;
+ // hparm->varParamStopFlag = hestDefaultVarParamStopFlag;
+ // hparm->multiFlagSep = hestDefaultMultiFlagSep;
return hparm;
}
@@ -534,7 +535,7 @@
}
if (opt[opi].flag) {
strcpy(tbuff, opt[opi].flag);
- if ((sep = strchr(tbuff, hparm->multiFlagSep))) {
+ if ((sep = strchr(tbuff, MULTI_FLAG_SEP))) {
*sep = '\0';
if (!(strlen(tbuff) && strlen(sep + 1))) {
if (err)
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/parseHest.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -55,7 +55,7 @@
*argsNumP = 0;
*respFileNumP = 0;
- if (!hparm->respFileEnable) {
+ if (!hparm->responseFileEnable) {
/* don't do response files; we're done */
return 0;
}
@@ -62,7 +62,7 @@
argIdx = 0;
while (argv /* can be NULL for testing */ && argv[argIdx]) {
- if (hparm->respFileFlag == argv[argIdx][0]) {
+ if (RESPONSE_FILE_FLAG == argv[argIdx][0]) {
/* argv[argIdx] looks like its naming a response file */
/* NOTE: despite the repeated temptation: "-" aka stdin cannot be a response file,
because it is going to be read in twice: once by argsInResponseFiles, and then
@@ -79,7 +79,7 @@
len = airOneLine(file, line, AIR_STRLEN_HUGE + 1);
while (len > 0) {
/* first # (or #-alike char) is turned into line end */
- if ((pound = strchr(line, hparm->respFileComment))) {
+ if ((pound = strchr(line, RESPONSE_FILE_COMMENT))) {
*pound = '\0';
}
/* count words in line */
@@ -123,10 +123,9 @@
'#' character is considered to mark the beginning of a comment, EVEN IF THAT '#' is
inside a string. Sorry. (This is why hest parsing is being re-written ...)
-For a brief moment in 2023, this also stopped if it saw "--" (or whatever
-parm->varParamStopFlag implies), but that meant "--" is a brick wall that hestParse could
-never see past. But that misunderstands the relationship between how hestParse works and
-how the world uses "--". According to POSIX guidelines:
+For a brief moment in 2023, this also stopped if it saw "--", but that meant "--" is a
+brick wall that hestParse could never see past. But that misunderstands the relationship
+between how hestParse works and how the world uses "--". According to POSIX guidelines:
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_01
the elements of argv can be first "options" and then "operands", where "options" are
indicated by something starting with '-', and may have 0 or more "option-arguments".
@@ -182,7 +181,7 @@
oldArgv[argIdx]);
printArgv(newArgc, newArgv, " ");
}
- if (!hparm->respFileEnable || hparm->respFileFlag != oldArgv[argIdx][0]) {
+ if (!hparm->responseFileEnable || RESPONSE_FILE_FLAG != oldArgv[argIdx][0]) {
/* either ignoring response files, or its not a response file:
we copy the arg, remember to free it, and increment the new arg idx */
newArgv[newArgc] = airStrdup(oldArgv[argIdx]);
@@ -198,7 +197,7 @@
unsigned rgi;
if (hparm->verbosity) printf("%s: line: |%s|\n", me, line);
/* HEY HEY too bad for you if you put # inside a string */
- if ((pound = strchr(line, hparm->respFileComment))) *pound = '\0';
+ if ((pound = strchr(line, RESPONSE_FILE_COMMENT))) *pound = '\0';
if (hparm->verbosity) printf("%s: -0-> line: |%s|\n", me, line);
airOneLinify(line);
incr = airStrntok(line, AIR_WHITESPACE);
@@ -261,13 +260,13 @@
static char *
identStr(char *ident, const hestOpt *opt, const hestParm *hparm, int brief) {
char copy[AIR_STRLEN_HUGE + 1], *sep;
-
- if (opt->flag && (sep = strchr(opt->flag, hparm->multiFlagSep))) {
+ AIR_UNUSED(hparm);
+ if (opt->flag && (sep = strchr(opt->flag, MULTI_FLAG_SEP))) {
strcpy(copy, opt->flag);
- sep = strchr(copy, hparm->multiFlagSep);
+ sep = strchr(copy, MULTI_FLAG_SEP);
*sep = '\0';
if (brief)
- sprintf(ident, "-%s%c--%s option", copy, hparm->multiFlagSep, sep + 1);
+ sprintf(ident, "-%s%c--%s option", copy, MULTI_FLAG_SEP, sep + 1);
else
sprintf(ident, "-%s option", copy);
} else {
@@ -282,8 +281,8 @@
given a string in "flag" (with the hypen prefix) finds which of the options in the given
array of options has the matching flag. Returns the index of the matching option, or -1
-if there is no match, but returns -2 if the flag is the end-of-parameters marker "--" (or
-whatever parm->varParamStopFlag implies)
+if there is no match, but returns -2 if the flag is the end-of-parameters marker "--"
+(and only "--", due to VAR_PARM_STOP_FLAG)
*/
static int
whichOptFlag(const hestOpt *opt, const char *flag, const hestParm *hparm) {
@@ -300,9 +299,9 @@
printf("%s: optIdx %d |%s| ?\n", me, optIdx,
opt[optIdx].flag ? opt[optIdx].flag : "(nullflag)");
if (!opt[optIdx].flag) continue;
- if (strchr(opt[optIdx].flag, hparm->multiFlagSep)) {
+ if (strchr(opt[optIdx].flag, MULTI_FLAG_SEP)) {
strcpy(copy, opt[optIdx].flag);
- sep = strchr(copy, hparm->multiFlagSep);
+ sep = strchr(copy, MULTI_FLAG_SEP);
*sep = '\0';
/* first try the short version */
sprintf(buff, "-%s", copy);
@@ -317,10 +316,10 @@
}
}
if (hparm->verbosity) printf("%s: (b) optNum = %d\n", me, optNum);
- if (hparm->varParamStopFlag) {
- sprintf(buff, "-%c", hparm->varParamStopFlag);
+ if (VAR_PARM_STOP_FLAG) {
+ sprintf(buff, "-%c", VAR_PARM_STOP_FLAG);
if (hparm->verbosity)
- printf("%s: does maybe-is-flag |%s| == -parm->varParamStopFlag |%s| ?\n", me, flag,
+ printf("%s: does maybe-is-flag |%s| == -VAR_PARM_STOP_FLAG |%s| ?\n", me, flag,
buff);
if (!strcmp(flag, buff)) {
if (hparm->verbosity) printf("%s: yes, it does! returning -2\n", me);
@@ -352,7 +351,7 @@
if (hparm) {
stops[0] = '-';
- stops[1] = hparm->varParamStopFlag;
+ stops[1] = VAR_PARM_STOP_FLAG;
stops[2] = '\0';
} /* else stops stays as empty string */
@@ -417,9 +416,9 @@
The sawP information is not set here, since it is better set at value parsing time, which
happens after defaults are enstated.
-This is where, thanks to the action of whichOptFlag(), "--" (or whatever
-parm->varParamStopFlag implies) is used as a marker for the end of a *flagged* variable
-parameter option. AND, the "--" marker is removed from the argv.
+This is where, thanks to the action of whichOptFlag(), "--" (and only "--" due to
+VAR_PARM_STOP_FLAG) is used as a marker for the end of a *flagged* variable parameter
+option. AND, the "--" marker is removed from the argv.
*/
static int
extractFlagged(char **optParms, unsigned int *optParmNum, int *optAprd, int *argcP,
@@ -488,8 +487,7 @@
sprintf(err,
"%ssaw \"-%c\" (option-parameter-stop flag) before getting %d "
"parameter%s for %s (got %d)",
- ME, hparm->varParamStopFlag, opt[optIdx].min,
- opt[optIdx].min > 1 ? "s" : "",
+ ME, VAR_PARM_STOP_FLAG, opt[optIdx].min, opt[optIdx].min > 1 ? "s" : "",
identStr(ident2, opt + optIdx, hparm, AIR_FALSE), parmNum);
}
return 1;
@@ -1407,10 +1405,10 @@
/* currently, any left-over arguments indicate error */
if (argc_used) {
- /* char stops[3] = {'-', HPARM->varParamStopFlag, '\0'}; triggers warning:
+ /* char stops[3] = {'-', VAR_PARM_STOP_FLAG, '\0'}; triggers warning:
initializer element is not computable at load time */
char stops[3] = "-X";
- stops[1] = HPARM->varParamStopFlag;
+ stops[1] = VAR_PARM_STOP_FLAG;
if (strcmp(stops, argv[0])) {
sprintf(err, "%sunexpected arg%s: \"%s\"", ME,
('-' == argv[0][0] ? " (or unrecognized flag)" : ""), argv[0]);
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/parsest.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -20,8 +20,10 @@
#include "hest.h"
#include "privateHest.h"
-/* parse, parser, parsest: this aims to be the final implmentation of hestParse */
+/* parse, parser, parsest: may this be the final implmentation of hestParse */
+#include <assert.h>
+
/* A little trickery for error reporting. For many of the functions here, if they hit an
error and hparm->verbosity is set, then we should reveal the current function name (set
by convention in `me`). But without verbosity, we hide that function name, so it appears
@@ -39,64 +41,77 @@
histProc(hestArgVec *havec, int *helpWantedP, hestInputStack *hist, char *err,
const hestParm *hparm) {
static const char me[] = "histProc: ";
- int ret = 0;
int popAtEnd = AIR_FALSE;
*helpWantedP = AIR_FALSE; // may over-write later
- hestInput *hinTop = hist->hin + (hist->len - 1);
- switch (hinTop->source) {
+ hestInput *theHin = hist->hin + hist->len - 1;
+ switch (theHin->source) {
case hestSourceDefault: // ---------------------------------
- sprintf(err, "%ssorry hestSourceDefault not implemented\n", ME);
- ret = 1;
+ sprintf(err, "%ssorry hestSourceDefault not implemented", ME);
+ return 1;
break;
case hestSourceCommandLine: // ---------------------------------
- /* argv[] 0 1 2 3 (argc=4) */
- /* cmd arg1 arg2 arg3 */
+ // argv[] 0 1 2 3 (argc=4)
+ // cmd arg1 arg2 arg3
if (hparm->verbosity > 1) {
- printf("%shist->len=%u -> hinTop=%p\n", me, hist->len, AIR_VOIDP(hinTop));
+ printf("%shist->len=%u -> theHin=%p\n", me, hist->len, AIR_VOIDP(theHin));
}
- if (hinTop->argIdx < hinTop->argc) {
- /* there are args left to parse */
- const char *thisArgv = hinTop->argv[hinTop->argIdx];
+ if (theHin->argIdx < theHin->argc) {
+ // there are args left to parse
+ uint thisArgIdx = theHin->argIdx;
+ const char *theArg = theHin->argv[thisArgIdx];
if (hparm->verbosity > 1) {
- printf("%slooking at argv[%u] |%s|\n", me, hinTop->argIdx, thisArgv);
+ printf("%slooking at argv[%u] |%s|\n", me, theHin->argIdx, theArg);
}
- hinTop->argIdx++;
- if (hparm->respectDashBraceComments && !strcmp("-{", thisArgv)) {
+ theHin->argIdx++;
+ // process theArg we just acquired
+ if (hparm->respectDashBraceComments && !strcmp("-{", theArg)) {
// start of -{ }- commenting (or increase in nesting level)
- hinTop->dashBraceComment += 1;
+ theHin->dashBraceComment += 1;
}
- if (!hinTop->dashBraceComment) {
- hestArgVecAppendString(havec, thisArgv);
+ if (theHin->dashBraceComment) {
+ if (hparm->verbosity > 1) {
+ printf("%sskipping commented-out |%s|\n", me, theArg);
+ }
+ } else {
+ // not commenting out thisArg
+ if (!hparm->responseFileEnable || theArg[0] != RESPONSE_FILE_FLAG) {
+ // not a response file, just an arg
+ hestArgVecAppendString(havec, theArg);
+ } else {
+ /* theArg is asking to be a response file; try pushing it. With or without an
+ error, we return early because there's nothing more for us to do */
+ return hestInputStackPushResponseFile(hist, theArg + 1, err, hparm);
+ }
}
- if (hparm->respectDashBraceComments && !strcmp("}-", thisArgv)) {
- if (hinTop->dashBraceComment) {
- hinTop->dashBraceComment -= 1;
+ if (hparm->respectDashBraceComments && !strcmp("}-", theArg)) {
+ if (theHin->dashBraceComment) {
+ theHin->dashBraceComment -= 1;
} else {
sprintf(err, "%send comment arg \"}-\" not balanced by prior \"-{\"", ME);
- ret = 1;
+ return 1;
}
}
- }
- if (hinTop->argIdx == hinTop->argc) {
+ } // NOT else
+ if (theHin->argIdx == theHin->argc) {
// we have gotten to the end of the given argv array */
- if (hinTop->dashBraceComment) {
+ if (theHin->dashBraceComment) {
sprintf(err, "%sstart comment arg \"-{\" not balanced by later \"}-\"", ME);
- ret = 1;
+ return 1;
} else {
popAtEnd = AIR_TRUE;
- // but don't pop now because we need to check for --help
+ // but don't pop now because we still need to check for --help
}
}
break;
case hestSourceResponseFile: // ---------------------------------
- sprintf(err, "%ssorry hestSourceResponseFile not implemented\n", ME);
- ret = 1;
+ sprintf(err, "%ssorry hestSourceResponseFile not implemented", ME);
+ return 1;
break;
}
/* when processing command-line or response file, check for --help
(it makes no sense for --help to appear in a default string) */
- if (hestSourceResponseFile == hinTop->source
- || hestSourceCommandLine == hinTop->source) {
+ if (hestSourceResponseFile == theHin->source
+ || hestSourceCommandLine == theHin->source) {
const hestArg *hlast;
if (hparm->respectDashDashHelp // watching for "--help"
&& havec->len // have at least one arg
@@ -107,10 +122,10 @@
}
if (popAtEnd) {
if (hestInputStackPop(hist, err, hparm)) {
- ret = 1;
+ return 1;
}
}
- return ret;
+ return 0;
}
int
Modified: teem/trunk/src/hest/privateHest.h
===================================================================
--- teem/trunk/src/hest/privateHest.h 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/privateHest.h 2025-09-18 20:39:52 UTC (rev 7456)
@@ -21,7 +21,31 @@
extern "C" {
#endif
-#include <assert.h>
+// pre-TeemV2, these used to be change-able defaults in defaultsHest.c:
+// char hestDefaultRespFileFlag = '@';
+// char hestDefaultRespFileComment = '#';
+// char hestDefaultVarParamStopFlag = '-';
+// char hestDefaultMultiFlagSep = ',';
+// with corresponding fields in the hestParm defined in hest.h
+// char respFileFlag, /* the character at the beginning of an argument
+// indicating that this is a response file name */
+// respFileComment, /* comment character for the response files */
+// varParamStopFlag, /* prefixed by '-' to form the flag (usually "--") that signals
+// the end of a *flagged* variable parameter option (single or
+// multiple). This is important to use if there is a flagged
+// variable parameter option preceeding an unflagged variable
+// parameter option, because otherwise how will you know where
+// the first stops and the second begins */
+// multiFlagSep; /* character in flag which signifies that there is a long and
+// short version, and which separates the two. Or, can be set
+// to '\0' to disable this behavior entirely. */
+// However, there is more confusion than utility created by allowing these
+// change. The actual value in giving these things names was in code legibility by
+// removing magic constants, so that's the role of these #define's now.
+#define RESPONSE_FILE_FLAG '@'
+#define RESPONSE_FILE_COMMENT '#'
+#define VAR_PARM_STOP_FLAG '-'
+#define MULTI_FLAG_SEP ','
typedef unsigned int uint;
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -33,6 +33,7 @@
hestOpt *opt = NULL;
hestParm *hparm = hestParmNew();
hparm->respectDashDashHelp = AIR_TRUE;
+ hparm->respFileEnable = AIR_TRUE;
int res[2];
hestOptAdd_2_Int(&opt, "res", "sx sy", res, NULL, "image resolution");
int flag;
Modified: teem/trunk/src/hest/usage.c
===================================================================
--- teem/trunk/src/hest/usage.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/hest/usage.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -26,13 +26,12 @@
static void
_hestSetBuff(char *B, const hestOpt *O, const hestParm *P, int showshort, int showlong) {
char copy[AIR_STRLEN_HUGE + 1], *sep;
- int max;
unsigned int len;
-
- max = _hestMax(O->max);
+ AIR_UNUSED(P); // formerly for P->multiFlagSep
+ int max = _hestMax(O->max);
if (O->flag) {
strcpy(copy, O->flag);
- if ((sep = strchr(copy, P->multiFlagSep))) {
+ if ((sep = strchr(copy, MULTI_FLAG_SEP))) {
*sep = 0;
if (showshort) {
strcat(B, "-");
@@ -41,7 +40,7 @@
if (showlong) {
if (showshort) {
len = AIR_UINT(strlen(B));
- B[len] = P->multiFlagSep;
+ B[len] = MULTI_FLAG_SEP;
B[len + 1] = '\0';
}
strcat(B, "--");
@@ -247,8 +246,8 @@
}
strcpy(buff, "Usage: ");
strcat(buff, argv0 ? argv0 : "");
- if (HPARM->respFileEnable) {
- sprintf(tmpS, " [%cfile\t...]", HPARM->respFileFlag);
+ if (HPARM->responseFileEnable) {
+ sprintf(tmpS, " [%cfile\t...]", RESPONSE_FILE_FLAG);
strcat(buff, tmpS);
}
for (i = 0; i < numOpts; i++) {
@@ -294,8 +293,8 @@
_hestSetBuff(buff, opt + i, HPARM, AIR_TRUE, AIR_FALSE);
maxlen = AIR_MAX((int)strlen(buff), maxlen);
}
- if (HPARM->respFileEnable) {
- sprintf(buff, "%cfile ...", HPARM->respFileFlag);
+ if (HPARM->responseFileEnable) {
+ sprintf(buff, "%cfile ...", RESPONSE_FILE_FLAG);
len = AIR_UINT(strlen(buff));
for (j = len; j < maxlen; j++) {
fprintf(f, " ");
@@ -315,7 +314,7 @@
fprintf(f, "%s", buff);
strcpy(buff, "");
#if 1
- if (opt[i].flag && strchr(opt[i].flag, HPARM->multiFlagSep)) {
+ if (opt[i].flag && strchr(opt[i].flag, MULTI_FLAG_SEP)) {
/* there is a long-form flag as well as short */
_hestSetBuff(buff, opt + i, HPARM, AIR_FALSE, AIR_TRUE);
strcat(buff, " = ");
Modified: teem/trunk/src/ten/tendBfit.c
===================================================================
--- teem/trunk/src/ten/tendBfit.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/ten/tendBfit.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -39,7 +39,7 @@
int iterMax;
char *outS;
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hestOptAdd_1_Other(&hopt, "i", "nin", &nin, "-",
"Input nrrd. List of DWIs from different b-values must "
Modified: teem/trunk/src/ten/tendGlyph.c
===================================================================
--- teem/trunk/src/ten/tendGlyph.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/ten/tendGlyph.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -123,7 +123,7 @@
double v2w[9], ldir[3], edir[3], fdir[3], corn[3], len;
/* so that command-line options can be read from file */
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hparm->elideSingleEmptyStringDefault = AIR_TRUE;
mop = airMopNew();
Modified: teem/trunk/src/unrrdu/join.c
===================================================================
--- teem/trunk/src/unrrdu/join.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/unrrdu/join.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -45,7 +45,7 @@
double mm[2], spc;
airArray *mop;
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hestOptAdd_Nv_Other(&opt, "i,input", "nin0", 1, -1, &nin, NULL,
"everything to be joined together", &ninLen, nrrdHestNrrdNoTTY);
Modified: teem/trunk/src/unrrdu/make.c
===================================================================
--- teem/trunk/src/unrrdu/make.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/unrrdu/make.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -82,7 +82,7 @@
const NrrdEncoding *encoding;
/* so that long lists of filenames can be read from file */
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hparm->greedySingleString = AIR_TRUE;
mop = airMopNew();
Modified: teem/trunk/src/unrrdu/shuffle.c
===================================================================
--- teem/trunk/src/unrrdu/shuffle.c 2025-09-18 15:34:17 UTC (rev 7455)
+++ teem/trunk/src/unrrdu/shuffle.c 2025-09-18 20:39:52 UTC (rev 7456)
@@ -44,7 +44,7 @@
airArray *mop;
/* so that long permutations can be read from file */
- hparm->respFileEnable = AIR_TRUE;
+ hparm->responseFileEnable = AIR_TRUE;
hestOptAdd_Nv_UInt(&opt, "p,permute", "slc0 slc1", 1, -1, &perm, NULL,
"new slice ordering", &permLen);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 15:34:20
|
Revision: 7455
http://sourceforge.net/p/teem/code/7455
Author: kindlmann
Date: 2025-09-18 15:34:17 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
ABI CHANGE: as part of shifting some ten/test/*.c programs to the new typed hestOptAdd_ functions, discovered that some fields in the tenEMBimodalParm struct were doubles when they should have been (boolean) ints: twoStage and verbose. They were set by the non-type-checked hestOptAdd() as ints, which still worked, but the type error has now been fixed
Modified Paths:
--------------
teem/trunk/src/ten/ten.h
teem/trunk/src/ten/test/cntr.c
teem/trunk/src/ten/test/igrt.c
teem/trunk/src/ten/test/odf-hist.c
teem/trunk/src/ten/test/teigen.c
teem/trunk/src/ten/test/tem.c
teem/trunk/src/ten/test/tg.c
teem/trunk/src/ten/test/tqgl.c
teem/trunk/src/ten/test/tt.c
Modified: teem/trunk/src/ten/ten.h
===================================================================
--- teem/trunk/src/ten/ten.h 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/ten.h 2025-09-18 15:34:17 UTC (rev 7455)
@@ -911,11 +911,11 @@
minDelta, /* convergence test for maximization */
minFraction, /* smallest fraction (in 0.0 to 1.0) that material
1 or 2 can legitimately have */
- minConfidence, /* smallest confidence value that the model fitting
- is allowed to have */
- twoStage, /* wacky two-stage fitting */
+ minConfidence; /* smallest confidence value that the model fitting
+ is allowed to have */
+ unsigned int maxIteration; /* cap on # of non-convergent iters allowed */
+ int twoStage, /* wacky two-stage fitting */
verbose; /* output messages and/or progress images */
- unsigned int maxIteration; /* cap on # of non-convergent iters allowed */
/* ----- internal ----- */
double *histo, /* double version of histogram */
*pp1, *pp2, /* pre-computed posterior probabilities for the
Modified: teem/trunk/src/ten/test/cntr.c
===================================================================
--- teem/trunk/src/ten/test/cntr.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/cntr.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -17,7 +17,6 @@
along with this library; if not, see <https://www.gnu.org/licenses/>.
*/
-
#include "../ten.h"
const char *info = ("does contraction between 2 2nd-order "
@@ -27,24 +26,25 @@
main(int argc, const char *argv[]) {
const char *me;
char *err;
- hestOpt *hopt=NULL;
+ hestOpt *hopt = NULL;
airArray *mop;
- char *outS;
- Nrrd *_ncov, *ncov, *_nten[2], *nten[2], *nout;
+ Nrrd *ncov, *nten[2], *nout;
double *cc, *t0, *t1, *out, ww[21];
size_t nn, ii;
mop = airMopNew();
me = argv[0];
- hestOptAdd(&hopt, "i4", "volume", airTypeOther, 1, 1, &_ncov, NULL,
- "4th-order tensor volume", NULL, NULL, nrrdHestNrrd);
- hestOptAdd(&hopt, "i2", "v0 v1", airTypeOther, 2, 2, _nten, NULL,
- "two 2nd-order tensor volumes", NULL, NULL, nrrdHestNrrd);
- hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS, "-",
- "file to write output nrrd to");
- hestParseOrDie(hopt, argc-1, argv+1, NULL,
- me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
+ Nrrd *_ncov;
+ hestOptAdd_1_Other(&hopt, "i4", "volume", &_ncov, NULL, "4th-order tensor volume",
+ nrrdHestNrrd);
+ Nrrd *_nten[2];
+ hestOptAdd_2_Other(&hopt, "i2", "v0 v1", _nten, NULL, "two 2nd-order tensor volumes",
+ nrrdHestNrrd);
+ char *outS;
+ hestOptAdd_1_String(&hopt, "o", "filename", &outS, "-",
+ "file to write output nrrd to");
+ hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
@@ -56,17 +56,17 @@
return 1;
}
if (!(4 == _ncov->dim && 21 == _ncov->axis[0].size)) {
- fprintf(stderr, "%s: didn't get a 4-D 21-by-X volume (got %u-D %u-by-X)\n",
- me, _ncov->dim, AIR_UINT(_ncov->axis[0].size));
+ fprintf(stderr, "%s: didn't get a 4-D 21-by-X volume (got %u-D %u-by-X)\n", me,
+ _ncov->dim, AIR_UINT(_ncov->axis[0].size));
airMopError(mop);
return 1;
}
- if (!(nrrdElementNumber(_ncov)/21 == nrrdElementNumber(_nten[0])/7
- && nrrdElementNumber(_nten[0])/7 == nrrdElementNumber(_nten[1])/7)) {
+ if (!(nrrdElementNumber(_ncov) / 21 == nrrdElementNumber(_nten[0]) / 7
+ && nrrdElementNumber(_nten[0]) / 7 == nrrdElementNumber(_nten[1]) / 7)) {
fprintf(stderr, "%s: number voxels %u %u %u don't all match\n", me,
- AIR_UINT(nrrdElementNumber(_ncov)/21),
- AIR_UINT(nrrdElementNumber(_nten[0])/7),
- AIR_UINT(nrrdElementNumber(_nten[1])/7));
+ AIR_UINT(nrrdElementNumber(_ncov) / 21),
+ AIR_UINT(nrrdElementNumber(_nten[0]) / 7),
+ AIR_UINT(nrrdElementNumber(_nten[1]) / 7));
airMopError(mop);
return 1;
}
@@ -83,8 +83,8 @@
|| nrrdConvert(nten[0], _nten[0], nrrdTypeDouble)
|| nrrdConvert(nten[1], _nten[1], nrrdTypeDouble)) {
airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
- fprintf(stderr, "%s: trouble converting to %s:\n%s\n",
- me, airEnumStr(nrrdType, nrrdTypeDouble), err);
+ fprintf(stderr, "%s: trouble converting to %s:\n%s\n", me,
+ airEnumStr(nrrdType, nrrdTypeDouble), err);
airMopError(mop);
return 1;
}
@@ -101,12 +101,27 @@
out = AIR_CAST(double *, nout->data);
nn = nrrdElementNumber(nout);
- ww[ 0] = 1*1; ww[ 1] = 2*1; ww[ 2] = 2*1; ww[ 3] = 1*1; ww[ 4] = 2*1; ww[ 5] = 1*1;
- /* */ ww[ 6] = 2*2; ww[ 7] = 2*2; ww[ 8] = 1*2; ww[ 9] = 2*2; ww[10] = 1*2;
- /* */ ww[11] = 2*2; ww[12] = 1*2; ww[13] = 2*2; ww[14] = 1*2;
- /* */ ww[15] = 1*1; ww[16] = 2*1; ww[17] = 1*1;
- /* */ ww[18] = 2*2; ww[19] = 1*2;
- /* */ ww[20] = 1*1;
+ ww[0] = 1 * 1;
+ ww[1] = 2 * 1;
+ ww[2] = 2 * 1;
+ ww[3] = 1 * 1;
+ ww[4] = 2 * 1;
+ ww[5] = 1 * 1;
+ /* */ ww[6] = 2 * 2;
+ ww[7] = 2 * 2;
+ ww[8] = 1 * 2;
+ ww[9] = 2 * 2;
+ ww[10] = 1 * 2;
+ /* */ ww[11] = 2 * 2;
+ ww[12] = 1 * 2;
+ ww[13] = 2 * 2;
+ ww[14] = 1 * 2;
+ /* */ ww[15] = 1 * 1;
+ ww[16] = 2 * 1;
+ ww[17] = 1 * 1;
+ /* */ ww[18] = 2 * 2;
+ ww[19] = 1 * 2;
+ /* */ ww[20] = 1 * 1;
/*
for (ii=0; ii<21; ii++) {
@@ -114,14 +129,26 @@
}
*/
- for (ii=0; ii<nn; ii++) {
+ for (ii = 0; ii < nn; ii++) {
- out[ii] = (+ cc[ 0]*ww[ 0]*t0[1]*t1[1] + cc[ 1]*ww[ 1]*t0[2]*t1[1] + cc[ 2]*ww[ 2]*t0[3]*t1[1] + cc[ 3]*ww[ 3]*t0[4]*t1[1] + cc[ 4]*ww[ 4]*t0[5]*t1[1] + cc[ 5]*ww[ 5]*t0[6]*t1[1] +
- + cc[ 1]*ww[ 1]*t0[1]*t1[2] + cc[ 6]*ww[ 6]*t0[2]*t1[2] + cc[ 7]*ww[ 7]*t0[3]*t1[2] + cc[ 8]*ww[ 8]*t0[4]*t1[2] + cc[ 9]*ww[ 9]*t0[5]*t1[2] + cc[10]*ww[10]*t0[6]*t1[2] +
- + cc[ 2]*ww[ 2]*t0[1]*t1[3] + cc[ 7]*ww[ 7]*t0[2]*t1[3] + cc[11]*ww[11]*t0[3]*t1[3] + cc[12]*ww[12]*t0[4]*t1[3] + cc[13]*ww[13]*t0[5]*t1[3] + cc[14]*ww[14]*t0[6]*t1[3] +
- + cc[ 3]*ww[ 3]*t0[1]*t1[4] + cc[ 8]*ww[ 8]*t0[2]*t1[4] + cc[12]*ww[12]*t0[3]*t1[4] + cc[15]*ww[15]*t0[4]*t1[4] + cc[16]*ww[16]*t0[5]*t1[4] + cc[17]*ww[17]*t0[6]*t1[4] +
- + cc[ 4]*ww[ 4]*t0[1]*t1[5] + cc[ 9]*ww[ 9]*t0[2]*t1[5] + cc[13]*ww[13]*t0[3]*t1[5] + cc[16]*ww[16]*t0[4]*t1[5] + cc[18]*ww[18]*t0[5]*t1[5] + cc[19]*ww[19]*t0[6]*t1[5] +
- + cc[ 5]*ww[ 5]*t0[1]*t1[6] + cc[10]*ww[10]*t0[2]*t1[6] + cc[14]*ww[14]*t0[3]*t1[6] + cc[17]*ww[17]*t0[4]*t1[6] + cc[19]*ww[19]*t0[5]*t1[6] + cc[20]*ww[20]*t0[6]*t1[6]);
+ out[ii] = (+cc[0] * ww[0] * t0[1] * t1[1] + cc[1] * ww[1] * t0[2] * t1[1]
+ + cc[2] * ww[2] * t0[3] * t1[1] + cc[3] * ww[3] * t0[4] * t1[1]
+ + cc[4] * ww[4] * t0[5] * t1[1] + cc[5] * ww[5] * t0[6] * t1[1]
+ + +cc[1] * ww[1] * t0[1] * t1[2] + cc[6] * ww[6] * t0[2] * t1[2]
+ + cc[7] * ww[7] * t0[3] * t1[2] + cc[8] * ww[8] * t0[4] * t1[2]
+ + cc[9] * ww[9] * t0[5] * t1[2] + cc[10] * ww[10] * t0[6] * t1[2]
+ + +cc[2] * ww[2] * t0[1] * t1[3] + cc[7] * ww[7] * t0[2] * t1[3]
+ + cc[11] * ww[11] * t0[3] * t1[3] + cc[12] * ww[12] * t0[4] * t1[3]
+ + cc[13] * ww[13] * t0[5] * t1[3] + cc[14] * ww[14] * t0[6] * t1[3]
+ + +cc[3] * ww[3] * t0[1] * t1[4] + cc[8] * ww[8] * t0[2] * t1[4]
+ + cc[12] * ww[12] * t0[3] * t1[4] + cc[15] * ww[15] * t0[4] * t1[4]
+ + cc[16] * ww[16] * t0[5] * t1[4] + cc[17] * ww[17] * t0[6] * t1[4]
+ + +cc[4] * ww[4] * t0[1] * t1[5] + cc[9] * ww[9] * t0[2] * t1[5]
+ + cc[13] * ww[13] * t0[3] * t1[5] + cc[16] * ww[16] * t0[4] * t1[5]
+ + cc[18] * ww[18] * t0[5] * t1[5] + cc[19] * ww[19] * t0[6] * t1[5]
+ + +cc[5] * ww[5] * t0[1] * t1[6] + cc[10] * ww[10] * t0[2] * t1[6]
+ + cc[14] * ww[14] * t0[3] * t1[6] + cc[17] * ww[17] * t0[4] * t1[6]
+ + cc[19] * ww[19] * t0[5] * t1[6] + cc[20] * ww[20] * t0[6] * t1[6]);
/* 0:xxxx 1:xxxy 2:xxxz 3:xxyy 4:xxyz 5:xxzz
* 6:xyxy 7:xyxz 8:xyyy 9:xyyz 10:xyzz
Modified: teem/trunk/src/ten/test/igrt.c
===================================================================
--- teem/trunk/src/ten/test/igrt.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/igrt.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -17,7 +17,6 @@
along with this library; if not, see <https://www.gnu.org/licenses/>.
*/
-
#include "../ten.h"
const char *info = ("tests invariant grads and rotation tangents.");
@@ -24,36 +23,32 @@
int
main(int argc, const char *argv[]) {
- const char *me;
- hestOpt *hopt=NULL;
- airArray *mop;
+ const char *me = argv[0];
+ hestOpt *hopt = NULL;
+ airArray *mop = airMopNew();
- double _ten[6], ten[7], minnorm, igrt[6][7], eval[3], evec[9],
- pp[3], qq[4], rot[9], matA[9], matB[9], tmp;
- int doK, ret, ii, jj;
- mop = airMopNew();
-
- me = argv[0];
- hestOptAdd(&hopt, NULL, "tensor", airTypeDouble, 6, 6, _ten, NULL,
- "tensor value");
- hestOptAdd(&hopt, "mn", "minnorm", airTypeDouble, 1, 1, &minnorm,
- "0.00001",
+ double _ten[6];
+ hestOptAdd_N_Double(&hopt, NULL, "tensor", 6, _ten, NULL, "tensor value");
+ double minnorm;
+ hestOptAdd(&hopt, "mn", "minnorm", airTypeDouble, 1, 1, &minnorm, "0.00001",
"minimum norm before special handling");
- hestOptAdd(&hopt, "k", NULL, airTypeInt, 0, 0, &doK, NULL,
- "Use K invariants, instead of R (the default)");
- hestOptAdd(&hopt, "p", "x y z", airTypeDouble, 3, 3, pp, "0 0 0",
- "location in quaternion quotient space");
- hestParseOrDie(hopt, argc-1, argv+1, NULL,
- me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
+ int doK;
+ hestOptAdd_Flag(&hopt, "k", &doK, "Use K invariants, instead of R (the default)");
+ double pp[3];
+ hestOptAdd_3_Double(&hopt, "p", "x y z", pp, "0 0 0",
+ "location in quaternion quotient space");
+ hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
- ELL_6V_COPY(ten+1, _ten);
+ double ten[7];
+ ELL_6V_COPY(ten + 1, _ten);
ten[0] = 1.0;
- fprintf(stderr, "input tensor = %f %f %f %f %f %f\n",
- ten[1], ten[2], ten[3], ten[4], ten[5], ten[6]);
+ fprintf(stderr, "input tensor = %f %f %f %f %f %f\n", ten[1], ten[2], ten[3],
+ ten[4], ten[5], ten[6]);
+ double qq[4], rot[9], matA[9], matB[9], tmp;
ELL_4V_SET(qq, 1, pp[0], pp[1], pp[2]);
ELL_4V_NORM(qq, qq, tmp);
ell_q_to_3m_d(rot, qq);
@@ -63,14 +58,13 @@
ELL_3M_MUL(matA, matB, rot);
TEN_M2T(ten, matA);
- fprintf(stderr, "rotated tensor = %f %f %f %f %f %f\n",
- ten[1], ten[2], ten[3], ten[4], ten[5], ten[6]);
+ fprintf(stderr, "rotated tensor = %f %f %f %f %f %f\n", ten[1], ten[2], ten[3],
+ ten[4], ten[5], ten[6]);
- ret = tenEigensolve_d(eval, evec, ten);
- fprintf(stderr, "eigensystem: %s: %g %g %g\n",
- airEnumDesc(ell_cubic_root, ret),
+ double igrt[6][7], eval[3], evec[9];
+ int ret = tenEigensolve_d(eval, evec, ten);
+ fprintf(stderr, "eigensystem: %s: %g %g %g\n", airEnumDesc(ell_cubic_root, ret),
eval[0], eval[1], eval[2]);
-
if (doK) {
tenInvariantGradientsK_d(igrt[0], igrt[1], igrt[2], ten, minnorm);
} else {
@@ -79,32 +73,25 @@
tenRotationTangents_d(igrt[3], igrt[4], igrt[5], evec);
fprintf(stderr, "invariant gradients and rotation tangents:\n");
- for (ii=0; ii<=2; ii++) {
- fprintf(stderr, " %s_%d: (norm=%g) %f %f %f %f %f %f\n",
- doK ? "K" : "R", ii+1,
- TEN_T_NORM(igrt[ii]),
- igrt[ii][1], igrt[ii][2], igrt[ii][3],
- igrt[ii][4], igrt[ii][5],
- igrt[ii][6]);
+ for (int ii = 0; ii <= 2; ii++) {
+ fprintf(stderr, " %s_%d: (norm=%g) %f %f %f %f %f %f\n", doK ? "K" : "R",
+ ii + 1, TEN_T_NORM(igrt[ii]), igrt[ii][1], igrt[ii][2], igrt[ii][3],
+ igrt[ii][4], igrt[ii][5], igrt[ii][6]);
}
- for (ii=3; ii<=5; ii++) {
- fprintf(stderr, "phi_%d: (norm=%g) %f %f %f %f %f %f\n",
- ii-2,
- TEN_T_NORM(igrt[ii]),
- igrt[ii][1], igrt[ii][2], igrt[ii][3],
- igrt[ii][4], igrt[ii][5],
- igrt[ii][6]);
+ for (int ii = 3; ii <= 5; ii++) {
+ fprintf(stderr, "phi_%d: (norm=%g) %f %f %f %f %f %f\n", ii - 2,
+ TEN_T_NORM(igrt[ii]), igrt[ii][1], igrt[ii][2], igrt[ii][3], igrt[ii][4],
+ igrt[ii][5], igrt[ii][6]);
}
fprintf(stderr, "dot products:\n");
- for (ii=0; ii<=5; ii++) {
- for (jj=ii+1; jj<=5; jj++) {
+ for (int ii = 0; ii <= 5; ii++) {
+ for (int jj = ii + 1; jj <= 5; jj++) {
fprintf(stderr, "%d,%d==%f ", ii, jj, TEN_T_DOT(igrt[ii], igrt[jj]));
}
fprintf(stderr, "\n");
}
-
airMopOkay(mop);
return 0;
}
Modified: teem/trunk/src/ten/test/odf-hist.c
===================================================================
--- teem/trunk/src/ten/test/odf-hist.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/odf-hist.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -27,28 +27,31 @@
hestOpt *hopt = NULL;
airArray *mop;
- char *errS, *outS, *covarS;
- Nrrd *_nodf, *nvec, *nhist, *ncovar;
- unsigned int bins;
+ char *errS;
+ Nrrd *nhist, *ncovar;
size_t size[NRRD_DIM_MAX];
- float min;
mop = airMopNew();
me = argv[0];
- hestOptAdd(&hopt, "i", "odf", airTypeOther, 1, 1, &_nodf, NULL,
- "ODF volume to analyze", NULL, NULL, nrrdHestNrrd);
- hestOptAdd(&hopt, "v", "odf", airTypeOther, 1, 1, &nvec, NULL,
- "list of vectors by which odf is sampled", NULL, NULL, nrrdHestNrrd);
- hestOptAdd(&hopt, "min", "min", airTypeFloat, 1, 1, &min, "0.0",
- "ODF values below this are ignored, and per-voxel ODF is "
- "normalized to have sum 1.0. Use \"nan\" to subtract out "
- "the per-voxel min.");
- hestOptAdd(&hopt, "b", "bins", airTypeUInt, 1, 1, &bins, "128",
- "number of bins in histograms");
- hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", "output file");
- hestOptAdd(&hopt, "co", "covariance out", airTypeString, 1, 1, &covarS, "covar.nrrd",
- "covariance output file");
+ Nrrd *_nodf;
+ hestOptAdd_1_Other(&hopt, "i", "odf", &_nodf, NULL, "ODF volume to analyze",
+ nrrdHestNrrd);
+ Nrrd *nvec;
+ hestOptAdd_1_Other(&hopt, "v", "odf", &nvec, NULL,
+ "list of vectors by which odf is sampled", nrrdHestNrrd);
+ float min;
+ hestOptAdd_1_Float(&hopt, "min", "min", &min, "0.0",
+ "ODF values below this are ignored, and per-voxel ODF is "
+ "normalized to have sum 1.0. Use \"nan\" to subtract out "
+ "the per-voxel min.");
+ unsigned int bins;
+ hestOptAdd_1_UInt(&hopt, "b", "bins", &bins, "128", "number of bins in histograms");
+ char *outS;
+ hestOptAdd_1_String(&hopt, "o", "nout", &outS, "-", "output file");
+ char *covarS;
+ hestOptAdd_1_String(&hopt, "co", "covariance out", &covarS, "covar.nrrd",
+ "covariance output file");
hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
Modified: teem/trunk/src/ten/test/teigen.c
===================================================================
--- teem/trunk/src/ten/test/teigen.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/teigen.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -17,46 +17,29 @@
along with this library; if not, see <https://www.gnu.org/licenses/>.
*/
-
#include "../ten.h"
const char *info = ("tests tenEigensolve_d and new stand-alone function.");
-#define ROOT_TRIPLE 2 /* ell_cubic_root_triple */
-#define ROOT_SINGLE_DOUBLE 3 /* ell_cubic_root_single_double */
-#define ROOT_THREE 4 /* ell_cubic_root_three */
+#define ROOT_TRIPLE 2 /* ell_cubic_root_triple */
+#define ROOT_SINGLE_DOUBLE 3 /* ell_cubic_root_single_double */
+#define ROOT_THREE 4 /* ell_cubic_root_three */
-#define ABS(a) (((a) > 0.0f ? (a) : -(a)))
-#define VEC_SET(v, a, b, c) \
- ((v)[0] = (a), (v)[1] = (b), (v)[2] = (c))
-#define VEC_DOT(v1, v2) \
- ((v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2])
-#define VEC_CROSS(v3, v1, v2) \
- ((v3)[0] = (v1)[1]*(v2)[2] - (v1)[2]*(v2)[1], \
- (v3)[1] = (v1)[2]*(v2)[0] - (v1)[0]*(v2)[2], \
- (v3)[2] = (v1)[0]*(v2)[1] - (v1)[1]*(v2)[0])
-#define VEC_ADD(v1, v2) \
- ((v1)[0] += (v2)[0], \
- (v1)[1] += (v2)[1], \
- (v1)[2] += (v2)[2])
-#define VEC_SUB(v1, v2) \
- ((v1)[0] -= (v2)[0], \
- (v1)[1] -= (v2)[1], \
- (v1)[2] -= (v2)[2])
-#define VEC_SCL(v1, s) \
- ((v1)[0] *= (s), \
- (v1)[1] *= (s), \
- (v1)[2] *= (s))
-#define VEC_LEN(v) (sqrt(VEC_DOT(v,v)))
-#define VEC_NORM(v, len) ((len) = VEC_LEN(v), VEC_SCL(v, 1.0/len))
-#define VEC_SCL_SUB(v1, s, v2) \
- ((v1)[0] -= (s)*(v2)[0], \
- (v1)[1] -= (s)*(v2)[1], \
- (v1)[2] -= (s)*(v2)[2])
-#define VEC_COPY(v1, v2) \
- ((v1)[0] = (v2)[0], \
- (v1)[1] = (v2)[1], \
- (v1)[2] = (v2)[2])
+#define ABS(a) (((a) > 0.0f ? (a) : -(a)))
+#define VEC_SET(v, a, b, c) ((v)[0] = (a), (v)[1] = (b), (v)[2] = (c))
+#define VEC_DOT(v1, v2) ((v1)[0] * (v2)[0] + (v1)[1] * (v2)[1] + (v1)[2] * (v2)[2])
+#define VEC_CROSS(v3, v1, v2) \
+ ((v3)[0] = (v1)[1] * (v2)[2] - (v1)[2] * (v2)[1], \
+ (v3)[1] = (v1)[2] * (v2)[0] - (v1)[0] * (v2)[2], \
+ (v3)[2] = (v1)[0] * (v2)[1] - (v1)[1] * (v2)[0])
+#define VEC_ADD(v1, v2) ((v1)[0] += (v2)[0], (v1)[1] += (v2)[1], (v1)[2] += (v2)[2])
+#define VEC_SUB(v1, v2) ((v1)[0] -= (v2)[0], (v1)[1] -= (v2)[1], (v1)[2] -= (v2)[2])
+#define VEC_SCL(v1, s) ((v1)[0] *= (s), (v1)[1] *= (s), (v1)[2] *= (s))
+#define VEC_LEN(v) (sqrt(VEC_DOT(v, v)))
+#define VEC_NORM(v, len) ((len) = VEC_LEN(v), VEC_SCL(v, 1.0 / len))
+#define VEC_SCL_SUB(v1, s, v2) \
+ ((v1)[0] -= (s) * (v2)[0], (v1)[1] -= (s) * (v2)[1], (v1)[2] -= (s) * (v2)[2])
+#define VEC_COPY(v1, v2) ((v1)[0] = (v2)[0], (v1)[1] = (v2)[1], (v1)[2] = (v2)[2])
/*
** All the three given vectors span only a 2D space, and this finds
@@ -65,8 +48,7 @@
** products to line up before summing.
*/
void
-nullspace1(double ret[3],
- const double r0[3], const double r1[3], const double r2[3]) {
+nullspace1(double ret[3], const double r0[3], const double r1[3], const double r2[3]) {
double crs[3];
/* ret = r0 x r1 */
@@ -96,8 +78,8 @@
** mutually vectors perpendicular to that span
*/
void
-nullspace2(double reta[3], double retb[3],
- const double r0[3], const double r1[3], const double r2[3]) {
+nullspace2(double reta[3], double retb[3], const double r0[3], const double r1[3],
+ const double r2[3]) {
double sqr[3], sum[3];
int idx;
@@ -114,14 +96,12 @@
}
/* find largest component, to get most stable expression for a
perpendicular vector */
- sqr[0] = sum[0]*sum[0];
- sqr[1] = sum[1]*sum[1];
- sqr[2] = sum[2]*sum[2];
+ sqr[0] = sum[0] * sum[0];
+ sqr[1] = sum[1] * sum[1];
+ sqr[2] = sum[2] * sum[2];
idx = 0;
- if (sqr[0] < sqr[1])
- idx = 1;
- if (sqr[idx] < sqr[2])
- idx = 2;
+ if (sqr[0] < sqr[1]) idx = 1;
+ if (sqr[idx] < sqr[2]) idx = 2;
/* reta will be perpendicular to sum */
if (0 == idx) {
VEC_SET(reta, sum[1] - sum[2], -sum[0], sum[0]);
@@ -170,10 +150,8 @@
**
*/
int
-evals(double eval[3],
- const double _M00, const double _M01, const double _M02,
- const double _M11, const double _M12,
- const double _M22) {
+evals(double eval[3], const double _M00, const double _M01, const double _M02,
+ const double _M11, const double _M12, const double _M22) {
#include "teigen-evals-A.c"
@@ -183,14 +161,11 @@
}
int
-evals_evecs(double eval[3], double evec[9],
- const double _M00, const double _M01, const double _M02,
- const double _M11, const double _M12,
- const double _M22) {
+evals_evecs(double eval[3], double evec[9], const double _M00, const double _M01,
+ const double _M02, const double _M11, const double _M12, const double _M22) {
double r0[3], r1[3], r2[3], crs[3], len, dot;
- double mean, norm, rnorm, Q, R, QQQ, D, theta,
- M00, M01, M02, M11, M12, M22;
+ double mean, norm, rnorm, Q, R, QQQ, D, theta, M00, M01, M02, M11, M12, M22;
double epsilon = 1.0E-12;
int roots;
@@ -206,7 +181,7 @@
** subtract out the eigenvalue mean (will add back to evals later);
** helps with numerical stability
*/
- mean = (M00 + M11 + M22)/3.0;
+ mean = (M00 + M11 + M22) / 3.0;
M00 -= mean;
M11 -= mean;
M22 -= mean;
@@ -215,10 +190,9 @@
** divide out L2 norm of eigenvalues (will multiply back later);
** this too seems to help with stability
*/
- norm = sqrt(M00*M00 + 2*M01*M01 + 2*M02*M02 +
- M11*M11 + 2*M12*M12 +
- M22*M22);
- rnorm = norm ? 1.0/norm : 1.0;
+ norm = sqrt(M00 * M00 + 2 * M01 * M01 + 2 * M02 * M02 + M11 * M11 + 2 * M12 * M12
+ + M22 * M22);
+ rnorm = norm ? 1.0 / norm : 1.0;
M00 *= rnorm;
M01 *= rnorm;
M02 *= rnorm;
@@ -228,21 +202,22 @@
/* this code is a mix of prior Teem code and ideas from Eberly's
"Eigensystems for 3 x 3 Symmetric Matrices (Revisited)" */
- Q = (M01*M01 + M02*M02 + M12*M12 - M00*M11 - M00*M22 - M11*M22)/3.0;
- QQQ = Q*Q*Q;
- R = (M00*M11*M22 + M02*(2*M01*M12 - M02*M11)
- - M00*M12*M12 - M01*M01*M22)/2.0;
- D = QQQ - R*R;
+ Q = (M01 * M01 + M02 * M02 + M12 * M12 - M00 * M11 - M00 * M22 - M11 * M22) / 3.0;
+ QQQ = Q * Q * Q;
+ R = (M00 * M11 * M22 + M02 * (2 * M01 * M12 - M02 * M11) - M00 * M12 * M12
+ - M01 * M01 * M22)
+ / 2.0;
+ D = QQQ - R * R;
if (D > epsilon) {
/* three distinct roots- this is the most common case */
double mm, ss, cc;
- theta = atan2(sqrt(D), R)/3.0;
+ theta = atan2(sqrt(D), R) / 3.0;
mm = sqrt(Q);
ss = sin(theta);
cc = cos(theta);
- eval[0] = 2*mm*cc;
- eval[1] = mm*(-cc + sqrt(3.0)*ss);
- eval[2] = mm*(-cc - sqrt(3.0)*ss);
+ eval[0] = 2 * mm * cc;
+ eval[1] = mm * (-cc + sqrt(3.0) * ss);
+ eval[2] = mm * (-cc - sqrt(3.0) * ss);
roots = ROOT_THREE;
/* else D is near enough to zero */
} else if (R < -epsilon || epsilon < R) {
@@ -250,13 +225,13 @@
/* one double root and one single root */
U = airCbrt(R); /* cube root function */
if (U > 0) {
- eval[0] = 2*U;
+ eval[0] = 2 * U;
eval[1] = -U;
eval[2] = -U;
} else {
eval[0] = -U;
eval[1] = -U;
- eval[2] = 2*U;
+ eval[2] = 2 * U;
}
roots = ROOT_SINGLE_DOUBLE;
} else {
@@ -271,57 +246,76 @@
VEC_SET(r1, M01, 0.0, M12);
VEC_SET(r2, M02, M12, 0.0);
if (ROOT_THREE == roots) {
- r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0];
- nullspace1(evec+0, r0, r1, r2);
- r0[0] = M00 - eval[1]; r1[1] = M11 - eval[1]; r2[2] = M22 - eval[1];
- nullspace1(evec+3, r0, r1, r2);
- r0[0] = M00 - eval[2]; r1[1] = M11 - eval[2]; r2[2] = M22 - eval[2];
- nullspace1(evec+6, r0, r1, r2);
+ r0[0] = M00 - eval[0];
+ r1[1] = M11 - eval[0];
+ r2[2] = M22 - eval[0];
+ nullspace1(evec + 0, r0, r1, r2);
+ r0[0] = M00 - eval[1];
+ r1[1] = M11 - eval[1];
+ r2[2] = M22 - eval[1];
+ nullspace1(evec + 3, r0, r1, r2);
+ r0[0] = M00 - eval[2];
+ r1[1] = M11 - eval[2];
+ r2[2] = M22 - eval[2];
+ nullspace1(evec + 6, r0, r1, r2);
} else if (ROOT_SINGLE_DOUBLE == roots) {
if (eval[1] == eval[2]) {
/* one big (eval[0]) , two small (eval[1,2]) */
- r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0];
- nullspace1(evec+0, r0, r1, r2);
- r0[0] = M00 - eval[1]; r1[1] = M11 - eval[1]; r2[2] = M22 - eval[1];
- nullspace2(evec+3, evec+6, r0, r1, r2);
- }
- else {
+ r0[0] = M00 - eval[0];
+ r1[1] = M11 - eval[0];
+ r2[2] = M22 - eval[0];
+ nullspace1(evec + 0, r0, r1, r2);
+ r0[0] = M00 - eval[1];
+ r1[1] = M11 - eval[1];
+ r2[2] = M22 - eval[1];
+ nullspace2(evec + 3, evec + 6, r0, r1, r2);
+ } else {
/* two big (eval[0,1]), one small (eval[2]) */
- r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0];
- nullspace2(evec+0, evec+3, r0, r1, r2);
- r0[0] = M00 - eval[2]; r1[1] = M11 - eval[2]; r2[2] = M22 - eval[2];
- nullspace1(evec+6, r0, r1, r2);
+ r0[0] = M00 - eval[0];
+ r1[1] = M11 - eval[0];
+ r2[2] = M22 - eval[0];
+ nullspace2(evec + 0, evec + 3, r0, r1, r2);
+ r0[0] = M00 - eval[2];
+ r1[1] = M11 - eval[2];
+ r2[2] = M22 - eval[2];
+ nullspace1(evec + 6, r0, r1, r2);
}
} else {
/* ROOT_TRIPLE == roots; use any basis for eigenvectors */
- VEC_SET(evec+0, 1, 0, 0);
- VEC_SET(evec+3, 0, 1, 0);
- VEC_SET(evec+6, 0, 0, 1);
+ VEC_SET(evec + 0, 1, 0, 0);
+ VEC_SET(evec + 3, 0, 1, 0);
+ VEC_SET(evec + 6, 0, 0, 1);
}
/* we always make sure its really orthonormal; keeping fixed the
eigenvector associated with the largest-magnitude eigenvalue */
if (ABS(eval[0]) > ABS(eval[2])) {
/* normalize evec+0 but don't move it */
- VEC_NORM(evec+0, len);
- dot = VEC_DOT(evec+0, evec+3); VEC_SCL_SUB(evec+3, dot, evec+0);
- VEC_NORM(evec+3, len);
- dot = VEC_DOT(evec+0, evec+6); VEC_SCL_SUB(evec+6, dot, evec+0);
- dot = VEC_DOT(evec+3, evec+6); VEC_SCL_SUB(evec+6, dot, evec+3);
- VEC_NORM(evec+6, len);
+ VEC_NORM(evec + 0, len);
+ dot = VEC_DOT(evec + 0, evec + 3);
+ VEC_SCL_SUB(evec + 3, dot, evec + 0);
+ VEC_NORM(evec + 3, len);
+ dot = VEC_DOT(evec + 0, evec + 6);
+ VEC_SCL_SUB(evec + 6, dot, evec + 0);
+ dot = VEC_DOT(evec + 3, evec + 6);
+ VEC_SCL_SUB(evec + 6, dot, evec + 3);
+ VEC_NORM(evec + 6, len);
} else {
/* normalize evec+6 but don't move it */
- VEC_NORM(evec+6, len);
- dot = VEC_DOT(evec+6, evec+3); VEC_SCL_SUB(evec+3, dot, evec+6);
- VEC_NORM(evec+3, len);
- dot = VEC_DOT(evec+3, evec+0); VEC_SCL_SUB(evec+0, dot, evec+3);
- dot = VEC_DOT(evec+6, evec+0); VEC_SCL_SUB(evec+0, dot, evec+6);
- VEC_NORM(evec+0, len);
+ VEC_NORM(evec + 6, len);
+ dot = VEC_DOT(evec + 6, evec + 3);
+ VEC_SCL_SUB(evec + 3, dot, evec + 6);
+ VEC_NORM(evec + 3, len);
+ dot = VEC_DOT(evec + 3, evec + 0);
+ VEC_SCL_SUB(evec + 0, dot, evec + 3);
+ dot = VEC_DOT(evec + 6, evec + 0);
+ VEC_SCL_SUB(evec + 0, dot, evec + 6);
+ VEC_NORM(evec + 0, len);
}
/* to be nice, make it right-handed */
- VEC_CROSS(crs, evec+0, evec+3);
- if (0 > VEC_DOT(crs, evec+6)) {
- VEC_SCL(evec+6, -1);
+ VEC_CROSS(crs, evec + 0, evec + 3);
+ if (0 > VEC_DOT(crs, evec + 6)) {
+ VEC_SCL(evec + 6, -1);
}
/* multiply back by eigenvalue L2 norm */
@@ -337,7 +331,6 @@
return roots;
}
-
void
testeigen(double tt[7], double eval[3], double evec[9]) {
double mat[9], dot[3], cross[3];
@@ -345,17 +338,14 @@
TEN_T2M(mat, tt);
printf("evals %g %g %g\n", eval[0], eval[1], eval[2]);
- printf("evec0 (%g) %g %g %g\n",
- ELL_3V_LEN(evec + 0), evec[0], evec[1], evec[2]);
- printf("evec1 (%g) %g %g %g\n",
- ELL_3V_LEN(evec + 3), evec[3], evec[4], evec[5]);
- printf("evec2 (%g) %g %g %g\n",
- ELL_3V_LEN(evec + 6), evec[6], evec[7], evec[8]);
+ printf("evec0 (%g) %g %g %g\n", ELL_3V_LEN(evec + 0), evec[0], evec[1], evec[2]);
+ printf("evec1 (%g) %g %g %g\n", ELL_3V_LEN(evec + 3), evec[3], evec[4], evec[5]);
+ printf("evec2 (%g) %g %g %g\n", ELL_3V_LEN(evec + 6), evec[6], evec[7], evec[8]);
printf("Mv - lv: (len) X Y Z (should be ~zeros)\n");
- for (ii=0; ii<3; ii++) {
+ for (ii = 0; ii < 3; ii++) {
double uu[3], vv[3], dd[3];
- ELL_3MV_MUL(uu, mat, evec + 3*ii);
- ELL_3V_SCALE(vv, eval[ii], evec + 3*ii);
+ ELL_3MV_MUL(uu, mat, evec + 3 * ii);
+ ELL_3V_SCALE(vv, eval[ii], evec + 3 * ii);
ELL_3V_SUB(dd, uu, vv);
printf("%d: (%g) %g %g %g\n", ii, ELL_3V_LEN(dd), dd[0], dd[1], dd[2]);
}
@@ -362,10 +352,9 @@
dot[0] = ELL_3V_DOT(evec + 0, evec + 3);
dot[1] = ELL_3V_DOT(evec + 0, evec + 6);
dot[2] = ELL_3V_DOT(evec + 3, evec + 6);
- printf("pairwise dots: (%g) %g %g %g\n",
- ELL_3V_LEN(dot), dot[0], dot[1], dot[2]);
- ELL_3V_CROSS(cross, evec+0, evec+3);
- printf("right-handed: %g\n", ELL_3V_DOT(evec+6, cross));
+ printf("pairwise dots: (%g) %g %g %g\n", ELL_3V_LEN(dot), dot[0], dot[1], dot[2]);
+ ELL_3V_CROSS(cross, evec + 0, evec + 3);
+ printf("right-handed: %g\n", ELL_3V_DOT(evec + 6, cross));
return;
}
@@ -372,30 +361,29 @@
int
main(int argc, const char *argv[]) {
const char *me;
- hestOpt *hopt=NULL;
+ hestOpt *hopt = NULL;
airArray *mop;
- double _tt[6], tt[7], ss, pp[3], qq[4], rot[9], mat1[9], mat2[9], tmp,
- evalA[3], evecA[9], evalB[3], evecB[9];
- int roots;
-
mop = airMopNew();
me = argv[0];
- hestOptAdd(&hopt, NULL, "m00 m01 m02 m11 m12 m22",
- airTypeDouble, 6, 6, _tt, NULL, "symmtric matrix coeffs");
- hestOptAdd(&hopt, "p", "vec", airTypeDouble, 3, 3, pp, "0 0 0",
- "rotation as P vector");
- hestOptAdd(&hopt, "s", "scl", airTypeDouble, 1, 1, &ss, "1.0",
- "scaling");
- hestParseOrDie(hopt, argc-1, argv+1, NULL,
- me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
+ double _tt[6];
+ hestOptAdd_N_Double(&hopt, NULL, "m00 m01 m02 m11 m12 m22", 6, _tt, NULL,
+ "symmtric matrix coeffs");
+ double pp[3];
+ hestOptAdd_3_Double(&hopt, "p", "vec", pp, "0 0 0", "rotation as P vector");
+ double ss;
+ hestOptAdd_1_Double(&hopt, "s", "scl", &ss, "1.0", "scaling");
+ hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
+ double tt[7];
ELL_6V_COPY(tt + 1, _tt);
tt[0] = 1.0;
TEN_T_SCALE(tt, ss, tt);
+ double qq[4], rot[9], mat1[9], mat2[9], tmp, evalA[3], evecA[9], evalB[3], evecB[9];
+ int roots;
ELL_4V_SET(qq, 1, pp[0], pp[1], pp[2]);
ELL_4V_NORM(qq, qq, tmp);
ell_q_to_3m_d(rot, qq);
@@ -410,8 +398,8 @@
ell_3m_mul_d(mat1, mat2, rot);
TEN_M2T(tt, mat1);
- printf("input matrix = \n %g %g %g\n %g %g\n %g\n",
- tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
+ printf("input matrix = \n %g %g %g\n %g %g\n %g\n", tt[1], tt[2], tt[3], tt[4], tt[5],
+ tt[6]);
printf("================== tenEigensolve_d ==================\n");
roots = tenEigensolve_d(evalA, evecA, tt);
@@ -430,10 +418,9 @@
printf("================== new eigensolve ==================\n");
roots = evals(evalB, tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
- printf("%s roots: %g %g %g\n", airEnumStr(ell_cubic_root, roots),
- evalB[0], evalB[1], evalB[2]);
- roots = evals_evecs(evalB, evecB,
- tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
+ printf("%s roots: %g %g %g\n", airEnumStr(ell_cubic_root, roots), evalB[0], evalB[1],
+ evalB[2]);
+ roots = evals_evecs(evalB, evecB, tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
printf("%s roots\n", airEnumStr(ell_cubic_root, roots));
testeigen(tt, evalB, evecB);
Modified: teem/trunk/src/ten/test/tem.c
===================================================================
--- teem/trunk/src/ten/test/tem.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/tem.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -17,7 +17,6 @@
along with this library; if not, see <https://www.gnu.org/licenses/>.
*/
-
#include "../ten.h"
const char *info = ("Test EM bimodal histogram fitting.");
@@ -26,11 +25,9 @@
main(int argc, const char *argv[]) {
const char *me;
char *err;
- hestOpt *hopt=NULL;
+ hestOpt *hopt = NULL;
airArray *mop;
- Nrrd *nhisto;
tenEMBimodalParm *biparm;
- double minprob[2];
mop = airMopNew();
me = argv[0];
@@ -38,18 +35,16 @@
biparm = tenEMBimodalParmNew();
airMopAdd(mop, biparm, (airMopper)tenEMBimodalParmNix, airMopAlways);
- hestOptAdd(&hopt, NULL, "histogram", airTypeOther, 1, 1, &nhisto, NULL,
- "The 1-D histogram to analyize", NULL, NULL, nrrdHestNrrd);
- hestOptAdd(&hopt, "ts", "two stage", airTypeInt, 0, 0,
- &(biparm->twoStage), NULL,
- "use two-stage processing");
- hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &(biparm->verbose), "1",
- "verbosity level");
- hestOptAdd(&hopt, "mp", "minprob 1,2", airTypeDouble, 2, 2, minprob, "0 0",
- "minimum significant posterior probabilies, for first and "
- "second stages");
- hestParseOrDie(hopt, argc-1, argv+1, NULL,
- me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
+ Nrrd *nhisto;
+ hestOptAdd_1_Other(&hopt, NULL, "histogram", &nhisto, NULL,
+ "The 1-D histogram to analyize", nrrdHestNrrd);
+ hestOptAdd_Flag(&hopt, "ts", &(biparm->twoStage), "use two-stage processing");
+ hestOptAdd_1_Int(&hopt, "v", "verbose", &(biparm->verbose), "1", "verbosity level");
+ double minprob[2];
+ hestOptAdd_2_Double(&hopt, "mp", "minprob 1,2", minprob, "0 0",
+ "minimum significant posterior probabilies, for first and "
+ "second stages");
+ hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
@@ -63,14 +58,13 @@
return 1;
}
fprintf(stderr, "%s: bimodal histogram fit\n", me);
- fprintf(stderr, "material 1 (%g%%): mean = %g, stdv = %g\n",
- 100*(biparm->fraction1), biparm->mean1, biparm->stdv1);
+ fprintf(stderr, "material 1 (%g%%): mean = %g, stdv = %g\n", 100 * (biparm->fraction1),
+ biparm->mean1, biparm->stdv1);
fprintf(stderr, "material 2 (%g%%): mean = %g, stdv = %g\n",
- 100*(1 - biparm->fraction1), biparm->mean2, biparm->stdv2);
- fprintf(stderr, " ---> optimal threshold = %g (confidence = %g)\n",
- biparm->threshold, biparm->confidence);
+ 100 * (1 - biparm->fraction1), biparm->mean2, biparm->stdv2);
+ fprintf(stderr, " ---> optimal threshold = %g (confidence = %g)\n", biparm->threshold,
+ biparm->confidence);
airMopOkay(mop);
return 0;
}
-
Modified: teem/trunk/src/ten/test/tg.c
===================================================================
--- teem/trunk/src/ten/test/tg.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/tg.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -54,32 +54,33 @@
int
main(int argc, const char *argv[]) {
const char *me;
- char *err, *outS;
+ char *err;
hestOpt *hopt = NULL;
airArray *mop;
- int xi, yi, zi, samp;
- float *tdata;
- double clp[2], xyz[3], q[4], len;
- double mD[9], mRF[9], mRI[9], mT[9];
- Nrrd *nten;
mop = airMopNew();
me = argv[0];
- hestOptAdd(&hopt, "n", "# samples", airTypeInt, 1, 1, &samp, "4",
- "number of samples along each edge of cube");
- hestOptAdd(&hopt, "c", "cl cp", airTypeDouble, 2, 2, clp, NULL,
- "shape of tensor to use; \"cl\" and \"cp\" are cl1 "
- "and cp1 values, both in [0.0,1.0]");
- hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
- "output file to save tensors into");
+ int samp;
+ hestOptAdd_1_Int(&hopt, "n", "# samples", &samp, "4",
+ "number of samples along each edge of cube");
+ double clp[2];
+ hestOptAdd_2_Double(&hopt, "c", "cl cp", clp, NULL,
+ "shape of tensor to use; \"cl\" and \"cp\" are cl1 "
+ "and cp1 values, both in [0.0,1.0]");
+ char *outS;
+ hestOptAdd_1_String(&hopt, "o", "nout", &outS, "-",
+ "output file to save tensors into");
hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
- nten = nrrdNew();
+ Nrrd *nten = nrrdNew();
airMopAdd(mop, nten, (airMopper)nrrdNuke, airMopAlways);
+ float *tdata;
+ double xyz[3], q[4], len;
+ double mD[9], mRF[9], mRI[9], mT[9];
_clp2xyz(xyz, clp);
fprintf(stderr, "%s: want evals = %g %g %g\n", me, xyz[0], xyz[1], xyz[2]);
@@ -93,9 +94,9 @@
ELL_3M_IDENTITY_SET(mD);
ELL_3M_DIAG_SET(mD, xyz[0], xyz[1], xyz[2]);
tdata = (float *)nten->data;
- for (zi = 0; zi < samp; zi++) {
- for (yi = 0; yi < samp; yi++) {
- for (xi = 0; xi < samp; xi++) {
+ for (int zi = 0; zi < samp; zi++) {
+ for (int yi = 0; yi < samp; yi++) {
+ for (int xi = 0; xi < samp; xi++) {
q[0] = 1.0;
q[1] = AIR_AFFINE(-0.5, (float)xi, samp - 0.5, -1, 1);
q[2] = AIR_AFFINE(-0.5, (float)yi, samp - 0.5, -1, 1);
Modified: teem/trunk/src/ten/test/tqgl.c
===================================================================
--- teem/trunk/src/ten/test/tqgl.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/tqgl.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -17,22 +17,17 @@
along with this library; if not, see <https://www.gnu.org/licenses/>.
*/
-
#include "../ten.h"
#include "../privateTen.h"
/* BAD gordon */
extern double _tenQGL_Kdist(const double RThZA[3], const double RThZB[3]);
-extern void _tenQGL_Klog(double klog[3],
- const double RThZA[3], const double RThZB[3]);
-extern void _tenQGL_Kexp(double RThZB[3],
- const double RThZA[3], const double klog[3]);
+extern void _tenQGL_Klog(double klog[3], const double RThZA[3], const double RThZB[3]);
+extern void _tenQGL_Kexp(double RThZB[3], const double RThZA[3], const double klog[3]);
extern double _tenQGL_Rdist(const double RThPhA[3], const double RThPhB[3]);
-extern void _tenQGL_Rlog(double rlog[3],
- const double RThPhA[3], const double RThPhB[3]);
-extern void _tenQGL_Rexp(double RThPhB[3],
- const double RThPhA[3], const double rlog[3]);
+extern void _tenQGL_Rlog(double rlog[3], const double RThPhA[3], const double RThPhB[3]);
+extern void _tenQGL_Rexp(double RThPhB[3], const double RThPhA[3], const double rlog[3]);
/* normalized gradients of k or r invariants, in XYZ space,
to help determine if path is really a loxodrome */
@@ -40,8 +35,7 @@
kgrads(double grad[3][3], const double eval[3]) {
double rtz[3];
- tenTripleConvertSingle_d(rtz, tenTripleTypeRThetaZ,
- eval, tenTripleTypeEigenvalue);
+ tenTripleConvertSingle_d(rtz, tenTripleTypeRThetaZ, eval, tenTripleTypeEigenvalue);
ELL_3V_SET(grad[0], cos(rtz[1]), sin(rtz[1]), 0);
ELL_3V_SET(grad[1], -sin(rtz[1]), cos(rtz[1]), 0);
@@ -52,17 +46,13 @@
rgrads(double grad[3][3], const double eval[3]) {
double rtp[3];
- tenTripleConvertSingle_d(rtp, tenTripleTypeRThetaPhi,
- eval, tenTripleTypeEigenvalue);
+ tenTripleConvertSingle_d(rtp, tenTripleTypeRThetaPhi, eval, tenTripleTypeEigenvalue);
- ELL_3V_SET(grad[0],
- cos(rtp[1])*sin(rtp[2]),
- sin(rtp[1])*sin(rtp[2]),
- cos(rtp[2]));
+ ELL_3V_SET(grad[0], cos(rtp[1]) * sin(rtp[2]), sin(rtp[1]) * sin(rtp[2]), cos(rtp[2]));
ELL_3V_SET(grad[1], -sin(rtp[1]), cos(rtp[1]), 0);
ELL_3V_SET(grad[2],
- cos(rtp[1])*cos(rtp[2]),
- sin(rtp[1])*cos(rtp[2]),
+ cos(rtp[1]) * cos(rtp[2]),
+ sin(rtp[1]) * cos(rtp[2]),
-sin(rtp[2]));
}
@@ -73,67 +63,47 @@
int
main(int argc, const char *argv[]) {
const char *me;
- hestOpt *hopt=NULL;
- airArray *mop;
+ hestOpt *hopt = NULL;
- double tripA[3], tripB[3], evalA[3], evalB[3],
- rt_A[3], rt_B[3], trip[3], eval[3], lasteval[3], lastxyz[3],
- logAB[3], ndist;
- int ittype, ottype, ptype, rttype;
- unsigned int NN, ii;
- tenInterpParm *tip;
-
- void (*interp)(double oeval[3], const double evalA[3],
- const double evalB[3], const double tt);
- double (*qdist)(const double RTh_A[3], const double RTh_B[3]);
- void (*qlog)(double klog[3],
- const double RThZA[3], const double RThZB[3]);
- void (*qexp)(double RThZB[3],
- const double RThZA[3], const double klog[3]);
- void (*grads)(double grad[3][3], const double eval[3]);
-
me = argv[0];
- mop = airMopNew();
- tip = tenInterpParmNew();
+ airArray *mop = airMopNew();
+ tenInterpParm *tip = tenInterpParmNew();
airMopAdd(mop, tip, (airMopper)tenInterpParmNix, airMopAlways);
- hestOptAdd(&hopt, "a", "start", airTypeDouble, 3, 3, tripA, NULL,
- "start triple of values");
- hestOptAdd(&hopt, "b", "end", airTypeDouble, 3, 3, tripB, NULL,
- "end triple of values");
- hestOptAdd(&hopt, "it", "type", airTypeEnum, 1, 1, &ittype, NULL,
- "type of given start and end triples", NULL, tenTripleType);
- hestOptAdd(&hopt, "ot", "type", airTypeEnum, 1, 1, &ottype, NULL,
- "type of triples for output", NULL, tenTripleType);
- hestOptAdd(&hopt, "p", "type", airTypeEnum, 1, 1, &ptype, NULL,
- "type of path interpolation", NULL, tenInterpType);
- hestOptAdd(&hopt, "n", "# steps", airTypeUInt, 1, 1, &NN, "100",
- "number of steps along path");
+ double tripA[3];
+ hestOptAdd_3_Double(&hopt, "a", "start", tripA, NULL, "start triple of values");
+ double tripB[3];
+ hestOptAdd_3_Double(&hopt, "b", "end", tripB, NULL, "end triple of values");
+ int ittype;
+ hestOptAdd_1_Enum(&hopt, "it", "type", &ittype, NULL,
+ "type of given start and end triples", tenTripleType);
+ int ottype;
+ hestOptAdd_1_Enum(&hopt, "ot", "type", &ottype, NULL, "type of triples for output",
+ tenTripleType);
+ int ptype;
+ hestOptAdd_1_Enum(&hopt, "p", "type", &ptype, NULL, "type of path interpolation",
+ tenInterpType);
+ unsigned int NN;
+ hestOptAdd_1_UInt(&hopt, "n", "# steps", &NN, "100", "number of steps along path");
- hestOptAdd(&hopt, "v", "verbosity", airTypeInt, 1, 1,
- &(tip->verbose), "0", "verbosity");
- hestOptAdd(&hopt, "s", "stepsize", airTypeDouble, 1, 1,
- &(tip->convStep), "1", "step size in update");
- hestOptAdd(&hopt, "r", "recurse", airTypeInt, 0, 0,
- &(tip->enableRecurse), NULL,
+ hestOptAdd(&hopt, "v", "verbosity", airTypeInt, 1, 1, &(tip->verbose), "0",
+ "verbosity");
+ hestOptAdd(&hopt, "s", "stepsize", airTypeDouble, 1, 1, &(tip->convStep), "1",
+ "step size in update");
+ hestOptAdd(&hopt, "r", "recurse", airTypeInt, 0, 0, &(tip->enableRecurse), NULL,
"enable recursive solution, when useful");
- hestOptAdd(&hopt, "mn", "minnorm", airTypeDouble, 1, 1,
- &(tip->minNorm), "0.000001",
+ hestOptAdd(&hopt, "mn", "minnorm", airTypeDouble, 1, 1, &(tip->minNorm), "0.000001",
"minnorm of something");
- hestOptAdd(&hopt, "mi", "maxiter", airTypeUInt, 1, 1,
- &(tip->maxIter), "0",
+ hestOptAdd(&hopt, "mi", "maxiter", airTypeUInt, 1, 1, &(tip->maxIter), "0",
"if non-zero, max # iterations for computation");
- hestOptAdd(&hopt, "c", "conv", airTypeDouble, 1, 1,
- &(tip->convEps), "0.0001",
+ hestOptAdd(&hopt, "c", "conv", airTypeDouble, 1, 1, &(tip->convEps), "0.0001",
"convergence threshold of length fraction");
- hestParseOrDie(hopt, argc-1, argv+1, NULL,
- me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
+ hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
- if (!( tenInterpTypeQuatGeoLoxK == ptype
- || tenInterpTypeQuatGeoLoxR == ptype )) {
+ if (!(tenInterpTypeQuatGeoLoxK == ptype || tenInterpTypeQuatGeoLoxR == ptype)) {
fprintf(stderr, "%s: need type %s or %s, not %s\n", me,
airEnumStr(tenInterpType, tenInterpTypeQuatGeoLoxK),
airEnumStr(tenInterpType, tenInterpTypeQuatGeoLoxR),
@@ -142,6 +112,13 @@
return 1;
}
+ void (*interp)(double oeval[3], const double evalA[3], const double evalB[3],
+ const double tt);
+ double (*qdist)(const double RTh_A[3], const double RTh_B[3]);
+ void (*qlog)(double klog[3], const double RThZA[3], const double RThZB[3]);
+ void (*qexp)(double RThZB[3], const double RThZA[3], const double klog[3]);
+ void (*grads)(double grad[3][3], const double eval[3]);
+ int rttype;
if (tenInterpTypeQuatGeoLoxK == ptype) {
interp = tenQGLInterpTwoEvalK;
qdist = _tenQGL_Kdist;
@@ -159,30 +136,28 @@
}
fprintf(stderr, "%s: (%s) %f %f %f \n--%s--> %f %f %f\n", me,
- airEnumStr(tenTripleType, ittype),
- tripA[0], tripA[1], tripA[2],
- airEnumStr(tenInterpType, ptype),
- tripB[0], tripB[1], tripB[2]);
+ airEnumStr(tenTripleType, ittype), tripA[0], tripA[1], tripA[2],
+ airEnumStr(tenInterpType, ptype), tripB[0], tripB[1], tripB[2]);
+ double evalA[3], evalB[3], rt_A[3], rt_B[3], trip[3], eval[3], lasteval[3], lastxyz[3],
+ logAB[3];
tenTripleConvertSingle_d(evalA, tenTripleTypeEigenvalue, tripA, ittype);
tenTripleConvertSingle_d(evalB, tenTripleTypeEigenvalue, tripB, ittype);
tenTripleConvertSingle_d(rt_A, rttype, tripA, ittype);
tenTripleConvertSingle_d(rt_B, rttype, tripB, ittype);
- ndist = 0;
+ double ndist = 0;
ELL_3V_SET(lasteval, AIR_NAN, AIR_NAN, AIR_NAN);
ELL_3V_SET(lastxyz, AIR_NAN, AIR_NAN, AIR_NAN);
qlog(logAB, rt_A, rt_B);
- fprintf(stderr, "%s: log = %g %g %g (%g)\n", me,
- logAB[0], logAB[1], logAB[2], ELL_3V_LEN(logAB));
- for (ii=0; ii<NN; ii++) {
+ fprintf(stderr, "%s: log = %g %g %g (%g)\n", me, logAB[0], logAB[1], logAB[2],
+ ELL_3V_LEN(logAB));
+ for (unsigned int ii = 0; ii < NN; ii++) {
double tt, xyz[3], dot[3], ll[3], prayRT[3], prayO[3];
- tt = AIR_AFFINE(0, ii, NN-1, 0.0, 1.0);
+ tt = AIR_AFFINE(0, ii, NN - 1, 0.0, 1.0);
interp(eval, evalA, evalB, tt);
- tenTripleConvertSingle_d(trip, ottype,
- eval, tenTripleTypeEigenvalue);
- tenTripleConvertSingle_d(xyz, tenTripleTypeXYZ,
- eval, tenTripleTypeEigenvalue);
+ tenTripleConvertSingle_d(trip, ottype, eval, tenTripleTypeEigenvalue);
+ tenTripleConvertSingle_d(xyz, tenTripleTypeXYZ, eval, tenTripleTypeEigenvalue);
ELL_3V_SCALE(ll, tt, logAB);
qexp(prayRT, rt_A, ll);
tenTripleConvertSingle_d(prayO, ottype, prayRT, rttype);
@@ -198,17 +173,13 @@
} else {
ELL_3V_SET(dot, 0, 0, 0);
}
- printf("%03u %g %g %g %g %g %g 00 %g %g %g\n", ii,
- trip[0], prayO[0],
- trip[1], prayO[1],
- trip[2], prayO[2],
- dot[0], dot[1], dot[2]);
+ printf("%03u %g %g %g %g %g %g 00 %g %g %g\n", ii, trip[0], prayO[0],
+ trip[1], prayO[1], trip[2], prayO[2], dot[0], dot[1], dot[2]);
ELL_3V_COPY(lasteval, eval);
ELL_3V_COPY(lastxyz, xyz);
}
- fprintf(stderr, "%s: dist %g =?= %g\n", me,
- qdist(rt_A, rt_B), ndist);
+ fprintf(stderr, "%s: dist %g =?= %g\n", me, qdist(rt_A, rt_B), ndist);
airMopOkay(mop);
return 0;
Modified: teem/trunk/src/ten/test/tt.c
===================================================================
--- teem/trunk/src/ten/test/tt.c 2025-09-18 08:28:52 UTC (rev 7454)
+++ teem/trunk/src/ten/test/tt.c 2025-09-18 15:34:17 UTC (rev 7455)
@@ -103,45 +103,44 @@
int
main(int argc, const char *argv[]) {
- const char *me;
- char *err, *outS;
+ const char *me = argv[0];
+ char *err;
hestOpt *hopt = NULL;
- airArray *mop;
- int sx, sy, xi, yi, samp, version, whole, right;
- float *tdata;
- double p[3], xyz[3], q[4], len, hackcp = 0, maxca;
- double ca, cp, mD[9], mRF[9], mRI[9], mT[9], hack;
- Nrrd *nten;
- mop = airMopNew();
-
- me = argv[0];
- hestOptAdd(&hopt, "n", "# samples", airTypeInt, 1, 1, &samp, "4",
- "number of glyphs along each edge of triangle");
- hestOptAdd(&hopt, "p", "x y z", airTypeDouble, 3, 3, p, NULL,
- "location in quaternion quotient space");
- hestOptAdd(&hopt, "ca", "max ca", airTypeDouble, 1, 1, &maxca, "0.8",
- "maximum ca to use at bottom edge of triangle");
- hestOptAdd(&hopt, "r", NULL, airTypeInt, 0, 0, &right, NULL,
- "sample a right-triangle-shaped region, instead of "
- "a roughly equilateral triangle. ");
- hestOptAdd(&hopt, "w", NULL, airTypeInt, 0, 0, &whole, NULL,
- "sample the whole triangle of constant trace, "
- "instead of just the "
- "sixth of it in which the eigenvalues have the "
- "traditional sorted order. ");
- hestOptAdd(&hopt, "hack", "hack", airTypeDouble, 1, 1, &hack, "0.04",
- "this is a hack");
- hestOptAdd(&hopt, "v", "version", airTypeInt, 1, 1, &version, "1",
- "which version of the Westin metrics to use to parameterize "
- "triangle; \"1\" for ISMRM 97, \"2\" for MICCAI 99");
- hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
- "output file to save tensors into");
+ airArray *mop = airMopNew();
+ int samp;
+ hestOptAdd_1_Int(&hopt, "n", "# samples", &samp, "4",
+ "number of glyphs along each edge of triangle");
+ double p[3];
+ hestOptAdd_3_Double(&hopt, "p", "x y z", p, NULL,
+ "location in quaternion quotient space");
+ double maxca;
+ hestOptAdd_1_Double(&hopt, "ca", "max ca", &maxca, "0.8",
+ "maximum ca to use at bottom edge of triangle");
+ int right;
+ hestOptAdd_Flag(&hopt, "r", &right,
+ "sample a right-triangle-shaped region, instead of "
+ "a roughly equilateral triangle. ");
+ int whole;
+ hestOptAdd_Flag(&hopt, "w", &whole,
+ "sample the whole triangle of constant trace, "
+ "instead of just the "
+ "sixth of it in which the eigenvalues have the "
+ "traditional sorted order. ");
+ double hack;
+ hestOptAdd_1_Double(&hopt, "hack", "hack", &hack, "0.04", "this is a hack");
+ int version;
+ hestOptAdd_1_Int(&hopt, "v", "version", &version, "1",
+ "which version of the Westin metrics to use to parameterize "
+ "triangle; \"1\" for ISMRM 97, \"2\" for MICCAI 99");
+ char *outS;
+ hestOptAdd_1_String(&hopt, "o", "nout", &outS, "-",
+ "output file to save tensors into");
hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
- nten = nrrdNew();
+ Nrrd *nten = nrrdNew();
airMopAdd(mop, nten, (airMopper)nrrdNuke, airMopAlways);
if (!(1 == version || 2 == version)) {
@@ -149,6 +148,7 @@
airMopError(mop);
return 1;
}
+ int sx, sy;
if (right) {
sx = samp;
sy = (int)(1.0 * samp / sqrt(3.0));
@@ -163,6 +163,9 @@
airMopError(mop);
return 1;
}
+ float *tdata;
+ double xyz[3], q[4], len, hackcp = 0;
+ double ca, cp, mD[9], mRF[9], mRI[9], mT[9];
q[0] = 1.0;
q[1] = p[0];
q[2] = p[1];
@@ -252,7 +255,7 @@
nten->axis[2].spacing = (sx - 1) / (sqrt(3.0) * (sy - 1));
nten->axis[3].spacing = 1;
} else {
- for (yi = 0; yi < samp; yi++) {
+ for (int yi = 0; yi < samp; yi++) {
if (whole) {
ca = AIR_AFFINE(0, yi, samp - 1, 0.0, 1.0);
} else {
@@ -259,7 +262,7 @@
ca = AIR_AFFINE(0, yi, samp - 1, hack, maxca);
hackcp = AIR_AFFINE(0, yi, samp - 1, hack, 0);
}
- for (xi = 0; xi <= yi; xi++) {
+ for (int xi = 0; xi <= yi; xi++) {
if (whole) {
cp = AIR_AFFINE(0, xi, samp - 1, 0.0, 1.0);
} else {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 08:28:55
|
Revision: 7454
http://sourceforge.net/p/teem/code/7454
Author: kindlmann
Date: 2025-09-18 08:28:52 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
testing correctness of new hestSource airEnum
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-18 08:02:11 UTC (rev 7453)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-18 08:28:52 UTC (rev 7454)
@@ -31,18 +31,19 @@
static const airEnum _hestSource
= {.name = "source",
.M = 3,
- .str = (const char *[]){"(unknown_source)", //
- "default", //
- "command-line", //
- "response-file"},
+ .str = (const char *[]){"(unknown_source)", // 0
+ "default", // 1
+ "command-line", // 2
+ "response-file"}, // 3
.val = NULL,
.desc = (const char *[]){"unknown source", //
"default string in hestOpt", //
"argc/argv command-line", //
"a response file"},
- .strEqv = (const char *[]){"default", //
- "command-line", "cmdline", //
- "response-file", "respfile"},
+ .strEqv = (const char *[]){"default", //
+ "command-line", "cmdline", //
+ "response-file", "respfile", //
+ ""},
.valEqv = (const int[]){hestSourceDefault, //
hestSourceCommandLine, hestSourceCommandLine, //
hestSourceResponseFile, hestSourceResponseFile},
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-18 08:02:11 UTC (rev 7453)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-18 08:28:52 UTC (rev 7454)
@@ -21,6 +21,14 @@
int
main(int argc, const char **argv) {
+
+ // airEnumPrint(stdout, hestSource);
+ char enerr[AIR_STRLEN_LARGE + 1];
+ if (airEnumCheck(enerr, hestSource)) {
+ fprintf(stderr, "%s: problem:\n%s\n", argv[0], enerr);
+ exit(1);
+ }
+
int ret = 0;
hestOpt *opt = NULL;
hestParm *hparm = hestParmNew();
@@ -41,5 +49,6 @@
hestOptFree(opt);
hestParmFree(hparm);
+
exit(ret);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 08:02:14
|
Revision: 7453
http://sourceforge.net/p/teem/code/7453
Author: kindlmann
Date: 2025-09-18 08:02:11 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
renamed coilMethod->numParm --> parmNum, and used more uints
Modified Paths:
--------------
teem/trunk/src/coil/coil.h
teem/trunk/src/coil/methodsCoil.c
teem/trunk/src/coil/test/coiler.c
Modified: teem/trunk/src/coil/coil.h
===================================================================
--- teem/trunk/src/coil/coil.h 2025-09-18 07:36:02 UTC (rev 7452)
+++ teem/trunk/src/coil/coil.h 2025-09-18 08:02:11 UTC (rev 7453)
@@ -104,8 +104,8 @@
*/
typedef struct {
char name[AIR_STRLEN_SMALL + 1];
- int type; /* from coilMethodType* enum */
- int numParm; /* number of parameters we need */
+ int type; /* from coilMethodType* enum */
+ unsigned int parmNum; /* number of parameters we need */
} coilMethod;
/*
Modified: teem/trunk/src/coil/methodsCoil.c
===================================================================
--- teem/trunk/src/coil/methodsCoil.c 2025-09-18 07:36:02 UTC (rev 7452)
+++ teem/trunk/src/coil/methodsCoil.c 2025-09-18 08:02:11 UTC (rev 7453)
@@ -19,6 +19,8 @@
#include "coil.h"
+typedef unsigned int uint;
+
int /* Biff: 1 */
coilVolumeCheck(const Nrrd *nin, const coilKind *kind) {
static const char me[] = "coilVolumeCheck";
@@ -68,7 +70,7 @@
const coilMethod *method, unsigned int radius, unsigned int numThreads,
int verbose, double parm[COIL_PARMS_NUM]) {
static const char me[] = "coilContextAllSet";
- int someExist, allExist, baseDim, pi;
+ int someExist, allExist, baseDim;
size_t size[NRRD_DIM_MAX], sx, sy, sz;
double xsp, ysp, zsp;
airArray *mop;
@@ -110,9 +112,9 @@
mop = airMopNew();
/* set parms */
- for (pi = 0; pi < method->numParm; pi++) {
+ for (uint pi = 0; pi < method->parmNum; pi++) {
if (!AIR_EXISTS(parm[pi])) {
- biffAddf(COIL, "%s: parm[%d] (need %d) doesn't exist", me, pi, method->numParm);
+ biffAddf(COIL, "%s: parm[%u] (need %d) doesn't exist", me, pi, method->parmNum);
airMopError(mop);
return 1;
}
Modified: teem/trunk/src/coil/test/coiler.c
===================================================================
--- teem/trunk/src/coil/test/coiler.c 2025-09-18 07:36:02 UTC (rev 7452)
+++ teem/trunk/src/coil/test/coiler.c 2025-09-18 08:02:11 UTC (rev 7453)
@@ -24,51 +24,59 @@
int
main(int argc, const char *argv[]) {
const char *me;
- char *err, *outS;
+ char *err;
hestOpt *hopt = NULL;
airArray *mop;
- int numIters, numThreads, methodType, kindType, _parmLen, pi, radius, verbose;
- Nrrd *nin, *nout;
- coilContext *cctx;
- double *_parm, parm[COIL_PARMS_NUM];
-
mop = airMopNew();
me = argv[0];
- hestOptAdd(&hopt, "iter", "# iters", airTypeInt, 1, 1, &numIters, "5",
- "number of iterations to do processing for");
- hestOptAdd(&hopt, "nt", "# threads", airTypeInt, 1, 1, &numThreads, "5",
- "number of threads to run");
- hestOptAdd(&hopt, "k", "kind", airTypeEnum, 1, 1, &kindType, NULL,
- "what kind of volume is input", NULL, coilKindType);
- hestOptAdd(&hopt, "m", "method", airTypeEnum, 1, 1, &methodType, "test",
- "what kind of filtering to perform", NULL, coilMethodType);
- hestOptAdd(&hopt, "p", "parms", airTypeDouble, 1, -1, &_parm, NULL,
- "all the parameters required for filtering method", &_parmLen);
- hestOptAdd(&hopt, "r", "radius", airTypeInt, 1, 1, &radius, "1",
- "radius of filtering neighborhood");
- hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &verbose, "1", "verbosity level");
- hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &(nin), "", "input volume to filter",
- NULL, NULL, nrrdHestNrrdNoTTY);
- hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
- "output file to save filtering result into");
+ unsigned int numIters;
+ hestOptAdd_1_UInt(&hopt, "iter", "# iters", &numIters, "5",
+ "number of iterations to do processing for");
+ unsigned int numThreads;
+ hestOptAdd_1_UInt(&hopt, "nt", "# threads", &numThreads, "5",
+ "number of threads to run");
+ int kindType;
+ hestOptAdd_1_Enum(&hopt, "k", "kind", &kindType, NULL, //
+ "what kind of volume is input", coilKindType);
+ int methodType;
+ hestOptAdd_1_Enum(&hopt, "m", "method", &methodType, "test",
+ "what kind of filtering to perform", coilMethodType);
+ double *_parm;
+ unsigned int _parmLen;
+ hestOptAdd_Nv_Double(&hopt, "p", "parms", 1, -1, &_parm, NULL,
+ "all the parameters required for filtering method", //
+ &_parmLen);
+ int radius;
+ hestOptAdd_1_Int(&hopt, "r", "radius", &radius, "1",
+ "radius of filtering neighborhood");
+ int verbose;
+ hestOptAdd_1_Int(&hopt, "v", "verbose", &verbose, "1", //
+ "verbosity level");
+ Nrrd *nin;
+ hestOptAdd_1_Other(&hopt, "i", "nin", &nin, "", //
+ "input volume to filter", nrrdHestNrrdNoTTY);
+ char *outS;
+ hestOptAdd_1_String(&hopt, "o", "nout", &outS, "-",
+ "output file to save filtering result into");
hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
- cctx = coilContextNew();
+ coilContext *cctx = coilContextNew();
airMopAdd(mop, cctx, (airMopper)coilContextNix, airMopAlways);
- nout = nrrdNew();
+ Nrrd *nout = nrrdNew();
airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
- if (_parmLen != coilMethodArray[methodType]->numParm) {
- fprintf(stderr, "%s: %s method wants %d parms, but got %d\n", me,
- coilMethodArray[methodType]->name, coilMethodArray[methodType]->numParm,
+ if (_parmLen != coilMethodArray[methodType]->parmNum) {
+ fprintf(stderr, "%s: %s method wants %u parms, but got %u\n", me,
+ coilMethodArray[methodType]->name, coilMethodArray[methodType]->parmNum,
_parmLen);
airMopError(mop);
return 1;
}
- for (pi = 0; pi < _parmLen; pi++) {
+ double parm[COIL_PARMS_NUM];
+ for (unsigned int pi = 0; pi < _parmLen; pi++) {
parm[pi] = _parm[pi];
}
if (coilContextAllSet(cctx, nin, coilKindArray[kindType], coilMethodArray[methodType],
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 07:36:04
|
Revision: 7452
http://sourceforge.net/p/teem/code/7452
Author: kindlmann
Date: 2025-09-18 07:36:02 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
oops last commit was broken
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-18 07:32:03 UTC (rev 7451)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-18 07:36:02 UTC (rev 7452)
@@ -49,6 +49,9 @@
.sense = AIR_FALSE};
const airEnum *const hestSource = &_hestSource;
+// see documentation in parseHest.c
+#define ME ((hparm && hparm->verbosity) ? me : "")
+
int
hestSourceUser(int src) {
return (hestSourceCommandLine == src || hestSourceResponseFile == src);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 07:32:07
|
Revision: 7451
http://sourceforge.net/p/teem/code/7451
Author: kindlmann
Date: 2025-09-18 07:32:03 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
tweaks and moving _hestOptCheck from parseHest to methodsHest.c
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parseHest.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-18 07:22:10 UTC (rev 7450)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-18 07:32:03 UTC (rev 7451)
@@ -416,6 +416,234 @@
return NULL;
}
+/*
+_hestOptCheck() (formerly _hestPanic, in parseHest.c)
+
+This performs the validation of the given hestOpt array itself (not the command line to
+be parsed), with descriptive error messages sprintf'ed into err, if given. hestOptCheck()
+is the expected way for users to access this.
+
+Prior to 2023 code revisit; this used to set the "kind" in all the opts but now that is
+more appropriately done at the time the option is added (by hestOptAdd, hestOptAdd_nva,
+hestOptSingleSet, or hestOptAdd_*_*)
+*/
+int
+_hestOptCheck(const hestOpt *opt, char *err, const hestParm *hparm) {
+ /* see note on ME (at top) for why me[] ends with ": " */
+ static const char me[] = "_hestOptCheck: ";
+ char tbuff[AIR_STRLEN_HUGE + 1], *sep;
+ int numvar, opi, optNum;
+
+ optNum = hestOptNum(opt);
+ numvar = 0;
+ for (opi = 0; opi < optNum; opi++) {
+ if (!(AIR_IN_OP(airTypeUnknown, opt[opi].type, airTypeLast))) {
+ if (err)
+ sprintf(err, "%sopt[%d].type (%d) not in valid range [%d,%d]", ME, opi,
+ opt[opi].type, airTypeUnknown + 1, airTypeLast - 1);
+ else
+ fprintf(stderr, "%s: panic 0\n", me);
+ return 1;
+ }
+ if (!(opt[opi].valueP)) {
+ if (err)
+ sprintf(err, "%sopt[%d]'s valueP is NULL!", ME, opi);
+ else
+ fprintf(stderr, "%s: panic 0.5\n", me);
+ return 1;
+ }
+ if (-1 == opt[opi].kind) {
+ if (err)
+ sprintf(err, "%sopt[%d]'s min (%d) and max (%d) incompatible", ME, opi,
+ opt[opi].min, opt[opi].max);
+ else
+ fprintf(stderr, "%s: panic 1\n", me);
+ return 1;
+ }
+ if (5 == opt[opi].kind && !(opt[opi].sawP)) {
+ if (err)
+ sprintf(err,
+ "%shave multiple variable parameters, "
+ "but sawP is NULL",
+ ME);
+ else
+ fprintf(stderr, "%s: panic 2\n", me);
+ return 1;
+ }
+ if (airTypeEnum == opt[opi].type) {
+ if (!(opt[opi].enm)) {
+ if (err) {
+ sprintf(err,
+ "%sopt[%d] (%s) is type \"enum\", but no "
+ "airEnum pointer given",
+ ME, opi, opt[opi].flag ? opt[opi].flag : "?");
+ } else {
+ fprintf(stderr, "%s: panic 3\n", me);
+ }
+ return 1;
+ }
+ }
+ if (airTypeOther == opt[opi].type) {
+ if (!(opt[opi].CB)) {
+ if (err) {
+ sprintf(err,
+ "%sopt[%d] (%s) is type \"other\", but no "
+ "callbacks given",
+ ME, opi, opt[opi].flag ? opt[opi].flag : "?");
+ } else {
+ fprintf(stderr, "%s: panic 4\n", me);
+ }
+ return 1;
+ }
+ if (!(opt[opi].CB->size > 0)) {
+ if (err)
+ sprintf(err, "%sopt[%d]'s \"size\" (%d) invalid", ME, opi,
+ (int)(opt[opi].CB->size));
+ else
+ fprintf(stderr, "%s: panic 5\n", me);
+ return 1;
+ }
+ if (!(opt[opi].CB->type)) {
+ if (err)
+ sprintf(err, "%sopt[%d]'s \"type\" is NULL", ME, opi);
+ else
+ fprintf(stderr, "%s: panic 6\n", me);
+ return 1;
+ }
+ if (!(opt[opi].CB->parse)) {
+ if (err)
+ sprintf(err, "%sopt[%d]'s \"parse\" callback NULL", ME, opi);
+ else
+ fprintf(stderr, "%s: panic 7\n", me);
+ return 1;
+ }
+ if (opt[opi].CB->destroy && (sizeof(void *) != opt[opi].CB->size)) {
+ if (err)
+ sprintf(err,
+ "%sopt[%d] has a \"destroy\", but size %lu isn't "
+ "sizeof(void*)",
+ ME, opi, (unsigned long)(opt[opi].CB->size));
+ else
+ fprintf(stderr, "%s: panic 8\n", me);
+ return 1;
+ }
+ }
+ if (opt[opi].flag) {
+ strcpy(tbuff, opt[opi].flag);
+ if ((sep = strchr(tbuff, hparm->multiFlagSep))) {
+ *sep = '\0';
+ if (!(strlen(tbuff) && strlen(sep + 1))) {
+ if (err)
+ sprintf(err,
+ "%seither short (\"%s\") or long (\"%s\") flag"
+ " of opt[%d] is zero length",
+ ME, tbuff, sep + 1, opi);
+ else
+ fprintf(stderr, "%s: panic 9\n", me);
+ return 1;
+ }
+ if (hparm->respectDashDashHelp && !strcmp("help", sep + 1)) {
+ if (err)
+ sprintf(err,
+ "%slong \"--%s\" flag of opt[%d] is same as \"--help\" "
+ "that requested hparm->respectDashDashHelp handles separately",
+ ME, sep + 1, opi);
+ else
+ fprintf(stderr, "%s: panic 9.5\n", me);
+ return 1;
+ }
+ } else {
+ if (!strlen(opt[opi].flag)) {
+ if (err)
+ sprintf(err, "%sopt[%d].flag is zero length", ME, opi);
+ else
+ fprintf(stderr, "%s: panic 10\n", me);
+ return 1;
+ }
+ }
+ if (hparm->respectDashBraceComments
+ && (strchr(opt[opi].flag, '{') || strchr(opt[opi].flag, '}'))) {
+ if (err)
+ sprintf(err,
+ "%srequested hparm->respectDashBraceComments but opt[%d]'s flag "
+ "\"%s\" confusingly contains '{' or '}'",
+ ME, opi, opt[opi].flag);
+ else
+ fprintf(stderr, "%s: panic 10.5\n", me);
+ return 1;
+ }
+ if (4 == opt[opi].kind) {
+ if (!opt[opi].dflt) {
+ if (err)
+ sprintf(err,
+ "%sflagged single variable parameter must "
+ "specify a default",
+ ME);
+ else
+ fprintf(stderr, "%s: panic 11\n", me);
+ return 1;
+ }
+ if (!strlen(opt[opi].dflt)) {
+ if (err)
+ sprintf(err,
+ "%sflagged single variable parameter default "
+ "must be non-zero length",
+ ME);
+ else
+ fprintf(stderr, "%s: panic 12\n", me);
+ return 1;
+ }
+ }
+ /*
+ sprintf(tbuff, "-%s", opt[op].flag);
+ if (1 == sscanf(tbuff, "%f", &tmpF)) {
+ if (err)
+ sprintf(err, "%sopt[%d].flag (\"%s\") is numeric, bad news",
+ ME, op, opt[op].flag);
+ return 1;
+ }
+ */
+ }
+ if (1 == opt[opi].kind) {
+ if (!opt[opi].flag) {
+ if (err)
+ sprintf(err, "%sflags must have flags", ME);
+ else
+ fprintf(stderr, "%s: panic 13\n", me);
+ return 1;
+ }
+ } else {
+ if (!opt[opi].name) {
+ if (err)
+ sprintf(err, "%sopt[%d] isn't a flag: must have \"name\"", ME, opi);
+ else
+ fprintf(stderr, "%s: panic 14\n", me);
+ return 1;
+ }
+ }
+ if (4 == opt[opi].kind && !opt[opi].dflt) {
+ if (err)
+ sprintf(err,
+ "%sopt[%d] is single variable parameter, but "
+ "no default set",
+ ME, opi);
+ else
+ fprintf(stderr, "%s: panic 15\n", me);
+ return 1;
+ }
+ numvar += ((int)opt[opi].min < _hestMax(opt[opi].max)
+ && (NULL == opt[opi].flag)); /* HEY scrutinize casts */
+ }
+ if (numvar > 1) {
+ if (err)
+ sprintf(err, "%scan't have %d unflagged min<max opts, only one", ME, numvar);
+ else
+ fprintf(stderr, "%s: panic 16\n", me);
+ return 1;
+ }
+ return 0;
+}
+
/* experiments in adding a nixer/free-er that exactly matches the airMopper type,
as part of trying to avoid all "undefined behavior" */
void *
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-18 07:22:10 UTC (rev 7450)
+++ teem/trunk/src/hest/parseHest.c 2025-09-18 07:32:03 UTC (rev 7451)
@@ -225,234 +225,6 @@
return newArgc;
}
-/*
-_hestOptCheck() (formerly _hestPanic)
-
-This performs the validation of the given hestOpt array itself (not the command line to
-be parsed), with descriptive error messages sprintf'ed into err, if given. hestOptCheck()
-is the expected way for users to access this.
-
-Prior to 2023 code revisit; this used to set the "kind" in all the opts but now that is
-more appropriately done at the time the option is added (by hestOptAdd, hestOptAdd_nva,
-hestOptSingleSet, or hestOptAdd_*_*)
-*/
-int
-_hestOptCheck(const hestOpt *opt, char *err, const hestParm *hparm) {
- /* see note on ME (at top) for why me[] ends with ": " */
- static const char me[] = "_hestOptCheck: ";
- char tbuff[AIR_STRLEN_HUGE + 1], *sep;
- int numvar, opi, optNum;
-
- optNum = hestOptNum(opt);
- numvar = 0;
- for (opi = 0; opi < optNum; opi++) {
- if (!(AIR_IN_OP(airTypeUnknown, opt[opi].type, airTypeLast))) {
- if (err)
- sprintf(err, "%sopt[%d].type (%d) not in valid range [%d,%d]", ME, opi,
- opt[opi].type, airTypeUnknown + 1, airTypeLast - 1);
- else
- fprintf(stderr, "%s: panic 0\n", me);
- return 1;
- }
- if (!(opt[opi].valueP)) {
- if (err)
- sprintf(err, "%sopt[%d]'s valueP is NULL!", ME, opi);
- else
- fprintf(stderr, "%s: panic 0.5\n", me);
- return 1;
- }
- if (-1 == opt[opi].kind) {
- if (err)
- sprintf(err, "%sopt[%d]'s min (%d) and max (%d) incompatible", ME, opi,
- opt[opi].min, opt[opi].max);
- else
- fprintf(stderr, "%s: panic 1\n", me);
- return 1;
- }
- if (5 == opt[opi].kind && !(opt[opi].sawP)) {
- if (err)
- sprintf(err,
- "%shave multiple variable parameters, "
- "but sawP is NULL",
- ME);
- else
- fprintf(stderr, "%s: panic 2\n", me);
- return 1;
- }
- if (airTypeEnum == opt[opi].type) {
- if (!(opt[opi].enm)) {
- if (err) {
- sprintf(err,
- "%sopt[%d] (%s) is type \"enum\", but no "
- "airEnum pointer given",
- ME, opi, opt[opi].flag ? opt[opi].flag : "?");
- } else {
- fprintf(stderr, "%s: panic 3\n", me);
- }
- return 1;
- }
- }
- if (airTypeOther == opt[opi].type) {
- if (!(opt[opi].CB)) {
- if (err) {
- sprintf(err,
- "%sopt[%d] (%s) is type \"other\", but no "
- "callbacks given",
- ME, opi, opt[opi].flag ? opt[opi].flag : "?");
- } else {
- fprintf(stderr, "%s: panic 4\n", me);
- }
- return 1;
- }
- if (!(opt[opi].CB->size > 0)) {
- if (err)
- sprintf(err, "%sopt[%d]'s \"size\" (%d) invalid", ME, opi,
- (int)(opt[opi].CB->size));
- else
- fprintf(stderr, "%s: panic 5\n", me);
- return 1;
- }
- if (!(opt[opi].CB->type)) {
- if (err)
- sprintf(err, "%sopt[%d]'s \"type\" is NULL", ME, opi);
- else
- fprintf(stderr, "%s: panic 6\n", me);
- return 1;
- }
- if (!(opt[opi].CB->parse)) {
- if (err)
- sprintf(err, "%sopt[%d]'s \"parse\" callback NULL", ME, opi);
- else
- fprintf(stderr, "%s: panic 7\n", me);
- return 1;
- }
- if (opt[opi].CB->destroy && (sizeof(void *) != opt[opi].CB->size)) {
- if (err)
- sprintf(err,
- "%sopt[%d] has a \"destroy\", but size %lu isn't "
- "sizeof(void*)",
- ME, opi, (unsigned long)(opt[opi].CB->size));
- else
- fprintf(stderr, "%s: panic 8\n", me);
- return 1;
- }
- }
- if (opt[opi].flag) {
- strcpy(tbuff, opt[opi].flag);
- if ((sep = strchr(tbuff, hparm->multiFlagSep))) {
- *sep = '\0';
- if (!(strlen(tbuff) && strlen(sep + 1))) {
- if (err)
- sprintf(err,
- "%seither short (\"%s\") or long (\"%s\") flag"
- " of opt[%d] is zero length",
- ME, tbuff, sep + 1, opi);
- else
- fprintf(stderr, "%s: panic 9\n", me);
- return 1;
- }
- if (hparm->respectDashDashHelp && !strcmp("help", sep + 1)) {
- if (err)
- sprintf(err,
- "%slong \"--%s\" flag of opt[%d] is same as \"--help\" "
- "that requested hparm->respectDashDashHelp handles separately",
- ME, sep + 1, opi);
- else
- fprintf(stderr, "%s: panic 9.5\n", me);
- return 1;
- }
- } else {
- if (!strlen(opt[opi].flag)) {
- if (err)
- sprintf(err, "%sopt[%d].flag is zero length", ME, opi);
- else
- fprintf(stderr, "%s: panic 10\n", me);
- return 1;
- }
- }
- if (hparm->respectDashBraceComments
- && (strchr(opt[opi].flag, '{') || strchr(opt[opi].flag, '}'))) {
- if (err)
- sprintf(err,
- "%srequested hparm->respectDashBraceComments but opt[%d]'s flag "
- "\"%s\" confusingly contains '{' or '}'",
- ME, opi, opt[opi].flag);
- else
- fprintf(stderr, "%s: panic 10.5\n", me);
- return 1;
- }
- if (4 == opt[opi].kind) {
- if (!opt[opi].dflt) {
- if (err)
- sprintf(err,
- "%sflagged single variable parameter must "
- "specify a default",
- ME);
- else
- fprintf(stderr, "%s: panic 11\n", me);
- return 1;
- }
- if (!strlen(opt[opi].dflt)) {
- if (err)
- sprintf(err,
- "%sflagged single variable parameter default "
- "must be non-zero length",
- ME);
- else
- fprintf(stderr, "%s: panic 12\n", me);
- return 1;
- }
- }
- /*
- sprintf(tbuff, "-%s", opt[op].flag);
- if (1 == sscanf(tbuff, "%f", &tmpF)) {
- if (err)
- sprintf(err, "%sopt[%d].flag (\"%s\") is numeric, bad news",
- ME, op, opt[op].flag);
- return 1;
- }
- */
- }
- if (1 == opt[opi].kind) {
- if (!opt[opi].flag) {
- if (err)
- sprintf(err, "%sflags must have flags", ME);
- else
- fprintf(stderr, "%s: panic 13\n", me);
- return 1;
- }
- } else {
- if (!opt[opi].name) {
- if (err)
- sprintf(err, "%sopt[%d] isn't a flag: must have \"name\"", ME, opi);
- else
- fprintf(stderr, "%s: panic 14\n", me);
- return 1;
- }
- }
- if (4 == opt[opi].kind && !opt[opi].dflt) {
- if (err)
- sprintf(err,
- "%sopt[%d] is single variable parameter, but "
- "no default set",
- ME, opi);
- else
- fprintf(stderr, "%s: panic 15\n", me);
- return 1;
- }
- numvar += ((int)opt[opi].min < _hestMax(opt[opi].max)
- && (NULL == opt[opi].flag)); /* HEY scrutinize casts */
- }
- if (numvar > 1) {
- if (err)
- sprintf(err, "%scan't have %d unflagged min<max opts, only one", ME, numvar);
- else
- fprintf(stderr, "%s: panic 16\n", me);
- return 1;
- }
- return 0;
-}
-
uint
_hestErrStrlen(const hestOpt *opt, int argc, const char **argv) {
uint ret = 0;
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-18 07:22:10 UTC (rev 7450)
+++ teem/trunk/src/hest/parsest.c 2025-09-18 07:32:03 UTC (rev 7451)
@@ -184,8 +184,7 @@
airMopError(mop);
return 1;
}
- /* keep going while there's something on stack and no calls for help have been seen
- */
+ // keep going while there's something on stack and no calls for help have been seen
} while (hist->len && !(opt->helpWanted));
hestArgVecPrint(__func__, havec);
Modified: teem/trunk/src/hest/privateHest.h
===================================================================
--- teem/trunk/src/hest/privateHest.h 2025-09-18 07:22:10 UTC (rev 7450)
+++ teem/trunk/src/hest/privateHest.h 2025-09-18 07:32:03 UTC (rev 7451)
@@ -28,9 +28,9 @@
/* methodsHest.c */
extern int _hestKind(const hestOpt *opt);
extern int _hestMax(int max);
+extern int _hestOptCheck(const hestOpt *opt, char *err, const hestParm *parm);
/* parseHest.c */
-extern int _hestOptCheck(const hestOpt *opt, char *err, const hestParm *parm);
extern uint _hestErrStrlen(const hestOpt *opt, int argc, const char **argv);
#ifdef __cplusplus
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 07:22:12
|
Revision: 7450
http://sourceforge.net/p/teem/code/7450
Author: kindlmann
Date: 2025-09-18 07:22:10 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
some more progress on hestParse re-write
Modified Paths:
--------------
teem/trunk/src/hest/argvHest.c
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parseHest.c
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-18 05:52:43 UTC (rev 7449)
+++ teem/trunk/src/hest/argvHest.c 2025-09-18 07:22:10 UTC (rev 7450)
@@ -54,6 +54,7 @@
/* initialize with \0 so that harg->str is "" */
airArrayLenIncr(harg->strArr, 1);
/* now harg->str = {0:'\0'} and harg->len = 1; */
+ harg->finished = AIR_FALSE;
return;
}
@@ -103,6 +104,9 @@
for (uint si = 0; si < len; si++) {
hestArgAddChar(harg, str[si]);
}
+ /* The assumption is that if you have a string to put here; then you know that the
+ string is finished. User can modify this if that's not the case. */
+ harg->finished = AIR_TRUE;
return;
}
@@ -141,7 +145,7 @@
for (uint idx = 0; idx < havec->hargArr->len; idx++) {
const hestArg *harg;
harg = havec->harg + idx;
- printf(" %u:<%s>", idx, harg->str);
+ printf(" %u:<%s>%c", idx, harg->str, harg->finished ? '.' : '~');
}
printf("\n");
}
@@ -158,6 +162,7 @@
hin->argIdx = 0;
hin->fname = NULL;
hin->file = NULL;
+ hin->dashBraceComment = 0;
return;
}
@@ -206,49 +211,39 @@
return NULL;
}
-void
-hestInputStackPushCommandLine(hestInputStack *hist, int argc, const char **argv) {
+int
+hestInputStackPushCommandLine(hestInputStack *hist, int argc, const char **argv,
+ char *err, const hestParm *hparm) {
assert(hist);
+ AIR_UNUSED(err);
+ if (hparm->verbosity) {
+ printf("%s: changing stack height: %u --> %u with argc=%d,argv=%p; "
+ "setting argIdx to 0\n",
+ __func__, hist->hinArr->len, hist->hinArr->len + 1, argc, AIR_VOIDP(argv));
+ }
uint idx = airArrayLenIncr(hist->hinArr, 1);
+ if (hparm->verbosity > 1) {
+ printf("%s: new hinTop = %p\n", __func__, AIR_VOIDP(hist->hin + idx));
+ }
hist->hin[idx].source = hestSourceCommandLine;
hist->hin[idx].argc = argc;
hist->hin[idx].argv = argv;
hist->hin[idx].argIdx = 0;
- return;
+ return 0;
}
-static int
-histProc(hestArgVec *havec, hestInputStack *hist) {
- hestInput *hinTop = hist->hin + (hist->len - 1);
- int done = AIR_FALSE;
- switch (hinTop->source) {
- case hestSourceDefault:
- fprintf(stderr, "%s: sorry hestSourceDefault not implemented\n", __func__);
- done = AIR_TRUE;
- break;
- case hestSourceCommandLine:
- /* argv[] 0 1 2 3 (argc=4) */
- /* cmd arg1 arg2 arg3 */
- if (hinTop->argIdx < hinTop->argc) {
- /* there are args left to parse */
- hestArgVecAppendString(havec, hinTop->argv[hinTop->argIdx]);
- hinTop->argIdx++;
- }
- done = (hinTop->argIdx == hinTop->argc);
- break;
- case hestSourceResponseFile:
- fprintf(stderr, "%s: sorry hestSourceResponseFile not implemented\n", __func__);
- done = AIR_TRUE;
- break;
+int
+hestInputStackPop(hestInputStack *hist, char *err, const hestParm *hparm) {
+ assert(hist);
+ uint len = hist->hinArr->len;
+ if (!len) {
+ sprintf(err, "%s: cannot pop from stack height 0", __func__);
+ return 1;
}
- return done;
-}
-
-int
-hestInputStackProcess(hestArgVec *havec, hestInputStack *hist) {
- int done;
- do {
- done = histProc(havec, hist);
- } while (!done);
+ if (hparm->verbosity) {
+ printf("%s: changing stack height: %u --> %u; popping %s source\n", __func__, len,
+ len - 1, airEnumStr(hestSource, hist->hin[len - 1].source));
+ }
+ airArrayLenIncr(hist->hinArr, -1);
return 0;
-}
+}
\ No newline at end of file
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-18 05:52:43 UTC (rev 7449)
+++ teem/trunk/src/hest/hest.h 2025-09-18 07:22:10 UTC (rev 7450)
@@ -44,8 +44,7 @@
/*
******** hestSource* enum
**
-** records whether the info to satisfy a particular option came from the default or from
-** the user: command-line or response file.
+** way of identifying where the info to satisfy a particular option came from.
*/
enum {
hestSourceUnknown, /* 0 */
@@ -189,15 +188,21 @@
elideSingleEmptyStringDefault, /* if default for a single string is empty
(""), then don't display default */
elideMultipleEmptyStringDefault,
- respectDashDashHelp, /* hestParse interprets seeing "--help" as not an
- error, but as a request to print usage info,
- so sets helpWanted in the (first) hestOpt */
- noArgsIsNoProblem, /* if non-zero, having no arguments to parse is not in and
- of itself a problem; this means that if all options have
- defaults, it would be *ok* to invoke the problem without
- any further command-line options. This is counter to
- pre-Teem-1.11 behavior (for which no arguments *always*
- meant "show me usage info"). */
+ respectDashDashHelp, /* (new with TeemV2) hestParse interprets seeing "--help" as not
+ an error, but as a request to print usage info, so sets
+ helpWanted in the (first) hestOpt */
+ respectDashBraceComments, /* (new with TeemV2) Sometimes in a huge command-line
+ invocation you want to comment part of it out. With this
+ set, hestParse recognizes hest-specific "-{" and "}-"
+ args as comment delimiters: these args and all args they
+ enclose are ignored. These must be stand-alone args, and
+ cannot be touching anything else, lest brace expansion
+ kick in. */
+ noArgsIsNoProblem, /* if non-zero, having no arguments to parse is not in and of
+ itself a problem; this means that if all options have defaults, it
+ would be *ok* to invoke the problem without any further
+ command-line options. This is counter to pre-Teem-1.11 behavior
+ (for which no arguments *always* meant "show me usage info"). */
greedySingleString, /* when parsing a single string, whether or not to be greedy
(as per airParseStrS) */
cleverPluralizeOtherY, /* when printing the type for airTypeOther, when the min
@@ -221,14 +226,31 @@
disable this behavior entirely. */
} hestParm;
-/* for building up and representing one argument */
+/*
+The hestArg, hestArgVec, hestInput, and hestInputStack were all created for the TeemV2
+rewrite of hestParse, to fix bugs and limits on how the code previously worked:
+- Command-line arguments containing spaces were fully never correctly handled: the
+ internal representation of one argument, amidst a space-seperated string of all
+ arguments (why?!?) put back in ""-quoting, but it was never correctly implemented.
+ Now the internal representation of argv is with an array data structure, not a single
+ string that has to be retokenized.
+- When parsing response files, ""-quoted strings were never handled at all (nor was "#"
+ appearing within a string), and response files could not invoke other response files.
+- Can now support long-wanted feature: commenting out of some span of arguments, with
+ new hest-specific "-{" "}-" delimiters. As long as these are space-separated from
+ other args, these are left intact by sh, bash, and zsh (csh and tcsh get confused).
+ They must be kept as separate args to avoid brace expansion.
+*/
+
+// hestArg: for building up and representing one argument
typedef struct {
char *str;
- unsigned int len; /* NOT strlen; this includes '\0'-termination */
+ unsigned int len; // NOT strlen; this includes '\0'-termination
airArray *strArr;
+ int finished; // we have finished building up this string
} hestArg;
-/* for building up a "vector" of arguments */
+// hestArgVec: for building up a "vector" of arguments
typedef struct {
hestArg *harg; /* array of hestArgs */
unsigned int len;
@@ -235,27 +257,31 @@
airArray *hargArr;
} hestArgVec;
-/* what is the thing we're currently processing to build up the arg vec */
+// hestInput: what is the thing we're processing now to build up an arg vec
typedef struct {
- int source; /* from the hestSource* enum */
- /* ------ if source == hestSourceDefault ------ */
- const char *dflt; /* we do NOT own*/
- /* ------ if source == hestSourceCommandLine ------ */
+ int source; // from the hestSource* enum
+ // ------ if source == hestSourceDefault ------
+ const char *dflt; // we do NOT own
+ // ------ if source == hestSourceCommandLine ------
unsigned int argc;
- const char **argv; /* we do NOT own */
+ const char **argv; // we do NOT own
unsigned int argIdx;
- /* ------ if source == hestSourceResponseFile ------ */
- char *fname; /* we do NOT own */
- FILE *file; /* someone opened this for us */
+ // ------ if source == hestSourceResponseFile ------
+ char *fname; // we do NOT own
+ FILE *file; // someone opened this for us
+ // ------ general for all inputs ------
+ unsigned int dashBraceComment; /* not a boolean: how many -{ }- comment levels
+ deep are we currently; tracked this way to
+ permit nested commenting */
} hestInput;
typedef struct {
- hestInput *hin; /* array of hestInputs */
+ hestInput *hin; // array of hestInputs
unsigned int len;
airArray *hinArr;
} hestInputStack;
-/* defaultsHest.c */
+// defaultsHest.c
HEST_EXPORT int hestDefaultVerbosity;
HEST_EXPORT int hestDefaultRespFileEnable;
HEST_EXPORT int hestDefaultElideSingleEnumType;
@@ -274,7 +300,7 @@
HEST_EXPORT char hestDefaultVarParamStopFlag;
HEST_EXPORT char hestDefaultMultiFlagSep;
-/* argvHest.c */
+// argvHest.c
HEST_EXPORT hestArg *hestArgNew(void);
HEST_EXPORT hestArg *hestArgNix(hestArg *harg);
HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
@@ -287,16 +313,19 @@
HEST_EXPORT hestInput *hestInputNix(hestInput *hin);
HEST_EXPORT hestInputStack *hestInputStackNew(void);
HEST_EXPORT hestInputStack *hestInputStackNix(hestInputStack *hist);
-HEST_EXPORT void hestInputStackPushCommandLine(hestInputStack *hist, int argc,
- const char **argv);
-HEST_EXPORT int hestInputStackProcess(hestArgVec *havec, hestInputStack *hist);
+HEST_EXPORT int hestInputStackPushCommandLine(hestInputStack *hist, int argc,
+ const char **argv, char *err,
+ const hestParm *hparm);
+HEST_EXPORT int hestInputStackPop(hestInputStack *hist, char *err,
+ const hestParm *hparm);
-/* parsest.c */
+// parsest.c
HEST_EXPORT int hestParse2(hestOpt *opt, int argc, const char **argv, char **errP,
const hestParm *hparm);
-/* methodsHest.c */
+// methodsHest.c
HEST_EXPORT const int hestPresent;
+HEST_EXPORT const airEnum *const hestSource;
HEST_EXPORT int hestSourceUser(int src);
HEST_EXPORT hestParm *hestParmNew(void);
HEST_EXPORT hestParm *hestParmFree(hestParm *hparm);
@@ -319,13 +348,13 @@
... /* unsigned int *sawP,
const airEnum *enm,
const hestCB *CB */);
-/* see also all the special-purpose and type-checked versions in adders.c, below */
+// SEE ALSO all the special-purpose and type-checked versions in adders.c, below
HEST_EXPORT unsigned int hestOptNum(const hestOpt *opt);
HEST_EXPORT hestOpt *hestOptFree(hestOpt *opt);
HEST_EXPORT void *hestOptFree_vp(void *opt);
HEST_EXPORT int hestOptCheck(hestOpt *opt, char **errP);
-/* parseHest.c */
+// parseHest.c
HEST_EXPORT int hestParse(hestOpt *opt, int argc, const char **argv, char **errP,
const hestParm *hparm);
HEST_EXPORT void *hestParseFree(hestOpt *opt);
@@ -333,7 +362,7 @@
hestParm *hparm, const char *me, const char *info,
int doInfo, int doUsage, int doGlossary);
-/* usage.c */
+// usage.c
HEST_EXPORT void _hestPrintStr(FILE *f, unsigned int indent, unsigned int already,
unsigned int width, const char *_str, int bslash);
HEST_EXPORT int hestMinNumArgs(const hestOpt *opt);
@@ -343,7 +372,7 @@
HEST_EXPORT void hestInfo(FILE *file, const char *argv0, const char *info,
const hestParm *hparm);
-/* adders.c */
+// adders.c
HEST_EXPORT void hestOptAddDeclsPrint(FILE *f);
/* Many many non-var-args alternatives to hestOptAdd, also usefully type-specific for the
type of value to be parsed in a way that hestOptAdd_nva cannot match. These capture all
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-18 05:52:43 UTC (rev 7449)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-18 07:22:10 UTC (rev 7450)
@@ -22,11 +22,33 @@
#include <limits.h>
#include <assert.h>
-#include <sys/ioctl.h> /* for ioctl(), TIOCGWINSZ, struct winsize */
-#include <unistd.h> /* for STDOUT_FILENO and friends */
+#include <sys/ioctl.h> // for ioctl(), TIOCGWINSZ, struct winsize
+#include <unistd.h> // for STDOUT_FILENO and friends
const int hestPresent = 42;
+// enjoying how C99 greatly simplifies creating an airEnum at compile-time
+static const airEnum _hestSource
+ = {.name = "source",
+ .M = 3,
+ .str = (const char *[]){"(unknown_source)", //
+ "default", //
+ "command-line", //
+ "response-file"},
+ .val = NULL,
+ .desc = (const char *[]){"unknown source", //
+ "default string in hestOpt", //
+ "argc/argv command-line", //
+ "a response file"},
+ .strEqv = (const char *[]){"default", //
+ "command-line", "cmdline", //
+ "response-file", "respfile"},
+ .valEqv = (const int[]){hestSourceDefault, //
+ hestSourceCommandLine, hestSourceCommandLine, //
+ hestSourceResponseFile, hestSourceResponseFile},
+ .sense = AIR_FALSE};
+const airEnum *const hestSource = &_hestSource;
+
int
hestSourceUser(int src) {
return (hestSourceCommandLine == src || hestSourceResponseFile == src);
@@ -70,11 +92,13 @@
can be a different top-level parser function that turns on parm->respectDashDashHelp
and knows how to check the results */
hparm->respectDashDashHelp = AIR_FALSE;
+ /* for these most recent addition to the hestParm,
+ abstaining from adding yet another default global variable */
+ hparm->respectDashBraceComments = AIR_TRUE;
hparm->noArgsIsNoProblem = hestDefaultNoArgsIsNoProblem;
hparm->greedySingleString = hestDefaultGreedySingleString;
hparm->cleverPluralizeOtherY = hestDefaultCleverPluralizeOtherY;
- /* for these most recent addition to the hestParm,
- abstaining from added yet another default global variable */
+ /* here too: newer addition to hestParm avoid adding another default global */
hparm->dieLessVerbose = AIR_FALSE;
hparm->noBlankLineBeforeUsage = AIR_FALSE;
hparm->columns = hestDefaultColumns;
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-18 05:52:43 UTC (rev 7449)
+++ teem/trunk/src/hest/parseHest.c 2025-09-18 07:22:10 UTC (rev 7450)
@@ -248,7 +248,7 @@
for (opi = 0; opi < optNum; opi++) {
if (!(AIR_IN_OP(airTypeUnknown, opt[opi].type, airTypeLast))) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]", ME, opi,
+ sprintf(err, "%sopt[%d].type (%d) not in valid range [%d,%d]", ME, opi,
opt[opi].type, airTypeUnknown + 1, airTypeLast - 1);
else
fprintf(stderr, "%s: panic 0\n", me);
@@ -256,7 +256,7 @@
}
if (!(opt[opi].valueP)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s valueP is NULL!", ME, opi);
+ sprintf(err, "%sopt[%d]'s valueP is NULL!", ME, opi);
else
fprintf(stderr, "%s: panic 0.5\n", me);
return 1;
@@ -263,7 +263,7 @@
}
if (-1 == opt[opi].kind) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible", ME, opi,
+ sprintf(err, "%sopt[%d]'s min (%d) and max (%d) incompatible", ME, opi,
opt[opi].min, opt[opi].max);
else
fprintf(stderr, "%s: panic 1\n", me);
@@ -272,7 +272,7 @@
if (5 == opt[opi].kind && !(opt[opi].sawP)) {
if (err)
sprintf(err,
- "%s!!!!!! have multiple variable parameters, "
+ "%shave multiple variable parameters, "
"but sawP is NULL",
ME);
else
@@ -283,7 +283,7 @@
if (!(opt[opi].enm)) {
if (err) {
sprintf(err,
- "%s!!!!!! opt[%d] (%s) is type \"enum\", but no "
+ "%sopt[%d] (%s) is type \"enum\", but no "
"airEnum pointer given",
ME, opi, opt[opi].flag ? opt[opi].flag : "?");
} else {
@@ -296,7 +296,7 @@
if (!(opt[opi].CB)) {
if (err) {
sprintf(err,
- "%s!!!!!! opt[%d] (%s) is type \"other\", but no "
+ "%sopt[%d] (%s) is type \"other\", but no "
"callbacks given",
ME, opi, opt[opi].flag ? opt[opi].flag : "?");
} else {
@@ -306,7 +306,7 @@
}
if (!(opt[opi].CB->size > 0)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"size\" (%d) invalid", ME, opi,
+ sprintf(err, "%sopt[%d]'s \"size\" (%d) invalid", ME, opi,
(int)(opt[opi].CB->size));
else
fprintf(stderr, "%s: panic 5\n", me);
@@ -314,7 +314,7 @@
}
if (!(opt[opi].CB->type)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"type\" is NULL", ME, opi);
+ sprintf(err, "%sopt[%d]'s \"type\" is NULL", ME, opi);
else
fprintf(stderr, "%s: panic 6\n", me);
return 1;
@@ -321,7 +321,7 @@
}
if (!(opt[opi].CB->parse)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"parse\" callback NULL", ME, opi);
+ sprintf(err, "%sopt[%d]'s \"parse\" callback NULL", ME, opi);
else
fprintf(stderr, "%s: panic 7\n", me);
return 1;
@@ -329,7 +329,7 @@
if (opt[opi].CB->destroy && (sizeof(void *) != opt[opi].CB->size)) {
if (err)
sprintf(err,
- "%s!!!!!! opt[%d] has a \"destroy\", but size %lu isn't "
+ "%sopt[%d] has a \"destroy\", but size %lu isn't "
"sizeof(void*)",
ME, opi, (unsigned long)(opt[opi].CB->size));
else
@@ -344,7 +344,7 @@
if (!(strlen(tbuff) && strlen(sep + 1))) {
if (err)
sprintf(err,
- "%s!!!!!! either short (\"%s\") or long (\"%s\") flag"
+ "%seither short (\"%s\") or long (\"%s\") flag"
" of opt[%d] is zero length",
ME, tbuff, sep + 1, opi);
else
@@ -354,7 +354,7 @@
if (hparm->respectDashDashHelp && !strcmp("help", sep + 1)) {
if (err)
sprintf(err,
- "%s!!!!!! long \"--%s\" flag of opt[%d] is same as \"--help\" "
+ "%slong \"--%s\" flag of opt[%d] is same as \"--help\" "
"that requested hparm->respectDashDashHelp handles separately",
ME, sep + 1, opi);
else
@@ -364,17 +364,28 @@
} else {
if (!strlen(opt[opi].flag)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d].flag is zero length", ME, opi);
+ sprintf(err, "%sopt[%d].flag is zero length", ME, opi);
else
fprintf(stderr, "%s: panic 10\n", me);
return 1;
}
}
+ if (hparm->respectDashBraceComments
+ && (strchr(opt[opi].flag, '{') || strchr(opt[opi].flag, '}'))) {
+ if (err)
+ sprintf(err,
+ "%srequested hparm->respectDashBraceComments but opt[%d]'s flag "
+ "\"%s\" confusingly contains '{' or '}'",
+ ME, opi, opt[opi].flag);
+ else
+ fprintf(stderr, "%s: panic 10.5\n", me);
+ return 1;
+ }
if (4 == opt[opi].kind) {
if (!opt[opi].dflt) {
if (err)
sprintf(err,
- "%s!!!!!! flagged single variable parameter must "
+ "%sflagged single variable parameter must "
"specify a default",
ME);
else
@@ -384,7 +395,7 @@
if (!strlen(opt[opi].dflt)) {
if (err)
sprintf(err,
- "%s!!!!!! flagged single variable parameter default "
+ "%sflagged single variable parameter default "
"must be non-zero length",
ME);
else
@@ -396,7 +407,7 @@
sprintf(tbuff, "-%s", opt[op].flag);
if (1 == sscanf(tbuff, "%f", &tmpF)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d].flag (\"%s\") is numeric, bad news",
+ sprintf(err, "%sopt[%d].flag (\"%s\") is numeric, bad news",
ME, op, opt[op].flag);
return 1;
}
@@ -405,7 +416,7 @@
if (1 == opt[opi].kind) {
if (!opt[opi].flag) {
if (err)
- sprintf(err, "%s!!!!!! flags must have flags", ME);
+ sprintf(err, "%sflags must have flags", ME);
else
fprintf(stderr, "%s: panic 13\n", me);
return 1;
@@ -413,7 +424,7 @@
} else {
if (!opt[opi].name) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d] isn't a flag: must have \"name\"", ME, opi);
+ sprintf(err, "%sopt[%d] isn't a flag: must have \"name\"", ME, opi);
else
fprintf(stderr, "%s: panic 14\n", me);
return 1;
@@ -422,7 +433,7 @@
if (4 == opt[opi].kind && !opt[opi].dflt) {
if (err)
sprintf(err,
- "%s!!!!!! opt[%d] is single variable parameter, but "
+ "%sopt[%d] is single variable parameter, but "
"no default set",
ME, opi);
else
@@ -434,8 +445,7 @@
}
if (numvar > 1) {
if (err)
- sprintf(err, "%s!!!!!! can't have %d unflagged min<max opts, only one", ME,
- numvar);
+ sprintf(err, "%scan't have %d unflagged min<max opts, only one", ME, numvar);
else
fprintf(stderr, "%s: panic 16\n", me);
return 1;
Modified: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c 2025-09-18 05:52:43 UTC (rev 7449)
+++ teem/trunk/src/hest/parsest.c 2025-09-18 07:22:10 UTC (rev 7450)
@@ -20,7 +20,7 @@
#include "hest.h"
#include "privateHest.h"
-/* (parse, parser, parsest) */
+/* parse, parser, parsest: this aims to be the final implmentation of hestParse */
/* A little trickery for error reporting. For many of the functions here, if they hit an
error and hparm->verbosity is set, then we should reveal the current function name (set
@@ -30,33 +30,115 @@
to `functionname: ` (NOTE the `: `) so that all of that goes away without verbosity. And,
that means that error message generation here should also defy convention and instead of
being "%s: what happened" it should just be "%swhat happened" */
-#define ME ((hparm && hparm->verbosity) ? me : "")
+// how to const-correctly use either given (const) _hparm or own (non-const) hparm
+#define HPARM (_hparm ? _hparm : hparm)
+#define HMME (HPARM->verbosity ? me : "")
+#define ME ((hparm && hparm->verbosity) ? me : "")
+static int
+histProc(hestArgVec *havec, int *helpWantedP, hestInputStack *hist, char *err,
+ const hestParm *hparm) {
+ static const char me[] = "histProc: ";
+ int ret = 0;
+ int popAtEnd = AIR_FALSE;
+ *helpWantedP = AIR_FALSE; // may over-write later
+ hestInput *hinTop = hist->hin + (hist->len - 1);
+ switch (hinTop->source) {
+ case hestSourceDefault: // ---------------------------------
+ sprintf(err, "%ssorry hestSourceDefault not implemented\n", ME);
+ ret = 1;
+ break;
+ case hestSourceCommandLine: // ---------------------------------
+ /* argv[] 0 1 2 3 (argc=4) */
+ /* cmd arg1 arg2 arg3 */
+ if (hparm->verbosity > 1) {
+ printf("%shist->len=%u -> hinTop=%p\n", me, hist->len, AIR_VOIDP(hinTop));
+ }
+ if (hinTop->argIdx < hinTop->argc) {
+ /* there are args left to parse */
+ const char *thisArgv = hinTop->argv[hinTop->argIdx];
+ if (hparm->verbosity > 1) {
+ printf("%slooking at argv[%u] |%s|\n", me, hinTop->argIdx, thisArgv);
+ }
+ hinTop->argIdx++;
+ if (hparm->respectDashBraceComments && !strcmp("-{", thisArgv)) {
+ // start of -{ }- commenting (or increase in nesting level)
+ hinTop->dashBraceComment += 1;
+ }
+ if (!hinTop->dashBraceComment) {
+ hestArgVecAppendString(havec, thisArgv);
+ }
+ if (hparm->respectDashBraceComments && !strcmp("}-", thisArgv)) {
+ if (hinTop->dashBraceComment) {
+ hinTop->dashBraceComment -= 1;
+ } else {
+ sprintf(err, "%send comment arg \"}-\" not balanced by prior \"-{\"", ME);
+ ret = 1;
+ }
+ }
+ }
+ if (hinTop->argIdx == hinTop->argc) {
+ // we have gotten to the end of the given argv array */
+ if (hinTop->dashBraceComment) {
+ sprintf(err, "%sstart comment arg \"-{\" not balanced by later \"}-\"", ME);
+ ret = 1;
+ } else {
+ popAtEnd = AIR_TRUE;
+ // but don't pop now because we need to check for --help
+ }
+ }
+ break;
+ case hestSourceResponseFile: // ---------------------------------
+ sprintf(err, "%ssorry hestSourceResponseFile not implemented\n", ME);
+ ret = 1;
+ break;
+ }
+ /* when processing command-line or response file, check for --help
+ (it makes no sense for --help to appear in a default string) */
+ if (hestSourceResponseFile == hinTop->source
+ || hestSourceCommandLine == hinTop->source) {
+ const hestArg *hlast;
+ if (hparm->respectDashDashHelp // watching for "--help"
+ && havec->len // have at least one arg
+ && (hlast = havec->harg + havec->len - 1)->finished // latest arg is finished
+ && !strcmp("--help", hlast->str)) { // and it equals "--help"
+ *helpWantedP = AIR_TRUE;
+ }
+ }
+ if (popAtEnd) {
+ if (hestInputStackPop(hist, err, hparm)) {
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
int
hestParse2(hestOpt *opt, int argc, const char **argv, char **_errP,
const hestParm *_hparm) {
- /* see note on ME (at top) for why me[] ends with ": " */
- // static const char me[] = "hestParse2: ";
+ /* see note on HMME (at top) for why me[] ends with ": " */
+ static const char me[] = "hestParse2: ";
- /* -------- initialize the mop */
+ // -------- initialize the mop
airArray *mop = airMopNew();
- /* -------- exactly one of (given) _hparm and (our) hparm is non-NULL */
+ // -------- make exactly one of (given) _hparm and (our) hparm non-NULL
hestParm *hparm = NULL;
if (!_hparm) {
hparm = hestParmNew();
airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
}
- /* how to const-correctly use hparm or _hparm in an expression */
-#define HPARM (_hparm ? _hparm : hparm)
+ if (HPARM->verbosity > 1) {
+ printf("%shparm->verbosity %d\n", HMME, HPARM->verbosity);
+ }
- /* -------- allocate the err string. We do it a dumb way for now.
- TODO: make this smarter */
+ // -------- allocate the err string. We do it a dumb way for now.
+ // TODO: make this smarter
uint eslen = 2 * AIR_STRLEN_HUGE;
char *err = AIR_CALLOC(eslen + 1, char);
assert(err);
if (_errP) {
- /* they care about the error string, so mop it only when there is _not_ an error */
+ // they care about the error string, so mop it only when there is _not_ an error
*_errP = err;
airMopAdd(mop, _errP, (airMopper)airSetNull, airMopOnOkay);
airMopAdd(mop, err, airFree, airMopOnOkay);
@@ -65,20 +147,47 @@
so we always clean it up on exit */
airMopAdd(mop, err, airFree, airMopAlways);
}
+ if (HPARM->verbosity > 1) {
+ printf("%serr %p\n", HMME, AIR_VOIDP(err));
+ }
- /* -------- check on validity of the hestOpt array */
+ // -------- check on validity of the hestOpt array
if (_hestOptCheck(opt, err, HPARM)) {
+ // error message has been sprinted into err
airMopError(mop);
return 1;
}
+ if (HPARM->verbosity > 1) {
+ printf("%s_hestOptCheck passed\n", HMME);
+ }
- /* -------- allocate the state we use during parsing */
+ // -------- allocate the state we use during parsing
hestInputStack *hist = hestInputStackNew();
airMopAdd(mop, hist, (airMopper)hestInputStackNix, airMopAlways);
hestArgVec *havec = hestArgVecNew();
airMopAdd(mop, havec, (airMopper)hestArgVecNix, airMopAlways);
- hestInputStackPushCommandLine(hist, argc, argv);
- hestInputStackProcess(havec, hist);
+ if (HPARM->verbosity > 1) {
+ printf("%shavec and hist allocated\n", HMME);
+ }
+
+ // -------- initialize input stack w/ given argc,argv, then process it
+ if (hestInputStackPushCommandLine(hist, argc, argv, err, HPARM)) {
+ airMopError(mop);
+ return 1;
+ }
+ do {
+ /* Every iteration of this will work on one argv[] element, or, one character of a
+ response file. As long as we avoid giving ourselves infinite work, eventually,
+ bird by bird, we will finish. */
+ if (histProc(havec, &(opt->helpWanted), hist, err, HPARM)) {
+ // error message in err
+ airMopError(mop);
+ return 1;
+ }
+ /* keep going while there's something on stack and no calls for help have been seen
+ */
+ } while (hist->len && !(opt->helpWanted));
+
hestArgVecPrint(__func__, havec);
airMopOkay(mop);
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-18 05:52:43 UTC (rev 7449)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-18 07:22:10 UTC (rev 7450)
@@ -21,12 +21,25 @@
int
main(int argc, const char **argv) {
-
+ int ret = 0;
hestOpt *opt = NULL;
+ hestParm *hparm = hestParmNew();
+ hparm->respectDashDashHelp = AIR_TRUE;
int res[2];
- hestOptAdd(&opt, "res", "sx sy", airTypeInt, 2, 2, res, NULL, "image resolution");
- hestParse2(opt, argc - 1, argv + 1, NULL, NULL);
+ hestOptAdd_2_Int(&opt, "res", "sx sy", res, NULL, "image resolution");
+ int flag;
+ hestOptAdd_Flag(&opt, "b,bingo", &flag, "a flag");
+ char *err;
+ hparm->verbosity = 0;
+ if (hestParse2(opt, argc - 1, argv + 1, &err, hparm)) {
+ fprintf(stderr, "%s: problem:\n%s\n", argv[0], err);
+ ret = 1;
+ }
+ if (opt->helpWanted) {
+ printf("%s: help wanted!\n", argv[0]);
+ }
hestOptFree(opt);
- exit(0);
+ hestParmFree(hparm);
+ exit(ret);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-18 05:52:46
|
Revision: 7449
http://sourceforge.net/p/teem/code/7449
Author: kindlmann
Date: 2025-09-18 05:52:43 +0000 (Thu, 18 Sep 2025)
Log Message:
-----------
more docs
Modified Paths:
--------------
teem/trunk/src/hest/README.md
Modified: teem/trunk/src/hest/README.md
===================================================================
--- teem/trunk/src/hest/README.md 2025-09-17 20:16:47 UTC (rev 7448)
+++ teem/trunk/src/hest/README.md 2025-09-18 05:52:43 UTC (rev 7449)
@@ -23,29 +23,35 @@
Note that `hest` does not attempt to follow POSIX conventions (or terminology) for command-line descriptions, because those conventions don't empower the kind of expressivity and flexibility that motivated `hest`'s creation. POSIX does not encompass the scientific computing and visualization contexts that Teem was built for.
-## How `hestParse` works
+## The different `kind`s of options, and how to `hestOptAdd` them.
-There are lot of moving pieces inside `hestParse`, and the description of how it works is complicated by how flexible a `hestOpt` can be. Two of the fields in the `hestOpt` are `min` and `max`: the min and max number of parameters that are parsed for the option. All the different traditional uses of the command-line can be parameterized in terms of `min` and `max`, but the full range of possibilities of `min`,`max` (which `hest` supports) include some less conventional uses. The _`kind`_ is `hest`'s term for a numeric identifier for the kind of option that a `hestOpt` describes. The following ASCII-art illustrates how `min` and `max` determine `kind`, and also give the prose name for each kind of option, which appears in the code and a description of its operation.
+There are lot of moving pieces inside `hestParse`, and the description of how it works is complicated by how flexible a `hestOpt` can be. Two of the fields in the `hestOpt` are `min` and `max`: the min and max number of parameters that may be parsed for that option. All the different traditional uses of the command-line can be parameterized in terms of `min` and `max`, but the full range of possibilities of `min`,`max` (which `hest` supports) include some less conventional uses. The _`kind`_ is `hest`'s term for a numeric identifier for the kind of option that a `hestOpt` describes. The following ASCII-art illustrates how `min` and `max` determine:
+- numeric `kind`, shown as `(`_n_`)`; for _n_ = 1,2,3,4,5
+- the prose name for that kind of option, which appears in the code and a description of its operation.
+- Which `hestOptAdd_` function or family of functions is used to parse that kind of option. Here, `hestOptAdd_` is abbreviated `hOA_` and the final `_T` stands for the type (eg. `_Bool`, `_Int`, `_Float`, `_Enum`, `_Other`, etc).
+
```
- : (k) kind of and term for .
- : different possible options; . /
- : learned by _hestKind(hopt) . /
- : . /
- : (5) multiple : (3) multiple
- 2--: variable : fixed
- : parms : parms
- :............................
- : (4) single : (2) single
- 1--: variable : fixed
- : parm : parm
- :..............
- : (1) stand-alone
- 0--: flag;
- : no parms
- ^ :............................................
-max | | |
- min > 0 1 2
+ | . / . /
+ | . / . /
+ | . / . /
+ | (5) multiple | (3) multiple
+ 2--| variable | fixed
+ | parms | parms
+ | hOA_Nv_T | hOA_{2,3,4,N}_T
+ |.............................../
+ | (4) single | (2) single
+ 1--| variable | fixed
+ | parm | parm
+ | hOA_1v_T | hOA_1_T
+ |...............|/
+ | (1) stand-alone
+ 0--| flag;
+ | no parms
+ | hOA_Flag
+ ^ |/_____________________________________________
+max | | |
+ min > 0 1 2
```
-The `kind` of option is independent of whether it is flagged or unflagged, and independent of being optional (because a default is given) or required (because no default given).
+The `kind` of option is independent of whether it is flagged or unflagged, and independent of being optional (because the `hestOpt` has a default string) or required (because no default is given).
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-17 20:16:49
|
Revision: 7448
http://sourceforge.net/p/teem/code/7448
Author: kindlmann
Date: 2025-09-17 20:16:47 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
cleaning up memory
Modified Paths:
--------------
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c 2025-09-17 20:11:25 UTC (rev 7447)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-17 20:16:47 UTC (rev 7448)
@@ -27,5 +27,6 @@
hestOptAdd(&opt, "res", "sx sy", airTypeInt, 2, 2, res, NULL, "image resolution");
hestParse2(opt, argc - 1, argv + 1, NULL, NULL);
+ 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-17 20:11:32
|
Revision: 7447
http://sourceforge.net/p/teem/code/7447
Author: kindlmann
Date: 2025-09-17 20:11:25 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
putting back in a TINY big of platform-dependence
Modified Paths:
--------------
teem/trunk/src/make/arch.mk
Modified: teem/trunk/src/make/arch.mk
===================================================================
--- teem/trunk/src/make/arch.mk 2025-09-17 20:05:11 UTC (rev 7446)
+++ teem/trunk/src/make/arch.mk 2025-09-17 20:11:25 UTC (rev 7447)
@@ -19,8 +19,9 @@
#### See NOTE in ../GNUMakefile about the big simplification to the non-CMake build
#### process made for TeemV2. This new file contains all the architecture-specific
-#### details about how to compile (on a non-Windows machine).
-#### Whatever is in this file is GLK needed to get Teem compiling; edit as you need.
+#### details about how to compile (on a non-Windows machine). Here there is only the
+#### most bare-bones platform-specific logic: some variables are differently for
+#### Mac vs Linux
# yes, we should probably be using ?= instead = for the assingments below, but
# the intent here is to be clear and explicit. The assignment "AR ?= libtool"
@@ -31,15 +32,21 @@
# CC = scan-build clang # to run static analyzer https://clang.llvm.org/docs/ClangStaticAnalyzer.html
CC := cc
LD := ld
-# historically `ar`
-AR := libtool
-# historically `ru`
-ARFLAGS := -static -o
+ifeq ($(shell uname -s),Darwin)
+ # on mac
+ AR := libtool
+ ARFLAGS := -static -o
+ # if non-empty: also delete X$(LITTER) when deleting executable X with "make clean"
+ LITTER := .dSYM
+else
+ # assume on linux
+ AR := ar
+ ARFLAGS := ru
+ LITTER :=
+endif
# sometimes needed after `ar` to store index in library
RANLIB :=
RM := rm -f
-# if non-empty: also delete X$(LITTER) when deleting executable X with "make clean"
-LITTER := .dSYM
CP := cp
CHMOD := chmod
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-17 20:05:12
|
Revision: 7446
http://sourceforge.net/p/teem/code/7446
Author: kindlmann
Date: 2025-09-17 20:05:11 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
ooops forgot to commit this new file
Added Paths:
-----------
teem/trunk/src/hest/parsest.c
Added: teem/trunk/src/hest/parsest.c
===================================================================
--- teem/trunk/src/hest/parsest.c (rev 0)
+++ teem/trunk/src/hest/parsest.c 2025-09-17 20:05:11 UTC (rev 7446)
@@ -0,0 +1,86 @@
+/*
+ Teem: Tools to process and visualize scientific data and images
+ Copyright (C) 2009--2025 University of Chicago
+ Copyright (C) 2005--2008 Gordon Kindlmann
+ Copyright (C) 1998--2004 University of Utah
+
+ This library is free software; you can redistribute it and/or modify it under the terms
+ of the GNU Lesser General Public License (LGPL) as published by the Free Software
+ Foundation; either version 2.1 of the License, or (at your option) any later version.
+ The terms of redistributing and/or modifying this software also include exceptions to
+ the LGPL that facilitate static linking.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "hest.h"
+#include "privateHest.h"
+
+/* (parse, parser, parsest) */
+
+/* A little trickery for error reporting. For many of the functions here, if they hit an
+error and hparm->verbosity is set, then we should reveal the current function name (set
+by convention in `me`). But without verbosity, we hide that function name, so it appears
+that the error is coming from the caller (probably identified as argv[0]). However, that
+means that functions using this `ME` macro should (in defiance of convention) set to `me`
+to `functionname: ` (NOTE the `: `) so that all of that goes away without verbosity. And,
+that means that error message generation here should also defy convention and instead of
+being "%s: what happened" it should just be "%swhat happened" */
+#define ME ((hparm && hparm->verbosity) ? me : "")
+
+int
+hestParse2(hestOpt *opt, int argc, const char **argv, char **_errP,
+ const hestParm *_hparm) {
+ /* see note on ME (at top) for why me[] ends with ": " */
+ // static const char me[] = "hestParse2: ";
+
+ /* -------- initialize the mop */
+ airArray *mop = airMopNew();
+
+ /* -------- exactly one of (given) _hparm and (our) hparm is non-NULL */
+ hestParm *hparm = NULL;
+ if (!_hparm) {
+ hparm = hestParmNew();
+ airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
+ }
+ /* how to const-correctly use hparm or _hparm in an expression */
+#define HPARM (_hparm ? _hparm : hparm)
+
+ /* -------- allocate the err string. We do it a dumb way for now.
+ TODO: make this smarter */
+ uint eslen = 2 * AIR_STRLEN_HUGE;
+ char *err = AIR_CALLOC(eslen + 1, char);
+ assert(err);
+ if (_errP) {
+ /* they care about the error string, so mop it only when there is _not_ an error */
+ *_errP = err;
+ airMopAdd(mop, _errP, (airMopper)airSetNull, airMopOnOkay);
+ airMopAdd(mop, err, airFree, airMopOnOkay);
+ } else {
+ /* otherwise, we're making the error string just for our own convenience,
+ so we always clean it up on exit */
+ airMopAdd(mop, err, airFree, airMopAlways);
+ }
+
+ /* -------- check on validity of the hestOpt array */
+ if (_hestOptCheck(opt, err, HPARM)) {
+ airMopError(mop);
+ return 1;
+ }
+
+ /* -------- allocate the state we use during parsing */
+ hestInputStack *hist = hestInputStackNew();
+ airMopAdd(mop, hist, (airMopper)hestInputStackNix, airMopAlways);
+ hestArgVec *havec = hestArgVecNew();
+ airMopAdd(mop, havec, (airMopper)hestArgVecNix, airMopAlways);
+ hestInputStackPushCommandLine(hist, argc, argv);
+ hestInputStackProcess(havec, hist);
+ hestArgVecPrint(__func__, havec);
+
+ 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-17 19:40:18
|
Revision: 7445
http://sourceforge.net/p/teem/code/7445
Author: kindlmann
Date: 2025-09-17 19:40:16 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
making slow progress on re-write of parsing
Modified Paths:
--------------
teem/trunk/src/hest/CMakeLists-v2.txt
teem/trunk/src/hest/GNUmakefile
teem/trunk/src/hest/argvHest.c
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/test/argv.c
Added Paths:
-----------
teem/trunk/src/hest/test/tparse.c
Modified: teem/trunk/src/hest/CMakeLists-v2.txt
===================================================================
--- teem/trunk/src/hest/CMakeLists-v2.txt 2025-09-17 19:39:05 UTC (rev 7444)
+++ teem/trunk/src/hest/CMakeLists-v2.txt 2025-09-17 19:40:16 UTC (rev 7445)
@@ -1,6 +1,6 @@
_Teem_add_library(${CMAKE_CURRENT_SOURCE_DIR}
SOURCES
- adders.c argvHest.c defaultsHest.c methodsHest.c parseHest.c usage.c
+ adders.c argvHest.c defaultsHest.c methodsHest.c parseHest.c parsest.c usage.c
# private header
privateHest.h
PUBLIC_HEADERS
Modified: teem/trunk/src/hest/GNUmakefile
===================================================================
--- teem/trunk/src/hest/GNUmakefile 2025-09-17 19:39:05 UTC (rev 7444)
+++ teem/trunk/src/hest/GNUmakefile 2025-09-17 19:40:16 UTC (rev 7445)
@@ -46,9 +46,9 @@
$(L).PublicHdr = hest.h
$(L).PrivateHdr = privateHest.h
$(L).Obj = $(patsubst %.c,%.o, \
- adders.c argvHest.c defaultsHest.c methodsHest.c parseHest.c usage.c \
+ adders.c argvHest.c defaultsHest.c methodsHest.c parseHest.c parsest.c usage.c \
)
-$(L).Test = argv ex1 ex2 ex3 ex4 ex5 ex6 strings bday tmpl
+$(L).Test = argv tparse ex1 ex2 ex3 ex4 ex5 ex6 strings bday tmpl
####
####
####
Modified: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c 2025-09-17 19:39:05 UTC (rev 7444)
+++ teem/trunk/src/hest/argvHest.c 2025-09-17 19:40:16 UTC (rev 7445)
@@ -24,6 +24,16 @@
#define INCR 32
+/* to avoid strict aliasing warnings */
+typedef union {
+ hestArg **harg;
+ hestArgVec **havec;
+ hestInput **hin;
+ void **v;
+} hestPtrPtrUnion;
+
+/* ---------------------- hestArg = harg = hestArg = harg ------------------ */
+
/* dereferences as char *, sets to '\0' */
static void
setNul(void *_c) {
@@ -34,13 +44,12 @@
static void
hargInit(void *_harg) {
- airPtrPtrUnion appu;
- hestArg *harg;
- harg = (hestArg *)_harg;
+ hestArg *harg = (hestArg *)_harg;
harg->str = NULL;
harg->len = 0;
+ airPtrPtrUnion appu;
appu.c = &(harg->str);
- harg->strArr = airArrayNew(appu.v, &(harg->len), 1 /* unit */, INCR);
+ harg->strArr = airArrayNew(appu.v, &(harg->len), sizeof(char), INCR);
airArrayStructCB(harg->strArr, setNul, NULL);
/* initialize with \0 so that harg->str is "" */
airArrayLenIncr(harg->strArr, 1);
@@ -50,23 +59,29 @@
hestArg *
hestArgNew(void) {
- hestArg *harg;
-
- harg = AIR_CALLOC(1, hestArg);
+ hestArg *harg = AIR_CALLOC(1, hestArg);
assert(harg);
hargInit(harg);
return harg;
}
+static void
+hargDone(void *_harg) {
+ hestArg *harg = (hestArg *)_harg;
+ if (harg->str) {
+ /* If caller wants to keep harg->str around,
+ they need to have copied it (the pointer) and set harg->str to NULL */
+ free(harg->str);
+ }
+ airArrayNix(harg->strArr); /* leave the underlying str alone */
+ return;
+}
+
hestArg *
hestArgNix(hestArg *harg) {
if (harg) {
- if (harg->str) {
- /* If caller wants to keep harg->str around,
- they need to have copied it (the pointer) and set harg->str to NULL */
- free(harg->str);
- }
- airArrayNix(harg->strArr); /* leave the underlying str alone */
+ hargDone(harg);
+ free(harg);
}
return NULL;
}
@@ -84,46 +99,46 @@
void
hestArgAddString(hestArg *harg, const char *str) {
assert(harg && str);
- uint len, si;
- len = AIR_UINT(strlen(str));
- for (si = 0; si < len; si++) {
+ uint len = AIR_UINT(strlen(str));
+ for (uint si = 0; si < len; si++) {
hestArgAddChar(harg, str[si]);
}
return;
}
-typedef union {
- hestArg **harg;
- hestArgVec **havec;
- void **v;
-} hestPtrPtrUnion;
+/* ------------------ hestArgVec = havec = hestArgVec = havec -------------- */
hestArgVec *
hestArgVecNew() {
- hestPtrPtrUnion hppu;
- hestArgVec *havec;
- havec = AIR_CALLOC(1, hestArgVec);
+ hestArgVec *havec = AIR_CALLOC(1, hestArgVec);
assert(havec);
havec->harg = NULL;
havec->len = 0;
+ hestPtrPtrUnion hppu;
hppu.harg = &(havec->harg);
- havec->hargArr = airArrayNew(hppu.v, &(havec->len), sizeof(hestArgVec), INCR);
- airArrayStructCB(havec->hargArr, hargInit, NULL);
+ havec->hargArr = airArrayNew(hppu.v, &(havec->len), sizeof(hestArg), INCR);
+ airArrayStructCB(havec->hargArr, hargInit, hargDone);
return havec;
}
+hestArgVec *
+hestArgVecNix(hestArgVec *havec) {
+ assert(havec);
+ airArrayNuke(havec->hargArr);
+ free(havec);
+ return NULL;
+}
+
void
hestArgVecAppendString(hestArgVec *havec, const char *str) {
- uint idx;
- idx = airArrayLenIncr(havec->hargArr, 1);
+ uint idx = airArrayLenIncr(havec->hargArr, 1);
hestArgAddString(havec->harg + idx, str);
}
void
-hestArgVecPrint(const hestArgVec *havec) {
- uint idx;
- printf("hestArgVec %p has %u args:\n", havec, havec->len);
- for (idx = 0; idx < havec->hargArr->len; idx++) {
+hestArgVecPrint(const char *caller, const hestArgVec *havec) {
+ printf("%s: hestArgVec %p has %u args:\n", caller, havec, havec->len);
+ for (uint idx = 0; idx < havec->hargArr->len; idx++) {
const hestArg *harg;
harg = havec->harg + idx;
printf(" %u:<%s>", idx, harg->str);
@@ -131,11 +146,11 @@
printf("\n");
}
-hestInput *
-hestInputNew(void) {
- hestInput *hin;
- hin = AIR_CALLOC(1, hestInput);
- assert(hin);
+/* --------------------- hestInput = hin = hestInput = hin ----------------- */
+
+static void
+hinInit(void *_hin) {
+ hestInput *hin = (hestInput *)_hin;
hin->source = hestSourceUnknown;
hin->dflt = NULL;
hin->argc = 0;
@@ -143,23 +158,97 @@
hin->argIdx = 0;
hin->fname = NULL;
hin->file = NULL;
+ return;
+}
+
+hestInput *
+hestInputNew(void) {
+ hestInput *hin = AIR_CALLOC(1, hestInput);
+ assert(hin);
+ hinInit(hin);
return hin;
}
-#if 0
+static void
+hinDone(void *_hin) {
+ hestInput *hin = (hestInput *)_hin;
+ /* nothing, for now*/
+ AIR_UNUSED(hin);
+ return;
+}
-/* what is the thing we're currently processing to build up the arg vec */
-typedef struct {
- int source; /* from the hestSource* enum */
- /* ------ if source == hestSourceDefault ------ */
- const char *dflt;
- /* ------ if source == hestSourceCommandLine ------ */
- int argc;
- const char **argv;
- unsigned int argIdx;
- /* ------ if source == hestSourceResponseFile ------ */
- char *fname;
- FILE *file;
-} hestInput;
+hestInput *
+hestInputNix(hestInput *hin) {
+ assert(hin);
+ hinDone(hin);
+ free(hin);
+ return NULL;
+}
-#endif
\ No newline at end of file
+hestInputStack *
+hestInputStackNew(void) {
+ hestInputStack *hist = AIR_CALLOC(1, hestInputStack);
+ assert(hist);
+ hist->hin = NULL;
+ hist->len = 0;
+ hestPtrPtrUnion hppu;
+ hppu.hin = &(hist->hin);
+ hist->hinArr = airArrayNew(hppu.v, &(hist->len), sizeof(hestInput), INCR);
+ airArrayStructCB(hist->hinArr, hinInit, hinDone);
+ return hist;
+}
+
+hestInputStack *
+hestInputStackNix(hestInputStack *hist) {
+ assert(hist);
+ airArrayNuke(hist->hinArr);
+ free(hist);
+ return NULL;
+}
+
+void
+hestInputStackPushCommandLine(hestInputStack *hist, int argc, const char **argv) {
+ assert(hist);
+ uint idx = airArrayLenIncr(hist->hinArr, 1);
+ hist->hin[idx].source = hestSourceCommandLine;
+ hist->hin[idx].argc = argc;
+ hist->hin[idx].argv = argv;
+ hist->hin[idx].argIdx = 0;
+ return;
+}
+
+static int
+histProc(hestArgVec *havec, hestInputStack *hist) {
+ hestInput *hinTop = hist->hin + (hist->len - 1);
+ int done = AIR_FALSE;
+ switch (hinTop->source) {
+ case hestSourceDefault:
+ fprintf(stderr, "%s: sorry hestSourceDefault not implemented\n", __func__);
+ done = AIR_TRUE;
+ break;
+ case hestSourceCommandLine:
+ /* argv[] 0 1 2 3 (argc=4) */
+ /* cmd arg1 arg2 arg3 */
+ if (hinTop->argIdx < hinTop->argc) {
+ /* there are args left to parse */
+ hestArgVecAppendString(havec, hinTop->argv[hinTop->argIdx]);
+ hinTop->argIdx++;
+ }
+ done = (hinTop->argIdx == hinTop->argc);
+ break;
+ case hestSourceResponseFile:
+ fprintf(stderr, "%s: sorry hestSourceResponseFile not implemented\n", __func__);
+ done = AIR_TRUE;
+ break;
+ }
+ return done;
+}
+
+int
+hestInputStackProcess(hestArgVec *havec, hestInputStack *hist) {
+ int done;
+ do {
+ done = histProc(havec, hist);
+ } while (!done);
+ return 0;
+}
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-17 19:39:05 UTC (rev 7444)
+++ teem/trunk/src/hest/hest.h 2025-09-17 19:40:16 UTC (rev 7445)
@@ -145,8 +145,7 @@
/* --------------------- Output
Things set/allocated by hestParse. */
- /* from the hestSource* enum; from whence was this information learned, else
- hestSourceUnknown if not */
+ /* from the hestSource* enum; from whence was this information learned */
int source;
/* if parseStr is non-NULL: a string (freed by hestParseFree) that is a lot like the
string (storing zero or many parameters), from which hestParse ultimately parsed
@@ -231,7 +230,7 @@
/* for building up a "vector" of arguments */
typedef struct {
- hestArg *harg;
+ hestArg *harg; /* array of hestArgs */
unsigned int len;
airArray *hargArr;
} hestArgVec;
@@ -240,16 +239,22 @@
typedef struct {
int source; /* from the hestSource* enum */
/* ------ if source == hestSourceDefault ------ */
- const char *dflt;
+ const char *dflt; /* we do NOT own*/
/* ------ if source == hestSourceCommandLine ------ */
- int argc;
- const char **argv;
+ unsigned int argc;
+ const char **argv; /* we do NOT own */
unsigned int argIdx;
/* ------ if source == hestSourceResponseFile ------ */
- char *fname;
- FILE *file;
+ char *fname; /* we do NOT own */
+ FILE *file; /* someone opened this for us */
} hestInput;
+typedef struct {
+ hestInput *hin; /* array of hestInputs */
+ unsigned int len;
+ airArray *hinArr;
+} hestInputStack;
+
/* defaultsHest.c */
HEST_EXPORT int hestDefaultVerbosity;
HEST_EXPORT int hestDefaultRespFileEnable;
@@ -275,10 +280,21 @@
HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
HEST_EXPORT void hestArgAddString(hestArg *harg, const char *str);
HEST_EXPORT hestArgVec *hestArgVecNew(void);
+HEST_EXPORT hestArgVec *hestArgVecNix(hestArgVec *havec);
HEST_EXPORT void hestArgVecAppendString(hestArgVec *havec, const char *str);
-HEST_EXPORT void hestArgVecPrint(const hestArgVec *havec);
+HEST_EXPORT void hestArgVecPrint(const char *caller, const hestArgVec *havec);
HEST_EXPORT hestInput *hestInputNew(void);
+HEST_EXPORT hestInput *hestInputNix(hestInput *hin);
+HEST_EXPORT hestInputStack *hestInputStackNew(void);
+HEST_EXPORT hestInputStack *hestInputStackNix(hestInputStack *hist);
+HEST_EXPORT void hestInputStackPushCommandLine(hestInputStack *hist, int argc,
+ const char **argv);
+HEST_EXPORT int hestInputStackProcess(hestArgVec *havec, hestInputStack *hist);
+/* parsest.c */
+HEST_EXPORT int hestParse2(hestOpt *opt, int argc, const char **argv, char **errP,
+ const hestParm *hparm);
+
/* methodsHest.c */
HEST_EXPORT const int hestPresent;
HEST_EXPORT int hestSourceUser(int src);
Modified: teem/trunk/src/hest/test/argv.c
===================================================================
--- teem/trunk/src/hest/test/argv.c 2025-09-17 19:39:05 UTC (rev 7444)
+++ teem/trunk/src/hest/test/argv.c 2025-09-17 19:40:16 UTC (rev 7445)
@@ -53,19 +53,21 @@
printf("%s: |%s|\n", argv[0], harg->str);
hestArgAddString(harg, "bingo bob lives\n");
printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgNix(harg);
hestArgVec *havec = hestArgVecNew();
- hestArgVecPrint(havec);
+ hestArgVecPrint(argv[0], havec);
hestArgVecAppendString(havec, "this");
- hestArgVecPrint(havec);
+ hestArgVecPrint(argv[0], havec);
hestArgVecAppendString(havec, "is");
- hestArgVecPrint(havec);
+ hestArgVecPrint(argv[0], havec);
hestArgVecAppendString(havec, "totally");
- hestArgVecPrint(havec);
+ hestArgVecPrint(argv[0], havec);
hestArgVecAppendString(havec, "");
- hestArgVecPrint(havec);
+ hestArgVecPrint(argv[0], havec);
hestArgVecAppendString(havec, "bonkers");
- hestArgVecPrint(havec);
+ hestArgVecPrint(argv[0], havec);
+ hestArgVecNix(havec);
exit(0);
}
Added: teem/trunk/src/hest/test/tparse.c
===================================================================
--- teem/trunk/src/hest/test/tparse.c (rev 0)
+++ teem/trunk/src/hest/test/tparse.c 2025-09-17 19:40:16 UTC (rev 7445)
@@ -0,0 +1,31 @@
+/*
+ Teem: Tools to process and visualize scientific data and images
+ Copyright (C) 2009--2023 University of Chicago
+ Copyright (C) 2005--2008 Gordon Kindlmann
+ Copyright (C) 1998--2004 University of Utah
+
+ This library is free software; you can redistribute it and/or modify it under the terms
+ of the GNU Lesser General Public License (LGPL) as published by the Free Software
+ Foundation; either version 2.1 of the License, or (at your option) any later version.
+ The terms of redistributing and/or modifying this software also include exceptions to
+ the LGPL that facilitate static linking.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "../hest.h"
+
+int
+main(int argc, const char **argv) {
+
+ hestOpt *opt = NULL;
+ int res[2];
+ hestOptAdd(&opt, "res", "sx sy", airTypeInt, 2, 2, res, NULL, "image resolution");
+ hestParse2(opt, argc - 1, argv + 1, NULL, NULL);
+
+ 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-17 19:39:08
|
Revision: 7444
http://sourceforge.net/p/teem/code/7444
Author: kindlmann
Date: 2025-09-17 19:39:05 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
slowly converting some count values to type uint
Modified Paths:
--------------
teem/trunk/src/hest/parseHest.c
teem/trunk/src/hest/privateHest.h
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-17 13:23:35 UTC (rev 7443)
+++ teem/trunk/src/hest/parseHest.c 2025-09-17 19:39:05 UTC (rev 7444)
@@ -443,25 +443,23 @@
return 0;
}
-int
+uint
_hestErrStrlen(const hestOpt *opt, int argc, const char **argv) {
- int ai, optNum, ret, other;
-
- ret = 0;
- optNum = hestOptNum(opt);
- other = AIR_FALSE;
+ uint ret = 0;
+ uint optNum = hestOptNum(opt);
+ int other = AIR_FALSE;
if (argv) {
- for (ai = 0; ai < argc; ai++) {
- ret = AIR_MAX(ret, (int)airStrlen(argv[ai]));
+ for (uint ai = 0; ai < (uint)argc; ai++) {
+ ret = AIR_MAX(ret, airStrlen(argv[ai]));
}
}
- for (ai = 0; ai < optNum; ai++) {
- ret = AIR_MAX(ret, (int)airStrlen(opt[ai].flag));
- ret = AIR_MAX(ret, (int)airStrlen(opt[ai].name));
+ for (uint ai = 0; ai < optNum; ai++) {
+ ret = AIR_MAX(ret, airStrlen(opt[ai].flag));
+ ret = AIR_MAX(ret, airStrlen(opt[ai].name));
other |= opt[ai].type == airTypeOther;
}
- for (ai = airTypeUnknown + 1; ai < airTypeLast; ai++) {
- ret = AIR_MAX(ret, (int)airStrlen(airTypeStr[ai]));
+ for (uint ai = airTypeUnknown + 1; ai < airTypeLast; ai++) {
+ ret = AIR_MAX(ret, airStrlen(airTypeStr[ai]));
}
if (other) {
/* the callback's error() function may sprintf an error message
Modified: teem/trunk/src/hest/privateHest.h
===================================================================
--- teem/trunk/src/hest/privateHest.h 2025-09-17 13:23:35 UTC (rev 7443)
+++ teem/trunk/src/hest/privateHest.h 2025-09-17 19:39:05 UTC (rev 7444)
@@ -21,6 +21,8 @@
extern "C" {
#endif
+#include <assert.h>
+
typedef unsigned int uint;
/* methodsHest.c */
@@ -29,7 +31,7 @@
/* parseHest.c */
extern int _hestOptCheck(const hestOpt *opt, char *err, const hestParm *parm);
-extern int _hestErrStrlen(const hestOpt *opt, int argc, const char **argv);
+extern uint _hestErrStrlen(const hestOpt *opt, int argc, const char **argv);
#ifdef __cplusplus
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-17 13:23:37
|
Revision: 7443
http://sourceforge.net/p/teem/code/7443
Author: kindlmann
Date: 2025-09-17 13:23:35 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
continuing experiment of moving docs into markdown
Modified Paths:
--------------
teem/trunk/src/hest/README.md
teem/trunk/src/hest/TODO.txt
Modified: teem/trunk/src/hest/README.md
===================================================================
--- teem/trunk/src/hest/README.md 2025-09-17 10:18:49 UTC (rev 7442)
+++ teem/trunk/src/hest/README.md 2025-09-17 13:23:35 UTC (rev 7443)
@@ -8,7 +8,7 @@
## 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. Note that `hest` does not follow POSIX conventions (or terminology) for command-line descriptions, because those conventions don't empower the kind of expressivity and flexibility that motivated `hest`'s creation. POSIX certainly isn't determinative for the scientific visualization contexts that Teem was built for.
+`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:
- 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[]`). `hest` processes all the args in the `argv` you give it.
- Arguments like `-v` and `-size`, which identify the variable to be set, are called _flags_.
@@ -20,3 +20,32 @@
- An option may have no parms, one parm, a fixed number of parms, or a variable number of parms. Unflagged options must have one or more parms. With `mv *.txt dir`, the `*.txt` filenames could be parsed as a variable number of parms for an unflagged option, and `dir` would be a fixed single parm for a second unflagged option. Flagged options can appear in any order on the command-line, and the same option can be repeated: later appearances over-ride earlier appearances.
- Sometimes multiple command-line options need to be saved and re-used together, over a time span longer than one shell or any variables set it. 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, and response files can 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.
+
+Note that `hest` does not attempt to follow POSIX conventions (or terminology) for command-line descriptions, because those conventions don't empower the kind of expressivity and flexibility that motivated `hest`'s creation. POSIX does not encompass the scientific computing and visualization contexts that Teem was built for.
+
+## How `hestParse` works
+
+There are lot of moving pieces inside `hestParse`, and the description of how it works is complicated by how flexible a `hestOpt` can be. Two of the fields in the `hestOpt` are `min` and `max`: the min and max number of parameters that are parsed for the option. All the different traditional uses of the command-line can be parameterized in terms of `min` and `max`, but the full range of possibilities of `min`,`max` (which `hest` supports) include some less conventional uses. The _`kind`_ is `hest`'s term for a numeric identifier for the kind of option that a `hestOpt` describes. The following ASCII-art illustrates how `min` and `max` determine `kind`, and also give the prose name for each kind of option, which appears in the code and a description of its operation.
+
+```
+ : (k) kind of and term for .
+ : different possible options; . /
+ : learned by _hestKind(hopt) . /
+ : . /
+ : (5) multiple : (3) multiple
+ 2--: variable : fixed
+ : parms : parms
+ :............................
+ : (4) single : (2) single
+ 1--: variable : fixed
+ : parm : parm
+ :..............
+ : (1) stand-alone
+ 0--: flag;
+ : no parms
+ ^ :............................................
+max | | |
+ min > 0 1 2
+```
+
+The `kind` of option is independent of whether it is flagged or unflagged, and independent of being optional (because a default is given) or required (because no default given).
Modified: teem/trunk/src/hest/TODO.txt
===================================================================
--- teem/trunk/src/hest/TODO.txt 2025-09-17 10:18:49 UTC (rev 7442)
+++ teem/trunk/src/hest/TODO.txt 2025-09-17 13:23:35 UTC (rev 7443)
@@ -6,28 +6,5 @@
hest to do error checking on all other (more error prone) options. But
it would be nice to indicate a parsing order seperate from the option order.
------------------------------------------------------------
-GLK documentary notes to self
- (k) kind of and term for .
- different possible options; . /
- learned by _hestKind(hopt) . /
- . /
- (5) multiple : (3) multiple
- 2 == variable : fixed
- parms : parms
- ..........................
- (4) single : (2) single
- 1 == variable : fixed
- parm : parm
- ................
- (1) stand-alone
- 0 == flag
- ^ no parms
-max | | |
- min > 0 1 2
-
-The kind of option is independent of whether it is flagged or unflagged,
-and of being optional (default given) or required (no default given).
-
??? What is relationship between parseHest.c/whichCase() and hestOpt.alloc ???
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-17 10:18:52
|
Revision: 7442
http://sourceforge.net/p/teem/code/7442
Author: kindlmann
Date: 2025-09-17 10:18:49 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
beginning to create machinery for re-written parsing; for now this lives alongside the old working code
Modified Paths:
--------------
teem/trunk/src/hest/CMakeLists-v2.txt
teem/trunk/src/hest/GNUmakefile
teem/trunk/src/hest/hest.h
Added Paths:
-----------
teem/trunk/src/hest/README.md
teem/trunk/src/hest/argvHest.c
teem/trunk/src/hest/test/argv.c
Modified: teem/trunk/src/hest/CMakeLists-v2.txt
===================================================================
--- teem/trunk/src/hest/CMakeLists-v2.txt 2025-09-17 10:08:23 UTC (rev 7441)
+++ teem/trunk/src/hest/CMakeLists-v2.txt 2025-09-17 10:18:49 UTC (rev 7442)
@@ -1,6 +1,6 @@
_Teem_add_library(${CMAKE_CURRENT_SOURCE_DIR}
SOURCES
- adders.c defaultsHest.c methodsHest.c parseHest.c usage.c
+ adders.c argvHest.c defaultsHest.c methodsHest.c parseHest.c usage.c
# private header
privateHest.h
PUBLIC_HEADERS
Modified: teem/trunk/src/hest/GNUmakefile
===================================================================
--- teem/trunk/src/hest/GNUmakefile 2025-09-17 10:08:23 UTC (rev 7441)
+++ teem/trunk/src/hest/GNUmakefile 2025-09-17 10:18:49 UTC (rev 7442)
@@ -46,9 +46,9 @@
$(L).PublicHdr = hest.h
$(L).PrivateHdr = privateHest.h
$(L).Obj = $(patsubst %.c,%.o, \
- adders.c defaultsHest.c methodsHest.c parseHest.c usage.c \
+ adders.c argvHest.c defaultsHest.c methodsHest.c parseHest.c usage.c \
)
-$(L).Test = ex1 ex2 ex3 ex4 ex5 ex6 strings bday tmpl
+$(L).Test = argv ex1 ex2 ex3 ex4 ex5 ex6 strings bday tmpl
####
####
####
Added: teem/trunk/src/hest/README.md
===================================================================
--- teem/trunk/src/hest/README.md (rev 0)
+++ teem/trunk/src/hest/README.md 2025-09-17 10:18:49 UTC (rev 7442)
@@ -0,0 +1,22 @@
+# `hest`: command-line parsing
+
+## Intro
+
+The purpose of `hest` is to bridge the `int argc`, `char *argv[]` command-line arguments and a set of C variables that need to be set for a C program to run. The variables can be of most any type (boolean, `int`, `float`, `char *` strings, or user-defined types), and the variables can hold single values (such as `float thresh`) or multiple values (such as `float RGBA[4]`).
+
+`hest` was created in 2002 out of frustration with how limiting other C command-line parsing libraries were, and has become essential for the utility of tools like `unu`. To the extent that `hest` bridges the interactive command-line with compiled C code, it has taken on some of the roles that in other contexts are served by scripting languages with C extensions. The `hest` code was revisited in 2023 to add long-overdue support for `--help`, and to add typed functions for specifying options like `hestOptAdd_4_Float`. Re-revisiting the code in 2025 finally fixed long-standing bugs with how quoted strings were handled and how response files were parsed, and to add `-{`, `}-` comments.
+
+## 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. Note that `hest` does not follow POSIX conventions (or terminology) for command-line descriptions, because those conventions don't empower the kind of expressivity and flexibility that motivated `hest`'s creation. POSIX certainly isn't determinative for the scientific visualization contexts that Teem was built for.
+
+- 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[]`). `hest` processes all the args in the `argv` you give it.
+- 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.
+- 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 defined 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.
+- An option may have no parms, one parm, a fixed number of parms, or a variable number of parms. Unflagged options must have one or more parms. With `mv *.txt dir`, the `*.txt` filenames could be parsed as a variable number of parms for an unflagged option, and `dir` would be a fixed single parm for a second unflagged option. Flagged options can appear in any order on the command-line, and the same option can be repeated: later appearances over-ride earlier appearances.
+- Sometimes multiple command-line options need to be saved and re-used together, over a time span longer than one shell or any variables set it. 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, and response files can 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.
Added: teem/trunk/src/hest/argvHest.c
===================================================================
--- teem/trunk/src/hest/argvHest.c (rev 0)
+++ teem/trunk/src/hest/argvHest.c 2025-09-17 10:18:49 UTC (rev 7442)
@@ -0,0 +1,165 @@
+/*
+ Teem: Tools to process and visualize scientific data and images
+ Copyright (C) 2009--2025 University of Chicago
+ Copyright (C) 2005--2008 Gordon Kindlmann
+ Copyright (C) 1998--2004 University of Utah
+
+ This library is free software; you can redistribute it and/or modify it under the terms
+ of the GNU Lesser General Public License (LGPL) as published by the Free Software
+ Foundation; either version 2.1 of the License, or (at your option) any later version.
+ The terms of redistributing and/or modifying this software also include exceptions to
+ the LGPL that facilitate static linking.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "hest.h"
+#include "privateHest.h"
+
+#include <assert.h>
+
+#define INCR 32
+
+/* dereferences as char *, sets to '\0' */
+static void
+setNul(void *_c) {
+ char *c = (char *)(_c);
+ c[0] = '\0';
+ return;
+}
+
+static void
+hargInit(void *_harg) {
+ airPtrPtrUnion appu;
+ hestArg *harg;
+ harg = (hestArg *)_harg;
+ harg->str = NULL;
+ harg->len = 0;
+ appu.c = &(harg->str);
+ harg->strArr = airArrayNew(appu.v, &(harg->len), 1 /* unit */, INCR);
+ airArrayStructCB(harg->strArr, setNul, NULL);
+ /* initialize with \0 so that harg->str is "" */
+ airArrayLenIncr(harg->strArr, 1);
+ /* now harg->str = {0:'\0'} and harg->len = 1; */
+ return;
+}
+
+hestArg *
+hestArgNew(void) {
+ hestArg *harg;
+
+ harg = AIR_CALLOC(1, hestArg);
+ assert(harg);
+ hargInit(harg);
+ return harg;
+}
+
+hestArg *
+hestArgNix(hestArg *harg) {
+ if (harg) {
+ if (harg->str) {
+ /* If caller wants to keep harg->str around,
+ they need to have copied it (the pointer) and set harg->str to NULL */
+ free(harg->str);
+ }
+ airArrayNix(harg->strArr); /* leave the underlying str alone */
+ }
+ return NULL;
+}
+
+void
+hestArgAddChar(hestArg *harg, char cc) {
+ assert(harg);
+ airArrayLenIncr(harg->strArr, 1);
+ /* if this was first call after hestArgNew, we have
+ harg->str = {0:'\0', 1:'\0'} and harg->len = 2 */
+ harg->str[harg->len - 2] = cc;
+ return;
+}
+
+void
+hestArgAddString(hestArg *harg, const char *str) {
+ assert(harg && str);
+ uint len, si;
+ len = AIR_UINT(strlen(str));
+ for (si = 0; si < len; si++) {
+ hestArgAddChar(harg, str[si]);
+ }
+ return;
+}
+
+typedef union {
+ hestArg **harg;
+ hestArgVec **havec;
+ void **v;
+} hestPtrPtrUnion;
+
+hestArgVec *
+hestArgVecNew() {
+ hestPtrPtrUnion hppu;
+ hestArgVec *havec;
+ havec = AIR_CALLOC(1, hestArgVec);
+ assert(havec);
+ havec->harg = NULL;
+ havec->len = 0;
+ hppu.harg = &(havec->harg);
+ havec->hargArr = airArrayNew(hppu.v, &(havec->len), sizeof(hestArgVec), INCR);
+ airArrayStructCB(havec->hargArr, hargInit, NULL);
+ return havec;
+}
+
+void
+hestArgVecAppendString(hestArgVec *havec, const char *str) {
+ uint idx;
+ idx = airArrayLenIncr(havec->hargArr, 1);
+ hestArgAddString(havec->harg + idx, str);
+}
+
+void
+hestArgVecPrint(const hestArgVec *havec) {
+ uint idx;
+ printf("hestArgVec %p has %u args:\n", havec, havec->len);
+ for (idx = 0; idx < havec->hargArr->len; idx++) {
+ const hestArg *harg;
+ harg = havec->harg + idx;
+ printf(" %u:<%s>", idx, harg->str);
+ }
+ printf("\n");
+}
+
+hestInput *
+hestInputNew(void) {
+ hestInput *hin;
+ hin = AIR_CALLOC(1, hestInput);
+ assert(hin);
+ hin->source = hestSourceUnknown;
+ hin->dflt = NULL;
+ hin->argc = 0;
+ hin->argv = NULL;
+ hin->argIdx = 0;
+ hin->fname = NULL;
+ hin->file = NULL;
+ return hin;
+}
+
+#if 0
+
+/* what is the thing we're currently processing to build up the arg vec */
+typedef struct {
+ int source; /* from the hestSource* enum */
+ /* ------ if source == hestSourceDefault ------ */
+ const char *dflt;
+ /* ------ if source == hestSourceCommandLine ------ */
+ int argc;
+ const char **argv;
+ unsigned int argIdx;
+ /* ------ if source == hestSourceResponseFile ------ */
+ char *fname;
+ FILE *file;
+} hestInput;
+
+#endif
\ No newline at end of file
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-17 10:08:23 UTC (rev 7441)
+++ teem/trunk/src/hest/hest.h 2025-09-17 10:18:49 UTC (rev 7442)
@@ -222,6 +222,34 @@
disable this behavior entirely. */
} hestParm;
+/* for building up and representing one argument */
+typedef struct {
+ char *str;
+ unsigned int len; /* NOT strlen; this includes '\0'-termination */
+ airArray *strArr;
+} hestArg;
+
+/* for building up a "vector" of arguments */
+typedef struct {
+ hestArg *harg;
+ unsigned int len;
+ airArray *hargArr;
+} hestArgVec;
+
+/* what is the thing we're currently processing to build up the arg vec */
+typedef struct {
+ int source; /* from the hestSource* enum */
+ /* ------ if source == hestSourceDefault ------ */
+ const char *dflt;
+ /* ------ if source == hestSourceCommandLine ------ */
+ int argc;
+ const char **argv;
+ unsigned int argIdx;
+ /* ------ if source == hestSourceResponseFile ------ */
+ char *fname;
+ FILE *file;
+} hestInput;
+
/* defaultsHest.c */
HEST_EXPORT int hestDefaultVerbosity;
HEST_EXPORT int hestDefaultRespFileEnable;
@@ -241,6 +269,16 @@
HEST_EXPORT char hestDefaultVarParamStopFlag;
HEST_EXPORT char hestDefaultMultiFlagSep;
+/* argvHest.c */
+HEST_EXPORT hestArg *hestArgNew(void);
+HEST_EXPORT hestArg *hestArgNix(hestArg *harg);
+HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
+HEST_EXPORT void hestArgAddString(hestArg *harg, const char *str);
+HEST_EXPORT hestArgVec *hestArgVecNew(void);
+HEST_EXPORT void hestArgVecAppendString(hestArgVec *havec, const char *str);
+HEST_EXPORT void hestArgVecPrint(const hestArgVec *havec);
+HEST_EXPORT hestInput *hestInputNew(void);
+
/* methodsHest.c */
HEST_EXPORT const int hestPresent;
HEST_EXPORT int hestSourceUser(int src);
Added: teem/trunk/src/hest/test/argv.c
===================================================================
--- teem/trunk/src/hest/test/argv.c (rev 0)
+++ teem/trunk/src/hest/test/argv.c 2025-09-17 10:18:49 UTC (rev 7442)
@@ -0,0 +1,71 @@
+/*
+ Teem: Tools to process and visualize scientific data and images
+ Copyright (C) 2009--2023 University of Chicago
+ Copyright (C) 2005--2008 Gordon Kindlmann
+ Copyright (C) 1998--2004 University of Utah
+
+ This library is free software; you can redistribute it and/or modify it under the terms
+ of the GNU Lesser General Public License (LGPL) as published by the Free Software
+ Foundation; either version 2.1 of the License, or (at your option) any later version.
+ The terms of redistributing and/or modifying this software also include exceptions to
+ the LGPL that facilitate static linking.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "../hest.h"
+
+int
+main(int argc, const char **argv) {
+
+ AIR_UNUSED(argc);
+ printf("%s: yo\n", argv[0]);
+ hestArg *harg = hestArgNew();
+ printf("%s: harg = %p\n", argv[0], harg);
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'c');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'a');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 't');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'a');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 's');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 't');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'r');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'o');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'p');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'h');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, 'e');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddChar(harg, '!');
+ printf("%s: |%s|\n", argv[0], harg->str);
+ hestArgAddString(harg, "bingo bob lives\n");
+ printf("%s: |%s|\n", argv[0], harg->str);
+
+ hestArgVec *havec = hestArgVecNew();
+ hestArgVecPrint(havec);
+ hestArgVecAppendString(havec, "this");
+ hestArgVecPrint(havec);
+ hestArgVecAppendString(havec, "is");
+ hestArgVecPrint(havec);
+ hestArgVecAppendString(havec, "totally");
+ hestArgVecPrint(havec);
+ hestArgVecAppendString(havec, "");
+ hestArgVecPrint(havec);
+ hestArgVecAppendString(havec, "bonkers");
+ hestArgVecPrint(havec);
+
+ 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-17 10:08:26
|
Revision: 7441
http://sourceforge.net/p/teem/code/7441
Author: kindlmann
Date: 2025-09-17 10:08:23 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
ah crap previous commit was broken
Modified Paths:
--------------
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/parseHest.c
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-17 09:58:09 UTC (rev 7440)
+++ teem/trunk/src/hest/hest.h 2025-09-17 10:08:23 UTC (rev 7441)
@@ -241,16 +241,6 @@
HEST_EXPORT char hestDefaultVarParamStopFlag;
HEST_EXPORT char hestDefaultMultiFlagSep;
-/* argvHest.c */
-HEST_EXPORT hestArg *hestArgNew(void);
-HEST_EXPORT hestArg *hestArgNix(hestArg *harg);
-HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
-HEST_EXPORT void hestArgAddString(hestArg *harg, const char *str);
-HEST_EXPORT hestArgVec *hestArgVecNew(void);
-HEST_EXPORT void hestArgVecAppendString(hestArgVec *havec, const char *str);
-HEST_EXPORT void hestArgVecPrint(const hestArgVec *havec);
-HEST_EXPORT hestInput *hestInputNew(void);
-
/* methodsHest.c */
HEST_EXPORT const int hestPresent;
HEST_EXPORT int hestSourceUser(int src);
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-17 09:58:09 UTC (rev 7440)
+++ teem/trunk/src/hest/parseHest.c 2025-09-17 10:08:23 UTC (rev 7441)
@@ -1143,7 +1143,6 @@
/* 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[op] && vP) {
- int pret;
switch (type) {
case airTypeEnum:
if (1 != airParseStrE((int *)vP, optParms[op], " ", 1, opt[op].enm)) {
@@ -1273,6 +1272,7 @@
case 4:
/* -------- optional single variables -------- */
if (optParms[op] && vP) {
+ int pret;
switch (type) {
case airTypeChar:
/* no "inversion" for chars: using the flag with no parameter is the same as
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-17 09:58:14
|
Revision: 7440
http://sourceforge.net/p/teem/code/7440
Author: kindlmann
Date: 2025-09-17 09:58:09 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
one API CHANGE but then lots of variable renaming (such as parm to hparm, and using less crytically short variable names inside parseHest.c) as part of making sense of hest code. The API CHANGE is that the hestSource* enum no longer has hestSourceUser; it was split into hestSourceCommandLine and hestSourceReponseFile. But to reduce disruption, a new hestSourceUser() helper function returns non-zero for those two source enum values; this affects lots of Teem-using code. This change sets the stage for the ongoing rewrite of hestParse
Modified Paths:
--------------
teem/trunk/src/bin/gprobe.c
teem/trunk/src/bin/ilk.c
teem/trunk/src/bin/overrgb.c
teem/trunk/src/bin/puller-with-Deft.c
teem/trunk/src/bin/puller.c
teem/trunk/src/hest/hest.h
teem/trunk/src/hest/methodsHest.c
teem/trunk/src/hest/parseHest.c
teem/trunk/src/hest/privateHest.h
teem/trunk/src/hest/test/ex3.c
teem/trunk/src/hest/test/ex6.c
teem/trunk/src/hest/usage.c
teem/trunk/src/meet/test/strace.c
teem/trunk/src/unrrdu/axinfo.c
teem/trunk/src/unrrdu/axinsert.c
teem/trunk/src/unrrdu/basinfo.c
teem/trunk/src/unrrdu/ilk.c
teem/trunk/src/unrrdu/make.c
teem/trunk/src/unrrdu/quantize.c
Modified: teem/trunk/src/bin/gprobe.c
===================================================================
--- teem/trunk/src/bin/gprobe.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/gprobe.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -438,7 +438,7 @@
/* we got the whole stack blar parm here */
gotOld = AIR_FALSE;
for (nsi = 0; nsi < NON_SBP_OPT_NUM; nsi++) {
- gotOld |= (hestSourceUser == hopt[nonSbpOpi[nsi]].source);
+ gotOld |= hestSourceUser(hopt[nonSbpOpi[nsi]].source);
}
if (gotOld) {
fprintf(stderr,
@@ -446,7 +446,7 @@
"scale-space options (used",
me);
for (nsi = 0; nsi < NON_SBP_OPT_NUM; nsi++) {
- if (hestSourceUser == hopt[nonSbpOpi[nsi]].source) {
+ if (hestSourceUser(hopt[nonSbpOpi[nsi]].source)) {
fprintf(stderr, " -%s", hopt[nonSbpOpi[nsi]].flag);
}
}
Modified: teem/trunk/src/bin/ilk.c
===================================================================
--- teem/trunk/src/bin/ilk.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/ilk.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -151,7 +151,7 @@
bkg = _bkg;
}
} else {
- if (hestSourceUser == hopt[bkgIdx].source) {
+ if (hestSourceUser(hopt[bkgIdx].source)) {
fprintf(stderr,
"%s: WARNING: got %u background colors, but with boundary %s, "
"they will not be used\n",
Modified: teem/trunk/src/bin/overrgb.c
===================================================================
--- teem/trunk/src/bin/overrgb.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/overrgb.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -132,7 +132,7 @@
return 1;
}
- if (hestSourceUser == hopt[srgbIdx].source && !nrrdFormatPNG->available()) {
+ if (hestSourceUser(hopt[srgbIdx].source) && !nrrdFormatPNG->available()) {
fprintf(stderr,
"%s: wanted to store sRGB intent \"%s\" in PNG output, but "
"this Teem build does not support the PNG file format.",
@@ -254,7 +254,7 @@
rgbaD += 4;
}
- if (hestSourceUser == hopt[srgbIdx].source) {
+ if (hestSourceUser(hopt[srgbIdx].source)) {
/* HEY copied to unrrdu/quantize.c */
nio = nrrdIoStateNew();
airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways);
Modified: teem/trunk/src/bin/puller-with-Deft.c
===================================================================
--- teem/trunk/src/bin/puller-with-Deft.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/puller-with-Deft.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -1124,13 +1124,13 @@
airMopError(mop);
return 1;
}
- if (!kssFinished && hestSourceUser == hopt[kssOpi].source) {
+ if (!kssFinished && hestSourceUser(hopt[kssOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified blurring kernels\n\n\n",
me, hopt[kssOpi].flag);
}
- if (!bspFinished && hestSourceUser == hopt[bspOpi].source) {
+ if (!bspFinished && hestSourceUser(hopt[bspOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified boundary specs\n\n\n",
Modified: teem/trunk/src/bin/puller.c
===================================================================
--- teem/trunk/src/bin/puller.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/bin/puller.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -357,13 +357,13 @@
airMopError(mop);
return 1;
}
- if (!kssFinished && hestSourceUser == hopt[kssOpi].source) {
+ if (!kssFinished && hestSourceUser(hopt[kssOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified blurring kernels\n\n\n",
me, hopt[kssOpi].flag);
}
- if (!bspFinished && hestSourceUser == hopt[bspOpi].source) {
+ if (!bspFinished && hestSourceUser(hopt[bspOpi].source)) {
fprintf(stderr,
"\n\n%s: WARNING! Used the -%s flag, but the "
"meetPullVol specified boundary specs\n\n\n",
Modified: teem/trunk/src/hest/hest.h
===================================================================
--- teem/trunk/src/hest/hest.h 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/hest/hest.h 2025-09-17 09:58:09 UTC (rev 7440)
@@ -45,13 +45,13 @@
******** hestSource* enum
**
** records whether the info to satisfy a particular option came from the default or from
-** the user (command-line or response file). Distinguishing command-line from response
-** file would take a much more significant code restructuring
+** the user: command-line or response file.
*/
enum {
- hestSourceUnknown, /* 0 */
- hestSourceDefault, /* 1 */
- hestSourceUser, /* 2 */
+ hestSourceUnknown, /* 0 */
+ hestSourceDefault, /* 1 */
+ hestSourceCommandLine, /* 2 (formerly called hestSourceUser) */
+ hestSourceResponseFile, /* 3 */
hestSourceLast
};
@@ -74,17 +74,16 @@
multiple parameter options. A non-zero return value is considered an error. Error
message goes in the err string */
void *(*destroy)(void *ptr);
- /* if non-NULL, this is the destructor that will be called by hestParseFree() (or by
- hestParse() if there is an error midway through parsing). The argument is NOT the
- same as passed to parse(): it is the result of dereferencing the argument to parse()
- */
+ /* if non-NULL, the destructor that will be called by hestParseFree() (or by
+ hestParse() if there is an error during parsing). The argument is NOT the same as
+ passed to parse(): it is the result of dereferencing the argument to parse() */
} hestCB;
/*
******** hestOpt struct
**
-** information which specifies one command-line option,
-** and describes it how it was parsed
+** information which specifies one command-line option, records state used during
+** parsing, and provides summary output info following parsing.
*/
typedef struct {
/* --------------------- "input" fields
@@ -97,7 +96,7 @@
int max; /* max # of parameters for option,
or -1 for "there is no max; # parms is unbounded" */
void *valueP; /* storage of parsed values */
- char *dflt, /* default value written out as string */
+ char *dflt, /* default value(s) written out as string */
*info; /* description to be printed with "glossary" info */
unsigned int *sawP; /* used ONLY for multiple variable parameter options
(min < max >= 2): storage of # of parsed values */
@@ -128,46 +127,50 @@
array of strings
3: free((*valueP)[i]) and free(*valueP), because it is a dynamically
allocated array of strings */
- /* Since hest's beginning, the basic container for a set of options was an array of
- hestOpt structs (not pointers to them, which rules out argv-style NULL-termination of
- the array), also unfortunately with no other top-level container (which is why
- helpWanted below is set only in the first hestOpt of the array). hestOptAdd has
- historically reallocated the entire array, incrementing the length only by one with
- each call, while maintaining a single terminating hestOpt, wherein some fields were set
- to special values to indicate termination. With the 2023 code revisit, that was deemed
- even uglier than this hack: the first hestOpt now stores here in arrAlloc the allocated
- length of the hestOpt array, and in arrLen the number of hestOpts actually used and
- set. This facilitates implementing something much like an airArray, but without the
- burden of extra calls for the user (like airArrayLenIncr), nor new kinds of containers
- for hest and its users to manage: it is just the same array of hestOpt structs */
+ /* Since hest's beginning in 2002, the basic container for a set of options was an
+ array of hestOpt structs (not pointers to them, which rules out argv-style
+ NULL-termination of the array), also unfortunately with no other top-level container
+ or hestContext (which is why helpWanted below is set only in the first hestOpt of the
+ array). hestOptAdd has historically reallocated the entire array, incrementing the
+ length only by one with each call, while maintaining a single terminating hestOpt,
+ wherein some fields were set to special values to indicate termination. With the 2023
+ code revisit, that was deemed even uglier than the new and current hack: the first
+ hestOpt now stores here in arrAlloc the allocated length of the hestOpt array, and in
+ arrLen the number of hestOpts actually used and set. This facilitates implementing
+ something much like an airArray, but without the burden of extra calls for the user
+ (like airArrayLenIncr), nor new kinds of containers for hest and its users to manage:
+ it is just the same array of hestOpt structs */
unsigned int arrAlloc, arrLen;
/* --------------------- Output
Things set/allocated by hestParse. */
- int source; /* from the hestSource* enum; from whence was this information learned,
- else hestSourceUnknown if not */
- char *parmStr; /* if non-NULL: a string (freed by hestParseFree) from which hestParse
- ultimately parsed whatever values were set in *valueP. All the
- parameters associated with this option are joined (with " " separation)
- into this single string. hestParse has always formed this string
- internally as part of its operation, but only belatedly (in 2023) is a
- copy of that string being made available here to the caller. Note that
- in the case of single variable parameter options used without a
- parameter, the value stored will be "inverted" from the string here. */
- int helpWanted; /* hestParse() saw something (like "--help") in one of the given
- arguments that looks like a call for help (and respectDashDashHelp is
- set in the hestParm), so it recorded that here. There is unfortunately
- no other top-level output container for info generated by hestParse(),
- so this field is going to be set only in the *first* hestOpt passed to
- hestParse(), even though that hestOpt has no particular relation to
- where hestParse() saw the call for help. */
+ /* from the hestSource* enum; from whence was this information learned, else
+ hestSourceUnknown if not */
+ int source;
+ /* if parseStr is non-NULL: a string (freed by hestParseFree) that is a lot like the
+ string (storing zero or many parameters), from which hestParse ultimately parsed
+ whatever values were set in *valueP above. Internally, hest maintains an argc,argv-like
+ representation of the info to parse, but here it is joined back together into a
+ space-delimited single string. Note that in the case of single variable parameter
+ options used without a parameter, the value stored will be "inverted" from the string
+ here. */
+ char *parmStr;
+ /* helpWanted indicates that hestParse() saw something (like "--help") in one of the
+ given arguments that looks like a call for help, and that respectDashDashHelp is set in
+ the hestParm. There is unfortunately no other top-level output container for info
+ generated by hestParse(), so this field is going to be set only in the *first* hestOpt
+ passed to hestParse(), even though that hestOpt has no particular relation to where
+ hestParse() saw the call for help. */
+ int helpWanted;
} hestOpt;
/*
******** hestParm struct
**
-** parameters to control behavior of hest functions.
+** parameters to control behavior of hest functions. Not to be confused with the
+** "parameters" to a hestOpt from which it parses values. Code should use "hparm" for
+** the pointer to this struct.
**
** GK: Don't even think about storing per-parse state in here.
*/
@@ -175,7 +178,7 @@
int verbosity, /* verbose diagnostic messages to stdout */
respFileEnable, /* whether or not to use response files */
elideSingleEnumType, /* if type is airTypeEnum, and if it's a single fixed parameter
- option, then don't bother printing the type information as
+ option, then don't bother printing the type information as
part of hestGlossary() */
elideSingleOtherType, /* like above, but for airTypeOther */
elideSingleOtherDefault, /* don't display default for single fixed airTypeOther
@@ -238,11 +241,22 @@
HEST_EXPORT char hestDefaultVarParamStopFlag;
HEST_EXPORT char hestDefaultMultiFlagSep;
+/* argvHest.c */
+HEST_EXPORT hestArg *hestArgNew(void);
+HEST_EXPORT hestArg *hestArgNix(hestArg *harg);
+HEST_EXPORT void hestArgAddChar(hestArg *harg, char cc);
+HEST_EXPORT void hestArgAddString(hestArg *harg, const char *str);
+HEST_EXPORT hestArgVec *hestArgVecNew(void);
+HEST_EXPORT void hestArgVecAppendString(hestArgVec *havec, const char *str);
+HEST_EXPORT void hestArgVecPrint(const hestArgVec *havec);
+HEST_EXPORT hestInput *hestInputNew(void);
+
/* methodsHest.c */
HEST_EXPORT const int hestPresent;
+HEST_EXPORT int hestSourceUser(int src);
HEST_EXPORT hestParm *hestParmNew(void);
-HEST_EXPORT hestParm *hestParmFree(hestParm *parm);
-HEST_EXPORT void *hestParmFree_vp(void *parm);
+HEST_EXPORT hestParm *hestParmFree(hestParm *hparm);
+HEST_EXPORT void *hestParmFree_vp(void *hparm);
HEST_EXPORT int hestParmColumnsIoctl(hestParm *hparm, unsigned int nonIoctlColumns);
HEST_EXPORT void hestOptSingleSet(hestOpt *opt, const char *flag, const char *name,
int type, unsigned int min, int max, void *valueP,
@@ -269,34 +283,35 @@
/* parseHest.c */
HEST_EXPORT int hestParse(hestOpt *opt, int argc, const char **argv, char **errP,
- const hestParm *parm);
+ const hestParm *hparm);
HEST_EXPORT void *hestParseFree(hestOpt *opt);
HEST_EXPORT void hestParseOrDie(hestOpt *opt, int argc, const char **argv,
- hestParm *parm, const char *me, const char *info,
+ hestParm *hparm, const char *me, const char *info,
int doInfo, int doUsage, int doGlossary);
/* usage.c */
HEST_EXPORT void _hestPrintStr(FILE *f, unsigned int indent, unsigned int already,
unsigned int width, const char *_str, int bslash);
-HEST_EXPORT int hestMinNumArgs(hestOpt *opt);
-HEST_EXPORT void hestUsage(FILE *file, hestOpt *opt, const char *argv0,
- const hestParm *parm);
-HEST_EXPORT void hestGlossary(FILE *file, hestOpt *opt, const hestParm *parm);
+HEST_EXPORT int hestMinNumArgs(const hestOpt *opt);
+HEST_EXPORT void hestUsage(FILE *file, const hestOpt *opt, const char *argv0,
+ const hestParm *hparm);
+HEST_EXPORT void hestGlossary(FILE *file, const hestOpt *opt, const hestParm *hparm);
HEST_EXPORT void hestInfo(FILE *file, const char *argv0, const char *info,
- const hestParm *parm);
+ const hestParm *hparm);
/* adders.c */
HEST_EXPORT void hestOptAddDeclsPrint(FILE *f);
/* Many many non-var-args alternatives to hestOptAdd, also usefully type-specific for the
type of value to be parsed in a way that hestOptAdd_nva cannot match. These capture all
-the common uses (and then some) of hest within Teem. They can be categorized, like
-hestOpt->kind, in terms of the min, max number of (type T) parameters to the option:
+the common uses (and then some) of hest within Teem. They are named according
+to kind, and according to the type T parameters to the option:
- min == max == 0 hestOptAdd_Flag (stand-alone flag; no parameters)
- min == max == 1 hestOptAdd_1_T single fixed parameter
- min == max >= 2 hestOptAdd_{2,3,4,N}_T multiple fixed parameters
- min == 0; max == 1 hestOptAdd_1v_T single variable parameter
- min < max; max >= 2 hestOptAdd_Nv_T multiple variable parameters
+min, max function family kind description
+min == max == 0 hestOptAdd_Flag 1 (stand-alone flag; no parameters)
+min == max == 1 hestOptAdd_1_T 2 single fixed parameter
+min == max >= 2 hestOptAdd_{2,3,4,N}_T 3 multiple fixed parameters
+min == 0; max == 1 hestOptAdd_1v_T 4 single variable parameter
+min < max; max >= 2 hestOptAdd_Nv_T 5 multiple variable parameters
An airEnum* is passed for _Enum options; or a hestCB* for _Other options. The number of
parameters *sawP that hestParm saw on the command-line is passed for the _Nv_ options.
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/hest/methodsHest.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -27,6 +27,11 @@
const int hestPresent = 42;
+int
+hestSourceUser(int src) {
+ return (hestSourceCommandLine == src || hestSourceResponseFile == src);
+}
+
/* INCR is like airArray->incr: granularity with which we (linearly) reallocate the
hestOpt array. Very few uses of hest within Teem use more than 32 options. Hopefully
this avoids all the reallocations in the past action of hestOptAdd and the like. */
@@ -34,33 +39,24 @@
hestParm *
hestParmNew() {
- hestParm *parm;
+ hestParm *hparm;
- parm = AIR_CALLOC(1, hestParm);
- assert(parm);
- parm->verbosity = hestDefaultVerbosity;
- parm->respFileEnable = hestDefaultRespFileEnable;
- parm->elideSingleEnumType = hestDefaultElideSingleEnumType;
- parm->elideSingleOtherType = hestDefaultElideSingleOtherType;
- parm->elideSingleOtherDefault = hestDefaultElideSingleOtherDefault;
- parm->greedySingleString = hestDefaultGreedySingleString;
- parm->elideSingleNonExistFloatDefault = hestDefaultElideSingleNonExistFloatDefault;
- parm->elideMultipleNonExistFloatDefault = hestDefaultElideMultipleNonExistFloatDefault;
- parm->elideSingleEmptyStringDefault = hestDefaultElideSingleEmptyStringDefault;
- parm->elideMultipleEmptyStringDefault = hestDefaultElideMultipleEmptyStringDefault;
- parm->cleverPluralizeOtherY = hestDefaultCleverPluralizeOtherY;
- parm->columns = hestDefaultColumns;
- parm->respFileFlag = hestDefaultRespFileFlag;
- parm->respFileComment = hestDefaultRespFileComment;
- parm->varParamStopFlag = hestDefaultVarParamStopFlag;
- parm->multiFlagSep = hestDefaultMultiFlagSep;
- /* for these most recent addition to the hestParm,
- abstaining from added yet another default global variable */
- parm->dieLessVerbose = AIR_FALSE;
- parm->noBlankLineBeforeUsage = AIR_FALSE;
+ hparm = AIR_CALLOC(1, hestParm);
+ assert(hparm);
+ hparm->verbosity = hestDefaultVerbosity;
+ hparm->respFileEnable = hestDefaultRespFileEnable;
+ hparm->elideSingleEnumType = hestDefaultElideSingleEnumType;
+ hparm->elideSingleOtherType = hestDefaultElideSingleOtherType;
+ hparm->elideSingleOtherDefault = hestDefaultElideSingleOtherDefault;
+ hparm->greedySingleString = hestDefaultGreedySingleString;
+ hparm->elideSingleNonExistFloatDefault = hestDefaultElideSingleNonExistFloatDefault;
+ hparm->elideMultipleNonExistFloatDefault
+ = hestDefaultElideMultipleNonExistFloatDefault;
+ hparm->elideSingleEmptyStringDefault = hestDefaultElideSingleEmptyStringDefault;
+ hparm->elideMultipleEmptyStringDefault = hestDefaultElideMultipleEmptyStringDefault;
/* It would be really nice for parm->respectDashDashHelp to default to true:
widespread conventions say what "--help" should mean e.g. https://clig.dev/#help
- HOWEVER, the problem is with how hestParse is called and how the return
+ HOWEVER, the problem is with how hestParse is called and how its return value
is interpreted as a boolean:
- zero has meant that hestParse could set values for all the options (either
from the command-line or from supplied defaults), and
@@ -70,17 +66,29 @@
is the precedent, so we have to work with it by default.
Now, with parm->respectDashDashHelp, upon seeing "--help", hestParse returns 0,
and sets helpWanted in the first hestOpt, and the caller will have to know
- to check for that. This logic is handled by hestParseOrDie, but maybe in
- the future there can be a different top-level parser function that turns on
- parm->respectDashDashHelp and knows how to check the results */
- parm->respectDashDashHelp = AIR_FALSE;
- return parm;
+ to check for that. This logic is handled by hestParse but maybe in the future there
+ can be a different top-level parser function that turns on parm->respectDashDashHelp
+ and knows how to check the results */
+ hparm->respectDashDashHelp = AIR_FALSE;
+ hparm->noArgsIsNoProblem = hestDefaultNoArgsIsNoProblem;
+ hparm->greedySingleString = hestDefaultGreedySingleString;
+ hparm->cleverPluralizeOtherY = hestDefaultCleverPluralizeOtherY;
+ /* for these most recent addition to the hestParm,
+ abstaining from added yet another default global variable */
+ hparm->dieLessVerbose = AIR_FALSE;
+ hparm->noBlankLineBeforeUsage = AIR_FALSE;
+ hparm->columns = hestDefaultColumns;
+ hparm->respFileFlag = hestDefaultRespFileFlag;
+ hparm->respFileComment = hestDefaultRespFileComment;
+ hparm->varParamStopFlag = hestDefaultVarParamStopFlag;
+ hparm->multiFlagSep = hestDefaultMultiFlagSep;
+ return hparm;
}
hestParm *
-hestParmFree(hestParm *parm) {
+hestParmFree(hestParm *hparm) {
- airFree(parm);
+ airFree(hparm);
return NULL;
}
@@ -387,8 +395,8 @@
/* experiments in adding a nixer/free-er that exactly matches the airMopper type,
as part of trying to avoid all "undefined behavior" */
void *
-hestParmFree_vp(void *_parm) {
- return AIR_VOIDP(hestParmFree((hestParm *)_parm));
+hestParmFree_vp(void *_hparm) {
+ return AIR_VOIDP(hestParmFree((hestParm *)_hparm));
}
void *
hestOptFree_vp(void *_opt) {
@@ -399,7 +407,7 @@
hestOptCheck(hestOpt *opt, char **errP) {
static const char me[] = "hestOptCheck";
char *err;
- hestParm *parm;
+ hestParm *hparm;
int big;
big = _hestErrStrlen(opt, 0, NULL);
@@ -411,8 +419,8 @@
if (errP) *errP = NULL;
return 1;
}
- parm = hestParmNew();
- if (_hestPanic(opt, err, parm)) {
+ hparm = hestParmNew();
+ if (_hestOptCheck(opt, err, hparm)) {
/* problems */
if (errP) {
/* they did give a pointer address; they'll free it */
@@ -421,12 +429,12 @@
/* they didn't give a pointer address; their loss */
free(err);
}
- hestParmFree(parm);
+ hestParmFree(hparm);
return 1;
}
/* else, no problems */
if (errP) *errP = NULL;
free(err);
- hestParmFree(parm);
+ hestParmFree(hparm);
return 0;
}
Modified: teem/trunk/src/hest/parseHest.c
===================================================================
--- teem/trunk/src/hest/parseHest.c 2025-09-17 09:51:26 UTC (rev 7439)
+++ teem/trunk/src/hest/parseHest.c 2025-09-17 09:58:09 UTC (rev 7440)
@@ -22,21 +22,32 @@
#include <string.h>
-#define ME ((parm && parm->verbosity) ? me : "")
+/* A little trickery for error reporting. For many of the functions here, if they hit an
+error and hparm->verbosity is set, then we should reveal the current function name (set
+by convention in `me`). But without verbosity, we hide that function name, so it appears
+that the error is coming from the caller (probably identified as argv[0]). However, that
+means that functions using this `ME` macro should (in defiance of convention) set to `me`
+to `functionname: ` (NOTE the `: `) so that all of that goes away without verbosity. And,
+that means that error message generation here should also defy convention and instead of
+being "%s: what happened" it should just be "%swhat happened" */
+#define ME ((hparm && hparm->verbosity) ? me : "")
/*
argsInResponseFiles()
-returns the number of "args" (i.e. the number of space-separated strings) that will be
-parsed from the response files. The role of this function is solely to simplify the task
-of avoiding memory leaks. By knowing exactly how many args we'll get in the response
-file, then hestParse() can allocate its local argv[] for exactly as long as it needs to
-be, and we can avoid using an airArray. The drawback is that we open and read through
-the response files twice. Alas.
+returns the number of "args" (i.e. the number of AIR_WHITESPACE-separated strings) that
+will be parsed from the response files. The role of this function is solely to simplify
+the task of avoiding memory leaks. By knowing exactly how many args we'll get in the
+response file, then hestParse() can allocate its local argv[] for exactly as long as it
+needs to be, and we can avoid using an airArray. The drawback is that we open and read
+through the response files twice. Alas.
+
+NOTE: Currently, this makes no effort to interpreted quoted strings "like this one" as a
+single arg, and we do not do any VTAB-separating of args here.
*/
static int
argsInResponseFiles(int *argsNumP, int *respFileNumP, const char **argv, char *err,
- const hestParm *parm) {
+ const hestParm *hparm) {
FILE *file;
static const char me[] = "argsInResponseFiles: ";
char line[AIR_STRLEN_HUGE + 1], *pound;
@@ -44,7 +55,7 @@
*argsNumP = 0;
*respFileNumP = 0;
- if (!parm->respFileEnable) {
+ if (!hparm->respFileEnable) {
/* don't do response files; we're done */
return 0;
}
@@ -51,7 +62,7 @@
argIdx = 0;
while (argv /* can be NULL for testing */ && argv[argIdx]) {
- if (parm->respFileFlag == argv[argIdx][0]) {
+ if (hparm->respFileFlag == argv[argIdx][0]) {
/* argv[argIdx] looks like its naming a response file */
/* NOTE: despite the repeated temptation: "-" aka stdin cannot be a response file,
because it is going to be read in twice: once by argsInResponseFiles, and then
@@ -68,7 +79,7 @@
len = airOneLine(file, line, AIR_STRLEN_HUGE + 1);
while (len > 0) {
/* first # (or #-alike char) is turned into line end */
- if ((pound = strchr(line, parm->respFileComment))) {
+ if ((pound = strchr(line, hparm->respFileComment))) {
*pound = '\0';
}
/* count words in line */
@@ -85,14 +96,14 @@
return 0;
}
-/* printArgv prints (for debugging) the given non-const argv array */
+/* prints (for debugging) the given non-const argv array */
static void
printArgv(int argc, char **argv, const char *pfx) {
- int a;
+ int ai;
printf("%sargc=%d : ", pfx ? pfx : "", argc);
- for (a = 0; a < argc; a++) {
- printf("%s%s ", pfx ? pfx : "", argv[a]);
+ for (ai = 0; ai < argc; ai++) {
+ printf("%s%s ", pfx ? pfx : "", argv[ai]);
}
printf("%s\n", pfx ? pfx : "");
}
@@ -101,14 +112,21 @@
copyArgv()
Copies given oldArgv to newArgv, including (if they are enabled) injecting the contents
-of response files. BUT: this stops upon seeing "--help" if parm->respectDashDashHelp.
+of response files. Returns the number of AIR_WHITESPACE-separated arguments in newArgv.
Allocations of the strings in newArgv are remembered (to be airFree'd later) in the given
-pmop. Returns the number of args set in newArgv, and sets sawHelp if saw "--help".
+pmop. Returns the number of args set in newArgv. BUT: upon seeing "--help" if
+parm->respectDashDashHelp, this sets *sawHelp=AIR_TRUE, and then finishes early.
-For a brief moment prior to the 2.0.0 release, this also stopped if it saw "--" (or
-whatever parm->varParamStopFlag implies), but that meant "--" is a brick wall that
-hestParse could never see past. But that misunderstands the relationship between how
-hestParse works and how the world uses "--". According to POSIX guidelines:
+NOTE: like argsInResponseFiles, this is totally naive about quoted strings that appear in
+response files! So "multiple words like this" would be processed as four args, the first
+one starting with '"', and the last one ending with '"'. The same naivety means that the
+'#' character is considered to mark the beginning of a comment, EVEN IF THAT '#' is
+inside a string. Sorry. (This is why hest parsing is being re-written ...)
+
+For a brief moment in 2023, this also stopped if it saw "--" (or whatever
+parm->varParamStopFlag implies), but that meant "--" is a brick wall that hestParse could
+never see past. But that misunderstands the relationship between how hestParse works and
+how the world uses "--". According to POSIX guidelines:
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_01
the elements of argv can be first "options" and then "operands", where "options" are
indicated by something starting with '-', and may have 0 or more "option-arguments".
@@ -131,7 +149,7 @@
what "--" should mean.
*/
static int
-copyArgv(int *sawHelp, char **newArgv, const char **oldArgv, const hestParm *parm,
+copyArgv(int *sawHelp, char **newArgv, const char **oldArgv, const hestParm *hparm,
airArray *pmop) {
static const char me[] = "copyArgv";
char line[AIR_STRLEN_HUGE + 1], *pound;
@@ -144,7 +162,7 @@
oldArgc++;
}
- if (parm->verbosity > 1) {
+ if (hparm->verbosity > 1) {
printf("%s: hello, oldArgc (number of input args) = %u:\n", me, oldArgc);
for (argIdx = 0; argIdx < oldArgc; argIdx++) {
printf(" oldArgv[%u] == |%s|\n", argIdx, oldArgv[argIdx]);
@@ -154,17 +172,17 @@
newArgc = 0;
*sawHelp = AIR_FALSE;
for (argIdx = 0; argIdx < oldArgc; argIdx++) {
- if (parm->respectDashDashHelp && !strcmp("--help", oldArgv[argIdx])) {
+ if (hparm->respectDashDashHelp && !strcmp("--help", oldArgv[argIdx])) {
*sawHelp = AIR_TRUE;
break;
}
/* else not a show-stopper argument */
- if (parm->verbosity) {
+ if (hparm->verbosity) {
printf("%s:________ newArgc = %u, argIdx = %u -> \"%s\"\n", me, newArgc, argIdx,
oldArgv[argIdx]);
printArgv(newArgc, newArgv, " ");
}
- if (!parm->respFileEnable || parm->respFileFlag != oldArgv[argIdx][0]) {
+ if (!hparm->respFileEnable || hparm->respFileFlag != oldArgv[argIdx][0]) {
/* either ignoring response files, or its not a response file:
we copy the arg, remember to free it, and increment the new arg idx */
newArgv[newArgc] = airStrdup(oldArgv[argIdx]);
@@ -178,13 +196,13 @@
len = airOneLine(file, line, AIR_STRLEN_HUGE + 1);
while (len > 0) {
unsigned rgi;
- if (parm->verbosity) printf("%s: line: |%s|\n", me, line);
+ if (hparm->verbosity) printf("%s: line: |%s|\n", me, line);
/* HEY HEY too bad for you if you put # inside a string */
- if ((pound = strchr(line, parm->respFileComment))) *pound = '\0';
- if (parm->verbosity) printf("%s: -0-> line: |%s|\n", me, line);
+ if ((pound = strchr(line, hparm->respFileComment))) *pound = '\0';
+ if (hparm->verbosity) printf("%s: -0-> line: |%s|\n", me, line);
airOneLinify(line);
incr = airStrntok(line, AIR_WHITESPACE);
- if (parm->verbosity) printf("%s: -1-> line: |%s|, incr=%d\n", me, line, incr);
+ if (hparm->verbosity) printf("%s: -1-> line: |%s|, incr=%d\n", me, line, incr);
airParseStrS(newArgv + newArgc, line, AIR_WHITESPACE, incr, AIR_FALSE);
for (rgi = 0; rgi < incr; rgi++) {
/* This time, we did allocate memory. We can use airFree and
@@ -196,7 +214,7 @@
}
fclose(file);
}
- if (parm->verbosity) {
+ if (hparm->verbosity) {
printArgv(newArgc, newArgv, " ");
printf("%s: ^^^^^^^ newArgc = %d, argIdx = %d\n", me, newArgc, argIdx);
}
@@ -208,48 +226,50 @@
}
/*
-** _hestPanic()
-**
-** all error checking on the given hest array itself (not the
-** command line to be parsed).
-**
-** Prior to 2023 code revisit; this used to set the "kind" in all the opts
-** but now that is more appropriately done at the time the option is added
-** (by hestOptAdd, hestOptAdd_nva, hestOptSingleSet, or hestOptAdd_*_*)
+_hestOptCheck() (formerly _hestPanic)
+
+This performs the validation of the given hestOpt array itself (not the command line to
+be parsed), with descriptive error messages sprintf'ed into err, if given. hestOptCheck()
+is the expected way for users to access this.
+
+Prior to 2023 code revisit; this used to set the "kind" in all the opts but now that is
+more appropriately done at the time the option is added (by hestOptAdd, hestOptAdd_nva,
+hestOptSingleSet, or hestOptAdd_*_*)
*/
int
-_hestPanic(hestOpt *opt, char *err, const hestParm *parm) {
- static const char me[] = "_hestPanic: ";
+_hestOptCheck(const hestOpt *opt, char *err, const hestParm *hparm) {
+ /* see note on ME (at top) for why me[] ends with ": " */
+ static const char me[] = "_hestOptCheck: ";
char tbuff[AIR_STRLEN_HUGE + 1], *sep;
- int numvar, op, numOpts;
+ int numvar, opi, optNum;
- numOpts = hestOptNum(opt);
+ optNum = hestOptNum(opt);
numvar = 0;
- for (op = 0; op < numOpts; op++) {
- if (!(AIR_IN_OP(airTypeUnknown, opt[op].type, airTypeLast))) {
+ for (opi = 0; opi < optNum; opi++) {
+ if (!(AIR_IN_OP(airTypeUnknown, opt[opi].type, airTypeLast))) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]", ME, op,
- opt[op].type, airTypeUnknown + 1, airTypeLast - 1);
+ sprintf(err, "%s!!!!!! opt[%d].type (%d) not in valid range [%d,%d]", ME, opi,
+ opt[opi].type, airTypeUnknown + 1, airTypeLast - 1);
else
fprintf(stderr, "%s: panic 0\n", me);
return 1;
}
- if (!(opt[op].valueP)) {
+ if (!(opt[opi].valueP)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s valueP is NULL!", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d]'s valueP is NULL!", ME, opi);
else
fprintf(stderr, "%s: panic 0.5\n", me);
return 1;
}
- if (-1 == opt[op].kind) {
+ if (-1 == opt[opi].kind) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible", ME, op,
- opt[op].min, opt[op].max);
+ sprintf(err, "%s!!!!!! opt[%d]'s min (%d) and max (%d) incompatible", ME, opi,
+ opt[opi].min, opt[opi].max);
else
fprintf(stderr, "%s: panic 1\n", me);
return 1;
}
- if (5 == opt[op].kind && !(opt[op].sawP)) {
+ if (5 == opt[opi].kind && !(opt[opi].sawP)) {
if (err)
sprintf(err,
"%s!!!!!! have multiple variable parameters, "
@@ -259,13 +279,13 @@
fprintf(stderr, "%s: panic 2\n", me);
return 1;
}
- if (airTypeEnum == opt[op].type) {
- if (!(opt[op].enm)) {
+ if (airTypeEnum == opt[opi].type) {
+ if (!(opt[opi].enm)) {
if (err) {
sprintf(err,
"%s!!!!!! opt[%d] (%s) is type \"enum\", but no "
"airEnum pointer given",
- ME, op, opt[op].flag ? opt[op].flag : "?");
+ ME, opi, opt[opi].flag ? opt[opi].flag : "?");
} else {
fprintf(stderr, "%s: panic 3\n", me);
}
@@ -272,54 +292,54 @@
return 1;
}
}
- if (airTypeOther == opt[op].type) {
- if (!(opt[op].CB)) {
+ if (airTypeOther == opt[opi].type) {
+ if (!(opt[opi].CB)) {
if (err) {
sprintf(err,
"%s!!!!!! opt[%d] (%s) is type \"other\", but no "
"callbacks given",
- ME, op, opt[op].flag ? opt[op].flag : "?");
+ ME, opi, opt[opi].flag ? opt[opi].flag : "?");
} else {
fprintf(stderr, "%s: panic 4\n", me);
}
return 1;
}
- if (!(opt[op].CB->size > 0)) {
+ if (!(opt[opi].CB->size > 0)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"size\" (%d) invalid", ME, op,
- (int)(opt[op].CB->size));
+ sprintf(err, "%s!!!!!! opt[%d]'s \"size\" (%d) invalid", ME, opi,
+ (int)(opt[opi].CB->size));
else
fprintf(stderr, "%s: panic 5\n", me);
return 1;
}
- if (!(opt[op].CB->type)) {
+ if (!(opt[opi].CB->type)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"type\" is NULL", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d]'s \"type\" is NULL", ME, opi);
else
fprintf(stderr, "%s: panic 6\n", me);
return 1;
}
- if (!(opt[op].CB->parse)) {
+ if (!(opt[opi].CB->parse)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d]'s \"parse\" callback NULL", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d]'s \"parse\" callback NULL", ME, opi);
else
fprintf(stderr, "%s: panic 7\n", me);
return 1;
}
- if (opt[op].CB->destroy && (sizeof(void *) != opt[op].CB->size)) {
+ if (opt[opi].CB->destroy && (sizeof(void *) != opt[opi].CB->size)) {
if (err)
sprintf(err,
"%s!!!!!! opt[%d] has a \"destroy\", but size %lu isn't "
"sizeof(void*)",
- ME, op, (unsigned long)(opt[op].CB->size));
+ ME, opi, (unsigned long)(opt[opi].CB->size));
else
fprintf(stderr, "%s: panic 8\n", me);
return 1;
}
}
- if (opt[op].flag) {
- strcpy(tbuff, opt[op].flag);
- if ((sep = strchr(tbuff, parm->multiFlagSep))) {
+ if (opt[opi].flag) {
+ strcpy(tbuff, opt[opi].flag);
+ if ((sep = strchr(tbuff, hparm->multiFlagSep))) {
*sep = '\0';
if (!(strlen(tbuff) && strlen(sep + 1))) {
if (err)
@@ -326,32 +346,32 @@
sprintf(err,
"%s!!!!!! either short (\"%s\") or long (\"%s\") flag"
" of opt[%d] is zero length",
- ME, tbuff, sep + 1, op);
+ ME, tbuff, sep + 1, opi);
else
fprintf(stderr, "%s: panic 9\n", me);
return 1;
}
- if (parm->respectDashDashHelp && !strcmp("help", sep + 1)) {
+ if (hparm->respectDashDashHelp && !strcmp("help", sep + 1)) {
if (err)
sprintf(err,
"%s!!!!!! long \"--%s\" flag of opt[%d] is same as \"--help\" "
"that requested hparm->respectDashDashHelp handles separately",
- ME, sep + 1, op);
+ ME, sep + 1, opi);
else
fprintf(stderr, "%s: panic 9.5\n", me);
return 1;
}
} else {
- if (!strlen(opt[op].flag)) {
+ if (!strlen(opt[opi].flag)) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d].flag is zero length", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d].flag is zero length", ME, opi);
else
fprintf(stderr, "%s: panic 10\n", me);
return 1;
}
}
- if (4 == opt[op].kind) {
- if (!opt[op].dflt) {
+ if (4 == opt[opi].kind) {
+ if (!opt[opi].dflt) {
if (err)
sprintf(err,
"%s!!!!!! flagged single variable parameter must "
@@ -361,7 +381,7 @@
fprintf(stderr, "%s: panic 11\n", me);
return 1;
}
- if (!strlen(opt[op].dflt)) {
+ if (!strlen(opt[opi].dflt)) {
if (err)
sprintf(err,
"%s!!!!!! flagged single variable parameter default "
@@ -382,8 +402,8 @@
}
*/
}
- if (1 == opt[op].kind) {
- if (!opt[op].flag) {
+ if (1 == opt[opi].kind) {
+ if (!opt[opi].flag) {
if (err)
sprintf(err, "%s!!!!!! flags must have flags", ME);
else
@@ -391,26 +411,26 @@
return 1;
}
} else {
- if (!opt[op].name) {
+ if (!opt[opi].name) {
if (err)
- sprintf(err, "%s!!!!!! opt[%d] isn't a flag: must have \"name\"", ME, op);
+ sprintf(err, "%s!!!!!! opt[%d] isn't a flag: must have \"name\"", ME, opi);
else
fprintf(stderr, "%s: panic 14\n", me);
return 1;
}
}
- if (4 == opt[op].kind && !opt[op].dflt) {
+ if (4 == opt[opi].kind && !opt[opi].dflt) {
if (err)
sprintf(err,
"%s!!!!!! opt[%d] is single variable parameter, but "
"no default set",
- ME, op);
+ ME, opi);
else
fprintf(stderr, "%s: panic 15\n", me);
return 1;
}
- numvar += ((int)opt[op].min < _hestMax(opt[op].max)
- && (NULL == opt[op].flag)); /* HEY scrutinize casts */
+ numvar += ((int)opt[opi].min < _hestMax(opt[opi].max)
+ && (NULL == opt[opi].flag)); /* HEY scrutinize casts */
}
if (numvar > 1) {
if (err)
@@ -425,23 +445,23 @@
int
_hestErrStrlen(const hestOpt *opt, int argc, const char **argv) {
- int a, numOpts, ret, other;
+ int ai, optNum, ret, other;
ret = 0;
- numOpts = hestOptNum(opt);
+ optNum = hestOptNum(opt);
other = AIR_FALSE;
if (argv) {
- for (a = 0; a < argc; a++) {
- ret = AIR_MAX(ret, (int)airStrlen(argv[a]));
+ for (ai = 0; ai < argc; ai++) {
+ ret = AIR_MAX(ret, (int)airStrlen(argv[ai]));
}
}
- for (a = 0; a < numOpts; a++) {
- ret = AIR_MAX(ret, (int)airStrlen(opt[a].flag));
- ret = AIR_MAX(ret, (int)airStrlen(opt[a].name));
- other |= opt[a].type == airTypeOther;
+ for (ai = 0; ai < optNum; ai++) {
+ ret = AIR_MAX(ret, (int)airStrlen(opt[ai].flag));
+ ret = AIR_MAX(ret, (int)airStrlen(opt[ai].name));
+ other |= opt[ai].type == airTypeOther;
}
- for (a = airTypeUnknown + 1; a < airTypeLast; a++) {
- ret = AIR_MAX(ret, (int)airStrlen(airTypeStr[a]));
+ for (ai = airTypeUnknown + 1; ai < airTypeLast; ai++) {
+ ret = AIR_MAX(ret, (int)airStrlen(airTypeStr[ai]));
}
if (other) {
/* the callback's error() function may sprintf an error message
@@ -459,15 +479,15 @@
copies into ident a string for identifying an option in error and usage messages
*/
static char *
-identStr(char *ident, hestOpt *opt, const hestParm *parm, int brief) {
+identStr(char *ident, const hestOpt *opt, const hestParm *hparm, int brief) {
char copy[AIR_STRLEN_HUGE + 1], *sep;
- if (opt->flag && (sep = strchr(opt->flag, parm->multiFlagSep))) {
+ if (opt->flag && (sep = strchr(opt->flag, hparm->multiFlagSep))) {
strcpy(copy, opt->flag);
- sep = strchr(copy, parm->multiFlagSep);
+ sep = strchr(copy, hparm->multiFlagSep);
*sep = '\0';
if (brief)
- sprintf(ident, "-%s%c--%s option", copy, parm->multiFlagSep, sep + 1);
+ sprintf(ident, "-%s%c--%s option", copy, hparm->multiFlagSep, sep + 1);
else
sprintf(ident, "-%s option", copy);
} else {
@@ -478,63 +498,72 @@
}
/*
-whichFlag()
+whichOptFlag()
-given a string in "flag" (with the hypen prefix) finds which of the flags in the given
-array of options matches that. Returns the index of the matching option, or -1 if
-there is no match, but returns -2 if the flag is the end-of-parameters
-marker "--" (or whatever parm->varParamStopFlag implies)
+given a string in "flag" (with the hypen prefix) finds which of the options in the given
+array of options has the matching flag. Returns the index of the matching option, or -1
+if there is no match, but returns -2 if the flag is the end-of-parameters marker "--" (or
+whatever parm->varParamStopFlag implies)
*/
static int
-whichFlag(hestOpt *opt, char *flag, const hestParm *parm) {
- static const char me[] = "whichFlag";
+whichOptFlag(const hestOpt *opt, const char *flag, const hestParm *hparm) {
+ static const char me[] = "whichOptFlag";
char buff[2 * AIR_STRLEN_HUGE + 1], copy[AIR_STRLEN_HUGE + 1], *sep;
- int op, numOpts;
+ int optIdx, optNum;
- numOpts = hestOptNum(opt);
- if (parm->verbosity)
- printf("%s: (a) looking for flag |%s| in numOpts=%d options\n", me, flag, numOpts);
- for (op = 0; op < numOpts; op++) {
- if (parm->verbosity) printf("%s: op = %d\n", me, op);
- if (!opt[op].flag) continue;
- if (strchr(opt[op].flag, parm->multiFlagSep)) {
- strcpy(copy, opt[op].flag);
- sep = strchr(copy, parm->multiFlagSep);
+ optNum = hestOptNum(opt);
+ if (hparm->verbosity)
+ printf("%s: (a) looking for maybe-is-flag |%s| in optNum=%d options\n", me, flag,
+ optNum);
+ for (optIdx = 0; optIdx < optNum; optIdx++) {
+ if (hparm->verbosity)
+ printf("%s: optIdx %d |%s| ?\n", me, optIdx,
+ opt[optIdx].flag ? opt[optIdx].flag : "(nullflag)");
+ if (!opt[optIdx].flag) continue;
+ if (strchr(opt[optIdx].flag, hparm->multiFlagSep)) {
+ strcpy(copy, opt[optIdx].flag);
+ sep = strchr(copy, hparm->multiFlagSep);
*sep = '\0';
/* first try the short version */
sprintf(buff, "-%s", copy);
- if (!strcmp(flag, buff)) return op;
+ if (!strcmp(flag, buff)) return optIdx;
/* then try the long version */
sprintf(buff, "--%s", sep + 1);
- if (!strcmp(flag, buff)) return op;
+ if (!strcmp(flag, buff)) return optIdx;
} else {
/* flag has only the short version */
- sprintf(buff, "-%s", opt[op].flag);
- if (!strcmp(flag, buff)) return op;
+ sprintf(buff, "-%s", opt[optIdx].flag);
+ if (!strcmp(flag, buff)) return optIdx;
}
}
- if (parm->verbosity) printf("%s: (b) numOpts = %d\n", me, numOpts);
- if (parm->varParamStopFlag) {
- sprintf(buff, "-%c", parm->varParamStopFlag);
- if (parm->verbosity)
- printf("%s: does flag |%s| == -parm->varParamStopFlag |%s| ?\n", me, flag, buff);
+ if (hparm->verbosity) printf("%s: (b) optNum = %d\n", me, optNum);
+ if (hparm->varParamStopFlag) {
+ sprintf(buff, "-%c", hparm->varParamStopFlag);
+ if (hparm->verbosity)
+ printf("%s: does maybe-is-flag |%s| == -parm->varParamStopFlag |%s| ?\n", me, flag,
+ buff);
if (!strcmp(flag, buff)) {
- if (parm->verbosity) printf("%s: yes, it does! returning -2\n", me);
+ if (hparm->verbosity) printf("%s: yes, it does! returning -2\n", me);
return -2;
}
}
- if (parm->verbosity) printf("%s: (c) returning -1\n", me);
+ if (hparm->verbosity) printf("%s: (c) returning -1\n", me);
return -1;
}
/*
-extractToStr: takes "pnum" parameters, starting at "base", out of the given argv, and
-puts them into a string WHICH THIS FUNCTION ALLOCATES, and also adjusts the argc value
-given as "*argcP".
+extractToStr: from the given *argcP,argv description of args, starting at arg index
+`base`, takes *UP TO* `pnum` parameters out of argv, and puts them into a new
+VTAB-separated qstring WHICH THIS FUNCTION ALLOCATES, and accordingly decreases `*argcP`.
+
+***** This is the function where VTAB starts being used.
+
+The number of parameters so extracted is stored in `*pnumGot` (if `pnumGot` non-NULL).
+`*pnumGot` can be less than `pnum` if we hit "--" (or the equivalent)
*/
static char *
extractToStr(int *argcP, char **argv, unsigned int base, unsigned int pnum,
- unsigned int *pnumGot, const hestParm *parm) {
+ unsigned int *pnumGot, const hestParm *hparm) {
unsigned int len, pidx, true_pnum;
char *ret;
char stops[3] = "";
@@ -541,9 +570,9 @@
if (!pnum) return NULL;
- if (parm) {
+ if (hparm) {
stops[0] = '-';
- stops[1] = parm->varParamStopFlag;
+ stops[1] = hparm->varParamStopFlag;
stops[2] = '\0';
} /* else stops stays as empty string */
@@ -551,7 +580,7 @@
len = 0;
for (pidx = 0; pidx < pnum; pidx++) {
if (base + pidx == AIR_UINT(*argcP)) {
- /* ran up against end of argv array */
+ /* ran up against end of argv array; game over */
return NULL;
}
if (!strcmp(argv[base + pidx], stops)) {
@@ -560,7 +589,7 @@
}
/* increment by strlen of current arg */
len += AIR_UINT(strlen(argv[base + pidx]));
- /* and by 2, for 2 '"'s around quoted parm */
+ /* and then increment by 2, for 2 '"'s around quoted parm */
if (strstr(argv[base + pidx], " ")) {
len += 2;
}
@@ -584,9 +613,11 @@
if (strstr(argv[base + pidx], " ")) {
strcat(ret, "\"");
}
- /* add space prior to anticipated next parm */
+ /* add space prior to anticipated next parm
+ HEY this needs to be re-written to extend an argv */
if (pidx < true_pnum - 1) strcat(ret, " ");
}
+ /* shuffle down later argv pointers */
for (pidx = base + true_pnum; pidx <= AIR_UINT(*argcP); pidx++) {
argv[pidx - true_pnum] = argv[pidx];
}
@@ -597,112 +628,129 @@
/*
extractFlagged()
-extracts the parameters associated with all flagged options from the given argc and argv,
-storing them in prms[], recording the number of parameters in nprm[], and whether or not
-the flagged option appeared in appr[].
+extracts the parameters associated with all flagged options from the given *argcP and
+argv (wherein the flag and subsequent parms were all separate strings), and here stores
+them in optParms[] as a single VTAB-separated string (VTABs originating in extractToStr),
+recording the number of parameters in optParmNum[], and whether or not the flagged option
+appeared in optAprd[].
The sawP information is not set here, since it is better set at value parsing time, which
happens after defaults are enstated.
-This is where, thanks to the action of whichFlag(), "--" (or whatever
+This is where, thanks to the action of whichOptFlag(), "--" (or whatever
parm->varParamStopFlag implies) is used as a marker for the end of a *flagged* variable
parameter option. AND, the "--" marker is removed from the argv.
*/
static int
-extractFlagged(char **prms, unsigned int *nprm, int *appr, int *argcP, char **argv,
- hestOpt *opt, char *err, const hestParm *parm, airArray *pmop) {
+extractFlagged(char **optParms, unsigned int *optParmNum, int *optAprd, int *argcP,
+ char **argv, hestOpt *opt, char *err, const hestParm *hparm,
+ airArray *pmop) {
+ /* see note on ME (at top) for why me[] ends with ": " */
static const char me[] = "extractFlagged: ";
char ident1[AIR_STRLEN_HUGE + 1], ident2[AIR_STRLEN_HUGE + 1];
- int a, np, flag, endflag, numOpts, op;
+ int argIdx, parmNum, optIdx, nextOptIdx, optNum, op;
- a = 0;
- if (parm->verbosity) printf("%s: *argcP = %d\n", me, *argcP);
- while (a <= *argcP - 1) {
- if (parm->verbosity) {
- printf("%s: ----------------- a = %d -> argv[a] = %s\n", me, a, argv[a]);
+ if (hparm->verbosity) printf("%s: *argcP = %d\n", me, *argcP);
+ argIdx = 0;
+ while (argIdx <= *argcP - 1) {
+ if (hparm->verbosity) {
+ printf("%s----------------- argIdx = %d -> argv[argIdx] = %s\n", me, argIdx,
+ argv[argIdx]);
}
- flag = whichFlag(opt, argv[a], parm);
- if (parm->verbosity) printf("%s: A: a = %d -> flag = %d\n", me, a, flag);
- if (!(0 <= flag)) {
+ optIdx = whichOptFlag(opt, argv[argIdx], hparm);
+ if (hparm->verbosity)
+ printf("%sA: argv[%d]=|%s| is flag of opt %d\n", me, argIdx, argv[argIdx], optIdx);
+ if (!(0 <= optIdx)) {
/* not a flag, move on */
- a++;
- if (parm->verbosity) printf("%s: !(0 <= %d), so: continue\n", me, flag);
+ argIdx++;
+ if (hparm->verbosity) printf("%s: !(0 <= %d), so: continue\n", me, optIdx);
continue;
}
/* see if we can associate some parameters with the flag */
- if (parm->verbosity) printf("%s: flag = %d; any parms?\n", me, flag);
- np = 0;
- endflag = 0;
- while (np < _hestMax(opt[flag].max) /* */
- && a + np + 1 <= *argcP - 1 /* */
- && -1 == (endflag = whichFlag(opt, argv[a + np + 1], parm))) {
- np++;
- if (parm->verbosity)
- printf("%s: np --> %d with flag = %d; endflag = %d\n", me, np, flag, endflag);
+ if (hparm->verbosity)
+ printf("%soptIdx %d |%s|: any parms?\n", me, optIdx, opt[optIdx].flag);
+ parmNum = 0;
+ nextOptIdx = 0; // what is index of option who's flag we see next
+ while (parmNum < _hestMax(opt[optIdx].max) /* */
+ && argIdx + parmNum + 1 <= *argcP - 1 /* */
+ && -1
+ == (nextOptIdx = whichOptFlag(opt, /* */
+ argv[argIdx + parmNum + 1], /* */
+ hparm))) {
+ parmNum++;
+ if (hparm->verbosity)
+ printf("%soptIdx %d |%s|: parmNum --> %d nextOptIdx = %d\n", me, optIdx,
+ opt[optIdx].flag, parmNum, nextOptIdx);
}
/* we stopped because we got the max number of parameters, or
because we hit the end of the command line, or
- because whichFlag() returned something other than -1,
- which means it returned -2, or a valid option index. If
- we stopped because of whichFlag()'s return value,
- endflag has been set to that return value */
- if (parm->verbosity)
- printf("%s: B: stopped with np = %d; flag = %d; endflag = %d\n", me, np, flag,
- endflag);
- if (np < (int)opt[flag].min) { /* HEY scrutinize casts */
+ because whichOptFlag() returned something other than -1,
+ which means it returned -2, or a valid option index.
+ If we stopped because of whichOptFlag()'s return value,
+ nextOptIdx has been set to that return value */
+ if (hparm->verbosity)
+ printf("%sB: optIdx %d |%s|: stopped with parmNum = %d nextOptIdx = %d\n", me,
+ optIdx, opt[optIdx].flag, parmNum, nextOptIdx);
+ if (parmNum < (int)opt[optIdx].min) { /* HEY scrutinize casts */
/* didn't get minimum number of parameters */
- if (!(a + np + 1 <= *argcP - 1)) {
+ if (!(argIdx + parmNum + 1 <= *argcP - 1)) {
sprintf(err,
- "%shit end of line before getting %d parameter%s "
+ "%sgot to end of line before getting %d parameter%s "
"for %s (got %d)",
- ME, opt[flag].min, opt[flag].min > 1 ? "s" : "",
- identStr(ident1, opt + flag, parm, AIR_TRUE), np);
- } else if (-2 != endflag) {
- sprintf(err, "%shit %s before getting %d parameter%s for %s (got %d)", ME,
- identStr(ident1, opt + endflag, parm, AIR_FALSE), opt[flag].min,
- opt[flag].min > 1 ? "s" : "",
- identStr(ident2, opt + flag, parm, AIR_FALSE), np);
+ ME, opt[optIdx].min, opt[optIdx].min > 1 ? "s" : "",
+ identStr(ident1, opt + optIdx, hparm, AIR_TRUE), parmNum);
+ } else if (-2 != nextOptIdx) {
+ sprintf(err, "%ssaw %s before getting %d parameter%s for %s (got %d)", ME,
+ identStr(ident1, opt + nextOptIdx, hparm, AIR_FALSE), opt[optIdx].min,
+ opt[optIdx].min > 1 ? "s" : "",
+ identStr(ident2, opt + optIdx, hparm, AIR_FALSE), parmNum);
} else {
sprintf(err,
- "%shit \"-%c\" (option-parameter-stop flag) before getting %d "
+ "%ssaw \"-%c\" (option-parameter-stop flag) before getting %d "
"parameter%s for %s (got %d)",
- ME, parm->varParamStopFlag, opt[flag].min, opt[flag].min > 1 ? "s" : "",
- identStr(ident2, opt + flag, parm, AIR_FALSE), np);
+ ME, hparm->varParamStopFlag, opt[optIdx].min,
+ opt[optIdx].min > 1 ? "s" : "",
+ identStr(ident2, opt + optIdx, hparm, AIR_FALSE), parmNum);
}
return 1;
}
- nprm[flag] = np;
- if (parm->verbosity) {
- printf("%s:________ a=%d, *argcP = %d -> flag = %d\n", me, a, *argcP, flag);
+ /* record number of parameters seen for this option */
+ optParmNum[optIdx] = parmNum;
+ if (hparm->verbosity) {
+ printf("%s________ argv[%d]=|%s|: *argcP = %d -> optIdx = %d\n", me, argIdx,
+ argv[argIdx], *argcP, optIdx);
printArgv(*argcP, argv, " ");
}
/* lose the flag argument */
- free(extractToStr(argcP, argv, a, 1, NULL, NULL));
+ free(extractToStr(argcP, argv, argIdx, 1, NULL, NULL));
/* extract the args after the flag */
- if (appr[flag]) {
- airMopSub(pmop, prms[flag], airFree);
- prms[flag] = (char *)airFree(prms[flag]);
+ if (optAprd[optIdx]) {
+ /* oh so this is not the first time we've seen this option;
+ so now forget everything triggered by having seen it already */
+ airMopSub(pmop, optParms[optIdx], airFree);
+ optParms[optIdx] = (char *)airFree(optParms[optIdx]);
}
- prms[flag] = extractToStr(argcP, argv, a, nprm[flag], NULL, NULL);
- airMopAdd(pmop, prms[flag], airFree, airMopAlways);
- appr[flag] = AIR_TRUE;
- if (-2 == endflag) {
+ optParms[optIdx] = extractToStr(argcP, argv, argIdx, optParmNum[optIdx], NULL, NULL);
+ airMopAdd(pmop, optParms[optIdx], airFree, airMopAlways);
+ optAprd[optIdx] = AIR_TRUE;
+ if (-2 == nextOptIdx) {
/* we drop the option-parameter-stop flag */
- free(extractToStr(argcP, argv, a, 1, NULL, NULL));
+ free(extractToStr(argcP, argv, argIdx, 1, NULL, NULL));
}
- if (parm->verbosity) {
+ if (hparm->verbosity) {
printArgv(*argcP, argv, " ");
- printf("%s:^^^^^^^^ *argcP = %d\n", me, *argcP);
- printf("%s: prms[%d] = %s\n", me, flag, prms[flag] ? prms[flag] : "(null)");
+ printf("%s^^^^^^^^ *argcP = %d\n", me, *argcP);
+ printf("%soptParms[%d] = |%s|\n", me, optIdx,
+ optParms[optIdx] ? optParms[optIdx] : "(null)");
}
}
/* make sure that flagged options without default were given */
- numOpts = hestOptNum(opt);
- for (op = 0; op < numOpts; op++) {
- if (1 != opt[op].kind && opt[op].flag && !opt[op].dflt && !appr[op]) {
+ optNum = hestOptNum(opt);
+ for (op = 0; op < optNum; op++) {
+ if (1 != opt[op].kind && opt[op].flag && !opt[op].dflt && !optAprd[op]) {
sprintf(err, "%sdidn't get required %s", ME,
- identStr(ident1, opt + op, parm, AIR_FALSE));
+ identStr(ident1, opt + op, hparm, AIR_FALSE));
return 1;
}
}
@@ -711,95 +759,108 @@
}
static int
-_hestNextUnflagged(int op, hestOpt *opt, int numOpts) {
+nextUnflagged(int op, hestOpt *opt, int optNum) {
- for (; op <= numOpts - 1; op++) {
+ for (; op <= optNum - 1; op++) {
if (!opt[op].flag) break;
}
return op;
}
+/*
+extractUnflagged()
+
+extracts the parameters associated with all unflagged options from the given *argcP and
+argv (wherein the flag and subsequent parms were all separate strings), and here stores
+them in optParms[] as a single VTAB-separated string (VTABs originating in extractToStr),
+recording the number of parameters in optParmNum[].
+
+This is the function that has to handle the trickly logic of allowing there to be
+multiple unflagged opti...
[truncated message content] |
|
From: <kin...@us...> - 2025-09-17 09:51:28
|
Revision: 7439
http://sourceforge.net/p/teem/code/7439
Author: kindlmann
Date: 2025-09-17 09:51:26 +0000 (Wed, 17 Sep 2025)
Log Message:
-----------
using new hestOptAdd functions
Modified Paths:
--------------
teem/trunk/src/moss/test/invert.c
Modified: teem/trunk/src/moss/test/invert.c
===================================================================
--- teem/trunk/src/moss/test/invert.c 2025-09-15 17:29:45 UTC (rev 7438)
+++ teem/trunk/src/moss/test/invert.c 2025-09-17 09:51:26 UTC (rev 7439)
@@ -21,16 +21,14 @@
int
main(int argc, const char *argv[]) {
- const char *me, *info="inverts a moss transform";
- hestOpt *hopt=NULL;
+ const char *me, *info = "inverts a moss transform";
+ hestOpt *hopt = NULL;
double *mat, inv[6];
me = argv[0];
- hestOptAdd(&hopt, "t", "transform", airTypeOther, 1, 1, &mat, "identity",
- "transform(s) to apply to image",
- NULL, NULL, mossHestTransform);
- hestParseOrDie(hopt, argc-1, argv+1, NULL,
- me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
+ hestOptAdd_1_Other(&hopt, "t", "transform", &mat, "identity",
+ "transform(s) to apply to image", mossHestTransform);
+ hestParseOrDie(hopt, argc - 1, argv + 1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
fprintf(stderr, "%s: got transform:\n", me);
mossMatPrint(stderr, mat);
@@ -40,4 +38,3 @@
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-15 17:29:47
|
Revision: 7438
http://sourceforge.net/p/teem/code/7438
Author: kindlmann
Date: 2025-09-15 17:29:45 +0000 (Mon, 15 Sep 2025)
Log Message:
-----------
old and probably busted version
Added Paths:
-----------
teem/trunk/CMake/FindFFTW3-v1.cmake
Added: teem/trunk/CMake/FindFFTW3-v1.cmake
===================================================================
--- teem/trunk/CMake/FindFFTW3-v1.cmake (rev 0)
+++ teem/trunk/CMake/FindFFTW3-v1.cmake 2025-09-15 17:29:45 UTC (rev 7438)
@@ -0,0 +1,22 @@
+
+find_path(FFTW3_INCLUDE_DIR fftw3.h
+ /usr/local/include
+ /usr/include
+)
+
+find_library(FFTW3_LIBRARY fftw3
+ /usr/lib
+ /usr/local/lib
+)
+
+set(FFTW3_FOUND FALSE)
+if(FFTW3_INCLUDE_DIR AND FFTW3_LIBRARY)
+ set(FFTW3_LIBRARIES ${FFTW3_LIBRARY} )
+ set(FFTW3_FOUND TRUE)
+endif()
+
+mark_as_advanced(
+ FFTW3_INCLUDE_DIR
+ FFTW3_LIBRARIES
+ FFTW3_FOUND
+ )
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-09-15 17:28:34
|
Revision: 7437
http://sourceforge.net/p/teem/code/7437
Author: kindlmann
Date: 2025-09-15 17:28:33 +0000 (Mon, 15 Sep 2025)
Log Message:
-----------
old and probably busted version
Added Paths:
-----------
teem/trunk/CMake/FindLEVMAR-v1.cmake
Added: teem/trunk/CMake/FindLEVMAR-v1.cmake
===================================================================
--- teem/trunk/CMake/FindLEVMAR-v1.cmake (rev 0)
+++ teem/trunk/CMake/FindLEVMAR-v1.cmake 2025-09-15 17:28:33 UTC (rev 7437)
@@ -0,0 +1,24 @@
+
+find_path(LEVMAR_INCLUDE_DIR levmar.h
+ /usr/local/include/levmar
+ /usr/local/include
+ /usr/include
+)
+
+find_library(LEVMAR_LIBRARY levmar
+ /usr/lib
+ /usr/local/lib
+)
+
+set(LEVMAR_FOUND FALSE)
+if(LEVMAR_INCLUDE_DIR AND LEVMAR_LIBRARY)
+ set(LEVMAR_INCLUDE_DIRS ${LEVMAR_INCLUDE_DIR} )
+ set(LEVMAR_LIBRARIES ${LEVMAR_LIBRARY} )
+ set(LEVMAR_FOUND TRUE)
+endif()
+
+mark_as_advanced(
+ LEVMAR_INCLUDE_DIR
+ LEVMAR_LIBRARIES
+ LEVMAR_FOUND
+ )
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|