commit e180be69b077bfcbbae77e1f49f21985db47788d Author: Scott R Charlton Date: Tue Feb 23 05:04:35 2010 +0000 Rearranging IPhreeqc git-svn-id: svn://136.177.114.72/svn_GW/IPhreeqc/trunk@4106 1feff8c3-07ed-0310-ac33-dd36852eb9cd diff --git a/CVar.hxx b/CVar.hxx new file mode 100644 index 00000000..dffa495d --- /dev/null +++ b/CVar.hxx @@ -0,0 +1,165 @@ +#ifndef __CVAR_HXX_INC +#define __CVAR_HXX_INC + + +#include "Debug.h" // ASSERT +#include "Var.h" +#include // std::ostream + +class CVar : public VAR +{ +// Constructors +public: + CVar(void) throw() + { + ::VarInit(this); + } + ~CVar(void) throw() + { + Clear(); + } + CVar(const VAR& varSrc) + { + type = TT_EMPTY; + InternalCopy(&varSrc); + } + CVar(const CVar& varSrc) + { + type = TT_EMPTY; + InternalCopy(&varSrc); + } + CVar(double dblSrc) throw() + { + type = TT_DOUBLE; + dVal = dblSrc; + } + CVar(const char* pszSrc) + { + type = TT_EMPTY; + *this = pszSrc; + } + CVar(long nSrc) throw() + { + type = TT_LONG; + lVal = nSrc; + } + +// Assignment Operators +public: + CVar& operator=(const CVar& varSrc) + { + InternalCopy(&varSrc); + return *this; + } + CVar& operator=(const VAR& varSrc) + { + InternalCopy(&varSrc); + return *this; + } + CVar& operator=(double dblSrc) throw() + { + if (type != TT_DOUBLE) + { + Clear(); + type = TT_DOUBLE; + } + dVal = dblSrc; + return *this; + } + CVar& operator=(const char* pszSrc) + { + Clear(); + type = TT_STRING; + sVal = ::VarAllocString(pszSrc); + + if (sVal == NULL && pszSrc != NULL) + { + type = TT_ERROR; + vresult = VR_OUTOFMEMORY; + } + return *this; + } + + friend std::ostream& operator<< (std::ostream &os, const CVar &a); + + +// Operations +public: + VRESULT Clear(void) { return ::VarClear(this); } + VRESULT Copy(const VAR* pSrc) { return ::VarCopy(this, const_cast(pSrc)); } + +// Implementation +public: + VRESULT InternalClear() + { + VRESULT vr = Clear(); + ASSERT(vr == VR_OK); + if (vr != VR_OK) + { + type = TT_ERROR; + vresult = vr; + } + return vr; + } + + void InternalCopy(const VAR* pSrc) + { + VRESULT vr = Copy(pSrc); + if (vr != VR_OK) + { + type = TT_ERROR; + vresult = vr; + } + } + +}; + +inline std::ostream& operator<< (std::ostream &os, const CVar &a) +{ + switch (a.type) { + case TT_EMPTY: + os << "(TT_EMPTY)"; + break; + case TT_ERROR: + switch (a.vresult) { + case VR_OK: + os << "VR_OK"; + break; + case VR_OUTOFMEMORY: + os << "VR_OUTOFMEMORY"; + break; + case VR_BADVARTYPE: + os << "VR_BADVARTYPE"; + break; + case VR_INVALIDARG: + os << "VR_INVALIDARG"; + break; + case VR_INVALIDROW: + os << "VR_INVALIDROW"; + break; + case VR_INVALIDCOL: + os << "VR_INVALIDCOL"; + break; + } + os << "(TT_ERROR)"; + break; + case TT_LONG: + os << a.lVal; + os << "(TT_LONG)"; + break; + case TT_DOUBLE: + os << a.dVal; + os << "(TT_DOUBLE)"; + break; + case TT_STRING: + os << "\"" << a.sVal << "\""; + os << "(TT_STRING)"; + break; + default: + os << "(BAD)"; + break; + } + return os; +} + +#endif // __CVAR_HXX_INC diff --git a/Debug.h b/Debug.h new file mode 100644 index 00000000..9da623d8 --- /dev/null +++ b/Debug.h @@ -0,0 +1,12 @@ +#ifndef _INC_DEBUG_H +#define _INC_DEBUG_H + +#if defined(_MSC_VER) +#include +#define ASSERT _ASSERT +#else +#include +#define ASSERT assert +#endif + +#endif /*_INC_DEBUG_H*/ diff --git a/ErrorReporter.hxx b/ErrorReporter.hxx new file mode 100644 index 00000000..a1eb67c3 --- /dev/null +++ b/ErrorReporter.hxx @@ -0,0 +1,60 @@ +#if !defined(__ERROR_REPORTER_HXX_INC) +#define __ERROR_REPORTER_HXX_INC + + +#include // std::ostream +#include // std::fprintf +#include "phreeqcns.hxx" + +class IErrorReporter { +public: + virtual size_t AddError(const char* error_msg) = 0; + virtual void Clear(void) = 0; +}; + +template +class CErrorReporter : public IErrorReporter +{ +public: + CErrorReporter(void); + virtual ~CErrorReporter(void); + + virtual size_t AddError(const char *error_msg); + virtual void Clear(void); + OS* GetOS(void) { return m_pOS; } +protected: + OS* m_pOS; + size_t m_error_count; +}; + +template +CErrorReporter::CErrorReporter(void) +: m_pOS(0) +, m_error_count(0) +{ + this->m_pOS = new OS; +} + +template +CErrorReporter::~CErrorReporter(void) +{ + delete this->m_pOS; +} + +template +size_t CErrorReporter::AddError(const char* error_msg) +{ + ++this->m_error_count; + (*this->m_pOS) << error_msg; + return this->m_error_count; +} + +template +void CErrorReporter::Clear(void) +{ + this->m_error_count = 0; + delete this->m_pOS; + this->m_pOS = new OS; +} + +#endif // __ERROR_REPORTER_HXX_INC diff --git a/FInterface.for b/FInterface.for new file mode 100644 index 00000000..d1bc3317 --- /dev/null +++ b/FInterface.for @@ -0,0 +1,116 @@ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION LoadDatabase(FILENAME) + CHARACTER(LEN=*) :: FILENAME + INTEGER(KIND=4) :: LoadDatabase + INTERFACE + FUNCTION FLoadDatabase(FILENAME) + !DEC$ ATTRIBUTES C,REFERENCE::FLoadDatabase + !DEC$ ATTRIBUTES ALIAS:'_LoadDatabaseF'::FLoadDatabase + CHARACTER(LEN=*) :: FILENAME + INTEGER(KIND=4) :: FLoadDatabase + END FUNCTION FLoadDatabase + END INTERFACE + LoadDatabase = FLoadDatabase(FILENAME) + END FUNCTION LoadDatabase +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + SUBROUTINE OutputLastError + INTERFACE + SUBROUTINE FOutputLastError + !DEC$ ATTRIBUTES C,REFERENCE::FOutputLines + !DEC$ ATTRIBUTES ALIAS:'_OutputLastError'::FOutputLastError + END SUBROUTINE FOutputLastError + END INTERFACE + CALL FOutputLastError + END SUBROUTINE OutputLastError +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION AccumulateLine(LINE) + CHARACTER(LEN=*) :: LINE + INTEGER(KIND=4) :: AccumulateLine + INTERFACE + FUNCTION FAccumulate(LINE) + !DEC$ ATTRIBUTES C,REFERENCE::FAccumulate + !DEC$ ATTRIBUTES ALIAS:'_AccumulateLineF'::FAccumulate + CHARACTER(LEN=*) :: LINE + INTEGER(KIND=4) :: FAccumulate + END FUNCTION FAccumulate + END INTERFACE + AccumulateLine = FAccumulate(LINE) + END FUNCTION AccumulateLine +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION Run(OUTPUT_ON, ERROR_ON, LOG_ON, SELECTED_ON) + LOGICAL(KIND=4) :: OUTPUT_ON + LOGICAL(KIND=4) :: ERROR_ON + LOGICAL(KIND=4) :: LOG_ON + LOGICAL(KIND=4) :: SELECTED_ON + INTEGER(KIND=4) :: Run + INTERFACE + FUNCTION FRun(OUTPUT_ON, ERROR_ON, LOG_ON, SELECTED_ON) + !DEC$ ATTRIBUTES C,REFERENCE::FRun + !DEC$ ATTRIBUTES ALIAS:'_RunF'::FRun + LOGICAL(KIND=4) :: OUTPUT_ON + LOGICAL(KIND=4) :: ERROR_ON + LOGICAL(KIND=4) :: LOG_ON + LOGICAL(KIND=4) :: SELECTED_ON + INTEGER(KIND=4) :: FRun + END FUNCTION FRun + END INTERFACE + Run = FRun(OUTPUT_ON, ERROR_ON, LOG_ON, SELECTED_ON) + END FUNCTION Run +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + SUBROUTINE OutputLines + INTERFACE + SUBROUTINE FOutputLines + !DEC$ ATTRIBUTES C,REFERENCE::FOutputLines + !DEC$ ATTRIBUTES ALIAS:'_OutputLines'::FOutputLines + END SUBROUTINE FOutputLines + END INTERFACE + CALL FOutputLines + END SUBROUTINE OutputLines +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION GetSelectedOutputRowCount + INTEGER(KIND=4) :: GetSelectedOutputRowCount + INTERFACE + FUNCTION FRows + !DEC$ ATTRIBUTES C,REFERENCE::FRows + !DEC$ ATTRIBUTES ALIAS:'_GetSelectedOutputRowCount'::FRows + INTEGER(KIND=4) :: FRows + END FUNCTION FRows + END INTERFACE + GetSelectedOutputRowCount = FRows() - 1 + END FUNCTION GetSelectedOutputRowCount +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION GetSelectedOutputColumnCount + INTEGER(KIND=4) :: GetSelectedOutputColumnCount + INTERFACE + FUNCTION FCols + !DEC$ ATTRIBUTES C,REFERENCE::FCols + !DEC$ ATTRIBUTES ALIAS:'_GetSelectedOutputColumnCount'::FCols + INTEGER(KIND=4) :: FCols + END FUNCTION FCols + END INTERFACE + GetSelectedOutputColumnCount = FCols() + END FUNCTION GetSelectedOutputColumnCount +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION GetSelectedOutputValue(ROW,COL,VTYPE,DVALUE,SVALUE) + INTEGER(KIND=4) :: ROW + INTEGER(KIND=4) :: COL + INTEGER(KIND=4) :: VTYPE + REAL(KIND=8) :: DVALUE + CHARACTER(LEN=*) :: SVALUE + INTEGER(KIND=4) :: GetSelectedOutputValue + INTEGER(KIND=4) :: adjcol + INTERFACE + FUNCTION Get(ROW,COL,VTYPE,DVALUE,SVALUE) + !DEC$ ATTRIBUTES C,REFERENCE::Get + !DEC$ ATTRIBUTES ALIAS:'_GetSelectedOutputValueF'::Get + INTEGER(KIND=4) :: ROW + INTEGER(KIND=4) :: COL + INTEGER(KIND=4) :: VTYPE + REAL(KIND=8) :: DVALUE + CHARACTER(LEN=*) :: SVALUE + INTEGER(KIND=4) :: Get + END FUNCTION Get + END INTERFACE + adjcol = col - 1 + GetSelectedOutputValue = Get(ROW,adjcol,VTYPE,DVALUE,SVALUE) + END FUNCTION GetSelectedOutputValue diff --git a/IPhreeqc.cpp b/IPhreeqc.cpp new file mode 100644 index 00000000..05209cab --- /dev/null +++ b/IPhreeqc.cpp @@ -0,0 +1,967 @@ +#if defined(_DEBUG) +#pragma warning(disable : 4786) // disable truncation warning +#endif +#include // std::cout +#include // std::ifstream +#include // std::auto_ptr +#include // std::istringstream +#include + +#if defined(_WIN32) +#include // ::OutputDebugString +#endif + +#include "phreeqcns.hxx" +#include "ErrorReporter.hxx" +#include "SelectedOutput.hxx" +#include "Var.h" +#include "IPhreeqc.h" +#include "module_files.h" + +#ifdef PHREEQC_CPP +extern int dump_entities(void); +extern int delete_entities(void); +extern int run_as_cells(void); +#endif + + +const char OUTPUT_FILENAME[] = "phreeqc.out"; +const char ERROR_FILENAME[] = "phreeqc.err"; +const char LOG_FILENAME[] = "phreeqc.log"; +const char PUNCH_FILENAME[] = "selected.out"; + + +const std::string& GetAccumulatedLines(void); +void ClearAccumulatedLines(void); + +void EndRow(void); +void AddSelectedOutput(const char* name, const char* format, va_list argptr); + + +struct PhreeqcStop{}; + +struct IPhreeqc +{ + // ctor + IPhreeqc(void) + : m_pIErrorReporter(0) + , m_bDatabaseLoaded(false) + , m_bSelectedOutputOn(false) + , m_sPunchFileName(NULL) + { + // initialize + UnLoadDatabase(); + }; + IPhreeqc(IErrorReporter *pIErrorReporter) + : m_pIErrorReporter(0) + , m_bDatabaseLoaded(false) + , m_bSelectedOutputOn(false) + , m_sPunchFileName(NULL) + { + // initialize + UnLoadDatabase(); + }; + ~IPhreeqc(void) + { + UnLoadDatabase(); + delete[] m_sPunchFileName; + }; + IErrorReporter *m_pIErrorReporter; + bool m_bDatabaseLoaded; + bool m_bSelectedOutputOn; + char *m_sPunchFileName; +}; + +static std::string s_string_input; +static std::ostringstream s_oss; +static CErrorReporter s_errorReporter; +static IPhreeqc s_IPhreeqc(&s_errorReporter); + +static void check_database(const char *sz_routine); + +static void do_run(const char* sz_routine, std::istream* pis, FILE* fp, int output_on, int error_on, int log_on, int selected_output_on, PFN_PRERUN_CALLBACK pfn_pre, PFN_POSTRUN_CALLBACK pfn_post, void *cookie); + + +int istream_getc(void *cookie); +int output_handler(const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args); +int open_handler(const int type, const char *file_name); +int handler(const int action, const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args); + + +int +istream_getc(void *cookie) +{ + if (cookie) + { + std::istream* is = (std::istream*)cookie; + return is->get(); + } + return EOF; +} + +int +handler(const int action, const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args) +{ + int n = OK; + switch (action) + { + case ACTION_OPEN: + n = open_handler(type, err_str); + break; + + case ACTION_OUTPUT: + n = output_handler(type, err_str, stop, cookie, format, args); + break; + + default: + n = module_handler(action, type, err_str, stop, cookie, format, args); + break; + } + + if (stop == STOP) + { + throw PhreeqcStop(); + } + return n; +} + +int +output_handler(const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args) +{ + IPhreeqc* pIPhreeqc = (IPhreeqc*) cookie; + + switch (type) + { + case OUTPUT_ERROR: + if (pIPhreeqc && pIPhreeqc->m_pIErrorReporter) + { + std::ostringstream oss; + oss << "ERROR: " << err_str << "\n"; + if (stop == STOP) { + oss << "Stopping.\n"; + } + pIPhreeqc->m_pIErrorReporter->AddError(oss.str().c_str()); + } + break; + + case OUTPUT_PUNCH: + AddSelectedOutput(err_str, format, args); + break; + + } + return module_handler(ACTION_OUTPUT, type, err_str, stop, cookie, format, args); +} + +int +open_handler(const int type, const char *file_name) +{ + int n = OK; + switch (type) + { + case OUTPUT_PUNCH: + if (file_name) + { + ASSERT(s_IPhreeqc.m_sPunchFileName != file_name); + if (s_IPhreeqc.m_sPunchFileName != file_name) + { + delete[] s_IPhreeqc.m_sPunchFileName; + s_IPhreeqc.m_sPunchFileName = NULL; + s_IPhreeqc.m_sPunchFileName = new char[::strlen(file_name) + 1]; + ::strcpy(s_IPhreeqc.m_sPunchFileName, file_name); + } + } + if (s_IPhreeqc.m_bSelectedOutputOn) + { + n = module_handler(ACTION_OPEN, type, file_name, CONTINUE, NULL, NULL, NULL); + } + break; + default: + n = module_handler(ACTION_OPEN, type, file_name, CONTINUE, NULL, NULL, NULL); + break; + } + return n; +} + +int +LoadDatabase(const char* filename) +{ + try + { + // cleanup + // + UnLoadDatabase(); + + CSelectedOutput::Instance()->Clear(); + +#if 0 + // open stream + // + std::ifstream ifs; + ifs.open(filename); + if (!ifs.is_open()) + { + std::ostringstream oss; + oss << "LoadDatabase: Unable to open:" << "\"" << filename << "\"."; + error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop + } + + // read input + // + read_database(istream_getc, &ifs); +#else + // open file + // + FILE* f = fopen(filename, "r"); + if (!f) + { + std::ostringstream oss; + oss << "LoadDatabase: Unable to open:" << "\"" << filename << "\"."; + error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop + } + + // read input + // + read_database(getc_callback, f); +#endif + } + catch (PhreeqcStop) + { + // do nothing + } + catch(...) + { + const char *errmsg = "LoadDatabase: An unhandled exception occured.\n"; + try + { + error_msg(errmsg, STOP); // throws PhreeqcStop + } + catch (PhreeqcStop) + { + // do nothing + } + } + + s_IPhreeqc.m_bDatabaseLoaded = (input_error == 0); + return input_error; +} + +int +LoadDatabaseString(const char* input) +{ + try + { + // cleanup + // + UnLoadDatabase(); + + CSelectedOutput::Instance()->Clear(); + + std::string s(input); + std::istringstream iss(s); + + // read input + // + read_database(istream_getc, &iss); + } + catch (PhreeqcStop) + { + // do nothing + } + catch(...) + { + const char *errmsg = "LoadDatabaseString: An unhandled exception occured.\n"; + try + { + error_msg(errmsg, STOP); // throws PhreeqcStop + } + catch (PhreeqcStop) + { + // do nothing + } + } + + s_IPhreeqc.m_bDatabaseLoaded = (input_error == 0); + return input_error; +} + +void +UnLoadDatabase(void) +{ + // init IPhreeqc + // + s_IPhreeqc.m_pIErrorReporter = &s_errorReporter; + s_IPhreeqc.m_bDatabaseLoaded = false; + s_IPhreeqc.m_bSelectedOutputOn = false; + + // clear error state + // + s_errorReporter.Clear(); + + // free selectedoutput + // + CSelectedOutput::Release(); + + // initialize phreeqc + // + clean_up(); + add_output_callback(handler, &s_IPhreeqc); + do_initialize(); + input_error = 0; +} + + +void +OutputLastError(void) +{ + std::cout << s_errorReporter.GetOS()->str().c_str() << std::endl; +} + +const char* +GetLastErrorString(void) +{ + static std::string str; + str = s_errorReporter.GetOS()->str(); + return str.c_str(); +} + +// COMMENT: {11/27/2006 7:00:49 PM}#if defined(_WIN32) +// COMMENT: {11/27/2006 7:00:49 PM}void +// COMMENT: {11/27/2006 7:00:49 PM}DebugOutputLastError(void) +// COMMENT: {11/27/2006 7:00:49 PM}{ +// COMMENT: {11/27/2006 7:00:49 PM} std::istringstream iss(s_errorReporter.GetOS()->str()); +// COMMENT: {11/27/2006 7:00:49 PM} std::string line; +// COMMENT: {11/27/2006 7:00:49 PM} while (std::getline(iss, line)) { +// COMMENT: {11/27/2006 7:00:49 PM} ::OutputDebugString(line.c_str()); +// COMMENT: {11/27/2006 7:00:49 PM} ::OutputDebugString("\n"); +// COMMENT: {11/27/2006 7:00:49 PM} } +// COMMENT: {11/27/2006 7:00:49 PM}} +// COMMENT: {11/27/2006 7:00:49 PM}#endif + + +VRESULT +AccumulateLine(const char *line) +{ + try + { + s_errorReporter.Clear(); + s_string_input.append(line); + s_string_input.append("\n"); + return VR_OK; + } + catch (...) + { + s_errorReporter.AddError("AccumulateLine: An unhandled exception occured.\n"); + } + return VR_OUTOFMEMORY; +} + +int +Run(int output_on, int error_on, int log_on, int selected_output_on) +{ + static const char *sz_routine = "Run"; + try + { + // this may throw + check_database(sz_routine); + + input_error = 0; + + // create input stream + std::istringstream iss(GetAccumulatedLines()); + + // this may throw + do_run(sz_routine, &iss, NULL, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL); + } + catch (PhreeqcStop) + { + // do nothing + } + catch(...) + { + const char *errmsg = "Run: An unhandled exception occured.\n"; + try + { + error_msg(errmsg, STOP); // throws PhreeqcStop + } + catch (PhreeqcStop) + { + // do nothing + } + } + + ::ClearAccumulatedLines(); + close_output_files(); + return input_error; +} + +int +RunFile(const char* filename, int output_on, int error_on, int log_on, int selected_output_on) +{ + static const char *sz_routine = "RunFile"; + try + { + // this may throw + check_database(sz_routine); + + input_error = 0; + +#if 0 + // create input stream + std::ifstream ifs; + ifs.open(filename); + if (!ifs.is_open()) + { + std::ostringstream oss; + oss << "RunFile: Unable to open:" << "\"" << filename << "\"."; + input_error = 1; + error_msg(oss.str().c_str(), STOP); // throws + } + + // this may throw + do_run(sz_routine, &ifs, NULL, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL); +#else + // open file + // + FILE* f = fopen(filename, "r"); + if (!f) + { + std::ostringstream oss; + oss << "RunFile: Unable to open:" << "\"" << filename << "\"."; + error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop + } + + // this may throw + do_run(sz_routine, NULL, f, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL); +#endif + } + catch (PhreeqcStop) + { + // do nothing + } + catch(...) + { + const char *errmsg = "RunFile: An unhandled exception occured.\n"; + try + { + error_msg(errmsg, STOP); // throws PhreeqcStop + } + catch (PhreeqcStop) + { + // do nothing + } + } + + close_output_files(); + return input_error; +} + +int +RunString(const char* input, int output_on, int error_on, int log_on, int selected_output_on) +{ + static const char *sz_routine = "RunString"; + try + { + // this may throw + check_database(sz_routine); + + input_error = 0; + + // create input stream + std::string s(input); + std::istringstream iss(s); + + // this may throw + do_run(sz_routine, &iss, NULL, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL); + } + catch (PhreeqcStop) + { + // do nothing + } + catch(...) + { + const char *errmsg = "RunString: An unhandled exception occured.\n"; + try + { + error_msg(errmsg, STOP); // throws PhreeqcStop + } + catch (PhreeqcStop) + { + // do nothing + } + } + + close_output_files(); + return input_error; +} + + +int +GetSelectedOutputRowCount(void) +{ + return (int)CSelectedOutput::Instance()->GetRowCount(); +} + +int +GetSelectedOutputColumnCount(void) +{ + return (int)CSelectedOutput::Instance()->GetColCount(); +} + +VRESULT +GetSelectedOutputValue(int row, int col, VAR* pVAR) +{ + s_errorReporter.Clear(); + if (!pVAR) { + s_errorReporter.AddError("GetSelectedOutputValue: VR_INVALIDARG pVar is NULL.\n"); + return VR_INVALIDARG; + } + + VRESULT v = CSelectedOutput::Instance()->Get(row, col, pVAR); + switch (v) { + case VR_OK: + break; + case VR_OUTOFMEMORY: + s_errorReporter.AddError("GetSelectedOutputValue: VR_OUTOFMEMORY Out of memory.\n"); + break; + case VR_BADVARTYPE: + s_errorReporter.AddError("GetSelectedOutputValue: VR_BADVARTYPE pVar must be initialized(VarInit) and/or cleared(VarClear).\n"); + break; + case VR_INVALIDARG: + // not possible + break; + case VR_INVALIDROW: + s_errorReporter.AddError("GetSelectedOutputValue: VR_INVALIDROW Row index out of range.\n"); + break; + case VR_INVALIDCOL: + s_errorReporter.AddError("GetSelectedOutputValue: VR_INVALIDCOL Column index out of range.\n"); + break; + } + return v; +} + +size_t +AddError(const char* error_msg) +{ + return s_errorReporter.AddError(error_msg); +} + +void +OutputLines(void) +{ + std::cout << s_string_input.c_str() << std::endl; +} + +// COMMENT: {11/27/2006 7:01:16 PM}#if defined(WIN32) +// COMMENT: {11/27/2006 7:01:16 PM}void +// COMMENT: {11/27/2006 7:01:16 PM}DebugOutputLines(void) +// COMMENT: {11/27/2006 7:01:16 PM}{ +// COMMENT: {11/27/2006 7:01:16 PM} std::istringstream iss(s_string_input); +// COMMENT: {11/27/2006 7:01:16 PM} std::string line; +// COMMENT: {11/27/2006 7:01:16 PM} while (std::getline(iss, line)) { +// COMMENT: {11/27/2006 7:01:16 PM} ::OutputDebugString(line.c_str()); +// COMMENT: {11/27/2006 7:01:16 PM} ::OutputDebugString("\n"); +// COMMENT: {11/27/2006 7:01:16 PM} } +// COMMENT: {11/27/2006 7:01:16 PM}} +// COMMENT: {11/27/2006 7:01:16 PM}#endif + +const std::string& +GetAccumulatedLines(void) +{ + return s_string_input; +} + +void +ClearAccumulatedLines(void) +{ + s_string_input.erase(); +} + +int +RunWithCallback(PFN_PRERUN_CALLBACK pfn_pre, PFN_POSTRUN_CALLBACK pfn_post, void *cookie, int output_on, int error_on, int log_on, int selected_output_on) +{ + static const char *sz_routine = "RunWithCallback"; + try + { + // this may throw + check_database(sz_routine); + + input_error = 0; + + // this may throw + do_run(sz_routine, NULL, NULL, output_on, error_on, log_on, selected_output_on, pfn_pre, pfn_post, cookie); + } + catch (PhreeqcStop) + { + // do nothing + } + catch(...) + { + const char *errmsg = "RunWithCallback: An unhandled exception occured.\n"; + try + { + error_msg(errmsg, STOP); // throws PhreeqcStop + } + catch (PhreeqcStop) + { + // do nothing + } + } + + ClearAccumulatedLines(); + close_output_files(); + output_close(OUTPUT_DUMP); // this should be closed in close_output_files + return input_error; +} + + +int +CatchErrors(PFN_CATCH_CALLBACK pfn, void *cookie) +{ + int rvalue = OK; + try + { + input_error = 0; + + if (pfn) + { + rvalue = pfn(cookie); + } + + } + catch (PhreeqcStop) + { + // do nothing + } + catch (...) + { + const char errmsg[] = "CatchErrors: Unhandled exception occured.\n"; + try + { + error_msg(errmsg, STOP); // throws PhreeqcStop + } + catch (PhreeqcStop) + { + // do nothing + } + } + return rvalue; +} + +static void +check_database(const char* sz_routine) +{ + s_errorReporter.Clear(); + CSelectedOutput::Instance()->Clear(); + + if (!s_IPhreeqc.m_bDatabaseLoaded) + { + std::ostringstream oss; + oss << sz_routine << ": No database is loaded"; + input_error = 1; + error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop + } +} + +static void +do_run(const char* sz_routine, std::istream* pis, FILE* fp, int output_on, int error_on, int log_on, int selected_output_on, PFN_PRERUN_CALLBACK pfn_pre, PFN_POSTRUN_CALLBACK pfn_post, void *cookie) +{ + std::auto_ptr auto_iss(NULL); + char token[MAX_LENGTH]; + + if (output_on) + { + if (output_open(OUTPUT_MESSAGE, OUTPUT_FILENAME) != OK) + { + std::ostringstream oss; + oss << sz_routine << ": Unable to open:" << "\"" << OUTPUT_FILENAME << "\".\n"; + warning_msg(oss.str().c_str()); + } + } + if (error_on) + { + if (output_open(OUTPUT_ERROR, ERROR_FILENAME) != OK) + { + std::ostringstream oss; + oss << sz_routine << ": Unable to open:" << "\"" << ERROR_FILENAME << "\".\n"; + warning_msg(oss.str().c_str()); + } + } + if (log_on) + { + if (output_open(OUTPUT_LOG, LOG_FILENAME) != OK) + { + std::ostringstream oss; + oss << sz_routine << ": Unable to open:" << "\"" << LOG_FILENAME << "\".\n"; + warning_msg(oss.str().c_str()); + } + } + + s_IPhreeqc.m_bSelectedOutputOn = (selected_output_on != 0); + +/* + * call pre-run callback + */ + if (pfn_pre) + { + pfn_pre(cookie); + } + +/* + * set read callback + */ + if (!pis) + { + if (fp) + { + set_read_callback(getc_callback, fp, FALSE); + } + else + { + std::auto_ptr a_iss(new std::istringstream(GetAccumulatedLines())); + auto_iss = a_iss; + set_read_callback(istream_getc, auto_iss.get(), FALSE); + } + } + else + { + set_read_callback(istream_getc, pis, FALSE); + } + + +/* + * Read input data for simulation + */ + for (simulation = 1; ; simulation++) { + +#ifdef PHREEQ98 + AddSeries = !connect_simulations; +#endif + sprintf(token, "Reading input data for simulation %d.", simulation); + + output_msg(OUTPUT_GUI_ERROR, "\nSimulation %d\n", simulation); + +#ifdef SWIG_SHARED_OBJ + int save_punch_in = punch.in; +#endif // SWIG_SHARED_OBJ + dup_print(token, TRUE); + if (read_input() == EOF) break; + +#ifdef SWIG_SHARED_OBJ + if (simulation > 1 && save_punch_in == TRUE && punch.new_def == TRUE) + { + std::ostringstream oss; + oss << sz_routine << ": Warning SELECTED_OUTPUT has been redefined.\n"; + warning_msg(oss.str().c_str()); + + } + if (simulation > 1 && keyword[39].keycount > 0) + { + std::ostringstream oss; + oss << sz_routine << ": Warning USER_PUNCH has been redefined.\n"; + warning_msg(oss.str().c_str()); + } +#endif // SWIG_SHARED_OBJ + + if (title_x != NULL) { + sprintf(token, "TITLE"); + dup_print(token, TRUE); + if (pr.headings == TRUE) output_msg(OUTPUT_MESSAGE,"%s\n\n", title_x); + } + +#ifdef SWIG_SHARED_OBJ + if (punch.in == TRUE) + { + // + // (punch.in == TRUE) when any "RUN" has contained + // a SELECTED_OUTPUT block since the last LoadDatabase call. + // + // Since LoadDatabase inititializes punch.in to FALSE + // (via UnLoadDatabase...do_initialize) + // and punch.in is set to TRUE in read_selected_output + // + // This causes the SELECTED_OUTPUT to contain the same headings + // until another SELECTED_OUTPUT is defined which sets the variable + // punch.new_def to TRUE + // + // WHAT IF A USER_PUNCH IS DEFINED?? IS punch.new_def SET TO + // TRUE ??? + // + // + if (!selected_output_on) ASSERT(!::output_isopen(OUTPUT_PUNCH)); + + if (pr.punch == FALSE) + { + // No selected_output for this simulation + // this happens when + // PRINT; -selected_output false + // is given as input + // Note: this also disables the CSelectedOutput object + } + else + { + if (punch.new_def == FALSE) + { + if (selected_output_on && !::output_isopen(OUTPUT_PUNCH)) + { + // + // LoadDatabase + // do_run -- containing SELECTED_OUTPUT ****TODO**** check -file option + // another do_run without SELECTED_OUTPUT + // + std::string filename = s_IPhreeqc.m_sPunchFileName; + output_open(OUTPUT_PUNCH, filename.c_str()); + if (!::output_isopen(OUTPUT_PUNCH)) + { + std::ostringstream oss; + oss << sz_routine << ": Unable to open:" << "\"" << filename << "\".\n"; + warning_msg(oss.str().c_str()); + } + else + { + // output selected_output headings + punch.new_def = TRUE; + tidy_punch(); + } + } + } + else + { + if (selected_output_on && !::output_isopen(OUTPUT_PUNCH)) + { + // This is a special case which could not occur in + // phreeqc + // + // LoadDatabase + // do_run -- containing SELECTED_OUTPUT ****TODO**** check -file option + // another do_run with SELECTED_OUTPUT + // + std::string filename = PUNCH_FILENAME; + if (s_IPhreeqc.m_sPunchFileName && ::strlen(s_IPhreeqc.m_sPunchFileName)) + { + filename = s_IPhreeqc.m_sPunchFileName; + } + output_open(OUTPUT_PUNCH, filename.c_str()); + if (!::output_isopen(OUTPUT_PUNCH)) + { + std::ostringstream oss; + oss << sz_routine << ": Unable to open:" << "\"" << filename << "\".\n"; + warning_msg(oss.str().c_str()); + } + else + { + // output selected_output headings + ASSERT(punch.new_def == TRUE); + tidy_punch(); + } + } + } + } + } + + if (!selected_output_on) ASSERT(!::output_isopen(OUTPUT_PUNCH)); + /* the converse is not necessarily true */ + + n_user_punch_index = -1; +#endif // SWIG_SHARED_OBJ + tidy_model(); +#ifdef PHREEQC_CPP + //test_classes(); +#endif +#ifdef PHREEQ98 + if (!phreeq98_debug) { +#endif + + +/* + * Calculate distribution of species for initial solutions + */ + if (new_solution) initial_solutions(TRUE); +/* + * Calculate distribution for exchangers + */ + if (new_exchange) initial_exchangers(TRUE); +/* + * Calculate distribution for surfaces + */ + if (new_surface) initial_surfaces(TRUE); +/* + * Calculate initial gas composition + */ + if (new_gas_phase) initial_gas_phases(TRUE); +/* + * Calculate reactions + */ + reactions(); +/* + * Calculate inverse models + */ + inverse_models(); +/* + * Calculate advection + */ + if (use.advect_in == TRUE) { + dup_print ("Beginning of advection calculations.", TRUE); + advection(); + } +/* + * Calculate transport + */ + if (use.trans_in == TRUE) { + dup_print ("Beginning of transport calculations.", TRUE); + transport(); + } + +#ifdef PHREEQC_CPP +/* + * run + */ + run_as_cells(); +#endif + +/* + * Copy + */ + if (new_copy) copy_entities(); +#ifdef PHREEQC_CPP + +/* + * dump + */ + dump_entities(); +/* + * delete + */ + delete_entities(); +#endif + +/* + * End of simulation + */ + dup_print( "End of simulation.", TRUE); +#ifdef PHREEQ98 + } /* if (!phreeq98_debug) */ +#endif + } + +/* + * Display successful status + */ + do_status(); + +/* + * call post-run callback + */ + if (pfn_post) + { + pfn_post(cookie); + } + + if (input_error > 0) + { + std::ostringstream oss; + oss << "\n"; + oss << s_string_input.c_str(); + oss << "\n"; + error_msg(oss.str().c_str(), CONTINUE); + } +} diff --git a/IPhreeqcF.F b/IPhreeqcF.F new file mode 100644 index 00000000..fdf25dd5 --- /dev/null +++ b/IPhreeqcF.F @@ -0,0 +1,194 @@ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION LoadDatabase(FILENAME) + IMPLICIT NONE + CHARACTER(LEN=*) :: FILENAME + INTEGER :: LoadDatabase +#if defined(_WIN32) + INTERFACE + FUNCTION LoadDatabaseF(FILENAME) + !DEC$ ATTRIBUTES C,REFERENCE::LoadDatabaseF + !DEC$ ATTRIBUTES ALIAS:'_LoadDatabaseF'::LoadDatabaseF + CHARACTER(LEN=*) :: FILENAME + INTEGER(KIND=4) :: LoadDatabaseF + END FUNCTION LoadDatabaseF + END INTERFACE +#else + INTEGER :: LoadDatabaseF +#endif + + LoadDatabase = LoadDatabaseF(FILENAME) + END FUNCTION LoadDatabase +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + SUBROUTINE OutputLastError + IMPLICIT NONE +#if defined(_WIN32) + INTERFACE + SUBROUTINE OutputLastErrorF + !DEC$ ATTRIBUTES C,REFERENCE::OutputLastErrorF + !DEC$ ATTRIBUTES ALIAS:'_OutputLastError'::OutputLastErrorF + END SUBROUTINE OutputLastErrorF + END INTERFACE +#endif + CALL OutputLastErrorF + END SUBROUTINE OutputLastError +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION AccumulateLine(LINE) + IMPLICIT NONE + CHARACTER(LEN=*) :: LINE + INTEGER :: AccumulateLine +#if defined(_WIN32) + INTERFACE + FUNCTION AccumulateLineF(LINE) + !DEC$ ATTRIBUTES C,REFERENCE::AccumulateLineF + !DEC$ ATTRIBUTES ALIAS:'_AccumulateLineF'::AccumulateLineF + CHARACTER(LEN=*) :: LINE + INTEGER(KIND=4) :: AccumulateLineF + END FUNCTION AccumulateLineF + END INTERFACE +#else + INTEGER :: AccumulateLineF +#endif + AccumulateLine = AccumulateLineF(LINE) + END FUNCTION AccumulateLine +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION Run(OUTPUT_ON, ERROR_ON, LOG_ON, SELECTED_ON) + IMPLICIT NONE + LOGICAL :: OUTPUT_ON + LOGICAL :: ERROR_ON + LOGICAL :: LOG_ON + LOGICAL :: SELECTED_ON + INTEGER :: Run +#if defined(_WIN32) + INTERFACE + FUNCTION RunF(OUTPUT_ON, ERROR_ON, LOG_ON, SELECTED_ON) + !DEC$ ATTRIBUTES C,REFERENCE::RunF + !DEC$ ATTRIBUTES ALIAS:'_RunF'::RunF + LOGICAL(KIND=4) :: OUTPUT_ON + LOGICAL(KIND=4) :: ERROR_ON + LOGICAL(KIND=4) :: LOG_ON + LOGICAL(KIND=4) :: SELECTED_ON + INTEGER(KIND=4) :: RunF + END FUNCTION RunF + END INTERFACE +#else + INTEGER :: RunF +#endif + Run = RunF(OUTPUT_ON, ERROR_ON, LOG_ON, SELECTED_ON) + END FUNCTION Run +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION RunFile(FILENAME,OUTPUT_ON,ERROR_ON,LOG_ON,SELECTED_ON) + IMPLICIT NONE + CHARACTER(LEN=*) :: FILENAME + LOGICAL :: OUTPUT_ON + LOGICAL :: ERROR_ON + LOGICAL :: LOG_ON + LOGICAL :: SELECTED_ON + INTEGER :: RunFile +#if defined(_WIN32) + INTERFACE + FUNCTION RunFileF(OUT_ON, ERR_ON, LOG_ON, SEL_ON, FILE) + !DEC$ ATTRIBUTES C,REFERENCE::RunFileF + !DEC$ ATTRIBUTES ALIAS:'_RunFileF'::RunFileF + LOGICAL(KIND=4) :: OUT_ON + LOGICAL(KIND=4) :: ERR_ON + LOGICAL(KIND=4) :: LOG_ON + LOGICAL(KIND=4) :: SEL_ON + CHARACTER(LEN=*) :: FILE + INTEGER(KIND=4) :: RunFileF + END FUNCTION RunFileF + END INTERFACE +#else + INTEGER :: RunFileF +#endif + RunFile = RunFileF(OUTPUT_ON, ERROR_ON, LOG_ON, + & SELECTED_ON, FILENAME) + END FUNCTION RunFile +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + SUBROUTINE OutputLines + IMPLICIT NONE +#if defined(_WIN32) + INTERFACE + SUBROUTINE OutputLinesF + !DEC$ ATTRIBUTES C,REFERENCE::OutputLinesF + !DEC$ ATTRIBUTES ALIAS:'_OutputLines'::OutputLinesF + END SUBROUTINE OutputLinesF + END INTERFACE +#endif + CALL OutputLinesF + END SUBROUTINE OutputLines +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION GetSelectedOutputRowCount() + IMPLICIT NONE + INTEGER :: GetSelectedOutputRowCount +#if defined(_WIN32) + INTERFACE + FUNCTION FRows + !DEC$ ATTRIBUTES C,REFERENCE::FRows + !DEC$ ATTRIBUTES ALIAS:'_GetSelectedOutputRowCountF'::FRows + INTEGER(KIND=4) :: FRows + END FUNCTION FRows + END INTERFACE + GetSelectedOutputRowCount = FRows() - 1 +#else + INTEGER :: GetSelectedOutputRowCountF + GetSelectedOutputRowCount = GetSelectedOutputRowCountF() - 1 +#endif + END FUNCTION GetSelectedOutputRowCount +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION GetSelectedOutputColumnCount() + IMPLICIT NONE + INTEGER :: GetSelectedOutputColumnCount +#if defined(_WIN32) + INTERFACE + FUNCTION FCols + !DEC$ ATTRIBUTES C,REFERENCE::FCols + !DEC$ ATTRIBUTES ALIAS:'_GetSelectedOutputColumnCount'::FCols + INTEGER(KIND=4) :: FCols + END FUNCTION FCols + END INTERFACE + GetSelectedOutputColumnCount = FCols() +#else + INTEGER :: GetSelectedOutputColumnCountF + GetSelectedOutputColumnCount = GetSelectedOutputColumnCountF() +#endif + END FUNCTION GetSelectedOutputColumnCount +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION GetSelectedOutputValue(ROW,COL,VTYPE,DVALUE,SVALUE) + IMPLICIT NONE + INTEGER :: ROW + INTEGER :: COL + INTEGER :: VTYPE + REAL*8 :: DVALUE + CHARACTER(LEN=*) :: SVALUE + INTEGER :: GetSelectedOutputValue + INTEGER :: adjcol +#if defined(_WIN32) + INTERFACE + FUNCTION Get(ROW,COL,VTYPE,DVALUE,SVALUE) + !DEC$ ATTRIBUTES C,REFERENCE::Get + !DEC$ ATTRIBUTES ALIAS:'_GetSelectedOutputValueF'::Get + INTEGER(KIND=4) :: ROW + INTEGER(KIND=4) :: COL + INTEGER(KIND=4) :: VTYPE + REAL(KIND=8) :: DVALUE + CHARACTER(LEN=*) :: SVALUE + INTEGER(KIND=4) :: Get + END FUNCTION Get + END INTERFACE + adjcol = col - 1 + GetSelectedOutputValue = Get(ROW,adjcol,VTYPE,DVALUE,SVALUE) +#else + INTEGER :: GetSelectedOutputValueF + adjcol = col - 1 + GetSelectedOutputValue = GetSelectedOutputValueF(ROW, + & adjcol,VTYPE,DVALUE,SVALUE) +#endif + END FUNCTION GetSelectedOutputValue +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION System(COMMAND) + IMPLICIT NONE + CHARACTER(LEN=*) :: COMMAND + INTEGER :: System + INTEGER :: SystemF + System = SystemF(COMMAND) + END FUNCTION System diff --git a/PhreeqcParser.hxx b/PhreeqcParser.hxx new file mode 100644 index 00000000..6984be5c --- /dev/null +++ b/PhreeqcParser.hxx @@ -0,0 +1,35 @@ +#if !defined(__PHREEQC_PARSER_HXX_INC) +#define __PHREEQC_PARSER_HXX_INC + + +// COMMENT: {11/10/2004 10:35:56 PM}#include +// COMMENT: {11/10/2004 10:35:56 PM}//#include +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM}struct PhreeqcStop{}; +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM}class CPhreeqcParser +// COMMENT: {11/10/2004 10:35:56 PM}{ +// COMMENT: {11/10/2004 10:35:56 PM}public: +// COMMENT: {11/10/2004 10:35:56 PM} CPhreeqcParser(std::istream& input); +// COMMENT: {11/10/2004 10:35:56 PM} virtual ~CPhreeqcParser(void); +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM} // const char* GetErrorMsg(void); +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM} // overrides +// COMMENT: {11/10/2004 10:35:56 PM} int get_logical_line(int *l); +// COMMENT: {11/10/2004 10:35:56 PM} int get_line(void); +// COMMENT: {11/10/2004 10:35:56 PM} // int error_msg (const char *err_str, const int stop); +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM}protected: +// COMMENT: {11/10/2004 10:35:56 PM} std::istream& m_input_stream; +// COMMENT: {11/10/2004 10:35:56 PM} //std::ostream& m_output_stream; +// COMMENT: {11/10/2004 10:35:56 PM} //std::ostream& m_error_stream; +// COMMENT: {11/10/2004 10:35:56 PM} +// COMMENT: {11/10/2004 10:35:56 PM} //std::string m_errors; +// COMMENT: {11/10/2004 10:35:56 PM}}; + + +#endif // __PHREEQC_PARSER_HXX_INC diff --git a/SelectedOutput.cpp b/SelectedOutput.cpp new file mode 100644 index 00000000..966488f8 --- /dev/null +++ b/SelectedOutput.cpp @@ -0,0 +1,455 @@ +// SelectedOutput.cpp: implementation of the CSelectedOutput class. +// +////////////////////////////////////////////////////////////////////// +#if defined(_DEBUG) +#pragma warning(disable : 4786) // disable truncation warning +#include // std::ostringstream +#include // ::OutputDebugString +#endif + +#include +#include + +#include "SelectedOutput.hxx" +#include "phreeqcns.hxx" + +const size_t RESERVE_ROWS = 80; +const size_t RESERVE_COLS = 80; + + +int EndRow(void); +void AddSelectedOutput(const char* name, const char* format, va_list argptr); +int warning_msg (const char *err_str); + +int EndRow(void) +{ + if (CSelectedOutput::Instance()->GetRowCount() <= 1) { + // ensure all user_punch headings are included + for (int i = n_user_punch_index; i < user_punch_count_headings; ++i) { + CSelectedOutput::Instance()->PushBackEmpty(user_punch_headings[i]); + } + } + return CSelectedOutput::Instance()->EndRow(); +} + +int PushBackDouble(const char* key, double dVal) +{ + return CSelectedOutput::Instance()->PushBackDouble(key, dVal); +} + +int PushBackLong(const char* key, long lVal) +{ + return CSelectedOutput::Instance()->PushBackLong(key, lVal); +} + +int PushBackString(const char* key, const char* sVal) +{ + return CSelectedOutput::Instance()->PushBackString(key, sVal); +} + +int PushBackEmpty(const char* key) +{ + return CSelectedOutput::Instance()->PushBackEmpty(key); +} + + +void AddSelectedOutput(const char* name, const char* format, va_list argptr) +{ + int bInt; + int bDouble; + int bString; + + int state; + int bLongDouble; + char ch; + + + /* state values + 0 Haven't found start(%) + 1 Just read start(%) + 2 Just read Flags(-0+ #) (zero or more) + 3 Just read Width + 4 Just read Precision start (.) + 5 Just read Size modifier + 6 Just read Type + */ + + if (name == NULL) { + return; + } + + bDouble = 0; + bInt = 0; + bString = 0; + + bLongDouble = 0; + + state = 0; + ch = *format++; + while (ch != '\0') { + switch (state) { + case 0: /* looking for Start specification (%) */ + switch (ch) { + case '%': + state = 1; + break; + default: + break; + } + ch = *format++; + break; + case 1: /* reading Flags (zero or more(-,+,0,# or space)) */ + switch (ch) { + case '-': case '0': case '+': case ' ': case '#': + ch = *format++; + break; + default: + state = 2; + break; + } + break; + case 2: /* reading Minimum field width (decimal integer constant) */ + switch (ch) { + case '.': + state = 3; + ch = *format++; + break; + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + ch = *format++; + break; + default: + state = 4; + break; + } + break; + case 3: /* reading Precision specification (period already read) */ + switch (ch) + { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + ch = *format++; + break; + default: + state = 4; + break; + } + break; + case 4: /* reading Size modifier */ + switch (ch) + { + case 'l': + ch = *format++; + break; + case 'L': + bLongDouble = 1; + ch = *format++; + break; + case 'h': + ch = *format++; + break; + } + state = 5; + break; + case 5: /* reading Conversion letter */ + switch (ch) { + case 'c': + break; + case 'd': + case 'i': + bInt = 1; + break; + case 'n': + case 'o': + case 'p': + break; + case 's': + bString = 1; + break; + case 'u': + case 'x': + case 'X': + case '%': + break; + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + bDouble = 1; + break; + default: + ASSERT(false); + break; + } + ch = '\0'; /* done */ + break; + } + } + + if (bDouble) { + double valDouble; + + if (bLongDouble) { + valDouble = (double)va_arg(argptr, long double); + } + else { + valDouble = va_arg(argptr, double); + } + + CSelectedOutput::Instance()->PushBackDouble(name, valDouble); + } + else if (bInt) { + int valInt; + valInt = va_arg(argptr, int); + + CSelectedOutput::Instance()->PushBackLong(name, (long)valInt); + } + else if (bString) { + char* valString; + valString = (char *)va_arg(argptr, char *); + + CSelectedOutput::Instance()->PushBackString(name, valString); + } + else { + ASSERT(false); + CSelectedOutput::Instance()->PushBackEmpty(name); + } +} + +// COMMENT: {11/16/2004 10:18:22 PM}CSelectedOutput CSelectedOutput::singleton; +CSelectedOutput* CSelectedOutput::s_instance = 0; + +CSelectedOutput* CSelectedOutput::Instance() +{ + if (s_instance == 0) + { + s_instance = new CSelectedOutput; + } + return s_instance; +} + +void CSelectedOutput::Release() +{ + if (s_instance) + { + delete s_instance; + s_instance = 0; + } +} + +CSelectedOutput::CSelectedOutput() +: m_nRowCount(0) +{ + this->m_arrayVar.reserve(RESERVE_COLS); +} + +CSelectedOutput::~CSelectedOutput() +{ +} + +void CSelectedOutput::Clear(void) +{ + this->m_nRowCount = 0; + this->m_vecVarHeadings.clear(); + this->m_arrayVar.clear(); + this->m_mapHeadingToCol.clear(); +} + +size_t CSelectedOutput::GetRowCount(void)const +{ + if (this->GetColCount()) + { + return this->m_nRowCount + 1; // rows + heading + } + else + { + return 0; + } +} + +size_t CSelectedOutput::GetColCount(void)const +{ + return this->m_vecVarHeadings.size(); +} + +CVar CSelectedOutput::Get(int nRow, int nCol)const +{ + CVar v; + this->Get(nRow, nCol, &v); + return v; +} + +VRESULT CSelectedOutput::Get(int nRow, int nCol, VAR* pVAR)const +{ + if ((size_t)nRow >= this->GetRowCount() || (size_t)nRow < 0) { + pVAR->type = TT_ERROR; + pVAR->vresult = VR_INVALIDROW; + return pVAR->vresult; + } + if ((size_t)nCol >= this->GetColCount() || (size_t)nCol < 0) { + pVAR->type = TT_ERROR; + pVAR->vresult = VR_INVALIDCOL; + return pVAR->vresult; + } + if (nRow) + { + ASSERT((size_t)nRow <= this->m_arrayVar[nCol].size()); + return ::VarCopy(pVAR, &(this->m_arrayVar[nCol])[nRow - 1]); + } + else + { + return ::VarCopy(pVAR, &(this->m_vecVarHeadings[nCol])); + } +} + + +int CSelectedOutput::EndRow(void) +{ + if (size_t ncols = this->GetColCount()) + { + ++this->m_nRowCount; + + // make sure array is full + for (size_t col = 0; col < ncols; ++col) + { + for (size_t row = 0; row < this->m_nRowCount; ++row) + { + size_t nrows = this->m_arrayVar[col].size(); + if (nrows < this->m_nRowCount) + { + // fill w/ empty + this->m_arrayVar[col].resize(this->m_nRowCount); + } +#if defined(_DEBUG) + else if (nrows > this->m_nRowCount) + { + ASSERT(false); + } +#endif + } + } + } +// COMMENT: {11/27/2006 7:22:37 PM}#if defined(_DEBUG) +// COMMENT: {11/27/2006 7:22:37 PM} this->AssertValid(); +// COMMENT: {11/27/2006 7:22:37 PM}#endif + return 0; +} + +int CSelectedOutput::PushBack(const char* key, const CVar& var) +{ + try + { + // check if key is new + std::map< std::string, size_t >::iterator find; + find = this->m_mapHeadingToCol.find(std::string(key)); + if (find == this->m_mapHeadingToCol.end()) + { + // new key(column) + // + this->m_mapHeadingToCol.insert(std::map< std::string, size_t >::value_type(std::string(key), + this->m_mapHeadingToCol.size()) ); + + // add heading + // + this->m_vecVarHeadings.push_back(CVar(key)); + + + // add new vector(col) + // + this->m_arrayVar.resize(this->m_arrayVar.size() + 1); + this->m_arrayVar.back().reserve(RESERVE_ROWS); + + // add empty rows if nec + if (this->m_nRowCount) + this->m_arrayVar.back().resize(this->m_nRowCount); + + this->m_arrayVar.back().push_back(var); + } + else + { + if (this->m_arrayVar[find->second].size() == this->m_nRowCount) { + this->m_arrayVar[find->second].push_back(var); + } + else { + ASSERT(this->m_arrayVar[find->second].size() == this->m_nRowCount + 1); + this->m_arrayVar[find->second].at(this->m_nRowCount) = var; + } + } + return 0; + } + catch(...) + { + ASSERT(false); + } + return 1; // error +} + + +int CSelectedOutput::PushBackDouble(const char* key, double value) +{ + CVar v(value); + return this->PushBack(key, v); +} + +int CSelectedOutput::PushBackLong(const char* key, long value) +{ + CVar v(value); + return this->PushBack(key, v); +} + +int CSelectedOutput::PushBackString(const char* key, const char* value) +{ + CVar v(value); + return this->PushBack(key, v); +} + +int CSelectedOutput::PushBackEmpty(const char* key) +{ + CVar v; + return this->PushBack(key, v); +} + +#if defined(_DEBUG) +void CSelectedOutput::Dump(const char* heading) +{ + ::OutputDebugStringA(heading); + std::ostringstream oss; + oss << *this; + std::istringstream iss(oss.str()); + std::string line; + while (std::getline(iss, line)) { + ::OutputDebugStringA(line.c_str()); + ::OutputDebugStringA("\n"); + } +} + +void CSelectedOutput::AssertValid(void)const +{ + if (size_t cols = this->GetColCount()) + { + size_t rows = this->m_arrayVar[0].size(); + for (size_t col = 0; col < cols; ++col) + { + ASSERT(rows == this->m_arrayVar[col].size()); + } + } +} +#endif + +std::ostream& operator<< (std::ostream &os, const CSelectedOutput &a) +{ +#if defined(_WIN32) + os << "CSelectedOutput(rows=" << a.GetRowCount() << ", cols=" << a.GetColCount() << ")\n"; +#endif + + CVar v; + for (size_t r = 0; r < a.GetRowCount(); ++r) { + for (size_t c = 0; c < a.GetColCount(); ++c) { + a.Get((int)r, (int)c, &v); + os << v << ", "; + ::VarClear(&v); + } + os << "\n"; + } + os << "\n"; + return os; +} diff --git a/SelectedOutput.hxx b/SelectedOutput.hxx new file mode 100644 index 00000000..accaf5e6 --- /dev/null +++ b/SelectedOutput.hxx @@ -0,0 +1,64 @@ +// SelectedOutput.h: interface for the CSelectedOutput class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined _INC_SELECTEDOUTPUT_H +#define _INC_SELECTEDOUTPUT_H + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include +#include +#include +#include +#include "CVar.hxx" + +// TODO: templatize +class CSelectedOutput +{ +protected: + CSelectedOutput(void); +public: + static CSelectedOutput* Instance(); + static void Release(); + + virtual ~CSelectedOutput(void); + + + int EndRow(void); + void Clear(void); + + size_t GetRowCount(void)const; + size_t GetColCount(void)const; + + CVar Get(int nRow, int nCol)const; + VRESULT Get(int nRow, int nCol, VAR* pVAR)const; + + int PushBack(const char* key, const CVar& var); + + int PushBackDouble(const char* key, double dVal); + int PushBackLong(const char* key, long lVal); + int PushBackString(const char* key, const char* sVal); + int PushBackEmpty(const char* key); + +#if defined(_DEBUG) + void Dump(const char* heading); + void AssertValid(void)const; +#endif + +protected: + friend std::ostream& operator<< (std::ostream &os, const CSelectedOutput &a); + + size_t m_nRowCount; + + std::vector< std::vector > m_arrayVar; + std::vector m_vecVarHeadings; + std::map< std::string, size_t > m_mapHeadingToCol; + +private: + static CSelectedOutput* s_instance; +}; + +#endif // !defined(_INC_SELECTEDOUTPUT_H) diff --git a/TallyF.F b/TallyF.F new file mode 100644 index 00000000..b20f1d13 --- /dev/null +++ b/TallyF.F @@ -0,0 +1,102 @@ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION build_tally_table() + IMPLICIT NONE + INTEGER :: build_tally_table +#if defined(_WIN32) + INTERFACE + FUNCTION build_tally_tableF() + !DEC$ ATTRIBUTES C,REFERENCE::build_tally_tableF + !DEC$ ATTRIBUTES ALIAS:'_build_tally_tableF'::build_tally_tableF + INTEGER(KIND=4) :: build_tally_tableF + END FUNCTION build_tally_tableF + END INTERFACE +#else + INTEGER :: build_tally_tableF +#endif + + build_tally_table = build_tally_tableF() + END FUNCTION build_tally_table + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION get_tally_table_rows_columns(rows, cols) + IMPLICIT NONE + INTEGER :: get_tally_table_rows_columns + INTEGER :: rows + INTEGER :: cols +#if defined(_WIN32) + INTERFACE + FUNCTION rows_cols(rows,cols) + !DEC$ ATTRIBUTES C,REFERENCE::rows_cols + !DEC$ ATTRIBUTES ALIAS:'_get_tally_table_rows_columnsF'::rows_cols + INTEGER :: rows + INTEGER :: cols + INTEGER(KIND=4) :: rows_cols + END FUNCTION rows_cols + END INTERFACE + + get_tally_table_rows_columns = rows_cols(rows,cols) +#else + INTEGER get_tally_table_rows_columnsF + get_tally_table_rows_columns = + & get_tally_table_rows_columnsF(rows,cols) +#endif + END FUNCTION get_tally_table_rows_columns + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION get_tally_table_column_heading(col,etype,string) + IMPLICIT NONE + INTEGER col + INTEGER etype + CHARACTER(*) string + INTEGER adjcol + INTEGER get_tally_table_column_heading +#if defined(_WIN32) + INTERFACE + FUNCTION col_head(col,etype,string) + !DEC$ ATTRIBUTES C,REFERENCE::col_head + !DEC$ ATTRIBUTES ALIAS:'_get_tally_table_column_headingF'::col_head + INTEGER col + INTEGER etype + CHARACTER(*) string + INTEGER col_head + END FUNCTION col_head + END INTERFACE + adjcol = col - 1 + get_tally_table_column_heading = col_head(adjcol,etype,string) +#else + INTEGER get_tally_table_column_headingF + adjcol = col - 1 + get_tally_table_column_heading = + & get_tally_table_column_headingF(adjcol,etype,string) +#endif + etype = etype + 1 + END FUNCTION get_tally_table_column_heading + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + FUNCTION get_tally_table_row_heading(row,string) + IMPLICIT NONE + INTEGER row + CHARACTER(*) string + INTEGER adjrow + INTEGER get_tally_table_row_heading +#if defined(_WIN32) + INTERFACE + FUNCTION row_head(row,string) + !DEC$ ATTRIBUTES C,REFERENCE::row_head + !DEC$ ATTRIBUTES ALIAS:'_get_tally_table_row_headingF'::row_head + INTEGER row + CHARACTER(*) string + INTEGER row_head + END FUNCTION row_head + END INTERFACE + adjrow = row - 1 + get_tally_table_row_heading = row_head(adjrow,string) +#else + INTEGER get_tally_table_row_headingF + adjrow = row - 1 + get_tally_table_row_heading = + & get_tally_table_row_headingF(adjrow,string) +#endif + END FUNCTION get_tally_table_row_heading diff --git a/Var.c b/Var.c new file mode 100644 index 00000000..1368ea7d --- /dev/null +++ b/Var.c @@ -0,0 +1,82 @@ +#include "Var.h" +#include +#include +#include + +// The VarInit function initializes the VAR +// by setting the type field to VT_EMPTY +// +void VarInit(VAR* pvar) +{ + pvar->type = TT_EMPTY; +} + +VRESULT VarClear(VAR* pvar) +{ + switch (pvar->type) + { + case TT_EMPTY: + break; + case TT_LONG: + break; + case TT_DOUBLE: + break; + case TT_STRING: + VarFreeString(pvar->sVal); + break; + case TT_ERROR: + break; + default: + assert(0); + return VR_BADVARTYPE; + } + VarInit(pvar); + return VR_OK; +} + +VRESULT VarCopy(VAR* pvarDest, const VAR* pvarSrc) +{ + VarClear(pvarDest); + + pvarDest->type = pvarSrc->type; + switch (pvarSrc->type) + { + case TT_EMPTY: + break; + case TT_LONG: + pvarDest->lVal = pvarSrc->lVal; + break; + case TT_DOUBLE: + pvarDest->dVal = pvarSrc->dVal; + break; + case TT_STRING: + pvarDest->sVal = VarAllocString(pvarSrc->sVal); + if (pvarDest->sVal == NULL && pvarSrc->sVal != NULL) { + pvarDest->type = TT_ERROR; + pvarDest->vresult = VR_OUTOFMEMORY; + return pvarDest->vresult; + } + break; + case TT_ERROR: + pvarDest->vresult = pvarSrc->vresult; + break; + default: + assert(0); + return VR_BADVARTYPE; + } + return VR_OK; +} + +char* VarAllocString(const char* pSrc) +{ + char* psz; + if (!pSrc) return NULL; + psz = (char*) malloc(strlen(pSrc) + 1); + strcpy(psz, pSrc); + return psz; +} + +void VarFreeString(char* pSrc) +{ + if (pSrc) free(pSrc); +} diff --git a/fwrap.c b/fwrap.c new file mode 100644 index 00000000..7d152103 --- /dev/null +++ b/fwrap.c @@ -0,0 +1,281 @@ +#include /* isgraph */ +#include /* malloc */ +#include /* memcpy */ +#include /* assert */ +#include /* printf */ + +#define EXTERNAL extern +#include "phreeqcpp/phreeqc/global.h" +#undef EXTERNAL + +struct buffer { + char *name; + struct master *master; + LDBLE moles; + LDBLE gfw; +}; + +/* + * Routines + */ +extern void add_all_components(void); +extern int build_tally_table(void); +extern int calc_dummy_kinetic_reaction(struct kinetics *kinetics_ptr); +extern int diff_tally_table(void); +extern int elt_list_to_tally_table(struct buffer *buffer_ptr); +extern int entity_exists (char *name, int n_user); +extern int extend_tally_table(void); +extern int free_tally_table(void); +extern int fill_tally_table(int *n_user, int n_buffer); +extern int get_tally_table_rows_columns(int *rows, int *columns); +extern int get_tally_table_column_heading(int column, int *type, char *string); +extern int get_tally_table_row_heading(int column, char *string); +extern int set_reaction_moles(int n_user, LDBLE moles); +extern int store_tally_table(double *array, int row_dim, int col_dim); +extern int warning_msg (const char *err_str); +extern int zero_tally_table(void); + + +#include "../include/IPhreeqc.h" + +/******************************* +When using GNU gcc/g++/g77 +compile fortran with: + g77 -fno-second-underscore +********************************/ +#if defined(__GNUC__) +#define LoadDatabaseF loaddatabasef_ +#define AccumulateLineF accumulatelinef_ +#define RunF runf_ +#define RunFileF runfilef_ +#define GetSelectedOutputValueF getselectedoutputvaluef_ +#define OutputLastErrorF outputlasterrorf_ +#define OutputLinesF outputlinesf_ +#define GetSelectedOutputRowCountF getselectedoutputrowcountf_ +#define GetSelectedOutputColumnCountF getselectedoutputcolumncountf_ +#define GetSelectedOutputValueF getselectedoutputvaluef_ +#define SystemF systemf_ +#endif + +#include "fwrap.h" + +char * +f2cstring(char* fstring, int len) +{ + char *cstr, *str; + int i; + + str = fstring; + for (i = len - 1; i >= 0 && !isgraph((int)str[i]); i--); + cstr = (char *) malloc((size_t) (i + 2)); + if (!cstr) return 0; + + cstr[i + 1] = '\0'; + memcpy(cstr,str,i+1); + return cstr; +} + +void +padfstring(char *dest, char *src, unsigned int len) +{ + unsigned int sofar; + + for (sofar = 0; (sofar < len) && (*src != '\0'); ++sofar) + *dest++ = *src++; + + while (sofar++ < len) + *dest++ = ' '; +} + +int +LoadDatabaseF(char* filename, unsigned int filename_length) +{ + int n; + char* cfilename; + + cfilename = f2cstring(filename, filename_length); + if (!cfilename) { + AddError("LoadDatabase: Out of memory.\n"); + return VR_OUTOFMEMORY; + } + + n = LoadDatabase(cfilename); + + free(cfilename); + + return n; +} + +VRESULT +AccumulateLineF(char *line, unsigned int line_length) +{ + VRESULT n; + char* cline; + + cline = f2cstring(line, line_length); + if (!cline) { + AddError("AccumulateLine: Out of memory.\n"); + return VR_OUTOFMEMORY; + } + + n = AccumulateLine(cline); + + free(cline); + + return n; +} + +int +RunF(int* output_on, int* error_on, int* log_on, int* selected_output_on) +{ + return Run(*output_on, *error_on, *log_on, *selected_output_on); +} + +int +RunFileF(int* output_on, int* error_on, int* log_on, int* selected_output_on, char* filename, unsigned int filename_length) +{ + char* cline; + + cline = f2cstring(filename, filename_length); + if (!cline) { + AddError("RunFile: Out of memory.\n"); + return (int)VR_OUTOFMEMORY; + } + + return RunFile(cline, *output_on, *error_on, *log_on, *selected_output_on); +} + +int +GetSelectedOutputRowCountF(void) +{ + return GetSelectedOutputRowCount(); +} + +int +GetSelectedOutputColumnCountF(void) +{ + return GetSelectedOutputColumnCount(); +} + +VRESULT +GetSelectedOutputValueF(int *row, int *col, int *vtype, double* dvalue, char* svalue, unsigned int svalue_length) +{ + VRESULT result; + VAR v; + VarInit(&v); + result = GetSelectedOutputValue(*row, *col, &v); + + switch (v.type) { + case TT_EMPTY: + *vtype = v.type; + break; + case TT_ERROR: + *vtype = v.type; + break; + case TT_LONG: + *vtype = TT_DOUBLE; + *dvalue = (double)v.lVal; + break; + case TT_DOUBLE: + *vtype = v.type; + *dvalue = v.dVal; + break; + case TT_STRING: + *vtype = v.type; + padfstring(svalue, v.sVal, svalue_length); + break; + default: + assert(0); + } + VarClear(&v); + return result; +} + +void +OutputLastErrorF(void) +{ + OutputLastError(); +} + +void +OutputLinesF(void) +{ + OutputLines(); +} + +#if defined(__cplusplus) +extern "C" { +#endif + +int +SystemF(char* command, unsigned int command_length) +{ + char* cline; + + cline = f2cstring(command, command_length); + if (!cline) { + AddError("System: Out of memory.\n"); + return (int)VR_OUTOFMEMORY; + } + + return system(cline); +} + +#if defined(__cplusplus) +} +#endif + + + +#if defined(_WIN32) + +#if defined(__cplusplus) +extern "C" { +#endif + +// +// Intel Fortran compiler 9.1 /iface:cvf +// +int __stdcall LOADDATABASE(char *filename, unsigned int len) +{ + return LoadDatabaseF(filename, len); +} +void __stdcall OUTPUTLASTERROR(void) +{ + OutputLastErrorF(); +} +int __stdcall ACCUMULATELINE(char *line, unsigned int len) +{ + return AccumulateLineF(line, len); +} +int __stdcall RUN(int *output_on, int *error_on, int *log_on, int *selected_on) +{ + return RunF(output_on, error_on, log_on, selected_on); +} +int __stdcall RUNFILE(char *filename, unsigned int len, int *output_on, int *error_on, int *log_on, int *selected_on) +{ + return RunFileF(output_on, error_on, log_on, selected_on, filename, len); +} +void __stdcall OUTPUTLINES(void) +{ + OutputLinesF(); +} +int __stdcall GETSELECTEDOUTPUTROWCOUNT(void) +{ + return GetSelectedOutputRowCountF() - 1; +} +int __stdcall GETSELECTEDOUTPUTCOLUMNCOUNT(void) +{ + return GetSelectedOutputColumnCountF(); +} +int __stdcall GETSELECTEDOUTPUTVALUE(int *row, int *col, int *vtype, double* dvalue, char* svalue, unsigned int svalue_length) +{ + int adjcol = *col - 1; + return GetSelectedOutputValueF(row, &adjcol, vtype, dvalue, svalue, svalue_length); +} +#if defined(__cplusplus) +} +#endif + +#endif + diff --git a/fwrap.h b/fwrap.h new file mode 100644 index 00000000..b8ad0335 --- /dev/null +++ b/fwrap.h @@ -0,0 +1,32 @@ +#ifndef __FWRAP__H +#define __FWRAP__H + + +#if defined(__cplusplus) +extern "C" { +#endif + + + int LoadDatabaseF(char* filename, unsigned int filename_length); + + VRESULT AccumulateLineF(char *line, unsigned int line_length); + + int RunF(int* output_on, int* error_on, int* log_on, int* selected_output_on); + + int RunFileF(int* output_on, int* error_on, int* log_on, int* selected_output_on, char* filename, unsigned int filename_length); + int GetSelectedOutputRowCountF(void); + + int GetSelectedOutputColumnCountF(void); + + VRESULT GetSelectedOutputValueF(int *row, int *col, int *vtype, double* dvalue, char* svalue, unsigned int svalue_length); + + void OutputLastErrorF(void); + + void OutputLinesF(void); + + +#if defined(__cplusplus) +} +#endif + +#endif /* __FWRAP__H */ diff --git a/fwrap2.c b/fwrap2.c new file mode 100644 index 00000000..5cc2642e --- /dev/null +++ b/fwrap2.c @@ -0,0 +1,55 @@ +#include "Var.h" +#include "fwrap.h" + +#if defined(_WIN32) + +#if defined(__cplusplus) +extern "C" { +#endif + +// +// Intel Fortran compiler 9.1 /iface:cvf +// +int LOADDATABASE(char *filename, unsigned int len) +{ + return LoadDatabaseF(filename, len); +} +void OUTPUTLASTERROR(void) +{ + OutputLastErrorF(); +} +int ACCUMULATELINE(char *line, unsigned int len) +{ + return AccumulateLineF(line, len); +} +int RUN(int *output_on, int *error_on, int *log_on, int *selected_on) +{ + return RunF(output_on, error_on, log_on, selected_on); +} +int RUNFILE(char *filename, unsigned int len, int *output_on, int *error_on, int *log_on, int *selected_on) +{ + return RunFileF(output_on, error_on, log_on, selected_on, filename, len); +} +void OUTPUTLINES(void) +{ + OutputLinesF(); +} +int GETSELECTEDOUTPUTROWCOUNT(void) +{ + return GetSelectedOutputRowCountF() - 1; +} +int GETSELECTEDOUTPUTCOLUMNCOUNT(void) +{ + return GetSelectedOutputColumnCountF(); +} +int GETSELECTEDOUTPUTVALUE(int *row, int *col, int *vtype, double* dvalue, char* svalue, unsigned int svalue_length) +{ + int adjcol = *col - 1; + return GetSelectedOutputValueF(row, &adjcol, vtype, dvalue, svalue, svalue_length); +} + +#if defined(__cplusplus) +} +#endif + +#endif \ No newline at end of file diff --git a/fwrap3.c b/fwrap3.c new file mode 100644 index 00000000..8049470a --- /dev/null +++ b/fwrap3.c @@ -0,0 +1,55 @@ +#include "Var.h" +#include "fwrap.h" + +#if defined(_WIN32) + +#if defined(__cplusplus) +extern "C" { +#endif + +// +// Intel Fortran compiler 9.1 /iface:cref /assume:underscore +// +int loaddatabase_(char *filename, unsigned int len) +{ + return LoadDatabaseF(filename, len); +} +void outputlasterror_(void) +{ + OutputLastErrorF(); +} +int accumulateline_(char *line, unsigned int len) +{ + return AccumulateLineF(line, len); +} +int run_(int *output_on, int *error_on, int *log_on, int *selected_on) +{ + return RunF(output_on, error_on, log_on, selected_on); +} +int runfile_(char *filename, unsigned int len, int *output_on, int *error_on, int *log_on, int *selected_on) +{ + return RunFileF(output_on, error_on, log_on, selected_on, filename, len); +} +void outputlines_(void) +{ + OutputLinesF(); +} +int getselectedoutputrowcount_(void) +{ + return GetSelectedOutputRowCountF() - 1; +} +int getselectedoutputcolumncount_(void) +{ + return GetSelectedOutputColumnCountF(); +} +int getselectedoutputvalue_(int *row, int *col, int *vtype, double* dvalue, char* svalue, unsigned int svalue_length) +{ + int adjcol = *col - 1; + return GetSelectedOutputValueF(row, &adjcol, vtype, dvalue, svalue, svalue_length); +} + +#if defined(__cplusplus) +} +#endif + +#endif \ No newline at end of file diff --git a/global.c b/global.c new file mode 100644 index 00000000..62c87820 --- /dev/null +++ b/global.c @@ -0,0 +1,5 @@ +#define EXTERNAL +#define MAIN +// TEST RMWEBB WRITE ACCESS +#include "global.h" +#include "phqalloc.h" diff --git a/module_files.c b/module_files.c new file mode 100644 index 00000000..f0d2c9f5 --- /dev/null +++ b/module_files.c @@ -0,0 +1,89 @@ +#include "module_files.h" +#if defined(R_SO) +#include "phreeqc_files.inl" +#else +#include "phreeqcpp/phreeqc/phreeqc_files.c" +#endif + +static int module_isopen_handler(const int type); +static int module_open_handler(const int type, const char *file_name); + +int +module_handler(const int action, const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args) +{ + switch (action) { + case ACTION_OPEN: + return module_open_handler(type, err_str); + break; + case ACTION_ISOPEN: + return module_isopen_handler(type); + break; + default: + return phreeqc_handler(action, type, err_str, stop, cookie, format, args); + break; + } + return ERROR; +} + +static int +module_isopen_handler(const int type) +{ + switch (type) + { + case OUTPUT_PUNCH: + if (punch_file) return 1; + break; + default: + assert(0); + } + return 0; +} + +static int +module_open_handler(const int type, const char *file_name) +{ + assert(file_name && strlen(file_name)); + switch (type) + { + case OUTPUT_MESSAGE: + if (output != NULL) + { + fclose(output); + output = NULL; + } + if ( (output = fopen(file_name, "w")) == NULL) + { + return ERROR; + } + break; + + case OUTPUT_ERROR: + assert(error_file != stderr); + if (error_file != NULL) + { + fclose(error_file); + error_file = NULL; + } + if ( (error_file = fopen(file_name, "w")) == NULL) + { + return ERROR; + } + break; + + case OUTPUT_LOG: + if (log_file != NULL) + { + fclose(log_file); + log_file = NULL; + } + if ( (log_file = fopen(file_name, "w")) == NULL) + { + return ERROR; + } + break; + default: + return open_handler(type, file_name); + break; + } + return(OK); +} diff --git a/module_files.h b/module_files.h new file mode 100644 index 00000000..c279cb18 --- /dev/null +++ b/module_files.h @@ -0,0 +1,25 @@ +#ifndef __MODULE_FILES__H +#define __MODULE_FILES__H + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +int module_handler(const int action, const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args); +int output_isopen(const int type); + + +typedef enum { + ACTION_ISOPEN = -100, +} module_action_type; + + +#if defined(__cplusplus) +} +#endif + +#endif /* __MODULE_FILES__H */ diff --git a/module_output.c b/module_output.c new file mode 100644 index 00000000..d4345f5f --- /dev/null +++ b/module_output.c @@ -0,0 +1,21 @@ +#include "module_files.h" + +#if defined(R_SO) +#include "output.inl" +#else +#include "phreeqcpp/phreeqc/output.c" +#endif + + +/* ---------------------------------------------------------------------- */ +int output_isopen(const int type) +/* ---------------------------------------------------------------------- */ +{ + size_t i; + int isopen; + for (i = 0; i < count_output_callback; ++i) { + isopen = (output_callbacks[i].callback)(ACTION_ISOPEN, type, NULL, CONTINUE, output_callbacks[i].cookie, NULL, NULL); + if (isopen) return 1; + } + return 0; +} diff --git a/phreeqcns.hxx b/phreeqcns.hxx new file mode 100644 index 00000000..5fb7c886 --- /dev/null +++ b/phreeqcns.hxx @@ -0,0 +1,27 @@ +// phreeqc namespace +// + +#if !defined(_INC_GLOBALNS) +#define _INC_GLOBALNS + +#if defined(_DEBUG) +#pragma warning(disable : 4786) // disable truncation warning +#endif + +#include + + +#define EXTERNAL extern + +#include "global.h" +#include "phqalloc.h" +#include "input.h" +#include "output.h" +#include "phrqproto.h" +EXTERNAL int n_user_punch_index; + +#undef EXTERNAL + + +#endif /* _INC_GLOBALNS */ + diff --git a/pp_sys.c b/pp_sys.c new file mode 100644 index 00000000..abc426a8 --- /dev/null +++ b/pp_sys.c @@ -0,0 +1,166 @@ +#if defined(linux) + +#include +#include + +#include /* strlen */ + +extern char *f2cstring(char* fstring, int len); +extern void padfstring(char *dest, char *src, unsigned int len); + +#define fullpathpp fullpathpp_ +#define splitpathpp splitpathpp_ +#define setenvpp setenvpp_ +#define peekcharpp peekcharpp_ + + +#if defined(__cplusplus) +extern "C" { +#endif + + int fullpathpp(char *name, char *path, unsigned int name_len, unsigned int path_len); + + int splitpathpp(char *path, char* drive, char* dir, char* name, char* ext, + unsigned int path_len, unsigned int drive_len, + unsigned int dir_len, unsigned int name_len, + unsigned int ext_len); + + int setenvpp(char *name, char *value, unsigned int name_len, unsigned int value_len); + + int peekcharpp(void); + +#if defined(__cplusplus) +} +#endif + + +int +fullpathpp(char *name, char *path, unsigned int name_len, unsigned int path_len) +{ + char *n; + char *ptr; + char buffer[PATH_MAX]; + + n = f2cstring(name, name_len); + + ptr = realpath(n, buffer); + if (ptr == NULL) { + // failure + free(n); + return 0; + } + else { + padfstring(path, buffer, path_len); + free(n); + return strlen(buffer); + } +} + +int +splitpathpp(char *path, char* drive, char* dir, char* name, char* ext, + unsigned int path_len, unsigned int drive_len, + unsigned int dir_len, unsigned int name_len, + unsigned int ext_len) +{ + int i; + int dot = 0; + int slash = 0; + int slash_found = 0; + char *cpath = NULL; + size_t plen = 0; + + /* linux has no drives */ + padfstring(drive, "", drive_len); + + if (cpath = f2cstring(path, path_len)) { + plen = strlen(cpath); + } + + if (plen == 0) { + padfstring(ext, "", ext_len); + padfstring(name, "", name_len); + padfstring(dir, "", dir_len); + free(cpath); + return 0; + } + + /* find last '.' and last '/' */ + for (i = plen - 1; i >= 0; --i) { + if ((cpath[i] == '.') && dot == 0) { + /* last '.' found */ + dot = i; + } + if (cpath[i] == '/') { + /* last '/' found */ + slash_found = 1; + slash = i; + break; + } + } + + /* copy ext */ + if (dot) { + /* ext found - '.' is included */ + padfstring(ext, &cpath[dot], ext_len); + cpath[dot] = '\0'; + } + else { + /* no ext */ + padfstring(ext, "", ext_len); + } + + if (slash_found) { + if (slash != plen - 1) { + /* copy name */ + padfstring(name, &cpath[slash+1], name_len); + cpath[slash+1] = '\0'; + } + else { + /* no name */ + padfstring(name, "", name_len); + } + + /* copy dir '/' is included */ + padfstring(dir, cpath, dir_len); + } + else { + /* copy name */ + padfstring(name, cpath, name_len); + + /* no dir */ + padfstring(dir, "", name_len); + } + + plen = strlen(dir); + free(cpath); + return plen; +} + +int +setenvpp(char *name, char *value, unsigned int name_len, unsigned int value_len) +{ + char *cname, *cvalue; + int result = 0; /* failure */ + + cname = f2cstring(name, name_len); + cvalue = f2cstring(value, value_len); + + if (cname != NULL && cvalue != NULL) { + if (setenv(cname, cvalue, 1) == 0) { + result = 1; /* success */ + } + } + + free(cname); + free(cvalue); + return result; +} + +int +peekcharpp(void) +{ + return 0; /* ignore for now */ +} + + +#endif /* defined(linux) */