diff --git a/README.md b/README.md index 55d639f..20e5d85 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,17 @@ CMake-based build system requires `cmake` version 3 or later. Use the following mkdir build cd build cmake -gmake +make +``` +The `-DGNUREADLINE=OFF` option to `cmake` will disable the use of the [GNU Readline library](https://en.wikipedia.org/wiki/GNU_Readline) for bash-style commandline editing and command history capabilities. The `-DENABLE_TESTING=ON` option also builds the application for unit testing, which can be executed by the following commands + +``` +make test + +or + +ctest ``` -The `-DGNUREADLINE=OFF` option to `cmake` will disable the use of the [GNU Readline library](https://en.wikipedia.org/wiki/GNU_Readline) for bash-style commandline editing and command history capabilities. The `-DENABLE_TESTING=ON` option will enable unit testing. While the hand-written `makefiles` have been tested with `make` version 3 only, they do not depend on a specific version of `make`. These `makefiles` are in the `code/nocmake_makefiles` directory. Using the command `cd code; make -f nocmake_makefiles/makefile` should build the _parafeed_ project. diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index b9f5721..f3441ed 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -49,6 +49,7 @@ target_include_directories(parafeed PUBLIC $) # install target set(header_list + parafeed.h clbool.h clconvert.h clError.h @@ -176,11 +177,11 @@ set(shccl_sources ParseCmdLine.cc clparseVal.cc InstallSymb.cc -# clgetSVal.cc + clgetSVal.cc # clgetNSVal.cc clgetFullVal.cc -# clgetValp.cc + clgetValp.cc clStartInteractive.cc clRestartShell.cc clfInteractive.cc diff --git a/code/ErrorObj.h b/code/ErrorObj.h index 76bbadb..67f3289 100644 --- a/code/ErrorObj.h +++ b/code/ErrorObj.h @@ -33,7 +33,7 @@ class ErrorObj: public std::exception{ // 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(), Message(),Level(l) {}; ErrorObj(const string &m, const string &i, int l): @@ -43,10 +43,12 @@ class ErrorObj: public std::exception{ ErrorObj(const ErrorObj& that); ~ErrorObj() {}; - + void SetSource(const char *m=0); + void SetMsg(const string& m) {Msg=m;} const char *Source() {return Src.c_str();} int Severity() {return Level;} + string GetMsg() {return Msg;}; const char *what(); ostream &operator<<(const std::string& m) {return cerr << m;} diff --git a/code/ParseCmdLine.cc b/code/ParseCmdLine.cc index 4805169..c5c94cf 100644 --- a/code/ParseCmdLine.cc +++ b/code/ParseCmdLine.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012, 2013 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) + * Copyright (c) 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 @@ -383,7 +383,7 @@ int startShell() { if (!cl_defaultsLoaded) /* Load the defaults */ { - loadDefaults(1); cl_defaultsLoaded=1; + loadDefaults(0); cl_defaultsLoaded=1; } if (doInp && !cl_NoPrompt) { diff --git a/code/SetVar.cc b/code/SetVar.cc index 71e9a85..684e0bd 100644 --- a/code/SetVar.cc +++ b/code/SetVar.cc @@ -87,7 +87,7 @@ int UnsetVar(Symbol *S, int setFactoryDefaults) if(pos==0) return -2; // if (pos->Exposed!=1) // { - // string msg="Attempted modification of a hidden variable (named \'" + string(pos->Name) + "\')."; + // string msg="Attempted modification of a hidden variable (named \'" + string(pos->Name) + "\')."; // //clThrowUp(msg.c_str(),"###Error",CL_INFORMATIONAL); // clError x(msg.c_str(),"###Error",CL_INFORMATIONAL); // throw(x); @@ -97,12 +97,12 @@ int UnsetVar(Symbol *S, int setFactoryDefaults) if (!Force) if (pos->Class == CL_USERCLASS) { - string msg="Attempted modification of a shell-constant (named \'" + string(pos->Name) + "\'). Ignored."; + string msg="Attempted modification of a shell-constant (named \'" + string(pos->Name) + "\'). Ignored."; clThrowUp(msg.c_str(),"###Error",CL_INFORMATIONAL); return -2; } - if ((val==NULL) || (strlen(val) == 0)) + if ((val==NULL) || (strlen(val) == 0)) { ret= UnsetVar(pos,1); } @@ -176,7 +176,7 @@ std::function noMatchExceptionLambda_ptr=noMatchException; newval=v; // if (S->Exposed!=1) // { - // string msg="Attempted modification of a hidden variable (named \'" + string(S->Name) + "\')."; + // string msg="Attempted modification of a hidden variable (named \'" + string(S->Name) + "\')."; // //clThrowUp(msg.c_str(),"###Error",CL_INFORMATIONAL); // clError x(msg.c_str(),"###Error",CL_INFORMATIONAL); // throw(x); @@ -242,7 +242,12 @@ void SetVal(const char *v, Symbol *S, int i) { // Same as cerr << x.what(), except that the output // stream is centrally specified in clError. - x << x << " at position " << i << endl; + std::stringstream msg; + + msg << x.GetMsg(); + if (i > 0) msg << " at position " << i; + //x << msg.str().c_str() << endl; + x.SetMsg(msg.str()); throw(x); } diff --git a/code/callbacks.cc b/code/callbacks.cc index ae99819..0e74080 100644 --- a/code/callbacks.cc +++ b/code/callbacks.cc @@ -487,6 +487,7 @@ int dosavefd(FILE *fd, const std::vector& opts) ifs.open(defFile.c_str()); + std::stringstream errorMessages; if (!ifs.good()) { clThrowUp(std::string("Error in opening file \"")+defFile+std::string("\""), "###Error", CL_FATAL); @@ -495,54 +496,72 @@ int dosavefd(FILE *fd, const std::vector& opts) else { Symbol *pos; - + uint lineNo=0; while(!ifs.eof()) { string line; - if (getline(ifs,line)) + try { - stripwhitep(line); - if ((line.size() > 0) && (line[0] != '#')) + if (getline(ifs,line)) { - // Separate the line into name and value strings - // separated by the first '=' char. Strip the - // white spaces. - std::string Name_str, Val_str; - BreakStrp(line,Name_str,Val_str); - stripwhitep(Name_str); - stripwhitep(Val_str); - - // Seperate the Name string into scope and Name - // string seperated by ':' - std::string Scope_str; - BreakStrp(Name_str, Scope_str, Name_str,"::"); - stripwhitep(Name_str); - stripwhitep(Scope_str); - if (Name_str == Scope_str) Scope_str=""; - - pos = NULL; - if ((Scope_str == "") || (Scope_str == ProgName())) + lineNo++; + stripwhitep(line); + if ((line.size() > 0) && (line[0] != '#')) { - if (Complement) - { - pos=SearchVSymbFullMatch(Name_str.c_str(), - cl_SymbTab); - if ((pos == (Symbol *)NULL)) - pos=AddVar(Name_str.c_str(),&cl_SymbTab, - &cl_TabTail); - if ((pos->NVals == 0)) - pos = (Symbol *)NULL; - } - if (pos==NULL) + // Separate the line into name and value strings + // separated by the first '=' char. Strip the + // white spaces. + std::string Name_str, Val_str; + BreakStrp(line,Name_str,Val_str); + stripwhitep(Name_str); + stripwhitep(Val_str); + + // Seperate the Name string into scope and Name + // string seperated by ':' + std::string Scope_str; + BreakStrp(Name_str, Scope_str, Name_str,"::"); + stripwhitep(Name_str); + stripwhitep(Scope_str); + if (Name_str == Scope_str) Scope_str=""; + + pos = NULL; + if ((Scope_str == "") || (Scope_str == ProgName())) { - if (doregister) - pos=AddVar(Name_str.c_str(),&cl_SymbTab,&cl_TabTail); - SetVar((char*)Name_str.c_str(),(char *)Val_str.c_str(), - cl_SymbTab,0,1,cl_do_doinp); + if (Complement) + { + pos=SearchVSymbFullMatch(Name_str.c_str(), + cl_SymbTab); + if ((pos == (Symbol *)NULL)) + pos=AddVar(Name_str.c_str(),&cl_SymbTab, + &cl_TabTail); + if ((pos->NVals == 0)) + pos = (Symbol *)NULL; + } + if (pos==NULL) + { + if (doregister) + pos=AddVar(Name_str.c_str(),&cl_SymbTab,&cl_TabTail); + SetVar((char*)Name_str.c_str(),(char *)Val_str.c_str(), + cl_SymbTab,0,1,cl_do_doinp); + } } } } } + catch(clError& x) + { + errorMessages + << "In " << defFile << ":" << lineNo << endl + << x + << endl << "-----------------------" << endl; + } + } + if (!errorMessages.str().empty()) + { + clExit x("","###Error",CL_INFORMATIONAL); + x.SetMsg(errorMessages.str()); + x << x << endl; + throw(x); } // Set all symbols loaded in the table to USERCLASS. The ones // that get queried (via clget*Val() functions) are converted diff --git a/code/cl.h b/code/cl.h index bba5608..3478ff7 100644 --- a/code/cl.h +++ b/code/cl.h @@ -56,7 +56,7 @@ { \ throw; \ } - + #else #define HANDLE_EXCEPTIONS(str) str @@ -73,9 +73,9 @@ extern "C" { #define CL_SEVERE -20 #define CL_FATAL -10 #define CL_WARNING -5 - /* + /* Define readline stuff as readline.h is - NOT ANSI C + NOT ANSI C */ #ifdef __cplusplus /* @@ -127,7 +127,7 @@ extern int add_history(char *); Symbol *IntallSymb(char *, char *, Symbol *); Symbol *SearchQSymb(const std::string& Name, const std::string& Type); Symbol *SearchVSymb(const char *Name, Symbol *Tab); - Symbol *AddQKey(const char *Name, const char *Type, + Symbol *AddQKey(const char *Name, const char *Type, Symbol **Head, Symbol **Tail); int ParseCmdLine(int, char **); std::vector clMakeArgvFromFile(const std::string& Name); @@ -151,8 +151,6 @@ int clgetIVal(char *Name, int *Val, int *N); int dbgclgetIVal(char *Name, int *Val, int *N); int clgetFVal(char *Name, float *Val, int *N); int dbgclgetFVal(char *Name, float *Val, int *N); -int clgetSVal(const char *Name, char *Val, int *N); -int dbgclgetSVal(const char *Name, char *Val, int *N); int clgetNIVal(char *Key, int *Val, int *m); int dbgclgetNIVal(char *Key, int *Val, int *m); int clgetNFVal(char *Name, float *Val, int *N); @@ -164,6 +162,9 @@ int dbgclgetBVal(char *Name, bool *Val, int *N); int clgetNBVal(char *Name, bool *Val, int *N); int dbgclgetNBVal(char *Name, bool *Val, int *N); +int clgetSVal(const char *Name, char *Val, int *N,SMap smap=SMap(),bool dbg=false); +inline int dbgclgetSVal(const char *Name, char *Val, int *N, SMap smap=SMap()) {return clgetSVal(Name,Val,N,smap,true);}; + #ifdef __cplusplus int clTgetOptp(const std::string& Name, std::string& Type); int clgetOptp(const std::string& Name); @@ -196,7 +197,7 @@ std::string stripwhitep (std::string& str); int redirect(char *, char *); void yyerror(char *); int clgetConfigFile(char *, char *); -int AddCmd(const char *Name, char *Doc, int (*func)(char *), +int AddCmd(const char *Name, char *Doc, int (*func)(char *), CmdSymbol **Head, CmdSymbol **Tail); int BreakStr(char *, char **, char **); int BreakStrp(const std::string& str, std::string& Name, std::string& Val, @@ -277,6 +278,7 @@ 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); +int clgetSValp(const std::string& Name, std::string& Val, int& N, SMap &smap,bool dbg); // //------------------------------------------------------------------------------------------------ // Wrappers for clgetValp(...,T& val,...) and clgetValp(...,vector&,...) diff --git a/code/clgetBaseCode.h b/code/clgetBaseCode.h index 700891e..2c18ee0 100644 --- a/code/clgetBaseCode.h +++ b/code/clgetBaseCode.h @@ -56,7 +56,7 @@ Symbol* clgetBaseCode(const string& Name, T& val, int& n, SMap &smap=SMap(), boo else S=SearchQSymb((char *)Name.c_str(),type_str); - if (S!=NULL) + if (S!=NULL) { // Use templated function that works for all values of T setAutoDefaults(S,val); @@ -74,7 +74,7 @@ Symbol* clgetBaseCode(const string& Name, T& val, int& n, SMap &smap=SMap(), boo }; // -// Templated functions for NVal calls. +// Templated functions for NVal calls. // template Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap &smap=SMap(), bool dbg=false) @@ -91,7 +91,7 @@ Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap HANDLE_EXCEPTIONS( S = SearchQSymb((char *)Name.c_str(), os.str()); - if (S!=NULL) + if (S!=NULL) { // Use templated function that works for all values of T setAutoDefaults(S,val); @@ -109,8 +109,6 @@ Symbol *clgetNValBaseCode(const string& Name, vector& val, int& m, const SMap } // //---------------------------------------------------------------------- -// This has the API-level templated functions that use the BaseCode -// functions above. -//#include +// #endif diff --git a/code/clgetFullVal.cc b/code/clgetFullVal.cc index c07976a..4a85389 100644 --- a/code/clgetFullVal.cc +++ b/code/clgetFullVal.cc @@ -17,11 +17,8 @@ * */ /* $Id: clgetFullVal.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ -#include -#include #include -#include -#include +#include #ifdef __cplusplus extern "C" { #endif @@ -94,7 +91,7 @@ Symbol* clgetFullValpBase(const string& Name, string& val, bool dbg) // Do not modify val if S->Val is empty. The // in-comming val may have a default value // that is not yet tranferred to S-Val. - if (S->NVals > 0) + if (S->NVals > 0) val = vecStr2Str(S->Val); } ); diff --git a/code/clgetSVal.cc b/code/clgetSVal.cc index bb3543f..3b4d342 100644 --- a/code/clgetSVal.cc +++ b/code/clgetSVal.cc @@ -17,65 +17,60 @@ * */ /* $Id: clgetSVal.c,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ -#include -#include -#include +#include #include -#include -#include -#include +//#include +//#include +//#include +//#include +//#include +//#include //#include -//#include #ifdef __cplusplus extern "C" { #endif - + /*------------------------------------------------------------------------ Return the Nth value of Name as a string ------------------------------------------------------------------------*/ -// int clgetSVal(const char *Name, char *val, int *n) -// { -// HANDLE_EXCEPTIONS( -// string valp; -// int r; -// if ((r = clgetSValp(std::string(Name), valp, *n))!= CL_FAIL) -// strncpy(val,valp.c_str(),valp.size()+1); -// return r; -// ); -// } +int clgetSVal(const char *Name, char *val, int *n, SMap smap, bool dbg) +{ + HANDLE_EXCEPTIONS( + string valp; + int r; + if ((r = clgetSValp(std::string(Name), valp, *n,smap,dbg))!= CL_FAIL) + strncpy(val,valp.c_str(),valp.size()+1); + return r; + ); +} #ifdef __cplusplus } #endif #ifdef __cplusplus -// int clgetSValp(const string &Name, string& val, int& n) -// { -// HANDLE_EXCEPTIONS( -// SMap emptyMap; -// return clgetSValp(Name, val, n, emptyMap); -// ); -// } -// int clgetSValp(const string& Name, string& val, int& n, SMap &smap) -// { -// Symbol *S; -// unsigned int N; +int clgetSValp(const string& Name, string& val, int& n, SMap &smap,bool dbg=false) +{ + Symbol *S; + unsigned int N; + +HANDLE_EXCEPTIONS( + S = clgetBaseCode(Name, val, n, smap,dbg); -// HANDLE_EXCEPTIONS( -// S = clgetBaseCode(Name, val, n, smap); -// N = _ABS(n); -// if (S!=NULL) -// { -// if (N <= S->NVals) -// { -// val = trim(S->Val[N-1]); -// return val.size(); -// } -// else -// return CL_FAIL; -// } -// else -// return CL_FAIL; -// ); -// } + N = _ABS(n); + if (S!=NULL) + { + if (N <= S->NVals) + { + val = trim(S->Val[N-1]); + // val = S->Val[N-1]; + return val.size(); + } + else + return CL_FAIL; + } + else + return CL_FAIL; + ); +} #endif diff --git a/code/clgetValp.cc b/code/clgetValp.cc index 3ad2ae8..078914a 100644 --- a/code/clgetValp.cc +++ b/code/clgetValp.cc @@ -64,6 +64,7 @@ int clgetValpVec(const std::string& Name, std::vector& val, int& m, const SMa HANDLE_EXCEPTIONS( S=clgetNValBaseCode(Name,val,m,smap,dbg); int n0=S->NVals; + if (n0==0) n0=S->DefaultVal.size(); int i=1; for(int j=0;j& val, int& n, SMap smap // These calls are used in other parts of parafeed code. This file // therefore needs to be compiled into the libparafeed library for // internal linking. -// +// template -inline int cldbggetValp(const std::string& Name, T& val, int& n) {return dbgclgetValp(Name,val,n);} - -inline int clgetFValp(const std::string& Name, float& val, int& n) {return clgetValp(Name,val,n);} -inline int clgetFValp(const std::string& Name, float& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} -inline int clgetNFValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} -inline int clgetNFValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} - -inline int clgetIValp(const std::string& Name, int &val, int &n) {return clgetValp(Name,val,n);} -inline int clgetIValp(const std::string& Name, int& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} -inline int clgetNIValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} -inline int clgetNIValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} - -inline int clgetBValp(const std::string& Name, bool& val, int &n) {return clgetValp(Name,val,n);} -inline int clgetBValp(const std::string& Name, bool& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} -inline int clgetNBValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} -inline int clgetNBValp(const std::string& Name, std::vector& val, int& n, SMap &smap){return clgetValp(Name,val,n,smap);} - -//inline int clgetSVal(const char *Name, char *val, int *n) {return clgetValp(std::string(Name), *val, *n);} -inline int clgetSValp(const std::string& Name, std::string& val, int &n) {return clgetValp(Name,val,n);} -inline int clgetSValp(const std::string& Name, std::string& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} -inline int clgetNSValp(const std::string& Name, std::vector& val, int& n) {return clgetValp(Name,val,n);} -inline int clgetNSValp(const std::string& Name, std::vector& val, int& n, SMap &smap) {return clgetValp(Name,val,n,smap);} -inline int clgetNSValp(const std::string& Name, std::vector& val, int& n, const SMap smap) {return clgetValp(Name,val,n,smap);} - -inline int cldbggetIValp(const std::string& Name, int& val, int& n) {return dbgclgetValp(Name,val,n);} -inline int cldbggetFValp(const std::string& Name, float& val, int& n) {return dbgclgetValp(Name,val,n);} -inline int cldbggetBValp(const std::string& Name, bool& val, int& n) {return dbgclgetValp(Name,val,n);} -inline int cldbggetSValp(const std::string& Name, std::string& val, int& n) {return dbgclgetValp(Name,val,n);} - -inline int cldbggetIValp(const std::string& Name, int& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} -inline int cldbggetFValp(const std::string& Name, float& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} -inline int cldbggetBValp(const std::string& Name, bool& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n, smap);} -inline int cldbggetSValp(const std::string& Name, std::string& val, int& n, SMap& smap) {return dbgclgetValp(Name,val,n,smap);} - -inline int cldbggetNIValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} -inline int cldbggetNFValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} -inline int cldbggetNBValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} -inline int cldbggetNSValp(const std::string& Key, std::vector& val, int& m) {return dbgclgetValp(Key, val, m);} - -inline int cldbggetNIValp(const std::string& Key, std::vector& val, int& m, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} -inline int cldbggetNFValp(const std::string& Key, std::vector& val, int& m, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} -inline int cldbggetNBValp(const std::string& Key, std::vector& val, int& m, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} -inline int cldbggetNSValp(const std::string& Key, std::vector& val, int& m, SMap& smap){return dbgclgetValp(Key, val, m,smap);} +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 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 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 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);} + +//inline int clgetSVal(const char *Name, char *val, int *n) {return clgetValp(std::string(Name), val, *n);} +int clgetSVal(const string& Name, char *Val, int *N, SMap smap=SMap()) {return clgetSVal(Name.c_str(),Val,N,smap,false);}; +int dbgclgetSVal(const string& Name, char *Val, int *N, SMap smap=SMap()) {return clgetSVal(Name.c_str(),Val,N,smap,true);}; + +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 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, SMap& smap) {return dbgclgetValp(Key, val, m,smap);} +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, SMap& smap){return dbgclgetValp(Key, val, m,smap);} #endif diff --git a/code/clgetValp.h b/code/clgetValp.h index e11c489..63c27d5 100644 --- a/code/clgetValp.h +++ b/code/clgetValp.h @@ -30,5 +30,5 @@ //---------------------------------------------------------------------- // Templated code and wrapper functions // -#include +//#include #endif diff --git a/code/clinteract.h b/code/clinteract.h index 07ba820..2b81431 100644 --- a/code/clinteract.h +++ b/code/clinteract.h @@ -17,7 +17,7 @@ * */ /* $Id: clinteract.h,v 2.0 1998/11/11 07:13:01 sanjay Exp $ */ -#include +//#include #ifdef __cplusplus extern "C" { #endif diff --git a/code/clparseVal.cc b/code/clparseVal.cc index d8b64fa..4cb45ce 100644 --- a/code/clparseVal.cc +++ b/code/clparseVal.cc @@ -20,10 +20,10 @@ #include #include #include -#include -#include #include -#include +//#include +//#include +//#include #ifdef __cplusplus extern "C" { #endif @@ -45,15 +45,15 @@ extern "C" { int clparseVal(Symbol *S, int *Which, string& val) { unsigned int N = _ABS(*Which); - - if (S!=NULL) + + if (S!=NULL) { - if (N <= S->NVals) + if (N <= S->NVals) { val = trim(S->Val[N-1]); return val.size(); } - else + else return CL_FAIL; } else diff --git a/code/clparseVal.h b/code/clparseVal.h index 4027758..5c7ab77 100644 --- a/code/clparseVal.h +++ b/code/clparseVal.h @@ -21,26 +21,34 @@ #define CLPARSEVAL_H #include -#include -#include -#include -#include -#include -#include -#include +//#include +//#include +//#include +//#include +//#include +//#include template int clparseVal(Symbol *S, int *Which, T &d) { unsigned int N = _ABS(*Which); + string val; HANDLE_EXCEPTIONS( if (S != NULL) { + // Transfer S-DefaultVal to S->Val if S->NVals == 0. Is this + // always the correct thing to do? + if (S->NVals == 0) + { + S->Val=S->DefaultVal; + S->NVals = S->Val.size(); + }; if (N > S->NVals) return 0; + if (ISSET(S->Attributes,CL_BOOLTYPE)) { int retVal; - string val(S->Val[N-1]); + val=S->Val[N-1]; if ((retVal=clIsTrue(val))==1) d=1; else if ((retVal=clIsFalse(val))==1) d=0; //*d = clIsTrue(val); diff --git a/code/clstring.cc b/code/clstring.cc index e03befc..233c4e9 100644 --- a/code/clstring.cc +++ b/code/clstring.cc @@ -43,7 +43,7 @@ int ntok(char *str, const char *sep,char esc) if (!STRING && str[i]==sep[0] && (str[i-1] != esc)) count++; } if (STRING && str[i]=='"' && str[i-1] != esc) STRING=0; - if (i>=N && STRING) + if (i>=N && STRING) { fprintf(stderr,"###Error: Missing \'\"\'\n"); return -1; @@ -51,13 +51,13 @@ int ntok(char *str, const char *sep,char esc) return count+1; } /*------------------------------------------------------------------------ - Given a null terminated string, this will write the string on the file - pointed to by fd. Special characters ',','"' and esc are escaped + Given a null terminated string, this will write the string on the file + pointed to by fd. Special characters ',','"' and esc are escaped using the char. esc. ------------------------------------------------------------------------*/ int tokenize(FILE *fd, char *str, const char *sep,char esc) { - while(*str) + while(*str) { //if (!strncmp(str,"/*",2)) // { @@ -89,10 +89,10 @@ char *clstrtok(char *str, const char *sep,char esc) if (!strncmp(&t[i],"/*",2)) { while(i < len) - if (!strncmp(&t[i++],"*/",2)) + if (!strncmp(&t[i++],"*/",2)) {i++;break;} } - if (!STRING && t[i] == esc) + if (!STRING && t[i] == esc) { int j=i+1; while (j<=len) {t[j-1]=t[j];j++;} @@ -101,7 +101,7 @@ char *clstrtok(char *str, const char *sep,char esc) else if (!STRING && t[i]==sep[0]) break; else { - if (t[i]=='"') + if (t[i]=='"') { int j=i+1; while (j<=len) {t[j-1]=t[j];j++;} @@ -116,28 +116,29 @@ char *clstrtok(char *str, const char *sep,char esc) if (prev >= len) return NULL; else t[i]='\0'; return &t[prev]; -} +} /*------------------------------------------------------------------------ Bunch of functions to remove whitespaces from a given string ------------------------------------------------------------------------*/ -const std::string WHITESPACE = " \n\r\t\f\v"; - -std::string ltrim(const std::string &s) -{ - size_t start = s.find_first_not_of(WHITESPACE); - return (start == std::string::npos) ? std::string("") : s.substr(start); -} - -std::string rtrim(const std::string &s) -{ - size_t end = s.find_last_not_of(WHITESPACE); - return (end == std::string::npos) ? std::string("") : s.substr(0, end + 1); -} - -std::string trim(const std::string &s) { - return rtrim(ltrim(s)); -} +// const std::string WHITESPACE = " \n\r\t\f\v"; + +// std::string ltrim(const std::string &s) +// { +// size_t start = s.find_first_not_of(WHITESPACE); +// return (start == std::string::npos) ? std::string("") : s.substr(start); +// } + +// std::string rtrim(const std::string &s) +// { +// size_t end = s.find_last_not_of(WHITESPACE); +// return (end == std::string::npos) ? std::string("") : s.substr(0, end + 1); +// } + +// std::string trim(const std::string &s) { +// string tt=rtrim(ltrim(s)); +// return tt; +// } #if defined(TESTBED) diff --git a/code/clstring.h b/code/clstring.h index 6c8e270..d8c89e6 100644 --- a/code/clstring.h +++ b/code/clstring.h @@ -32,8 +32,28 @@ extern "C" { #ifdef __cplusplus } #endif -std::string ltrim(const std::string &s); -std::string rtrim(const std::string &s); -std::string trim(const std::string &s); +// std::string ltrim(const std::string &s); +// std::string rtrim(const std::string &s); +// std::string trim(const std::string &s); + +const std::string CL_STRING_WHITESPACE = " \n\r\t\f\v"; + +inline std::string ltrim(const std::string &s) +{ + size_t start = s.find_first_not_of(CL_STRING_WHITESPACE); + return (start == std::string::npos) ? std::string("") : s.substr(start); +} + +inline std::string rtrim(const std::string &s) +{ + size_t end = s.find_last_not_of(CL_STRING_WHITESPACE); + return (end == std::string::npos) ? std::string("") : s.substr(0, end + 1); +} + +inline std::string trim(const std::string &s) { + string tt=rtrim(ltrim(s)); + return tt; +} + #endif diff --git a/code/parafeed.h b/code/parafeed.h new file mode 100644 index 0000000..49a9ee8 --- /dev/null +++ b/code/parafeed.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#if !defined(PARAFEED_H) +#define PARAFEED_H +#include +#include +#include +#include +//#include +//#include +#endif diff --git a/code/setAutoDefaults.h b/code/setAutoDefaults.h index 1362a27..5a346cd 100644 --- a/code/setAutoDefaults.h +++ b/code/setAutoDefaults.h @@ -38,7 +38,8 @@ void setAutoDefaults(Symbol *S, T const & val) { std::vector tmp; tmp.push_back(val); - setAutoDefaults(S, tmp); + // If S->Val.size() == 0, always set S->Val = S->DefaultVal; + setAutoDefaults(S, tmp,true); return; } /*---------------------------------------------------------------------------*/ @@ -59,7 +60,7 @@ void setAutoDefaults(Symbol *S, const vector& val,const bool def2val=false) S->DefaultVal[i] = os.str(); } } - + if (def2val) { if (S->Val.size() == 0) diff --git a/code/test/tst2.cc b/code/test/tst2.cc index 3cc09c8..ae1fa72 100644 --- a/code/test/tst2.cc +++ b/code/test/tst2.cc @@ -1,6 +1,4 @@ /* $Id: tst2.c,v 2.0 1998/11/11 07:13:02 sanjay Exp $ */ -#include -#include /* * Copyright (c) 2000-2021, 2022 S. Bhatnagar (bhatnagar dot sanjay at gmail dot com) * @@ -19,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include +#include #include /* Test program to test the embedded shell via the commandline library diff --git a/code/test/unittest/CMakeLists.txt b/code/test/unittest/CMakeLists.txt index b7fa92d..70f2f48 100644 --- a/code/test/unittest/CMakeLists.txt +++ b/code/test/unittest/CMakeLists.txt @@ -1,3 +1,19 @@ +# Copyright (c) 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + cmake_minimum_required(VERSION 3.14) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED OFF) diff --git a/code/test/unittest/ParafeedTest.h b/code/test/unittest/ParafeedTest.h index c2ebbae..14764f8 100644 --- a/code/test/unittest/ParafeedTest.h +++ b/code/test/unittest/ParafeedTest.h @@ -1,8 +1,23 @@ +/* + * Copyright (c) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include #include -#include -#include -#include -#include #include #include #include @@ -67,6 +82,148 @@ auto makeCanonicalArgs=[](std::string defFile=std::string(), // //-------------------------------------------------------------------- // +auto FactoryCanonicalTest=[]() +{ + int i; + // bool + bool b = false; + SMap watchPoints; + VString exposedKeys = {"bool1"}; + watchPoints["1"] = exposedKeys; + i = 1; + clgetValp("bool", b, i, watchPoints); + EXPECT_FALSE(b); + + // bool1 + bool b1 = true; + ClearMap(watchPoints); + exposedKeys = {"int"}; + watchPoints["0"] = exposedKeys; + i = 1; + clgetValp("bool1", b1, i, watchPoints); + EXPECT_TRUE(b1); + + // int + int intVal = 0; + ClearMap(watchPoints); + exposedKeys = {"float"}; + watchPoints["1"] = exposedKeys; + i = 1; + clgetValp("int", intVal, i, watchPoints); + EXPECT_EQ(intVal, 0); + + // dbgint + int dbgInt = 10; + i = 1; + cldbggetValp("dbgint", dbgInt, i); + EXPECT_EQ(dbgInt, 10); + + // float + float fVal = 10.96f; + i = 1; + clgetValp("float", fVal, i); + EXPECT_FLOAT_EQ(fVal, 10.96f); + + // oneint + int oneintVal = 3; + i = 1; + clgetValp("oneint", oneintVal, i); + EXPECT_EQ(oneintVal, 3); + + // string + std::string str; + ClearMap(watchPoints); + exposedKeys = {"strarr"}; + watchPoints["showstrarr"] = exposedKeys; + exposedKeys = {"fullval"}; + watchPoints["showfullval"] = exposedKeys; + str = "showstrarr"; + i = 1; + clgetValp("string", str, i, watchPoints); + EXPECT_EQ(str, "showstrarr"); + + // Test backward compatible API: [dbg]clgetSVal(...,[watchPoints]) + // ensuring that sstr goes out of scope after each call to + // clgetSVal(). + { + char sstr[100]; + clgetSVal("string", sstr, &i, watchPoints); + EXPECT_EQ(string("showstrarr"),sstr); + } + { + char sstr[100]; + clgetSVal("string", sstr, &i); + EXPECT_EQ(string("showstrarr"),sstr); + } + { + char sstr[100]; + dbgclgetSVal("string", sstr, &i,watchPoints); + EXPECT_EQ(string("showstrarr"),sstr); + } + { + char sstr[100]; + dbgclgetSVal("string", sstr, &i); + EXPECT_EQ(string("showstrarr"),sstr); + } + // Check for clgetSVal(string&, char *, int *, SMap) interface. + { + char sstr[100]; + clgetSVal(string("string"), sstr, &i, watchPoints); + EXPECT_EQ(string("showstrarr"),sstr); + } + { + char sstr[100]; + dbgclgetSVal(string("string"), sstr, &i); + EXPECT_EQ(string("showstrarr"),sstr); + } + + // fullval + std::string fullVal; + i = 0; + clgetFullValp("fullval", fullVal); + EXPECT_EQ(fullVal, ""); + + // dbgfullval + std::string dbgFullVal="This is dbg full val factory setting"; + i = 0; + dbgclgetFullValp("dbgfullval", dbgFullVal); + EXPECT_EQ(dbgFullVal, "This is dbg full val factory setting"); + + // strarr + VString strarr={"v1","v2"}; + i = 0; + clgetValp("strarr", strarr, i); + ASSERT_EQ(strarr.size(), 2u); + EXPECT_EQ(strarr[0], "v1"); + EXPECT_EQ(strarr[1], "v2"); + + // farray + int N = 0; + int count; + + // Test that the values returned after the "go" command are actually + // filled from internal symbol table. + + // Registeration Pass: fv is used for factory setting. + std::vector fv={3.14,2*3.14,3*3.14}; + if (cl_Pass == 0) + { + count = clgetValp("farray", fv, N); + } + else + { + // Get the values in a vector different from the vector used to + // set the defaults (fv) + std::vector fv0; + count = clgetValp("farray", fv0, N); + EXPECT_EQ(fv0,fv); + } + EXPECT_EQ(count, fv.size()); + EXPECT_EQ(count, N); +}; +// +//-------------------------------------------------------------------- +// auto canonicalTest=[]() { int i; @@ -128,16 +285,16 @@ auto canonicalTest=[]() clgetValp("string", str, i, watchPoints); EXPECT_EQ(str, "showstrarr"); - // { - // char sstr[100]; - // clgetSVal("string", sstr, &i, watchPoints); - // //EXPECT_EQ(sstr, "showstrarr");// DOES NOT WORK! - // EXPECT_EQ(sstr, str); - - // clgetSVal("string", sstr, &i); - // //EXPECT_EQ(sstr, "showstrarr");// DOES NOT WORK! - // EXPECT_EQ(sstr, str); - // } + { + char sstr[100]; + clgetSVal("string", sstr, &i, watchPoints); + //EXPECT_EQ(sstr, "showstrarr");// DOES NOT WORK! + EXPECT_EQ(sstr, str); + + clgetSVal("string", sstr, &i); + //EXPECT_EQ(sstr, "showstrarr");// DOES NOT WORK! + EXPECT_EQ(sstr, str); + } // fullval std::string fullVal; @@ -160,7 +317,7 @@ auto canonicalTest=[]() EXPECT_EQ(strarr[1], "val2"); // farray - std::vector fv(3); + std::vector fv; int N = 3; int count = clgetValp("farray", fv, N); EXPECT_EQ(count, 3); diff --git a/code/test/unittest/test_parafeed_interactive.cpp b/code/test/unittest/test_parafeed_interactive.cpp index 1c90b2c..67935fb 100644 --- a/code/test/unittest/test_parafeed_interactive.cpp +++ b/code/test/unittest/test_parafeed_interactive.cpp @@ -1,5 +1,66 @@ +/* + * Copyright (c) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ #include // +// Test for default factory settings (i.e., defaults in the compiled +// code). +TEST_F(ParafeedTest, InteractiveFactoryCanonical) +{ + // std::vector args=makeCanonicalArgs("","help=dbg"); + std::vector args={"test2","help=dbg"}; + auto [argc, argv] = MakeArgv(args); + sendCmd("go\n"); + BeginCL(argc, argv); + { + clInteractive(0); + + FactoryCanonicalTest(); + + // Get a pointer to the named symbol from the internal symbol + // table. + // + // The following keys should be of the CL_DBGCLASS class and + // CL_DBG_ON==true. In the interactive shell, these keys will be + // visible. + // + Symbol *S; + S=SearchVSymb("dbgint"); + EXPECT_EQ(CL_DBG_ON && S->Class==CL_DBGCLASS, true); + + S=SearchVSymb("dbgfullval"); + EXPECT_EQ(CL_DBG_ON && S->Class==CL_DBGCLASS, true); + + if (cl_Pass > 0) + { + // default settings are bool=false. That hides "int", which + // hides "float" + S=SearchVSymb("int"); + EXPECT_NE(S,nullptr); EXPECT_EQ(S->Exposed,0); + + S=SearchVSymb("float"); + EXPECT_NE(S,nullptr); EXPECT_EQ(S->Exposed,0); + } + } + EndCL(); + FreeArgv(argc, argv); +} +// // Test the canonical Args setting in the interactive mode. This has // "bool1=false int=42" setting. Check that bool1=false exposes // "int", and "int=42" keeps "float" hidden. @@ -41,6 +102,110 @@ TEST_F(ParafeedTest, InteractiveCanonical) EndCL(); FreeArgv(argc, argv); } +// +// Test the most standard way of running an application in the default +// mode. The test2.def file, with error, is written before starting +// the UI. EndCL() should throw clExit exception, which is reported, +// before it can start the interactive shell. +// +TEST_F(ParafeedTest, InteractiveDefFile) +{ + std::vector args = + { + "test2", + //"help=noprompt", + "bool=x", + "oneint=xy", + "string=showstrarr", + "strarr=foo,barrr", + "farray=1,3,4,5,6,7,8,9,10" + }; + + std::string defFile("test2.def"); + std::remove(defFile.c_str()); + makeDefFile(args,defFile); + + args={"test2"}; + + auto [argc, argv] = MakeArgv(args); + + // 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\n strarr=foo,bar\n oneint=100\n fullval=this is full val\n inp\n 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(N); + string fullVal="this is the default value"; + + 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); + + i=0;clgetFullValp("fullval",fullVal); + + try + { + if (cl_Pass == 0) + { + // Registraction pass should throw clExit() exception + cerr << "[INFO] parafeed Registeration pass..." << endl; + EXPECT_THROW(EndCL(),clExit); + } + else + { + // This should never be reached. + cerr << "[INFO] parafeed post-regsitration pass..." << endl; + EndCL(); + + // Expect the value as set interactively vis sendCmd() + EXPECT_EQ(oneint,100); + EXPECT_EQ(fullVal,"this is full val"); + } + } + catch(clExit& x) + { + x << x << endl; + } + + std::remove(defFile.c_str()); + FreeArgv(argc, argv); +} + + // //-------------------------------------------------------------------- // Test for incorrect values in argv. Here, oneint=x, instead of a diff --git a/code/test/unittest/test_parafeed_noninteractive.cpp b/code/test/unittest/test_parafeed_noninteractive.cpp index db39764..8f8a98d 100644 --- a/code/test/unittest/test_parafeed_noninteractive.cpp +++ b/code/test/unittest/test_parafeed_noninteractive.cpp @@ -1,3 +1,21 @@ +/* + * Copyright (c) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ #include // // --------------------------------------------------------------------------------- diff --git a/code/tstcpp.cc b/code/tstcpp.cc index 828fb80..cd5bc87 100644 --- a/code/tstcpp.cc +++ b/code/tstcpp.cc @@ -17,13 +17,10 @@ * */ /* $Id: tst2.c,v 2.0 1998/11/11 07:13:02 sanjay Exp $ */ -#include -#include -#include #include #include #include -//#include +#include /* Test program to test the embedded shell via the commandline library */