From e180be69b077bfcbbae77e1f49f21985db47788d Mon Sep 17 00:00:00 2001 From: Scott R Charlton Date: Tue, 23 Feb 2010 05:04:35 +0000 Subject: [PATCH] Rearranging IPhreeqc git-svn-id: svn://136.177.114.72/svn_GW/IPhreeqc/trunk@4106 1feff8c3-07ed-0310-ac33-dd36852eb9cd --- CVar.hxx | 165 ++++++++ Debug.h | 12 + ErrorReporter.hxx | 60 +++ FInterface.for | 116 ++++++ IPhreeqc.cpp | 967 +++++++++++++++++++++++++++++++++++++++++++++ IPhreeqcF.F | 194 +++++++++ PhreeqcParser.hxx | 35 ++ SelectedOutput.cpp | 455 +++++++++++++++++++++ SelectedOutput.hxx | 64 +++ TallyF.F | 102 +++++ Var.c | 82 ++++ fwrap.c | 281 +++++++++++++ fwrap.h | 32 ++ fwrap2.c | 55 +++ fwrap3.c | 55 +++ global.c | 5 + module_files.c | 89 +++++ module_files.h | 25 ++ module_output.c | 21 + phreeqcns.hxx | 27 ++ pp_sys.c | 166 ++++++++ 21 files changed, 3008 insertions(+) create mode 100644 CVar.hxx create mode 100644 Debug.h create mode 100644 ErrorReporter.hxx create mode 100644 FInterface.for create mode 100644 IPhreeqc.cpp create mode 100644 IPhreeqcF.F create mode 100644 PhreeqcParser.hxx create mode 100644 SelectedOutput.cpp create mode 100644 SelectedOutput.hxx create mode 100644 TallyF.F create mode 100644 Var.c create mode 100644 fwrap.c create mode 100644 fwrap.h create mode 100644 fwrap2.c create mode 100644 fwrap3.c create mode 100644 global.c create mode 100644 module_files.c create mode 100644 module_files.h create mode 100644 module_output.c create mode 100644 phreeqcns.hxx create mode 100644 pp_sys.c 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) */