From d171ffd66bae5dca869592851e91c7ba6ad10dfb Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Sun, 22 Mar 2026 21:16:25 -0600 Subject: [PATCH 01/21] SetVar.cc:VerfiyVal(): Use supplied functionals for matching and reporting matching failure. This is in prep to support user-supplied functionls for more sophistacted matching and reporting. --- code/SetVar.cc | 54 +++++++++++++++++++++++++++++++++----------------- code/cl.h | 6 ++++-- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/code/SetVar.cc b/code/SetVar.cc index 79302e2..ed9fd30 100644 --- a/code/SetVar.cc +++ b/code/SetVar.cc @@ -28,6 +28,7 @@ #include #include #include +#include extern "C" { /* #define getmem(a,b) malloc((a))*/ @@ -127,8 +128,39 @@ int UnsetVar(Symbol *S, int setFactoryDefaults) return ret; } + /*----------------------------------------------------------------------*/ - void VerifyVal(const char *v, Symbol *S,string& newval) + bool matchOpts(const std::string& val,const Symbol& S) + { + bool Matched=false; + for(auto opt : S.Options) + if (opt == val) + { + Matched=true; + break; + } + return Matched; + }; + + void noMatchException(const Symbol& S) + { + string msg; + msg = "###Warning: Value did not match any factory supplied options for keyword \""; + msg += S.Name; msg += "\""; + clError errObj; + errObj << msg.c_str() << endl; + if (!S.Options.empty()) + { + msg = "###Informational: Valid options are "; + for(auto opt : S.Options) + {msg += "\"" + opt;msg += "\" ";} + errObj << msg.c_str() << endl; + } + }; +/*----------------------------------------------------------------------*/ + void VerifyVal(const char *v, Symbol *S,string& newval, + std::function matchOptsLambda=matchOpts, + std::function noMatchExceptionLambda=noMatchException) { int n = S->Options.size(); int Matched=1; @@ -181,25 +213,11 @@ int UnsetVar(Symbol *S, int setFactoryDefaults) } else if (n > 0) { - Matched=0; - for(int i=0; iOptions[i] == v) - {Matched=1;break;} + Matched=matchOptsLambda(std::string(v),*S); } if (!Matched) { - string msg; - msg = "###Warning: Value did not match any factory supplied options for keyword \""; - msg += S->Name; msg += "\""; - clError errObj; - errObj << msg.c_str() << endl; - if (n>0) - { - msg = "###Informational: Valid options are "; - for(int i=0; iOptions[i];msg += "\" ";} - errObj << msg.c_str() << endl; - } + noMatchExceptionLambda(*S); } } /*----------------------------------------------------------------------*/ @@ -210,7 +228,7 @@ void SetVal(const char *v, Symbol *S, int i) try { - VerifyVal(trimmed.c_str(),S,vv); + VerifyVal(trimmed.c_str(),S,vv,matchOpts); } catch (clError& x) { diff --git a/code/cl.h b/code/cl.h index 3447ae4..740046a 100644 --- a/code/cl.h +++ b/code/cl.h @@ -19,7 +19,7 @@ /* $Id: cl.h,v 2.0 1998/11/11 07:12:46 sanjay Exp sanjay $ */ #if !defined(CL_H) #define CL_H - +#include /* Names of the environment variables and other default values used for user customizaion. @@ -252,7 +252,9 @@ int UnsetVar(Symbol *,int); int SetVar(char *Name, char *val, Symbol *tab,short int force, short int fullmatch, short int doinp); //void SetVal(const char *, Symbol *, int); #ifdef __cplusplus -void VerifyVal(const char *, Symbol *,string &); + void VerifyVal(const char *, Symbol *,string &, + std::function matchOptsLambda, + std::function noMatchExceptionLambda); #endif int CopyVSymb(Symbol *, Symbol *,int); int FreeVSymb(Symbol *); From 5efa90f04681574bd0b1d25dc81aa6fd3d1683ee Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Mon, 23 Mar 2026 08:07:10 -0600 Subject: [PATCH 02/21] clgetBaseCode.h: Added the dbg parameter for clgetNValBaseCode. Also setting the S->Attributes and ->CLASS bits. --- code/clgetBaseCode.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/code/clgetBaseCode.h b/code/clgetBaseCode.h index 526e666..9b7e2a6 100644 --- a/code/clgetBaseCode.h +++ b/code/clgetBaseCode.h @@ -50,7 +50,6 @@ Symbol* clgetBaseCode(const string& Name, T& val, int& n, SMap &smap=SMap(), boo else if (std::is_same::value) {type_str="bool"; type_int=CL_BOOLTYPE;} else if (std::is_same::value) {type_str="string";type_int=CL_STRINGTYPE;} - HANDLE_EXCEPTIONS( if (n < 0) S=SearchVSymb((char *)Name.c_str(),cl_SymbTab); @@ -76,27 +75,30 @@ Symbol* clgetBaseCode(const string& Name, T& val, int& n, SMap &smap=SMap(), boo // Templated functions for NVal calls. // template -Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap &smap=SMap()) +Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap &smap=SMap(), bool dbg=false) { Symbol *S; std::ostringstream os; + uint type_int=CL_MIXEDTYPE; + + if (std::is_same::value) {(m <= 0) ? os << "int[]" : os << "int[" << m << "]"; type_int=CL_INTEGERTYPE;} + else if (std::is_same::value) {(m <= 0) ? os << "float[]" : os << "float[" << m << "]";type_int=CL_FLOATTYPE;} + else if (std::is_same::value) {(m <= 0) ? os << "bool[]" : os << "bool[" << m << "]";type_int=CL_BOOLTYPE;} + else if (std::is_same::value) {(m <= 0) ? os << "string[]" : os << "string[" << m << "]";type_int=CL_STRINGTYPE;} - if (std::is_same::value) (m <= 0) ? os << "int[]" : os << "int[" << m << "]"; - else if (std::is_same::value) (m <= 0) ? os << "float[]" : os << "float[" << m << "]"; - else if (std::is_same::value) (m <= 0) ? os << "bool[]" : os << "bool[" << m << "]"; - else if (std::is_same::value) (m <= 0) ? os << "string[]" : os << "string[" << m << "]"; - HANDLE_EXCEPTIONS( S = SearchQSymb((char *)Name.c_str(), os.str()); - // - // Remember the number of values set by the user. - // - setAutoDefaults(S,val); if (S!=NULL) { + // Use templated function that works for all values of T + setAutoDefaults(S,val); + S->Class=CL_APPLNCLASS; - if (!smap.empty()) S->smap = smap; + if (dbg) S->Class=CL_DBGCLASS; + SETBIT(S->Attributes,type_int); + if (!smap.empty()) + S->smap = smap; } return S; ); From 070c0af724523f10860028db82fd61973d679962 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Mon, 23 Mar 2026 18:53:54 -0600 Subject: [PATCH 03/21] clgetBaseCode.h: Added the dbg parameter in clgetNValBaseCode(), and fixed the code to set the Symbol::Attributes and ::Class bits. --- code/SetVar.cc | 1 + code/clgetBaseCode.h | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/code/SetVar.cc b/code/SetVar.cc index ed9fd30..0ff2b48 100644 --- a/code/SetVar.cc +++ b/code/SetVar.cc @@ -157,6 +157,7 @@ int UnsetVar(Symbol *S, int setFactoryDefaults) errObj << msg.c_str() << endl; } }; +std::function noMatchExceptionLambda_ptr=noMatchException; /*----------------------------------------------------------------------*/ void VerifyVal(const char *v, Symbol *S,string& newval, std::function matchOptsLambda=matchOpts, diff --git a/code/clgetBaseCode.h b/code/clgetBaseCode.h index 526e666..85103c4 100644 --- a/code/clgetBaseCode.h +++ b/code/clgetBaseCode.h @@ -76,30 +76,33 @@ Symbol* clgetBaseCode(const string& Name, T& val, int& n, SMap &smap=SMap(), boo // Templated functions for NVal calls. // template -Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap &smap=SMap()) +Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap &smap=SMap(), bool dbg=false ) { Symbol *S; std::ostringstream os; + uint type_int=CL_MIXEDTYPE; - if (std::is_same::value) (m <= 0) ? os << "int[]" : os << "int[" << m << "]"; - else if (std::is_same::value) (m <= 0) ? os << "float[]" : os << "float[" << m << "]"; - else if (std::is_same::value) (m <= 0) ? os << "bool[]" : os << "bool[" << m << "]"; - else if (std::is_same::value) (m <= 0) ? os << "string[]" : os << "string[" << m << "]"; + if (std::is_same::value) {(m <= 0) ? os << "int[]" : os << "int[" << m << "]";type_int=CL_INTEGERTYPE;} + else if (std::is_same::value) {(m <= 0) ? os << "float[]" : os << "float[" << m << "]";type_int=CL_FLOATTYPE;} + else if (std::is_same::value) {(m <= 0) ? os << "bool[]" : os << "bool[" << m << "]";type_int=CL_BOOLTYPE;} + else if (std::is_same::value) {(m <= 0) ? os << "string[]" : os << "string[" << m << "]";type_int=CL_STRINGTYPE;} HANDLE_EXCEPTIONS( S = SearchQSymb((char *)Name.c_str(), os.str()); - // - // Remember the number of values set by the user. - // - setAutoDefaults(S,val); if (S!=NULL) { + // Use templated function that works for all values of T + setAutoDefaults(S,val); + S->Class=CL_APPLNCLASS; - if (!smap.empty()) S->smap = smap; + if (dbg) S->Class=CL_DBGCLASS; + SETBIT(S->Attributes,type_int); + if (!smap.empty()) + S->smap = smap; } - return S; ); + return S; } // //---------------------------------------------------------------------- From fde6f70878f76277d5360d48105069b48b9e2995 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Mon, 23 Mar 2026 21:02:07 -0600 Subject: [PATCH 04/21] clparseVal.{cc,h}: clparseVal() is now templated to work for T=int,float,bool,std::string clgetValp.cc: With the clparseVal properly templated, separate implementations for T=string or T=std::vector for cl[dbg]getValp aren't necessary. This reduces the number of template functions by four. CMakeLists.txt: Removed duplication clparseVal.h tstcpp.cc, clgetValp.h, clgetBaseCode.h: Date change in Copyright notice. --- code/CMakeLists.txt | 3 +- code/clgetBaseCode.h | 2 +- code/clgetValp.cc | 196 ++++++++++++++++++++++--------------------- code/clgetValp.h | 2 +- code/clparseVal.cc | 39 +-------- code/clparseVal.h | 60 ++++++++++++- code/tstcpp.cc | 2 +- 7 files changed, 163 insertions(+), 141 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index f4a62a0..5d737a1 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1,6 +1,6 @@ # -*- cmake -*- # /* -# * Copyright (c) 2000-2021, 2022 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) +# * Copyright (c) 2000-2025, 2026 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) # * # * This program is free software; you can redistribute it and/or modify # * it under the terms of the GNU General Public License as published by @@ -70,7 +70,6 @@ set(header_list support.h iosupport.h SymbTab.h - clparseVal.h clgetValp.h clgetValp.cc ) diff --git a/code/clgetBaseCode.h b/code/clgetBaseCode.h index 08b51e9..0faaa90 100644 --- a/code/clgetBaseCode.h +++ b/code/clgetBaseCode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2021, 2022 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) + * Copyright (c) 2000-2025, 2026 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/code/clgetValp.cc b/code/clgetValp.cc index 5b0e925..ed76800 100644 --- a/code/clgetValp.cc +++ b/code/clgetValp.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2021, 2022 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) + * Copyright (c) 2000-2025, 2026 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,8 +59,9 @@ int clgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) int N; HANDLE_EXCEPTIONS( S=clgetBaseCode(Name,val,n,smap); - double d; - if ((N=clparseVal(S,&n,&d))>0) val = (T)d; + T d; + //if ((N=clparseVal(S,&n,d))>0) val = (T)d; + if ((N=clparseVal(S,&n,d))>0) val = d; return N; ); @@ -68,23 +69,23 @@ int clgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) // //------------------------------------------------------------------------- // -template <> -int clgetValp(const std::string&, std::string& val, int& n,SMap)=delete; -// -//---------------------------------------------------------------------- -// -int clgetValp(const std::string& Name, std::string& val, int& n, SMap smap=SMap()) -{ - Symbol *S; - int N; - HANDLE_EXCEPTIONS( - S=clgetBaseCode(Name,val,n,smap); - std::string d; - if ((N=clparseVal(S,&n,d))>0) val = d; +// template <> +// int clgetValp(const std::string&, std::string& val, int& n,SMap)=delete; +// // +// //---------------------------------------------------------------------- +// // +// int clgetValp(const std::string& Name, std::string& val, int& n, SMap smap=SMap()) +// { +// Symbol *S; +// int N; +// HANDLE_EXCEPTIONS( +// S=clgetBaseCode(Name,val,n,smap); +// std::string d; +// if ((N=clparseVal(S,&n,d))>0) val = d; - return N; - ); -} +// return N; +// ); +// } // //------------------------------------------------------------------------- // @@ -100,20 +101,21 @@ template int clgetValp(const std::string& Name, std::vector& val, int& m, const SMap smap=SMap()) { Symbol *S; - double d; + T d; HANDLE_EXCEPTIONS( S=clgetNValBaseCode(Name,val,m,smap); int n0=S->NVals; int i=1; for(int j=0;jNVals=i-1;return i-1;} else { val.resize(i); - val[i-1] = (T)d; + //val[i-1] = (T)d; + val[i-1] = d; i++; } } @@ -123,38 +125,38 @@ int clgetValp(const std::string& Name, std::vector& val, int& m, const SMap s ); } -template <> -int clgetValp(const std::string&, std::vector& val, int& n,const SMap)=delete; +// template <> +// int clgetValp(const std::string&, std::vector& val, int& n,const SMap)=delete; -// -//---------------------------------------------------------------------- -// -int clgetValp(const std::string& Name, std::vector& val, int& m, const SMap smap=SMap()) -{ - Symbol *S; - std::string d; +// // +// //---------------------------------------------------------------------- +// // +// int clgetValp(const std::string& Name, std::vector& val, int& m, const SMap smap=SMap()) +// { +// Symbol *S; +// std::string d; - HANDLE_EXCEPTIONS( - S=clgetNValBaseCode(Name,val,m,smap); - int n0=S->NVals; - int i=1; - for(int j=0;jNVals=i-1;return i-1;} - else - { - val.resize(i); - val[i-1] = d; - i++; - } - } - } - m=S->NVals=i-1; - return i-1; - ); -} +// HANDLE_EXCEPTIONS( +// S=clgetNValBaseCode(Name,val,m,smap); +// int n0=S->NVals; +// int i=1; +// for(int j=0;jNVals=i-1;return i-1;} +// else +// { +// val.resize(i); +// val[i-1] = d; +// i++; +// } +// } +// } +// m=S->NVals=i-1; +// return i-1; +// ); +// } // //------------------------------------------------------------------------- // @@ -162,12 +164,12 @@ template int dbgclgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) { Symbol *S; - double d; + T d; int N; HANDLE_EXCEPTIONS( { S=clgetBaseCode(Name,val,n,smap,true); - if ((N=clparseVal(S,&n,&d))>0) val = (T)d; + if ((N=clparseVal(S,&n,d))>0) val = d; return N; } ); @@ -175,22 +177,22 @@ int dbgclgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) // //---------------------------------------------------------------------- // -template <> -int dbgclgetValp(const std::string& Name, std::string& val, int& n, SMap smap)=delete; +// template <> +// int dbgclgetValp(const std::string& Name, std::string& val, int& n, SMap smap)=delete; -int dbgclgetValp(const std::string& Name, std::string& val, int& n, SMap smap=SMap()) -{ - Symbol *S; - std::string d; - int N; - HANDLE_EXCEPTIONS( - { - S=clgetBaseCode(Name,val,n,smap,true); - if ((N=clparseVal(S,&n,d))>0) val = d; - return N; - } - ); -} +// int dbgclgetValp(const std::string& Name, std::string& val, int& n, SMap smap=SMap()) +// { +// Symbol *S; +// std::string d; +// int N; +// HANDLE_EXCEPTIONS( +// { +// S=clgetBaseCode(Name,val,n,smap,true); +// if ((N=clparseVal(S,&n,d))>0) val = d; +// return N; +// } +// ); +// } // //---------------------------------------------------------------------- // @@ -198,46 +200,48 @@ template int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap=SMap()) { Symbol *S; - double d; - int N; - HANDLE_EXCEPTIONS( - { - S=clgetBaseCode(Name,val,n,smap,true); - int i=1; - while(i <= n) - { - if ((N=clparseVal(S,&n,&d))==CL_FAIL) return N; - else if (N==0) break; - else {val.push_back((T)d); i++;} - } - return i-1; - } - ); -} -template <> -int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap)=delete; -// -//---------------------------------------------------------------------- -// -int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap=SMap()) -{ - Symbol *S; - std::string d; + // double d; + T d; int N; HANDLE_EXCEPTIONS( { S=clgetBaseCode(Name,val,n,smap,true); int i=1; + val.resize(0); while(i <= n) { - if ((N=clparseVal(S,&n,d))==CL_FAIL) return N; + if ((N=clparseVal(S,&i,d))==CL_FAIL) return N; else if (N==0) break; + // else {val.push_back((T)d); i++;} else {val.push_back(d); i++;} } - return i-1; + return n=S->NVals=val.size(); } ); } +// template <> +// int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap)=delete; +// // +// //---------------------------------------------------------------------- +// // +// int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap=SMap()) +// { +// Symbol *S; +// std::string d; +// int N; +// HANDLE_EXCEPTIONS( +// S=clgetNValBaseCode(Name,val,n,smap,true); +// int i=1; +// val.resize(0); +// while(i <= n) +// { +// if ((N=clparseVal(S,&i,d))==CL_FAIL) return N; +// else if (N==0) break; +// else {val.push_back(d); i++;} +// } +// return n=S->NVals=val.size(); +// ); +// } // //---------------------------------------------------------------------- diff --git a/code/clgetValp.h b/code/clgetValp.h index bdef0f5..6bad2e5 100644 --- a/code/clgetValp.h +++ b/code/clgetValp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2021, 2022 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) + * Copyright (c) 2000-2025, 2026 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/code/clparseVal.cc b/code/clparseVal.cc index 1643684..a959896 100644 --- a/code/clparseVal.cc +++ b/code/clparseVal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012, 2013 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) + * Copyright (c) 2000-2025, 2026 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,6 +42,7 @@ extern "C" { #ifdef __cplusplus } #endif + int clparseVal(Symbol *S, int *Which, string& val) { unsigned int N = _ABS(*Which); @@ -60,39 +61,3 @@ int clparseVal(Symbol *S, int *Which, string& val) return CL_FAIL; } - - -int clparseVal(Symbol *S, int *Which, double *d) -{ - unsigned int N = _ABS(*Which); -HANDLE_EXCEPTIONS( - if (S != NULL) - { - if (N > S->NVals) return 0; - if (ISSET(S->Attributes,CL_BOOLTYPE)) - { - int retVal; - string val(S->Val[N-1]); - if ((retVal=clIsTrue(val))==1) *d=1; - else if ((retVal=clIsFalse(val))==1) *d=0; - //*d = clIsTrue(val); - if (retVal == CL_UNKNOWNBOOL ) - { - clBoolParsingError clExcp; - reportParseError(clExcp, *S, N-1); - } - } - else - { - int n=calc((char *)S->Val[N-1].c_str(),d); - if (n < 0) - { - clNumParsingError clExcp; - reportParseError(clExcp,*S, N-1); - } - } - return 1; - } - else return CL_FAIL; -) -} diff --git a/code/clparseVal.h b/code/clparseVal.h index dc96f8d..e47dc85 100644 --- a/code/clparseVal.h +++ b/code/clparseVal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2021, 2022 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) + * Copyright (c) 2000-2025, 2026 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,11 +15,65 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - */ + * $Id: clparseVal.c,v 2.0 1998/11/11 07:13:02 sanjay Exp sanjay $ */ + #ifndef CLPARSEVAL_H #define CLPARSEVAL_H #include -int clparseVal(Symbol *S, int *Which, double* val); +#include +#include +#include +#include +#include +#include +#include + +template +int clparseVal(Symbol *S, int *Which, T &d) +{ + unsigned int N = _ABS(*Which); +HANDLE_EXCEPTIONS( + if (S != NULL) + { + if (N > S->NVals) return 0; + if (ISSET(S->Attributes,CL_BOOLTYPE)) + { + int retVal; + string val(S->Val[N-1]); + if ((retVal=clIsTrue(val))==1) d=1; + else if ((retVal=clIsFalse(val))==1) d=0; + //*d = clIsTrue(val); + if (retVal == CL_UNKNOWNBOOL) + { + clBoolParsingError clExcp; + reportParseError(clExcp, *S, N-1); + } + } + else + { + double dd=d; + int n=calc((char *)S->Val[N-1].c_str(),&dd); + d=dd; + if (n < 0) + { + clNumParsingError clExcp; + reportParseError(clExcp,*S, N-1); + } + } + return 1; + } + else return CL_FAIL; +) +} + +// +// Delete the function generated by the template above for string. +// The specific implementation of this is in clparseVal.cc +// +template <> +int clparseVal(Symbol *S, int *Which, string& val)=delete; + int clparseVal(Symbol *S, int *which, string& val); + #endif diff --git a/code/tstcpp.cc b/code/tstcpp.cc index 688b1d8..c9ceb15 100644 --- a/code/tstcpp.cc +++ b/code/tstcpp.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2021, 2022 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) + * Copyright (c) 2000-2025, 2026 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 8c8d6af39a1e4303cd462639d2f788f88d54b655 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Tue, 24 Mar 2026 08:21:49 -0600 Subject: [PATCH 05/21] General cleanup, and further refactoring in clgetValp.cc. --- code/clgetValp.cc | 194 +++++++--------------------------------------- code/clgetValp.h | 46 ----------- 2 files changed, 30 insertions(+), 210 deletions(-) diff --git a/code/clgetValp.cc b/code/clgetValp.cc index ed76800..b50df0c 100644 --- a/code/clgetValp.cc +++ b/code/clgetValp.cc @@ -22,43 +22,34 @@ // // There are templated version of clgetValp(), clgetNValp(), // dbgclgetValp() and dbgclgetNValp(). These use the templated -// clgetBaseCode() and clparseVal(). This file needs to be included -// in any code that uses clgetValp() interface. It is therefore -// included in clinteract.h (which is required in the client code -// anyway). +// clgetBaseCode() and clparseVal(). // // Templates for std::string type is deleted and overloaded since // val = (T)d cannot work the same way for string as it works // for float,int, bool types. // // For directly using clget?Valp() interface, nothing else is required -// other than these templates. This useage is recommended. -// For backward compatibility, the clget[SIBF][N]Valp() functions are +// other than these templates. This usage is recommended. For +// backward compatibility, the clget[SIBF][N]Valp() functions are // implemented which are wrappers around clgetValp() functions. These -// functions are still in use in other parts of the library -- so these -// are required even internally for now. -// -//---------------------------------------------------------------------------------------------------------- -// Calls with type in the name for backward compatibility. -// -// Similar functions may also be possible for pure-C interface. +// functions are still in use in other parts of the library -- so +// these are required even internally for now. Similar functions may +// also be possible for pure-C interface. // #ifndef CLGETVALP_CPP #define CLGETVALP_CPP #include - // // //---------------------------------------------------------------------- -// The templated API-level function that can be used in the applications. // template -int clgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) +int clgetValp0(const std::string& Name, T& val, int& n, SMap smap=SMap(),bool dbg=false) { Symbol *S; int N; HANDLE_EXCEPTIONS( - S=clgetBaseCode(Name,val,n,smap); + S=clgetBaseCode(Name,val,n,smap,dbg); T d; //if ((N=clparseVal(S,&n,d))>0) val = (T)d; if ((N=clparseVal(S,&n,d))>0) val = d; @@ -67,181 +58,56 @@ int clgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) ); } // -//------------------------------------------------------------------------- -// -// template <> -// int clgetValp(const std::string&, std::string& val, int& n,SMap)=delete; -// // -// //---------------------------------------------------------------------- -// // -// int clgetValp(const std::string& Name, std::string& val, int& n, SMap smap=SMap()) -// { -// Symbol *S; -// int N; -// HANDLE_EXCEPTIONS( -// S=clgetBaseCode(Name,val,n,smap); -// std::string d; -// if ((N=clparseVal(S,&n,d))>0) val = d; - -// return N; -// ); -// } -// -//------------------------------------------------------------------------- -// -// //---------------------------------------------------------------------- -// The templated API-level function that can be used in the applications. -// The clgetN?Valp() functions are wrappers around this function for -// backward compatibility. -// // -//---------------------------------------------------------------------- template -int clgetValp(const std::string& Name, std::vector& val, int& m, const SMap smap=SMap()) +int clgetValpVec(const std::string& Name, std::vector& val, int& m, const SMap smap=SMap(),bool dbg=false) { Symbol *S; - T d; HANDLE_EXCEPTIONS( - S=clgetNValBaseCode(Name,val,m,smap); + S=clgetNValBaseCode(Name,val,m,smap,dbg); int n0=S->NVals; int i=1; + val.resize(0); for(int j=0;jNVals=i-1;return i-1;} - else - { - val.resize(i); - //val[i-1] = (T)d; - val[i-1] = d; - i++; - } + if (m==0) break; + else {val.push_back(d);i++;} } } - m=S->NVals=i-1; - return i-1; + //m=S->NVals=i-1; + return m=val.size(); ); } -// template <> -// int clgetValp(const std::string&, std::vector& val, int& n,const SMap)=delete; - -// // -// //---------------------------------------------------------------------- -// // -// int clgetValp(const std::string& Name, std::vector& val, int& m, const SMap smap=SMap()) -// { -// Symbol *S; -// std::string d; - -// HANDLE_EXCEPTIONS( -// S=clgetNValBaseCode(Name,val,m,smap); -// int n0=S->NVals; -// int i=1; -// for(int j=0;jNVals=i-1;return i-1;} -// else -// { -// val.resize(i); -// val[i-1] = d; -// i++; -// } -// } -// } -// m=S->NVals=i-1; -// return i-1; -// ); -// } // //------------------------------------------------------------------------- -// -template -int dbgclgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) -{ - Symbol *S; - T d; - int N; - HANDLE_EXCEPTIONS( - { - S=clgetBaseCode(Name,val,n,smap,true); - if ((N=clparseVal(S,&n,d))>0) val = d; - return N; - } - ); -} +// The templated API-level function that can be used in the applications. +// The clgetN?Valp() functions are wrappers around this function for +// backward compatibility. // //---------------------------------------------------------------------- // -// template <> -// int dbgclgetValp(const std::string& Name, std::string& val, int& n, SMap smap)=delete; +template +int clgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) +{return clgetValp0(Name,val,n,smap,false);} -// int dbgclgetValp(const std::string& Name, std::string& val, int& n, SMap smap=SMap()) -// { -// Symbol *S; -// std::string d; -// int N; -// HANDLE_EXCEPTIONS( -// { -// S=clgetBaseCode(Name,val,n,smap,true); -// if ((N=clparseVal(S,&n,d))>0) val = d; -// return N; -// } -// ); -// } +template +int dbgclgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) +{return clgetValp0(Name,val,n,smap,true);} // //---------------------------------------------------------------------- // +template +int clgetValp(const std::string& Name, std::vector& val, int& n, SMap smap=SMap()) +{return clgetValpVec(Name,val,n,smap,false);} + template int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap=SMap()) -{ - Symbol *S; - // double d; - T d; - int N; - HANDLE_EXCEPTIONS( - { - S=clgetBaseCode(Name,val,n,smap,true); - int i=1; - val.resize(0); - while(i <= n) - { - if ((N=clparseVal(S,&i,d))==CL_FAIL) return N; - else if (N==0) break; - // else {val.push_back((T)d); i++;} - else {val.push_back(d); i++;} - } - return n=S->NVals=val.size(); - } - ); -} -// template <> -// int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap)=delete; -// // -// //---------------------------------------------------------------------- -// // -// int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap=SMap()) -// { -// Symbol *S; -// std::string d; -// int N; -// HANDLE_EXCEPTIONS( -// S=clgetNValBaseCode(Name,val,n,smap,true); -// int i=1; -// val.resize(0); -// while(i <= n) -// { -// if ((N=clparseVal(S,&i,d))==CL_FAIL) return N; -// else if (N==0) break; -// else {val.push_back(d); i++;} -// } -// return n=S->NVals=val.size(); -// ); -// } +{return clgetValpVec(Name,val,n,smap,true);} // //---------------------------------------------------------------------- diff --git a/code/clgetValp.h b/code/clgetValp.h index 6bad2e5..d14dbc6 100644 --- a/code/clgetValp.h +++ b/code/clgetValp.h @@ -32,52 +32,6 @@ #include #include #include -//#include #include #include -//#include -// -// // -//---------------------------------------------------------------------- -// The templated API-level function that can be used in the applications. -// The clget?Valp() functions are wrappers around this function for -// backward compatibility. -// -// int clgetValp(const string& Name, std::string& val, int& n, SMap& smap); -// template -// int clgetValp(const string& Name, T& val, int& n, SMap& smap); -// // -// //------------------------------------------------------------------------- -// // -// template -// int clgetValp(const string& Name, T& val, int& n); - -// -//------------------------------------------------------------------------- -// -// template -// int dbgclgetValp(const string& Name, T& val, int& n, SMap& smap); - -// // -// //------------------------------------------------------------------------- -// // -// template -// int dbgclgetValp(const string& Name, T& val, int& n); - -// -//---------------------------------------------------------------------- -// The templated API-level function that can be used in the applications. -// The clgetN?Valp() functions are wrappers around this function for -// backward compatibility. -// -// template -// int clgetNValp(const string& Name, vector& val, int& m, const SMap &smap); - -// template -// int clgetNValp(const string& Name, vector& val, int& m); - -// int clgetNValp(const string& Name, vector& val, int& m, const SMap &smap); - -// int clgetNValp(const string& Name, vector& val, int& m); - #endif From 94c0d6ea9eeae86ecf92d36e8402eaaab05f52bd Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Tue, 24 Mar 2026 08:52:19 -0600 Subject: [PATCH 06/21] Minor mods and cleanup in ErrorObj.{cc,h} --- code/ErrorObj.cc | 12 +++++++++--- code/ErrorObj.h | 11 ++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/code/ErrorObj.cc b/code/ErrorObj.cc index c5a8005..2b31582 100644 --- a/code/ErrorObj.cc +++ b/code/ErrorObj.cc @@ -28,10 +28,16 @@ void ErrorObj::SetSource(const char *s) if (s) {Src = s;} } -const char* ErrorObj::what() +std::string ErrorObj::what() { - Message=Id+": "+Msg; - return Message.c_str(); + std::string Message=Id+": "+Msg; + return Message; +} + +const char* ErrorObj::what() const noexcept +{ + std::string tmp=what(); + return tmp.c_str(); } ostream &operator<<(ostream& o, const ErrorObj &E) diff --git a/code/ErrorObj.h b/code/ErrorObj.h index 76bbadb..2eb9636 100644 --- a/code/ErrorObj.h +++ b/code/ErrorObj.h @@ -28,16 +28,16 @@ using namespace std; class ErrorObj: public std::exception{ public: enum {Informational=100,Recoverable,Severe,Fatal}; - ErrorObj():Id(), Msg(), Src(), Message(),Level(0) + ErrorObj():Id(), Msg(), Src(),Level(0) {}; // Id.resize(0);Msg.resize(0);Src.resize(0);Message.resize(0);}; ErrorObj(const char *m, const char *i, int l=0): - Id(i), Msg(m), Src(), Message(),Level(l) + Id(i), Msg(m), Src(), Level(l) {}; ErrorObj(const string &m, const string &i, int l): - Id(i), Msg(m), Src(), Message(),Level(l) + Id(i), Msg(m), Src(), Level(l) {}; ErrorObj(const ErrorObj& that); @@ -47,7 +47,8 @@ class ErrorObj: public std::exception{ void SetSource(const char *m=0); const char *Source() {return Src.c_str();} int Severity() {return Level;} - const char *what(); + const char* what() const noexcept; + std::string what(); ostream &operator<<(const std::string& m) {return cerr << m;} ostream &operator<<(const char *m) {return cerr << m;} @@ -55,7 +56,7 @@ class ErrorObj: public std::exception{ friend ostream &operator<<(ostream& o,const ErrorObj&); protected: - string Id,Msg,Src,Message; + string Id,Msg,Src; int Level; }; From 8cd5f0614de65cf4affce4375fb07513158d119a Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Tue, 24 Mar 2026 10:36:07 -0600 Subject: [PATCH 07/21] Revert "Minor mods and cleanup in ErrorObj.{cc,h}" This reverts commit 94c0d6ea9eeae86ecf92d36e8402eaaab05f52bd. --- code/ErrorObj.cc | 12 +++--------- code/ErrorObj.h | 11 +++++------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/code/ErrorObj.cc b/code/ErrorObj.cc index 2b31582..c5a8005 100644 --- a/code/ErrorObj.cc +++ b/code/ErrorObj.cc @@ -28,16 +28,10 @@ void ErrorObj::SetSource(const char *s) if (s) {Src = s;} } -std::string ErrorObj::what() +const char* ErrorObj::what() { - std::string Message=Id+": "+Msg; - return Message; -} - -const char* ErrorObj::what() const noexcept -{ - std::string tmp=what(); - return tmp.c_str(); + Message=Id+": "+Msg; + return Message.c_str(); } ostream &operator<<(ostream& o, const ErrorObj &E) diff --git a/code/ErrorObj.h b/code/ErrorObj.h index 2eb9636..76bbadb 100644 --- a/code/ErrorObj.h +++ b/code/ErrorObj.h @@ -28,16 +28,16 @@ using namespace std; class ErrorObj: public std::exception{ public: enum {Informational=100,Recoverable,Severe,Fatal}; - ErrorObj():Id(), Msg(), Src(),Level(0) + ErrorObj():Id(), Msg(), Src(), Message(),Level(0) {}; // Id.resize(0);Msg.resize(0);Src.resize(0);Message.resize(0);}; ErrorObj(const char *m, const char *i, int l=0): - Id(i), Msg(m), Src(), Level(l) + Id(i), Msg(m), Src(), Message(),Level(l) {}; ErrorObj(const string &m, const string &i, int l): - Id(i), Msg(m), Src(), Level(l) + Id(i), Msg(m), Src(), Message(),Level(l) {}; ErrorObj(const ErrorObj& that); @@ -47,8 +47,7 @@ class ErrorObj: public std::exception{ void SetSource(const char *m=0); const char *Source() {return Src.c_str();} int Severity() {return Level;} - const char* what() const noexcept; - std::string what(); + const char *what(); ostream &operator<<(const std::string& m) {return cerr << m;} ostream &operator<<(const char *m) {return cerr << m;} @@ -56,7 +55,7 @@ class ErrorObj: public std::exception{ friend ostream &operator<<(ostream& o,const ErrorObj&); protected: - string Id,Msg,Src; + string Id,Msg,Src,Message; int Level; }; From 52d33700f4b1f135dabd93dc161c36d2a98b4c80 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Wed, 25 Mar 2026 08:24:35 -0600 Subject: [PATCH 08/21] clgetValp.cc: Fix in clgetValpVec(), where val.push_back(d) does not work! (see commented code) SetVar.cc: Re-set S->Val in case of error during parsing/setting values. --- code/SetVar.cc | 48 +++++++++++++++++++---------------------------- code/clgetValp.cc | 32 ++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/code/SetVar.cc b/code/SetVar.cc index 0ff2b48..71e9a85 100644 --- a/code/SetVar.cc +++ b/code/SetVar.cc @@ -113,15 +113,22 @@ int UnsetVar(Symbol *S, int setFactoryDefaults) // Count the number of commas. Strip off leading and trailing white // spaces from val, copy into another buffer, take comma seperated // tokens from the new buffer and put it in Tab. - // try - { - vector tokens = clstrtokp(trim(string(val)),',',CL_ESC); - unsigned ntokens=tokens.size(); - pos->NVals=ntokens; - pos->Val.resize(pos->NVals); - for (unsigned i=0;i valBackup=pos->Val; + try + { + vector tokens = clstrtokp(trim(string(val)),',',CL_ESC); + unsigned ntokens=tokens.size(); + pos->NVals=ntokens; + pos->Val.resize(pos->NVals); + for (unsigned i=0;iNVals=valBackup.size(); + pos->Val=valBackup; + throw(x); + } } if (dodoinp) doinp((char *)(string("-t ")+key).c_str()); @@ -233,7 +240,9 @@ void SetVal(const char *v, Symbol *S, int i) } catch (clError& x) { - cerr << x.what() << " " << S->Val[i] << endl; + // Same as cerr << x.what(), except that the output + // stream is centrally specified in clError. + x << x << " at position " << i << endl; throw(x); } @@ -242,25 +251,6 @@ void SetVal(const char *v, Symbol *S, int i) S->NVals=S->Val.size(); S->Val[i]=vv; S->Used=0; - - /* if ((unsigned int)i >= S->NVals) */ - /* { */ - /* S->Val = (char **)realloc(S->Val,sizeof(char **)*(i+1)); */ - /* len = S->NVals; */ - /* do S->Val[len++]=NULL; while (len < i); */ - /* } */ - - /* len=strlen(vv.c_str()); */ - - /* S->Val[i] = (char *)realloc(S->Val[i],len+1); */ - - /* if (strlen(vv.c_str())) */ - /* { */ - /* strncpy(S->Val[i],vv.c_str(),len+1); */ - /* S->Val[i][len] = '\0'; */ - /* if ((unsigned int)i>=S->NVals) S->NVals++; */ - /* S->Used=0; */ - /* } */ } } diff --git a/code/clgetValp.cc b/code/clgetValp.cc index b50df0c..b598392 100644 --- a/code/clgetValp.cc +++ b/code/clgetValp.cc @@ -65,23 +65,45 @@ int clgetValpVec(const std::string& Name, std::vector& val, int& m, const SMa { Symbol *S; HANDLE_EXCEPTIONS( - S=clgetNValBaseCode(Name,val,m,smap,dbg); + S=clgetNValBaseCode(Name,val,m,smap); int n0=S->NVals; int i=1; - val.resize(0); for(int j=0;jNVals=i-1; - return m=val.size(); + return m=S->NVals=i-1; ); + // S=clgetNValBaseCode(Name,val,m,smap,dbg); + // int n0=S->NVals; + // int i=1; + // val.resize(0); + // for(int j=0;jNVals=i-1; + // return m=val.size(); + // ); + } // //------------------------------------------------------------------------- From 46b1315c13e7d3a95daebd918e25e1f44f09ac75 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Wed, 25 Mar 2026 11:33:49 -0600 Subject: [PATCH 09/21] Added the missing cldbg*getValp() functions with SMap. --- code/clgetValp.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/clgetValp.cc b/code/clgetValp.cc index b598392..e06785c 100644 --- a/code/clgetValp.cc +++ b/code/clgetValp.cc @@ -152,18 +152,21 @@ int clgetFValp(const std::string& Name, float& val, int& n, SMap &smap) int clgetNFValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} int clgetNFValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int cldbggetFValp(const std::string& Name, float& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetFValp(const std::string& Name, float& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} int clgetIValp(const std::string& Name, int &val, int &n) {return clgetValp(Name,val,n);} int clgetIValp(const std::string& Name, int& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNIValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} int clgetNIValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int cldbggetIValp(const std::string& Name, int& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetIValp(const std::string& Name, int& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} int clgetBValp(const std::string& Name, bool& val, int &n) {return clgetValp(Name,val,n);} int clgetBValp(const std::string& Name, bool& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNBValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} int clgetNBValp(const std::string& Name, std::vector& val, int& n, SMap &smap){return clgetValp(Name,val,n,smap);} int cldbggetBValp(const std::string& Name, bool& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetBValp(const std::string& Name, bool& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n, smap);} int clgetSValp(const std::string& Name, std::string& val, int &n) {return clgetValp(Name,val,n);} int clgetSValp(const std::string& Name, std::string& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} @@ -171,6 +174,7 @@ int clgetNSValp(const std::string& Name, std::vector& val, int& n) int clgetNSValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNSValp(const std::string& Name, std::vector& val, int& n, const SMap smap) {return clgetValp(Name,val,n,smap);} int cldbggetSValp(const std::string& Name, std::string& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetSValp(const std::string& Name, std::string& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} int cldbggetNIValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} int cldbggetNIValp(const std::string& Key, std::vector& val, int& m, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} From 7a18c63d21e4ade54c1189e9013d7e0a475a1d20 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Wed, 25 Mar 2026 13:43:53 -0600 Subject: [PATCH 10/21] Removed unnecessary #include --- code/GetStdString.cc | 1 - code/clMakeArgvFromFile.cc | 2 +- code/clReset.cc | 1 - code/clSaneExit.cc | 1 - code/clSetOptions.cc | 2 +- code/clgetBaseCode.h | 2 +- code/clgetCommandLine.cc | 2 +- code/clgetConfigFile.cc | 2 +- code/clgetInputFile.cc | 2 +- code/clgetOptsList.cc | 2 +- code/clgetOutputFile.cc | 2 +- code/clgetSVal.cc | 2 +- code/clgetValp.h | 2 +- code/clhashdefines.h | 4 ++++ code/clparseVal.cc | 1 - code/clparseVal.h | 2 +- code/clstrtStream.cc | 1 - code/isBool.cc | 1 - code/setAutoDefaults.h | 1 - code/shell.h | 4 +--- 20 files changed, 16 insertions(+), 21 deletions(-) diff --git a/code/GetStdString.cc b/code/GetStdString.cc index 1ac0647..05d4117 100644 --- a/code/GetStdString.cc +++ b/code/GetStdString.cc @@ -19,7 +19,6 @@ /* $Id: clstrtStream.c,v 2.0 1998/11/11 07:13:02 sanjay Exp $ */ #include #include -#include #ifdef __cplusplus extern "C" { diff --git a/code/clMakeArgvFromFile.cc b/code/clMakeArgvFromFile.cc index a013f32..1927227 100644 --- a/code/clMakeArgvFromFile.cc +++ b/code/clMakeArgvFromFile.cc @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #ifdef __cplusplus diff --git a/code/clReset.cc b/code/clReset.cc index b375b0e..28be9af 100644 --- a/code/clReset.cc +++ b/code/clReset.cc @@ -20,7 +20,6 @@ #include #include -#include #include #ifdef __cplusplus diff --git a/code/clSaneExit.cc b/code/clSaneExit.cc index 65f5760..fe91e73 100644 --- a/code/clSaneExit.cc +++ b/code/clSaneExit.cc @@ -18,7 +18,6 @@ */ /* $Id: clSaneExit.c,v 2.0 1998/11/11 07:12:54 sanjay Exp $ */ #include -#include #ifdef __cplusplus extern "C" { diff --git a/code/clSetOptions.cc b/code/clSetOptions.cc index d27a130..004c8b5 100644 --- a/code/clSetOptions.cc +++ b/code/clSetOptions.cc @@ -18,7 +18,7 @@ */ /* $Id: clgetSVal.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ #include -#include +#include #include #include #include diff --git a/code/clgetBaseCode.h b/code/clgetBaseCode.h index 0faaa90..91785c6 100644 --- a/code/clgetBaseCode.h +++ b/code/clgetBaseCode.h @@ -30,7 +30,7 @@ #ifndef CLGETBASECODE_H #define CLGETBASECODE_H #include -#include +#include #include #include #include diff --git a/code/clgetCommandLine.cc b/code/clgetCommandLine.cc index ce0d413..d74ca19 100644 --- a/code/clgetCommandLine.cc +++ b/code/clgetCommandLine.cc @@ -18,7 +18,7 @@ */ /* $Id: clgetCommandLine.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/code/clgetConfigFile.cc b/code/clgetConfigFile.cc index eb0b2ee..61ef319 100644 --- a/code/clgetConfigFile.cc +++ b/code/clgetConfigFile.cc @@ -19,7 +19,7 @@ /* $Id: clgetConfigFile.c,v 2.1 1999/03/19 04:29:49 sanjay Exp sanjay $ */ #include #include -#include +#include #include #include diff --git a/code/clgetInputFile.cc b/code/clgetInputFile.cc index a103b22..0039f19 100644 --- a/code/clgetInputFile.cc +++ b/code/clgetInputFile.cc @@ -18,7 +18,7 @@ */ /* $Id: clgetInputFile.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/code/clgetOptsList.cc b/code/clgetOptsList.cc index 01cb1cf..fe51139 100644 --- a/code/clgetOptsList.cc +++ b/code/clgetOptsList.cc @@ -18,7 +18,7 @@ */ /* $Id: clgetOptsList.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ #include -#include +#include #define OPTSLEN 128 #ifdef __cplusplus diff --git a/code/clgetOutputFile.cc b/code/clgetOutputFile.cc index 3645a26..a2d0a5e 100644 --- a/code/clgetOutputFile.cc +++ b/code/clgetOutputFile.cc @@ -18,7 +18,7 @@ */ /* $Id: clgetOutputFile.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/code/clgetSVal.cc b/code/clgetSVal.cc index 444d217..700963d 100644 --- a/code/clgetSVal.cc +++ b/code/clgetSVal.cc @@ -18,7 +18,7 @@ */ /* $Id: clgetSVal.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ #include -#include +#include #include #include #include diff --git a/code/clgetValp.h b/code/clgetValp.h index d14dbc6..acaef64 100644 --- a/code/clgetValp.h +++ b/code/clgetValp.h @@ -30,7 +30,7 @@ #ifndef CLGETVALP_H #define CLGETVALP_H #include -#include +#include #include #include #include diff --git a/code/clhashdefines.h b/code/clhashdefines.h index 010c05f..fe60f9c 100644 --- a/code/clhashdefines.h +++ b/code/clhashdefines.h @@ -44,6 +44,10 @@ #define CL_ALLOWHIDDEN 1 // keyword value change, no warning issued #define CL_ALLOWHIDDEN_WITHWARNING 2 // keyword value change, warning issued +#define CL_FAIL -1 +#define CL_ESC '\\' /* The character used for 'escaping' chars. */ + /* in a string */ + #define SETBIT(V,MASK) ((V) |= (MASK)) // Bitwise OR with the mask #define RESETBIT(V,MASK) ((V) &= ~(MASK)) // Bitwise AND with the complement of the mask #define ISSET(V,MASK) ((((V) & (MASK))==(MASK))) diff --git a/code/clparseVal.cc b/code/clparseVal.cc index a959896..d8b64fa 100644 --- a/code/clparseVal.cc +++ b/code/clparseVal.cc @@ -20,7 +20,6 @@ #include #include #include -//#include #include #include #include diff --git a/code/clparseVal.h b/code/clparseVal.h index e47dc85..4027758 100644 --- a/code/clparseVal.h +++ b/code/clparseVal.h @@ -21,7 +21,7 @@ #define CLPARSEVAL_H #include -#include +#include #include #include #include diff --git a/code/clstrtStream.cc b/code/clstrtStream.cc index 792139a..bb095ca 100644 --- a/code/clstrtStream.cc +++ b/code/clstrtStream.cc @@ -19,7 +19,6 @@ /* $Id: clstrtStream.c,v 2.0 1998/11/11 07:13:02 sanjay Exp $ */ #include #include -#include #ifdef __cplusplus extern "C" { diff --git a/code/isBool.cc b/code/isBool.cc index 2abba05..ce76e63 100644 --- a/code/isBool.cc +++ b/code/isBool.cc @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/code/setAutoDefaults.h b/code/setAutoDefaults.h index f19ea79..1362a27 100644 --- a/code/setAutoDefaults.h +++ b/code/setAutoDefaults.h @@ -21,7 +21,6 @@ #define SETAUTODEFAULTS_H #include #include -#include #include #include #include diff --git a/code/shell.h b/code/shell.h index 6bdb5dc..070ebdb 100644 --- a/code/shell.h +++ b/code/shell.h @@ -22,14 +22,12 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { #endif -#define CL_FAIL -1 -#define CL_ESC '\\' /* The character used for 'escaping' chars. */ - /* in a string */ /* Bits to determine what needs to be copied in Copy[V,C]Symb routines. */ #define COPYNAME 1 #define COPYCLASS 2 From 1eeae035bd4c481983471bc477f25877f3b7c7f8 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Fri, 27 Mar 2026 08:50:28 -0600 Subject: [PATCH 11/21] Fix in CMakeLists.txt for installing GTest. Some cleanup + adding more unit tests. --- code/test/unittest/CMakeLists.txt | 5 +- .../unittest/test_parafeed_noninteractive.cpp | 69 +++++++------------ 2 files changed, 29 insertions(+), 45 deletions(-) diff --git a/code/test/unittest/CMakeLists.txt b/code/test/unittest/CMakeLists.txt index 757d36c..c41c4d1 100644 --- a/code/test/unittest/CMakeLists.txt +++ b/code/test/unittest/CMakeLists.txt @@ -17,8 +17,9 @@ if(NOT GTest_FOUND) include(FetchContent) FetchContent_Declare( googletest - URL https://github.com/google/googletest/archive/release-1.12.1.zip - DOWNLOAD_EXTRACT_TIMESTAMP TRUE + GIT_REPOSITORY https://github.com/google/googletest + GIT_TAG release-1.12.1 + GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(googletest) endif() diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index a8f6606..3be29cf 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -8,6 +8,8 @@ #include class ParafeedTest : public ::testing::Test { +public: + ~ParafeedTest() {clCleanUp();} protected: std::pair MakeArgv(const std::vector& args) { char** argv = new char*[args.size()]; @@ -140,44 +142,33 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { } // below tests can be included when parafeed throws on these wrong usage. -/* -TEST_F(ParafeedTest, PrintsErrorOnUnknownParameter) { - std::vector args = { - "test2", - "help=noprompt", - "bool=true", - "unknownparam=badvalue" // This should cause an error message - }; - auto [argc, argv] = MakeArgv(args); - - ::testing::internal::CaptureStdout(); // Begin capturing stderr - - BeginCL(argc, argv); - clInteractive(0); - - // Try accessing only the known parameter - bool b = false; - int i = 1; - clgetValp("bool", b, i); - - std::string unused; - i = 1; - clgetSValp("unknownparam", unused, i); - EndCL(); +// TEST_F(ParafeedTest, PrintsErrorOnUnknownParameter) { +// std::vector args = { +// "test2", +// "help=noprompt", +// "bool=true" +// // "unknownparam=badvalue" // This will add the named parameter to the symbol table. +// // The library allows user-defined symbols. +// }; +// auto [argc, argv] = MakeArgv(args); - std::string errOutput = ::testing::internal::GetCapturedStdout(); - std::cerr << "Captured stderr: \n" << errOutput << std::endl; +// BeginCL(argc, argv); +// clInteractive(0); - FreeArgv(argc, argv); +// // Try accessing only the known parameter +// bool b = false; +// int i = 1; +// clgetValp("bool", b, i); - // Check that the error message contains the expected output - EXPECT_NE(errOutput.find("undefined symbol"), std::string::npos) - << "Expected error message about undefined symbol not found in stdout:\n" << errOutput; +// std::string unused; +// i = 1; +// clgetSValp("unknownparam", unused, i); +// EndCL(); +// FreeArgv(argc, argv); +// } -} -*/ /*TEST_F(ParafeedTest, MissingRequiredParam) { @@ -221,7 +212,7 @@ TEST_F(ParafeedTest, PrintsErrorOnUnknownParameter) { EXPECT_NE(output.find("###Error"), std::string::npos) << "Expected error message for missing 'strarr' not found in stdout:\n" << output; } - +*/ TEST_F(ParafeedTest, WrongDataType) { std::vector args = { @@ -235,8 +226,6 @@ TEST_F(ParafeedTest, WrongDataType) { }; auto [argc, argv] = MakeArgv(args); - ::testing::internal::CaptureStdout(); - BeginCL(argc, argv); clInteractive(0); @@ -250,7 +239,7 @@ TEST_F(ParafeedTest, WrongDataType) { clgetValp("bool", b, i); // Should fail due to wrong type - clgetValp("oneint", oneint, i); + EXPECT_THROW({clgetValp("oneint", oneint, i);},clError); clgetValp("string", s, i); int idx = 0; @@ -260,13 +249,7 @@ TEST_F(ParafeedTest, WrongDataType) { EndCL(); - std::string output = ::testing::internal::GetCapturedStdout(); FreeArgv(argc, argv); - - - EXPECT_NE(output.find("###Error"), std::string::npos) - << "Expected error for wrong data type for 'oneint' not found:\n" << output; - -}*/ +} From 3258248246df5d5742a4d81eedbc2f565161a927 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Fri, 27 Mar 2026 10:13:34 -0600 Subject: [PATCH 12/21] test_parafeed_noninterative.cpp: Enabled the WrongDataType test. --- code/test/unittest/test_parafeed_noninteractive.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index 3be29cf..20f7f57 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -218,11 +218,11 @@ TEST_F(ParafeedTest, WrongDataType) { std::vector args = { "test2", "help=noprompt", - "bool=true", - "oneint=not_int", // Wrong data type + "bool=not_true", // Wrong data type + "oneint=not_int", // Wrong data type "string=showstrarr", "strarr=foo,bar", - "farray=1,2,3,4,5,6,7,8,9,10" + "farray=1,x,3,4,5,6,7,8,9,10" // One wrong data type }; auto [argc, argv] = MakeArgv(args); @@ -236,7 +236,7 @@ TEST_F(ParafeedTest, WrongDataType) { std::vector farray(10); int i = 1; - clgetValp("bool", b, i); + EXPECT_THROW({clgetValp("bool", b, i);},clError); // Should fail due to wrong type EXPECT_THROW({clgetValp("oneint", oneint, i);},clError); @@ -245,7 +245,8 @@ TEST_F(ParafeedTest, WrongDataType) { int idx = 0; clgetValp("strarr", strarr, idx); int N = 10; - clgetValp("farray", farray, N); + + EXPECT_THROW({clgetValp("farray", farray, N);},clError); EndCL(); From 2c48209d2aa23592e340e3e24ea6dcc3a09dabb7 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Fri, 27 Mar 2026 12:06:52 -0600 Subject: [PATCH 13/21] SearchSymb.cc,cl.h: Added SearchVSymb() function to the low-level API. --- code/SearchSymb.cc | 7 ++++++- code/cl.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/code/SearchSymb.cc b/code/SearchSymb.cc index cb0351a..b39ad50 100644 --- a/code/SearchSymb.cc +++ b/code/SearchSymb.cc @@ -37,7 +37,7 @@ extern "C" { return t; } /*----------------------------------------------------------------------*/ - Symbol *SearchVSymb(const char *Name, Symbol *Tab) + Symbol *SearchVSymb(const char *Name, Symbol *Tab=cl_SymbTab) { return minmatch(Name,Tab); } @@ -56,3 +56,8 @@ extern "C" { #ifdef __cplusplus } #endif + /*----------------------------------------------------------------------*/ + Symbol *SearchVSymb(const char *Name) + { + return SearchVSymb(Name,cl_SymbTab); + } diff --git a/code/cl.h b/code/cl.h index 740046a..2ad4bc6 100644 --- a/code/cl.h +++ b/code/cl.h @@ -271,6 +271,8 @@ void clSetPrompt(const bool& prompt); } #endif #ifdef __cplusplus +Symbol *SearchVSymb(const char *Name); + int clgetFullp(const string& Arg, int &N); int clgetFullValp(const string& Name, string& Val); int dbgclgetFullValp(const string& Name, string& Val); From f803d9bf852c54aad7b88208604c237e6b4864d2 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Sun, 29 Mar 2026 18:49:47 -0600 Subject: [PATCH 14/21] cl.h, shell.l: Added get/set_shell_input() functions to get/set a function for scanning input stream for parsing. clgetBaseCode.h: Throw exception if the searched symbol is not found. test_parafeed_noninteractive.cpp: Not-yet-working attempts at setting shell_input function. --- code/cl.h | 3 ++ code/clgetBaseCode.h | 4 ++ code/shell.l | 23 +++++----- .../unittest/test_parafeed_noninteractive.cpp | 46 +++++++++++++++---- 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/code/cl.h b/code/cl.h index 2ad4bc6..4d6e05b 100644 --- a/code/cl.h +++ b/code/cl.h @@ -307,6 +307,9 @@ int clgetNBValp(const string& Name, bool& Val, int& N, SMap &smap); int clgetNIValp(const string& Name, int& Val, int& N, SMap &smap); int clgetBaseCore(const string& Name, int& Val, int& N, SMap &smap); void clTextColouring(const string& text, const unsigned int textType, string& startSeq, string& endSeq); +extern std::function cl_shell_input_g; +void set_shell_input(std::function inp_func); +std::function get_shell_input(); #endif #if !defined(FORTRAN) #include diff --git a/code/clgetBaseCode.h b/code/clgetBaseCode.h index 91785c6..700891e 100644 --- a/code/clgetBaseCode.h +++ b/code/clgetBaseCode.h @@ -67,6 +67,8 @@ Symbol* clgetBaseCode(const string& Name, T& val, int& n, SMap &smap=SMap(), boo if (!smap.empty()) S->smap = smap; } + else + throw(clError("Unknown keyword","###Error: ",CL_FATAL)); ) return S; }; @@ -100,6 +102,8 @@ Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap if (!smap.empty()) S->smap = smap; } + else + throw(clError("Unknown keyword","###Error: ",CL_FATAL)); ); return S; } diff --git a/code/shell.l b/code/shell.l index c978ede..317c4c8 100644 --- a/code/shell.l +++ b/code/shell.l @@ -28,6 +28,7 @@ #include #include #include +#include using namespace std; /* This piece is added only if commandline editing (via GNU Readline and @@ -41,26 +42,20 @@ be another #define here for lex to define input() using GNU Readline calls instead of gets(). */ -//typedef yy_size_t cl_size_t; -typedef int cl_size_t; extern char *sh_Prompt; char *sh_line=0; -void (*CL_INPUT)(char *, int *, int)=NULL; -void inp_readline(char *,cl_size_t &,int); -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=inp_readline(buf,max_size) - //#define YY_INPUT(buf,result,max_size) (*CL_INPUT)(buf,&result,max_size) static int inp_readline(char *buf, size_t max_size) { int n,result; static size_t index=0; - rl_instream=stdin; - rl_outstream=stderr; + if (rl_instream == NULL) rl_instream=stdin; + if (rl_outstream == NULL) rl_outstream=stderr; if (index==0) { if (sh_line) free(sh_line);sh_line=0; - sh_line = readline(sh_Prompt); + if (rl_instream == stdin) sh_line = readline(sh_Prompt); + else sh_line = readline(NULL); if (sh_line) { stripwhite(sh_line); @@ -93,7 +88,13 @@ static int inp_readline(char *buf, size_t max_size) } return result; } - /* +std::function cl_shell_input_g=inp_readline; +void set_shell_input(std::function inp_func) {cl_shell_input_g=inp_func;}; +std::function get_shell_input() {return cl_shell_input_g;} +//int inp_readline(char *,size_t); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) {result=cl_shell_input_g(buf,max_size);}//inp_readline(buf,max_size) +/* { \ int n; \ static int index=0; \ diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index 20f7f57..7a91f33 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -6,10 +6,31 @@ #include #include #include +#include class ParafeedTest : public ::testing::Test { public: - ~ParafeedTest() {clCleanUp();} + // std::function backup_cl_shell_input_g; + ~ParafeedTest() + { + clCleanUp(); + // set_shell_input(backup_cl_shell_input_g); + } + + static int test_shell_inp(char *buf, size_t len) + { + string str("go\n\0"); + buf = (char *)str.c_str(); + len=str.size()+1; + return (int)len; + } + + void init() + { + // backup_cl_shell_input_g=get_shell_input(); + // set_shell_input(test_shell_inp); + } + protected: std::pair MakeArgv(const std::vector& args) { char** argv = new char*[args.size()]; @@ -27,7 +48,9 @@ class ParafeedTest : public ::testing::Test { delete[] argv; } }; - +// +//--------------------------------------------------------------------------------- +// TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { std::vector args = { "test2", @@ -46,6 +69,13 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { }; auto [argc, argv] = MakeArgv(args); + // FILE* string_stream=NULL; + // string input_str("go"); + // read_from_string(input_str); + // string_stream = fmemopen(const_cast(input_str.c_str()), input_str.size(), "r"); + // rl_instream = string_stream; + + init(); BeginCL(argc, argv); clInteractive(0); @@ -163,7 +193,7 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { // std::string unused; // i = 1; -// clgetSValp("unknownparam", unused, i); +// clgetValp("unknownparam", unused, i); // EndCL(); // FreeArgv(argc, argv); @@ -236,18 +266,18 @@ TEST_F(ParafeedTest, WrongDataType) { std::vector farray(10); int i = 1; - EXPECT_THROW({clgetValp("bool", b, i);},clError); + EXPECT_THROW(clgetValp("bool", b, i),clError); // Should fail due to wrong type - EXPECT_THROW({clgetValp("oneint", oneint, i);},clError); - + EXPECT_THROW(clgetValp("oneint", oneint, i),clError); + clgetValp("string", s, i); int idx = 0; clgetValp("strarr", strarr, idx); int N = 10; - EXPECT_THROW({clgetValp("farray", farray, N);},clError); - + EXPECT_THROW(clgetValp("farray", farray, N),clError); + EndCL(); FreeArgv(argc, argv); From 3736ae4ca5ddc7321803c4d0bea1a55c3c8bdc4b Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Mon, 30 Mar 2026 20:20:37 -0600 Subject: [PATCH 15/21] ParafeedTest.h: Factored out the ParafeedTest class. Nominal support for setting the input source for flex scanner (see the note below) test_parafeed_{non}interactive.cpp: Added the interactive test. Switching the input source of flex scanner does not work within a single file. All test in a single file are run in the same process in GTest. And I (SB) haven't yet figure out how to set the YY_INPUT macro to different input sources dynamically at runtime. Therefore, current the interactive and non-interactive tests are in separate file. --- code/test/unittest/CMakeLists.txt | 10 +- code/test/unittest/ParafeedTest.h | 65 ++++++++ .../unittest/test_parafeed_interactive.cpp | 49 ++++++ .../unittest/test_parafeed_noninteractive.cpp | 154 +++++++++--------- 4 files changed, 195 insertions(+), 83 deletions(-) create mode 100644 code/test/unittest/ParafeedTest.h create mode 100644 code/test/unittest/test_parafeed_interactive.cpp diff --git a/code/test/unittest/CMakeLists.txt b/code/test/unittest/CMakeLists.txt index c41c4d1..b7fa92d 100644 --- a/code/test/unittest/CMakeLists.txt +++ b/code/test/unittest/CMakeLists.txt @@ -35,11 +35,17 @@ add_executable(ParafeedTests ${TEST_SOURCES}) # Link with Google Test target_include_directories(ParafeedTests PRIVATE - "${CMAKE_SOURCE_DIR}/code") + "${CMAKE_SOURCE_DIR}/code/test") target_link_libraries(ParafeedTests GTest::gtest_main parafeed) +set(TEST_SOURCES test_parafeed_interactive.cpp) +add_executable(iParafeedTests ${TEST_SOURCES}) +target_include_directories(iParafeedTests PRIVATE "${CMAKE_SOURCE_DIR}/code/test") +# Link with Google Test +target_link_libraries(iParafeedTests GTest::gtest_main parafeed) + # Add the test executable as a test target add_test(NAME ParafeedTests COMMAND ParafeedTests) - +add_test(NAME iParafeedTests COMMAND iParafeedTests) diff --git a/code/test/unittest/ParafeedTest.h b/code/test/unittest/ParafeedTest.h new file mode 100644 index 0000000..70dda36 --- /dev/null +++ b/code/test/unittest/ParafeedTest.h @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +string cmd_g; +bool firstPass=true; +class ParafeedTest : public ::testing::Test { +public: + ~ParafeedTest() + { + clCleanUp(); + // Reset the input mechanism for the scanner/parser + set_shell_input(backup_cl_shell_input_g); + firstPass=true; + } + + //------------------------------------------------------------------ + // Function that can supply the input to the scanner/parser from a + // string (here the global cmd_g variable). + static int test_shell_inp(char *buf, size_t max_size) + { + int i=0; + for (auto c : cmd_g) buf[i++]=c; + + i=0; + if (firstPass) {i=cmd_g.size();firstPass=false;} + + return i; + } + + //------------------------------------------------------------------ + // Save the current input function for the scanner before setting + // the scanner another function. + void sendCmd(const string& cmd) + { + cmd_g=cmd; + backup_cl_shell_input_g=get_shell_input(); + set_shell_input(test_shell_inp); + } + + std::function backup_cl_shell_input_g; + +protected: + std::pair MakeArgv(const std::vector& args) { + char** argv = new char*[args.size()]; + for (size_t i = 0; i < args.size(); ++i) { + argv[i] = new char[args[i].size() + 1]; + std::strcpy(argv[i], args[i].c_str()); + } + return {static_cast(args.size()), argv}; + } + + void FreeArgv(int argc, char** argv) { + for (int i = 0; i < argc; ++i) { + delete[] argv[i]; + } + delete[] argv; + } +}; diff --git a/code/test/unittest/test_parafeed_interactive.cpp b/code/test/unittest/test_parafeed_interactive.cpp new file mode 100644 index 0000000..97ca9d5 --- /dev/null +++ b/code/test/unittest/test_parafeed_interactive.cpp @@ -0,0 +1,49 @@ +#include +// +//-------------------------------------------------------------------- +// This does not yet work as expected. +// +TEST_F(ParafeedTest, Interactive) { + std::vector args = { + "test2", + //"help=noprompt", + "bool=1", // Wrong data type + "oneint=1", // Wrong data type + "string=showstrarr", + "strarr=foo,bar", + "farray=1,3,4,5,6,7,8,9,10" // One wrong data type + }; + auto [argc, argv] = MakeArgv(args); + + clCleanUp(); + sendCmd("bool=true\noneint=100\ninp\ngo\n"); + //sendCmd("go\n"); + BeginCL(argc, argv); + clInteractive(1); + + bool b = false; + int oneint = 0; + std::string s; + std::vector strarr; + std::vector farray(10); + int i = 1; + + // EXPECT_THROW(clgetValp("bool", b, i),clError); + clgetValp("bool", b, i); + + // Should fail due to wrong type + clgetValp("oneint", oneint, i); + + clgetValp("string", s, i); + int idx = 0; + clgetValp("strarr", strarr, idx); + int N = 10; + + clgetValp("farray", farray, N); + + EndCL(); + + EXPECT_EQ(oneint,100); + + FreeArgv(argc, argv); +} diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index 7a91f33..ed5f5db 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -1,60 +1,11 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class ParafeedTest : public ::testing::Test { -public: - // std::function backup_cl_shell_input_g; - ~ParafeedTest() - { - clCleanUp(); - // set_shell_input(backup_cl_shell_input_g); - } - - static int test_shell_inp(char *buf, size_t len) - { - string str("go\n\0"); - buf = (char *)str.c_str(); - len=str.size()+1; - return (int)len; - } - - void init() - { - // backup_cl_shell_input_g=get_shell_input(); - // set_shell_input(test_shell_inp); - } - -protected: - std::pair MakeArgv(const std::vector& args) { - char** argv = new char*[args.size()]; - for (size_t i = 0; i < args.size(); ++i) { - argv[i] = new char[args[i].size() + 1]; - std::strcpy(argv[i], args[i].c_str()); - } - return {static_cast(args.size()), argv}; - } - - void FreeArgv(int argc, char** argv) { - for (int i = 0; i < argc; ++i) { - delete[] argv[i]; - } - delete[] argv; - } -}; +#include // -//--------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------- // TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { std::vector args = { "test2", - "help=noprompt", + //"help=noprompt", "bool=true", "bool1=false", "int=42", @@ -69,13 +20,7 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { }; auto [argc, argv] = MakeArgv(args); - // FILE* string_stream=NULL; - // string input_str("go"); - // read_from_string(input_str); - // string_stream = fmemopen(const_cast(input_str.c_str()), input_str.size(), "r"); - // rl_instream = string_stream; - - init(); + sendCmd("go\n"); BeginCL(argc, argv); clInteractive(0); @@ -173,31 +118,31 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { // below tests can be included when parafeed throws on these wrong usage. -// TEST_F(ParafeedTest, PrintsErrorOnUnknownParameter) { -// std::vector args = { -// "test2", -// "help=noprompt", -// "bool=true" -// // "unknownparam=badvalue" // This will add the named parameter to the symbol table. -// // The library allows user-defined symbols. -// }; -// auto [argc, argv] = MakeArgv(args); +TEST_F(ParafeedTest, PrintsErrorOnUnknownParameter) { + std::vector args = { + "test2", + "help=noprompt", + "bool=true" + // "unknownparam=badvalue" // This will add the named parameter to the symbol table. + // The library allows user-defined symbols. + }; + auto [argc, argv] = MakeArgv(args); -// BeginCL(argc, argv); -// clInteractive(0); + BeginCL(argc, argv); + clInteractive(0); -// // Try accessing only the known parameter -// bool b = false; -// int i = 1; -// clgetValp("bool", b, i); + // Try accessing only the known parameter + bool b = false; + int i = 1; + clgetValp("bool", b, i); -// std::string unused; -// i = 1; -// clgetValp("unknownparam", unused, i); -// EndCL(); + std::string unused; + i = 1; + clgetValp("unknownparam", unused, i); + EndCL(); -// FreeArgv(argc, argv); -// } + FreeArgv(argc, argv); +} @@ -257,7 +202,7 @@ TEST_F(ParafeedTest, WrongDataType) { auto [argc, argv] = MakeArgv(args); BeginCL(argc, argv); - clInteractive(0); + // clInteractive(0); bool b = false; int oneint = 0; @@ -283,4 +228,51 @@ TEST_F(ParafeedTest, WrongDataType) { FreeArgv(argc, argv); } +// +//-------------------------------------------------------------------- +// This does not yet work as expected. +// +// TEST_F(ParafeedTest, Interactive) { +// std::vector args = { +// "test2", +// //"help=noprompt", +// "bool=1", // Wrong data type +// "oneint=1", // Wrong data type +// "string=showstrarr", +// "strarr=foo,bar", +// "farray=1,3,4,5,6,7,8,9,10" // One wrong data type +// }; +// auto [argc, argv] = MakeArgv(args); + +// clCleanUp(); +// sendCmd("bool=true\noneint=100\ninp\ngo\n"); +// //sendCmd("go\n"); +// BeginCL(argc, argv); +// clInteractive(1); + +// bool b = false; +// int oneint = 0; +// std::string s; +// std::vector strarr; +// std::vector farray(10); +// int i = 1; + +// // EXPECT_THROW(clgetValp("bool", b, i),clError); +// clgetValp("bool", b, i); + +// // Should fail due to wrong type +// clgetValp("oneint", oneint, i); + +// clgetValp("string", s, i); +// int idx = 0; +// clgetValp("strarr", strarr, idx); +// int N = 10; +// clgetValp("farray", farray, N); + +// EndCL(); + +// EXPECT_EQ(oneint,100); + +// FreeArgv(argc, argv); +// } From 4443074f2cb0b019abf1fbaee468c25064a1a205 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Wed, 1 Apr 2026 09:09:58 -0600 Subject: [PATCH 16/21] Added the Interactive test where some working of the interactive session get tested. Add explanatory comments. --- .../unittest/test_parafeed_interactive.cpp | 92 ++++++++++++++++--- 1 file changed, 78 insertions(+), 14 deletions(-) diff --git a/code/test/unittest/test_parafeed_interactive.cpp b/code/test/unittest/test_parafeed_interactive.cpp index 97ca9d5..fcdb9e1 100644 --- a/code/test/unittest/test_parafeed_interactive.cpp +++ b/code/test/unittest/test_parafeed_interactive.cpp @@ -7,43 +7,107 @@ TEST_F(ParafeedTest, Interactive) { std::vector args = { "test2", //"help=noprompt", - "bool=1", // Wrong data type - "oneint=1", // Wrong data type + "bool=1", + "oneint=x", "string=showstrarr", "strarr=foo,bar", - "farray=1,3,4,5,6,7,8,9,10" // One wrong data type + "farray=1,3,4,5,6,7,8,9,10" }; auto [argc, argv] = MakeArgv(args); clCleanUp(); + // sendCmd() sets the parser input stream to be the give string. + // The parses scans this string in the interactive shell (started + // in the EndCL() call below). sendCmd("bool=true\noneint=100\ninp\ngo\n"); - //sendCmd("go\n"); + BeginCL(argc, argv); clInteractive(1); bool b = false; int oneint = 0; + int N = 10; + int i = 1; + std::string s; std::vector strarr; - std::vector farray(10); - int i = 1; + std::vector farray(N); - // EXPECT_THROW(clgetValp("bool", b, i),clError); - clgetValp("bool", b, i); + i=1;clgetValp("bool", b, i); - // Should fail due to wrong type - clgetValp("oneint", oneint, i); + i=1; + + // + // The setting from argv is used in the first pass + // (a.k.a. "registeration pass"). Without the "help=noprompt" + // detected in this first pass, the EndCL() call starts the + // interactive shell, which triggers the the second pass on the + // "go" command (setjmp() called in EndCL() to restart execution + // from the location of the clInteractive() call). In this second + // pass the interactive settings (here, vis the sendCmd() call) + // replaces the values which are then available in the clgetValp() + // calls. + // + if (cl_Pass == 0) // cl_Pass is a global parafeed lib. control + // variable + EXPECT_THROW(clgetValp("oneint", oneint, i),clError); + else + clgetValp("oneint", oneint, i); - clgetValp("string", s, i); - int idx = 0; - clgetValp("strarr", strarr, idx); - int N = 10; + i=1;clgetValp("string", s, i); + + i=0;clgetValp("strarr", strarr, i); clgetValp("farray", farray, N); EndCL(); + // Expect the value as set interactively vis sendCmd() EXPECT_EQ(oneint,100); FreeArgv(argc, argv); } + +TEST_F(ParafeedTest, InteractiveWrongType) { + std::vector args = { + "test2", + //"help=noprompt", + "bool=1", + "oneint=1", + "string=showstrarr", + "strarr=foo,bar", + "farray=1,3,4,5,6,7,8,9,10" + }; + auto [argc, argv] = MakeArgv(args); + + clCleanUp(); + // Interactively set the wrong type for bool + sendCmd("oneint=100\nbool=xtrue\ninp\ngo\n"); + + BeginCL(argc, argv); + clInteractive(1); + + bool b = false; + int oneint = 0; + int N = 10; + int i = 1; + std::string s; + std::vector strarr; + std::vector farray(N); + + i=1;clgetValp("bool", b, i); + + i=1;clgetValp("oneint", oneint, i); + + i=1;clgetValp("string", s, i); + + i=0;clgetValp("strarr", strarr, i); + + clgetValp("farray", farray, N); + + // Exception thrown in the interactive shell due to illegal + // keyword setting (bool=xtrue) via sendCmd() + EXPECT_THROW(EndCL(),clError); + + FreeArgv(argc, argv); +} From fc5317ffc73988e72d58e0271177f7efaba4646f Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Wed, 1 Apr 2026 10:52:07 -0600 Subject: [PATCH 17/21] test_parafeed_noninteractive.cpp: Fixed the ParsesClgetValpParametersCorrectly test to be non-interactive. --- code/test/unittest/test_parafeed_noninteractive.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index ed5f5db..0b7e60a 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -5,7 +5,7 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { std::vector args = { "test2", - //"help=noprompt", + "help=noprompt", "bool=true", "bool1=false", "int=42", @@ -20,7 +20,6 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { }; auto [argc, argv] = MakeArgv(args); - sendCmd("go\n"); BeginCL(argc, argv); clInteractive(0); From bbce2f1ac2ae6dcb22a8ada30d6efe83b5576bc8 Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Thu, 2 Apr 2026 07:46:21 -0600 Subject: [PATCH 18/21] clgetValp.cc: The dbg parameter in clgetValVec() was not forwarded to the clgetNValBaseCode() call. See change request in PR #33. test_parafeed_interactive.cpp: Typo corrections in the comments. --- code/clgetValp.cc | 2 +- code/test/unittest/test_parafeed_interactive.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/clgetValp.cc b/code/clgetValp.cc index e06785c..93f3ce5 100644 --- a/code/clgetValp.cc +++ b/code/clgetValp.cc @@ -65,7 +65,7 @@ int clgetValpVec(const std::string& Name, std::vector& val, int& m, const SMa { Symbol *S; HANDLE_EXCEPTIONS( - S=clgetNValBaseCode(Name,val,m,smap); + S=clgetNValBaseCode(Name,val,m,smap,dbg); int n0=S->NVals; int i=1; for(int j=0;j Date: Thu, 2 Apr 2026 08:29:43 -0600 Subject: [PATCH 19/21] cl.h: Added the missing wrappers to translate dbgclget*() cldbgget*() (see comments for PR #33) Added std:: name space for string and vector Reorganized the wrapper for clgetValp() to reduce cognitive overload for humans clgetValp.cc: Reorganized the wrapper for clgetValp() to reduce cognitive overload for humans --- code/cl.h | 127 ++++++++++++++++++++++++++++++++-------------- code/clgetValp.cc | 45 ++++++++-------- 2 files changed, 112 insertions(+), 60 deletions(-) diff --git a/code/cl.h b/code/cl.h index 4d6e05b..bba5608 100644 --- a/code/cl.h +++ b/code/cl.h @@ -130,7 +130,7 @@ extern int add_history(char *); Symbol *AddQKey(const char *Name, const char *Type, Symbol **Head, Symbol **Tail); int ParseCmdLine(int, char **); - vector clMakeArgvFromFile(const string& Name); + std::vector clMakeArgvFromFile(const std::string& Name); int startShell(); void clLoadSymb(); @@ -165,10 +165,10 @@ int clgetNBVal(char *Name, bool *Val, int *N); int dbgclgetNBVal(char *Name, bool *Val, int *N); #ifdef __cplusplus -int clTgetOptp(const string& Name, string& Type); -int clgetOptp(const string& Name); -int clgetNValsp(const string& Name); -int clSetOptions(const string& Name, const VString& options); +int clTgetOptp(const std::string& Name, std::string& Type); +int clgetOptp(const std::string& Name); +int clgetNValsp(const std::string& Name); +int clSetOptions(const std::string& Name, const VString& options); #endif void clRestartShell(); @@ -184,9 +184,9 @@ int clclearOptsList(char ***,int); int clloadConfig(char *); void clCleanUp(); #ifdef __cplusplus -int clBoolCmp(const string&, const bool& cmpVal); -int clIsTrue(const string&); -int clIsFalse(const string&); +int clBoolCmp(const std::string&, const bool& cmpVal); +int clIsTrue(const std::string&); +int clIsFalse(const std::string&); #endif void clReset(); void clRetry(); @@ -252,7 +252,7 @@ int UnsetVar(Symbol *,int); int SetVar(char *Name, char *val, Symbol *tab,short int force, short int fullmatch, short int doinp); //void SetVal(const char *, Symbol *, int); #ifdef __cplusplus - void VerifyVal(const char *, Symbol *,string &, + void VerifyVal(const char *, Symbol *,std::string &, std::function matchOptsLambda, std::function noMatchExceptionLambda); #endif @@ -273,40 +273,90 @@ void clSetPrompt(const bool& prompt); #ifdef __cplusplus Symbol *SearchVSymb(const char *Name); -int clgetFullp(const string& Arg, int &N); -int clgetFullValp(const string& Name, string& Val); -int dbgclgetFullValp(const string& Name, string& Val); +int clgetBaseCore(const std::string& Name, int& Val, int& N, SMap &smap); +int clgetFullValp(const std::string& Name, std::string& Val); +int dbgclgetFullValp(const std::string& Name, std::string& Val); +int clgetFullp(const std::string& Arg, int &N); +// +//------------------------------------------------------------------------------------------------ +// Wrappers for clgetValp(...,T& val,...) and clgetValp(...,vector&,...) +// +int clgetIValp(const std::string& Name, int& Val, int& N); +int clgetFValp(const std::string& Name, float& Val, int& N); +int clgetBValp(const std::string& Name, bool& val, int& N); +int clgetSValp(const std::string& Name, std::string& Val, int& N); +//------------------------------------------------------------------------------------------------ +int clgetNIValp(const std::string& Key, std::vector& Val, int& m); +int clgetNFValp(const std::string& Name, std::vector& Val, int& N); +int clgetNBValp(const std::string& Name, std::vector& val, int& N); +int clgetNSValp(const std::string& Name, std::vector& Val, int& N); +// +//------------------------------------------------------------------------------------------------ +// Wrappers for clgetValp(...,T&,..., SMap&) and clgetValp(...,vector&,...,SMap&) +// +int clgetIValp(const std::string& Name, int& Val, int& N, SMap &smap); +int clgetFValp(const std::string& Name, float& Val, int& N, SMap &smap); +int clgetBValp(const std::string& Name, bool& Val, int& N, SMap &smap); +int clgetSValp(const std::string& Name, std::string& Val, int& N, SMap &smap); +//------------------------------------------------------------------------------------------------ +int clgetNIValp(const std::string& Name, std::vector& Val, int& N, SMap &smap); +int clgetNFValp(const std::string& Name, std::vector& Val, int& N, SMap &smap); +int clgetNBValp(const std::string& Name, std::vector& Val, int& N, SMap &smap); +int clgetNSValp(const std::string& Name, std::vector& Val, int& N, SMap& smap); +// +//------------------------------------------------------------------------------------------------ +// Wrappers for clgetValp(...,T&,...,bool dbg=true) and clgetValp(...,vector&,...,bool dbg=true) +// +int dbgclgetIValp(const std::string& Name, int& Val, int& N); +int dbgclgetFValp(const std::string& Name, float& Val, int& N); +int dbgclgetBValp(const std::string& Name, bool& val, int& N); +int dbgclgetSValp(const std::string& Name, std::string& Val, int& N); +//------------------------------------------------------------------------------------------------ +int dbgclgetNIValp(const std::string& Key, std::vector& Val, int& m); +int dbgclgetNFValp(const std::string& Name, std::vector& Val, int& N); +int dbgclgetNBValp(const std::string& Name, std::vector& val, int& N); +int dbgclgetNSValp(const std::string& Name, std::vector& Val, int& N); +// +//------------------------------------------------------------------------------------------------ +// Wrappers for clgetValp(...,T&,...,SMap&, bool dbg=true) and clgetValp(...,vector&,...,SMap&, bool dbg=true) +// +int dbgclgetIValp(const std::string& Name, int& Val, int& N, SMap &smap); +int dbgclgetFValp(const std::string& Name, float& Val, int& N, SMap &smap); +int dbgclgetBValp(const std::string& Name, bool& val, int& N, SMap &smap); +int dbgclgetSValp(const std::string& Name, std::string& Val, int& N, SMap &smap); +//------------------------------------------------------------------------------------------------ +int dbgclgetNIValp(const std::string& Key, std::vector& Val, int& N, SMap &smap); +int dbgclgetNFValp(const std::string& Name, std::vector& Val, int& N, SMap &smap); +int dbgclgetNBValp(const std::string& Name, std::vector& val, int& N, SMap &smap); +int dbgclgetNSValp(const std::string& Name, std::vector& Val, int& N, SMap &smap); +// +//------------------------------------------------------------------------------------------------ +// Wrappers to translate dbgclget*() to cldbgget*() +// +int cldbggetIValp(const std::string& Name, int& val, int& n); +int cldbggetFValp(const std::string& Name, float& val, int& n); +int cldbggetBValp(const std::string& Name, bool& val, int& n); +int cldbggetSValp(const std::string& Name, std::string& val, int& n); -int clgetIValp(const string& Name, int& Val, int& N); -int dbgclgetIValp(const string& Name, int& Val, int& N); -int clgetNIValp(const string& Key, vector& Val, int& m); -int dbgclgetNIValp(const string& Key, int& Val, int& m); +int cldbggetIValp(const std::string& Name, int& val, int& n, SMap& smap); +int cldbggetFValp(const std::string& Name, float& val, int& n, SMap& smap); +int cldbggetBValp(const std::string& Name, bool& val, int& n, SMap& smap); +int cldbggetSValp(const std::string& Name, std::string& val, int& n, SMap& smap); -int clgetBValp(const string& Name, bool& val, int& N); -int dbgclgetBValp(const string& Name, bool& val, int& N); -int clgetNBValp(const string& Name, bool& val, int& N); -int dbgclgetNBValp(const string& Name, bool& val, int& N); +int cldbggetNIValp(const std::string& Key, std::vector& val, int& m); +int cldbggetNFValp(const std::string& Key, std::vector& val, int& m); +int cldbggetNBValp(const std::string& Key, std::vector& val, int& m); +int cldbggetNSValp(const std::string& Key, std::vector& val, int& m); -int clgetFValp(const string& Name, float& Val, int& N); -int dbgclgetFValp(const string& Name, float& Val, int& N); -int clgetNFValp(const string& Name, vector& Val, int& N); -int dbgclgetNFValp(const string& Name, float& Val, int& N); +int cldbggetNIValp(const std::string& Key, std::vector& val, int& m, SMap& smap); +int cldbggetNFValp(const std::string& Key, std::vector& val, int& m, SMap& smap); +int cldbggetNBValp(const std::string& Key, std::vector& val, int& m, SMap& smap); +int cldbggetNSValp(const std::string& Key, std::vector& val, int& m, SMap& smap); -int clgetSValp(const string& Name, string& Val, int& N); -int dbgclgetSValp(const string& Name, string& Val, int& N); -int clgetNSValp(const string& Name, vector& Val, int& N); -int dbgclgetNSValp(const string& Name, vector& Val, int& N); -int clgetSValp(const string& Name, string& Val, int& N, SMap &smap); -int clgetFValp(const string& Name, float& Val, int& N, SMap &smap); -int clgetBValp(const string& Name, bool& Val, int& N, SMap &smap); -int clgetIValp(const string& Name, int& Val, int& N, SMap &smap); -//int clgetNSValp(const string& Name, string& Val, int& N, SMap &smap); -int clgetNFValp(const string& Name, float& Val, int& N, SMap &smap); -int clgetNBValp(const string& Name, bool& Val, int& N, SMap &smap); -int clgetNIValp(const string& Name, int& Val, int& N, SMap &smap); -int clgetBaseCore(const string& Name, int& Val, int& N, SMap &smap); -void clTextColouring(const string& text, const unsigned int textType, string& startSeq, string& endSeq); +void clTextColouring(const std::string& text, const unsigned int textType, + std::string& startSeq, string& endSeq); + extern std::function cl_shell_input_g; void set_shell_input(std::function inp_func); std::function get_shell_input(); @@ -315,4 +365,3 @@ std::function get_shell_input(); #include #endif #endif - diff --git a/code/clgetValp.cc b/code/clgetValp.cc index 93f3ce5..5d2cfa9 100644 --- a/code/clgetValp.cc +++ b/code/clgetValp.cc @@ -145,43 +145,46 @@ int dbgclgetValp(const std::string& Name, std::vector& val, int& n, SMap smap // template -int cldbggetValp(const std::string& Name, T& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetValp(const std::string& Name, T& val, int& n) {return dbgclgetValp(Name,val,n);} -int clgetFValp(const std::string& Name, float &val, int &n) {return clgetValp(Name,val,n);} -int clgetFValp(const std::string& Name, float& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} +int clgetFValp(const std::string& Name, float &val, int &n) {return clgetValp(Name,val,n);} +int clgetFValp(const std::string& Name, float& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNFValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} int clgetNFValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} -int cldbggetFValp(const std::string& Name, float& val, int& n) {return dbgclgetValp(Name,val,n);} -int cldbggetFValp(const std::string& Name, float& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} -int clgetIValp(const std::string& Name, int &val, int &n) {return clgetValp(Name,val,n);} -int clgetIValp(const std::string& Name, int& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} +int clgetIValp(const std::string& Name, int &val, int &n) {return clgetValp(Name,val,n);} +int clgetIValp(const std::string& Name, int& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNIValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} int clgetNIValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} -int cldbggetIValp(const std::string& Name, int& val, int& n) {return dbgclgetValp(Name,val,n);} -int cldbggetIValp(const std::string& Name, int& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} -int clgetBValp(const std::string& Name, bool& val, int &n) {return clgetValp(Name,val,n);} -int clgetBValp(const std::string& Name, bool& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} +int clgetBValp(const std::string& Name, bool& val, int &n) {return clgetValp(Name,val,n);} +int clgetBValp(const std::string& Name, bool& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNBValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} int clgetNBValp(const std::string& Name, std::vector& val, int& n, SMap &smap){return clgetValp(Name,val,n,smap);} -int cldbggetBValp(const std::string& Name, bool& val, int& n) {return dbgclgetValp(Name,val,n);} -int cldbggetBValp(const std::string& Name, bool& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n, smap);} -int clgetSValp(const std::string& Name, std::string& val, int &n) {return clgetValp(Name,val,n);} -int clgetSValp(const std::string& Name, std::string& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} +int clgetSValp(const std::string& Name, std::string& val, int &n) {return clgetValp(Name,val,n);} +int clgetSValp(const std::string& Name, std::string& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNSValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} int clgetNSValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} int clgetNSValp(const std::string& Name, std::vector& val, int& n, const SMap smap) {return clgetValp(Name,val,n,smap);} -int cldbggetSValp(const std::string& Name, std::string& val, int& n) {return dbgclgetValp(Name,val,n);} -int cldbggetSValp(const std::string& Name, std::string& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} -int cldbggetNIValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} +int cldbggetIValp(const std::string& Name, int& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetFValp(const std::string& Name, float& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetBValp(const std::string& Name, bool& val, int& n) {return dbgclgetValp(Name,val,n);} +int cldbggetSValp(const std::string& Name, std::string& val, int& n) {return dbgclgetValp(Name,val,n);} + +int cldbggetIValp(const std::string& Name, int& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} +int cldbggetFValp(const std::string& Name, float& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} +int cldbggetBValp(const std::string& Name, bool& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n, smap);} +int cldbggetSValp(const std::string& Name, std::string& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} + +int cldbggetNIValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} +int cldbggetNFValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} +int cldbggetNBValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} +int cldbggetNSValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} + int cldbggetNIValp(const std::string& Key, std::vector& val, int& m, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} -int cldbggetNFValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} int cldbggetNFValp(const std::string& Key, std::vector& val, int& m, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} -int cldbggetNBValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} int cldbggetNBValp(const std::string& Key, std::vector& val, int& m, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} -int cldbggetNSValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} int cldbggetNSValp(const std::string& Key, std::vector& val, int& m, SMap& smap){return dbgclgetValp(Key, val, m,smap);} #endif From 02a4966b22d7e58a91f13550715bf0ac28004e9f Mon Sep 17 00:00:00 2001 From: Sanjay Bhatnagar Date: Thu, 2 Apr 2026 10:06:30 -0600 Subject: [PATCH 20/21] ParafeedTest.h: Applied the patch suggested in PR #33. test_parafeed_interactive.cpp: Removed a stray comment not applicable now. --- code/test/unittest/ParafeedTest.h | 22 ++++++++++++------- .../unittest/test_parafeed_interactive.cpp | 1 - 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/code/test/unittest/ParafeedTest.h b/code/test/unittest/ParafeedTest.h index 70dda36..dcbb362 100644 --- a/code/test/unittest/ParafeedTest.h +++ b/code/test/unittest/ParafeedTest.h @@ -6,10 +6,12 @@ #include #include #include +#include #include string cmd_g; bool firstPass=true; +size_t cmd_pos_g=0; class ParafeedTest : public ::testing::Test { public: ~ParafeedTest() @@ -18,6 +20,7 @@ class ParafeedTest : public ::testing::Test { // Reset the input mechanism for the scanner/parser set_shell_input(backup_cl_shell_input_g); firstPass=true; + cmd_pos_g=0; } //------------------------------------------------------------------ @@ -25,21 +28,24 @@ class ParafeedTest : public ::testing::Test { // string (here the global cmd_g variable). static int test_shell_inp(char *buf, size_t max_size) { - int i=0; - for (auto c : cmd_g) buf[i++]=c; + if (!firstPass || cmd_pos_g >= cmd_g.size()) return 0; - i=0; - if (firstPass) {i=cmd_g.size();firstPass=false;} - - return i; + const size_t n_to_copy = std::min(max_size, cmd_g.size() - cmd_pos_g); + std::memcpy(buf, cmd_g.data() + cmd_pos_g, n_to_copy); + cmd_pos_g += n_to_copy; + if (cmd_pos_g >= cmd_g.size()) firstPass=false; + return static_cast(n_to_copy); } //------------------------------------------------------------------ - // Save the current input function for the scanner before setting - // the scanner another function. + // Set the string for the scanner in test_shell_inp(). Save the + // current input function for the scanner before resetting the + // scanner void sendCmd(const string& cmd) { cmd_g=cmd; + firstPass=true; + cmd_pos_g=0; backup_cl_shell_input_g=get_shell_input(); set_shell_input(test_shell_inp); } diff --git a/code/test/unittest/test_parafeed_interactive.cpp b/code/test/unittest/test_parafeed_interactive.cpp index becf9fe..f8ef97e 100644 --- a/code/test/unittest/test_parafeed_interactive.cpp +++ b/code/test/unittest/test_parafeed_interactive.cpp @@ -1,7 +1,6 @@ #include // //-------------------------------------------------------------------- -// This does not yet work as expected. // TEST_F(ParafeedTest, Interactive) { std::vector args = { From 550837bdc44b41eb3fb2472d9b6772cf2f911975 Mon Sep 17 00:00:00 2001 From: Genie Hsieh Date: Thu, 2 Apr 2026 23:56:32 -0600 Subject: [PATCH 21/21] Fixed the CI unit test failures by making clTextColouring() robust when TERM is unset (i.e. getenv("TERM") == NULL), avoiding std::string construction from a null pointer. Added a new unit test that unsets TERM and verifies clTextColouring(...) does not throw, then restores the environment variable afterward. --- code/clTextColouring.cc | 5 ++++- .../unittest/test_parafeed_noninteractive.cpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/code/clTextColouring.cc b/code/clTextColouring.cc index 4040151..7f007ae 100644 --- a/code/clTextColouring.cc +++ b/code/clTextColouring.cc @@ -29,7 +29,10 @@ extern int clBreakStr(const string& str, string& Name, string& val); void clTextColouring(const string& text, const unsigned int textType,string& startSeq,string& endSeq) { - string term(getenv("TERM")); + //string term(getenv("TERM")); + const char *termEnv = getenv("TERM"); + string term = termEnv ? termEnv : ""; + if ((term.find("xterm") != std::string::npos) && // The current terminal cannot display colours (term.find("vt200") != std::string::npos) ) diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index 0b7e60a..1659328 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -1,4 +1,6 @@ #include +#include + // // --------------------------------------------------------------------------------- // @@ -115,6 +117,23 @@ TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { FreeArgv(argc, argv); } +TEST_F(ParafeedTest, TextColouringHandlesMissingTermEnvironment) { + const char* originalTerm = std::getenv("TERM"); + std::string originalTermValue = originalTerm ? originalTerm : ""; + + unsetenv("TERM"); + + std::string startSeq; + std::string endSeq; + EXPECT_NO_THROW(clTextColouring("keyword", CL_HIDDENKEYWORD, startSeq, endSeq)); + + if (originalTerm) { + setenv("TERM", originalTermValue.c_str(), 1); + } else { + unsetenv("TERM"); + } +} + // below tests can be included when parafeed throws on these wrong usage. TEST_F(ParafeedTest, PrintsErrorOnUnknownParameter) {