iphreeqc/PBasic.cpp
Darth Vader b8745514b6 Squashed 'phreeqcpp/' changes from da9d06b..2243d25
2243d25 Merge commit '013c822f76e5dc2e4fc19e87c6e5777aea6151d2'
c1af6f3 added newlines for CRAN
013c822 added newlines for CRAN
e4bd9ba [phreeqc3] fixes -Wclass-memaccess warnings for CRAN
29f06d2 fixed alignment in Description of solution
09a2680 guarded write_banner with NO_UTF8_ENCODING
082edbb changed src/print.cpp back to windows-1252 encoding; updated check_utf.sh
8d7c1fc adding mcd_Jtot and mcd_Jconc
9f0f622  Merge branch 'master' of github.com:usgs-coupled/phreeqc3
1040066 Merge remote-tracking branch 'usgs-coupled/master'
2a94644 cleaned up to eliminate some prints
07a864d all jacobians are consistent. Looks pretty good.
56975a7 Saved surface for numerical derivatives
df0d68b Runs all the test cases. Numerical derivatives work, but still some changes in residuals before and after jacobian calculations.
6bd936e Fixed numerical derivative (non-pitzer)
0dde2b0 removed comments
aef51fa Finally have derivatives right, I think
20281a0 always reset gases
13ec2fc best I could do for H2S while maintaining old tests. Used INCREMENTAL reactions
8be1ba8 revised jacobian_pz with new logic. Works with fixed_pressure examples H2S, H2S_pz, H2S_pz_appt, H2S_NaCl_Na2SO4.
71cf2a9 still produces different residuals
9022ded Tony H2S. Amm.dat, phreeqc.dat, pitzer.dat, utf8, updated test cases
cb1f9af Finished up C, Fortran, documentation. Need to check DOxygen
9dad447 Merge remote-tracking branch 'origin/master' into state
d647eec Added StateSave, StateApply, StateDelete with documentation for C++. Need testing, Fortran, and C
48cb5e8 Including OH- in converting units. Revised calculated density for H+ and OH-. Makes a difference in several test cases. Removed timing at end of .out in test cases. Checking in all test cases and selected output.
47e1ce5 added OH in density iteration calculation, test case NaOH_density
4aefb06 allow Fe(+3), equivalent to Fe(3), in TOT and TOTMOL. Previously fixed in SELECTED_OUTPUT -total
bea0ad1 unused variable, punch Fe(+3)
eaf788b fixed add_constant, undefined surface null pointer, added test cases
2212f9c fixed bug in reprep when sit had surface species. Added capability of sit + edl, have not tested it
79956e3 made tally_table a vector of class tally
58b0d1f Merge commit 'd77c11ec700085f19b76af6543013e23ee0739d3'
d77c11e [phreeqci] fixed header error with phast
63175ab [phreeqci] fixed header error with phast
0feb715 [phreeqci] fixed WINDOWS.H already included error on windows builds
123cc8a [phreeqci] fixed _ASSERTE error on linux builds
22c4a62 [phreeqci] struct to class changes
4cee19d Merge commit '2d8ca2d0f37d13ad67be582208a4e65edfcf702f'
2d8ca2d [phreeqci] added 'new' debugging
d0c8212 [phreeqci] added 'new' debugging
9661fea tokadd_heading leak
4565c5d catching upMerge remote-tracking branch 'origin/master' into classify
c22d792 fix notab leak
6d2b45a Merge remote-tracking branch 'usgs-coupled/master'
38cfe18 memory leak user_print, pitz/sit store, add uphill_NPa, remove TESTINT
24f9bf7 removed TESTING definition
e2ce928 Tony agreed with change for all_cells, new test case
d2a5d63 reset all_cells in all cases
e3c0d61 initialize aphi
c960e05 builds on vs2005; still needs to initialize class pitz_param* aphi
71dc944 cl1mp, bad initialization
2e5f255 fixed errors/warnings from ming and intel
369733e converted to classes
7961b16 release.txt, couple size_t
5d76f82 copy operator works well enough
7ce8947 updated InternalCopy for operator equal
7bd13ff new/delete theta params, pitz_param_copy
50e8903 new/delete pitz_params
87d6792 reverting changes to sit_params and theta_params. Will consider using new and delet
dcb9efe sit_params
ac3335e theta_params
8878232 delete rate, unused cptr
492df61 descriptions
25e0621 cell_data
051ddba stag_data
33157a2 fixed more size_t and initialized all structs
f86f430 back to original set of files I think
af1b761 removing CReaction and Classes files
006d1de reorganizing
287f81c elt_list vectorized
7228bd0 move struct rxn_token
28de8b5 more size_t
d2e3a4e Removed cxxChemRxn
ce64720 cleaned up, removed struct reaction
028e908 moving to CReaction
dc2dc53 vectorized token
9fd3f2a save_values rewritten with map
8a6cef5 vectorized save_values
8685225 fixed clang errors, needed .c_str
318e267 (size_t) max and count
1547d91 finished up spread
b5c7ba4 going to work on warnings
4c848b4 all inverse structures vectorized. Starting on solver workspace
980d58e finished vectorizing struct inverse. Need to do sub structs
d13bb76 removed count_elts
89ab28d vector inverse elts
d575ade tidy.cpp, title_x
16fd18f removed string_duplicate from prep.cpp
82a10d6 revised get_elt and get_token
d7e3be4 cleaned up some string_duplicate
76366a6 fixed processing file names
157a458 description_x
51fec19 class_main
c748922 added const qualifier for all the parsing
380a6ea methods set to const, variables need to follow
6d67e22 copier and dash
48e6b93 fixed a new master, advection punch_temp and print_temp, some tidying
5f21daf unknown->master now a vector. Using size instead of a null to end list.
3c432d0 user_graph commands, alk_list
2b14f80 last_model
7a6b8b6  Merge branch 'warnings_redux' into vectorize_2
885a2f7 Fix memory bug in ex13_impl, tweak Makefile.
6907bb0 base, sit arrays
90e8412 starting on pitzer
bd0cad9 vector kinetics arrays
1850c32 basic commands are now std::string
78a83ed c,d in polint
d82d5d6 vector llnl parameters, removed hash references
7c538b6  Revert "delete s[i]"
97bcfd7  Merge branch 'warnings_redux' into vectorize
15a8991 delete s[i]
0b19404 master new/delete
b100f85 more new/delete. Fixed str_tolower for ming
fd93f84 needed to new/delete species and phase structs
1986e00 alphabetize tokens
ee6fa53 bool analytic
cc614e6 add_logk for logk, species, phases
67447c5 Removed hashtable, all hashes have been replaced with maps.
ee7d2c5 replaced hash for isotope_ratio, isotope_alpha, calculate_value with maps. Fixed some case errors with new maps.
52e0622 replase master_isotope_hash_table with master_isotope_map
c01c8d6 replace logk_hash_table with logk_map. Added str_tolower(std::string)
3e69461 replaced phases_hash_table with phases_map
effafe0 replace species_hash_table with species_map
8bff6d3 removed HASH code. replaced elements_hash_table with elements_map
90e9ee0 removed ineq_init. Vector advection_print, advection_punch
2f38047 size_t for subscripts
5161ea7 Merged origin/master, Alphabetized Basic toks
f8e05c1 only call qsort with more than one element
1ab8641 remove _v, use std::vector only, alloc at least 1 scratch
9732a1c cannot qsort size 0 vector
67fc478 one more .data
2f0f5e1 Some replacements of .data() were incorrect
ba9813a remove .data()
43765f8 need <struct xxx>
0feb20d after merging origin/master, one fix needed
f136feb Merging origin/master. Merge remote-tracking branch 'origin/master' into warnings_redux
71aa5b9 bug count_sys not incremented
e43550c vector inverse
d4cc14e vector x
6c0edef vector rates
e3cc46a vector save_values
41b9965 vector species_list
449a54f vector mb_unknowns
51514eb vector delta, sum_jacobx
f0707aa vector sum_mb1, sum_mb2
7d303de vector trxn.token
83cfb29 elt_list, moved qsort to elt_list_combine
e8c9027 vector elt_list
0957a52 vector theta_params
b1af156 vector pitz_params
e3ea010 vector sit_params
b87d0cd vector my_array, residual, delta
e43471a vector s_x
622d361 vector s_x
3d41ef8 vector logk
e8dd208 vector sys
3c9f594 vector master
de1ba62 vector s
e7c78a8 vector phases
f2c64fe vector elements
e8af689 vector isotope_alpha
ba2601a vector isotope_ratio
76da4f8 finished master_isotope
4bb1c80 vector master_isotope
97e574d vector calculate_value**
9d9fbfb cl1 variables converted to std::vector
1e0d410 using memset
54b0d4d starting on space
5a649c2 Merge pull request #2 from usgs-coupled/gasphasepressures
a992537 (void)sscanf, removed SKIP, removed PHREEQ98
6a5bb8a Merge pull request #1 from usgs-coupled/mar10
d9ced82 Fixed uninitialized constructors and couple of other warnings
c79d2c2 working on UTF-8
fcee4d5 Added delta_h_species, delta_h_phase, dh_a0, dh_bdot Basic functions
81e862d Tonys changes Mar 10. SIs in inverse calulations
9e8b382 Merge remote-tracking branch 'usgs-coupled/master'
053b4c6 Merge remote-tracking branch 'origin/master'
20091aa Merge branch 'log10molalities' into gasphasepressures
41e1112 Last of changes for GetGasPhasePressures and GetGasPhasePhi, openmp and mpi. MPI fortrans not tested.
e1f9cb1 more checking in. Should be down to tweaks for SetGasPhaseMoles.
00ee6e3 C++ is working with OpenMP and MPI for Get/SetGasPhaseMoles. Need to add c and F90.
c3a3153 Added GetSpeciesLog10Molalities. Tested OpenMP with VS. Tested MPI with MinGW. Fortran, C, and C++ seem to work.
e8b11f3 added optional 6th argument to Basic function sys to change sort order from molality or moles to the name. Added synonym PAD$. Added new mytest/sys_sort.
3e4fc7e cleanup commented lines
54b992f working on tabs and no newline
2181847 Merge branch 'master' of https://github.com/usgs-coupled/phreeqc3
deeecb0 needed strexpr in ADD_HEADING to allow expressions
9b7785f [iphreeqccom] updated date
711b1d0 Merge commit '608e74f5d3c55a4d91a4e08d86f2fd6df0ce0a05'
608e74f [wphast] updated date
5128e13 [phreeqc3] updated image location
fba8ae2 [phreeqc3] updated image location
43988f0 initialize punch_newline
176fb02 Moved initialization from header to constructor, special characters in As.out
c9f796a added ADD_HEADING for IPhreeqc
1362f0f Added EOL_NOTAB$ and NO_NEWLINE$, updated release notes
2b4dbbd Merge commit 'cd51d8aeed46909e5f028a19089acfef43d6ede9'
f2023c4 Merge branch 'gtest' into 'master'
cd51d8a reset for dlls
54161f4 reset for dlls
01c99a7 Merge remote-tracking branch 'github/master'
23f3917 Merge remote-tracking branch 'scharlton2/master'
f6644e6 check for null pointer. Encoding for .out file
9319c9d Merge commit '5b816fa1fd82eb94e2702b6bd9df6066fb71267b'
5b816fa added src/phreeqcpp/common/PHRQ_exports.h
07717b1 added src/phreeqcpp/common/PHRQ_exports.h
d8c638f Merge remote-tracking branch 'origin/master' into gtest
87bbb6a adjusted alignment for utf-8 strings
03bda16 added write_banner to non-DOS and added UTF8 define
995de52 converted to utf-8
fc8fe3e re-added src/ZedGraph.dll
fbae3e9 code change for extending porosity definition. Change to TonyLitharge2a
46257e7 added googletest and fixed some minor bugs
13ca055 added googletest and fixed some minor bugs
f1dda6c Fixed problem with exchange-related when exchanger is defined as CaX2
20daad4 I guess cxxSurface::NO_EDL is correct
801812d Tony's changes to implicit Nernst-Planck calculation
6b4892c added Basic function DEBYE_LENGTH and test case zeta
921ab10 Changed tidy_exchange_min and tidy_exchange_kin to tidy only for new_def and n_user >= 0. Fixed bug if surf_charge not defined for NO_EDL. Added test MoreExchMix
2aef60a Finished up surface and exchange related for cases where related phase or kinetic reaction was modified. Proportionality should now be maintained. Added test cases.
569e1e1 Exchange related. Needed to update in case the related entity changed.
ea54e02 Free str in callback in PBasic
a87cd1f Merge commit '1871b026ca8487c23a025415dbc0b2eca01f9af4'
1871b02 fixed some c2011 warnings, added more info for -formula errors, fixed pressure llnl examples
aa4d023 fixed some c2011 warnings, added more info for -formula errors, fixed pressure llnl examples
e1465e3 Commit from David's Email 2020-05-22; Implementing llnl-type databases with higher temperature nad pressure
e18e1ec Tony bug fix for TRANSPORT. Harmonic mean for boundary? Added Cub example.
44f077e Merge commit 'e68934133fc9cd45e7cccc397c55e13f7ee92e5b'
e689341 [phreeqci] Testing subtree merges
4f34fd0 [phreeqci] Testing subtree merges
69c0bb3 fixed conflict on merge
55c4dba Merge commit 'b25fc5bdd48b6d3ab8d677f7d38ad3a462789500'
b25fc5b fixed conflict on merge
ca80be6 fixed conflict on merge
49a74a6 [phreeqc3] Testing subtree merges
aec6f90 [phreeqc3] Testing subtree merges
c4c224a Merge commit '84865ad5ac30a9edb86c89ced4194d127ee896fd'
0bf4138 Merge commit '4a8727cecd9fefd1587485820e913c0e666b77d9'
553875f Merge commit 'aab8bc12ea8be8aec5943e1c77a54b19d28168cb'
aab8bc1 Merge commit '84865ad5ac30a9edb86c89ced4194d127ee896fd'
7bd02ff Fixed bug with more porosities than cells in TRANSPORT. Added silica sorption to databases. Revised CalPortDiff
84865ad Added .gitlab-ci.yml
d398195 Added .gitlab-ci.yml
40c2787 Added .gitlab-ci.yml
3b6ce6c Added .gitlab-ci.yml
daf64a1 Added .gitlab-ci.yml
ae06f35 Fixed GFW bug on new elements in TRANSPORT
9cc783b added Basic functions for PHAST: velocity_x, velocity_y, velocity_z, transport_cell_no
79f768a Merge branch 'master' into 'master'
bd7634a removed j = j in loop
542394c IPhreeqc: ifdef'd out references to std::cerr and std::cout
6067ce8 Merge branch 'implicit3' into 'master'
21bd20f Fixed more compile warnings. Removed andra_kin_ss from testing, results are inconsistent between Linux and Windows, presumably the ifs in RATES
97b9c58 Merge branch 'implicit3' into 'master'
45db5cf Another Linux warning, lower tol on andra_kin_ss.
443be1c Merge branch 'implicit3' into 'master'
9a29aaf Last Linux compile warnings. Added more precision to andra_kin_ss.
6dafd7d Merge branch 'implicit3' into 'master'
fbde633 Fixing Linux compiler warnings, checking in new regression test files.
2207711 Merge branch 'implicit3' into 'master'
77e36a2 Tony fixed some transport, revised colloid_U. New cases added to Makefile.
f07caf9 Changed back print to allow incremental_reactions to work correctly
beadd07 Merge commit '5947da90657d1cb8f832152b4573dca0bbefb49e'
6a49d41 changes to make related and mixing items independent of case. surface_mix test case.
5947da9 initial Tony changes
8089c10 initial Tony changes
009aec7 Merge remote-tracking branch 'coupled/master'
4676ee4 added more P-R gas paramteters
c07314c Merge commit '492a4d257f300b7a9e0b5dc7e212c8f85ecb7f6e'
492a4d2 Merge remote-tracking branch 'coupled/master'
81ca633 Merge remote-tracking branch 'coupled/master'
950fca2 CRAN: replaced deprecated std::ptr_fun with lambda function
597bcd7 CRAN: replaced deprecated std::ptr_fun with lambda function
044e0ea phreeqc_ptr bug in internal copy
5934297 Merge commit '5c53fb207238bc0e846123a7e0d71a48bd9976ab'
5c53fb2 Merge commit '1327e93127e40e7a55ec629dcc9dd91ec29e77fe'
c117e18 Tony fix of index error
b90ddb5 Fixed Tony's fix, added implicit_as example
03acc3f changed abs to fabs
1fef40e added implicit, max_mixf to internal copy
32939ba Merge commit '1327e93127e40e7a55ec629dcc9dd91ec29e77fe'
b3bf691 fixed > > in templates for gcc
c929113 Tony fix May 31
1327e93 Implicit seems to be working with Tony's latest changes
55ea163 Implicit seems to be working with Tony's latest changes
c7111f7 Sort of works, still bugs and serious errors compared to explicit
600c7ee Fixed some bugs with iso.dat inverse modeling, added test case. Still does not generate [13C](4) and [13C](-4) from SOLUTION
2291700 Fixed gas_phase_mix bug, added test case
035a4e0 Tony tweak to transport.cpp
bd4fc25 Merge branch 'tony20190117' into 'master'
71c994b skipping restart
1257f8c Merge branch 'issue-3' into 'master'
ce33478 Fixed -Wcatch-value warnings reported by CRAN
040fd95 include restart, remove ex20_debug
d57264d 2. changes to solid solution numerical method
3fd8155 changes to solid solution numerical method
2b14a94 Tony's changes 20190117
ae6e8b0 added modify methods for restart files
b500c54 changed restart file to include UZ
fffac6d another try for ex20_debug
fa5ee50 fix problem with ex20_debug
d993901 encoding, limit.h
92c81f9 Revised logic for nmix
3cc84da Merge remote-tracking branch 'coupled/master' into ss_trans
56b5bf3 create valid ranges when sscanf doesn't return 2
c43c9af tweaked ss, changed surf function per Kinniburgh
b10df16 Corrected syntax of integer limit, previous commit actually changed ss convergence parameter, used to multiply by 0.99
d74c8ff Corrected syntax of integer limit
906cfd4 Check value of nmix
058375c removed check of ss when sum of components is small
2977db4 Tonys fix to diffusion bug with porosity change
f904467 revised lists to be cumulative for eq, gas, kin, ss
9285985 merging coupled/master into copy
7c23b62 Fixed string_duplicate memory error
2d5551a fixed sc7 for copy and initial time
4842d9e inverse iter 100000; finished copy operator; a bit more testing to go
4eefe43 ex20_debug fix
78e39cd still debugging copy
cee10e7 fixing bugs in copy operator
ebab4bc fixing bugs in copy operator
5a35e02 Fixed Linux warnings, memory errors
b86f793 Beginning to test copy operator
5d40e69 [IPhreeqc] added parens for clang++ -Wlogical-op-parentheses
936de38 removed register keywords and updated for misc clang warnings
ec9de4c beginning of checking copy operation
ebeddcd [iphreeqc] Changes for CRAN 3.4.7
9592d6e Merge branch 'dlpark-phreeqc3-TonyApr2018' into 'master'
7c0fb65 [phreeqc3] needed to check gas phase type for same model, added test case
9152ca2 Closes #1
ebc4f69 Merge branch 'dlpark-phreeqc3-TonyApr2018' into 'master'
97a0cec Fixed bug where 1W was interpreted as an isotope
2deb4ed added option -ddl to surface. Added test case
df7d5de Merge branch 'gammas' into 'master'
34abb5b gammas finished, working on reactants
5314827 Tony's changes; diffuse layer with pitzer
4271ca4 Tonys corrections, added balonis test
2e390fd commit fix for Mtg

git-subtree-dir: phreeqcpp
git-subtree-split: 2243d25babbc524e7875b3d591bb6b91c4399a95
2021-10-31 18:21:10 +00:00

7547 lines
160 KiB
C++

#if !(defined(WIN32) && !defined(__GNUC__))
#include <assert.h>
#define _ASSERTE assert
#endif
#include <stdlib.h>
#include "Phreeqc.h"
#include "PBasic.h"
#include "phqalloc.h"
#include "NameDouble.h"
#include "Utils.h"
#include "Solution.h"
/* Run-time library for PhreeqcPtr->use with "p2c", the Pascal to C translator */
/* "p2c" Copyright (C) 1989, 1990, 1991 Free Software Foundation.
* By Dave Gillespie, daveg@csvax.cs.caltech.edu. Version 1.20.
* This file may be copied, modified, etc. in any way. It is not restricted
* by the licence agreement accompanying p2c itself.
*/
#define STOP 1
#define CONTINUE 0
#define Isspace(c) isspace(c) /* or "((c) == ' ')" if preferred */
#define toklength 20
typedef long chset[9];
#if defined(PHREEQCI_GUI)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
/* Output from p2c, the Pascal-to-C translator */
/* From input file "basic.p" */
PBasic::PBasic(Phreeqc * ptr, PHRQ_io *phrq_io)
: PHRQ_base(phrq_io)
{
if (ptr == NULL)
{
error_msg("No Phreeqc instance in PBasic constructor\n", 1);
}
PhreeqcPtr = ptr;
inbuf = NULL;
linebase = NULL;
varbase = NULL;
loopbase = NULL;
curline = 0;
stmtline = NULL;
dataline = NULL;
stmttok = NULL;
datatok = NULL;
buf = NULL;
exitflag = false;
EXCP_LINE = 0;
P_escapecode = 0;
P_ioresult = 0;
parse_all = false;
phreeqci_gui = false;
parse_whole_program = true;
#if defined(PHREEQCI_GUI)
hInfiniteLoop = 0;
nIDErrPrompt = 0;
#else
nIDErrPrompt = (PBasic::IDErr)0;
#endif
nErrLineNumber = 0;
punch_tab = true;
skip_punch = false;
// Basic commands initialized at bottom of file
}
PBasic::~PBasic(void)
{
}
int PBasic::
basic_compile(const char *commands, void **lnbase, void **vbase, void **lpbase)
{ /*main */
int l;
const char *ptr;
P_escapecode = 0;
P_ioresult = 0;
inbuf = (char *) PhreeqcPtr->PHRQ_calloc(PhreeqcPtr->max_line, sizeof(char));
if (inbuf == NULL)
PhreeqcPtr->malloc_error();
linebase = NULL;
varbase = NULL;
loopbase = NULL;
exitflag = false;
ptr = commands;
do
{
try
{
ptr = commands;
do
{
if (sget_logical_line(&ptr, &l, inbuf) == EOF)
{
strcpy(inbuf, "bye");
}
parseinput(&buf);
if (curline == 0)
{
stmtline = NULL;
stmttok = buf;
if (stmttok != NULL)
exec();
disposetokens(&buf);
}
}
while (!(exitflag || P_eof()));
}
catch (const PBasicStop&)
{
if (P_escapecode != -20)
{
if (phreeqci_gui)
{
_ASSERTE(false);
}
else
{
char * error_string = PhreeqcPtr->sformatf("%d/%d", (int) P_escapecode,
(int) P_ioresult);
PhreeqcPtr->warning_msg(error_string);
}
}
else
{
if (phreeqci_gui)
{
_ASSERTE(false);
}
else
{
/* putchar('\n');*/
output_msg("\n");
}
}
}
catch (const PhreeqcStop&)
{
// clean up memory
disposetokens(&buf);
PhreeqcPtr->PHRQ_free(inbuf);
*lnbase = (void *) linebase;
*vbase = (void *) varbase;
*lpbase = (void *) loopbase;
throw; // rethrow
}
}
while (!(exitflag || P_eof()));
/* exit(EXIT_SUCCESS); */
PhreeqcPtr->PHRQ_free(inbuf);
*lnbase = (void *) linebase;
*vbase = (void *) varbase;
*lpbase = (void *) loopbase;
return (P_escapecode);
}
int PBasic::
basic_renumber(char *commands, void **lnbase, void **vbase, void **lpbase)
{ /*main */
int l, i;
const char *ptr;
P_escapecode = 0;
P_ioresult = 0;
inbuf = (char *) PhreeqcPtr->PHRQ_calloc(PhreeqcPtr->max_line, sizeof(char));
if (inbuf == NULL)
PhreeqcPtr->malloc_error();
linebase = NULL;
varbase = NULL;
loopbase = NULL;
exitflag = false;
ptr = commands;
do
{
try
{
i = 0;
ptr = commands;
do
{
if (sget_logical_line(&ptr, &l, inbuf) == EOF)
{
i++;
if (i == 1)
{
strcpy(inbuf, "renum");
}
else if (i == 2)
{
strcpy(inbuf, "list");
}
else if (i == 3)
{
strcpy(inbuf, "new");
}
else if (i == 4)
{
strcpy(inbuf, "bye");
}
}
parseinput(&buf);
if (curline == 0)
{
stmtline = NULL;
stmttok = buf;
if (stmttok != NULL)
exec();
disposetokens(&buf);
}
}
while (!(exitflag || P_eof()));
}
catch (const PBasicStop&)
{
if (P_escapecode != -20)
{
char * error_string = PhreeqcPtr->sformatf( "%d/%d", (int) P_escapecode,
(int) P_ioresult);
PhreeqcPtr->warning_msg(error_string);
}
else
{
/* putchar('\n');*/
output_msg("\n");
}
}
}
while (!(exitflag || P_eof()));
/* exit(EXIT_SUCCESS); */
PhreeqcPtr->PHRQ_free(inbuf);
*lnbase = (void *) linebase;
*vbase = (void *) varbase;
*lpbase = (void *) loopbase;
return (P_escapecode);
}
int PBasic::
basic_run(char *commands, void *lnbase, void *vbase, void *lpbase)
{ /*main */
int l;
const char *ptr;
P_escapecode = 0;
P_ioresult = 0;
inbuf = (char *) PhreeqcPtr->PHRQ_calloc(PhreeqcPtr->max_line, sizeof(char));
if (inbuf == NULL)
PhreeqcPtr->malloc_error();
linebase = NULL;
varbase = NULL;
loopbase = NULL;
exitflag = false;
ptr = commands;
linebase = (linerec *) lnbase;
varbase = (varrec *) vbase;
loopbase = (looprec *) lpbase;
do
{
try
{
do
{
if (sget_logical_line(&ptr, &l, inbuf) == EOF)
{
strcpy(inbuf, "bye");
}
parseinput(&buf);
if (curline == 0)
{
stmtline = NULL;
stmttok = buf;
if (stmttok != NULL)
exec();
disposetokens(&buf);
}
}
while (!(exitflag || P_eof()));
}
catch (const PBasicStop&)
{
if (P_escapecode != -20)
{
if (phreeqci_gui)
{
_ASSERTE(FALSE);
}
else
{
char * error_string = PhreeqcPtr->sformatf( "%d/%d", (int) P_escapecode,
(int) P_ioresult);
PhreeqcPtr->warning_msg(error_string);
}
}
else
{
/* putchar('\n');*/
output_msg("\n");
}
}
}
while (!(exitflag || P_eof()));
/* exit(EXIT_SUCCESS); */
PhreeqcPtr->PHRQ_free(inbuf);
// Cleanup after run
clearvars();
clearloops();
restoredata();
return (P_escapecode);
}
int PBasic::
basic_main(const char *commands)
{ /*main */
int l;
const char *ptr;
P_escapecode = 0;
P_ioresult = 0;
inbuf = (char *) PhreeqcPtr->PHRQ_calloc(PhreeqcPtr->max_line, sizeof(char));
if (inbuf == NULL)
PhreeqcPtr->malloc_error();
linebase = NULL;
varbase = NULL;
loopbase = NULL;
#ifdef SKIP
printf("Chipmunk BASIC 1.0\n\n");
#endif
exitflag = false;
ptr = commands;
do
{
try
{
do
{
if (sget_logical_line(&ptr, &l, inbuf) == EOF)
{
strcpy(inbuf, "bye");
}
parseinput(&buf);
if (curline == 0)
{
stmtline = NULL;
stmttok = buf;
if (stmttok != NULL)
exec();
disposetokens(&buf);
}
}
while (!(exitflag || P_eof()));
}
catch (const PBasicStop&)
{
if (P_escapecode != -20)
{
char * error_string = PhreeqcPtr->sformatf( "%d/%d", (int) P_escapecode,
(int) P_ioresult);
PhreeqcPtr->warning_msg(error_string);
}
else
{
/* putchar('\n');*/
output_msg("\n");
}
}
}
while (!(exitflag || P_eof()));
return 1;
/* exit(EXIT_SUCCESS); */
}
/* ---------------------------------------------------------------------- */
int PBasic::
sget_logical_line(const char **ptr, int *l, char *return_line)
/* ---------------------------------------------------------------------- */
{
/*
* Reads file fp until end of line, ";", or eof
* stores characters in line_save
* reallocs line_save and line if more space is needed
*
* returns:
* EOF on empty line on end of file or
* OK otherwise
* *l returns length of line
*/
int i;
char c;
i = 0;
if (**ptr == '\0')
return (EOF);
for (;;)
{
c = **ptr;
if (c == '\0')
break;
(*ptr)++;
if (c == ';' || c == '\n')
break;
return_line[i++] = c;
}
return_line[i] = '\0';
*l = i;
return (1);
}
void PBasic::
restoredata(void)
{
dataline = NULL;
datatok = NULL;
}
void PBasic::
clearloops(void)
{
looprec *l;
while (loopbase != NULL)
{
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
}
}
void PBasic::
clearvar(varrec * v)
{
if (v->numdims != 0)
{
if (v->stringvar == 0)
{
PhreeqcPtr->PHRQ_free(v->UU.U0.arr);
v->UU.U0.arr = NULL;
}
else
{
free_dim_stringvar(v);
}
}
else if (v->stringvar && v->UU.U1.sv != NULL)
{
PhreeqcPtr->PHRQ_free(v->UU.U1.sv);
}
v->numdims = 0;
if (v->stringvar)
{
v->UU.U1.sv = NULL;
v->UU.U1.sval = &v->UU.U1.sv;
}
else
{
v->UU.U0.rv = 0.0;
v->UU.U0.val = &v->UU.U0.rv;
}
}
void PBasic::
clearvars(void)
{
varrec *v;
v = varbase;
while (v != NULL)
{
clearvar(v);
v = v->next;
}
}
char * PBasic::
numtostr(char * Result, LDBLE n)
{
char *l_s;
long i;
l_s = (char *) PhreeqcPtr->PHRQ_calloc(PhreeqcPtr->max_line, sizeof(char));
if (l_s == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
l_s[PhreeqcPtr->max_line - 1] = '\0';
/* if ((n != 0 && fabs(n) < 1e-2) || fabs(n) >= 1e12) { */
if (ceil(n) == floor(n))
{
//if (PhreeqcPtr->current_selected_output != NULL &&
// !PhreeqcPtr->current_selected_output->Get_high_precision())
//{
// sprintf(l_s, "%12.0f", (double) n);
//}
//else
//{
// sprintf(l_s, "%20.0f", (double) n);
//}
bool temp_high_precision = (PhreeqcPtr->current_selected_output != NULL) ?
PhreeqcPtr->current_selected_output->Get_high_precision() :
PhreeqcPtr->high_precision;
if (!temp_high_precision)
{
sprintf(l_s, "%12.0f", (double) n);
}
else
{
sprintf(l_s, "%20.0f", (double) n);
}
}
else
{
bool temp_high_precision = (PhreeqcPtr->current_selected_output != NULL) ?
PhreeqcPtr->current_selected_output->Get_high_precision() :
PhreeqcPtr->high_precision;
if (!temp_high_precision)
{
sprintf(l_s, "%12.4e", (double) n);
}
else
{
sprintf(l_s, "%20.12e", (double) n);
}
}
i = (int) strlen(l_s) + 1;
l_s[i - 1] = '\0';
/* p2c: basic.p, line 237:
* Note: Modification of string length may translate incorrectly [146] */
strcpy(Result, l_s);
PhreeqcPtr->free_check_null(l_s);
return (Result);
/* } else {
if (PhreeqcPtr->punch.high_precision == FALSE) sprintf(l_s, "%30.10f", n);
else sprintf(l_s, "%30.12f", n);
i = strlen(l_s) + 1;
do {
i--;
} while (l_s[i - 1] == '0');
if (l_s[i - 1] == '.')
i--;
l_s[i] = '\0';
* p2c: basic.p, line 248:
* Note: Modification of string length may translate incorrectly [146] *
return strcpy(Result, strltrim(l_s));
} */
}
void PBasic::
parse(char * l_inbuf, tokenrec ** l_buf)
{
long i, j, begin, len, m, lp, q;
char token[toklength + 1] = {0};
tokenrec *t, *tptr;
varrec *v;
char ch;
char *ptr;
tptr = NULL;
*l_buf = NULL;
i = 1;
lp = q = 0;
do
{
ch = ' ';
while (i <= (int) strlen(l_inbuf) && (ch == ' ' || ch == '\t'))
{
ch = l_inbuf[i - 1];
i++;
}
if (ch != ' ')
{
t = (tokenrec *) PhreeqcPtr->PHRQ_calloc(1, sizeof(tokenrec));
if (t == NULL)
PhreeqcPtr->malloc_error();
if (tptr == NULL)
*l_buf = t;
else
tptr->next = t;
if (phreeqci_gui)
{
t->n_sz = 0;
t->sz_num = 0;
}
tptr = t;
t->next = NULL;
switch (ch)
{
case '"':
case '\'':
q += 1;
t->kind = tokstr;
j = 0;
len = (int) strlen(l_inbuf);
begin = i;
while (i <= len && l_inbuf[i - 1] != ch)
{
++j;
++i;
}
if (l_inbuf[i - 1] == ch) q -= 1;
m = 256;
if (j + 1 > m)
m = j + 1;
t->UU.sp = (char *) PhreeqcPtr->PHRQ_calloc(m, sizeof(char));
if (t->UU.sp == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
strncpy(t->UU.sp, l_inbuf + begin - 1, j);
t->UU.sp[j] = '\0';
/* p2c: basic.p, line 415:
* Note: Modification of string length may translate incorrectly [146] */
i++;
break;
case '+':
t->kind = tokplus;
break;
case '-':
t->kind = tokminus;
break;
case '*':
t->kind = toktimes;
break;
case '/':
t->kind = tokdiv;
break;
case '^':
t->kind = tokup;
break;
case '(':
case '[':
t->kind = toklp;
lp += 1;
break;
case ')':
case ']':
t->kind = tokrp;
lp -= 1;
break;
case ',':
t->kind = tokcomma;
break;
case ';':
t->kind = toksemi;
break;
case ':':
t->kind = tokcolon;
break;
case '?':
t->kind = tokprint;
break;
case '=':
t->kind = tokeq;
break;
case '<':
if (i <= (int) strlen(l_inbuf) && l_inbuf[i - 1] == '=')
{
t->kind = tokle;
i++;
}
else if (i <= (int) strlen(l_inbuf) && l_inbuf[i - 1] == '>')
{
t->kind = tokne;
i++;
}
else
t->kind = toklt;
break;
case '>':
if (i <= (int) strlen(l_inbuf) && l_inbuf[i - 1] == '=')
{
t->kind = tokge;
i++;
}
else
t->kind = tokgt;
break;
default:
if (isalpha((int) ch))
{
i--;
j = 0;
token[toklength] = '\0';
while (i <= (int) strlen(l_inbuf) &&
(l_inbuf[i - 1] == '$' || l_inbuf[i - 1] == '_' ||
isalnum((int) l_inbuf[i - 1])))
{
if (j < toklength)
{
j++;
token[j - 1] = l_inbuf[i - 1];
}
i++;
}
token[j] = '\0';
/* p2c: basic.p, line 309:
* Note: Modification of string length may translate incorrectly [146] */
/*
* Search list
*/
PhreeqcPtr->str_tolower(token);
std::map<const std::string, BASIC_TOKEN>::const_iterator item;
item = command_tokens.find(token);
if (item != command_tokens.end())
{
t->kind = item->second;
if (t->kind == tokrem)
{
m = (int) strlen(l_inbuf) + 1;
if (m < 256)
m = 256;
t->UU.sp = (char *) PhreeqcPtr->PHRQ_calloc(m, sizeof(char));
if (t->UU.sp == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
sprintf(t->UU.sp, "%.*s",
(int) (strlen(l_inbuf) - i + 1),
l_inbuf + i - 1);
i = (int) strlen(l_inbuf) + 1;
}
}
else
{
t->kind = tokvar;
v = varbase;
while (v != NULL && strcmp(v->name, token))
v = v->next;
if (v == NULL)
{
v = (varrec *) PhreeqcPtr->PHRQ_calloc(1, sizeof(varrec));
if (v == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
v->UU.U0.arr = NULL;
v->next = varbase;
varbase = v;
strcpy(v->name, token);
v->numdims = 0;
if (token[strlen(token) - 1] == '$')
{
v->stringvar = true;
v->UU.U1.sv = NULL;
v->UU.U1.sval = &v->UU.U1.sv;
}
else
{
v->stringvar = false;
v->UU.U0.rv = 0.0;
v->UU.U0.val = &v->UU.U0.rv;
}
}
t->UU.vp = v;
}
}
else if (isdigit((int) ch) || ch == '.')
{
t->kind = toknum;
i--;
t->UU.num = strtod(&l_inbuf[i - 1], &ptr);
if (&l_inbuf[i - 1] == ptr)
{
/*
Note: the following causes an infinite loop:
X = ..9
*/
t->kind = toksnerr;
t->UU.snch = ch;
i++;
break;
}
#if defined(PHREEQCI_GUI)
if (phreeqci_gui)
{
_ASSERTE(t->n_sz == 0);
_ASSERTE(t->sz_num == NULL);
t->n_sz = max(23, ptr - &inbuf[i - 1]);
t->sz_num =
(char *) PhreeqcPtr->PHRQ_calloc((t->n_sz + 1), sizeof(char));
if (t->sz_num == NULL)
PhreeqcPtr->malloc_error();
if (ptr > &inbuf[i - 1])
{
strncpy(t->sz_num, &inbuf[i - 1],
(ptr - &inbuf[i - 1]));
t->sz_num[ptr - &inbuf[i - 1]] = '\0';
}
else
{
t->sz_num[0] = '\0';
}
}
#endif
i += (int) (ptr - &l_inbuf[i - 1]);
}
else
{
t->kind = toksnerr;
t->UU.snch = ch;
}
break;
}
}
}
while (i <= (int) strlen(l_inbuf));
if (q) {
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
_ASSERTE(P_escapecode == 0);
nIDErrPrompt = IDS_ERR_MISSING_Q;
P_escapecode = -20;
return;
}
else
{
char * error_string = PhreeqcPtr->sformatf( " missing \" or \' in BASIC line\n %ld %s", curline, l_inbuf);
error_msg(error_string, STOP);
}
}
if (lp > 0) {
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
_ASSERTE(P_escapecode == 0);
nIDErrPrompt = IDS_ERR_MISSING_RP;
P_escapecode = -20;
return;
}
else
{
char * error_string = PhreeqcPtr->sformatf( " missing ) or ] in BASIC line\n %ld %s", curline, l_inbuf);
error_msg(error_string, STOP);
}
}
else if (lp < 0) {
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
_ASSERTE(P_escapecode == 0);
nIDErrPrompt = IDS_ERR_MISSING_RP;
P_escapecode = -20;
return;
}
else
{
char * error_string = PhreeqcPtr->sformatf( " missing ( or [ in BASIC line\n %ld %s", curline, l_inbuf);
error_msg(error_string, STOP);
}
}
}
#undef toklength
void PBasic::
listtokens(FILE * f, tokenrec * l_buf)
{
bool ltr;
char STR1[256] = {0};
char *string;
ltr = false;
while (l_buf != NULL)
{
if ((l_buf->kind >= (long) toknot && l_buf->kind <= (long) tokrenum) ||
l_buf->kind == (long) toknum || l_buf->kind == (long) tokvar ||
l_buf->kind >= (long) toktc)
{
if (ltr)
/*putc(' ', f); */
output_msg(" ");
ltr = (bool) (l_buf->kind != toknot);
}
else
ltr = false;
switch (l_buf->kind)
{
case tokvar:
/*fputs(l_buf->UU.vp->name, f); */
PhreeqcPtr->output_msg(PhreeqcPtr->sformatf("%s", l_buf->UU.vp->name));
break;
case toknum:
/*fputs(numtostr(STR1, l_buf->UU.num), f); */
string = numtostr(STR1, l_buf->UU.num);
PhreeqcPtr->string_trim(string);
output_msg(PhreeqcPtr->sformatf("%s", string));
break;
case tokstr:
if (strchr(l_buf->UU.sp, '\"'))
{
output_msg(PhreeqcPtr->sformatf("\'%s\'", l_buf->UU.sp));
}
else
{
output_msg(PhreeqcPtr->sformatf("\"%s\"", l_buf->UU.sp));
}
break;
case toksnerr:
output_msg(PhreeqcPtr->sformatf("{%c}", l_buf->UU.snch));
break;
case tokplus:
/*putc('+', f); */
output_msg("+");
break;
case tokminus:
/*putc('-', f); */
output_msg("-");
break;
case toktimes:
/*putc('*', f); */
output_msg("*");
break;
case tokdiv:
/*putc('/', f); */
output_msg("/");
break;
case tokup:
/*putc('^', f); */
output_msg("^");
break;
case toklp:
/*putc('(', f); */
output_msg("(");
break;
case tokrp:
/*putc(')', f); */
output_msg(")");
break;
case tokcomma:
/*putc(',', f); */
output_msg(",");
break;
case toksemi:
/*putc(';', f); */
output_msg(";");
break;
case tokcolon:
output_msg(" : ");
break;
case tokeq:
output_msg(" = ");
break;
case toklt:
output_msg(" < ");
break;
case tokgt:
output_msg(" > ");
break;
case tokle:
output_msg(" <= ");
break;
case tokge:
output_msg(" >= ");
break;
case tokne:
output_msg(" <> ");
break;
case tokand:
output_msg(" AND ");
break;
case tokor:
output_msg(" OR ");
break;
case tokxor:
output_msg(" XOR ");
break;
case tokmod:
output_msg(" MOD ");
break;
case toknot:
output_msg("NOT ");
break;
case toksqr:
output_msg("SQR");
break;
case toksqrt:
output_msg("SQRT");
break;
case toksin:
output_msg("SIN");
break;
case tokcos:
output_msg("COS");
break;
case toktan:
output_msg("TAN");
break;
case tokarctan:
output_msg("ARCTAN");
break;
case toklog:
output_msg("LOG");
break;
case tokexp:
output_msg("EXP");
break;
case tokabs:
output_msg("ABS");
break;
case toksgn:
output_msg("SGN");
break;
case tokstr_:
output_msg("STR$");
break;
case tokval:
output_msg("VAL");
break;
case tokchr_:
output_msg("CHR$");
break;
case tokasc:
output_msg("ASC");
break;
case toklen:
output_msg("LEN");
break;
case tokmid_:
output_msg("MID$");
break;
case tokpeek:
output_msg("PEEK");
break;
case tokrem:
output_msg(PhreeqcPtr->sformatf("REM%s", l_buf->UU.sp));
break;
case toklet:
output_msg("LET");
break;
case tokinput:
output_msg("INPUT");
break;
case tokgoto:
output_msg("GOTO");
break;
case tokif:
output_msg("IF");
break;
case tokend:
output_msg("END");
break;
case tokstop:
output_msg("STOP");
break;
case tokfor:
output_msg("FOR");
break;
case toknext:
output_msg("NEXT");
break;
case tokwhile:
output_msg("WHILE");
break;
case tokwend:
output_msg("WEND");
break;
case tokgosub:
output_msg("GOSUB");
break;
case tokreturn:
output_msg("RETURN");
break;
case tokread:
output_msg("READ");
break;
case tokdata:
output_msg("DATA");
break;
case tokrestore:
output_msg("RESTORE");
break;
case tokgotoxy:
output_msg("GOTOXY");
break;
case tokon:
output_msg("ON");
break;
case tokdim:
output_msg("DIM");
break;
case tokpoke:
output_msg("POKE");
break;
case toklist:
output_msg("LIST");
break;
case tokrun:
output_msg("RUN");
break;
case toknew:
output_msg("NEW");
break;
case tokload:
output_msg("LOAD");
break;
case tokmerge:
output_msg("MERGE");
break;
case tokbye:
output_msg("BYE");
break;
case tokdel:
output_msg("DEL");
break;
case tokrenum:
output_msg("RENUM");
break;
case tokthen:
output_msg(" THEN ");
break;
case tokelse:
output_msg(" ELSE ");
break;
case tokto:
output_msg(" TO ");
break;
case tokstep:
output_msg(" STEP ");
break;
/*
* PHREEQC functions
*/
case tokact:
output_msg("ACT");
break;
case tokadd_heading:
output_msg("ADD_HEADING");
break;
case tokalk:
output_msg("ALK");
break;
case tokaphi:
output_msg("APHI"); // mole volume of a phase
break;
case tokcalc_value:
output_msg("CALC_VALUE");
break;
case tokceil:
output_msg("CEIL");
break;
case tokcell_no:
output_msg("CELL_NO");
break;
case tokchange_por:
output_msg("CHANGE_POR");
break;
case tokchange_surf:
output_msg("CHANGE_SURF");
break;
case tokcharge_balance:
output_msg("CHARGE_BALANCE");
break;
case tokcurrent_a:
output_msg("CURRENT_A");
break;
case tokdebye_length:
output_msg("DEBYE_LENGTH"); // Debye-Hueckel length
break;
case tokdelta_h_phase:
output_msg("DELTA_H_PHASE");
break;
case tokdelta_h_species:
output_msg("DELTA_H_SPECIES");
break;
case tokdescription:
output_msg("DESCRIPTION");
break;
case tokdh_a:
output_msg("DH_A"); // Debye-Hueckel A
break;
case tokdh_a0:
output_msg("DH_A0");
break;
case tokdh_av:
output_msg("DH_Av"); // Debye-Hueckel Av
break;
case tokdh_b:
output_msg("DH_B"); // Debye-Hueckel B
break;
case tokdh_bdot:
output_msg("DH_BDOT");
break;
case tokdiff_c:
output_msg("DIFF_C");
break;
case tokdist:
output_msg("DIST");
break;
case tokedl:
output_msg("EDL");
break;
case tokedl_species:
output_msg("EDL_SPECIES");
break;
case tokeol_:
output_msg("EOL$");
break;
case tokeol_notab_:
output_msg("EOL_NOTAB$");
break;
case tokeps_r:
output_msg("EPS_R"); // dielectric constant
break;
case tokeq_frac:
case tokequiv_frac:
output_msg("EQ_FRAC");
break;
case tokequi:
output_msg("EQUI");
break;
case tokequi_delta:
output_msg("EQUI_DELTA");
break;
case tokerase:
output_msg("ERASE");
break;
case tokexists:
output_msg("EXISTS");
break;
case tokfloor:
output_msg("FLOOR");
break;
case tokgamma:
output_msg("GAMMA");
break;
case tokgas:
output_msg("GAS");
break;
case tokgas_p:
output_msg("GAS_P");
break;
case tokgas_vm:
output_msg("GAS_VM");
break;
case tokget:
output_msg("GET");
break;
case tokget_por:
output_msg("GET_POR");
break;
case tokgfw:
output_msg("GFW"); // gram formula weight of a formula
break;
#if defined MULTICHART
case tokgraph_x:
output_msg("GRAPH_X");
break;
case tokgraph_y:
output_msg("GRAPH_Y");
break;
case tokgraph_sy:
output_msg("GRAPH_SY");
break;
#endif
case tokinstr:
output_msg("INSTR");
break;
case tokiso:
output_msg("ISO");
break;
case tokiso_unit:
output_msg("ISO_UNIT");
break;
case tokiterations:
output_msg("ITERATIONS");
break;
case tokkappa:
output_msg("KAPPA"); // compressibility of pure water, d(rho)/d(P) / rho
break;
case tokkin:
output_msg("KIN");
break;
case tokkin_delta:
output_msg("KIN_DELTA");
break;
case tokkin_time:
output_msg("KIN_TIME");
break;
case tokkinetics_formula:
case tokkinetics_formula_:
output_msg("KINETICS_FORMULA$");
break;
case tokla:
output_msg("LA");
break;
case toklg:
output_msg("LG");
break;
case toklist_s_s:
output_msg("LIST_S_S");
break;
case toklk_named:
output_msg("LK_NAMED");
break;
case toklk_phase:
output_msg("LK_PHASE");
break;
case toklk_species:
output_msg("LK_SPECIES");
break;
case toklm:
output_msg("LM");
break;
case tokltrim:
output_msg("LTRIM");
break;
case tokm:
output_msg("M");
break;
case tokm0:
output_msg("M0");
break;
case tokmcd_jtot:
output_msg("MCD_JTOT");
break;
case tokmcd_jconc:
output_msg("MCD_JCONC");
break;
case tokmisc1:
output_msg("MISC1");
break;
case tokmisc2:
output_msg("MISC2");
break;
case tokmol:
output_msg("MOL");
break;
case tokmu:
output_msg("MU");
break;
case tokno_newline_:
output_msg("NO_NEWLINE$");
break;
case tokosmotic:
output_msg("OSMOTIC");
break;
case tokpad_:
case tokpad:
output_msg("PAD");
break;
case tokparm:
output_msg("PARM");
break;
case tokpercent_error:
output_msg("PERCENT_ERROR");
break;
case tokphase_formula:
case tokphase_formula_:
output_msg("PHASE_FORMULA$");
break;
case tokphase_vm:
output_msg("PHASE_VM"); // mole volume of a phase
break;
#if defined MULTICHART
case tokplot_xy:
output_msg("PLOT_XY");
break;
#endif
case tokpot_v:
output_msg("POT_V");
break;
case tokpr_p:
output_msg("PR_P");
break;
case tokpr_phi:
output_msg("PR_PHI");
break;
case tokpressure:
output_msg("PRESSURE");
break;
case tokprint:
output_msg("PRINT");
break;
case tokpunch:
output_msg("PUNCH");
break;
case tokput:
output_msg("PUT");
break;
case tokqbrn:
output_msg("QBrn"); // Q_Born, d(eps_r)/d(P)/(eps_r^2)
break;
case tokrho:
output_msg("RHO");
break;
case tokrho_0:
output_msg("RHO_0");
break;
case tokrtrim:
output_msg("RTRIM");
break;
case tokrxn:
output_msg("RXN");
break;
case toks_s:
output_msg("S_S");
break;
case toksave:
output_msg("SAVE");
break;
case toksc:
output_msg("SC");
break;
case toksetdiff_c:
output_msg("SETDIFF_C");
break;
case toksi:
output_msg("SI");
case toksim_no:
output_msg("SIM_NO");
break;
case toksim_time:
output_msg("SIM_TIME");
break;
case toksoln_vol:
output_msg("SOLN_VOL"); // volume of solution
break;
case tokspecies_formula:
case tokspecies_formula_:
output_msg("SPECIES_FORMULA$");
break;
case toksr:
output_msg("SR");
break;
case tokstep_no:
output_msg("STEP_NO");
break;
case tokstr_e_:
output_msg("STR_E$");
break;
case tokstr_f_:
output_msg("STR_F$");
break;
case toksum_gas:
output_msg("SUM_GAS");
break;
case toksum_s_s:
output_msg("SUM_s_s");
break;
case toksum_species:
output_msg("SUM_SPECIES");
case toksurf:
output_msg("SURF");
break;
case toksys:
output_msg("SYS");
break;
case tokt_sc:
output_msg("T_SC");
break;
case toktc:
output_msg("TC");
break;
case toktime:
output_msg("TIME");
break;
case toktitle:
output_msg("TITLE");
break;
case toktk:
output_msg("TK");
break;
case toktot:
output_msg("TOT");
break;
case toktotal_time:
output_msg("TOTAL_TIME");
break;
case toktotmole:
case toktotmol:
case toktotmoles:
output_msg("TOTMOLE");
break;
case toktrim:
output_msg("TRIM");
break;
case tokviscos:
output_msg("VISCOS");
break;
case tokviscos_0:
output_msg("VISCOS_0");
break;
case tokvm:
output_msg("VM"); // mole volume of aqueous solute
break;
/*
* End PHREEQC functions
*/
case toksa_declercq: // Undocumented function
output_msg("SA_DECLERCQ");
break;
case tokcallback: // PHAST function
output_msg("CALLBACK");
break;
case tokcell_pore_volume: // PHAST function
case tokporevolume:
output_msg("POREVOLUME");
break;
case tokcell_porosity: // PHAST function
output_msg("CELL_POROSITY");
break;
case tokcell_saturation: // PHAST function
output_msg("CELL_SATURATION");
break;
case tokcell_volume: // PHAST function
output_msg("CELL_VOLUME");
break;
case toktransport_cell_no: // PHAST function
output_msg("TRANSPORT_CELL_NO");
break;
case tokvelocity_x: // PHAST function
output_msg("VELOCITY_X");
break;
case tokvelocity_y: // PHAST function
output_msg("VELOCITY_Y");
break;
case tokvelocity_z: // PHAST function
output_msg("VELOCITY_Z");
break;
case toklog10:
output_msg("LOG10");
break;;
}
l_buf = l_buf->next;
}
}
void PBasic::
disposetokens(tokenrec ** tok)
{
tokenrec *tok1;
while (*tok != NULL)
{
tok1 = (*tok)->next;
if (phreeqci_gui)
{
if ((*tok)->kind == (long) toknum)
{
PhreeqcPtr->PHRQ_free((*tok)->sz_num);
}
#ifdef _DEBUG
else
{
_ASSERTE((*tok)->sz_num == NULL);
}
#endif /* _DEBUG */
}
if ((*tok)->kind == (long) tokrem || (*tok)->kind == (long) tokstr)
{
(*tok)->UU.sp = (char *) PhreeqcPtr->free_check_null((*tok)->UU.sp);
}
*tok = (tokenrec *) PhreeqcPtr->free_check_null(*tok);
*tok = tok1;
}
}
void PBasic::
parseinput(tokenrec ** l_buf)
{
linerec *l, *l0, *l1;
while (PhreeqcPtr->replace("\t", " ", inbuf));
while (PhreeqcPtr->replace("\r", " ", inbuf));
PhreeqcPtr->string_trim(inbuf);
curline = 0;
while (*inbuf != '\0' && isdigit((int) inbuf[0]))
{
curline = curline * 10 + inbuf[0] - 48;
memmove(inbuf, inbuf + 1, strlen(inbuf));
}
parse(inbuf, l_buf);
if (curline == 0)
return;
l = linebase;
l0 = NULL;
while (l != NULL && l->num < curline)
{
l0 = l;
l = l->next;
}
if (l != NULL && l->num == curline)
{
l1 = l;
l = l->next;
if (l0 == NULL)
linebase = l;
else
l0->next = l;
disposetokens(&l1->txt);
PhreeqcPtr->PHRQ_free(l1);
}
if (*l_buf != NULL)
{
l1 = (linerec *) PhreeqcPtr->PHRQ_calloc(1, sizeof(linerec));
if (l1 == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
l1->next = l;
if (l0 == NULL)
linebase = l1;
else
l0->next = l1;
l1->num = curline;
l1->txt = *l_buf;
strncpy(l1->inbuf, inbuf, MAX_LINE);
l1->inbuf[MAX_LINE-1] = '\0';
}
clearloops();
restoredata();
}
void PBasic::
errormsg(const char * l_s)
{
if (phreeqci_gui)
{
/* set nIDErrPrompt before calling errormsg see snerr */
_ASSERTE(nIDErrPrompt != 0);
}
else
{
error_msg(l_s, CONTINUE);
}
_Escape(42);
}
void PBasic::
snerr(const char * l_s)
{
char str[MAX_LENGTH] = {0};
strcpy(str, "Syntax_error ");
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_SYNTAX;
}
strcat(str, l_s);
strcat(str, " in line: ");
if (strcmp(inbuf, "run"))
strcat(str, inbuf);
errormsg(str);
}
void PBasic::
tmerr(const char * l_s)
{
char str[MAX_LENGTH] = {0};
strcpy(str, "Type mismatch error");
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_MISMATCH;
}
strcat(str, l_s);
strcat(str, " in line: ");
if (strcmp(inbuf, "run"))
strcat(str, inbuf);
errormsg(str);
}
void PBasic::
badsubscr(void)
{
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_BAD_SUBSCRIPT;
}
errormsg("Bad subscript");
}
LDBLE PBasic::
realfactor(struct LOC_exec *LINK)
{
valrec n;
n = factor(LINK);
if (n.stringval)
tmerr(": found characters, not a number");
return (n.UU.val);
}
char * PBasic::
strfactor(struct LOC_exec * LINK)
{
valrec n;
n = factor(LINK);
if (!n.stringval)
//tmerr(": chemical name is not enclosed in \" \"" );
tmerr(": Expected quoted string or character variable." );
return (n.UU.sval);
}
char * PBasic::
stringfactor(char * Result, struct LOC_exec * LINK)
{
valrec n;
n = factor(LINK);
if (!n.stringval)
//tmerr(": chemical name is not enclosed in \" \"" );
tmerr(": Expected quoted string or character variable." );
strcpy(Result, n.UU.sval);
PhreeqcPtr->PHRQ_free(n.UU.sval);
return Result;
}
const char * PBasic::
stringfactor(std::string & Result, struct LOC_exec * LINK)
{
valrec n;
n = factor(LINK);
if (!n.stringval)
//tmerr(": chemical name is not enclosed in \" \"" );
tmerr(": Expected quoted string or character variable." );
Result = n.UU.sval;
PhreeqcPtr->PHRQ_free(n.UU.sval);
return Result.c_str();
}
long PBasic::
intfactor(struct LOC_exec *LINK)
{
return ((long) floor(realfactor(LINK) + 0.5));
}
LDBLE PBasic::
realexpr(struct LOC_exec *LINK)
{
valrec n;
n = expr(LINK);
if (n.stringval)
tmerr(": found characters, not a number");
return (n.UU.val);
}
char * PBasic::
strexpr(struct LOC_exec * LINK)
{
valrec n;
n = expr(LINK);
if (!n.stringval)
//tmerr(": chemical name is not enclosed in \" \"" );
tmerr(": Expected quoted string or character variable." );
return (n.UU.sval);
}
char * PBasic::
stringexpr(char * Result, struct LOC_exec * LINK)
{
valrec n;
n = expr(LINK);
if (!n.stringval)
//tmerr(": chemical name is not enclosed in \" \"" );
tmerr(": Expected quoted string or character variable." );
strcpy(Result, n.UU.sval);
PhreeqcPtr->PHRQ_free(n.UU.sval);
return Result;
}
long PBasic::
intexpr(struct LOC_exec *LINK)
{
return ((long) floor(realexpr(LINK) + 0.5));
}
void PBasic::
require(int k, struct LOC_exec *LINK)
{
char str[MAX_LENGTH] = {0};
if (LINK->t == NULL || LINK->t->kind != k)
{
std::map<const std::string, BASIC_TOKEN>::const_iterator item;
for (item = command_tokens.begin(); item != command_tokens.end(); item++)
{
if (item->second == k)
break;
}
if (item == command_tokens.end())
snerr(": missing unknown command");
else {
strcpy(str, ": missing ");
snerr(strcat(str, item->first.c_str()));
}
#if !defined(R_SO)
exit(4);
#endif
}
LINK->t = LINK->t->next;
}
void PBasic::
skipparen(struct LOC_exec *LINK)
{
do
{
if (LINK->t == NULL)
{
snerr(": parenthesis missing");
#if !defined(R_SO)
exit(4);
#endif
}
if (LINK->t->kind == tokrp || LINK->t->kind == tokcomma)
goto _L1;
if (LINK->t->kind == toklp)
{
LINK->t = LINK->t->next;
skipparen(LINK);
}
LINK->t = LINK->t->next;
}
while (true);
_L1:;
}
varrec * PBasic::
findvar(struct LOC_exec *LINK)
{
varrec *v;
long i, j, k;
tokenrec *tok;
long FORLIM;
if (LINK->t == NULL || LINK->t->kind != tokvar)
{
snerr(": can`t find variable");
#if !defined(R_SO)
exit(4);
#endif
}
v = LINK->t->UU.vp;
LINK->t = LINK->t->next;
if (LINK->t == NULL || LINK->t->kind != toklp)
{
if (v->numdims != 0)
badsubscr();
return v;
}
if (v->numdims == 0)
{
tok = LINK->t;
i = 0;
j = 1;
do
{
if (i >= maxdims)
badsubscr();
LINK->t = LINK->t->next;
skipparen(LINK);
j *= 11;
i++;
v->dims[i - 1] = 11;
}
while (LINK->t->kind != tokrp);
v->numdims = (char) i;
if (v->stringvar)
{
v->UU.U1.sarr = (char **) PhreeqcPtr->PHRQ_malloc(j * sizeof(char *));
if (v->UU.U1.sarr == NULL)
PhreeqcPtr->malloc_error();
for (k = 0; k < j; k++)
v->UU.U1.sarr[k] = NULL;
}
else
{
v->UU.U0.arr = (LDBLE *) PhreeqcPtr->PHRQ_malloc(j * sizeof(LDBLE));
if (v->UU.U0.arr == NULL)
PhreeqcPtr->malloc_error();
for (k = 0; k < j; k++)
v->UU.U0.arr[k] = 0.0;
}
LINK->t = tok;
}
k = 0;
LINK->t = LINK->t->next;
FORLIM = v->numdims;
for (i = 1; i <= FORLIM; i++)
{
j = intexpr(LINK);
if ((unsigned long) j >= (unsigned long) v->dims[i - 1])
badsubscr();
k = k * v->dims[i - 1] + j;
if (i < v->numdims)
require(tokcomma, LINK);
}
require(tokrp, LINK);
if (v->stringvar)
v->UU.U1.sval = &v->UU.U1.sarr[k];
else
v->UU.U0.val = &v->UU.U0.arr[k];
return v;
}
valrec PBasic::
factor(struct LOC_exec * LINK)
{
char string[MAX_LENGTH] = {0};
cxxSolution *soln_ptr;
varrec *v;
tokenrec *facttok;
valrec n;
long i, j, m;
tokenrec *tok, *tok1;
char *l_s;
LDBLE l_dummy;
int i_rate;
union
{
long i;
char *c;
} trick;
LDBLE TEMP;
std::string STR1, STR2;
const char *elt_name, *surface_name, *mytemplate, *name;
varrec *count_varrec = NULL, *names_varrec = NULL, *types_varrec =
NULL, *moles_varrec = NULL;
char **names_arg, **types_arg;
LDBLE *moles_arg;
int arg_num;
LDBLE count_species;
const char *string1, *string2;
if (LINK->t == NULL)
snerr(": missing variable or command");
facttok = LINK->t;
LINK->t = LINK->t->next;
n.stringval = false;
switch (facttok->kind)
{
case toknum:
n.UU.val = facttok->UU.num;
break;
case tokstr:
n.stringval = true;
m = (int)strlen(facttok->UU.sp) + 1;
if (m < 256)
m = 256;
n.UU.sval = (char*)PhreeqcPtr->PHRQ_calloc(m, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
strcpy(n.UU.sval, facttok->UU.sp);
break;
case tokvar:
LINK->t = facttok;
v = findvar(LINK);
n.stringval = v->stringvar;
if (n.stringval)
{
if (*v->UU.U1.sval != NULL)
{
m = (int)strlen(*v->UU.U1.sval) + 1;
if (m < 256)
m = 256;
}
else
{
m = 256;
}
n.UU.sval = (char*)PhreeqcPtr->PHRQ_calloc(m, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
if (*v->UU.U1.sval != NULL)
{
strcpy(n.UU.sval, *v->UU.U1.sval);
}
}
else
n.UU.val = *v->UU.U0.val;
break;
case toklp:
n = expr(LINK);
require(tokrp, LINK);
break;
case tokminus:
n.UU.val = -realfactor(LINK);
break;
case tokplus:
{
n.UU.val = realfactor(LINK);
}
break;
case toknot:
{
n.UU.val = ~intfactor(LINK);
}
break;
case toksqr:
{
TEMP = realfactor(LINK);
n.UU.val = TEMP * TEMP;
}
break;
case toksqrt:
{
n.UU.val = sqrt(realfactor(LINK));
}
break;
/*
* PHREEQC functions=============================================
*/
case tokact:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->activity(str);
}
break;
case tokadd_heading:
{
require(toklp, LINK);
name = strexpr(LINK);
require(tokrp, LINK);
if (PhreeqcPtr->current_user_punch != NULL)
{
PhreeqcPtr->current_user_punch->Get_headings().push_back(name);
n.UU.val = (parse_all) ? 1 : (double)PhreeqcPtr->current_user_punch->Get_headings().size();
}
else {
n.UU.val = 0;
}
name = (char*)PhreeqcPtr->free_check_null((void*) name);
}
break;
case tokalk:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->total_alkalinity / PhreeqcPtr->mass_water_aq_x;
}
break;
case tokaphi:
{
n.UU.val = PhreeqcPtr->A0;
}
break;
case tokcalc_value:
{
require(toklp, LINK);
name = stringfactor(STR1, LINK);
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->get_calculate_value(name);
}
break;
case tokceil:
{
n.UU.val = ceil(realfactor(LINK));
}
break;
case tokcell_no:
{
if (parse_all)
{
n.UU.val = 1;
break;
}
n.UU.val = PhreeqcPtr->solution_number();
}
break;
case tokcharge_balance:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->cb_x;
}
break;
case tokcurrent_a:
{
//n.UU.val = (parse_all) ? 1 : PhreeqcPtr->current_x;
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->current_A;
}
break;
case tokdebye_length:
{
double debye_length = (PhreeqcPtr->eps_r * EPSILON_ZERO * R_KJ_DEG_MOL * 1000.0 * PhreeqcPtr->tk_x)
/ (2. * F_C_MOL * F_C_MOL * PhreeqcPtr->mu_x * 1000.);
n.UU.val = sqrt(debye_length);
}
break;
case tokdelta_h_phase:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_deltah_p(str);
}
break;
case tokdelta_h_species:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_deltah_s(str);
}
break;
case tokdescription:
{
n.stringval = true;
if (PhreeqcPtr->state == REACTION)
{
if (PhreeqcPtr->use.Get_mix_in())
{
sprintf(string, "Mix %d", PhreeqcPtr->use.Get_n_mix_user());
n.UU.sval = PhreeqcPtr->string_duplicate(string);
}
else
{
soln_ptr = Utilities::Rxn_find(PhreeqcPtr->Rxn_solution_map,
PhreeqcPtr->use.Get_n_solution_user());
if (soln_ptr != NULL)
{
n.UU.sval = PhreeqcPtr->string_duplicate(soln_ptr->Get_description().c_str());
}
else
{
n.UU.sval = PhreeqcPtr->string_duplicate("Unknown");
}
}
}
else if (PhreeqcPtr->state == ADVECTION || PhreeqcPtr->state == TRANSPORT || PhreeqcPtr->state == PHAST)
{
sprintf(string, "Cell %d", PhreeqcPtr->cell_no);
n.UU.sval = PhreeqcPtr->string_duplicate(string);
}
else
{
if (PhreeqcPtr->use.Get_solution_ptr() != NULL)
{
n.UU.sval = PhreeqcPtr->string_duplicate(PhreeqcPtr->use.Get_solution_ptr()->Get_description().c_str());
}
else
{
n.UU.sval = PhreeqcPtr->string_duplicate("Unknown");
}
}
while (PhreeqcPtr->replace("\t", " ", n.UU.sval));
}
break;
case tokdh_a:
{
if (PhreeqcPtr->llnl_temp.size() > 0)
{
n.UU.val = PhreeqcPtr->a_llnl;
}
else
{
n.UU.val = PhreeqcPtr->DH_A;
}
}
break;
case tokdh_a0:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->dh_a0(str);
}
break;
case tokdh_av:
{
n.UU.val = PhreeqcPtr->DH_Av;
}
break;
case tokdh_b:
{
if (PhreeqcPtr->llnl_temp.size() > 0)
{
n.UU.val = PhreeqcPtr->b_llnl;
}
else
{
n.UU.val = PhreeqcPtr->DH_B;
}
}
break;
case tokdh_bdot:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->dh_bdot(str);
}
break;
case tokdiff_c:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->diff_c(str);
}
break;
case tokdist:
{
if (PhreeqcPtr->state == PHAST)
{
n.UU.val = 0;
}
else if (PhreeqcPtr->state == TRANSPORT)
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->cell_data[PhreeqcPtr->cell].mid_cell_x;
}
else if (PhreeqcPtr->state == ADVECTION)
{
n.UU.val = (parse_all) ? 1 : (LDBLE)PhreeqcPtr->use.Get_n_solution_user();
}
else
{
n.UU.val = 0;
}
}
break;
case tokedl:
{
require(toklp, LINK);
elt_name = stringfactor(STR1, LINK);
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
surface_name = stringfactor(STR2, LINK);
}
else
{
surface_name = NULL;
}
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->diff_layer_total(elt_name, surface_name);
}
break;
case tokedl_species:
{
double area = 0.0, thickness = 0.0;
require(toklp, LINK);
const char* surf_name = stringfactor(STR1, LINK);
require(tokcomma, LINK);
// variable for number of species
count_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || !count_varrec || count_varrec->stringvar != 0)
{
snerr(": Missing or wrong type count variable.");
#if !defined(R_SO)
exit(4);
#endif
}
// variable for species names
LINK->t = LINK->t->next;
require(tokcomma, LINK);
names_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || !names_varrec || names_varrec->stringvar != 1)
{
snerr(": Missing or wrong type name variable.");
#if !defined(R_SO)
exit(4);
#endif
}
// variable for species concentrations
LINK->t = LINK->t->next;
require(tokcomma, LINK);
moles_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || moles_varrec->stringvar != 0)
snerr(": Missing or wrong type moles variable.");
// variable for area
LINK->t = LINK->t->next;
require(tokcomma, LINK);
varrec* area_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || area_varrec->stringvar != 0)
snerr(": Missing or wrong type area varaiable.");
// varaiable for thickness
LINK->t = LINK->t->next;
require(tokcomma, LINK);
varrec* thickness_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || thickness_varrec->stringvar != 0)
snerr(": Missing or wrong type thickness variable.");
LINK->t = LINK->t->next;
require(tokrp, LINK);
free_dim_stringvar(names_varrec);
PhreeqcPtr->free_check_null(moles_varrec->UU.U0.arr);
moles_varrec->UU.U0.arr = NULL;
// Call subroutine
if (parse_all)
{
PhreeqcPtr->sys_tot = 0;
//PhreeqcPtr->count_sys = 1000;
//int count_sys = PhreeqcPtr->count_sys;
size_t count_sys = 1000;
names_arg = (char**)PhreeqcPtr->PHRQ_calloc((count_sys + 1), sizeof(char*));
if (names_arg == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
moles_arg = (LDBLE*)PhreeqcPtr->PHRQ_calloc((count_sys + 1), sizeof(LDBLE));
if (moles_arg == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
names_arg[0] = NULL;
moles_arg[0] = 0;
count_species = (LDBLE)count_sys;
n.UU.val = 0;
}
else
{
//n.UU.val = PhreeqcPtr->system_total(elt_name, &count_species, &(names_arg),
// &(types_arg), &(moles_arg));
n.UU.val = PhreeqcPtr->edl_species(surf_name, &count_species, &(names_arg), &(moles_arg), &area, &thickness);
}
/*
* fill in varrec structures
*/
*count_varrec->UU.U0.val = count_species;
names_varrec->UU.U1.sarr = names_arg;
moles_varrec->UU.U0.arr = moles_arg;
*area_varrec->UU.U0.val = area;
*thickness_varrec->UU.U0.val = thickness;
for (i = 0; i < maxdims; i++)
{
names_varrec->dims[i] = 0;
moles_varrec->dims[i] = 0;
}
names_varrec->dims[0] = (long)(*count_varrec->UU.U0.val) + 1;
moles_varrec->dims[0] = (long)(*count_varrec->UU.U0.val) + 1;
names_varrec->numdims = 1;
moles_varrec->numdims = 1;
}
break;
case tokeol_:
{
n.stringval = true;
n.UU.sval = (char*)PhreeqcPtr->PHRQ_calloc(256, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
strcpy(n.UU.sval, "\n");
}
break;
case tokeol_notab_:
{
n.stringval = true;
n.UU.sval = (char*)PhreeqcPtr->PHRQ_calloc(256, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
strcpy(n.UU.sval, "\n");
punch_tab = false;
}
break;
case tokeps_r:
{
n.UU.val = PhreeqcPtr->eps_r;
}
break;
case tokeq_frac:
case tokequiv_frac:
{
// left parenthesis
require(toklp, LINK);
// species name
std::string species_name(stringfactor(STR1, LINK));
require(tokcomma, LINK);
// equivalents
count_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || count_varrec->stringvar != 0)
snerr(": Cannot find equivalents variable");
LINK->t = LINK->t->next;
require(tokcomma, LINK);
// exchange or surface element
varrec* elt_varrec = NULL;
elt_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || elt_varrec->stringvar != 1)
snerr(": Cannot find element string variable");
free_dim_stringvar(elt_varrec);
*elt_varrec->UU.U1.sval = (char*)PhreeqcPtr->free_check_null(*elt_varrec->UU.U1.sval);
// right parenthesis
LINK->t = LINK->t->next;
require(tokrp, LINK);
// set function value
LDBLE eq;
std::string elt_name;
// return equivalent fraction
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->equivalent_fraction(species_name.c_str(), &eq, elt_name);
// set equivalents
*count_varrec->UU.U0.val = (parse_all) ? 1 : eq;
// set element name
size_t l = elt_name.size();
l = l < 256 ? 256 : l + 1;
char* token = (char*)PhreeqcPtr->PHRQ_malloc(l * sizeof(char));
strcpy(token, elt_name.c_str());
*elt_varrec->UU.U1.sval = token;
}
break;
case tokequi:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->equi_phase(str);
}
break;
case tokequi_delta:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->equi_phase_delta(str);
}
break;
case tokexists:
{
std::ostringstream oss;
require(toklp, LINK);
/* get first subscript */
if (LINK->t != NULL && LINK->t->kind != tokrp)
{
i = intexpr(LINK);
oss << i << ",";
}
/* get other subscripts */
for (;;)
{
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
j = intexpr(LINK);
oss << j << ",";
}
else
{
/* get right parentheses */
require(tokrp, LINK);
break;
}
}
if (parse_all)
{
n.UU.val = 1;
}
else
{
std::map<std::string, double>::iterator it = PhreeqcPtr->save_values.find(oss.str());
n.UU.val = (it == PhreeqcPtr->save_values.end()) ? 0 : 1;
}
}
break;
case tokfloor:
{
n.UU.val = floor(realfactor(LINK));
}
break;
case tokmcd_jtot:
{
double f = 0.0;
const char* str = stringfactor(STR1, LINK);
if (PhreeqcPtr->state == TRANSPORT && PhreeqcPtr->multi_Dflag)
{
f = PhreeqcPtr->flux_mcd(str, 1);
}
n.UU.val = (parse_all) ? 1 : f;
}
break;
case tokmcd_jconc:
{
double f = 0.0;
const char* str = stringfactor(STR1, LINK);
if (PhreeqcPtr->state == TRANSPORT && PhreeqcPtr->multi_Dflag)
{
f = PhreeqcPtr->flux_mcd(str, 2);
}
n.UU.val = (parse_all) ? 1 : f;
}
break;
case tokgamma:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->activity_coefficient(str);
}
break;
case tokgas:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->find_gas_comp(str);
}
break;
case tokgas_p:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->find_gas_p();
}
break;
case tokgas_vm:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->find_gas_vm();
}
break;
case tokget:
{
std::ostringstream oss;
require(toklp, LINK);
/* get first subscript */
if (LINK->t != NULL && LINK->t->kind != tokrp)
{
i = intexpr(LINK);
oss << i << ",";
}
/* get other subscripts */
for (;;)
{
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
j = intexpr(LINK);
oss << j << ",";
}
else
{
/* get right parentheses */
require(tokrp, LINK);
break;
}
}
if (parse_all)
{
n.UU.val = 1;
}
else
{
std::map<std::string, double>::iterator it = PhreeqcPtr->save_values.find(oss.str());
n.UU.val = (it == PhreeqcPtr->save_values.end()) ? 0 : it->second;
}
break;
}
case tokget_por:
{
i = intfactor(LINK);
if (parse_all)
{
n.UU.val = 1;
}
else
{
if (PhreeqcPtr->phast != TRUE)
{
if (i <= 0 || i > PhreeqcPtr->count_cells * (1 + PhreeqcPtr->stag_data.count_stag) + 1
|| i == PhreeqcPtr->count_cells + 1)
{
/* warning_msg("Note... no porosity for boundary solutions."); */
n.UU.val = 0;
break;
}
else
n.UU.val = PhreeqcPtr->cell_data[i].por;
break;
}
else
{
n.UU.val = PhreeqcPtr->cell_porosity;
break;
}
}
}
break;
case tokgfw:
{
const char* str = stringfactor(STR1, LINK);
LDBLE gfw;
PhreeqcPtr->compute_gfw(str, &gfw);
n.UU.val = (parse_all) ? 1 : gfw;
}
break;
case tokinstr:
{
require(toklp, LINK);
string1 = stringfactor(STR1, LINK);
require(tokcomma, LINK);
string2 = stringfactor(STR2, LINK);
require(tokrp, LINK);
{
const char* cptr = strstr(string1, string2);
if (cptr == NULL)
{
n.UU.val = 0;
}
else
{
n.UU.val = ((LDBLE)(cptr - string1)) + 1;
}
}
}
break;
case tokiso:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->iso_value(str);
}
break;
case tokiso_unit:
{
n.stringval = true;
require(toklp, LINK);
string1 = stringfactor(STR1, LINK);
require(tokrp, LINK);
trim(STR1);
n.UU.sval = (parse_all) ? PhreeqcPtr->string_duplicate("unknown") : PhreeqcPtr->iso_unit(STR1.c_str());
}
break;
case tokiterations:
{
n.UU.val = (parse_all) ? 0 : PhreeqcPtr->overall_iterations;
}
break;
case tokkappa:
{
n.UU.val = PhreeqcPtr->kappa_0;
}
break;
case tokkin:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->kinetics_moles(str);
}
break;
case tokkin_delta:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->kinetics_moles_delta(str);
}
break;
case tokkin_time:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->rate_kin_time;
}
break;
case tokkinetics_formula:
case tokkinetics_formula_:
{
require(toklp, LINK);
std::string kinetics_name(stringfactor(STR1, LINK));
varrec* elts_varrec = NULL, * coef_varrec = NULL;
cxxNameDouble stoichiometry;
/*
* Parse arguments
*/
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
/* kinetics_formula("calcite", count, elt, coef) */
/* return formula */
/*int c; */
/* struct varrec *count_varrec, *names_varrec, *types_varrec, *moles_varrec; */
/* struct varrec *count_varrec, *elt_varrec, *coef_varrec; */
/* return number of species */
LINK->t = LINK->t->next;
count_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || count_varrec->stringvar != 0)
snerr(": Cannot find count variable");
/* return number of names of elements */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
elts_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || elts_varrec->stringvar != 1)
snerr(": Cannot find element string variable");
/* return coefficients of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
coef_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || coef_varrec->stringvar != 0)
snerr(": Cannot find coefficient variable");
LINK->t = LINK->t->next;
arg_num = 4;
}
else
{
arg_num = 1;
}
require(tokrp, LINK);
if (arg_num > 1)
{
free_dim_stringvar(elts_varrec);
PhreeqcPtr->free_check_null(coef_varrec->UU.U0.arr);
coef_varrec->UU.U0.arr = NULL;
}
/*
* Call subroutine
*/
std::string form = PhreeqcPtr->kinetics_formula(kinetics_name, stoichiometry);
// put formula as return value
n.stringval = true;
n.UU.sval = PhreeqcPtr->string_duplicate(form.c_str());
/*
* fill in varrec structure
*/
if (arg_num > 1)
{
size_t count = stoichiometry.size();
*count_varrec->UU.U0.val = (LDBLE)count;
/*
* malloc space
*/
elts_varrec->UU.U1.sarr = (char**)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(char*));
if (elts_varrec->UU.U1.sarr == NULL)
PhreeqcPtr->malloc_error();
coef_varrec->UU.U0.arr = (LDBLE*)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(LDBLE));
if (coef_varrec->UU.U0.arr == NULL)
PhreeqcPtr->malloc_error();
// first position not used
elts_varrec->UU.U1.sarr[0] = NULL;
coef_varrec->UU.U0.arr[0] = 0;
// set dims for Basic array
for (i = 0; i < maxdims; i++)
{
elts_varrec->dims[i] = 0;
coef_varrec->dims[i] = 0;
}
// set dims for first dimension and number of dims
elts_varrec->dims[0] = (long)(count + 1);
coef_varrec->dims[0] = (long)(count + 1);
elts_varrec->numdims = 1;
coef_varrec->numdims = 1;
// fill in arrays
i = 1;
for (cxxNameDouble::iterator it = stoichiometry.begin(); it != stoichiometry.end(); it++)
{
elts_varrec->UU.U1.sarr[i] = PhreeqcPtr->string_duplicate((it->first).c_str());
coef_varrec->UU.U0.arr[i] = it->second;
i++;
}
}
}
break;
case tokla:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->log_activity(str);
}
break;
case toklg:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->log_activity_coefficient(str);
}
break;
case toklist_s_s:
{
/* list_s_s("calcite", count, name$, moles) */
/* return total moles */
require(toklp, LINK);
std::string s_s_name(stringfactor(STR1, LINK));
cxxNameDouble composition;
/*
* Parse arguments
*/
arg_num = -1;
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
count_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || count_varrec->stringvar != 0)
snerr(": Cannot find count variable");
/* return number of names of components */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
names_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || names_varrec->stringvar != 1)
snerr(": Cannot find component string variable");
/* return number of moles of components */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
moles_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || moles_varrec->stringvar != 0)
snerr(": Cannot find moles of component variable");
LINK->t = LINK->t->next;
arg_num = 4;
}
else
{
snerr(": Expected 4 arguments for list_s_s");
#if !defined(R_SO)
exit(4);
#endif
}
require(tokrp, LINK);
if (arg_num > 1)
{
free_dim_stringvar(names_varrec);
if (moles_varrec)
{
PhreeqcPtr->free_check_null(moles_varrec->UU.U0.arr);
moles_varrec->UU.U0.arr = NULL;
}
}
/*
* Call subroutine
*/
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->list_ss(s_s_name, composition);
/*
* fill in varrec structure
*/
if (arg_num > 1)
{
size_t count = composition.size();
*count_varrec->UU.U0.val = (LDBLE)count;
/*
* malloc space
*/
names_varrec->UU.U1.sarr = (char**)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(char*));
if (names_varrec->UU.U1.sarr == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
moles_varrec->UU.U0.arr = (LDBLE*)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(LDBLE));
if (moles_varrec->UU.U0.arr == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
// first position not used
names_varrec->UU.U1.sarr[0] = NULL;
moles_varrec->UU.U0.arr[0] = 0;
// set dims for Basic array
for (i = 0; i < maxdims; i++)
{
names_varrec->dims[i] = 0;
moles_varrec->dims[i] = 0;
}
// set dims for first dimension and number of dims
names_varrec->dims[0] = (long)(count + 1);
moles_varrec->dims[0] = (long)(count + 1);
names_varrec->numdims = 1;
moles_varrec->numdims = 1;
// fill in arrays
i = 1;
std::vector< std::pair<std::string, LDBLE> > sort_comp = composition.sort_second();
size_t j;
for (j = 0; j != sort_comp.size(); j++)
{
names_varrec->UU.U1.sarr[i] = PhreeqcPtr->string_duplicate(sort_comp[j].first.c_str());
moles_varrec->UU.U0.arr[i] = sort_comp[j].second;
i++;
}
}
}
break;
case toklk_named:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_logk_n(str);
}
break;
case toklk_phase:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_logk_p(str);
}
break;
case toklk_species:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_logk_s(str);
}
break;
case toklm:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->log_molality(str);
}
break;
case tokltrim:
{
n.stringval = true;
require(toklp, LINK);
string1 = stringfactor(STR1, LINK);
require(tokrp, LINK);
trim_left(STR1);
n.UU.sval = PhreeqcPtr->string_duplicate(STR1.c_str());
}
break;
case tokm:
{
n.UU.val = PhreeqcPtr->rate_m;
}
break;
case tokm0:
{
n.UU.val = PhreeqcPtr->rate_m0;
}
break;
case tokmisc1:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->find_misc1(str);
}
break;
case tokmisc2:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->find_misc2(str);
}
break;
case tokmol:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->molality(str);
}
break;
case tokmu:
{
n.UU.val = PhreeqcPtr->mu_x;
}
break;
case tokno_newline_:
{
n.stringval = true;
PhreeqcPtr->Set_output_newline(false);
this->skip_punch = true;
}
break;
case tokosmotic:
{
if (PhreeqcPtr->pitzer_model == TRUE || PhreeqcPtr->sit_model == TRUE)
{
n.UU.val = PhreeqcPtr->COSMOT;
}
else
{
n.UU.val = 0.0;
}
}
break;
case tokpad_:
case tokpad:
{
n.stringval = true;
require(toklp, LINK);
string1 = stringfactor(STR1, LINK);
require(tokcomma, LINK);
i = intexpr(LINK);
require(tokrp, LINK);
n.UU.sval = PhreeqcPtr->string_pad(string1, i);
}
break;
case tokparm:
{
i_rate = intfactor(LINK);
if (parse_all)
{
n.UU.val = 1;
}
else
{
if (i_rate > PhreeqcPtr->count_rate_p || i_rate == 0)
{
errormsg("Parameter subscript out of range.");
}
n.UU.val = PhreeqcPtr->rate_p[(size_t)i_rate - 1];
}
}
break;
case tokpercent_error:
{
n.UU.val = (parse_all) ? 1 : 100 * PhreeqcPtr->cb_x / PhreeqcPtr->total_ions_x;
}
break;
case tokphase_formula:
case tokphase_formula_:
{
require(toklp, LINK);
std::string phase_name(stringfactor(STR1, LINK));
varrec* elts_varrec = NULL, * coef_varrec = NULL;
cxxNameDouble stoichiometry;
/*
* Parse arguments
*/
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
/* phase_formula("calcite", count, elt, coef) */
/* return formula */
/*int c; */
/* struct varrec *count_varrec, *names_varrec, *types_varrec, *moles_varrec; */
/* struct varrec *count_varrec, *elt_varrec, *coef_varrec; */
/* return number of species */
LINK->t = LINK->t->next;
count_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || count_varrec->stringvar != 0)
snerr(": Cannot find count variable");
/* return number of names of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
elts_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || elts_varrec->stringvar != 1)
snerr(": Cannot find element string variable");
/* return coefficients of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
coef_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || coef_varrec->stringvar != 0)
snerr(": Cannot find coefficient variable");
LINK->t = LINK->t->next;
arg_num = 4;
}
else
{
arg_num = 1;
}
require(tokrp, LINK);
if (arg_num > 1)
{
free_dim_stringvar(elts_varrec);
PhreeqcPtr->free_check_null(coef_varrec->UU.U0.arr);
coef_varrec->UU.U0.arr = NULL;
}
/*
* Call subroutine
*/
std::string form = PhreeqcPtr->phase_formula(phase_name, stoichiometry);
// put formula as return value
n.stringval = true;
n.UU.sval = PhreeqcPtr->string_duplicate(form.c_str());
/*
* fill in varrec structure
*/
if (arg_num > 1)
{
size_t count = stoichiometry.size();
*count_varrec->UU.U0.val = (LDBLE)count;
/*
* malloc space
*/
elts_varrec->UU.U1.sarr = (char**)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(char*));
if (elts_varrec->UU.U1.sarr == NULL)
PhreeqcPtr->malloc_error();
coef_varrec->UU.U0.arr = (LDBLE*)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(LDBLE));
if (coef_varrec->UU.U0.arr == NULL)
PhreeqcPtr->malloc_error();
// first position not used
elts_varrec->UU.U1.sarr[0] = NULL;
coef_varrec->UU.U0.arr[0] = 0;
// set dims for Basic array
for (i = 0; i < maxdims; i++)
{
elts_varrec->dims[i] = 0;
coef_varrec->dims[i] = 0;
}
// set dims for first dimension and number of dims
elts_varrec->dims[0] = (long)(count + 1);
coef_varrec->dims[0] = (long)(count + 1);
elts_varrec->numdims = 1;
coef_varrec->numdims = 1;
// fill in arrays
i = 1;
for (cxxNameDouble::iterator it = stoichiometry.begin(); it != stoichiometry.end(); it++)
{
elts_varrec->UU.U1.sarr[i] = PhreeqcPtr->string_duplicate((it->first).c_str());
coef_varrec->UU.U0.arr[i] = it->second;
i++;
}
}
}
break;
case tokphase_vm:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->phase_vm(str);
}
break;
case tokpot_v:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->use.Get_solution_ptr()->Get_potV();
}
break;
case tokpr_p:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->pr_pressure(stringfactor(STR1, LINK));
}
break;
case tokpr_phi:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->pr_phi(stringfactor(STR1, LINK));
}
break;
case tokpressure:
{
n.UU.val = PhreeqcPtr->pressure();
}
break;
case tokqbrn:
{
n.UU.val = PhreeqcPtr->QBrn;
}
break;
case tokrho:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_dens();
}
break;
case tokrho_0:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->rho_0;
}
break;
case tokrtrim:
{
n.stringval = true;
require(toklp, LINK);
string1 = stringfactor(STR1, LINK);
require(tokrp, LINK);
trim_right(STR1);
n.UU.sval = PhreeqcPtr->string_duplicate(STR1.c_str());
}
break;
case tokrxn:
{
if (PhreeqcPtr->state == REACTION ||
PhreeqcPtr->state == ADVECTION ||
PhreeqcPtr->state == TRANSPORT)
{
n.UU.val = PhreeqcPtr->step_x;
}
else
{
n.UU.val = 0.0;
}
}
break;
case toks_s:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->find_ss_comp(str);
}
break;
case toksc:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_SC();
}
break;
case toksetdiff_c:
{
double d;
require(toklp, LINK);
const char* str = stringfactor(STR1, LINK);
require(tokcomma, LINK);
// double arugument
d = realexpr(LINK);
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->setdiff_c(str, d);
//PhreeqcPtr->PHRQ_free((void *) str);
}
break;
case toksi:
{
const char* str = stringfactor(STR1, LINK);
if (parse_all)
{
n.UU.val = 1;
}
else
{
PhreeqcPtr->saturation_index(str, &l_dummy, &n.UU.val);
}
}
break;
case toksim_no:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->simulation;
}
break;
case toksim_time:
{
if (!PhreeqcPtr->use.Get_kinetics_in())
{
if (PhreeqcPtr->state == PHAST)
{
n.UU.val = PhreeqcPtr->rate_sim_time;
}
else if (PhreeqcPtr->state == TRANSPORT)
{
n.UU.val = PhreeqcPtr->transport_step * PhreeqcPtr->timest;
}
else if (PhreeqcPtr->state == ADVECTION)
{
if (PhreeqcPtr->advection_kin_time_defined == TRUE)
{
n.UU.val = PhreeqcPtr->advection_step * PhreeqcPtr->advection_kin_time;
}
else
{
n.UU.val = PhreeqcPtr->advection_step;
}
}
else
{
n.UU.val = 0;
}
}
else
{
n.UU.val = PhreeqcPtr->rate_sim_time;
}
}
break;
case toksoln_vol:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_solution_volume();
}
break;
case tokspecies_formula:
case tokspecies_formula_:
{
require(toklp, LINK);
std::string species_name(stringfactor(STR1, LINK));
varrec* elts_varrec = NULL, * coef_varrec = NULL;
cxxNameDouble stoichiometry;
/*
* Parse arguments
*/
require(tokcomma, LINK);
count_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || count_varrec->stringvar != 0)
snerr(": Cannot find count variable");
/* return number of names of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
elts_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || elts_varrec->stringvar != 1)
snerr(": Cannot find element string variable");
/* return coefficients of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
coef_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || coef_varrec->stringvar != 0)
snerr(": Cannot find coefficient variable");
LINK->t = LINK->t->next;
require(tokrp, LINK);
free_dim_stringvar(elts_varrec);
PhreeqcPtr->free_check_null(coef_varrec->UU.U0.arr);
coef_varrec->UU.U0.arr = NULL;
/*
* Call subroutine
*/
std::string type = PhreeqcPtr->species_formula(species_name, stoichiometry);
// put type as return value
n.stringval = true;
n.UU.sval = PhreeqcPtr->string_duplicate(type.c_str());
/*
* fill in varrec structure
*/
size_t count = stoichiometry.size();
*count_varrec->UU.U0.val = (LDBLE)count;
/*
* malloc space
*/
elts_varrec->UU.U1.sarr = (char**)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(char*));
if (elts_varrec->UU.U1.sarr == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
coef_varrec->UU.U0.arr = (LDBLE*)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(LDBLE));
if (coef_varrec->UU.U0.arr == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
// first position not used
elts_varrec->UU.U1.sarr[0] = NULL;
coef_varrec->UU.U0.arr[0] = 0;
// set dims for Basic array
for (i = 0; i < maxdims; i++)
{
elts_varrec->dims[i] = 0;
coef_varrec->dims[i] = 0;
}
// set dims for first dimension and number of dims
elts_varrec->dims[0] = (long)(count + 1);
coef_varrec->dims[0] = (long)(count + 1);
elts_varrec->numdims = 1;
coef_varrec->numdims = 1;
// fill in arrays
i = 1;
for (cxxNameDouble::iterator it = stoichiometry.begin(); it != stoichiometry.end(); it++)
{
elts_varrec->UU.U1.sarr[i] = PhreeqcPtr->string_duplicate((it->first).c_str());
coef_varrec->UU.U0.arr[i] = it->second;
i++;
}
}
break;
case toksr:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->saturation_ratio(str);
}
break;
case tokstep_no:
{
if (PhreeqcPtr->state == PHAST)
{
n.UU.val = 0;
}
else if (PhreeqcPtr->state == TRANSPORT)
{
n.UU.val = PhreeqcPtr->transport_step;
}
else if (PhreeqcPtr->state == ADVECTION)
{
n.UU.val = PhreeqcPtr->advection_step;
}
else if (PhreeqcPtr->state == REACTION)
{
n.UU.val = PhreeqcPtr->reaction_step;
}
else
{
n.UU.val = 0;
}
}
break;
case tokstr_e_:
{
// left parenthesis
require(toklp, LINK);
// set number
LDBLE nmbr;
nmbr = realexpr(LINK);
// set total length
require(tokcomma, LINK);
int length = (int)realexpr(LINK);
// set total length
require(tokcomma, LINK);
int width = (int)realexpr(LINK);
// right parenthesis
require(tokrp, LINK);
// Make work space
int max_length = length < 256 ? 256 : length;
char* token = (char*)PhreeqcPtr->PHRQ_calloc((max_length + 1), sizeof(char));
if (token == NULL) PhreeqcPtr->malloc_error();
std::string std_num;
{
sprintf(token, "%*.*e", length, width, nmbr);
std_num = token;
}
// set function value
n.UU.sval = (char*)PhreeqcPtr->PHRQ_calloc(std_num.size() + 2, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
strcpy(n.UU.sval, std_num.c_str());
n.stringval = true;
// free work space
PhreeqcPtr->free_check_null(token);
}
break;
case tokstr_f_:
{
// left parenthesis
require(toklp, LINK);
// set number
LDBLE nmbr;
nmbr = realexpr(LINK);
// set total length
require(tokcomma, LINK);
int length = (int)realexpr(LINK);
// set total length
require(tokcomma, LINK);
int width = (int)realexpr(LINK);
// right parenthesis
require(tokrp, LINK);
// Make work space
int max_length = length < 256 ? 256 : length;
char* token = (char*)PhreeqcPtr->PHRQ_calloc((max_length + 1), sizeof(char));
if (token == NULL) PhreeqcPtr->malloc_error();
std::string std_num;
{
sprintf(token, "%*.*f", length, width, nmbr);
std_num = token;
}
// set function value
n.UU.sval = (char*)PhreeqcPtr->PHRQ_calloc(std_num.size() + 2, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
strcpy(n.UU.sval, std_num.c_str());
n.stringval = true;
// free work space
PhreeqcPtr->free_check_null(token);
}
break;
case toksum_gas:
{
require(toklp, LINK);
mytemplate = stringfactor(STR1, LINK);
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
elt_name = stringfactor(STR2, LINK);
}
else
{
elt_name = NULL;
}
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->sum_match_gases(mytemplate, elt_name);
}
break;
case toksum_s_s:
{
require(toklp, LINK);
mytemplate = stringfactor(STR1, LINK);
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
elt_name = stringfactor(STR2, LINK);
}
else
{
elt_name = NULL;
}
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->sum_match_ss(mytemplate, elt_name);
}
break;
case toksum_species:
{
require(toklp, LINK);
mytemplate = stringfactor(STR1, LINK);
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
elt_name = stringfactor(STR2, LINK);
}
else
{
elt_name = NULL;
}
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->sum_match_species(mytemplate, elt_name);
}
break;
case toksurf:
{
require(toklp, LINK);
elt_name = stringfactor(STR1, LINK);
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
surface_name = stringfactor(STR2, LINK);
}
else
{
surface_name = NULL;
}
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->surf_total(elt_name, surface_name);
}
break;
case toksys:
{
int isort = 0;
require(toklp, LINK);
elt_name = stringfactor(STR1, LINK);
/*
* Parse arguments
*/
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
/* return number of species */
LINK->t = LINK->t->next;
count_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || !count_varrec || count_varrec->stringvar != 0)
{
snerr(": can`t find variable");
#if !defined(R_SO)
exit(4);
#endif
}
/* return number of names of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
names_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || !names_varrec || names_varrec->stringvar != 1)
{
snerr(": can`t find name of species");
#if !defined(R_SO)
exit(4);
#endif
}
/* return number of types of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
types_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || types_varrec->stringvar != 1)
snerr(": can`t find type of species");
/* return number of moles of species */
LINK->t = LINK->t->next;
require(tokcomma, LINK);
moles_varrec = LINK->t->UU.vp;
if (LINK->t->kind != tokvar || moles_varrec->stringvar != 0)
snerr(": can`t find moles of species");
LINK->t = LINK->t->next;
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
isort = intexpr(LINK);
arg_num = 5;
}
else
{
arg_num = 4;
}
}
else
{
arg_num = 1;
}
require(tokrp, LINK);
if (arg_num > 1)
{
free_dim_stringvar(names_varrec);
free_dim_stringvar(types_varrec);
PhreeqcPtr->free_check_null(moles_varrec->UU.U0.arr);
moles_varrec->UU.U0.arr = NULL;
}
/*
* Call subroutine
*/
/*
n.UU.val = system_total(elt_name, count_varrec->UU.U0.val, &(names_varrec->UU.U1.sarr), &(types_varrec->UU.U1.sarr), &(moles_varrec->UU.U0.arr));
*/
if (parse_all)
{
PhreeqcPtr->sys_tot = 0;
//PhreeqcPtr->count_sys = 1000;
//int count_sys = PhreeqcPtr->count_sys;
size_t count_sys = 1000;
names_arg = (char**)PhreeqcPtr->PHRQ_calloc((size_t)(count_sys + 1), sizeof(char*));
if (names_arg == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
types_arg = (char**)PhreeqcPtr->PHRQ_calloc((size_t)(count_sys + 1), sizeof(char*));
if (types_arg == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
moles_arg = (LDBLE*)PhreeqcPtr->PHRQ_calloc((size_t)(count_sys + 1), sizeof(LDBLE));
if (moles_arg == NULL)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
names_arg[0] = NULL;
types_arg[0] = NULL;
moles_arg[0] = 0;
count_species = (LDBLE)count_sys;
n.UU.val = 0;
}
else
{
n.UU.val = PhreeqcPtr->system_total(elt_name, &count_species, &(names_arg),
&(types_arg), &(moles_arg), isort);
}
/*
* fill in varrec structure
*/
if (arg_num > 1)
{
*count_varrec->UU.U0.val = count_species;
names_varrec->UU.U1.sarr = names_arg;
types_varrec->UU.U1.sarr = types_arg;
moles_varrec->UU.U0.arr = moles_arg;
for (i = 0; i < maxdims; i++)
{
names_varrec->dims[i] = 0;
types_varrec->dims[i] = 0;
moles_varrec->dims[i] = 0;
}
names_varrec->dims[0] = (long)(*count_varrec->UU.U0.val) + 1;
types_varrec->dims[0] = (long)(*count_varrec->UU.U0.val) + 1;
moles_varrec->dims[0] = (long)(*count_varrec->UU.U0.val) + 1;
names_varrec->numdims = 1;
types_varrec->numdims = 1;
moles_varrec->numdims = 1;
}
else
{
for (i = 0; i < count_species + 1; i++)
{
PhreeqcPtr->free_check_null(names_arg[i]);
PhreeqcPtr->free_check_null(types_arg[i]);
}
PhreeqcPtr->free_check_null(names_arg);
PhreeqcPtr->free_check_null(types_arg);
PhreeqcPtr->free_check_null(moles_arg);
}
}
break;
case tokt_sc:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->calc_t_sc(str);
}
break;
case toktc:
{
n.UU.val = PhreeqcPtr->tc_x;
}
break;
case toktime:
{
n.UU.val = PhreeqcPtr->rate_time;
}
break;
case toktitle:
{
n.stringval = true;
if (strlen(PhreeqcPtr->last_title_x.c_str()) == 0)
{
PhreeqcPtr->last_title_x = " ";
}
n.UU.sval = PhreeqcPtr->string_duplicate(PhreeqcPtr->last_title_x.c_str());
while (PhreeqcPtr->replace("\t", " ", n.UU.sval));
}
break;
case toktk:
{
n.UU.val = PhreeqcPtr->tc_x + 273.15;
}
break;
case toktot:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->total(str);
}
break;
case toktotal_time:
{
if (!PhreeqcPtr->use.Get_kinetics_in())
{
if (PhreeqcPtr->state == PHAST)
{
n.UU.val = PhreeqcPtr->rate_sim_time_end;
}
else if (PhreeqcPtr->state == TRANSPORT)
{
n.UU.val = PhreeqcPtr->initial_total_time + PhreeqcPtr->transport_step * PhreeqcPtr->timest;
}
else if (PhreeqcPtr->state == ADVECTION)
{
n.UU.val =
PhreeqcPtr->initial_total_time + PhreeqcPtr->advection_step * PhreeqcPtr->advection_kin_time;
}
else
{
n.UU.val = 0;
}
}
else
{
n.UU.val = PhreeqcPtr->initial_total_time + PhreeqcPtr->rate_sim_time;
}
}
break;
case toktotmole:
case toktotmol:
case toktotmoles:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->total_mole(str);
}
break;
case toktrim:
{
n.stringval = true;
require(toklp, LINK);
string1 = stringfactor(STR1, LINK);
require(tokrp, LINK);
STR1 = trim(STR1);
n.UU.sval = PhreeqcPtr->string_duplicate(STR1.c_str());
}
break;
case tokviscos:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->viscos;
}
break;
case tokviscos_0:
{
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->viscos_0;
}
break;
case tokvm:
{
const char* str = stringfactor(STR1, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->aqueous_vm(str);
}
break;
/*
* End of PHREEQC functions
*/
case toksa_declercq: // Undocumented function
{
double type, sa, d, m, m0, gfw;
// left parenthesis
require(toklp, LINK);
// first double arugument, type
type = realfactor(LINK);
require(tokcomma, LINK);
// second double arugument, Sa
sa = realfactor(LINK);
require(tokcomma, LINK);
// third double arugument, Sa
d = realfactor(LINK);
require(tokcomma, LINK);
// fourth double arugument, m
m = realfactor(LINK);
require(tokcomma, LINK);
// fifth double arugument, m0
m0 = realfactor(LINK);
require(tokcomma, LINK);
// sixth double arugument, gfw
gfw = realfactor(LINK);
require(tokrp, LINK);
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->sa_declercq(type, sa, d, m, m0, gfw);
}
break;
case tokcallback: // PHAST function
{
double x1, x2;
char* str;
// left parenthesis
require(toklp, LINK);
// first double arugument
x1 = realfactor(LINK);
require(tokcomma, LINK);
// second double arugument
x2 = realfactor(LINK);
require(tokcomma, LINK);
// string arugument
str = strexpr(LINK);
require(tokrp, LINK);
// call callback Basic function
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x2, str);
PhreeqcPtr->PHRQ_free(str);
}
break;
case tokcell_pore_volume: // PHAST function
case tokporevolume:
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "cell_pore_volume");
}
break;
case tokcell_porosity: // PHAST function
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "cell_porosity");
}
break;
case tokcell_saturation: // PHAST function
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "cell_saturation");
}
break;
case tokcell_volume: // PHAST function
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "cell_volume");
}
break;
case toktransport_cell_no: // PHAST function
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "transport_cell_no");
}
break;
case tokvelocity_x: // PHAST function
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "velocity_x");
}
break;
case tokvelocity_y: // PHAST function
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "velocity_y");
}
break;
case tokvelocity_z: // PHAST function
{
double x1 = (double)PhreeqcPtr->solution_number();
n.UU.val = (parse_all) ? 1 : PhreeqcPtr->basic_callback(x1, x1, "velocity_z");
}
break;
case toklog10:
{
LDBLE t = realfactor(LINK);
{
n.UU.val = log10(t);
}
}
break;
case toksin:
{
n.UU.val = sin(realfactor(LINK));
}
break;
case tokcos:
{
n.UU.val = cos(realfactor(LINK));
}
break;
case toktan:
{
n.UU.val = realfactor(LINK);
n.UU.val = sin(n.UU.val) / cos(n.UU.val);
}
break;
case tokarctan:
{
n.UU.val = atan(realfactor(LINK));
}
break;
case toklog:
{
n.UU.val = log(realfactor(LINK));
}
break;
case tokexp:
{
n.UU.val = exp(realfactor(LINK));
}
break;
case tokabs:
{
n.UU.val = fabs(realfactor(LINK));
}
break;
case toksgn:
{
n.UU.val = realfactor(LINK);
n.UU.val = (double)(n.UU.val > 0) - (double)(n.UU.val < 0);
}
break;
case tokstr_:
n.stringval = true;
n.UU.sval = (char *) PhreeqcPtr->PHRQ_calloc(256, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
numtostr(n.UU.sval, realfactor(LINK));
break;
case tokval:
l_s = strfactor(LINK);
tok1 = LINK->t;
parse(l_s, &LINK->t);
tok = LINK->t;
if (tok == NULL)
n.UU.val = 0.0;
else
n = expr(LINK);
disposetokens(&tok);
LINK->t = tok1;
PhreeqcPtr->PHRQ_free(l_s);
break;
case tokchr_:
n.stringval = true;
n.UU.sval = (char *) PhreeqcPtr->PHRQ_calloc(256, sizeof(char));
if (n.UU.sval == NULL)
PhreeqcPtr->malloc_error();
strcpy(n.UU.sval, " ");
n.UU.sval[0] = (char) intfactor(LINK);
break;
case tokasc:
l_s = strfactor(LINK);
if (*l_s == '\0')
n.UU.val = 0.0;
else
n.UU.val = l_s[0];
PhreeqcPtr->PHRQ_free(l_s);
break;
case tokmid_:
n.stringval = true;
require(toklp, LINK);
n.UU.sval = strexpr(LINK);
require(tokcomma, LINK);
i = intexpr(LINK);
if (i < 1)
i = 1;
j = (int) strlen(n.UU.sval);
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
j = intexpr(LINK);
}
{
std::string str = n.UU.sval;
str = str.substr((size_t)i - 1, (size_t)j);
strcpy(n.UU.sval, str.c_str());
}
require(tokrp, LINK);
break;
case toklen:
l_s = strfactor(LINK);
n.UU.val = (double) strlen(l_s);
PhreeqcPtr->PHRQ_free(l_s);
break;
case tokpeek:
/* p2c: basic.p, line 1029: Note: Range checking is OFF [216] */
if (parse_all)
{
intfactor(LINK);
n.UU.val = 1.0;
}
else
{
trick.i = intfactor(LINK);
n.UU.val = *trick.c;
}
/* p2c: basic.p, line 1032: Note: Range checking is ON [216] */
break;
default:
snerr(": missing \" or (");
break;
}
return n;
}
valrec PBasic::
upexpr(struct LOC_exec * LINK)
{
valrec n, n2;
n = factor(LINK);
while (LINK->t != NULL && LINK->t->kind == tokup)
{
if (n.stringval)
tmerr(": not a number before ^");
LINK->t = LINK->t->next;
n2 = upexpr(LINK);
if (n2.stringval)
tmerr(": not a number after ^");
if (n.UU.val >= 0)
{
if (n.UU.val > 0)
{
n.UU.val = exp(n2.UU.val * log(n.UU.val));
}
continue;
}
if (n2.UU.val != (long) n2.UU.val)
{
tmerr(": negative number cannot be raised to a fractional power.");
}
else
{
n.UU.val = exp(n2.UU.val * log(-n.UU.val));
if (((long) n2.UU.val) & 1)
n.UU.val = -n.UU.val;
}
}
return n;
}
valrec PBasic::
term(struct LOC_exec * LINK)
{
valrec n, n2;
int k;
n = upexpr(LINK);
while (LINK->t != NULL && (unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) & ((1L << ((long) toktimes)) |
(1L << ((long) tokdiv)) | (1L <<
((long) tokmod)))) != 0)
{
k = LINK->t->kind;
LINK->t = LINK->t->next;
n2 = upexpr(LINK);
if (n.stringval || n2.stringval)
tmerr(": found char, but need a number for * or /");
if (k == tokmod)
{
/* n.UU.val = (long)floor(n.UU.val + 0.5) % (long)floor(n2.UU.val + 0.5); */
if (n.UU.val != 0)
{
n.UU.val =
fabs(n.UU.val) / n.UU.val * fmod(fabs(n.UU.val) +
1e-14, n2.UU.val);
}
else
{
n.UU.val = 0;
}
/* p2c: basic.p, line 1078:
* Note: Using % for possibly-negative arguments [317] */
}
else if (k == toktimes)
n.UU.val *= n2.UU.val;
else if (n2.UU.val != 0)
{
n.UU.val /= n2.UU.val;
}
else
{
if (!parse_all)
{
char * error_string = PhreeqcPtr->sformatf( "Zero divide in BASIC line\n %ld %s.\nValue set to zero.", stmtline->num, stmtline->inbuf);
PhreeqcPtr->warning_msg(error_string);
}
n.UU.val = 0;
}
}
return n;
}
valrec PBasic::
sexpr(struct LOC_exec * LINK)
{
valrec n, n2;
int k, m;
n = term(LINK);
while (LINK->t != NULL && (unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) tokplus)) | (1L << ((long) tokminus)))) != 0)
{
k = LINK->t->kind;
LINK->t = LINK->t->next;
n2 = term(LINK);
if (n.stringval != n2.stringval)
tmerr(": found char, but need a number for + or - ");
if (k == tokplus)
{
if (n.stringval)
{
m = 1;
if (n.UU.sval)
{
m += (int) strlen(n.UU.sval);
}
if (n2.UU.sval)
{
m += (int) strlen(n2.UU.sval);
}
//m = (int) strlen(n.UU.sval) + (int) strlen(n2.UU.sval) + 1;
if (m < 256)
m = 256;
n.UU.sval = (char *) PhreeqcPtr->PHRQ_realloc(n.UU.sval, (size_t) m * sizeof(char));
if (n.UU.sval == NULL)
{
PhreeqcPtr->malloc_error();
}
else
{
if (n2.UU.sval)
{
strcat(n.UU.sval, n2.UU.sval);
PhreeqcPtr->PHRQ_free(n2.UU.sval);
}
}
}
else
n.UU.val += n2.UU.val;
}
else
{
if (n.stringval)
tmerr(": found char, but need a number for - ");
else
n.UU.val -= n2.UU.val;
}
}
return n;
}
valrec PBasic::
relexpr(struct LOC_exec * LINK)
{
valrec n, n2;
bool f;
int k;
n = sexpr(LINK);
while (LINK->t != NULL && (unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) tokne + 1)) - (1L << ((long) tokeq)))) != 0)
{
k = LINK->t->kind;
LINK->t = LINK->t->next;
n2 = sexpr(LINK);
if (n.stringval != n2.stringval)
tmerr("");
if (n.stringval)
{
f = (bool) ((!strcmp(n.UU.sval, n2.UU.sval)
&& (unsigned long) k < 32
&& ((1L << ((long) k)) &
((1L << ((long) tokeq)) |
(1L << ((long) tokge)) | (1L <<
((long) tokle))))
!= 0) || (strcmp(n.UU.sval, n2.UU.sval) < 0
&& (unsigned long) k < 32
&& ((1L << ((long) k)) &
((1L << ((long) toklt)) |
(1L << ((long) tokle)) | (1L <<
((long)
tokne))))
!= 0)
|| (strcmp(n.UU.sval, n2.UU.sval) > 0
&& (unsigned long) k < 32
&& ((1L << ((long) k)) &
((1L << ((long) tokgt)) |
(1L << ((long) tokge)) | (1L <<
((long)
tokne)))) !=
0));
/* p2c: basic.p, line 2175: Note:
* Line breaker spent 0.0+1.00 seconds, 5000 tries on line 1518 [251] */
PhreeqcPtr->PHRQ_free(n.UU.sval);
PhreeqcPtr->PHRQ_free(n2.UU.sval);
}
else
f = (bool) ((n.UU.val == n2.UU.val && (unsigned long) k < 32 &&
((1L << ((long) k)) & ((1L << ((long) tokeq)) |
(1L << ((long) tokge)) |
(1L << ((long) tokle)))) !=
0) || (n.UU.val < n2.UU.val
&& (unsigned long) k < 32
&& ((1L << ((long) k)) &
((1L << ((long) toklt)) |
(1L << ((long) tokle)) | (1L <<
((long)
tokne))))
!= 0) || (n.UU.val > n2.UU.val
&& (unsigned long) k < 32
&& ((1L << ((long) k)) &
((1L << ((long) tokgt)) |
(1L << ((long) tokge)) | (1L
<<
((long) tokne)))) != 0));
/* p2c: basic.p, line 2175: Note:
* Line breaker spent 0.0+2.00 seconds, 5000 tries on line 1532 [251] */
n.stringval = false;
n.UU.val = f;
}
return n;
}
valrec PBasic::
andexpr(struct LOC_exec * LINK)
{
valrec n, n2;
n = relexpr(LINK);
while (LINK->t != NULL && LINK->t->kind == tokand)
{
LINK->t = LINK->t->next;
n2 = relexpr(LINK);
if (n.stringval || n2.stringval)
tmerr("");
n.UU.val = ((long) n.UU.val) & ((long) n2.UU.val);
}
return n;
}
valrec PBasic::
expr(struct LOC_exec * LINK)
{
valrec n, n2;
int k;
n = andexpr(LINK);
while (LINK->t != NULL && (unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) tokor)) | (1L << ((long) tokxor)))) != 0)
{
k = LINK->t->kind;
LINK->t = LINK->t->next;
n2 = andexpr(LINK);
if (n.stringval || n2.stringval)
tmerr("");
if (k == tokor)
n.UU.val = ((long) n.UU.val) | ((long) n2.UU.val);
else
n.UU.val = ((long) n.UU.val) ^ ((long) n2.UU.val);
}
return n;
}
void PBasic::
checkextra(struct LOC_exec *LINK)
{
if (LINK->t != NULL)
{
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_EXTRA;
}
errormsg("Extra information on line");
}
}
bool PBasic::
iseos(struct LOC_exec *LINK)
{
return ((bool) (LINK->t == NULL || LINK->t->kind == (long) tokelse ||
LINK->t->kind == (long) tokcolon));
}
void PBasic::
skiptoeos(struct LOC_exec *LINK)
{
while (!iseos(LINK))
LINK->t = LINK->t->next;
}
linerec * PBasic::
findline(long n)
{
linerec *l;
l = linebase;
while (l != NULL && l->num != n)
l = l->next;
return l;
}
linerec * PBasic::
mustfindline(long n)
{
linerec *l;
l = findline(n);
if (phreeqci_gui)
{
if (parse_whole_program)
{
if (l == NULL)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_UNDEF_LINE;
char * error_string = PhreeqcPtr->sformatf( "Undefined line %ld", n);
errormsg(error_string);
}
}
}
else
{
if (l == NULL)
{
char * error_string = PhreeqcPtr->sformatf( "Undefined line %ld", n);
errormsg(error_string);
}
}
return l;
}
void PBasic::
cmdend(struct LOC_exec *LINK)
{
stmtline = NULL;
LINK->t = NULL;
}
void PBasic::
cmdnew(struct LOC_exec *LINK)
{
void *p;
int i, k;
cmdend(LINK);
clearloops();
restoredata();
while (linebase != NULL)
{
p = linebase->next;
disposetokens(&linebase->txt);
PhreeqcPtr->PHRQ_free(linebase);
linebase = (linerec *) p;
}
while (varbase != NULL)
{
p = varbase->next;
if (varbase->stringvar)
{
if (varbase->numdims > 0)
{
k = 1;
for (i = 0; i < varbase->numdims; i++)
{
k = k * (varbase->dims[i]);
}
for (i = 0; i < k; i++)
{
PhreeqcPtr->free_check_null(varbase->UU.U1.sarr[i]);
}
PhreeqcPtr->free_check_null(varbase->UU.U1.sarr);
}
else if (*varbase->UU.U1.sval != NULL)
{
*varbase->UU.U1.sval =
(char *) PhreeqcPtr->free_check_null(*varbase->UU.U1.sval);
}
}
else
{
PhreeqcPtr->free_check_null(varbase->UU.U0.arr);
varbase->UU.U0.arr = NULL;
}
PhreeqcPtr->PHRQ_free(varbase);
varbase = (varrec *) p;
}
}
void PBasic::
cmdlist(struct LOC_exec *LINK)
{
linerec *l;
long n1, n2;
do
{
n1 = 0;
n2 = LONG_MAX;
if (LINK->t != NULL && LINK->t->kind == toknum)
{
n1 = (long) LINK->t->UU.num;
LINK->t = LINK->t->next;
if (LINK->t == NULL || LINK->t->kind != tokminus)
n2 = n1;
}
if (LINK->t != NULL && LINK->t->kind == tokminus)
{
LINK->t = LINK->t->next;
if (LINK->t != NULL && LINK->t->kind == toknum)
{
n2 = (long) LINK->t->UU.num;
LINK->t = LINK->t->next;
}
else
n2 = LONG_MAX;
}
l = linebase;
while (l != NULL && l->num <= n2)
{
if (l->num >= n1)
{
/* printf("%ld ", l->num); */
/* listtokens(stdout, l->txt); */
/* putchar('\n'); */
output_msg(PhreeqcPtr->sformatf("%ld ", l->num));
listtokens(NULL, l->txt);
output_msg("\n");
}
l = l->next;
}
if (!iseos(LINK))
require(tokcomma, LINK);
}
while (!iseos(LINK));
}
void PBasic::
cmdload(bool merging, char * name, struct LOC_exec *LINK)
{
FILE *f;
tokenrec *l_buf;
char STR1[256] = {0};
char *TEMP;
f = NULL;
if (!merging)
cmdnew(LINK);
if (f != NULL)
{
sprintf(STR1, "%s.TEXT", name);
f = freopen(STR1, "r", f);
}
else
{
sprintf(STR1, "%s.TEXT", name);
f = fopen(STR1, "r");
}
if (f == NULL)
{
_EscIO(FileNotFound);
return;
}
while (fgets(inbuf, 256, f) != NULL)
{
TEMP = strchr(inbuf, '\n');
if (TEMP != NULL)
*TEMP = 0;
parseinput(&l_buf);
if (curline == 0)
{
/* printf("Bad line in file\n"); */
output_msg("Bad line in file\n");
disposetokens(&l_buf);
}
}
if (f != NULL)
fclose(f);
f = NULL;
if (f != NULL)
fclose(f);
}
void PBasic::
cmdrun(struct LOC_exec *LINK)
{
linerec *l;
long i;
char *l_s;
l_s = (char *) PhreeqcPtr->PHRQ_calloc(PhreeqcPtr->max_line, sizeof(char));
if (l_s == NULL)
PhreeqcPtr->malloc_error();
l = linebase;
if (!iseos(LINK))
{
if (LINK->t->kind == toknum)
/*l = mustfindline(intexpr(LINK), LINK); */
l = mustfindline(intexpr(LINK));
else
{
stringexpr(l_s, LINK);
i = 0;
if (!iseos(LINK))
{
require(tokcomma, LINK);
i = intexpr(LINK);
}
checkextra(LINK);
cmdload(false, l_s, LINK);
if (i == 0)
l = linebase;
else
l = mustfindline(i);
}
}
stmtline = l;
LINK->gotoflag = true;
clearvars();
clearloops();
restoredata();
PhreeqcPtr->free_check_null(l_s);
return;
}
/* PhreeqcPtr->replace basic save command with transport of rate back to calc_kinetic_rate */
void PBasic::
cmdsave(struct LOC_exec *LINK)
{
valrec n;
while (!iseos(LINK))
{
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
if (n.stringval)
{
snerr(": in SAVE command");
}
else
{
PhreeqcPtr->rate_moles = n.UU.val;
}
}
}
void PBasic::
cmdput(struct LOC_exec *LINK)
{
int j;
std::ostringstream oss;
/* get parentheses */
require(toklp, LINK);
/* get first argumen */
double value = realexpr(LINK);
for (;;)
{
if (LINK->t != NULL && LINK->t->kind == tokcomma)
{
LINK->t = LINK->t->next;
j = intexpr(LINK);
oss << j << ",";
}
else
{
/* get right parentheses */
require(tokrp, LINK);
break;
}
}
if (!parse_all)
{
PhreeqcPtr->save_values[oss.str()] = value;
}
}
void PBasic::
cmdchange_por(struct LOC_exec *LINK)
{
int j;
LDBLE TEMP;
require(toklp, LINK);
/* get new porosity */
TEMP = realexpr(LINK);
require(tokcomma, LINK);
/* get cell_no */
j = intexpr(LINK);
require(tokrp, LINK);
if (j > 0 && j <= PhreeqcPtr->count_cells * (1 + PhreeqcPtr->stag_data.count_stag) + 1
&& j != PhreeqcPtr->count_cells + 1)
PhreeqcPtr->cell_data[j].por = TEMP;
}
void PBasic::
cmdchange_surf(struct LOC_exec *LINK)
{
/*
change_surf("Hfo", 0.3, "Sfo", 0, 5 )
(old_name, fraction, new_name, new_Dw, cell_no)
*/
char *c1;
int count;
PhreeqcPtr->change_surf_count += 1;
count = PhreeqcPtr->change_surf_count;
if (PhreeqcPtr->change_surf[count - 1].next == FALSE)
PhreeqcPtr->change_surf = PhreeqcPtr->change_surf_alloc(count + 1);
require(toklp, LINK);
/* get surface component name (change affects all comps of the same charge structure) */
c1 = strexpr(LINK);
PhreeqcPtr->change_surf[count - 1].comp_name = PhreeqcPtr->string_hsave(c1);
PhreeqcPtr->PHRQ_free(c1);
require(tokcomma, LINK);
/* get fraction of comp to change */
PhreeqcPtr->change_surf[count - 1].fraction = realexpr(LINK);
require(tokcomma, LINK);
/* get new surface component name */
c1 = strexpr(LINK);
PhreeqcPtr->change_surf[count - 1].new_comp_name = PhreeqcPtr->string_hsave(c1);
PhreeqcPtr->PHRQ_free(c1);
require(tokcomma, LINK);
/* get new Dw (no transport if 0) */
PhreeqcPtr->change_surf[count - 1].new_Dw = realexpr(LINK);
require(tokcomma, LINK);
/* get cell_no */
PhreeqcPtr->change_surf[count - 1].cell_no = intexpr(LINK);
require(tokrp, LINK);
if (PhreeqcPtr->change_surf->cell_no == 0 || PhreeqcPtr->change_surf->cell_no == PhreeqcPtr->count_cells + 1)
PhreeqcPtr->change_surf[count - 1].cell_no = -99;
}
void PBasic::
cmdbye(void)
{
exitflag = true;
}
void PBasic::
cmddel(struct LOC_exec *LINK)
{
linerec *l, *l0, *l1;
long n1, n2;
do
{
if (iseos(LINK))
snerr(": no variable name after del");
n1 = 0;
n2 = LONG_MAX;
if (LINK->t != NULL && LINK->t->kind == toknum)
{
n1 = (long) LINK->t->UU.num;
LINK->t = LINK->t->next;
if (LINK->t == NULL || LINK->t->kind != tokminus)
n2 = n1;
}
if (LINK->t != NULL && LINK->t->kind == tokminus)
{
LINK->t = LINK->t->next;
if (LINK->t != NULL && LINK->t->kind == toknum)
{
n2 = (long) LINK->t->UU.num;
LINK->t = LINK->t->next;
}
else
n2 = LONG_MAX;
}
l = linebase;
l0 = NULL;
while (l != NULL && l->num <= n2)
{
l1 = l->next;
if (l->num >= n1)
{
if (l == stmtline)
{
cmdend(LINK);
clearloops();
restoredata();
}
if (l0 == NULL)
linebase = l->next;
else
l0->next = l->next;
disposetokens(&l->txt);
PhreeqcPtr->PHRQ_free(l);
}
else
l0 = l;
l = l1;
}
if (!iseos(LINK))
require(tokcomma, LINK);
}
while (!iseos(LINK));
}
void PBasic::
cmdrenum(struct LOC_exec *LINK)
{
linerec *l, *l1;
tokenrec *tok;
long lnum, step;
lnum = 10;
step = 10;
if (!iseos(LINK))
{
lnum = intexpr(LINK);
if (!iseos(LINK))
{
require(tokcomma, LINK);
step = intexpr(LINK);
}
}
l = linebase;
if (l == NULL)
return;
while (l != NULL)
{
l->num2 = lnum;
lnum += step;
l = l->next;
}
l = linebase;
do
{
tok = l->txt;
do
{
if (tok->kind == (long) tokdel || tok->kind == (long) tokrestore
|| tok->kind == (long) toklist || tok->kind == (long) tokrun
|| tok->kind == (long) tokelse || tok->kind == (long) tokthen
|| tok->kind == (long) tokgosub
|| tok->kind == (long) tokgoto)
{
while (tok->next != NULL && tok->next->kind == toknum)
{
tok = tok->next;
lnum = (long) floor(tok->UU.num + 0.5);
l1 = linebase;
while (l1 != NULL && l1->num != lnum)
l1 = l1->next;
if (l1 == NULL)
{
/* printf("Undefined line %ld in line %ld\n", lnum,
l->num2); */
output_msg(PhreeqcPtr->sformatf("Undefined line %ld in line %ld\n", lnum, l->num2));
}
else
{
#if defined(PHREEQCI_GUI)
if (phreeqci_gui)
{
_snprintf(tok->sz_num, tok->n_sz, "%ld", l1->num2);
}
#endif
tok->UU.num = l1->num2;
}
if (tok->next != NULL && tok->next->kind == tokcomma)
tok = tok->next;
}
}
tok = tok->next;
}
while (tok != NULL);
l = l->next;
}
while (l != NULL);
l = linebase;
while (l != NULL)
{
l->num = l->num2;
l = l->next;
}
}
void PBasic::
cmdprint(struct LOC_exec *LINK)
{
bool semiflag;
valrec n;
char STR1[256] = {0};
semiflag = false;
while (!iseos(LINK))
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
if (n.stringval)
{
if (!skip_punch) {
/* fputs(n.UU.sval, stdout); */
output_msg(PhreeqcPtr->sformatf("%s ", n.UU.sval));
}
n.UU.sval = (char*)PhreeqcPtr->free_check_null(n.UU.sval);
}
else
/* printf("%s ", numtostr(STR1, n.UU.val)); */
output_msg(PhreeqcPtr->sformatf("%s ", numtostr(STR1, n.UU.val)));
}
if (!semiflag && PhreeqcPtr->Get_output_newline())
/* putchar('\n');*/
output_msg("\n");
PhreeqcPtr->Set_output_newline(true);
skip_punch = false;
}
void PBasic::
cmdpunch(struct LOC_exec *LINK)
{
valrec n;
/* char STR1[256]; */
while (!iseos(LINK))
{
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
bool temp_high_precision = (PhreeqcPtr->current_selected_output != NULL) ?
PhreeqcPtr->current_selected_output->Get_high_precision() :
PhreeqcPtr->high_precision;
if (!this->skip_punch)
{
if (n.stringval)
{
/* fputs(n.UU.sval, stdout); */
{
if (!temp_high_precision)
{
if (strlen(n.UU.sval) <= 12)
{
if (punch_tab)
{
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%12.12s\t", n.UU.sval);
}
else {
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%12.12s", n.UU.sval);
}
}
else
{
if (punch_tab)
{
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%s\t", n.UU.sval);
}
else {
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%s", n.UU.sval);
}
}
}
else
{
if (strlen(n.UU.sval) <= 20)
{
if (punch_tab) {
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%20.20s\t", n.UU.sval);
}
else {
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%20.20s", n.UU.sval);
}
}
else
{
if (punch_tab) {
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%s\t", n.UU.sval);
}
else {
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%s", n.UU.sval);
}
}
}
}
n.UU.sval = (char*)PhreeqcPtr->free_check_null(n.UU.sval);
}
else if (!temp_high_precision)
{
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%12.4e\t", (double)n.UU.val);
}
else
{
PhreeqcPtr->fpunchf_user(PhreeqcPtr->n_user_punch_index, "%20.12e\t", (double)n.UU.val);
}
punch_tab = true;
++PhreeqcPtr->n_user_punch_index;
}
else
{
n.UU.sval = (char*)PhreeqcPtr->free_check_null(n.UU.sval);
}
this->skip_punch = false;
}
}
#if defined PHREEQ98
void PBasic::
cmdgraph_x(struct LOC_exec *LINK)
{
bool semiflag;
valrec n;
char STR1[256];
semiflag = false;
while (!iseos(LINK))
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
if (colnr == 0)
{
rownr++;
}
if (n.stringval)
{
/* fputs(n.UU.sval, stdout); */
GridChar(n.UU.sval, "x");
PhreeqcPtr->PHRQ_free(n.UU.sval);
}
else
GridChar(numtostr(STR1, n.UU.val), "x");
colnr++;
}
}
void PBasic::
cmdgraph_y(struct LOC_exec *LINK)
{
bool semiflag;
valrec n;
char STR1[256];
semiflag = false;
while (!iseos(LINK))
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
if (colnr == 0)
{
rownr++;
}
if (n.stringval)
{
/* fputs(n.UU.sval, stdout); */
GridChar(n.UU.sval, "y");
PhreeqcPtr->PHRQ_free(n.UU.sval);
}
else
GridChar(numtostr(STR1, n.UU.val), "y");
colnr++;
}
}
void PBasic::
cmdgraph_sy(struct LOC_exec *LINK)
{
bool semiflag;
valrec n;
char STR1[256];
semiflag = false;
while (!iseos(LINK))
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
if (colnr == 0)
{
rownr++;
}
if (n.stringval)
{
/* fputs(n.UU.sval, stdout); */
GridChar(n.UU.sval, "s");
PhreeqcPtr->PHRQ_free(n.UU.sval);
}
else
GridChar(numtostr(STR1, n.UU.val), "s");
colnr++;
}
}
#endif
void PBasic::
cmdlet(bool implied, struct LOC_exec *LINK)
{
varrec *v;
char *old, *mynew;
LDBLE d_value;
LDBLE *target;
char **starget;
target = NULL;
starget = NULL;
if (implied)
LINK->t = stmttok;
v = findvar(LINK);
if (v->stringvar)
{
starget = v->UU.U1.sval;
}
else
{
target = v->UU.U0.val;
}
require(tokeq, LINK);
if (!v->stringvar)
{
/* in case array is used on right hand side */
d_value = realexpr(LINK);
v->UU.U0.val = target;
*v->UU.U0.val = d_value;
/* *v->UU.U0.val = realexpr(LINK); */
return;
}
mynew = strexpr(LINK);
v->UU.U1.sval = starget;
old = *v->UU.U1.sval;
*v->UU.U1.sval = mynew;
if (old != NULL)
PhreeqcPtr->PHRQ_free(old);
}
void PBasic::
cmdgoto(struct LOC_exec *LINK)
{
stmtline = mustfindline(intexpr(LINK));
LINK->t = NULL;
LINK->gotoflag = true;
}
void PBasic::
cmdif(struct LOC_exec *LINK)
{
LDBLE n;
long i;
n = realexpr(LINK);
require(tokthen, LINK);
if (n == 0)
{
i = 0;
do
{
if (LINK->t != NULL)
{
if (LINK->t->kind == tokif)
i++;
if (LINK->t->kind == tokelse)
i--;
LINK->t = LINK->t->next;
}
}
while (LINK->t != NULL && i >= 0);
}
if (LINK->t != NULL && LINK->t->kind == toknum)
cmdgoto(LINK);
else
LINK->elseflag = true;
}
void PBasic::
cmdelse(struct LOC_exec *LINK)
{
LINK->t = NULL;
}
bool PBasic::
skiploop(int up, int dn, struct LOC_exec *LINK)
{
bool Result;
long i;
linerec *saveline;
saveline = stmtline;
i = 0;
do
{
while (LINK->t == NULL)
{
if (stmtline == NULL || stmtline->next == NULL)
{
Result = false;
stmtline = saveline;
goto _L1;
}
stmtline = stmtline->next;
LINK->t = stmtline->txt;
}
if (LINK->t->kind == up)
i++;
if (LINK->t->kind == dn)
i--;
LINK->t = LINK->t->next;
}
while (i >= 0);
Result = true;
_L1:
return Result;
}
void PBasic::
cmdfor(struct LOC_exec *LINK)
{
looprec *l, lr;
linerec *saveline;
long i, j;
lr.UU.U0.vp = findvar(LINK);
if (lr.UU.U0.vp->stringvar)
snerr(": error in FOR command");
require(tokeq, LINK);
*lr.UU.U0.vp->UU.U0.val = realexpr(LINK);
require(tokto, LINK);
lr.UU.U0.max = realexpr(LINK);
if (LINK->t != NULL && LINK->t->kind == tokstep)
{
LINK->t = LINK->t->next;
lr.UU.U0.step = realexpr(LINK);
}
else
lr.UU.U0.step = 1.0;
lr.homeline = stmtline;
lr.hometok = LINK->t;
lr.kind = forloop;
lr.next = loopbase;
if ((lr.UU.U0.step >= 0 && *lr.UU.U0.vp->UU.U0.val > lr.UU.U0.max) ||
(lr.UU.U0.step <= 0 && *lr.UU.U0.vp->UU.U0.val < lr.UU.U0.max))
{
saveline = stmtline;
i = 0;
j = 0;
do
{
while (LINK->t == NULL)
{
if (stmtline == NULL || stmtline->next == NULL)
{
stmtline = saveline;
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_FOR_WO_NEXT;
}
errormsg("FOR without NEXT");
}
stmtline = stmtline->next;
LINK->t = stmtline->txt;
}
if (LINK->t->kind == tokfor)
{
if (LINK->t->next != NULL && LINK->t->next->kind == tokvar &&
LINK->t->next->UU.vp == lr.UU.U0.vp)
j++;
else
i++;
}
if (LINK->t->kind == toknext)
{
if (LINK->t->next != NULL && LINK->t->next->kind == tokvar &&
LINK->t->next->UU.vp == lr.UU.U0.vp)
j--;
else
i--;
}
LINK->t = LINK->t->next;
}
while (i >= 0 && j >= 0);
skiptoeos(LINK);
return;
}
l = (looprec *) PhreeqcPtr->PHRQ_calloc(1, sizeof(looprec));
if (l == NULL)
{
PhreeqcPtr->malloc_error();
}
else
{
*l = lr;
loopbase = l;
}
}
void PBasic::
cmdnext(struct LOC_exec *LINK)
{
varrec *v;
bool found;
looprec *l, *WITH;
if (!iseos(LINK))
v = findvar(LINK);
else
v = NULL;
do
{
if (loopbase == NULL || loopbase->kind == gosubloop)
{
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_NEXT_WO_FOR;
}
errormsg("NEXT without FOR");
}
found = (bool) (loopbase->kind == forloop &&
(v == NULL || loopbase->UU.U0.vp == v));
if (!found)
{
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
}
}
while (!found);
WITH = loopbase;
*WITH->UU.U0.vp->UU.U0.val += WITH->UU.U0.step;
if ((WITH->UU.U0.step < 0
|| *WITH->UU.U0.vp->UU.U0.val <= WITH->UU.U0.max)
&& (WITH->UU.U0.step > 0
|| *WITH->UU.U0.vp->UU.U0.val >= WITH->UU.U0.max))
{
stmtline = WITH->homeline;
LINK->t = WITH->hometok;
return;
}
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
}
void PBasic::
cmdwhile(struct LOC_exec *LINK)
{
looprec *l;
l = (looprec *) PhreeqcPtr->PHRQ_calloc(1, sizeof(looprec));
if (l == NULL)
{
PhreeqcPtr->malloc_error();
return;
}
l->next = loopbase;
loopbase = l;
l->kind = whileloop;
l->homeline = stmtline;
l->hometok = LINK->t;
if (iseos(LINK))
return;
if (realexpr(LINK) != 0)
return;
if (phreeqci_gui)
{
if (parse_whole_program == TRUE)
{
if (!skiploop(tokwhile, tokwend, LINK))
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_WHILE_WO_WEND;
errormsg("WHILE without WEND");
}
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
skiptoeos(LINK);
}
}
else
{
if (!skiploop(tokwhile, tokwend, LINK))
{
errormsg("WHILE without WEND");
}
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
skiptoeos(LINK);
}
}
void PBasic::
cmdwend(struct LOC_exec *LINK)
{
tokenrec *tok;
linerec *tokline;
looprec *l;
bool found;
if (phreeqci_gui && !parse_whole_program)
{
return;
}
do
{
if (loopbase == NULL || loopbase->kind == gosubloop)
{
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_WEND_WO_WHILE;
}
errormsg("WEND without WHILE");
}
found = (bool) (loopbase->kind == whileloop);
if (!found)
{
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
}
}
while (!found);
if (!iseos(LINK))
{
if (realexpr(LINK) != 0)
found = false;
}
tok = LINK->t;
tokline = stmtline;
if (found)
{
stmtline = loopbase->homeline;
LINK->t = loopbase->hometok;
if (!iseos(LINK))
{
if (realexpr(LINK) == 0)
found = false;
}
}
if (found)
return;
LINK->t = tok;
stmtline = tokline;
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
}
void PBasic::
cmdgosub(struct LOC_exec *LINK)
{
looprec *l;
l = (looprec *) PhreeqcPtr->PHRQ_calloc(1, sizeof(looprec));
if (l == NULL)
{
PhreeqcPtr->malloc_error();
return;
}
l->next = loopbase;
loopbase = l;
l->kind = gosubloop;
l->homeline = stmtline;
l->hometok = LINK->t;
cmdgoto(LINK);
}
void PBasic::
cmdreturn(struct LOC_exec *LINK)
{
looprec *l;
bool found;
if (phreeqci_gui && !parse_whole_program)
{
return;
}
do
{
if (loopbase == NULL)
{
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_RETURN_WO_GOSUB;
}
errormsg("RETURN without GOSUB");
}
found = (bool) (loopbase->kind == gosubloop);
if (!found)
{
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
}
}
while (!found);
stmtline = loopbase->homeline;
LINK->t = loopbase->hometok;
l = loopbase->next;
PhreeqcPtr->PHRQ_free(loopbase);
loopbase = l;
skiptoeos(LINK);
}
void PBasic::
cmdread(struct LOC_exec *LINK)
{
varrec *v;
tokenrec *tok;
bool found;
do
{
v = findvar(LINK);
tok = LINK->t;
LINK->t = datatok;
if (phreeqci_gui)
{
if (parse_whole_program)
{
if (dataline == NULL)
{
dataline = linebase;
LINK->t = dataline->txt;
}
if (LINK->t == NULL || LINK->t->kind != tokcomma)
{
do
{
while (LINK->t == NULL)
{
if (dataline == NULL || dataline->next == NULL)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_OUT_OF_DATA;
errormsg("Out of Data");
}
dataline = dataline->next;
LINK->t = dataline->txt;
}
found = (bool) (LINK->t->kind == tokdata);
LINK->t = LINK->t->next;
}
while (!found || iseos(LINK));
}
else
LINK->t = LINK->t->next;
if (v->stringvar)
{
if (*v->UU.U1.sval != NULL)
*v->UU.U1.sval = (char *) PhreeqcPtr->free_check_null(*v->UU.U1.sval);
*v->UU.U1.sval = strexpr(LINK);
}
else
*v->UU.U0.val = realexpr(LINK);
}
}
else
{
if (dataline == NULL)
{
dataline = linebase;
LINK->t = dataline->txt;
}
if (LINK->t == NULL || LINK->t->kind != tokcomma)
{
do
{
while (LINK->t == NULL)
{
if (dataline == NULL || dataline->next == NULL)
errormsg("Out of Data");
dataline = dataline->next;
LINK->t = dataline->txt;
}
found = (bool) (LINK->t->kind == tokdata);
LINK->t = LINK->t->next;
}
while (!found || iseos(LINK));
}
else
LINK->t = LINK->t->next;
if (v->stringvar)
{
if (*v->UU.U1.sval != NULL)
*v->UU.U1.sval = (char *) PhreeqcPtr->free_check_null(*v->UU.U1.sval);
*v->UU.U1.sval = strexpr(LINK);
}
else
*v->UU.U0.val = realexpr(LINK);
}
datatok = LINK->t;
LINK->t = tok;
if (!iseos(LINK))
require(tokcomma, LINK);
}
while (!iseos(LINK));
}
void PBasic::
cmddata(struct LOC_exec *LINK)
{
skiptoeos(LINK);
}
void PBasic::
cmdrestore(struct LOC_exec *LINK)
{
if (iseos(LINK))
restoredata();
else
{
dataline = mustfindline(intexpr(LINK));
if (phreeqci_gui)
{
if (parse_whole_program)
{
datatok = dataline->txt;
}
}
else
{
datatok = dataline->txt;
}
}
}
void PBasic::
cmdgotoxy(struct LOC_exec *LINK)
{
intexpr(LINK);
require(tokcomma, LINK);
}
void PBasic::
cmdon(struct LOC_exec *LINK)
{
long i;
looprec *l;
i = intexpr(LINK);
if (LINK->t != NULL && LINK->t->kind == tokgosub)
{
l = (looprec *) PhreeqcPtr->PHRQ_calloc(1, sizeof(looprec));
if (l == NULL)
{
PhreeqcPtr->malloc_error();
}
else
{
l->next = loopbase;
loopbase = l;
l->kind = gosubloop;
l->homeline = stmtline;
l->hometok = LINK->t;
LINK->t = LINK->t->next;
}
}
else
require(tokgoto, LINK);
if (i < 1)
{
skiptoeos(LINK);
return;
}
while (i > 1 && !iseos(LINK))
{
require(toknum, LINK);
if (!iseos(LINK))
require(tokcomma, LINK);
i--;
}
if (!iseos(LINK))
cmdgoto(LINK);
}
void PBasic::
cmddim(struct LOC_exec *LINK)
{
long i, j, k;
varrec *v;
bool done;
do
{
if (LINK->t == NULL || LINK->t->kind != tokvar)
snerr(": error in DIM command");
v = LINK->t->UU.vp;
LINK->t = LINK->t->next;
if (v->numdims != 0)
{
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_ARRAY_ALREADY;
}
errormsg("Array already dimensioned before");
}
j = 1;
i = 0;
require(toklp, LINK);
do
{
k = intexpr(LINK) + 1;
if (k < 1)
badsubscr();
if (i >= maxdims)
badsubscr();
i++;
v->dims[i - 1] = k;
j *= k;
done = (bool) (LINK->t != NULL && LINK->t->kind == tokrp);
if (!done)
require(tokcomma, LINK);
}
while (!done);
LINK->t = LINK->t->next;
v->numdims = (char) i;
if (v->stringvar)
{
v->UU.U1.sarr = (char **) PhreeqcPtr->PHRQ_malloc(j * sizeof(char *));
if (!v->UU.U1.sarr)
{
PhreeqcPtr->malloc_error();
#if !defined(R_SO)
exit(4);
#endif
}
if (v->UU.U1.sarr == NULL)
PhreeqcPtr->malloc_error();
for (i = 0; i < j; i++)
v->UU.U1.sarr[i] = NULL;
}
else
{
v->UU.U0.arr = (LDBLE *) PhreeqcPtr->PHRQ_malloc(j * sizeof(LDBLE));
if (v->UU.U0.arr == NULL)
{
PhreeqcPtr->malloc_error();
}
else
{
for (i = 0; i < j; i++)
v->UU.U0.arr[i] = 0.0;
}
}
if (!iseos(LINK))
require(tokcomma, LINK);
}
while (!iseos(LINK));
}
void PBasic::
cmderase(struct LOC_exec *LINK)
{
varrec *v = NULL;
do
{
if (LINK->t == NULL || LINK->t->kind != tokvar)
{
snerr(": error in DIM command");
}
else
{
v = LINK->t->UU.vp;
LINK->t = LINK->t->next;
clearvar(v);
if (!iseos(LINK)) require(tokcomma, LINK);
}
}
while (!iseos(LINK));
}
void PBasic::
cmdpoke(struct LOC_exec *LINK)
{
union
{
long i;
char *c;
} trick;
/* p2c: basic.p, line 2073: Note: Range checking is OFF [216] */
trick.i = intexpr(LINK);
require(tokcomma, LINK);
*trick.c = (char) intexpr(LINK);
/* p2c: basic.p, line 2077: Note: Range checking is ON [216] */
}
void PBasic::
exec(void)
{
struct LOC_exec V;
V.gotoflag = false;
V.elseflag = false;
V.t = NULL;
char STR1[256] = {0};
try
{
do
{
do
{
V.gotoflag = false;
V.elseflag = false;
while (stmttok != NULL && stmttok->kind == tokcolon)
stmttok = stmttok->next;
V.t = stmttok;
if (V.t != NULL)
{
V.t = V.t->next;
#if defined(PHREEQCI_GUI)
if (phreeqci_gui)
{
if (WaitForSingleObject(hInfiniteLoop, 0) == WAIT_OBJECT_0)
{
nIDErrPrompt = IDS_ERR_INFINITE_LOOP;
errormsg("Possible infinite loop");
}
}
#endif
switch (stmttok->kind)
{
case tokrem:
/* blank case */
break;
case toklist:
cmdlist(&V);
break;
case tokrun:
cmdrun(&V);
break;
case toknew:
cmdnew(&V);
break;
case tokload:
cmdload(false, stringexpr(STR1, &V), &V);
break;
case tokmerge:
cmdload(true, stringexpr(STR1, &V), &V);
break;
case toksave:
cmdsave(&V);
break;
case tokbye:
cmdbye();
break;
case tokdel:
cmddel(&V);
break;
case tokrenum:
cmdrenum(&V);
break;
case toklet:
cmdlet(false, &V);
break;
case tokvar:
cmdlet(true, &V);
break;
case tokprint:
cmdprint(&V);
break;
case tokpunch:
cmdpunch(&V);
break;
case tokput:
cmdput(&V);
break;
case tokchange_por:
cmdchange_por(&V);
break;
case tokchange_surf:
cmdchange_surf(&V);
break;
#if defined PHREEQ98 || defined MULTICHART
case tokgraph_x:
cmdgraph_x(&V);
break;
case tokgraph_y:
cmdgraph_y(&V);
break;
case tokgraph_sy:
cmdgraph_sy(&V);
break;
#endif
#if defined MULTICHART
case tokplot_xy:
cmdplot_xy(&V);
break;
#endif
case tokinput:
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_INPUT_NOTLEGAL;
errormsg ("Basic command INPUT is not a legal command in PHREEQC.");
}
else
{
error_msg ("Basic command INPUT is not a legal command in PHREEQC.", STOP);
}
break;
case tokgoto:
cmdgoto(&V);
break;
case tokif:
cmdif(&V);
break;
case tokelse:
cmdelse(&V);
break;
case tokend:
cmdend(&V);
break;
case tokstop:
P_escapecode = -20;
throw PBasicStop();
//goto _Ltry1;
break;
case tokfor:
cmdfor(&V);
break;
case toknext:
cmdnext(&V);
break;
case tokwhile:
cmdwhile(&V);
break;
case tokwend:
cmdwend(&V);
break;
case tokgosub:
cmdgosub(&V);
break;
case tokreturn:
cmdreturn(&V);
break;
case tokread:
cmdread(&V);
break;
case tokdata:
cmddata(&V);
break;
case tokrestore:
cmdrestore(&V);
break;
case tokgotoxy:
cmdgotoxy(&V);
break;
case tokon:
cmdon(&V);
break;
case tokdim:
cmddim(&V);
break;
case tokerase:
cmderase(&V);
break;
case tokpoke:
cmdpoke(&V);
break;
default:
if (phreeqci_gui)
{
_ASSERTE(nIDErrPrompt == 0);
nIDErrPrompt = IDS_ERR_ILLEGAL;
}
strcat(STR1, "Illegal command in line: ");
if (strcmp(inbuf, "run"))
strcat(STR1, inbuf);
errormsg(STR1);
break;
}
}
if (!V.elseflag && !iseos(&V))
checkextra(&V);
stmttok = V.t;
}
while (V.t != NULL);
if (stmtline != NULL)
{
if (!V.gotoflag)
stmtline = stmtline->next;
if (stmtline != NULL)
stmttok = stmtline->txt;
}
}
while (stmtline != NULL);
}
catch (const PBasicStop&)
{
//_Ltry1:
if (P_escapecode == -20)
PhreeqcPtr->warning_msg("Break");
/* printf("Break"); */
else if (P_escapecode != 42)
{
switch (P_escapecode)
{
case -4:
{
char * error_string = PhreeqcPtr->sformatf( "Integer overflow in BASIC line\n %ld %s", stmtline->num, stmtline->inbuf);
PhreeqcPtr->warning_msg(error_string);
}
break;
case -5:
{
char * error_string = PhreeqcPtr->sformatf( "Divide by zero in BASIC line\n %ld %s", stmtline->num, stmtline->inbuf);
PhreeqcPtr->warning_msg(error_string);
}
break;
case -6:
{
char * error_string = PhreeqcPtr->sformatf( "Real math overflow in BASIC line\n %ld %s", stmtline->num, stmtline->inbuf);
PhreeqcPtr->warning_msg(error_string);
}
break;
case -7:
{
char * error_string = PhreeqcPtr->sformatf( "Real math underflow in BASIC line\n %ld %s", stmtline->num, stmtline->inbuf);
PhreeqcPtr->warning_msg(error_string);
}
break;
case -8:
case -19:
case -18:
case -17:
case -16:
case -15:
{
char * error_string = PhreeqcPtr->sformatf( "Value range error in BASIC line\n %ld %s", stmtline->num, stmtline->inbuf);
PhreeqcPtr->warning_msg(error_string);
}
break;
case -10:
{
char * error_string = PhreeqcPtr->sformatf("I/O Error %d", (int) P_ioresult);
PhreeqcPtr->warning_msg(error_string);
}
break;
default:
if (EXCP_LINE != -1)
{
char * error_string = PhreeqcPtr->sformatf( "%12ld\n", EXCP_LINE);
PhreeqcPtr->warning_msg(error_string);
}
_Escape(P_escapecode);
break;
}
}
if (stmtline != NULL)
{
if (phreeqci_gui)
{
_ASSERTE(nErrLineNumber == 0);
nErrLineNumber = stmtline->num;
}
else
{
char * error_string = PhreeqcPtr->sformatf( " in BASIC line\n %ld %s", stmtline->num, stmtline->inbuf);
error_msg(error_string, CONTINUE);
}
}
} // end catch
} /*exec */
int PBasic::
free_dim_stringvar(varrec *l_varbase)
{
int i, k;
if (l_varbase->numdims > 0)
{
k = 1;
for (i = 0; i < l_varbase->numdims; i++)
{
k = k * (l_varbase->dims[i]);
}
for (i = 0; i < k; i++)
{
PhreeqcPtr->free_check_null(l_varbase->UU.U1.sarr[i]);
}
l_varbase->UU.U1.sarr = (char **) PhreeqcPtr->free_check_null(l_varbase->UU.U1.sarr);
}
return (OK);
}
#if defined MULTICHART
void PBasic::
cmdplot_xy(struct LOC_exec *LINK)
{
bool semiflag;
valrec n[2];
char STR[2][256];
int i = 0;
semiflag = false;
while (!iseos(LINK) && i < 2)
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
i++;
continue;
}
n[i] = expr(LINK);
if (n[i].stringval)
{
strcpy(STR[i], n[i].UU.sval);
PhreeqcPtr->PHRQ_free(n[i].UU.sval);
}
else
numtostr(STR[i], n[i].UU.val);
}
ChartObject *chart = PhreeqcPtr->chart_handler.Get_current_chart();
if (chart == NULL) return;
std::string x_str(STR[0]), y_str(STR[1]);
// Code formerly in PlotXY, included here
{
bool new_sim = false, new_trans = false;
if (chart->Get_FirstCallToUSER_GRAPH() && chart->Get_colnr() == 0)
chart->Set_prev_sim_no(PhreeqcPtr->simulation);
else
chart->Set_prev_sim_no(PhreeqcPtr->simulation);
// Add a curve if necessary
if ((int) chart->Get_Curves().size() == chart->Get_colnr())
{
std::string head("");
if (chart->Get_new_headings().size() > 0)
{
head = chart->Get_new_headings()[0];
chart->Get_new_headings().erase(chart->Get_new_headings().begin());
}
if (chart->Get_new_plotxy_curves().size() > 0)
{
// find plotxy curve definitions
chart->Add_curve(true, head,
chart->Get_new_plotxy_curves()[0].Get_line_w(),
chart->Get_new_plotxy_curves()[0].Get_symbol(),
chart->Get_new_plotxy_curves()[0].Get_symbol_size(),
chart->Get_new_plotxy_curves()[0].Get_y_axis(),
chart->Get_new_plotxy_curves()[0].Get_color()
);
// pop plotxy curve definition
chart->Get_new_plotxy_curves().erase(chart->Get_new_plotxy_curves().begin());
}
else
{
chart->Add_curve(true, head);
}
chart->Set_curve_added(true);
}
if (x_str.size() > 0 && y_str.size() > 0)
{
chart->Get_Curves()[chart->Get_colnr()]->Get_x().push_back(atof(x_str.c_str()));
chart->Get_Curves()[chart->Get_colnr()]->Get_y().push_back(atof(y_str.c_str()));
chart->Set_point_added(true);
// Mark added curve for first point, might have been invisible in DefineCurves
if (chart->Get_Curves()[chart->Get_colnr()]->Get_x().size() == 1)
chart->Set_curve_added(true);
}
}
chart->Set_colnr(chart->Get_colnr() + 1);
}
void PBasic::
cmdgraph_x(struct LOC_exec *LINK)
{
bool semiflag;
valrec n;
semiflag = false;
ChartObject *chart = PhreeqcPtr->chart_handler.Get_current_chart();
if (chart == NULL) return;
while (!iseos(LINK))
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
if (n.stringval)
{
if (strlen(n.UU.sval) > 0)
{
chart->Set_graph_x(atof(n.UU.sval));
}
PhreeqcPtr->PHRQ_free(n.UU.sval);
}
else
chart->Set_graph_x(n.UU.val);
}
if ((int) chart->Get_Curves().size() == chart->Get_colnr())
{
if (chart->Get_new_headings().size() > 0)
{
// remove x heading
//if (chart->Get_colnr() == chart->Get_ColumnOffset())
{
chart->Get_new_headings().erase(chart->Get_new_headings().begin());
}
}
}
}
void PBasic::
cmdgraph_y(struct LOC_exec *LINK)
{
bool semiflag;
valrec n;
semiflag = false;
ChartObject *chart = PhreeqcPtr->chart_handler.Get_current_chart();
if (chart == NULL) return;
while (!iseos(LINK))
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
// wait until x value is known before storing in curve
if (n.stringval)
{
if (strlen(n.UU.sval) > 0)
{
chart->Get_graph_y()[chart->Get_colnr()] = atof(n.UU.sval);
}
PhreeqcPtr->PHRQ_free(n.UU.sval);
}
else
{
chart->Get_graph_y()[chart->Get_colnr()] = n.UU.val;
}
chart->Set_point_added(true);
// Add a new curve if necessary
if ((int) chart->Get_Curves().size() == chart->Get_colnr())
{
if (chart->Get_new_headings().size() > 0)
{
chart->Add_curve(false, chart->Get_new_headings()[0]);
chart->Get_new_headings().erase(chart->Get_new_headings().begin());
}
else
{
chart->Add_curve(false);
}
chart->Set_curve_added(true);
}
chart->Set_colnr(chart->Get_colnr() + 1);
}
}
void PBasic::
cmdgraph_sy(struct LOC_exec *LINK)
{
bool semiflag;
valrec n;
semiflag = false;
ChartObject *chart = PhreeqcPtr->chart_handler.Get_current_chart();
if (chart == NULL) return;
while (!iseos(LINK))
{
semiflag = false;
if ((unsigned long) LINK->t->kind < 32 &&
((1L << ((long) LINK->t->kind)) &
((1L << ((long) toksemi)) | (1L << ((long) tokcomma)))) != 0)
{
semiflag = true;
LINK->t = LINK->t->next;
continue;
}
n = expr(LINK);
chart->Get_secondary_y()[chart->Get_colnr()] = true;
// wait until x value is known before storing in curve
if (n.stringval)
{
if (strlen(n.UU.sval) > 0)
{
chart->Get_graph_y()[chart->Get_colnr()] = atof(n.UU.sval);
}
PhreeqcPtr->PHRQ_free(n.UU.sval);
}
else
chart->Get_graph_y()[chart->Get_colnr()] = n.UU.val;
chart->Set_point_added(true);
// Add a new curve if necessary
if ((int) chart->Get_Curves().size() == chart->Get_colnr())
{
if (chart->Get_new_headings().size() > 0)
{
chart->Add_curve(false, chart->Get_new_headings()[0]);
chart->Get_new_headings().erase(chart->Get_new_headings().begin());
}
else
{
chart->Add_curve(false);
}
chart->Set_curve_added(true);
}
chart->Set_colnr(chart->Get_colnr() + 1);
}
}
#endif // MULTICHART
/* In case your system lacks these... */
long PBasic::
my_labs(long l_x)
{
return ((l_x > 0) ? l_x : -l_x);
}
/* #define __STDC__ */ /* PHREEQ98 */
void * PBasic::
my_memmove(void * d, Const void * l_s, size_t n)
{
char *dd = (char *) d, *ss = (char *) l_s;
if (dd < ss || (unsigned int) (dd - ss) >= n)
{
memcpy(dd, ss, n);
}
else if (n > 0)
{
dd += n;
ss += n;
while (n-- > 0)
*--dd = *--ss;
}
return d;
}
void * PBasic::
my_memcpy(void * d, Const void * l_s, size_t n)
{
char *ss = (char *) l_s, *dd = (char *) d;
while (n-- > 0)
*dd++ = *ss++;
return d;
}
int PBasic::
my_memcmp(Const void * s1, Const void * s2, size_t n)
{
char *a = (char *) s1, *b = (char *) s2;
int i;
while (n-- > 0)
if ((i = (*a++) - (*b++)) != 0)
return i;
return 0;
}
void * PBasic::
my_memset(void * d, int c, size_t n)
{
char *dd = (char *) d;
while (n-- > 0)
*dd++ = (char) c;
return d;
}
int PBasic::
my_toupper(int c)
{
if (islower(c))
return _toupper(c);
else
return c;
}
int PBasic::
my_tolower(int c)
{
if (isupper(c))
return _tolower(c);
else
return c;
}
long PBasic::
ipow(long a, long b)
{
long v;
if (a == 0 || a == 1)
return a;
if (a == -1)
return (b & 1) ? -1 : 1;
if (b < 0)
return 0;
if (a == 2)
return 1L << b;
v = (b & 1) ? a : 1;
while ((b >>= 1) > 0)
{
a *= a;
if (b & 1)
v *= a;
}
return v;
}
/* Common string functions: */
/* Store in "ret" the substring of length "len" starting from "pos" (1-based).
Store a shorter or null string if out-of-range. Return "ret". */
char * PBasic::
strsub(char *ret, char *l_s, int pos,
int len)
{
char *s2;
if (--pos < 0 || len <= 0)
{
*ret = 0;
return ret;
}
while (pos > 0)
{
if (!*l_s++)
{
*ret = 0;
return ret;
}
pos--;
}
s2 = ret;
while (--len >= 0)
{
if (!(*s2++ = *l_s++))
return ret;
}
*s2 = 0;
return ret;
}
/* Return the index of the first occurrence of "pat" as a substring of "s",
starting at index "pos" (1-based). Result is 1-based, 0 if not found. */
int PBasic::
strpos2(char *l_s, char *pat, int pos)
{
char *cp, ch;
int slen;
if (--pos < 0)
return 0;
slen = (int) strlen(l_s) - pos;
cp = l_s + pos;
if (!(ch = *pat++))
return 0;
pos = (int) strlen(pat);
slen -= pos;
while (--slen >= 0)
{
if (*cp++ == ch && !strncmp(cp, pat, pos))
return (int) (cp - l_s);
}
return 0;
}
/* Case-insensitive version of strcmp. */
int PBasic::
strcicmp(char *s1, char *s2)
{
unsigned char c1, c2;
while (*s1)
{
if (*s1++ != *s2++)
{
if (!s2[-1])
return 1;
c1 = (unsigned char) toupper(s1[-1]);
c2 = (unsigned char) toupper(s2[-1]);
if (c1 != c2)
return c1 - c2;
}
}
if (*s2)
return -1;
return 0;
}
/* HP and Turbo Pascal string functions: */
/* Trim blanks at left end of string. */
char * PBasic::
strltrim(char *l_s)
{
while (Isspace((int) *l_s++));
return l_s - 1;
}
/* Trim blanks at right end of string. */
char * PBasic::
strrtrim(char *l_s)
{
char *s2 = l_s;
if (!*l_s)
return l_s;
while (*++s2);
while (s2 > l_s && Isspace((int) *--s2))
*s2 = 0;
return l_s;
}
/* Store in "ret" string "s" with enough pad chars added to reach "size". */
/* Copy the substring of length "len" from index "spos" of "s" (1-based)
to index "dpos" of "d", lengthening "d" if necessary. Length and
indices must be in-range. */
void PBasic::
strmove(int len, char *l_s, int spos,
char *d, int dpos)
{
l_s += (size_t)spos - 1;
d += (size_t)dpos - 1;
while (*d && --len >= 0)
*d++ = *l_s++;
if (len > 0)
{
while (--len >= 0)
*d++ = *l_s++;
*d = 0;
}
}
/* Insert string "src" at index "pos" of "dst". */
void PBasic::
strinsert(char *src, char *dst, int pos)
{
int slen, dlen;
if (--pos < 0)
return;
dlen = (int) strlen(dst);
dst += dlen;
dlen -= pos;
if (dlen <= 0)
{
strcpy(dst, src);
return;
}
slen = (int) strlen(src);
do
{
dst[slen] = *dst;
--dst;
}
while (--dlen >= 0);
dst++;
while (--slen >= 0)
*dst++ = *src++;
}
/* File functions */
/* Peek at next character of input stream; return EOF at end-of-file. */
int PBasic::
P_peek(FILE * f)
{
int ch;
ch = getc(f);
if (ch == EOF)
return EOF;
ungetc(ch, f);
return (ch == '\n') ? ' ' : ch;
}
/* Check if at end of file, using Pascal "eof" semantics. End-of-file for
stdin is broken; remove the special case for it to be broken in a
different way. */
/*int P_eof(FILE *f)*/
int PBasic::
P_eof(void)
{
return 0;
}
/* Check if at end of line (or end of entire file). */
int PBasic::
P_eoln(FILE * f)
{
int ch;
ch = getc(f);
if (ch == EOF)
return 1;
ungetc(ch, f);
return (ch == '\n');
}
/* Read a packed array of characters from a file. */
void PBasic::
P_readpaoc(FILE * f, char *l_s, int len)
{
int ch;
for (;;)
{
if (len <= 0)
return;
ch = getc(f);
if (ch == EOF || ch == '\n')
break;
*l_s++ = (char) ch;
--len;
}
while (--len >= 0)
*l_s++ = ' ';
if (ch != EOF)
ungetc(ch, f);
}
void PBasic::
P_readlnpaoc(FILE * f, char *l_s, int len)
{
int ch;
for (;;)
{
ch = getc(f);
if (ch == EOF || ch == '\n')
break;
if (len > 0)
{
*l_s++ = (char) ch;
--len;
}
}
while (--len >= 0)
*l_s++ = ' ';
}
/* Compute maximum legal "seek" index in file (0-based). */
long PBasic::
P_maxpos(FILE * f)
{
long savepos = ftell(f);
long val;
if (fseek(f, 0L, SEEK_END))
return -1;
val = ftell(f);
if (fseek(f, savepos, SEEK_SET))
return -1;
return val;
}
/* Use packed array of char for a file name. */
char * PBasic::
P_trimname(char * fn, int len)
{
char *cp = fnbuf;
while (--len >= 0 && *fn && !isspace((int) *fn))
*cp++ = *fn++;
*cp = 0;
return fnbuf;
}
/* Pascal's "memavail" doesn`t make much sense in Unix with virtual memory.
We fix memory size as 10Meg as a reasonable compromise. */
long PBasic::
memavail(void)
{
return 10000000; /* worry about this later! */
}
long PBasic::
maxavail(void)
{
return memavail();
}
/* Sets are stored as an array of longs. S[0] is the size of the set;
S[N] is the n`th 32-bit chunk of the set. S[0] equals the maximum
I such that S[I] is nonzero. S[0] is zero for an empty set. Within
each long, bits are packed from lsb to msb. The first bit of the
set is the element with ordinal value 0. (Thus, for a "set of 5..99",
the lowest five bits of the first long are unused and always zero.) */
/* (Sets with 32 or fewer elements are normally stored as plain longs.) */
long * PBasic::
P_setunion(long *d, long *s1, long *s2) /* d := s1 + s2 */
{
long *dbase = d++;
int sz1 = *s1++, sz2 = *s2++;
while (sz1 > 0 && sz2 > 0)
{
*d++ = *s1++ | *s2++;
sz1--, sz2--;
}
while (--sz1 >= 0)
*d++ = *s1++;
while (--sz2 >= 0)
*d++ = *s2++;
*dbase = (int) (d - dbase - 1);
return dbase;
}
long * PBasic::
P_setint(long *d, long *s1, long *s2) /* d := s1 * s2 */
{
long *dbase = d++;
int sz1 = *s1++, sz2 = *s2++;
while (--sz1 >= 0 && --sz2 >= 0)
*d++ = *s1++ & *s2++;
while (--d > dbase && !*d);
*dbase = (int) (d - dbase);
return dbase;
}
long * PBasic::
P_setdiff(long *d, long *s1, long *s2) /* d := s1 - s2 */
{
long *dbase = d++;
int sz1 = *s1++, sz2 = *s2++;
while (--sz1 >= 0 && --sz2 >= 0)
*d++ = *s1++ & ~*s2++;
if (sz1 >= 0)
{
while (sz1-- >= 0)
*d++ = *s1++;
}
while (--d > dbase && !*d);
*dbase = (int) (d - dbase);
return dbase;
}
long * PBasic::
P_setxor(long *d, long *s1, long *s2) /* d := s1 / s2 */
{
long *dbase = d++;
int sz1 = *s1++, sz2 = *s2++;
while (sz1 > 0 && sz2 > 0)
{
*d++ = *s1++ ^ *s2++;
sz1--, sz2--;
}
while (--sz1 >= 0)
*d++ = *s1++;
while (--sz2 >= 0)
*d++ = *s2++;
while (--d > dbase && !*d);
*dbase = (int) (d - dbase);
return dbase;
}
long * PBasic::
P_addset(long *l_s, unsigned val) /* s := s + [val] */
{
long *sbase = l_s;
int bit, size;
bit = val % SETBITS;
val /= SETBITS;
size = *l_s;
if ((long) ++val > size)
{
l_s += size;
while ((long) val > size)
*++l_s = 0, size++;
*sbase = size;
}
else
l_s += val;
*l_s |= 1L << bit;
return sbase;
}
//long * PBasic::
//P_addsetr(long *l_s, unsigned v1, unsigned v2) /* s := s + [v1..v2] */
//{
// long *sbase = l_s;
// int b1, b2, size;
// if ((int) v1 > (int) v2)
// return sbase;
// b1 = v1 % SETBITS;
// v1 /= SETBITS;
// b2 = v2 % SETBITS;
// v2 /= SETBITS;
// size = *l_s;
// v1++;
// if ((int) ++v2 > size)
// {
// while ((int) v2 > size)
// l_s[++size] = 0;
// l_s[v2] = 0;
// *l_s = v2;
// }
// l_s += v1;
// if (v1 == v2)
// {
// *l_s |= (~((-2L) << (b2 - b1))) << b1;
// }
// else
// {
// *l_s++ |= (-1L) << b1;
// while (++v1 < v2)
// *l_s++ = -1;
// *l_s |= ~((-2L) << b2);
// }
// return sbase;
//}
long * PBasic::
P_remset(long *l_s, unsigned val) /* s := s - [val] */
{
int bit;
bit = val % SETBITS;
val /= SETBITS;
if ((long) ++val <= *l_s)
{
if (!(l_s[val] &= ~(1L << bit)))
while (*l_s && !l_s[*l_s])
(*l_s)--;
}
return l_s;
}
int PBasic::
P_setequal(long *s1, long *s2) /* s1 = s2 */
{
int size = *s1++;
if (*s2++ != size)
return 0;
while (--size >= 0)
{
if (*s1++ != *s2++)
return 0;
}
return 1;
}
int PBasic::
P_subset(long *s1, long *s2) /* s1 <= s2 */
{
int sz1 = *s1++, sz2 = *s2++;
if (sz1 > sz2)
return 0;
while (--sz1 >= 0)
{
if (*s1++ & ~*s2++)
return 0;
}
return 1;
}
long * PBasic::
P_setcpy(long *d, long *l_s) /* d := s */
{
long *save_d = d;
#ifdef SETCPY_MEMCPY
memcpy(d, l_s, (*l_s + 1) * sizeof(long));
#else
int i = *l_s + 1;
while (--i >= 0)
*d++ = *l_s++;
#endif
return save_d;
}
/* s is a "smallset", i.e., a 32-bit or less set stored
directly in a long. */
long * PBasic::
P_expset(long *d, long l_s) /* d := s */
{
if (l_s)
{
d[1] = l_s;
*d = 1;
}
else
*d = 0;
return d;
}
long PBasic::
P_packset(long *l_s) /* convert s to a small-set */
{
if (*l_s++)
return *l_s;
else
return 0;
}
int PBasic::
_OutMem(void)
{
return _Escape(-2);
}
int PBasic::
_CaseCheck(void)
{
return _Escape(-9);
}
int PBasic::
_NilCheck(void)
{
return _Escape(-3);
}
/* The following is suitable for the HP Pascal operating system.
It might want to be revised when emulating another system. */
char * PBasic::
_ShowEscape(char *buf, int code, int ior, char *prefix)
{
char *bufp;
if (prefix && *prefix)
{
strcpy(buf, prefix);
strcat(buf, ": ");
bufp = buf + strlen(buf);
}
else
{
bufp = buf;
}
if (code == -10)
{
sprintf(bufp, "Pascal system I/O error %d", ior);
switch (ior)
{
case 3:
strcat(buf, " (illegal I/O request)");
break;
case 7:
strcat(buf, " (bad file name)");
break;
case FileNotFound: /*10 */
strcat(buf, " (file not found)");
break;
case FileNotOpen: /*13 */
strcat(buf, " (file not open)");
break;
case BadInputFormat: /*14 */
strcat(buf, " (bad input format)");
break;
case 24:
strcat(buf, " (not open for reading)");
break;
case 25:
strcat(buf, " (not open for writing)");
break;
case 26:
strcat(buf, " (not open for direct access)");
break;
case 28:
strcat(buf, " (string subscript out of range)");
break;
case EndOfFile: /*30 */
strcat(buf, " (end-of-file)");
break;
case FileWriteError: /*38 */
strcat(buf, " (file write error)");
break;
}
}
else
{
sprintf(bufp, "Pascal system error %d", code);
switch (code)
{
case -2:
strcat(buf, " (out of memory)");
break;
case -3:
strcat(buf, " (reference to NIL pointer)");
break;
case -4:
strcat(buf, " (integer overflow)");
break;
case -5:
strcat(buf, " (divide by zero)");
break;
case -6:
strcat(buf, " (real math overflow)");
break;
case -8:
strcat(buf, " (value range error)");
break;
case -9:
strcat(buf, " (CASE value range error)");
break;
case -12:
strcat(buf, " (bus error)");
break;
case -20:
strcat(buf, " (stopped by user)");
break;
}
}
return buf;
}
int PBasic::
_Escape(int code)
{
P_escapecode = code;
throw PBasicStop();
// following not used
}
int PBasic::
_EscIO(int code)
{
P_ioresult = code;
return _Escape(-10);
}
const std::map<const std::string, PBasic::BASIC_TOKEN>::value_type temp_tokens[] = {
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("+", PBasic::tokplus),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("-", PBasic::tokminus),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("*", PBasic::toktimes),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("/", PBasic::tokdiv),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("^", PBasic::tokup),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("( or [", PBasic::toklp),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type(") or ]", PBasic::tokrp),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("]", PBasic::tokcomma),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type(";", PBasic::toksemi),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type(":", PBasic::tokcolon),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("=", PBasic::tokeq),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("<", PBasic::toklt),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("<=", PBasic::tokle),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type(">", PBasic::tokgt),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type(">=", PBasic::tokge),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("and", PBasic::tokand),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("or", PBasic::tokor),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("xor", PBasic::tokxor),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("not", PBasic::toknot),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("mod", PBasic::tokmod),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sqr", PBasic::toksqr),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sqrt", PBasic::toksqrt),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("ceil", PBasic::tokceil),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("floor", PBasic::tokfloor),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sin", PBasic::toksin),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("cos", PBasic::tokcos),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("tan", PBasic::toktan),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("arctan", PBasic::tokarctan),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("log", PBasic::toklog),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("exp", PBasic::tokexp),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("abs", PBasic::tokabs),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sgn", PBasic::toksgn),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("str$", PBasic::tokstr_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("val", PBasic::tokval),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("chr$", PBasic::tokchr_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("eol$", PBasic::tokeol_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("eol_notab$", PBasic::tokeol_notab_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("no_newline$", PBasic::tokno_newline_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("asc", PBasic::tokasc),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("len", PBasic::toklen),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("mid$", PBasic::tokmid_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("peek", PBasic::tokpeek),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("let", PBasic::toklet),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("input", PBasic::tokinput),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("goto", PBasic::tokgoto),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("go to", PBasic::tokgoto),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("if", PBasic::tokif),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("end", PBasic::tokend),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("stop", PBasic::tokstop),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("for", PBasic::tokfor),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("next", PBasic::toknext),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("while", PBasic::tokwhile),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("wend", PBasic::tokwend),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("gosub", PBasic::tokgosub),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("return", PBasic::tokreturn),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("read", PBasic::tokread),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("data", PBasic::tokdata),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("restore", PBasic::tokrestore),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("gotoxy", PBasic::tokgotoxy),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("on", PBasic::tokon),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("dim", PBasic::tokdim),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("erase", PBasic::tokerase),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("poke", PBasic::tokpoke),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("list", PBasic::toklist),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("run", PBasic::tokrun),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("new", PBasic::toknew),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("load", PBasic::tokload),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("merge", PBasic::tokmerge),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("save", PBasic::toksave),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("bye", PBasic::tokbye),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("quit", PBasic::tokbye),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("del", PBasic::tokdel),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("renum", PBasic::tokrenum),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("then", PBasic::tokthen),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("else", PBasic::tokelse),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("to", PBasic::tokto),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("step", PBasic::tokstep),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("act", PBasic::tokact),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("add_heading", PBasic::tokadd_heading),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("alk", PBasic::tokalk),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("aphi", PBasic::tokaphi),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("calc_value", PBasic::tokcalc_value),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("callback", PBasic::tokcallback),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("cell_no", PBasic::tokcell_no),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("change_por", PBasic::tokchange_por),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("change_surf", PBasic::tokchange_surf),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("charge_balance", PBasic::tokcharge_balance),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("current_a", PBasic::tokcurrent_a),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("debye_length", PBasic::tokdebye_length),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("delta_h_phase", PBasic::tokdelta_h_phase),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("delta_h_species", PBasic::tokdelta_h_species),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("description", PBasic::tokdescription),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("dh_a0", PBasic::tokdh_a0),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("dh_a", PBasic::tokdh_a),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("dh_av", PBasic::tokdh_av),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("dh_b", PBasic::tokdh_b),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("dh_bdot", PBasic::tokdh_bdot),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("diff_c", PBasic::tokdiff_c),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("dist", PBasic::tokdist),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("edl", PBasic::tokedl),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("edl_species", PBasic::tokedl_species),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("eps_r", PBasic::tokeps_r),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("eq_frac", PBasic::tokeq_frac),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("equi", PBasic::tokequi),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("equi_delta", PBasic::tokequi_delta),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("equiv_frac", PBasic::tokeq_frac),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("exists", PBasic::tokexists),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("gamma", PBasic::tokgamma),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("gas", PBasic::tokgas),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("gas_p", PBasic::tokgas_p),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("gas_vm", PBasic::tokgas_vm),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("get", PBasic::tokget),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("get_por", PBasic::tokget_por),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("gfw", PBasic::tokgfw),
#if defined (PHREEQ98) || defined (MULTICHART)
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("graph_x", PBasic::tokgraph_x),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("graph_y", PBasic::tokgraph_y),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("graph_sy", PBasic::tokgraph_sy),
#endif
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("instr", PBasic::tokinstr),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("iso", PBasic::tokiso),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("iso_unit", PBasic::tokiso_unit),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("iterations", PBasic::tokiterations),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("kappa", PBasic::tokkappa),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("kin", PBasic::tokkin),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("kin_delta", PBasic::tokkin_delta),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("kin_time", PBasic::tokkin_time),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("kinetics_formula", PBasic::tokkinetics_formula),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("kinetics_formula$", PBasic::tokkinetics_formula),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("la", PBasic::tokla),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("lg", PBasic::toklg),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("list_s_s", PBasic::toklist_s_s),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("lk_named", PBasic::toklk_named),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("lk_phase", PBasic::toklk_phase),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("lk_species", PBasic::toklk_species),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("lm", PBasic::toklm),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("log10", PBasic::toklog10),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("ltrim", PBasic::tokltrim),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("m0", PBasic::tokm0),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("m", PBasic::tokm),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("mcd_jtot", PBasic::tokmcd_jtot),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("mcd_jconc", PBasic::tokmcd_jconc),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("misc1", PBasic::tokmisc1),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("misc2", PBasic::tokmisc2),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("mol", PBasic::tokmol),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("mu", PBasic::tokmu),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("osmotic", PBasic::tokosmotic),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("pad", PBasic::tokpad),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("pad$", PBasic::tokpad_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("parm", PBasic::tokparm),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("percent_error", PBasic::tokpercent_error),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("phase_formula", PBasic::tokphase_formula),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("phase_formula$", PBasic::tokphase_formula_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("phase_vm", PBasic::tokphase_vm),
#if defined MULTICHART
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("plot_xy", PBasic::tokplot_xy),
#endif
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("porevolume", PBasic::tokporevolume),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("pot_v", PBasic::tokpot_v),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("pr_p", PBasic::tokpr_p),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("pr_phi", PBasic::tokpr_phi),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("pressure", PBasic::tokpressure),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("print", PBasic::tokprint),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("punch", PBasic::tokpunch),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("put", PBasic::tokput),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("qbrn", PBasic::tokqbrn),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("rem", PBasic::tokrem),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("rho", PBasic::tokrho),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("rho_0", PBasic::tokrho_0),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("rtrim", PBasic::tokrtrim),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("rxn", PBasic::tokrxn),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("s_s", PBasic::toks_s),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sc", PBasic::toksc),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("setdiff_c", PBasic::toksetdiff_c),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("si", PBasic::toksi),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sim_no", PBasic::toksim_no),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sim_time", PBasic::toksim_time),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("soln_vol", PBasic::toksoln_vol),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("species_formula", PBasic::tokspecies_formula),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("species_formula$", PBasic::tokspecies_formula_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sr", PBasic::toksr),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("step_no", PBasic::tokstep_no),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("str_e$", PBasic::tokstr_e_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("str_f$", PBasic::tokstr_f_),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sum_gas", PBasic::toksum_gas),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sum_s_s", PBasic::toksum_s_s),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sum_species", PBasic::toksum_species),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("surf", PBasic::toksurf),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sys", PBasic::toksys),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("t_sc", PBasic::tokt_sc),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("tc", PBasic::toktc),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("time", PBasic::toktime),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("title", PBasic::toktitle),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("tk", PBasic::toktk),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("tot", PBasic::toktot),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("total_time", PBasic::toktotal_time),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("totmol", PBasic::toktotmol),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("totmole", PBasic::toktotmole),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("totmoles", PBasic::toktotmoles),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("trim", PBasic::toktrim),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("viscos", PBasic::tokviscos),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("viscos_0", PBasic::tokviscos_0),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("vm", PBasic::tokvm),
/* PHAST */
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("cell_pore_volume", PBasic::tokcell_pore_volume),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("cell_porosity", PBasic::tokcell_porosity),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("cell_saturation", PBasic::tokcell_saturation),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("cell_volume", PBasic::tokcell_volume),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("transport_cell_no", PBasic::toktransport_cell_no),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("velocity_x", PBasic::tokvelocity_x),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("velocity_y", PBasic::tokvelocity_y),
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("velocity_z", PBasic::tokvelocity_z),
/* Undocumented */
std::map<const std::string, PBasic::BASIC_TOKEN>::value_type("sa_declercq", PBasic::toksa_declercq)
};
std::map<const std::string, PBasic::BASIC_TOKEN> PBasic::command_tokens(temp_tokens, temp_tokens + sizeof temp_tokens / sizeof temp_tokens[0]);
/* End. */