Skip to main content
deleted 26 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

Reverse Polish Notation Calculator in C++11notation calculator similar to dc on Unix/Linux systems using dynamic libraries

An Exampleexample of what I'm looking for:

This morning looking at other questions I found out about nullptr, I should have used nullptr rather than NULL in the constructor in RpnDLData.cpp.

This morning looking at other questions I found out about nullptr. I should have used nullptr rather than NULL in the constructor in RpnDLData.cpp.

I started using C++ in 1989, ten years before C++98 was implemented. I never learned C++98, C++03 or C++11 until now.

I started using C++ in 1989, ten years before C++98 was implemented. I never learned C++98, C++03 or C++11 until now.

To decrease the amount of code here in the question, I have not includedexcluded the objects that deal with I/O or the Operating System Interface (relies heavily on boost for portability (parsing command lines or environment variables)).

TstDbgCommon.hTstDbgCommon.h

TestBase.hTestBase.h

TestBase.cppTestBase.cpp

DebugBase.hDebugBase.h

DebugBase.cppDebugBase.cpp

DbgTstHandling.hDbgTstHandling.h

DbgTstHandling.cppDbgTstHandling.cpp

RpnDLData.hRpnDLData.h

RpnDLData.cppRpnDLData.cpp

RpnOpsTab.hRpnOpsTab.h

RpnOpsTab.cppRpnOpsTab.cpp

RpnCalc.hRpnCalc.h

Reverse Polish Notation Calculator in C++11 similar to dc on Unix/Linux systems using dynamic libraries

An Example of what I'm looking for:

This morning looking at other questions I found out about nullptr, I should have used nullptr rather than NULL in the constructor in RpnDLData.cpp.

I started using C++ in 1989, ten years before C++98 was implemented. I never learned C++98, C++03 or C++11 until now.

To decrease the amount of code here in the question I have not included the objects that deal with I/O or the Operating System Interface (relies heavily on boost for portability (parsing command lines or environment variables)).

TstDbgCommon.h

TestBase.h

TestBase.cpp

DebugBase.h

DebugBase.cpp

DbgTstHandling.h

DbgTstHandling.cpp

RpnDLData.h

RpnDLData.cpp

RpnOpsTab.h

RpnOpsTab.cpp

RpnCalc.h

Reverse Polish notation calculator similar to dc on Unix/Linux systems using dynamic libraries

An example of what I'm looking for:

This morning looking at other questions I found out about nullptr. I should have used nullptr rather than NULL in the constructor in RpnDLData.cpp.

I started using C++ in 1989, ten years before C++98 was implemented. I never learned C++98, C++03 or C++11 until now.

To decrease the amount of code here in the question, I have excluded the objects that deal with I/O or the Operating System Interface (relies heavily on boost for portability (parsing command lines or environment variables)).

TstDbgCommon.h

TestBase.h

TestBase.cpp

DebugBase.h

DebugBase.cpp

DbgTstHandling.h

DbgTstHandling.cpp

RpnDLData.h

RpnDLData.cpp

RpnOpsTab.h

RpnOpsTab.cpp

RpnCalc.h

Seperated RpnDLData.h from RpnDLData.cpp, added an example of what I'm looking for.
Source Link
pacmaninbw
  • 26.1k
  • 13
  • 47
  • 114

An Example of what I'm looking for:

This morning looking at other questions I found out about nullptr, I should have used nullptr rather than NULL in the constructor in RpnDLData.cpp.

I started using C++ in 1989, ten years before C++98 was implemented. I never learned C++98, C++03 or C++11 until now.

#ifndef RPNDLDATA_H_
#define RPNDLDATA_H_
#include <string>
using namespace std;
#include "plugins.h"
#include "DbgTstHandling.h"

using namespace std;
class RpnDLData : protected DebugAndTestHandling {
private:
    void *m_LibHandle;
    string *m_LibPath;
    OpTableEntry *m_Data;
    void m_OpenLibrary();
    void m_CloseLibrary();
    void m_FindRpnHubSymbol();
public:
    RpnDLData(string FullLibraryPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnDLData();
    inline const string *GetPath() { return m_LibPath; };
    inline int IsLibraryOpen() { return ((m_LibHandle) ? 1 : 0); };
    const OpTableEntry *GetOperationTableData();
    inline int IsRpnLibrary() { return (IsLibraryOpen() && m_Data); };
    void TestReportThisObject();
    void Test_ReportM_LibHandle();
    void Test_ReportM_LibPath();
    void Test_ReportM_Data();
    void Test_Reportm_IsOpen();
};

#endif /* RPNDLDATA_H_ */

RpnDLData.cpp

#include <iostream>
#include <dlfcn.h>
#include <string>
#include <typeinfo>
#include "RpnDLData.h"
using namespace std;
void RpnDLData::Test_Reportm_IsOpen()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_IsOpen: %d\n",
        IsLibraryOpen());
}
void RpnDLData::Test_ReportM_LibPath()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibPath %s\n",
        m_LibPath->c_str());
}
void RpnDLData::Test_ReportM_LibHandle()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibHandle 0x%x\n", m_LibHandle);
}
void RpnDLData::Test_ReportM_Data()
{
    if (m_Data)
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data = 0x%x\n", m_Data);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->FuncPtr = 0x%x\n",
            m_Data->FuncPtr);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->name = %s\n",
            m_Data->name);
    }
    else
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_data = NULL\n");
    }
}
void RpnDLData::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Dynamic Library Object Test Report\n");
    ObjectLevelDebuggingOrTesting("\tRpnDLData->TestLevel = %d\n",
        GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting("\tRpnDLData->DebugLevel = %d\n",
        GetObjectDebugLevel());
    Test_ReportM_LibPath();
    Test_Reportm_IsOpen();
    Test_ReportM_Data();
    Test_ReportM_LibHandle();
}
RpnDLData::RpnDLData(string FullLibraryPath, int ObjectDebugTestLevel)
    {
    m_LibPath = NULL;
    m_LibHandle = NULL;
    m_Data = NULL;
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    m_LibPath = new string(FullLibraryPath);
    m_OpenLibrary();
    m_FindRpnHubSymbol();
    TestReportThisObject();
}
RpnDLData::~RpnDLData()
    {
    m_CloseLibrary();
    delete m_LibPath;
}
void RpnDLData::m_CloseLibrary()
{
    if (m_LibHandle)
    {
        dlclose(m_LibHandle);
        m_LibHandle = 0;
    }
}
void RpnDLData::m_OpenLibrary()
{
    if (!IsLibraryOpen())
    {
        if (!(m_LibHandle = dlopen(m_LibPath->c_str(), (RTLD_NOW | RTLD_LOCAL))))
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
                "Can't open shared library %s\n", m_LibPath);
        }
    }
}
void RpnDLData::m_FindRpnHubSymbol()
{
    if (IsLibraryOpen())
    {
        if (m_Data)
        {
            return;
        }
        void *Found = NULL;
        dlerror();    // Clear any previous errors
        Found = dlsym(m_LibHandle, "rpnhub_plugin");
        if (Found)
        {
            OpTableEntry *TableEntry = static_cast<OpTableEntry *>(Found);
            if (!TableEntry)
            {
                m_CloseLibrary();
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "Symbol does not convert %s\n", m_LibPath);
            }
            else
            {
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "TableEntry = {%s,0x%x}\n", TableEntry->name,
                    TableEntry->FuncPtr);
            }
            m_Data = TableEntry;
        }
        else
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
               "Can't find symbol rpnhub_plugin %s\n", m_LibPath);
        }
    }
}
const OpTableEntry *RpnDLData::GetOperationTableData()
{
    if (!IsRpnLibrary())
    {
        m_OpenLibrary();
        m_FindRpnHubSymbol();
    }
    return m_Data;
}
#ifndef RPNDLDATA_H_
#define RPNDLDATA_H_
#include <string>
using namespace std;
#include "plugins.h"
#include "DbgTstHandling.h"

using namespace std;
class RpnDLData : protected DebugAndTestHandling {
private:
    void *m_LibHandle;
    string *m_LibPath;
    OpTableEntry *m_Data;
    void m_OpenLibrary();
    void m_CloseLibrary();
    void m_FindRpnHubSymbol();
public:
    RpnDLData(string FullLibraryPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnDLData();
    inline const string *GetPath() { return m_LibPath; };
    inline int IsLibraryOpen() { return ((m_LibHandle) ? 1 : 0); };
    const OpTableEntry *GetOperationTableData();
    inline int IsRpnLibrary() { return (IsLibraryOpen() && m_Data); };
    void TestReportThisObject();
    void Test_ReportM_LibHandle();
    void Test_ReportM_LibPath();
    void Test_ReportM_Data();
    void Test_Reportm_IsOpen();
};

#endif /* RPNDLDATA_H_ */
#include <iostream>
#include <dlfcn.h>
#include <string>
#include <typeinfo>
#include "RpnDLData.h"
using namespace std;
void RpnDLData::Test_Reportm_IsOpen()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_IsOpen: %d\n",
        IsLibraryOpen());
}
void RpnDLData::Test_ReportM_LibPath()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibPath %s\n",
        m_LibPath->c_str());
}
void RpnDLData::Test_ReportM_LibHandle()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibHandle 0x%x\n", m_LibHandle);
}
void RpnDLData::Test_ReportM_Data()
{
    if (m_Data)
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data = 0x%x\n", m_Data);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->FuncPtr = 0x%x\n",
            m_Data->FuncPtr);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->name = %s\n",
            m_Data->name);
    }
    else
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_data = NULL\n");
    }
}
void RpnDLData::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Dynamic Library Object Test Report\n");
    ObjectLevelDebuggingOrTesting("\tRpnDLData->TestLevel = %d\n",
        GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting("\tRpnDLData->DebugLevel = %d\n",
        GetObjectDebugLevel());
    Test_ReportM_LibPath();
    Test_Reportm_IsOpen();
    Test_ReportM_Data();
    Test_ReportM_LibHandle();
}
RpnDLData::RpnDLData(string FullLibraryPath, int ObjectDebugTestLevel)
    {
    m_LibPath = NULL;
    m_LibHandle = NULL;
    m_Data = NULL;
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    m_LibPath = new string(FullLibraryPath);
    m_OpenLibrary();
    m_FindRpnHubSymbol();
    TestReportThisObject();
}
RpnDLData::~RpnDLData()
    {
    m_CloseLibrary();
    delete m_LibPath;
}
void RpnDLData::m_CloseLibrary()
{
    if (m_LibHandle)
    {
        dlclose(m_LibHandle);
        m_LibHandle = 0;
    }
}
void RpnDLData::m_OpenLibrary()
{
    if (!IsLibraryOpen())
    {
        if (!(m_LibHandle = dlopen(m_LibPath->c_str(), (RTLD_NOW | RTLD_LOCAL))))
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
                "Can't open shared library %s\n", m_LibPath);
        }
    }
}
void RpnDLData::m_FindRpnHubSymbol()
{
    if (IsLibraryOpen())
    {
        if (m_Data)
        {
            return;
        }
        void *Found = NULL;
        dlerror();    // Clear any previous errors
        Found = dlsym(m_LibHandle, "rpnhub_plugin");
        if (Found)
        {
            OpTableEntry *TableEntry = static_cast<OpTableEntry *>(Found);
            if (!TableEntry)
            {
                m_CloseLibrary();
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "Symbol does not convert %s\n", m_LibPath);
            }
            else
            {
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "TableEntry = {%s,0x%x}\n", TableEntry->name,
                    TableEntry->FuncPtr);
            }
            m_Data = TableEntry;
        }
        else
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
               "Can't find symbol rpnhub_plugin %s\n", m_LibPath);
        }
    }
}
const OpTableEntry *RpnDLData::GetOperationTableData()
{
    if (!IsRpnLibrary())
    {
        m_OpenLibrary();
        m_FindRpnHubSymbol();
    }
    return m_Data;
}

An Example of what I'm looking for:

This morning looking at other questions I found out about nullptr, I should have used nullptr rather than NULL in the constructor in RpnDLData.cpp.

I started using C++ in 1989, ten years before C++98 was implemented. I never learned C++98, C++03 or C++11 until now.

#ifndef RPNDLDATA_H_
#define RPNDLDATA_H_
#include <string>
using namespace std;
#include "plugins.h"
#include "DbgTstHandling.h"

using namespace std;
class RpnDLData : protected DebugAndTestHandling {
private:
    void *m_LibHandle;
    string *m_LibPath;
    OpTableEntry *m_Data;
    void m_OpenLibrary();
    void m_CloseLibrary();
    void m_FindRpnHubSymbol();
public:
    RpnDLData(string FullLibraryPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnDLData();
    inline const string *GetPath() { return m_LibPath; };
    inline int IsLibraryOpen() { return ((m_LibHandle) ? 1 : 0); };
    const OpTableEntry *GetOperationTableData();
    inline int IsRpnLibrary() { return (IsLibraryOpen() && m_Data); };
    void TestReportThisObject();
    void Test_ReportM_LibHandle();
    void Test_ReportM_LibPath();
    void Test_ReportM_Data();
    void Test_Reportm_IsOpen();
};

#endif /* RPNDLDATA_H_ */

RpnDLData.cpp

#include <iostream>
#include <dlfcn.h>
#include <string>
#include <typeinfo>
#include "RpnDLData.h"
using namespace std;
void RpnDLData::Test_Reportm_IsOpen()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_IsOpen: %d\n",
        IsLibraryOpen());
}
void RpnDLData::Test_ReportM_LibPath()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibPath %s\n",
        m_LibPath->c_str());
}
void RpnDLData::Test_ReportM_LibHandle()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibHandle 0x%x\n", m_LibHandle);
}
void RpnDLData::Test_ReportM_Data()
{
    if (m_Data)
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data = 0x%x\n", m_Data);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->FuncPtr = 0x%x\n",
            m_Data->FuncPtr);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->name = %s\n",
            m_Data->name);
    }
    else
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_data = NULL\n");
    }
}
void RpnDLData::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Dynamic Library Object Test Report\n");
    ObjectLevelDebuggingOrTesting("\tRpnDLData->TestLevel = %d\n",
        GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting("\tRpnDLData->DebugLevel = %d\n",
        GetObjectDebugLevel());
    Test_ReportM_LibPath();
    Test_Reportm_IsOpen();
    Test_ReportM_Data();
    Test_ReportM_LibHandle();
}
RpnDLData::RpnDLData(string FullLibraryPath, int ObjectDebugTestLevel)
    {
    m_LibPath = NULL;
    m_LibHandle = NULL;
    m_Data = NULL;
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    m_LibPath = new string(FullLibraryPath);
    m_OpenLibrary();
    m_FindRpnHubSymbol();
    TestReportThisObject();
}
RpnDLData::~RpnDLData()
    {
    m_CloseLibrary();
    delete m_LibPath;
}
void RpnDLData::m_CloseLibrary()
{
    if (m_LibHandle)
    {
        dlclose(m_LibHandle);
        m_LibHandle = 0;
    }
}
void RpnDLData::m_OpenLibrary()
{
    if (!IsLibraryOpen())
    {
        if (!(m_LibHandle = dlopen(m_LibPath->c_str(), (RTLD_NOW | RTLD_LOCAL))))
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
                "Can't open shared library %s\n", m_LibPath);
        }
    }
}
void RpnDLData::m_FindRpnHubSymbol()
{
    if (IsLibraryOpen())
    {
        if (m_Data)
        {
            return;
        }
        void *Found = NULL;
        dlerror();    // Clear any previous errors
        Found = dlsym(m_LibHandle, "rpnhub_plugin");
        if (Found)
        {
            OpTableEntry *TableEntry = static_cast<OpTableEntry *>(Found);
            if (!TableEntry)
            {
                m_CloseLibrary();
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "Symbol does not convert %s\n", m_LibPath);
            }
            else
            {
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "TableEntry = {%s,0x%x}\n", TableEntry->name,
                    TableEntry->FuncPtr);
            }
            m_Data = TableEntry;
        }
        else
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
               "Can't find symbol rpnhub_plugin %s\n", m_LibPath);
        }
    }
}
const OpTableEntry *RpnDLData::GetOperationTableData()
{
    if (!IsRpnLibrary())
    {
        m_OpenLibrary();
        m_FindRpnHubSymbol();
    }
    return m_Data;
}
split files
Source Link
200_success
  • 145.6k
  • 22
  • 191
  • 481

#ifndef TSTDBGCOMMON_H_ #define TSTDBGCOMMON_H_

TstDbgCommon.h

#ifndef TSTDBGCOMMON_H_
#define TSTDBGCOMMON_H_

const unsigned int NODEBUGORTEST = 0;
const unsigned int NODEBUG = 0;
const unsigned int NOTEST = 0;
const unsigned int DEFAULTOBJECTTESTLEVEL = 1;
const unsigned int DEFAULTOBJECTDEBUGLEVEL = 0;
const unsigned int LEVEL1 = 1;
const unsigned int LEVEL2 = 2;
const unsigned int LEVEL3 = 3;
const unsigned int LEVEL4 = 4;
const unsigned int LEVEL5 = 5;
const unsigned int LEVEL6 = 6;
const unsigned int LEVEL7 = 7;
const unsigned int LEVEL8 = 8;
const unsigned int LEVEL9 = 9;
const unsigned int LEVEL10 = 10;
const unsigned int LEVEL11 = 11;
const unsigned int LEVEL12 = 12;
const unsigned int LEVEL13 = 13;
const unsigned int LEVEL14 = 14;
const unsigned int LEVEL15 = 15;
const unsigned int LEVEL16 = 16;
const unsigned int LEVEL17 = 17;
const unsigned int LEVEL18 = 18;
const unsigned int LEVEL19 = 19;
const unsigned int LEVEL20 = 20;

#endif /* TSTDBGCOMMON_H_ */

TestBase.h

#ifndef TESTBASE_H_
#define TESTBASE_H_

#include "TstDbgCommon.h"
using namespace std;
class TestBase
{
private:
    static unsigned int mA_Level;
    unsigned int mA_ObjectMinimumLevel;
    inline unsigned int mF_CheckLevelAgainstObjectLevel(unsigned int level)
    {
        return (mA_ObjectMinimumLevel < level);
    };
    inline unsigned int mF_CheckLevelAgainstProjectLevel(unsigned int level)
    {
        return (GetProjectTestLevel() > level);
    };
    inline unsigned int mF_CheckLevel(unsigned int level)
    {
        return (
            (mF_GetObjectLevel() < level) &&
            (level < GetProjectTestLevel())
        );
    };
protected:
    void mF_SetLevel(unsigned int Level)
    {
        this->mA_Level = Level;
    };
    inline unsigned int  mF_GetLevel()
    {
        return this->mA_Level;
    };
    inline void mF_SetObjectLevel(unsigned int Level)
    {
        this->mA_ObjectMinimumLevel = Level;
    };
    inline unsigned int  mF_GetObjectLevel()
    {
        return this->mA_ObjectMinimumLevel;
    };
    inline unsigned int mF_CheckTestLevel(unsigned int level)
    {
        return mF_CheckLevel(level);
    };
public:
    TestBase();
    virtual ~TestBase();
    inline void SetProjectTestLevel(unsigned int TestLevel)
    {
        mF_SetLevel(TestLevel);
    };
    inline unsigned int GetProjectTestLevel()
    {
        return mF_GetLevel();
    };
    inline void SetObjectTestLevel(unsigned int level)
    {
        mF_SetObjectLevel(level);
    };
    inline unsigned int GetObjectTestLevel()
    {
        return mF_GetObjectLevel();
    };
    inline unsigned int IsTesting()
    {
        return (
            (this->mA_Level) ?
                (
                    (this->mA_ObjectMinimumLevel) ?
                    (
                        this->mA_Level >= this->mA_ObjectMinimumLevel
                    )
                    : 0
                )
            : 0
        );
    };
    void ObjectLevelTesting(const char *OutputBuffer);
    virtual void ShowOnlyIfLevelGreaterThan(int forceLevel,
        const char* format, ...) = 0;
    virtual void TestReportThisObject() = 0;
};

#endif /* TESTBASE_H_ */

TestBase.cpp

#include "TestBase.h"
#include <iostream>
using namespace std;
unsigned int TestBase::mA_Level = NOTEST;
TestBase::TestBase() {
    mA_ObjectMinimumLevel = DEFAULTOBJECTTESTLEVEL;
}
TestBase::~TestBase() {
}

void TestBase::ObjectLevelTesting(const char *OutputBuffer)
{
    if (IsTesting())
    {
        cout << OutputBuffer;
    }
}

DebugBase.h

#ifndef DEBUGBASE_H_
#define DEBUGBASE_H_
#include "TstDbgCommon.h"
#include <functional>
using namespace std;
class DebugBase
{
private:
    static unsigned int mA_Level;
    unsigned int mA_ObjectMinimumLevel;
protected:
    inline void mF_SetProjectLevel(unsigned int Level)
    {
        this->mA_Level = Level;
    };
    inline unsigned int  mF_GetProjectLevel()
    {
        return this->mA_Level;
    };
    inline void  mF_SetObjectLevel(unsigned int level)
    {
        this->mA_ObjectMinimumLevel = level;
    };
    inline unsigned int  mF_GetObjectLevel()
    {
        return this->mA_ObjectMinimumLevel;
    };
    inline unsigned int mF_CheckLevelAgainstObjectLevel(unsigned int level)
    {
        return (mF_GetObjectLevel() < level);
    };
    inline unsigned int mF_CheckLevelAgainstProjectLevel(unsigned int level)
    {
        return (mF_GetProjectLevel() > level);
    };
    inline unsigned int mF_CheckLevel(unsigned int level)
    {
        return (
            (mF_GetObjectLevel() < level) &&
            (level < mF_GetProjectLevel())
        );
    };
public:
   DebugBase();
    virtual ~DebugBase();
    inline void SetProjectDebugLevel(unsigned int TestLevel)
    {
        mF_SetProjectLevel(TestLevel);
    };
    inline unsigned int GetProjectDebugLevel()
    {
        return mF_GetProjectLevel();
    };
    inline void SetObjectDebugLevel(unsigned int TestLevel)
    {
        mF_SetObjectLevel(TestLevel);
    };
    inline unsigned int GetObjectDebugLevel()
    {
        return mF_GetObjectLevel();
    };
    inline unsigned int IsDebugging()
    {
        return (
            (this->mA_Level) ?
            (
                (this->mA_ObjectMinimumLevel) ?
                (this->mA_Level >= this->mA_ObjectMinimumLevel)
                : 0)
            : 0
        );
    };
    void ObjectLevelDebugging(const char *OutputBuffer);
    virtual void ShowOnlyIfLevelGreaterThan(int forceLevel, const char* format, ...) = 0;
};
#endif /* DEBUGBASE_H_ */

 

DebugBase.cpp

#include "DebugBase.h"
#include <iostream>
using namespace std;
unsigned int DebugBase::mA_Level = 0;
DebugBase::DebugBase() {
    SetObjectDebugLevel(0);

}

DebugBase::~DebugBase() {
}

void DebugBase::ObjectLevelDebugging(const char *OutputBuffer)
{
    if (IsDebugging()) {
        cout << OutputBuffer;
    }
}

 

DbgTstHandling.h

#ifndef DBGTSTHANDLING_H_
#define DBGTSTHANDLING_H_
#include "TestBase.h"
#include "DebugBase.h"
#include <vector>
using namespace std;
class DebugAndTestHandling : protected TestBase, protected DebugBase
{
private:
    void mF_CommonDebugAndTestReporting(const char *Output);
    inline int mF_CheckLevelAgainstObjectLevels(unsigned int level)
    {
        return (
            ((TestBase::mF_GetObjectLevel() > level)) ||
            (DebugBase::mF_GetObjectLevel()> level)
        );
    };
    inline int mF_CheckLevelAgainstProjectDebug(unsigned int level)
    {
        return (GetProjectDebugLevel() > level);
    };
    inline int mF_CheckLevelAgainstProjectTest(unsigned int level)
    {
        return (GetProjectTestLevel() > level);
    };
    inline int mF_CheckLevelAgainstProjectLevels(unsigned int level)
    {
        return (
            (mF_CheckLevelAgainstProjectDebug(level)) ||
            (mF_CheckLevelAgainstProjectTest(level))
        );
    };
    inline int mF_CheckLevels(int level)
    {
        return (
            (TestBase::mF_CheckTestLevel(level)) ||
            (DebugBase::mF_CheckLevel(level))
        );
    };
protected:
    void ObjectLevelDebuggingOrTesting(const char *format, ...);
    void ShowOnlyIfLevelGreaterThan(int forceLevel, const char* format, ...);
    inline unsigned int IsTestingOrDebugging()
    {
        return ((IsTesting()) || (IsDebugging()));
    };
public:
    DebugAndTestHandling();
    virtual ~DebugAndTestHandling();
    inline void SetObjectMinimumDebugOrTestLevel(int level)
    {
        TestBase::SetObjectTestLevel(level);
        DebugBase::SetObjectDebugLevel(level);
    };
};

#endif /* DBGTSTHANDLING_H_ */

 

DbgTstHandling.cpp

#include "DbgTstHandling.h"
#include <iostream>
#include <cstdarg>
#include <ctype.h>
#include <string.h>
DebugAndTestHandling::DebugAndTestHandling()
{
    TestBase::SetObjectTestLevel(DEFAULTOBJECTTESTLEVEL);
    DebugBase::SetObjectDebugLevel(DEFAULTOBJECTDEBUGLEVEL);
}

DebugAndTestHandling::~DebugAndTestHandling()
{

}
void DebugAndTestHandling::mF_CommonDebugAndTestReporting(
        const char *OutputBuffer)
{
    if (IsDebugging())
    {
        ObjectLevelDebugging(OutputBuffer);
        return;
    }

    if (IsTesting())
    {
        ObjectLevelTesting(OutputBuffer);
        return;
    }
}
void DebugAndTestHandling::ObjectLevelDebuggingOrTesting(
        const char *format, ...)
{
    if (IsTestingOrDebugging())
    {
        char localBuffer[2028];
        va_list args;
        va_start(args, format);
        vsprintf(localBuffer, format, args);
        mF_CommonDebugAndTestReporting(localBuffer);
        va_end(args);
    }
}
void DebugAndTestHandling::ShowOnlyIfLevelGreaterThan(int forceLevel,
        const char *format, ...)
{
    if (mF_CheckLevels(forceLevel))
    {
        // Indent output by level
        for (int TabOutput = forceLevel; --TabOutput; )
    {
            cout << "\t";
        }
        char localBuffer[2028];
        va_list args;
        va_start(args, format);
        vsprintf(localBuffer, format, args);
        mF_CommonDebugAndTestReporting(localBuffer);
        va_end(args);
    }
}

 

RpnDLData.h

#ifndef RPNDLDATA_H_
#define RPNDLDATA_H_
#include <string>
using namespace std;
#include "plugins.h"
#include "DbgTstHandling.h"

using namespace std;
class RpnDLData : protected DebugAndTestHandling {
private:
    void *m_LibHandle;
    string *m_LibPath;
    OpTableEntry *m_Data;
    void m_OpenLibrary();
    void m_CloseLibrary();
    void m_FindRpnHubSymbol();
public:
    RpnDLData(string FullLibraryPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnDLData();
    inline const string *GetPath() { return m_LibPath; };
    inline int IsLibraryOpen() { return ((m_LibHandle) ? 1 : 0); };
    const OpTableEntry *GetOperationTableData();
    inline int IsRpnLibrary() { return (IsLibraryOpen() && m_Data); };
    void TestReportThisObject();
    void Test_ReportM_LibHandle();
    void Test_ReportM_LibPath();
    void Test_ReportM_Data();
    void Test_Reportm_IsOpen();
};

#endif /* RPNDLDATA_H_ */
#include <iostream>
#include <dlfcn.h>
#include <string>
#include <typeinfo>
#include "RpnDLData.h"
using namespace std;
void RpnDLData::Test_Reportm_IsOpen()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_IsOpen: %d\n",
        IsLibraryOpen());
}
void RpnDLData::Test_ReportM_LibPath()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibPath %s\n",
        m_LibPath->c_str());
}
void RpnDLData::Test_ReportM_LibHandle()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibHandle 0x%x\n", m_LibHandle);
}
void RpnDLData::Test_ReportM_Data()
{
    if (m_Data)
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data = 0x%x\n", m_Data);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->FuncPtr = 0x%x\n",
            m_Data->FuncPtr);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->name = %s\n",
            m_Data->name);
    }
    else
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_data = NULL\n");
    }
}
void RpnDLData::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Dynamic Library Object Test Report\n");
    ObjectLevelDebuggingOrTesting("\tRpnDLData->TestLevel = %d\n",
        GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting("\tRpnDLData->DebugLevel = %d\n",
        GetObjectDebugLevel());
    Test_ReportM_LibPath();
    Test_Reportm_IsOpen();
    Test_ReportM_Data();
    Test_ReportM_LibHandle();
}
RpnDLData::RpnDLData(string FullLibraryPath, int ObjectDebugTestLevel)
    {
    m_LibPath = NULL;
    m_LibHandle = NULL;
    m_Data = NULL;
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    m_LibPath = new string(FullLibraryPath);
    m_OpenLibrary();
    m_FindRpnHubSymbol();
    TestReportThisObject();
}
RpnDLData::~RpnDLData()
    {
    m_CloseLibrary();
    delete m_LibPath;
}
void RpnDLData::m_CloseLibrary()
{
    if (m_LibHandle)
    {
        dlclose(m_LibHandle);
        m_LibHandle = 0;
    }
}
void RpnDLData::m_OpenLibrary()
{
    if (!IsLibraryOpen())
    {
        if (!(m_LibHandle = dlopen(m_LibPath->c_str(), (RTLD_NOW | RTLD_LOCAL))))
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
                "Can't open shared library %s\n", m_LibPath);
        }
    }
}
void RpnDLData::m_FindRpnHubSymbol()
{
    if (IsLibraryOpen())
    {
        if (m_Data)
        {
            return;
        }
        void *Found = NULL;
        dlerror();    // Clear any previous errors
        Found = dlsym(m_LibHandle, "rpnhub_plugin");
        if (Found)
        {
            OpTableEntry *TableEntry = static_cast<OpTableEntry *>(Found);
            if (!TableEntry)
            {
                m_CloseLibrary();
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "Symbol does not convert %s\n", m_LibPath);
            }
            else
            {
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "TableEntry = {%s,0x%x}\n", TableEntry->name,
                    TableEntry->FuncPtr);
            }
            m_Data = TableEntry;
        }
        else
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
               "Can't find symbol rpnhub_plugin %s\n", m_LibPath);
        }
    }
}
const OpTableEntry *RpnDLData::GetOperationTableData()
{
    if (!IsRpnLibrary())
    {
        m_OpenLibrary();
        m_FindRpnHubSymbol();
    }
    return m_Data;
}

 

RpnOpsTab.h

#ifndef RPNOPSTAB_H_
#define RPNOPSTAB_H_
using namespace std;
#include <vector>
#include <stack>
#include <string>
#include <map>
#include "plugins.h"
#include "DbgTstHandling.h"
class RpnOperationsTable : protected DebugAndTestHandling {
private:
    string *m_SearchPath;
    map<string, const OpTableEntry *> m_Operations;
    vector<class RpnDLData *> m_OpenedLibraries;
    int m_FindAndAddPluginLibraries();
    int m_AddLibraryToTable(string Library);
    void m_CloseAllLibraries();

public:
    RpnOperationsTable(string *LibPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnOperationsTable();
    void ExecuteOperation(string InputToken, stack<double>& Operands);
    void TestReportThisObject();
};

#endif /* RPNOPSTAB_H_ */

 

RpnOpsTab.cpp

#include <stdexcept>
#include <cstdlib>
#include <error_code.hpp>
#include <range.hpp>
#include <filesystem.hpp>
#include "RpnDLData.h"
#include "RpnOpsTab.h"
using namespace std;
using namespace boost;
using namespace boost::system;
using namespace boost::filesystem;
using namespace boost::range;
RpnOperationsTable::RpnOperationsTable(string *PathSpec, int ObjectDebugTestLevel)
{
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    if (!PathSpec)
    {
        string Emsg = "In RpnOperationsTable Constructor: Drop in directory path not specified";
        throw runtime_error(Emsg);
    }
    m_SearchPath = new string(*PathSpec);
    ObjectLevelDebuggingOrTesting("Current Path = %s\n", m_SearchPath->c_str());

    if (!m_FindAndAddPluginLibraries())
    {
        string Emsg = "No plugin libraries found for rpn in the search directory ";
        Emsg.append(*m_SearchPath);
        throw runtime_error(Emsg);
    }
}
RpnOperationsTable::~RpnOperationsTable()
    {
    m_CloseAllLibraries();
    delete m_SearchPath;
}
void RpnOperationsTable::m_CloseAllLibraries()
{
    for (auto OpenSharedLib : m_OpenedLibraries)
    {
        RpnDLData *DLCloseData = OpenSharedLib;
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Closing shared Library: %s\n", DLCloseData->GetPath()->c_str());
        delete DLCloseData;
    }
}
int RpnOperationsTable::m_FindAndAddPluginLibraries()
{
    int Found = 0;
    path plugins_dir(*m_SearchPath);
    path SharedLibExtention(".so");        // Change to .dll on Microsoft Windows
    if ((exists(plugins_dir)) && (is_directory(plugins_dir)))
    {
        for(auto& File_Iter : make_iterator_range(directory_iterator(plugins_dir), {}))
        {
            path PathToCheck = File_Iter;
            ShowOnlyIfLevelGreaterThan(LEVEL2, "Found library: %s\n", PathToCheck.c_str());
            if ((!is_directory(File_Iter)) && (PathToCheck.extension() == SharedLibExtention))
            {
                if (m_AddLibraryToTable(PathToCheck.string()))
                {
                    Found++;
                }
            }
        }
    }
    else
    {
        string Emsg = "The search path : ";
        Emsg.append(*m_SearchPath);
        Emsg.append(" either doesn't exist or is not a directory");
        throw runtime_error(Emsg);
    }
    return Found;
}
int RpnOperationsTable::m_AddLibraryToTable(string Library)
{
    int Added = 0;
    ObjectLevelDebuggingOrTesting("Attempting to insert library %s\n", Library.c_str());

    RpnDLData *DLCloseData = new RpnDLData(Library, GetObjectDebugLevel());
    if (!DLCloseData->IsLibraryOpen())
    {
        ShowOnlyIfLevelGreaterThan(LEVEL3, "Can't open shared library : %s\n", Library.c_str());
        return Added;    // If errors occur then ignore this library
    }
    const OpTableEntry *TableEntry = DLCloseData->GetOperationTableData();
    if (!TableEntry)
    {
        delete DLCloseData;
        ShowOnlyIfLevelGreaterThan(LEVEL3, "Can't find symbol rpnhub_plugin in  : %s\n", Library.c_str());
    }
    else
    {
        m_OpenedLibraries.push_back(DLCloseData);
        m_Operations[TableEntry->name] = TableEntry;
        Added++;
    }

    return Added;
}
void RpnOperationsTable::ExecuteOperation(string InputToken, stack<double>& Operands)
{
    OpTableEntry const *TableEntry = m_Operations[InputToken];
    if (TableEntry)
    {
        TableEntry->FuncPtr(Operands);
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Performed : %s\n", InputToken.c_str());
    }
    else
    {
        char Operator[32];
        strncpy(Operator, InputToken.c_str(), 32);
        Operands.push(atof(Operator));
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Added %s to Operands\n",
            InputToken.c_str());
    }
}
void RpnOperationsTable::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Operations Table Object Test Report\n");
    ObjectLevelDebuggingOrTesting(
        "\tRpnOpsTable->TestLevel = %d\n", GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting(
        "\tRpnOpsTable->DebugLevel = %d\n", GetObjectDebugLevel());
    ObjectLevelDebuggingOrTesting(
        "\tCurrent Path : %s\n", m_SearchPath->c_str());
    ObjectLevelDebuggingOrTesting(
        "\t%d Operations were added to the Operations Table\n",
        static_cast<int> (m_Operations.size()));

    for (auto& kv : m_Operations)
    {
        ObjectLevelDebuggingOrTesting("\t\tKey '%s' 0x%x\n",
            kv.first.c_str(), kv.second);
    }
}

 

RpnCalc.h

#ifndef RPNCALC_H_
#define RPNCALC_H_
#include "DbgTstHandling.h"
using namespace std;
class RpnCalculator : protected DebugAndTestHandling
{
private:
    class RpnOperationsTable *m_OpsTable;
    class RpnCalculatorIOSystem *m_IOSystem;
protected:
    inline int Test_DoesOperationsTableExist() {
        return ((m_OpsTable) ? 1 : 0);
    };
    inline int Test_DoesIOSystemExist() {
        return ((m_IOSystem) ? 1 : 0);
    };
    virtual void CalCulatorRunLoop();
public:
    RpnCalculator(int argc, char const * const argv[],
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnCalculator();
    virtual void RunUntilQuit();
    inline int Test_InternalTestsPassed() {
        return (
            Test_DoesOperationsTableExist() &&
            Test_DoesIOSystemExist()
        );
    };
    void TestReportThisObject();
};

#endif /* RPNCALC_H_ */

#ifndef TSTDBGCOMMON_H_ #define TSTDBGCOMMON_H_

const unsigned int NODEBUGORTEST = 0;
const unsigned int NODEBUG = 0;
const unsigned int NOTEST = 0;
const unsigned int DEFAULTOBJECTTESTLEVEL = 1;
const unsigned int DEFAULTOBJECTDEBUGLEVEL = 0;
const unsigned int LEVEL1 = 1;
const unsigned int LEVEL2 = 2;
const unsigned int LEVEL3 = 3;
const unsigned int LEVEL4 = 4;
const unsigned int LEVEL5 = 5;
const unsigned int LEVEL6 = 6;
const unsigned int LEVEL7 = 7;
const unsigned int LEVEL8 = 8;
const unsigned int LEVEL9 = 9;
const unsigned int LEVEL10 = 10;
const unsigned int LEVEL11 = 11;
const unsigned int LEVEL12 = 12;
const unsigned int LEVEL13 = 13;
const unsigned int LEVEL14 = 14;
const unsigned int LEVEL15 = 15;
const unsigned int LEVEL16 = 16;
const unsigned int LEVEL17 = 17;
const unsigned int LEVEL18 = 18;
const unsigned int LEVEL19 = 19;
const unsigned int LEVEL20 = 20;

#endif /* TSTDBGCOMMON_H_ */
#ifndef TESTBASE_H_
#define TESTBASE_H_

#include "TstDbgCommon.h"
using namespace std;
class TestBase
{
private:
    static unsigned int mA_Level;
    unsigned int mA_ObjectMinimumLevel;
    inline unsigned int mF_CheckLevelAgainstObjectLevel(unsigned int level)
    {
        return (mA_ObjectMinimumLevel < level);
    };
    inline unsigned int mF_CheckLevelAgainstProjectLevel(unsigned int level)
    {
        return (GetProjectTestLevel() > level);
    };
    inline unsigned int mF_CheckLevel(unsigned int level)
    {
        return (
            (mF_GetObjectLevel() < level) &&
            (level < GetProjectTestLevel())
        );
    };
protected:
    void mF_SetLevel(unsigned int Level)
    {
        this->mA_Level = Level;
    };
    inline unsigned int  mF_GetLevel()
    {
        return this->mA_Level;
    };
    inline void mF_SetObjectLevel(unsigned int Level)
    {
        this->mA_ObjectMinimumLevel = Level;
    };
    inline unsigned int  mF_GetObjectLevel()
    {
        return this->mA_ObjectMinimumLevel;
    };
    inline unsigned int mF_CheckTestLevel(unsigned int level)
    {
        return mF_CheckLevel(level);
    };
public:
    TestBase();
    virtual ~TestBase();
    inline void SetProjectTestLevel(unsigned int TestLevel)
    {
        mF_SetLevel(TestLevel);
    };
    inline unsigned int GetProjectTestLevel()
    {
        return mF_GetLevel();
    };
    inline void SetObjectTestLevel(unsigned int level)
    {
        mF_SetObjectLevel(level);
    };
    inline unsigned int GetObjectTestLevel()
    {
        return mF_GetObjectLevel();
    };
    inline unsigned int IsTesting()
    {
        return (
            (this->mA_Level) ?
                (
                    (this->mA_ObjectMinimumLevel) ?
                    (
                        this->mA_Level >= this->mA_ObjectMinimumLevel
                    )
                    : 0
                )
            : 0
        );
    };
    void ObjectLevelTesting(const char *OutputBuffer);
    virtual void ShowOnlyIfLevelGreaterThan(int forceLevel,
        const char* format, ...) = 0;
    virtual void TestReportThisObject() = 0;
};

#endif /* TESTBASE_H_ */
#include "TestBase.h"
#include <iostream>
using namespace std;
unsigned int TestBase::mA_Level = NOTEST;
TestBase::TestBase() {
    mA_ObjectMinimumLevel = DEFAULTOBJECTTESTLEVEL;
}
TestBase::~TestBase() {
}

void TestBase::ObjectLevelTesting(const char *OutputBuffer)
{
    if (IsTesting())
    {
        cout << OutputBuffer;
    }
}
#ifndef DEBUGBASE_H_
#define DEBUGBASE_H_
#include "TstDbgCommon.h"
#include <functional>
using namespace std;
class DebugBase
{
private:
    static unsigned int mA_Level;
    unsigned int mA_ObjectMinimumLevel;
protected:
    inline void mF_SetProjectLevel(unsigned int Level)
    {
        this->mA_Level = Level;
    };
    inline unsigned int  mF_GetProjectLevel()
    {
        return this->mA_Level;
    };
    inline void  mF_SetObjectLevel(unsigned int level)
    {
        this->mA_ObjectMinimumLevel = level;
    };
    inline unsigned int  mF_GetObjectLevel()
    {
        return this->mA_ObjectMinimumLevel;
    };
    inline unsigned int mF_CheckLevelAgainstObjectLevel(unsigned int level)
    {
        return (mF_GetObjectLevel() < level);
    };
    inline unsigned int mF_CheckLevelAgainstProjectLevel(unsigned int level)
    {
        return (mF_GetProjectLevel() > level);
    };
    inline unsigned int mF_CheckLevel(unsigned int level)
    {
        return (
            (mF_GetObjectLevel() < level) &&
            (level < mF_GetProjectLevel())
        );
    };
public:
   DebugBase();
    virtual ~DebugBase();
    inline void SetProjectDebugLevel(unsigned int TestLevel)
    {
        mF_SetProjectLevel(TestLevel);
    };
    inline unsigned int GetProjectDebugLevel()
    {
        return mF_GetProjectLevel();
    };
    inline void SetObjectDebugLevel(unsigned int TestLevel)
    {
        mF_SetObjectLevel(TestLevel);
    };
    inline unsigned int GetObjectDebugLevel()
    {
        return mF_GetObjectLevel();
    };
    inline unsigned int IsDebugging()
    {
        return (
            (this->mA_Level) ?
            (
                (this->mA_ObjectMinimumLevel) ?
                (this->mA_Level >= this->mA_ObjectMinimumLevel)
                : 0)
            : 0
        );
    };
    void ObjectLevelDebugging(const char *OutputBuffer);
    virtual void ShowOnlyIfLevelGreaterThan(int forceLevel, const char* format, ...) = 0;
};
#endif /* DEBUGBASE_H_ */

 #include "DebugBase.h"
#include <iostream>
using namespace std;
unsigned int DebugBase::mA_Level = 0;
DebugBase::DebugBase() {
    SetObjectDebugLevel(0);

}

DebugBase::~DebugBase() {
}

void DebugBase::ObjectLevelDebugging(const char *OutputBuffer)
{
    if (IsDebugging()) {
        cout << OutputBuffer;
    }
}

 #ifndef DBGTSTHANDLING_H_
#define DBGTSTHANDLING_H_
#include "TestBase.h"
#include "DebugBase.h"
#include <vector>
using namespace std;
class DebugAndTestHandling : protected TestBase, protected DebugBase
{
private:
    void mF_CommonDebugAndTestReporting(const char *Output);
    inline int mF_CheckLevelAgainstObjectLevels(unsigned int level)
    {
        return (
            ((TestBase::mF_GetObjectLevel() > level)) ||
            (DebugBase::mF_GetObjectLevel()> level)
        );
    };
    inline int mF_CheckLevelAgainstProjectDebug(unsigned int level)
    {
        return (GetProjectDebugLevel() > level);
    };
    inline int mF_CheckLevelAgainstProjectTest(unsigned int level)
    {
        return (GetProjectTestLevel() > level);
    };
    inline int mF_CheckLevelAgainstProjectLevels(unsigned int level)
    {
        return (
            (mF_CheckLevelAgainstProjectDebug(level)) ||
            (mF_CheckLevelAgainstProjectTest(level))
        );
    };
    inline int mF_CheckLevels(int level)
    {
        return (
            (TestBase::mF_CheckTestLevel(level)) ||
            (DebugBase::mF_CheckLevel(level))
        );
    };
protected:
    void ObjectLevelDebuggingOrTesting(const char *format, ...);
    void ShowOnlyIfLevelGreaterThan(int forceLevel, const char* format, ...);
    inline unsigned int IsTestingOrDebugging()
    {
        return ((IsTesting()) || (IsDebugging()));
    };
public:
    DebugAndTestHandling();
    virtual ~DebugAndTestHandling();
    inline void SetObjectMinimumDebugOrTestLevel(int level)
    {
        TestBase::SetObjectTestLevel(level);
        DebugBase::SetObjectDebugLevel(level);
    };
};

#endif /* DBGTSTHANDLING_H_ */

 #include "DbgTstHandling.h"
#include <iostream>
#include <cstdarg>
#include <ctype.h>
#include <string.h>
DebugAndTestHandling::DebugAndTestHandling()
{
    TestBase::SetObjectTestLevel(DEFAULTOBJECTTESTLEVEL);
    DebugBase::SetObjectDebugLevel(DEFAULTOBJECTDEBUGLEVEL);
}

DebugAndTestHandling::~DebugAndTestHandling()
{

}
void DebugAndTestHandling::mF_CommonDebugAndTestReporting(
        const char *OutputBuffer)
{
    if (IsDebugging())
    {
        ObjectLevelDebugging(OutputBuffer);
        return;
    }

    if (IsTesting())
    {
        ObjectLevelTesting(OutputBuffer);
        return;
    }
}
void DebugAndTestHandling::ObjectLevelDebuggingOrTesting(
        const char *format, ...)
{
    if (IsTestingOrDebugging())
    {
        char localBuffer[2028];
        va_list args;
        va_start(args, format);
        vsprintf(localBuffer, format, args);
        mF_CommonDebugAndTestReporting(localBuffer);
        va_end(args);
    }
}
void DebugAndTestHandling::ShowOnlyIfLevelGreaterThan(int forceLevel,
        const char *format, ...)
{
    if (mF_CheckLevels(forceLevel))
    {
        // Indent output by level
        for (int TabOutput = forceLevel; --TabOutput; )
    {
            cout << "\t";
        }
        char localBuffer[2028];
        va_list args;
        va_start(args, format);
        vsprintf(localBuffer, format, args);
        mF_CommonDebugAndTestReporting(localBuffer);
        va_end(args);
    }
}

 #ifndef RPNDLDATA_H_
#define RPNDLDATA_H_
#include <string>
using namespace std;
#include "plugins.h"
#include "DbgTstHandling.h"

using namespace std;
class RpnDLData : protected DebugAndTestHandling {
private:
    void *m_LibHandle;
    string *m_LibPath;
    OpTableEntry *m_Data;
    void m_OpenLibrary();
    void m_CloseLibrary();
    void m_FindRpnHubSymbol();
public:
    RpnDLData(string FullLibraryPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnDLData();
    inline const string *GetPath() { return m_LibPath; };
    inline int IsLibraryOpen() { return ((m_LibHandle) ? 1 : 0); };
    const OpTableEntry *GetOperationTableData();
    inline int IsRpnLibrary() { return (IsLibraryOpen() && m_Data); };
    void TestReportThisObject();
    void Test_ReportM_LibHandle();
    void Test_ReportM_LibPath();
    void Test_ReportM_Data();
    void Test_Reportm_IsOpen();
};

#endif /* RPNDLDATA_H_ */
#include <iostream>
#include <dlfcn.h>
#include <string>
#include <typeinfo>
#include "RpnDLData.h"
using namespace std;
void RpnDLData::Test_Reportm_IsOpen()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_IsOpen: %d\n",
        IsLibraryOpen());
}
void RpnDLData::Test_ReportM_LibPath()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibPath %s\n",
        m_LibPath->c_str());
}
void RpnDLData::Test_ReportM_LibHandle()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibHandle 0x%x\n", m_LibHandle);
}
void RpnDLData::Test_ReportM_Data()
{
    if (m_Data)
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data = 0x%x\n", m_Data);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->FuncPtr = 0x%x\n",
            m_Data->FuncPtr);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->name = %s\n",
            m_Data->name);
    }
    else
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_data = NULL\n");
    }
}
void RpnDLData::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Dynamic Library Object Test Report\n");
    ObjectLevelDebuggingOrTesting("\tRpnDLData->TestLevel = %d\n",
        GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting("\tRpnDLData->DebugLevel = %d\n",
        GetObjectDebugLevel());
    Test_ReportM_LibPath();
    Test_Reportm_IsOpen();
    Test_ReportM_Data();
    Test_ReportM_LibHandle();
}
RpnDLData::RpnDLData(string FullLibraryPath, int ObjectDebugTestLevel)
    {
    m_LibPath = NULL;
    m_LibHandle = NULL;
    m_Data = NULL;
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    m_LibPath = new string(FullLibraryPath);
    m_OpenLibrary();
    m_FindRpnHubSymbol();
    TestReportThisObject();
}
RpnDLData::~RpnDLData()
    {
    m_CloseLibrary();
    delete m_LibPath;
}
void RpnDLData::m_CloseLibrary()
{
    if (m_LibHandle)
    {
        dlclose(m_LibHandle);
        m_LibHandle = 0;
    }
}
void RpnDLData::m_OpenLibrary()
{
    if (!IsLibraryOpen())
    {
        if (!(m_LibHandle = dlopen(m_LibPath->c_str(), (RTLD_NOW | RTLD_LOCAL))))
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
                "Can't open shared library %s\n", m_LibPath);
        }
    }
}
void RpnDLData::m_FindRpnHubSymbol()
{
    if (IsLibraryOpen())
    {
        if (m_Data)
        {
            return;
        }
        void *Found = NULL;
        dlerror();    // Clear any previous errors
        Found = dlsym(m_LibHandle, "rpnhub_plugin");
        if (Found)
        {
            OpTableEntry *TableEntry = static_cast<OpTableEntry *>(Found);
            if (!TableEntry)
            {
                m_CloseLibrary();
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "Symbol does not convert %s\n", m_LibPath);
            }
            else
            {
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "TableEntry = {%s,0x%x}\n", TableEntry->name,
                    TableEntry->FuncPtr);
            }
            m_Data = TableEntry;
        }
        else
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
               "Can't find symbol rpnhub_plugin %s\n", m_LibPath);
        }
    }
}
const OpTableEntry *RpnDLData::GetOperationTableData()
{
    if (!IsRpnLibrary())
    {
        m_OpenLibrary();
        m_FindRpnHubSymbol();
    }
    return m_Data;
}

 #ifndef RPNOPSTAB_H_
#define RPNOPSTAB_H_
using namespace std;
#include <vector>
#include <stack>
#include <string>
#include <map>
#include "plugins.h"
#include "DbgTstHandling.h"
class RpnOperationsTable : protected DebugAndTestHandling {
private:
    string *m_SearchPath;
    map<string, const OpTableEntry *> m_Operations;
    vector<class RpnDLData *> m_OpenedLibraries;
    int m_FindAndAddPluginLibraries();
    int m_AddLibraryToTable(string Library);
    void m_CloseAllLibraries();

public:
    RpnOperationsTable(string *LibPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnOperationsTable();
    void ExecuteOperation(string InputToken, stack<double>& Operands);
    void TestReportThisObject();
};

#endif /* RPNOPSTAB_H_ */

 #include <stdexcept>
#include <cstdlib>
#include <error_code.hpp>
#include <range.hpp>
#include <filesystem.hpp>
#include "RpnDLData.h"
#include "RpnOpsTab.h"
using namespace std;
using namespace boost;
using namespace boost::system;
using namespace boost::filesystem;
using namespace boost::range;
RpnOperationsTable::RpnOperationsTable(string *PathSpec, int ObjectDebugTestLevel)
{
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    if (!PathSpec)
    {
        string Emsg = "In RpnOperationsTable Constructor: Drop in directory path not specified";
        throw runtime_error(Emsg);
    }
    m_SearchPath = new string(*PathSpec);
    ObjectLevelDebuggingOrTesting("Current Path = %s\n", m_SearchPath->c_str());

    if (!m_FindAndAddPluginLibraries())
    {
        string Emsg = "No plugin libraries found for rpn in the search directory ";
        Emsg.append(*m_SearchPath);
        throw runtime_error(Emsg);
    }
}
RpnOperationsTable::~RpnOperationsTable()
    {
    m_CloseAllLibraries();
    delete m_SearchPath;
}
void RpnOperationsTable::m_CloseAllLibraries()
{
    for (auto OpenSharedLib : m_OpenedLibraries)
    {
        RpnDLData *DLCloseData = OpenSharedLib;
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Closing shared Library: %s\n", DLCloseData->GetPath()->c_str());
        delete DLCloseData;
    }
}
int RpnOperationsTable::m_FindAndAddPluginLibraries()
{
    int Found = 0;
    path plugins_dir(*m_SearchPath);
    path SharedLibExtention(".so");        // Change to .dll on Microsoft Windows
    if ((exists(plugins_dir)) && (is_directory(plugins_dir)))
    {
        for(auto& File_Iter : make_iterator_range(directory_iterator(plugins_dir), {}))
        {
            path PathToCheck = File_Iter;
            ShowOnlyIfLevelGreaterThan(LEVEL2, "Found library: %s\n", PathToCheck.c_str());
            if ((!is_directory(File_Iter)) && (PathToCheck.extension() == SharedLibExtention))
            {
                if (m_AddLibraryToTable(PathToCheck.string()))
                {
                    Found++;
                }
            }
        }
    }
    else
    {
        string Emsg = "The search path : ";
        Emsg.append(*m_SearchPath);
        Emsg.append(" either doesn't exist or is not a directory");
        throw runtime_error(Emsg);
    }
    return Found;
}
int RpnOperationsTable::m_AddLibraryToTable(string Library)
{
    int Added = 0;
    ObjectLevelDebuggingOrTesting("Attempting to insert library %s\n", Library.c_str());

    RpnDLData *DLCloseData = new RpnDLData(Library, GetObjectDebugLevel());
    if (!DLCloseData->IsLibraryOpen())
    {
        ShowOnlyIfLevelGreaterThan(LEVEL3, "Can't open shared library : %s\n", Library.c_str());
        return Added;    // If errors occur then ignore this library
    }
    const OpTableEntry *TableEntry = DLCloseData->GetOperationTableData();
    if (!TableEntry)
    {
        delete DLCloseData;
        ShowOnlyIfLevelGreaterThan(LEVEL3, "Can't find symbol rpnhub_plugin in  : %s\n", Library.c_str());
    }
    else
    {
        m_OpenedLibraries.push_back(DLCloseData);
        m_Operations[TableEntry->name] = TableEntry;
        Added++;
    }

    return Added;
}
void RpnOperationsTable::ExecuteOperation(string InputToken, stack<double>& Operands)
{
    OpTableEntry const *TableEntry = m_Operations[InputToken];
    if (TableEntry)
    {
        TableEntry->FuncPtr(Operands);
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Performed : %s\n", InputToken.c_str());
    }
    else
    {
        char Operator[32];
        strncpy(Operator, InputToken.c_str(), 32);
        Operands.push(atof(Operator));
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Added %s to Operands\n",
            InputToken.c_str());
    }
}
void RpnOperationsTable::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Operations Table Object Test Report\n");
    ObjectLevelDebuggingOrTesting(
        "\tRpnOpsTable->TestLevel = %d\n", GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting(
        "\tRpnOpsTable->DebugLevel = %d\n", GetObjectDebugLevel());
    ObjectLevelDebuggingOrTesting(
        "\tCurrent Path : %s\n", m_SearchPath->c_str());
    ObjectLevelDebuggingOrTesting(
        "\t%d Operations were added to the Operations Table\n",
        static_cast<int> (m_Operations.size()));

    for (auto& kv : m_Operations)
    {
        ObjectLevelDebuggingOrTesting("\t\tKey '%s' 0x%x\n",
            kv.first.c_str(), kv.second);
    }
}

 #ifndef RPNCALC_H_
#define RPNCALC_H_
#include "DbgTstHandling.h"
using namespace std;
class RpnCalculator : protected DebugAndTestHandling
{
private:
    class RpnOperationsTable *m_OpsTable;
    class RpnCalculatorIOSystem *m_IOSystem;
protected:
    inline int Test_DoesOperationsTableExist() {
        return ((m_OpsTable) ? 1 : 0);
    };
    inline int Test_DoesIOSystemExist() {
        return ((m_IOSystem) ? 1 : 0);
    };
    virtual void CalCulatorRunLoop();
public:
    RpnCalculator(int argc, char const * const argv[],
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnCalculator();
    virtual void RunUntilQuit();
    inline int Test_InternalTestsPassed() {
        return (
            Test_DoesOperationsTableExist() &&
            Test_DoesIOSystemExist()
        );
    };
    void TestReportThisObject();
};

#endif /* RPNCALC_H_ */

TstDbgCommon.h

#ifndef TSTDBGCOMMON_H_
#define TSTDBGCOMMON_H_

const unsigned int NODEBUGORTEST = 0;
const unsigned int NODEBUG = 0;
const unsigned int NOTEST = 0;
const unsigned int DEFAULTOBJECTTESTLEVEL = 1;
const unsigned int DEFAULTOBJECTDEBUGLEVEL = 0;
const unsigned int LEVEL1 = 1;
const unsigned int LEVEL2 = 2;
const unsigned int LEVEL3 = 3;
const unsigned int LEVEL4 = 4;
const unsigned int LEVEL5 = 5;
const unsigned int LEVEL6 = 6;
const unsigned int LEVEL7 = 7;
const unsigned int LEVEL8 = 8;
const unsigned int LEVEL9 = 9;
const unsigned int LEVEL10 = 10;
const unsigned int LEVEL11 = 11;
const unsigned int LEVEL12 = 12;
const unsigned int LEVEL13 = 13;
const unsigned int LEVEL14 = 14;
const unsigned int LEVEL15 = 15;
const unsigned int LEVEL16 = 16;
const unsigned int LEVEL17 = 17;
const unsigned int LEVEL18 = 18;
const unsigned int LEVEL19 = 19;
const unsigned int LEVEL20 = 20;

#endif /* TSTDBGCOMMON_H_ */

TestBase.h

#ifndef TESTBASE_H_
#define TESTBASE_H_

#include "TstDbgCommon.h"
using namespace std;
class TestBase
{
private:
    static unsigned int mA_Level;
    unsigned int mA_ObjectMinimumLevel;
    inline unsigned int mF_CheckLevelAgainstObjectLevel(unsigned int level)
    {
        return (mA_ObjectMinimumLevel < level);
    };
    inline unsigned int mF_CheckLevelAgainstProjectLevel(unsigned int level)
    {
        return (GetProjectTestLevel() > level);
    };
    inline unsigned int mF_CheckLevel(unsigned int level)
    {
        return (
            (mF_GetObjectLevel() < level) &&
            (level < GetProjectTestLevel())
        );
    };
protected:
    void mF_SetLevel(unsigned int Level)
    {
        this->mA_Level = Level;
    };
    inline unsigned int  mF_GetLevel()
    {
        return this->mA_Level;
    };
    inline void mF_SetObjectLevel(unsigned int Level)
    {
        this->mA_ObjectMinimumLevel = Level;
    };
    inline unsigned int  mF_GetObjectLevel()
    {
        return this->mA_ObjectMinimumLevel;
    };
    inline unsigned int mF_CheckTestLevel(unsigned int level)
    {
        return mF_CheckLevel(level);
    };
public:
    TestBase();
    virtual ~TestBase();
    inline void SetProjectTestLevel(unsigned int TestLevel)
    {
        mF_SetLevel(TestLevel);
    };
    inline unsigned int GetProjectTestLevel()
    {
        return mF_GetLevel();
    };
    inline void SetObjectTestLevel(unsigned int level)
    {
        mF_SetObjectLevel(level);
    };
    inline unsigned int GetObjectTestLevel()
    {
        return mF_GetObjectLevel();
    };
    inline unsigned int IsTesting()
    {
        return (
            (this->mA_Level) ?
                (
                    (this->mA_ObjectMinimumLevel) ?
                    (
                        this->mA_Level >= this->mA_ObjectMinimumLevel
                    )
                    : 0
                )
            : 0
        );
    };
    void ObjectLevelTesting(const char *OutputBuffer);
    virtual void ShowOnlyIfLevelGreaterThan(int forceLevel,
        const char* format, ...) = 0;
    virtual void TestReportThisObject() = 0;
};

#endif /* TESTBASE_H_ */

TestBase.cpp

#include "TestBase.h"
#include <iostream>
using namespace std;
unsigned int TestBase::mA_Level = NOTEST;
TestBase::TestBase() {
    mA_ObjectMinimumLevel = DEFAULTOBJECTTESTLEVEL;
}
TestBase::~TestBase() {
}

void TestBase::ObjectLevelTesting(const char *OutputBuffer)
{
    if (IsTesting())
    {
        cout << OutputBuffer;
    }
}

DebugBase.h

#ifndef DEBUGBASE_H_
#define DEBUGBASE_H_
#include "TstDbgCommon.h"
#include <functional>
using namespace std;
class DebugBase
{
private:
    static unsigned int mA_Level;
    unsigned int mA_ObjectMinimumLevel;
protected:
    inline void mF_SetProjectLevel(unsigned int Level)
    {
        this->mA_Level = Level;
    };
    inline unsigned int  mF_GetProjectLevel()
    {
        return this->mA_Level;
    };
    inline void  mF_SetObjectLevel(unsigned int level)
    {
        this->mA_ObjectMinimumLevel = level;
    };
    inline unsigned int  mF_GetObjectLevel()
    {
        return this->mA_ObjectMinimumLevel;
    };
    inline unsigned int mF_CheckLevelAgainstObjectLevel(unsigned int level)
    {
        return (mF_GetObjectLevel() < level);
    };
    inline unsigned int mF_CheckLevelAgainstProjectLevel(unsigned int level)
    {
        return (mF_GetProjectLevel() > level);
    };
    inline unsigned int mF_CheckLevel(unsigned int level)
    {
        return (
            (mF_GetObjectLevel() < level) &&
            (level < mF_GetProjectLevel())
        );
    };
public:
   DebugBase();
    virtual ~DebugBase();
    inline void SetProjectDebugLevel(unsigned int TestLevel)
    {
        mF_SetProjectLevel(TestLevel);
    };
    inline unsigned int GetProjectDebugLevel()
    {
        return mF_GetProjectLevel();
    };
    inline void SetObjectDebugLevel(unsigned int TestLevel)
    {
        mF_SetObjectLevel(TestLevel);
    };
    inline unsigned int GetObjectDebugLevel()
    {
        return mF_GetObjectLevel();
    };
    inline unsigned int IsDebugging()
    {
        return (
            (this->mA_Level) ?
            (
                (this->mA_ObjectMinimumLevel) ?
                (this->mA_Level >= this->mA_ObjectMinimumLevel)
                : 0)
            : 0
        );
    };
    void ObjectLevelDebugging(const char *OutputBuffer);
    virtual void ShowOnlyIfLevelGreaterThan(int forceLevel, const char* format, ...) = 0;
};
#endif /* DEBUGBASE_H_ */

DebugBase.cpp

#include "DebugBase.h"
#include <iostream>
using namespace std;
unsigned int DebugBase::mA_Level = 0;
DebugBase::DebugBase() {
    SetObjectDebugLevel(0);

}

DebugBase::~DebugBase() {
}

void DebugBase::ObjectLevelDebugging(const char *OutputBuffer)
{
    if (IsDebugging()) {
        cout << OutputBuffer;
    }
}

DbgTstHandling.h

#ifndef DBGTSTHANDLING_H_
#define DBGTSTHANDLING_H_
#include "TestBase.h"
#include "DebugBase.h"
#include <vector>
using namespace std;
class DebugAndTestHandling : protected TestBase, protected DebugBase
{
private:
    void mF_CommonDebugAndTestReporting(const char *Output);
    inline int mF_CheckLevelAgainstObjectLevels(unsigned int level)
    {
        return (
            ((TestBase::mF_GetObjectLevel() > level)) ||
            (DebugBase::mF_GetObjectLevel()> level)
        );
    };
    inline int mF_CheckLevelAgainstProjectDebug(unsigned int level)
    {
        return (GetProjectDebugLevel() > level);
    };
    inline int mF_CheckLevelAgainstProjectTest(unsigned int level)
    {
        return (GetProjectTestLevel() > level);
    };
    inline int mF_CheckLevelAgainstProjectLevels(unsigned int level)
    {
        return (
            (mF_CheckLevelAgainstProjectDebug(level)) ||
            (mF_CheckLevelAgainstProjectTest(level))
        );
    };
    inline int mF_CheckLevels(int level)
    {
        return (
            (TestBase::mF_CheckTestLevel(level)) ||
            (DebugBase::mF_CheckLevel(level))
        );
    };
protected:
    void ObjectLevelDebuggingOrTesting(const char *format, ...);
    void ShowOnlyIfLevelGreaterThan(int forceLevel, const char* format, ...);
    inline unsigned int IsTestingOrDebugging()
    {
        return ((IsTesting()) || (IsDebugging()));
    };
public:
    DebugAndTestHandling();
    virtual ~DebugAndTestHandling();
    inline void SetObjectMinimumDebugOrTestLevel(int level)
    {
        TestBase::SetObjectTestLevel(level);
        DebugBase::SetObjectDebugLevel(level);
    };
};

#endif /* DBGTSTHANDLING_H_ */

DbgTstHandling.cpp

#include "DbgTstHandling.h"
#include <iostream>
#include <cstdarg>
#include <ctype.h>
#include <string.h>
DebugAndTestHandling::DebugAndTestHandling()
{
    TestBase::SetObjectTestLevel(DEFAULTOBJECTTESTLEVEL);
    DebugBase::SetObjectDebugLevel(DEFAULTOBJECTDEBUGLEVEL);
}

DebugAndTestHandling::~DebugAndTestHandling()
{

}
void DebugAndTestHandling::mF_CommonDebugAndTestReporting(
        const char *OutputBuffer)
{
    if (IsDebugging())
    {
        ObjectLevelDebugging(OutputBuffer);
        return;
    }

    if (IsTesting())
    {
        ObjectLevelTesting(OutputBuffer);
        return;
    }
}
void DebugAndTestHandling::ObjectLevelDebuggingOrTesting(
        const char *format, ...)
{
    if (IsTestingOrDebugging())
    {
        char localBuffer[2028];
        va_list args;
        va_start(args, format);
        vsprintf(localBuffer, format, args);
        mF_CommonDebugAndTestReporting(localBuffer);
        va_end(args);
    }
}
void DebugAndTestHandling::ShowOnlyIfLevelGreaterThan(int forceLevel,
        const char *format, ...)
{
    if (mF_CheckLevels(forceLevel))
    {
        // Indent output by level
        for (int TabOutput = forceLevel; --TabOutput; )
    {
            cout << "\t";
        }
        char localBuffer[2028];
        va_list args;
        va_start(args, format);
        vsprintf(localBuffer, format, args);
        mF_CommonDebugAndTestReporting(localBuffer);
        va_end(args);
    }
}

RpnDLData.h

#ifndef RPNDLDATA_H_
#define RPNDLDATA_H_
#include <string>
using namespace std;
#include "plugins.h"
#include "DbgTstHandling.h"

using namespace std;
class RpnDLData : protected DebugAndTestHandling {
private:
    void *m_LibHandle;
    string *m_LibPath;
    OpTableEntry *m_Data;
    void m_OpenLibrary();
    void m_CloseLibrary();
    void m_FindRpnHubSymbol();
public:
    RpnDLData(string FullLibraryPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnDLData();
    inline const string *GetPath() { return m_LibPath; };
    inline int IsLibraryOpen() { return ((m_LibHandle) ? 1 : 0); };
    const OpTableEntry *GetOperationTableData();
    inline int IsRpnLibrary() { return (IsLibraryOpen() && m_Data); };
    void TestReportThisObject();
    void Test_ReportM_LibHandle();
    void Test_ReportM_LibPath();
    void Test_ReportM_Data();
    void Test_Reportm_IsOpen();
};

#endif /* RPNDLDATA_H_ */
#include <iostream>
#include <dlfcn.h>
#include <string>
#include <typeinfo>
#include "RpnDLData.h"
using namespace std;
void RpnDLData::Test_Reportm_IsOpen()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_IsOpen: %d\n",
        IsLibraryOpen());
}
void RpnDLData::Test_ReportM_LibPath()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibPath %s\n",
        m_LibPath->c_str());
}
void RpnDLData::Test_ReportM_LibHandle()
{
    ObjectLevelDebuggingOrTesting("\tRpnDLData->m_LibHandle 0x%x\n", m_LibHandle);
}
void RpnDLData::Test_ReportM_Data()
{
    if (m_Data)
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data = 0x%x\n", m_Data);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->FuncPtr = 0x%x\n",
            m_Data->FuncPtr);
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_Data->name = %s\n",
            m_Data->name);
    }
    else
    {
        ObjectLevelDebuggingOrTesting("\tRpnDLData->m_data = NULL\n");
    }
}
void RpnDLData::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Dynamic Library Object Test Report\n");
    ObjectLevelDebuggingOrTesting("\tRpnDLData->TestLevel = %d\n",
        GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting("\tRpnDLData->DebugLevel = %d\n",
        GetObjectDebugLevel());
    Test_ReportM_LibPath();
    Test_Reportm_IsOpen();
    Test_ReportM_Data();
    Test_ReportM_LibHandle();
}
RpnDLData::RpnDLData(string FullLibraryPath, int ObjectDebugTestLevel)
    {
    m_LibPath = NULL;
    m_LibHandle = NULL;
    m_Data = NULL;
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    m_LibPath = new string(FullLibraryPath);
    m_OpenLibrary();
    m_FindRpnHubSymbol();
    TestReportThisObject();
}
RpnDLData::~RpnDLData()
    {
    m_CloseLibrary();
    delete m_LibPath;
}
void RpnDLData::m_CloseLibrary()
{
    if (m_LibHandle)
    {
        dlclose(m_LibHandle);
        m_LibHandle = 0;
    }
}
void RpnDLData::m_OpenLibrary()
{
    if (!IsLibraryOpen())
    {
        if (!(m_LibHandle = dlopen(m_LibPath->c_str(), (RTLD_NOW | RTLD_LOCAL))))
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
                "Can't open shared library %s\n", m_LibPath);
        }
    }
}
void RpnDLData::m_FindRpnHubSymbol()
{
    if (IsLibraryOpen())
    {
        if (m_Data)
        {
            return;
        }
        void *Found = NULL;
        dlerror();    // Clear any previous errors
        Found = dlsym(m_LibHandle, "rpnhub_plugin");
        if (Found)
        {
            OpTableEntry *TableEntry = static_cast<OpTableEntry *>(Found);
            if (!TableEntry)
            {
                m_CloseLibrary();
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "Symbol does not convert %s\n", m_LibPath);
            }
            else
            {
                ShowOnlyIfLevelGreaterThan(LEVEL3,
                    "TableEntry = {%s,0x%x}\n", TableEntry->name,
                    TableEntry->FuncPtr);
            }
            m_Data = TableEntry;
        }
        else
        {
            ShowOnlyIfLevelGreaterThan(LEVEL3,
               "Can't find symbol rpnhub_plugin %s\n", m_LibPath);
        }
    }
}
const OpTableEntry *RpnDLData::GetOperationTableData()
{
    if (!IsRpnLibrary())
    {
        m_OpenLibrary();
        m_FindRpnHubSymbol();
    }
    return m_Data;
}

RpnOpsTab.h

#ifndef RPNOPSTAB_H_
#define RPNOPSTAB_H_
using namespace std;
#include <vector>
#include <stack>
#include <string>
#include <map>
#include "plugins.h"
#include "DbgTstHandling.h"
class RpnOperationsTable : protected DebugAndTestHandling {
private:
    string *m_SearchPath;
    map<string, const OpTableEntry *> m_Operations;
    vector<class RpnDLData *> m_OpenedLibraries;
    int m_FindAndAddPluginLibraries();
    int m_AddLibraryToTable(string Library);
    void m_CloseAllLibraries();

public:
    RpnOperationsTable(string *LibPath,
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnOperationsTable();
    void ExecuteOperation(string InputToken, stack<double>& Operands);
    void TestReportThisObject();
};

#endif /* RPNOPSTAB_H_ */

RpnOpsTab.cpp

#include <stdexcept>
#include <cstdlib>
#include <error_code.hpp>
#include <range.hpp>
#include <filesystem.hpp>
#include "RpnDLData.h"
#include "RpnOpsTab.h"
using namespace std;
using namespace boost;
using namespace boost::system;
using namespace boost::filesystem;
using namespace boost::range;
RpnOperationsTable::RpnOperationsTable(string *PathSpec, int ObjectDebugTestLevel)
{
    SetObjectMinimumDebugOrTestLevel(ObjectDebugTestLevel);
    if (!PathSpec)
    {
        string Emsg = "In RpnOperationsTable Constructor: Drop in directory path not specified";
        throw runtime_error(Emsg);
    }
    m_SearchPath = new string(*PathSpec);
    ObjectLevelDebuggingOrTesting("Current Path = %s\n", m_SearchPath->c_str());

    if (!m_FindAndAddPluginLibraries())
    {
        string Emsg = "No plugin libraries found for rpn in the search directory ";
        Emsg.append(*m_SearchPath);
        throw runtime_error(Emsg);
    }
}
RpnOperationsTable::~RpnOperationsTable()
    {
    m_CloseAllLibraries();
    delete m_SearchPath;
}
void RpnOperationsTable::m_CloseAllLibraries()
{
    for (auto OpenSharedLib : m_OpenedLibraries)
    {
        RpnDLData *DLCloseData = OpenSharedLib;
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Closing shared Library: %s\n", DLCloseData->GetPath()->c_str());
        delete DLCloseData;
    }
}
int RpnOperationsTable::m_FindAndAddPluginLibraries()
{
    int Found = 0;
    path plugins_dir(*m_SearchPath);
    path SharedLibExtention(".so");        // Change to .dll on Microsoft Windows
    if ((exists(plugins_dir)) && (is_directory(plugins_dir)))
    {
        for(auto& File_Iter : make_iterator_range(directory_iterator(plugins_dir), {}))
        {
            path PathToCheck = File_Iter;
            ShowOnlyIfLevelGreaterThan(LEVEL2, "Found library: %s\n", PathToCheck.c_str());
            if ((!is_directory(File_Iter)) && (PathToCheck.extension() == SharedLibExtention))
            {
                if (m_AddLibraryToTable(PathToCheck.string()))
                {
                    Found++;
                }
            }
        }
    }
    else
    {
        string Emsg = "The search path : ";
        Emsg.append(*m_SearchPath);
        Emsg.append(" either doesn't exist or is not a directory");
        throw runtime_error(Emsg);
    }
    return Found;
}
int RpnOperationsTable::m_AddLibraryToTable(string Library)
{
    int Added = 0;
    ObjectLevelDebuggingOrTesting("Attempting to insert library %s\n", Library.c_str());

    RpnDLData *DLCloseData = new RpnDLData(Library, GetObjectDebugLevel());
    if (!DLCloseData->IsLibraryOpen())
    {
        ShowOnlyIfLevelGreaterThan(LEVEL3, "Can't open shared library : %s\n", Library.c_str());
        return Added;    // If errors occur then ignore this library
    }
    const OpTableEntry *TableEntry = DLCloseData->GetOperationTableData();
    if (!TableEntry)
    {
        delete DLCloseData;
        ShowOnlyIfLevelGreaterThan(LEVEL3, "Can't find symbol rpnhub_plugin in  : %s\n", Library.c_str());
    }
    else
    {
        m_OpenedLibraries.push_back(DLCloseData);
        m_Operations[TableEntry->name] = TableEntry;
        Added++;
    }

    return Added;
}
void RpnOperationsTable::ExecuteOperation(string InputToken, stack<double>& Operands)
{
    OpTableEntry const *TableEntry = m_Operations[InputToken];
    if (TableEntry)
    {
        TableEntry->FuncPtr(Operands);
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Performed : %s\n", InputToken.c_str());
    }
    else
    {
        char Operator[32];
        strncpy(Operator, InputToken.c_str(), 32);
        Operands.push(atof(Operator));
        ShowOnlyIfLevelGreaterThan(LEVEL2, "Added %s to Operands\n",
            InputToken.c_str());
    }
}
void RpnOperationsTable::TestReportThisObject()
{
    ObjectLevelDebuggingOrTesting("RPN Operations Table Object Test Report\n");
    ObjectLevelDebuggingOrTesting(
        "\tRpnOpsTable->TestLevel = %d\n", GetObjectTestLevel());
    ObjectLevelDebuggingOrTesting(
        "\tRpnOpsTable->DebugLevel = %d\n", GetObjectDebugLevel());
    ObjectLevelDebuggingOrTesting(
        "\tCurrent Path : %s\n", m_SearchPath->c_str());
    ObjectLevelDebuggingOrTesting(
        "\t%d Operations were added to the Operations Table\n",
        static_cast<int> (m_Operations.size()));

    for (auto& kv : m_Operations)
    {
        ObjectLevelDebuggingOrTesting("\t\tKey '%s' 0x%x\n",
            kv.first.c_str(), kv.second);
    }
}

RpnCalc.h

#ifndef RPNCALC_H_
#define RPNCALC_H_
#include "DbgTstHandling.h"
using namespace std;
class RpnCalculator : protected DebugAndTestHandling
{
private:
    class RpnOperationsTable *m_OpsTable;
    class RpnCalculatorIOSystem *m_IOSystem;
protected:
    inline int Test_DoesOperationsTableExist() {
        return ((m_OpsTable) ? 1 : 0);
    };
    inline int Test_DoesIOSystemExist() {
        return ((m_IOSystem) ? 1 : 0);
    };
    virtual void CalCulatorRunLoop();
public:
    RpnCalculator(int argc, char const * const argv[],
        int ObjectDebugTestLevel=DEFAULTOBJECTTESTLEVEL);
    virtual ~RpnCalculator();
    virtual void RunUntilQuit();
    inline int Test_InternalTestsPassed() {
        return (
            Test_DoesOperationsTableExist() &&
            Test_DoesIOSystemExist()
        );
    };
    void TestReportThisObject();
};

#endif /* RPNCALC_H_ */
Clarified why it's using dynamic libraries.
Source Link
pacmaninbw
  • 26.1k
  • 13
  • 47
  • 114
Loading
Removed non-relevant portion of question.
Source Link
pacmaninbw
  • 26.1k
  • 13
  • 47
  • 114
Loading
Source Link
pacmaninbw
  • 26.1k
  • 13
  • 47
  • 114
Loading