mathomatic/lib/lib.c

239 lines
6.7 KiB
C

/*
* Mathomatic API, Copyright (C) 1996-2012 George Gesslein II.
*
* This file contains the required C functions and simple interface
* for developers to use the Mathomatic symbolic math library properly.
* These functions are included in the library.
* Refer to this, if you are going to use the Mathomatic code in other projects.
*
* Be sure to call matho_clear(3) to erase all equation spaces
* after completing each group of operations,
* otherwise the equation spaces will fill up.
*/
#include "../includes.h"
#include "mathomatic.h"
/** 3
* matho_init - Initialize the Mathomatic symbolic math library
* Call this only once before calling any Mathomatic code.
* This must be called exactly once upon program startup and not again,
* unless free_mem() is called.
*
* Returns true if successful.
* If this returns false, there was not enough memory available
* and Mathomatic cannot be used.
*/
int
matho_init(void)
{
init_gvars();
default_out = stdout; /* if default_out is a file that is not stdout, output is logged to that file */
gfp = default_out;
if (!init_mem()) {
return false;
}
signal(SIGFPE, fphandler); /* handle floating point exceptions, currently ignored */
return true;
}
/** 3
* matho_clear - Erase all equation spaces so they can be reused
* Mathomatic only has a limited number of equation spaces.
* Similar to a restart, recommended after each group of symbolic math operations.
* Currently this is the same as entering the command "clear all".
*
* matho_init(3) must have been called only one time before this
* to initialize the Mathomatic symbolic math engine.
*/
void
matho_clear(void)
{
clear_all();
}
/** 3
* matho_process - Process Mathomatic command or expression input
* Process a Mathomatic command or enter an expression into an equation space.
* The command or expression ASCII string is given as "input",
* the resulting output string is stored in "*outputp".
*
* matho_init(3) must have been called only one time before this
* to initialize the Mathomatic symbolic math engine.
* Use matho_clear(3) as many times as you want to restart Mathomatic
* for the next group of operations.
*
* This function works just like typing something into the Mathomatic prompt.
* To only parse any expression or equation and store it, use matho-parse(3).
*
* If this returns true (non-zero), the command or input was successful,
* and the resulting expression output string is stored in "*outputp".
* That is a malloc()ed text string which must be free()d after use
* to return the memory used by the string.
* The equation number of the equation space that the output expression
* is additionally stored in (if any) is available in the global "result_en",
* otherwise result_en = -1.
*
* If this returns false, the command or input failed and a text error
* message is always stored in "*outputp".
* The error message is a constant string and should NOT be free()d.
*
* Some commands, like the set command, will return no output when successful,
* setting "*outputp" to NULL.
*
* The resulting output string can safely be ignored by calling
* this function with "outputp" set to NULL.
*/
int
matho_process(char *input, char **outputp)
{
int i;
int rv;
if (outputp)
*outputp = NULL;
result_str = NULL;
result_en = -1;
error_str = NULL;
warning_str = NULL;
if (input == NULL)
return false;
input = strdup(input);
if ((i = setjmp(jmp_save)) != 0) {
clean_up(); /* Mathomatic processing was interrupted, so do a clean up. */
if (i == 14) {
error(_("Expression too large."));
}
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
} else {
*outputp = _("Processing was interrupted.");
}
}
free_result_str();
free(input);
previous_return_value = 0;
return false;
}
set_error_level(input);
rv = process(input);
if (rv) {
if (outputp) {
*outputp = result_str;
} else {
if (result_str) {
free(result_str);
result_str = NULL;
}
}
} else {
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
} else {
*outputp = _("Unknown error.");
}
}
free_result_str();
}
free(input);
return rv;
}
/** 3
* matho_parse - Process Mathomatic expression or equation input
* Parse a mathematical equation or expression and store in the next available equation space,
* making it the current equation.
* Afterwards, it can be operated on by Mathomatic commands using matho_process(3).
*
* matho_init(3) must have been called only one time before this
* to initialize the Mathomatic symbolic math engine.
* Use matho_clear(3) as many times as you want to restart Mathomatic
* for the next group of operations.
*
* The input and output ASCII strings are expressions, if successful.
* The expression or equation string to enter is in "input",
* the resulting output string is stored in "*outputp".
* The equation number of the equation space that the output expression
* is additionally stored in (if any) is available in the global "result_en",
* otherwise result_en = -1.
*
* Works the same as matho_process(3), except commands are not allowed,
* so that variables are not ever confused with commands.
* In fact, this function is currently set to only allow
* entry and storage of expressions and equations.
*
* Returns true (non-zero) if successful.
*/
int
matho_parse(char *input, char **outputp)
{
int i;
int rv;
if (outputp)
*outputp = NULL;
result_str = NULL;
result_en = -1;
error_str = NULL;
warning_str = NULL;
if (input == NULL)
return false;
input = strdup(input);
if ((i = setjmp(jmp_save)) != 0) {
clean_up(); /* Mathomatic processing was interrupted, so do a clean up. */
if (i == 14) {
error(_("Expression too large."));
}
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
} else {
*outputp = _("Processing was interrupted.");
}
}
free_result_str();
free(input);
return false;
}
set_error_level(input);
i = next_espace();
#if 1 /* Leave this as 1 if you want to be able to enter single variable or constant expressions with no solving or selecting. */
rv = parse(i, input); /* All set auto options ignored. */
#else
rv = process_parse(i, input); /* All set auto options respected. */
#endif
if (rv) {
if (outputp) {
*outputp = result_str;
} else {
if (result_str) {
free(result_str);
result_str = NULL;
}
}
} else {
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
} else {
*outputp = _("Unknown error.");
}
}
free_result_str();
}
free(input);
return rv;
}
/*
* Floating point exception handler.
* Usually doesn't work in most operating systems, so just ignore it.
*/
void
fphandler(int sig)
{
/* error(_("Floating point exception.")); */
}