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/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/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/SetVar.cc b/code/SetVar.cc index 79302e2..71e9a85 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))*/ @@ -112,23 +113,62 @@ 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()); 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; + } + }; +std::function noMatchExceptionLambda_ptr=noMatchException; +/*----------------------------------------------------------------------*/ + 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 +221,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,11 +236,13 @@ 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) { - 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); } @@ -223,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/cl.h b/code/cl.h index 3447ae4..bba5608 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. @@ -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,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 *,std::string &, + std::function matchOptsLambda, + std::function noMatchExceptionLambda); #endif int CopyVSymb(Symbol *, Symbol *,int); int FreeVSymb(Symbol *); @@ -269,43 +271,97 @@ void clSetPrompt(const bool& prompt); } #endif #ifdef __cplusplus -int clgetFullp(const string& Arg, int &N); -int clgetFullValp(const string& Name, string& Val); -int dbgclgetFullValp(const string& Name, string& Val); +Symbol *SearchVSymb(const char *Name); + +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(); #endif #if !defined(FORTRAN) #include #endif #endif - 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/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/clgetBaseCode.h b/code/clgetBaseCode.h index 526e666..700891e 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 @@ -30,7 +30,7 @@ #ifndef CLGETBASECODE_H #define CLGETBASECODE_H #include -#include +#include #include #include #include @@ -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); @@ -68,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; }; @@ -76,30 +77,35 @@ 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; + else + throw(clError("Unknown keyword","###Error: ",CL_FATAL)); ); + return S; } // //---------------------------------------------------------------------- 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.cc b/code/clgetValp.cc index 5b0e925..5d2cfa9 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 @@ -22,128 +22,59 @@ // // 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()) -{ - Symbol *S; - int N; - HANDLE_EXCEPTIONS( - S=clgetBaseCode(Name,val,n,smap); - double d; - if ((N=clparseVal(S,&n,&d))>0) val = (T)d; - - return N; - ); -} -// -//------------------------------------------------------------------------- -// -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()) +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); - std::string d; + 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; 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; - double 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; - i++; - } - } - } - m=S->NVals=i-1; - return i-1; - ); - -} -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); + S=clgetNValBaseCode(Name,val,m,smap,dbg); int n0=S->NVals; int i=1; for(int j=0;jNVals=i-1;return i-1;} - else + if (m==0) break; + else { val.resize(i); val[i-1] = d; @@ -151,93 +82,54 @@ int clgetValp(const std::string& Name, std::vector& val, int& m, co } } } - m=S->NVals=i-1; - return i-1; + 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(); + // ); + } // //------------------------------------------------------------------------- -// -template -int dbgclgetValp(const std::string& Name, T& val, int& n, SMap smap=SMap()) -{ - Symbol *S; - double d; - int N; - HANDLE_EXCEPTIONS( - { - S=clgetBaseCode(Name,val,n,smap,true); - if ((N=clparseVal(S,&n,&d))>0) val = (T)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; - 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; - 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(d); i++;} - } - return i-1; - } - ); -} +{return clgetValpVec(Name,val,n,smap,true);} // //---------------------------------------------------------------------- @@ -253,39 +145,46 @@ int dbgclgetValp(const std::string& Name, std::vector& val, int& n, // 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 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 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 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 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 diff --git a/code/clgetValp.h b/code/clgetValp.h index bdef0f5..acaef64 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 @@ -30,54 +30,8 @@ #ifndef CLGETVALP_H #define CLGETVALP_H #include -#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 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 1643684..d8b64fa 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 @@ -20,7 +20,6 @@ #include #include #include -//#include #include #include #include @@ -42,6 +41,7 @@ extern "C" { #ifdef __cplusplus } #endif + int clparseVal(Symbol *S, int *Which, string& val) { unsigned int N = _ABS(*Which); @@ -60,39 +60,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..4027758 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/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 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/CMakeLists.txt b/code/test/unittest/CMakeLists.txt index 757d36c..b7fa92d 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() @@ -34,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..dcbb362 --- /dev/null +++ b/code/test/unittest/ParafeedTest.h @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +string cmd_g; +bool firstPass=true; +size_t cmd_pos_g=0; +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; + cmd_pos_g=0; + } + + //------------------------------------------------------------------ + // 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) + { + if (!firstPass || cmd_pos_g >= cmd_g.size()) return 0; + + 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); + } + + //------------------------------------------------------------------ + // 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); + } + + 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..f8ef97e --- /dev/null +++ b/code/test/unittest/test_parafeed_interactive.cpp @@ -0,0 +1,112 @@ +#include +// +//-------------------------------------------------------------------- +// +TEST_F(ParafeedTest, Interactive) { + std::vector args = { + "test2", + //"help=noprompt", + "bool=1", + "oneint=x", + "string=showstrarr", + "strarr=foo,bar", + "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 given string. + // The parser scans this string in the interactive shell (started + // in the EndCL() call below). + sendCmd("bool=true\noneint=100\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; + + // + // 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 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); + + 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); +} diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index a8f6606..1659328 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -1,31 +1,9 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -class ParafeedTest : public ::testing::Test { -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 +#include +// +// --------------------------------------------------------------------------------- +// TEST_F(ParafeedTest, ParsesClgetValpParametersCorrectly) { std::vector args = { "test2", @@ -139,19 +117,35 @@ 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) { std::vector args = { "test2", "help=noprompt", - "bool=true", - "unknownparam=badvalue" // This should cause an error message + "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); - ::testing::internal::CaptureStdout(); // Begin capturing stderr - BeginCL(argc, argv); clInteractive(0); @@ -162,22 +156,12 @@ TEST_F(ParafeedTest, PrintsErrorOnUnknownParameter) { std::string unused; i = 1; - clgetSValp("unknownparam", unused, i); - + clgetValp("unknownparam", unused, i); EndCL(); - std::string errOutput = ::testing::internal::GetCapturedStdout(); - std::cerr << "Captured stderr: \n" << errOutput << std::endl; - FreeArgv(argc, argv); - - // 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; - - } -*/ + /*TEST_F(ParafeedTest, MissingRequiredParam) { @@ -221,24 +205,22 @@ 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 = { "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); - ::testing::internal::CaptureStdout(); - BeginCL(argc, argv); - clInteractive(0); + // clInteractive(0); bool b = false; int oneint = 0; @@ -247,26 +229,68 @@ 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 - clgetValp("oneint", oneint, i); - + EXPECT_THROW(clgetValp("oneint", oneint, i),clError); + clgetValp("string", s, i); int idx = 0; clgetValp("strarr", strarr, idx); int N = 10; - clgetValp("farray", farray, N); + EXPECT_THROW(clgetValp("farray", farray, N),clError); + EndCL(); - std::string output = ::testing::internal::GetCapturedStdout(); 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; - EXPECT_NE(output.find("###Error"), std::string::npos) - << "Expected error for wrong data type for 'oneint' not found:\n" << output; - -}*/ +// clgetValp("farray", farray, N); + +// EndCL(); +// EXPECT_EQ(oneint,100); +// FreeArgv(argc, argv); +// } 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