#include "Phreeqc.h"
#include "phqalloc.h"

#if defined(PHREEQCI_GUI)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif

/* ---------------------------------------------------------------------- */
int Phreeqc::
parse_eq(char* eqn, std::vector<class elt_list>& new_elt_list, int association)
/* ---------------------------------------------------------------------- */
/*
 *   function to break equation up into component species
 *   returns species name, coefficient, and charge in global variable "rxn_list".
 *   Also returns pointer to elt_list structure array with list of elements
 *   and coefficients in species.
 *   rxn_list     global variable, output with contiguous rxn_list structures,
 *                      which is the reaction.  Target species is first in
 *                      list, coefficient is -1.0.
 *
 *   Argurments:
 *      *eqn         input,  pointer to equation to be parsed.
 *     **elt_ptr     output, pointer to contiguous elt_list structures,
 *                           which is list of elements and coefficients in the
 *                           target species.
 *       association input, TRUE or FALSE if reaction is an association reaction
 */
{
	int i;
	LDBLE coef, l_z;
	char c;
	const char* cptr;
	char token[MAX_LENGTH];

	paren_count = 0;
	/*
	 *   Remove white space
	 */
	squeeze_white(eqn);
	/*
	 *   Check for illegal characters
	 */
	for (i = 0; (c = eqn[i]) != '\0'; i++)
	{
		if (islegit(c) == FALSE)
		{
			error_string = sformatf("Character is not allowed,\
 %c (octal: %o).", c, c);
			error_msg(error_string, CONTINUE);
			return (ERROR);
		}
	}

	/*
	 *   Find coefficients, name, and charge for each species for lhs
	 */
	count_trxn = 0;
	trxn.dz[0] = trxn.dz[1] = trxn.dz[2] = 0.0;
	cptr = eqn;
	c = cptr[0];
	for (;;)
	{
		if (c == '=')
			break;
		if (c == '\0')
		{
			error_string = sformatf("Equation has no equal sign.\n\t%s", eqn);
			error_msg(error_string, CONTINUE);
			return (ERROR);
		}
		if (get_species(&cptr) == ERROR)
		{
			return (ERROR);
		}
		c = cptr[0];
		if (association == FALSE)
		{
			trxn.token[count_trxn].coef *= -1.0;
		}
		count_trxn++;
	}
	/*
	 *   Get coefficient, name, and charge of species for dissociation reaction
	 */
	cptr++;
	if (association == TRUE)
	{
		if (get_species(&cptr) == ERROR)
		{
			return (ERROR);
		}
		trxn.token[count_trxn].coef *= -1.0;
		/*   Swap species into first structure position */
		const char* char_ptr = trxn.token[0].name;
		coef = trxn.token[0].coef;
		l_z = trxn.token[0].z;
		trxn.token[0].name = trxn.token[count_trxn].name;
		trxn.token[0].coef = trxn.token[count_trxn].coef;
		trxn.token[0].z = trxn.token[count_trxn].z;
		trxn.token[count_trxn].name = char_ptr;
		trxn.token[count_trxn].coef = coef;
		trxn.token[count_trxn].z = l_z;
		count_trxn++;
	}
	/*
	 *   Get reaction species from rhs of equation
	 */
	c = cptr[0];
	for (;;)
	{
		if (c == '\0')
			break;
		if (get_species(&cptr) == ERROR)
		{
			return (ERROR);
		}
		c = cptr[0];
		if (association == TRUE)
		{
			trxn.token[count_trxn].coef *= -1.0;
		}
		count_trxn++;
	}
	/*
	 *   Sort list of reaction species
	 */
	trxn_sort();
	/*
	 *   Get elements in species or mineral formula
	 */
	count_elts = 0;
	strcpy(token, trxn.token[0].name);
	replace("(s)", "", token);
	replace("(S)", "", token);
	replace("(g)", "", token);
	replace("(G)", "", token);
	const char* char_ptr = token;

	if (get_elts_in_species(&char_ptr, trxn.token[0].coef) == ERROR)
	{
		return (ERROR);
	}
	/*
	 *   Sort elements in reaction and combine
	 */
	if (elt_list_combine() == ERROR)
		return (ERROR);
	/*
	 *   Malloc space and store element data for return
	 */
	new_elt_list.resize(count_elts + 1);
	for (i = 0; i < count_elts; i++)
	{
		new_elt_list[i].elt = elt_list[i].elt;
		new_elt_list[i].coef = -elt_list[i].coef;
	}
	new_elt_list[count_elts].elt = NULL;

	/*
	 *   Debugging print of parsed equation
		trxn_print();
	 */
	return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
check_eqn(int association)
/* ---------------------------------------------------------------------- */
/*
 *   Check that equation is balanced reaction. Uses array "trxn.token" and
 *   assumes "count_trxn" is set to number of species in reaction.
 *   Charge and elements are checked.
 *
 *   Arguments:
 *
 *      association  input, TRUE or FALSE if reaction is an association reaction.
 */
{
	int i;
	int oops = 0;
	LDBLE sumcharge;

	paren_count = 0;
	count_elts = 0;
/*
 *   Check that coefficient of first species is -1.0
 */
	if (equal(trxn.token[0].coef, -1.0, TOL) == FALSE)
	{
		if (association == TRUE)
		{
			error_string = sformatf(
					"Coefficient of first species on rhs is not equal to 1.0.");
			error_msg(error_string, CONTINUE);
		}
		else
		{
			error_string = sformatf(
					"Coefficient of mineral (first on lhs) is not equal to 1.0.");
			error_msg(error_string, CONTINUE);
		}
		return (ERROR);
	}
/*
 *   Go through all species in the reaction; sum the charge and store elements
 */
	sumcharge = 0.0;
	for (i = 0; i < count_trxn; i++)
	{
		sumcharge += (trxn.token[i].coef) * (trxn.token[i].z);
		const char* t_ptr = trxn.token[i].name;
		if (get_elts_in_species(&t_ptr, trxn.token[i].coef) == ERROR)
		{
			return (ERROR);
		}
	}
/*
 *   Sort elements in reaction and combine
 */
	if (elt_list_combine() == ERROR)
		return (ERROR);
/*
 *   Check charge
 */
	if (equal(sumcharge, 0.0, TOL) == FALSE)
	{
		error_string = sformatf( "Equation is not charge balanced, right - left = %7.4f moles charge", sumcharge);
		error_msg(error_string, CONTINUE);
		oops++;
	}
/*
 *   Check mass balance
 */
	for (i = 0; i < count_elts; i++)
	{
		if ((equal(elt_list[i].coef, 0.0, TOL) == FALSE) &&
			strncmp((elt_list[i].elt)->name, "e", MAX_LENGTH) != 0)
		{
			error_string = sformatf(
				"Equation does not balance for element, %s: right - left = %7.4f moles",
				(elt_list[i].elt)->name, elt_list[i].coef);
			error_msg(error_string, CONTINUE);
			oops++;
		}
	}
	if (oops == 0)
	{
		return (OK);
	}
	else
	{
		return (ERROR);
	}
}

/* ---------------------------------------------------------------------- */
int Phreeqc::
get_charge(char *charge, LDBLE * l_z)
/* ---------------------------------------------------------------------- */
/*
 *   Function takes character string and calculates the charge on
 *   the species.  Charge can be in two forms: (1) string of "+" or "-"
 *   or (2) + or - followed by an integer. Charge is reduced to form (2)
 *   and stored in the pointer location *charge.
 *
 *   Arguments:
 *      *charge    input, string containing charge
 *                 output, string containing charge of the form + or -
 *                    followed by an integer, if integer greater than 1.
 *      *z         output, value of charge.
 *
 *   Returns:
 *      ERROR,
 *      OK.
 */
{
	int i;
	char* ptr;
	char c, c1;
/*
 *   Charge is zero
 */
	if ((c = charge[0]) == '\0')
	{
		*l_z = 0.0;
		return (OK);
	}
/*
 *   Error check for + or - at start of string
 */
	if (c != '+' && c != '-')
	{
		error_string = sformatf(
				"Character string for charge does not start with + or -,\t%s.",
				charge);
		error_msg(error_string, CONTINUE);
		return (ERROR);
	}
/*
 *   Count string of +'s or -'s
 */
	i = 0;
	while (c == (c1 = charge[i++]));
	i--;
	if (c1 == '\0')
	{
		if (c == '-')
			i = -i;
	}
	else
	{
/*
 *   + or - followed by a number
 */
		errno = 0;
		i = strtol(charge, &ptr, 0);
/*
 *   Truncate fractional part of charge if all zeros
 */
		if (*ptr != '\0')
		{
			if (*ptr == '.')
			{
				while (*(++ptr) != '\0')
				{
					if (*ptr != '0')
					{
						char* ptr;
						*l_z = strtod(charge, &ptr);
						return (OK);
					}
				}
/*
 *   Non-numeric characters
 */
			}
			else
			{
				error_string = sformatf(
						"Error in character string for charge, %s.", charge);
				error_msg(error_string, CONTINUE);
				return (ERROR);
			}
		}
	}
/*
 *   Charge is zero, must have had +0 or -0 in eqn
 */
	if (i == 0)
	{
		charge[0] = '\0';
	}
/*
 *   Charge is +1 or -1, single + or -
 */
	if (abs(i) == 1)
	{
		charge[0] = c;
		charge[1] = '\0';
	}
/*
 *   Abs(z)>1, set charge to + or - plus integer
 */
	if (abs(i) > 1)
	{
		if (sprintf(charge, "%-+d", i) == EOF)
		{
			error_string = sformatf(
					"Error converting charge to character string, %s.",
					charge);
			error_msg(error_string, CONTINUE);
			return (ERROR);
		}
	}
	*l_z = i;
	return (OK);
}

/* ---------------------------------------------------------------------- */
int Phreeqc::
get_coef(LDBLE * coef, const char **eqnaddr)
/* ---------------------------------------------------------------------- */
/*
 *   Function reads through eqn and determines the coefficient of the next
 *   species.
 *
 *   Arguments:
 *       *coef    output, coefficient of next species.
 *
 *      **eqnaddr input, pointer to a position in eqn to start parsing
 *                output, pointer to next position after coefficient
 *
 *   Returns:
 *      ERROR,
 *      OK.
 */
{
	int i;
	char c, c1;
	const char* cptr;
	const char* rest;
	char* ptr1;
	char token[MAX_LENGTH];;

	rest = *eqnaddr;
	cptr = *eqnaddr;				/* address of a position in eqn */
	c = *cptr;					/* character in eqn */
	*coef = 0.0;
/*
 *   No leading sign or number
 */
	if (isalpha((int) c) ||
		(c == '(') || (c == ')') || (c == '[') || (c == ']'))
	{
		*coef = 1.0;
		return (OK);
	}
/*
 *   Leading +, no digits
 */
	c1 = *(cptr + 1);
	if (c == '+' &&
		(isalpha((int) c1) ||
		 (c1 == '(') || (c1 == ')') || (c1 == '[') || (c1 == ']')))
	{
		*eqnaddr = ++cptr;
		*coef = 1.0;
		return (OK);
	}
/*
 *   Leading -, no digits
 */
	if (c == '-' &&
		(isalpha((int) c1) ||
		 (c1 == '(') || (c1 == ')') || (c1 == '[') || (c1 == ']')))
	{
		*eqnaddr = ++cptr;
		*coef = -1.0;
		return (OK);
	}
	i = 0;
/*
 *   Has number coefficient
 */
	if (isdigit((int) c) || c == '+' || c == '-' || c == '.')
	{
		while (isdigit((int) c) || c == '+' || c == '-' || c == '.')
		{
			token[i++] = c;
			if (i >= MAX_LENGTH)
			{
				error_string = sformatf(
						"Coefficient has more than MAX_LENGTH characters.");
				error_msg(error_string, CONTINUE);
				return (ERROR);
			}
			c = *(++cptr);
		}
		token[i] = '\0';
		*eqnaddr = cptr;
		errno = 0;
		*coef = strtod(token, &ptr1);
		if ((errno == ERANGE) || (*ptr1 != '\0'))
		{
			error_string = sformatf(
					"Error converting coefficient in get_coef, %s.", token);
			error_msg(error_string, CONTINUE);
			return (ERROR);
		}
		return (OK);
	}
/*
 *   None of the above, unknown construct
 */
	error_string = sformatf(
			"Illegal equation construct detected in get_coef.\n\t%s.", rest);
	error_msg(error_string, CONTINUE);
	return (ERROR);
}

/* ---------------------------------------------------------------------- */
int Phreeqc::
get_elt(const char** t_ptr, std::string& element, int* i)
/* ---------------------------------------------------------------------- */
/*
 *      Function reads an element name out of the equation string.
 *      An element name is composed of a capital letter followed by any number
 *      of lower case characters.
 *
 *      Arguments:
 *         **t_ptr   input, points to position in the equation to begin
 *                   output, points to next character of equation after
 *                      element name.
 *         *element  input pointer to place to return element character string
 */
{
	char c;

	element.clear();
	c = *(*t_ptr)++;
	if (c == '\0')
	{
		error_string = sformatf(
			"Empty string in get_elt.  Expected an element name.");
		error_msg(error_string, CONTINUE);
		return (ERROR);
	}
	/*
	 *   Load name into char array element
	 */
	element.push_back(c);
	*i = 1;
	if (c == '[')
	{
		while ((c = (**t_ptr)) != ']')
		{
			element.push_back(c);
			(*i)++;
			(*t_ptr)++;
			if ((c = (**t_ptr)) == ']')
			{
				element.push_back(c);
				(*i)++;
				(*t_ptr)++;
				break;
			}
			else if (**t_ptr == '\0')
			{
				error_msg("No ending bracket (]) for element name", CONTINUE);
				input_error++;
				break;
			}
		}
		while (islower((int)(c = (**t_ptr))) || c == '_')
		{
			element.push_back(c);
			(*i)++;
			(*t_ptr)++;
		}
	}
	else
	{
		while (islower((int)(c = (**t_ptr))) || c == '_')
		{
			element.push_back(c);
			(*i)++;
			(*t_ptr)++;
		}
	}
	return (OK);
}

/* ---------------------------------------------------------------------- */
int Phreeqc::
get_elts_in_species(const char **t_ptr, LDBLE coef)
/* ---------------------------------------------------------------------- */
{
/*
 *    Makes a list of elements with their coefficients, stores elements
 *    in elt_list at position count_elts.  Global variable count_elts is
 *    updated with each stored element.  Also uses static global variable
 *    paren_count.
 *
 *    Arguments:
 *       **t_ptr    input, point in token string to start looking
 *                  output, is next position to start looking
 *         coef     input, coefficient to multiply subscripts by
 */
	int l;
	size_t count;
	char c, c1;
	LDBLE d;
	std::string element;
	const char** t_ptr_save = t_ptr;
	while (((c = **t_ptr) != '+') && (c != '-') && (c != '\0'))
	{
		/* close parenthesis */
		if (c == ')')
		{
			paren_count--;
			if (paren_count < 0)
			{
				error_string = sformatf( "Too many right parentheses.");
				error_msg(error_string, CONTINUE);
				return (ERROR);
			}
			(*t_ptr)++;
			return (OK);
		}
		c1 = *((*t_ptr) + 1);
		/* beginning of element name */
		if (isupper((int) c) || (c == 'e' && c1 == '-') || (c == '['))
		{
/*
 *   Get new element and subscript
 */
			if (get_elt(t_ptr, element, &l) == ERROR)
			{
				return (ERROR);
			}
			if (count_elts >= (int)elt_list.size())
			{
				elt_list.resize(count_elts + 1);
			}
			elt_list[count_elts].elt = element_store(element.c_str());
			if (get_num(t_ptr, &d) == ERROR)
			{
				return (ERROR);
			}
			elt_list[count_elts].coef = d * coef;
			count_elts++;
/*
 *   Expand working space for elements if necessary
 */
			if (count_elts >= (int)elt_list.size())
			{
				elt_list.resize(count_elts + 1);
			}
			continue;
		}
/*
 *   Open parentheses
 */
		if (c == '(')
		{
			count = count_elts;
			if (c1 == ')')
			{
				error_string = sformatf( "Empty parentheses.");
				warning_msg(error_string);
			}
			paren_count++;
			(*t_ptr)++;
			if (get_elts_in_species(t_ptr, coef) == ERROR)
			{
				return (ERROR);
			}
			if (get_num(t_ptr, &d) == ERROR)
			{
				return (ERROR);
			}
			for (size_t i = count; i < count_elts; i++)
			{
				elt_list[i].coef *= d;
			}
			continue;
		}
/*
 *   Colon
 */
		if (c == ':')
		{
			count = count_elts;
			(*t_ptr)++;
			if (get_num(t_ptr, &d) == ERROR)
			{
				return (ERROR);
			}
			if (get_elts_in_species(t_ptr, coef) == ERROR)
			{
				return (ERROR);
			}
			for (size_t i = count; i < count_elts; i++)
			{
				elt_list[i].coef *= d;
			}
			continue;
		}
/*
 *   Not beginning of element and not opening paren
 */
		error_string = sformatf(
				"Parsing error in get_elts_in_species, unexpected character, %c.",
				c);
		error_msg(error_string, CONTINUE);
		input_error++;
		return (ERROR);
	}
	if (paren_count != 0)
	{
		error_string = sformatf( "Unbalanced parentheses: %s", *t_ptr_save);
		error_msg(error_string, CONTINUE);
		input_error++;
		return (ERROR);
	}
	return (OK);
}

/* ---------------------------------------------------------------------- */
 int Phreeqc::
get_secondary(const char **t_ptr, char *element, int *i)
/* ---------------------------------------------------------------------- */
/*
 *      Function reads an element name out of the equation string.
 *      An element name is composed of a capital letter followed by any number
 *      of lower case characters.
 *
 *      Arguments:
 *         **t_ptr   input, points to position in the equation to begin
 *                   output, points to next character of equation after
 *                      element name.
 *         *element  input pointer to place to return element character string
 */
{
	int j;
	char c;
	const char* cptr;

	c = *(*t_ptr)++;
	if (c == '\0')
	{
		error_string = sformatf(
				"Empty string in get_elt.  Expected an element name.");
		error_msg(error_string, CONTINUE);
		input_error++;
		return (ERROR);
	}
/*
 *   Load name into char array element
 */
	element[0] = c;
	*i = 1;
	if (c == '[')
	{
		while ((c = (**t_ptr)) != ']')
		{
			element[*i] = c;
			(*i)++;
			(*t_ptr)++;
			if ((c = (**t_ptr)) == ']')
			{
				element[*i] = c;
				(*i)++;
				(*t_ptr)++;
				c = (**t_ptr);
				break;
			}
			else if ((c = (**t_ptr)) == '\0')
			{
				error_msg("Did not find ending bracket (])", CONTINUE);
				input_error++;
				return (ERROR);
			}
		}
		while (islower((int) (c = (**t_ptr))) || c == '_')
		{
			element[*i] = c;
			(*i)++;
			(*t_ptr)++;
		}
	}
	else
	{
		while (islower((int) (c = (**t_ptr))) || c == '_')
		{
			element[*i] = c;
			(*i)++;
			(*t_ptr)++;
		}
	}
/*
 *   Check if secondary master species element
 */
	j = *i;
	cptr = *t_ptr;
	if (c == '(')
	{
		/* copy parenthesis */
		element[*i] = c;
		(*i)++;
		(*t_ptr)++;
		/* copy number */
		for (;;)
		{
			c = **t_ptr;
			if (isdigit((int) c) || c == '-' || c == '.')
			{
				element[*i] = c;
				(*i)++;
				(*t_ptr)++;
			}
			else if (c == '+')
			{
				(*t_ptr)++;
			}
			else
			{
				break;
			}
		}
		/* go back to before parenthesis */
		if (c != ')')
		{
			*i = j;
			*t_ptr = cptr;
			/* put in closing parenthesis */
		}
		else
		{
			element[*i] = c;
			(*i)++;
			(*t_ptr)++;
		}
	}
	element[*i] = '\0';
	return (OK);
}

/* ---------------------------------------------------------------------- */
int Phreeqc::
get_secondary_in_species(const char **t_ptr, LDBLE coef)
/* ---------------------------------------------------------------------- */
{
/*
 *    Makes a list of elements with their coefficients, stores elements
 *    in elt_list at position count_elts.  Global variable count_elts is
 *    updated with each stored element.  Also uses static global variable
 *    paren_count.
 *
 *    Arguments:
 *       **t_ptr    input, point in token string to start looking
 *                  output, is next position to start looking
 *         coef     input, coefficient to multiply subscripts by
 */
	int l;
	size_t count;
	char c, c1;
	LDBLE d;
	char element[MAX_LENGTH];
	const char** t_ptr_save = t_ptr;
	while (((c = **t_ptr) != '+') && (c != '-') && (c != '\0'))
	{
		/* close parenthesis */
		if (c == ')')
		{
			paren_count--;
			if (paren_count < 0)
			{
				error_string = sformatf( "Too many right parentheses.");
				error_msg(error_string, CONTINUE);
				input_error++;
				return (ERROR);
			}
			(*t_ptr)++;
			return (OK);
		}
		c1 = *((*t_ptr) + 1);
		/* beginning of element name */
		if (isupper((int) c) || c == '[' || (c == 'e' && c1 == '-'))
		{
/*
 *   Get new element and subscript
 */
			if (get_secondary(t_ptr, element, &l) == ERROR)
			{
				return (ERROR);
			}
			elt_list[count_elts].elt = element_store(element);
			if (get_num(t_ptr, &d) == ERROR)
			{
				return (ERROR);
			}
			elt_list[count_elts].coef = d * coef;
			count_elts++;
/*
 *   Expand working space for elements if necessary
 */
			if (count_elts >= (int)elt_list.size())
			{
				elt_list.resize(count_elts + 1);
			}
			continue;
		}
/*
 *   Open parentheses
 */
		if (c == '(')
		{
			count = count_elts;
			if (c1 == ')')
			{
				error_string = sformatf( "Empty parentheses.");
				warning_msg(error_string);
			}
			paren_count++;
			(*t_ptr)++;
			if (get_secondary_in_species(t_ptr, coef) == ERROR)
			{
				return (ERROR);
			}
			if (get_num(t_ptr, &d) == ERROR)
			{
				return (ERROR);
			}
			for (size_t i = count; i < count_elts; i++)
			{
				elt_list[i].coef *= d;
			}
			continue;
		}
/*
 *   Colon
 */
		if (c == ':')
		{
			count = count_elts;
			(*t_ptr)++;
			if (get_num(t_ptr, &d) == ERROR)
			{
				return (ERROR);
			}
			if (get_secondary_in_species(t_ptr, coef) == ERROR)
			{
				return (ERROR);
			}
			for (size_t i = count; i < count_elts; i++)
			{
				elt_list[i].coef *= d;
			}
			continue;
		}
/*
 *   Not beginning of element and not opening paren
 */
		error_string = sformatf(
				"Parsing error in get_secondary_in_species, unexpected character, %c.",
				c);
		error_msg(error_string, CONTINUE);
		return (ERROR);
	}
	if (paren_count != 0)
	{
		error_string = sformatf("Unbalanced parentheses: %s", *t_ptr_save);
		error_msg(error_string, CONTINUE);
		return (ERROR);
	}
	return (OK);
}

/* ---------------------------------------------------------------------- */
int Phreeqc::
get_num(const char **t_ptr, LDBLE * num)
/* ---------------------------------------------------------------------- */
/*
 *      Function reads through a string looking for leading numeric field
 *      if no numeric field is found, the number is set to 1.0.
 *
 *      Arguments:
 *
 *       **t_ptr     input, points to a position in a character string from which
 *                      a number is to be extracted.
 *                   output, points to next position to be parsed.
 *        *num       address where the number is to be stored.
 *
 *      Returns:
 *         ERROR,
 *         OK.
 */
{
	int i, decimal;
	char c;
	char* ptr1;
	char token[MAX_LENGTH];

	*num = 1.0;
	i = 0;
	c = **t_ptr;
	decimal = 0;
	if (isdigit((int) c) || (c == '.'))
	{
		while (isdigit((int) c) || (c == '.'))
		{
			if (c == '.')
				decimal++;
			if (decimal > 1)
				break;
			token[i++] = c;
			/* check number length */
			if (i >= MAX_LENGTH)
			{
				error_string = sformatf(
						"Number was greater than MAX_LENGTH characters.");
				error_msg(error_string, CONTINUE);
				input_error++;
				return (ERROR);
			}
			c = *(++(*t_ptr));
		}
		token[i] = '\0';
		errno = 0;
		*num = strtod(token, &ptr1);
		if (errno == ERANGE)
		{
			error_string = sformatf( "Converting number in get_num, %s.", token);
			input_error++;
			error_msg(error_string, CONTINUE);
			return (ERROR);
		}
	}
	return (OK);
}

/* ---------------------------------------------------------------------- */
int Phreeqc::
get_species(const char **cptr)
/* ---------------------------------------------------------------------- */
{
/*   Function reads next species out of the equation, including optional
 *   preceding coefficient and optional trailing charge. Data are
 *   store in trxn.token[count].
 *
 *   Arguments:
 *    **cptr       input, points to the position in the equation to pick up the species.
 *                output, points to the next character after the species charge.
 *
 */
	std::string string;
	int l;

	if ((size_t) count_trxn + 1 > trxn.token.size()) 
		trxn.token.resize(count_trxn + 1);
	/* coefficient */
	if (get_coef(&(trxn.token[count_trxn].coef), cptr) == ERROR)
	{
		return (ERROR);
	}
	/* name and charge */
	if (get_token(cptr, string, &trxn.token[count_trxn].z, &l) == ERROR)
	{
		return (ERROR);
	}
	trxn.token[count_trxn].name = string_hsave(string.c_str());
	/*
	   trxn.token[count_trxn].z = 0;
	   trxn.token[count_trxn].s = NULL;
	   trxn.token[count_trxn].unknown = NULL;
	 */
	return (OK);
}
