mirror of
https://github.com/mfillpot/mathomatic.git
synced 2026-01-09 04:59:37 +00:00
239 lines
6.7 KiB
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.")); */
|
|
}
|